From 1ea65f0285d7022ce20ef84d4e35e3c94bcb3fbd Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++++++- 3 files changed, 42 insertions(+), 39 deletions(-) (limited to 'indra/llui') 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 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 { Mandatory name; - Optional persist; + Optional persist, + log_to_im, + log_to_chat; Optional 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 mTags; + + // inject these notifications into chat/IM streams + bool mLogToChat; + bool mLogToIM; }; #endif //LL_LLNOTIFICATION_TEMPLATE_H -- cgit v1.2.3 From 2fa1c42aadbe2a29e1bcced9a487c0e5abf0602b Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui/llnotifications.cpp | 92 ++++++++++++++++++---------------- indra/llui/llnotifications.h | 49 +++++++++++------- indra/llui/llnotificationslistener.cpp | 8 +-- 3 files changed, 83 insertions(+), 66 deletions(-) (limited to 'indra/llui') 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(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(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 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 LLNotificationChannelPtr; +typedef boost::intrusive_ptr 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 { 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 + { + Mandatory name; + Optional filter; + Optional comparator; + Multiple 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 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 mListener; + std::vector 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); } -- cgit v1.2.3 From c2afd200a0d55c5137de6f89200a8d4b09ba8b6e Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++++++++++++ 3 files changed, 46 insertions(+), 19 deletions(-) (limited to 'indra/llui') 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 { @@ -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 LLNotificationFormPtr; // from the appropriate local language directory). struct LLNotificationTemplate { + struct CombineBehaviorNames + : public LLInitParam::TypeValuesHelper + { + static void declareValues() + { + declare("newest", LLNotification::USE_NEWEST); + declare("oldest", LLNotification::USE_OLDEST); + } + }; + + struct GlobalString : public LLInitParam::Block { Mandatory name, @@ -94,9 +105,11 @@ struct LLNotificationTemplate Optional dummy_val; public: Multiple contexts; + Optional 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 -- cgit v1.2.3 From e5c0cfdc5a0dd20afbec047049cbd920686cb55d Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine 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/llui') 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 menu_filename; - Optional position; + Optional position; Params(); }; -- cgit v1.2.3 From 69cf10a1e9b969a1c87473a8b153281dc60e7b56 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine 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/llui') 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 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/llui') 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(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(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(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 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 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 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llui') 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(mMenuHandle.get()); -- cgit v1.2.3 From fff9567a67ded34471fd17af9c50bc1d307e7b19 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llui') 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, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue, 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, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + void ParamValue, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) { p.writeValue(sd.asString(), name_stack); } - void ParamValue, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue, 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 > + class ParamValue, NOT_BLOCK > : public CustomParamValue { typedef boost::add_reference::type>::type T_const_ref; @@ -100,7 +100,7 @@ namespace LLInitParam public: Optional name; - ParamValue(LLUIImage* const& image) + ParamValue(LLUIImage* const& image = NULL) : super_t(image) { updateBlockFromValue(false); -- cgit v1.2.3 From a3d08c2355e35758b27b0fb7dca926959c440e63 Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 855fbc0bf331c116d20d402f427535f060f70345 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llui') 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 + struct Images : public LLInitParam::Block { Multiple image; @@ -62,8 +62,8 @@ public: struct Params : public LLInitParam::Block { - Optional images_per_sec; - Optional images; + Optional images_per_sec; + Optional > images; Params() : images_per_sec("images_per_sec", 1.0f), -- cgit v1.2.3 From 61d202a15d70ec56e46bca2edadd49cfd5cbb956 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 13 Apr 2012 11:48:37 -0700 Subject: renamed Lazy to Atomic --- indra/llui/llloadingindicator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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 { Optional images_per_sec; - Optional > images; + Optional > images; Params() : images_per_sec("images_per_sec", 1.0f), -- cgit v1.2.3 From 82c9b0fbbca6f61e57464a6126ae36a59b13d6ed Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++++++++-------- 6 files changed, 35 insertions(+), 35 deletions(-) (limited to 'indra/llui') 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 >::ParamValue(const LLUIColor& color) + ParamValue::ParamValue(const LLUIColor& color) : super_t(color), red("red"), green("green"), @@ -2118,7 +2118,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() { if (control.isProvided() && !control().empty()) { @@ -2130,7 +2130,7 @@ namespace LLInitParam } } - void ParamValue >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue::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 >::ParamValue(const LLFontGL* fontp) + ParamValue::ParamValue(const LLFontGL* fontp) : super_t(fontp), name("name"), size("size"), @@ -2160,7 +2160,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() { const LLFontGL* res_fontp = LLFontGL::getFontByName(name); if (res_fontp) @@ -2183,7 +2183,7 @@ namespace LLInitParam } } - void ParamValue >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue::updateBlockFromValue(bool make_block_authoritative) { if (getValue()) { @@ -2193,7 +2193,7 @@ namespace LLInitParam } } - ParamValue >::ParamValue(const LLRect& rect) + ParamValue::ParamValue(const LLRect& rect) : super_t(rect), left("left"), top("top"), @@ -2205,7 +2205,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() { LLRect rect; @@ -2269,7 +2269,7 @@ namespace LLInitParam updateValue(rect); } - void ParamValue >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue::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 >::ParamValue(const LLCoordGL& coord) + ParamValue::ParamValue(const LLCoordGL& coord) : super_t(coord), x("x"), y("y") @@ -2294,12 +2294,12 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() { updateValue(LLCoordGL(x, y)); } - void ParamValue >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue::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 > + class ParamValue : public CustomParamValue { typedef CustomParamValue super_t; @@ -531,7 +531,7 @@ namespace LLInitParam }; template<> - class ParamValue > + class ParamValue : public CustomParamValue { typedef CustomParamValue super_t; @@ -549,7 +549,7 @@ namespace LLInitParam }; template<> - class ParamValue > + class ParamValue : public CustomParamValue { typedef CustomParamValue super_t; @@ -589,7 +589,7 @@ namespace LLInitParam template<> - class ParamValue > + class ParamValue : public CustomParamValue { typedef CustomParamValue 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 >::updateValueFromBlock() + void ParamValue::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 >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue::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, NOT_BLOCK > + class ParamValue : public CustomParamValue { typedef boost::add_reference::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 >::ParamValue(const LLUIColor& color) + ParamValue::ParamValue(const LLUIColor& color) : super_t(color) {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::updateBlockFromValue(bool) {} bool ParamCompare::equals(const LLFontGL* a, const LLFontGL* b) @@ -142,14 +142,14 @@ namespace LLInitParam return false; } - ParamValue >::ParamValue(const LLFontGL* fontp) + ParamValue::ParamValue(const LLFontGL* fontp) : super_t(fontp) {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::updateBlockFromValue(bool) {} void TypeValues::declareValues() @@ -161,10 +161,10 @@ namespace LLInitParam void TypeValues::declareValues() {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::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 >::ParamValue(const LLUIColor& color) + ParamValue::ParamValue(const LLUIColor& color) : super_t(color) {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::updateBlockFromValue(bool) {} bool ParamCompare::equals(const LLFontGL* a, const LLFontGL* b) @@ -113,14 +113,14 @@ namespace LLInitParam } - ParamValue >::ParamValue(const LLFontGL* fontp) + ParamValue::ParamValue(const LLFontGL* fontp) : super_t(fontp) {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::updateBlockFromValue(bool) {} void TypeValues::declareValues() @@ -132,10 +132,10 @@ namespace LLInitParam void TypeValues::declareValues() {} - void ParamValue >::updateValueFromBlock() + void ParamValue::updateValueFromBlock() {} - void ParamValue >::updateBlockFromValue(bool) + void ParamValue::updateBlockFromValue(bool) {} bool ParamCompare::equals( -- cgit v1.2.3 From 7dc9ddff4b775bf78561ef545db281cf47f2240f Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Sun, 15 Apr 2012 20:43:55 -0700 Subject: attempted fix for gcc --- indra/llui/llsdparam.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue::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, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + void ParamValue::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) { p.writeValue(sd.asString(), name_stack); } - void ParamValue, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue::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; -- cgit v1.2.3 From 2412401e4c705c7073be845bba74353d446bd017 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Sat, 14 Apr 2012 21:03:36 +0300 Subject: CHUI-78 WIP Minor cleanup. --- indra/llui/llmenubutton.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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(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(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(mMenuHandle.get()); + LLToggleableMenu* menu = getMenu(); if (!menu) return; // Store the button rectangle to toggle menu visibility if a mouse event -- cgit v1.2.3 From 3adf89351359210f6f8a0f33cef94733a815dea1 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine 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/llui') 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 37186d452fcb94b13e34d01aa801e7db17ee353e Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +- 4 files changed, 118 insertions(+), 85 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 234ce663fa52a588662153e6e465a53643c4e0f4 Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 42b5dfda161a1e6b92990cd5206bca5ff5b95ab6 Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 5955e6260e6e263fb089f7cc91c0be482cccdfb8 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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"), -- cgit v1.2.3 From 2babcb4af56e6b7fb443f1b78002dc9e61e891c7 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Thu, 23 Feb 2012 21:02:46 +0200 Subject: Linux build fix. Moved type casts from protected base classes to derived LLCoord. --- indra/llui/llfloater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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(*this); + const LLCoordFloater& self = static_cast(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(*this); + LLCoordFloater& self = static_cast(LLCoordFloater::getTypedCoords(*this)); LLRect snap_rect = gFloaterView->getSnapRect(); LLFloater* floaterp = mFloater.get(); S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; -- cgit v1.2.3 From fac210075f4c68db372ae0535e332ffe9765a5d1 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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() -- cgit v1.2.3 From f59aa880395d4b744c89b0a375b21ee2bf429625 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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 +++ 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'indra/llui') 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 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 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 -- cgit v1.2.3 From 296e55c1b323c05b6544b69ace04afe19102396b Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++- 3 files changed, 125 insertions(+), 44 deletions(-) (limited to 'indra/llui') 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 { Optional name; + Optional 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 name; Optional persist, log_to_im, + show_toast, log_to_chat; Optional 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 -- cgit v1.2.3 From 61bc25211be31ad28b8ae342c17b4ea1c32d955c Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++- 3 files changed, 120 insertions(+), 174 deletions(-) (limited to 'indra/llui') 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& 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(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(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 #include -// 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 name; - - // optional - Optional substitutions; - Optional payload; + Optional id; + Optional substitutions, + form_elements, + payload; Optional priority; - Optional form_elements; - Optional time_stamp; + Optional time_stamp, + expiry; Optional context; Optional responder; @@ -326,7 +323,7 @@ public: Alternative 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& 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 - struct orderBy + struct orderByUUID { - typedef boost::function 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 - { - orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy(&LLNotification::id, direction) {} - }; - - struct orderByDate : public orderBy - { - orderByDate(EDirection direction = ORDER_INCREASING) : orderBy(&LLNotification::getDate, direction) {} }; }; typedef boost::function LLNotificationFilter; typedef boost::function LLNotificationComparator; -typedef std::set LLNotificationSet; +typedef std::set LLNotificationSet; typedef std::multimap 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 name; Optional filter; - Optional comparator; Multiple 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 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 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::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); } } -- cgit v1.2.3 From f89d94434c6e9d96ad71586d55c2b32d933a1e05 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 21 May 2012 18:26:18 -0700 Subject: made param blocks smaller by making param overhead 3 bytes instead of 4 Optional should now be 4 bytes smaller. --- indra/llui/tests/llurlentry_stub.cpp | 4 +++- indra/llui/tests/llurlmatch_test.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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(this); const U8* block_addr = reinterpret_cast(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(this); const U8* block_addr = reinterpret_cast(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; } -- cgit v1.2.3 From 4dffa3351401bd8ba8326958b38a3d500805b5d1 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 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 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llui') 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 getHandle() { return getDerivedHandle(); } + protected: bool mClosedByButtonClick; LLRect mButtonRect; -- cgit v1.2.3 From d713925f435add08f6e48fec2472671fae58f170 Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 2286dcb73bfddb9bd4102869005b14241053377d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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/llui') 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 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 +- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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(); } -- cgit v1.2.3 From b64fc84707a0ab4c11e84cf5caec32bbc267f313 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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) -- cgit v1.2.3 From 18aabdfd3d2efc1b5507e2fe001cfc36ee84b710 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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 +- 8 files changed, 477 insertions(+), 38 deletions(-) create mode 100644 indra/llui/llchatentry.cpp create mode 100644 indra/llui/llchatentry.h (limited to 'indra/llui') 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 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 + { + Optional has_history, + is_expandable; + + Optional 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 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 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 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; -- cgit v1.2.3 From ad4ae5583534197cb00c13d769e504fcde4d19d5 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 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 91be3bf3019581b74a3515c1081aef883c0658fa Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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 r("text_editor"); +static LLDefaultChildRegistry::Register r("chat_editor"); LLChatEntry::Params::Params() : has_history("has_history", true), -- cgit v1.2.3 From 47c140b81d868229187f85185e4721946430ad87 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 74092930afdc294ef4d204830173d4750a310616 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'indra/llui') 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); } //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); -- cgit v1.2.3 From 41e965c12e29136d2b81a9b67d6b6c9af4fb2092 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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); -- cgit v1.2.3 From 677c205131e695eb5a3b2a190799330b49d636d8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 a7831406abfe87e9bd1da8091e008edcd65b402c Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 cb865a7e1300d4ce0bedae7c856fb210b68a43f8 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From 1494a1058f41c5aa00a8ed08fe71123f63e92e81 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++++++ 7 files changed, 5330 insertions(+) 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 (limited to 'indra/llui') 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 + +///---------------------------------------------------------------------------- +/// 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(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 (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 (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + //addChild(mStatusTextBox); + + + // make the popup menu available + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget("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 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::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 LLFolderView::getSelectionList() const +{ + std::set selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); + return selection; +} + +bool LLFolderView::startDrag() +{ + std::vector 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& selectedItems) +{ + LLFolderViewItem* item_parent = dynamic_cast(item->getParent()); + + if (item_parent) + { + for(std::vector::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(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 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 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::FAIL)) + { + listeners.put(listener); + } + } + listener = static_cast(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((*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 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(item); + if (folder == NULL) + { + item = item->getParentFolder(); + } + folder_set.insert(folder); + } + + std::set::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(); + 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 + { + Mandatory parent_panel; + Optional title; + Optional use_label_suffix, + allow_multiselect, + show_empty_message, + use_ellipses, + show_item_link_overlays; + Mandatory 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& 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 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 mPopupMenuHandle; + + typedef std::deque 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 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 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 r("folder_view_item"); + +// statics +std::map 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::getSelectionList() const +{ + std::set 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(); + 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 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(); + 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 item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) + { + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + std::deque 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& 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 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 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::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::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(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 + { + Optional folder_arrow_image, + selection_image; + Optional root; + Mandatory listener; + + Optional folder_indentation, // pixels + item_height, + item_top_pad; + + Optional 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 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 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 items_t; + typedef std::list 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& items); + +public: + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } + template 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& 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 +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(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(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 getIcon() const = 0; + virtual LLPointer getIconOpen() const { return getIcon(); } + virtual LLPointer 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& 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 child_list_t; + child_list_t mChildren; + LLFolderViewModelItem* mParent; + + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; +}; + + +#endif // LLFOLDERVIEWMODEL_H -- cgit v1.2.3 From d3edb1c466f42e2c46c77e43b26d700c6298b8d6 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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 folder_arrow_image, selection_image; - Optional root; + Mandatory root; Mandatory listener; Optional folder_indentation, // pixels -- cgit v1.2.3 From ec15ff6350c0997421cf2884e40aa9feaa070d4d Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'indra/llui') 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()); } -- cgit v1.2.3 From 9ab042dd1d003da15dd579f366db04d4aae3ff6b Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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/llui') 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 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/llui') 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& 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 -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(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(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& 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 +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(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(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 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/llui') 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 176b7d82be3b48344e2a54f81402352273719108 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++++++++++----------------------- 2 files changed, 11 insertions(+), 32 deletions(-) (limited to 'indra/llui') 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()) -- cgit v1.2.3 From decd8a435d8fb15bab52eec9e447b176e33eb5cf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From 891a09561d4dff23836c8618d481a6cd2dd001de Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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(item); if (folder == NULL) { - item = item->getParentFolder(); + folder = item->getParentFolder(); } folder_set.insert(folder); } -- cgit v1.2.3 From f6dfd6bf0f3ea0e9b5f56a939867353c393539d6 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 69b57d4ac075db855d88c2ff0e8c580e9e41ebf7 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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 handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider - } - template LLHandle getDerivedHandle(typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) const { @@ -173,6 +166,12 @@ protected: return downcast_handle; } +protected: + typedef LLHandle handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider + } private: mutable LLRootHandle mHandle; -- cgit v1.2.3 From 88f259f7c1aefea197ae8b6c49a79de09feebf5b Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) { + if (name_stack.first == name_stack.second + && p.readValue(mValue)) + { + return true; + } + LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); LLSD::String string; @@ -325,7 +331,11 @@ namespace LLInitParam void ParamValue::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(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 0479e8d4ad1212b0028805cd4e39b6fe593b86c7 Mon Sep 17 00:00:00 2001 From: Todd Stinson Date: Fri, 27 Jul 2012 14:28:31 -0700 Subject: Updating comments for merge conflicts after reviewing with Richard. --- indra/llui/llfolderviewitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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(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(); -- cgit v1.2.3 From 209fd15176647a4b8defbb6e66daea6eb12d4b42 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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/llui') 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 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/llui') 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 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 +---- 4 files changed, 16 insertions(+), 17 deletions(-) (limited to 'indra/llui') 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 creation_date; + Optional 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); } -//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 static const typename T::Params& getDefaultParams() { - //#pragma message("Generating ParamDefaults") return ParamDefaults::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); -- cgit v1.2.3 From f29bdc27b3038a19317095ef914bd560f3199d28 Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 e9a484f98d0376a5651d4f6eb5a692db4f77c800 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++- 3 files changed, 36 insertions(+), 28 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From a204059d2e69fb33cb1a3c8d2fbed35d3967297c Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++++++++++++++++++++++++++++----------- 6 files changed, 107 insertions(+), 85 deletions(-) (limited to 'indra/llui') 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::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(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& 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 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& 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 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& 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 -- cgit v1.2.3 From 8ccaa8b0b8e65d6022c6ad0d449cecdd8a72f81d Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 4256b54ee78a89dc5e790cc13556451e1a7c43fa Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 1 Aug 2012 10:45:11 -0700 Subject: build fix --- indra/llui/llfolderviewitem.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra/llui') 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& 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 void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } -- cgit v1.2.3 From 4cb1e766fcfcaba702c2638f4c7daa9dd17bcbd8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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. -- cgit v1.2.3 From 898ec6cd362cd92ceef8dca8faf3fb8ed119b1be Mon Sep 17 00:00:00 2001 From: Richard Linden 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/llui') 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 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/llui') 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 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 +- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'indra/llui') 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) -- cgit v1.2.3 From 88e81f99293c992944787289699bf885568bf327 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 + 3 files changed, 35 insertions(+), 29 deletions(-) (limited to 'indra/llui') 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& selectedItems) -{ - LLFolderViewItem* item_parent = dynamic_cast(item->getParent()); - - if (item_parent) - { - for(std::vector::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(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; } -- cgit v1.2.3 From 0fa1e2b9ae41bb06e5c7db90900d4f469f44b8d3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++--- 4 files changed, 44 insertions(+), 30 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From faac868b682360df1bf461624667cc6e0bbdd8c6 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +++-- 2 files changed, 37 insertions(+), 68 deletions(-) (limited to 'indra/llui') 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 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 ); -- cgit v1.2.3 From af8d113557105075af0e010c560ba9846d812aa0 Mon Sep 17 00:00:00 2001 From: Richard Linden 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 +-- 3 files changed, 63 insertions(+), 54 deletions(-) (limited to 'indra/llui') 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 { Optional 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 sFonts; // map of styles to fonts @@ -262,7 +260,6 @@ protected: friend class LLUICtrlFactory; public: - typedef std::list items_t; typedef std::list 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) { -- cgit v1.2.3 From 2b026a806617532a0b2c8a796e9530273c110cf4 Mon Sep 17 00:00:00 2001 From: Todd Stinson 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/llui') 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 52814c4e99f62815af85d1270f3268ef37adcb49 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ----- 1 file changed, 5 deletions(-) (limited to 'indra/llui') 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(); - //} } } -- cgit v1.2.3 From 41cba389f89ff16c0e574ea26d6a1ceb60133ef7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra/llui') 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(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(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 -- cgit v1.2.3 From c4638d1dca7f3292d7ce48ddb2f5598f86282c88 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Aug 2012 19:09:57 -0700 Subject: CHUI-280 : WIP : Implement update of LLConversationModel in LLParticipantList --- indra/llui/llfolderviewmodel.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra/llui') 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) { -- cgit v1.2.3 From be61b5be2f4089e12ca25ca1ece13bd0fdaea543 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/llui') 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(); ) -- cgit v1.2.3 From ab37263a5cda14227724181c771ac1d3ef55f467 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 30 Aug 2012 21:34:48 -0700 Subject: CHUI-285 : LLIMFloaterContainer is now using LLParticipantList fully --- indra/llui/llfolderviewmodel.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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 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 child_list_t; child_list_t mChildren; LLFolderViewModelItem* mParent; LLFolderViewModelInterface& mRootViewModel; -- cgit v1.2.3 From ae2e611dfb7b712c159ebafabb83ebbc1f7465b6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 + 2 files changed, 8 insertions(+) (limited to 'indra/llui') 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); -- cgit v1.2.3 From 5dc8738076d158aa74a93f7f3630a17d9102fdc4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui/llfolderviewitem.cpp | 8 ++++++-- indra/llui/llfolderviewitem.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) mode change 100644 => 100755 indra/llui/llfolderviewitem.cpp mode change 100644 => 100755 indra/llui/llfolderviewitem.h (limited to 'indra/llui') 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(); 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(); -- cgit v1.2.3 From be06bebffcc1a08c3018ab3712048599455e025b Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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 - 1 file changed, 1 deletion(-) (limited to 'indra/llui') 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: -- cgit v1.2.3 From 51725b3898df96aa5819d86d1e8e7c71b47304f2 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine 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 + 2 files changed, 6 insertions(+) (limited to 'indra/llui') 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 (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 label_width; Optional decimal_digits; Optional allow_text_entry; + Optional allow_digits_only; Optional label_wrap; Optional text_enabled_color; -- cgit v1.2.3 From 2084d33c1ec827b4e8d975a3bf1232e971f704e2 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From c6863d18d7c981756c57bbcd52baa06af00d1551 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui/llfolderviewitem.cpp | 31 ++++++++++++++++--------------- indra/llui/llfolderviewitem.h | 4 +++- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'indra/llui') 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(); 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 sFonts; // map of styles to fonts + }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From e4de40ad8e1abed99c8c8d681c1dda46e72df94f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llui') 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& exceptions = std::set()); @@ -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 - 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(findInstance(name, key)); } template - 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(getInstance(name, key)); } template - 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(showInstance(name, key, focus)); } -- cgit v1.2.3 From 3c8407f32cf947ee1631ed66bba7a676e8b3b670 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui/llfolderviewitem.cpp | 230 +++++++++++++++++++++------------------- indra/llui/llfolderviewitem.h | 3 + 2 files changed, 125 insertions(+), 108 deletions(-) (limited to 'indra/llui') 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(); - 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(); 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, -- cgit v1.2.3 From 86ac47474f42598d3edb65970117b442457f7284 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui') 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 5cb0a6221613f1a2f1181cea0fb8bd526ab872bf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui') 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 381c13d0e51c3c054fdf2afeff8a8bcb6fc7aa11 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +++++++++++++------ 3 files changed, 77 insertions(+), 35 deletions(-) (limited to 'indra/llui') 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 creation_date; Optional allow_open; + Optional 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. -- cgit v1.2.3 From 59a6a23ee0a94a7695679ea8df93bc0c60682262 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui') 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 b5583906d0cce652f456851732db5b1c19659662 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From f9e0831ba04f99335bfb494a22435446dc0852de Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 5b0e06108b3c4373c55103dedab3306f06d392c9 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra/llui') 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(); -- cgit v1.2.3 From 3502e783b7425ba30d92f66697bafa89ae891e60 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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(); -- cgit v1.2.3 From a62a4b60e8a954509a722b96c984b0a798653516 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine 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 +++++++ 2 files changed, 75 insertions(+), 36 deletions(-) (limited to 'indra/llui') 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 r("folder_view_item"); // statics std::map 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 items_t; typedef std::list folders_t; -- cgit v1.2.3 From 0651e10afff81a6e32828c122753d87b8503a79b Mon Sep 17 00:00:00 2001 From: Merov Linden 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 + 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From 7fc33cc47fdc080bbc7674cf118011b689ba1485 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 -- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'indra/llui') 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 { -- cgit v1.2.3 From 11a148415e810706f2a1835b6b717a0a062d458f Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); if (!menu) { menu = LLUICtrlFactory::getDefaultWidget("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 view_model; + Optional options_menu; + Params(); }; -- cgit v1.2.3 From 5e6f224b5eb3591e9ecea981613cf64a2ce56b8a Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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/llui') 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 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 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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 view_model; - Optional options_menu; + Mandatory options_menu; Params(); -- cgit v1.2.3 From efd8910069a01d8440e45f350979054f88e794cb Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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/llui') 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 06a7bd27cb07bd692d02604dcce735122456be6b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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/llui') 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 ad371c2cfd9d39a4d615cb709b8f85fada0154c6 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 5a22949cf509ebd1a3c7dfbd029b4bc188fee4a3 Mon Sep 17 00:00:00 2001 From: maxim_productengine 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 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From 1251f45e6246d81658cf4fe6f2654472c772e94b Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 + 4 files changed, 87 insertions(+), 72 deletions(-) (limited to 'indra/llui') 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(view); + if (context) + return appendContextSubMenu(context); + + LLMenuItemSeparatorGL* separator = dynamic_cast(view); + if (separator) + return append(separator); + + LLMenuItemGL* item = dynamic_cast(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(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 - { - Mandatory 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 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(p); - LLMenuGL::sMenuContainer->addChild(item->getBranch()); - - return append( item ); -} - bool LLContextMenu::addChild(LLView* view, S32 tab_group) { - LLContextMenu* context = dynamic_cast(view); - if (context) - return appendContextSubMenu(context); - - LLMenuItemSeparatorGL* separator = dynamic_cast(view); - if (separator) - return append(separator); - - LLMenuItemGL* item = dynamic_cast(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 getHandle() { return getDerivedHandle(); } LLView* getSpawningView() const { return mSpawningViewHandle.get(); } @@ -691,7 +696,33 @@ protected: LLHandle mSpawningViewHandle; }; +//----------------------------------------------------------------------------- +// class LLContextMenuBranch +// A branch to another context menu +//----------------------------------------------------------------------------- +class LLContextMenuBranch : public LLMenuItemGL +{ +public: + struct Params : public LLInitParam::Block + { + Mandatory 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 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 -- cgit v1.2.3 From 05a72687d848c13754039f6e720a137827533fdb Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 17 Oct 2012 14:55:36 -0700 Subject: CHUI-410: Now when a converation floater is focused the default text 'To ' 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 +++- 4 files changed, 54 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From 49ad7fd4b57cec635c557070be02556094e90ff6 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui') 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 89ba6b793a5a8b3e0599cd2c8db2f1b479ec0fb4 Mon Sep 17 00:00:00 2001 From: maxim_productengine 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/llui') 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 0356ef61cf9f70b97dc78a59fba58465d99f5fc0 Mon Sep 17 00:00:00 2001 From: William Todd Stinson 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/llui') 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 0d25cca2e1e117962aad57dc951c102bec52cb50 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Mon, 22 Oct 2012 15:01:03 -0700 Subject: Backed out changeset: 4202e227f8e4 --- indra/llui/llfloaterreg.cpp | 2 +- indra/llui/llfloaterreg.h | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llui') 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& exceptions = std::set()); @@ -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 - 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(findInstance(name, key)); } template - 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(getInstance(name, key)); } template - 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(showInstance(name, key, focus)); } -- cgit v1.2.3 From a780eb1a92811c2531c2fc1d211e8e5dd03da103 Mon Sep 17 00:00:00 2001 From: maxim_productengine 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/llui') 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 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/llui') 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 d49de3a66a5476f4541f15dc61c68e0e509c4c70 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'indra/llui') 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 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; -- cgit v1.2.3 From a815585fd7de0f5aba60739127f473fd9d22ccfc Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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/llui') 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 5215bf6edef283cb6c570d3e7aea11f0ecf8313f Mon Sep 17 00:00:00 2001 From: maxim_productengine 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/llui') 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 f9b1b440710668a9979e33c7582d79d14cae8d0d Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++ 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 7f2ea292e10b10958b3e00a641b50b194f131e41 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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) -- cgit v1.2.3 From 51cabb2089244f170b307b436e0014a872a145ed Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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 items_t; -- cgit v1.2.3 From 6e2b3527cc95b92bf136b65fd2ee344d4c879faa Mon Sep 17 00:00:00 2001 From: William Todd Stinson 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 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 11 deletions(-) (limited to 'indra/llui') 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 #include #include +#include #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. -- cgit v1.2.3 From 4f6afb08d7f4c5ae721bd343999715bc22dfca8b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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/llui') 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 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 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/llui') 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 8828eb21e2a8960bbcfd4edb2d113dbada7d4a5d Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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, -- cgit v1.2.3 From d1f45654d91762af4e614de2156304d7acad6619 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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(); } } -- cgit v1.2.3 From 2813e49d198400a0f6416e01f720bdeb5f506144 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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/llui') 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 f429decb0c222b293cee4d3b27c8340262fab572 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 -- 2 files changed, 1 insertion(+), 15 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From dbc37f6ca74dba6c6d5194e0397d5cfe6f570c1d Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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 + 1 file changed, 1 insertion(+) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 37d7f469055d3ba4b81815fa2ac8459022e1e3cf Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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/llui') 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, 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 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 + 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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::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 { -- cgit v1.2.3 From 987350fcb3cf2da03b70ac3fbadb0429f523d07a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++---- 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'indra/llui') 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 mTags; -- cgit v1.2.3 From 50b69c3f97c0b58791f7dd67f8b2fbdc9e8ef503 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++ 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'indra/llui') 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 llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams()); - +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 sFonts; // map of styles to fonts + LLFlashTimer* mFlashTimer; }; -- cgit v1.2.3 From e298c2ded8e25a28127c668cf30a74a25c139041 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 +-- 8 files changed, 185 insertions(+), 38 deletions(-) create mode 100644 indra/llui/llflashtimer.cpp create mode 100644 indra/llui/llflashtimer.h (limited to 'indra/llui') 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 llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams()); -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 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 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(); } -- cgit v1.2.3 From 48a683af70fe359f4b4b6fdf6486208fc34dc2a9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 19 Nov 2012 17:40:46 +0200 Subject: CHUI-488 ADD. fIX Clean up code --- indra/llui/llbutton.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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 llbutton_orig_h_pad ("UIButtonOrigHPad", 0); -- cgit v1.2.3 From 834ded33ae4926b59074f00c13fa3dbf228a3ba0 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 - 1 file changed, 1 deletion(-) (limited to 'indra/llui') 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 getSelectionList() const; - S32 getNumSelectedItems() { return mSelectedItems.size(); } // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); -- cgit v1.2.3 From edeeed95416be2679e1ad3d29bab5396dbcccaa2 Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 + 10 files changed, 107 insertions(+), 49 deletions(-) (limited to 'indra/llui') 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 llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams()); @@ -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 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 handle_right_mouse; + Optional button_flash_enable; Optional button_flash_count; Optional 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 is_starting_function; Optional is_starting_parameters; + Optional 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 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(button_p); -- cgit v1.2.3 From f37645554ce97026869563aedea8f8c6133d8044 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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/llui') 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 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/llui') 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 1a3c5e574bb262f4b334b1c00c671db346c1c658 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From 80f8a465eb2885246b0a1daca66077ecd1dcc61d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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, -- cgit v1.2.3 From 1ce49f764fa00406088f7bcd7623603baedd5fe8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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 */ -- cgit v1.2.3 From 2ee6bcab371a08791bccad3a4fa072c1d60cd6c9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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; -- cgit v1.2.3 From 60c72c85e2360284ecc3326871dcc76fcce0e945 Mon Sep 17 00:00:00 2001 From: William Todd Stinson 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/llui') 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 LLNotificationFilter; -typedef boost::function LLNotificationComparator; typedef std::set LLNotificationSet; typedef std::multimap 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 mListener; std::vector 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 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 -#include -#include - -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 > 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 8642088d65ec340b50661e2a3bf74820ec595010 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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); -- cgit v1.2.3 From fc000880b40143534c47c475a7a0aba6ab75039e Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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& 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 context; Optional responder; + Optional offer_from_agent; struct Functor : public LLInitParam::ChoiceBlock { @@ -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; -- cgit v1.2.3 From ffe80818064572a19b52d4f39f0e14538f701275 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +--- 2 files changed, 1 insertion(+), 15 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From a4a2cc62c3411f0391b90d9720a13b49b0e123ef Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +++++++--- 2 files changed, 26 insertions(+), 23 deletions(-) (limited to 'indra/llui') 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 r("folder_view_item"); // statics std::map 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 creation_date; Optional allow_open; + Optional font_color; + Optional font_highlight_color; + Optional 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 -- cgit v1.2.3 From 3a49beed0e96a797a6d663bcae5e932437ca3661 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llurlentry.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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(); } // -- cgit v1.2.3 From 5f6d55eb1b264780fbb703b115e9b4428cc4ee2b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine 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/llui') 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 items_t; -- cgit v1.2.3 From bb322a1cccd3fab28951ad4e11b5edcfc4e48140 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui/tests/llurlentry_stub.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'indra/llui') 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 // -- cgit v1.2.3 From 5df9d52d48b56a5d8f36a45ced0393c99473f536 Mon Sep 17 00:00:00 2001 From: William Todd Stinson 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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); -- cgit v1.2.3 From 569701cfc898091a414dad0650f89471b1962d49 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From c73947ac1fc6c48bca75ea7d6beeda63eb695b2b Mon Sep 17 00:00:00 2001 From: William Todd Stinson 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 +++ 2 files changed, 5 insertions(+) (limited to 'indra/llui') 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; }; -- cgit v1.2.3 From 22c2fff4ba4198b8dca8367ae3f03d189e815770 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'indra/llui') 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 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)); } -- cgit v1.2.3 From 9b556fb3fea0a97f5773d8fd435a428b0fafacbf Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llurlentry.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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(); } // -- cgit v1.2.3 From 01bdfb3ecb88ce71078494274a8d7835d181c50e Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 ++++++++++++++++++--- 6 files changed, 36 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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 listener) {mResizeListener = listener;} private: S32 mDragLastScreenX; @@ -84,6 +85,7 @@ private: BOOL mSnappingEnabled; BOOL mAllowDoubleClickSnapping; LLView* mResizingView; + boost::function 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, -- cgit v1.2.3 From 6fe7144104cd8b5bd9c7d215f76afdeafe13b7ee Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++++++ 4 files changed, 36 insertions(+), 15 deletions(-) (limited to 'indra/llui') 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; }; -- cgit v1.2.3 From c2d332a89cb29d54df40f1f120304d871278fb76 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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"); } -- cgit v1.2.3 From d2102c9b9f7ad31d3b5061a19f7b955af2f34b9f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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/llui') 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 8adca4583ec95ac063f79990ac092998f24415b8 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++- 2 files changed, 33 insertions(+), 18 deletions(-) (limited to 'indra/llui') 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 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, -- cgit v1.2.3 From ba297b167f75d8a09c959952a300d492f2aec88b Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 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 090636f107a2d3ba3438a6690f36eac3ec257314 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From d99fa985c8ff65913e85dfaa9fd91892a197c4cc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'indra/llui') 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 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) -- cgit v1.2.3 From aa6fee292d1721eac6f0f1f270844e01e06979d4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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 name; Alternative function; Alternative responder; + Alternative responder_sd; Functor() : name("responseFunctor"), function("functor"), - responder("responder") + responder("responder"), + responder_sd("responder_sd") {} }; Optional functor; -- cgit v1.2.3 From 118201943da157b6932d8c79ab3eb3d8c3c0a9a4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'indra/llui') 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) { } -- cgit v1.2.3 From 02ca16c1334d1409d8b14136f76305686796c359 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'indra/llui') 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& 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 context; Optional responder; Optional offer_from_agent; + Optional is_dnd; struct Functor : public LLInitParam::ChoiceBlock { @@ -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; -- cgit v1.2.3 From 3d0ec3da5baea6bb2b9b72707a884ac7b516c4fd Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From d71c0ab32c744a6672e4364e3d090d317ec0647c Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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() { -- cgit v1.2.3 From 0e7e877379b4ab0d8d8b7ae3ce8c9dfb91cc9de7 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 974720373d608a8cbcd3cd26c125b6487b5926a2 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 + 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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); -- cgit v1.2.3 From 856969285e027def5acba6c252dc65a242349d4f Mon Sep 17 00:00:00 2001 From: "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/llui') 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 b5172de28fd6bb8a833cf93180d2d43dd9d4a073 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++-- 2 files changed, 33 insertions(+), 22 deletions(-) (limited to 'indra/llui') 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& 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); -- cgit v1.2.3 From 4ef1181cdcb03a08fbce8d774cd85ef914bef8f3 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +- 3 files changed, 1 insertion(+), 91 deletions(-) (limited to 'indra/llui') 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((*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& 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 { -- cgit v1.2.3 From 60eaa8875df45f023c3bf0fb82863b05cb5a090f Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 Date: Wed, 9 Jan 2013 20:20:32 -0800 Subject: CHUI-649 : WIP : Cleanup code to make it readable --- indra/llui/llfolderviewitem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llui') 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(); } } -- cgit v1.2.3 From 2e3113863022a21d2145cc23992d6afab9c6fbcd Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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" 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/llui') 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 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/llui') 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 b7f4916b3e4af149d6212a701c556915e23e7c0a Mon Sep 17 00:00:00 2001 From: Cho 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/llui') 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 b0774ec9147ddc2c2e5e93e5a74c929c802c32af Mon Sep 17 00:00:00 2001 From: "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/llui') 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 aabfce7d9f14ff18ea073708d79c6f62118b3453 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'indra/llui') 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(view)) + LLMenuGL* menup = dynamic_cast(view); + if (menup) { - appendMenu(menup); - return true; + return appendMenu(menup); } - else if (LLMenuItemGL* itemp = dynamic_cast(view)) + + LLMenuItemGL* itemp = dynamic_cast(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(view); if (context) + { return appendContextSubMenu(context); + } LLMenuItemSeparatorGL* separator = dynamic_cast(view); if (separator) + { return append(separator); + } LLMenuItemGL* item = dynamic_cast(view); if (item) + { return append(item); - + } + + LLMenuGL* menup = dynamic_cast(view); + if (menup) + { + return appendMenu(menup); + } + return false; } -- cgit v1.2.3 From 5eef65e99476b716985eeccfbbcdafdfb664cb1a Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 ++++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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(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(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 -- cgit v1.2.3 From 52018b79bdd715dbb7bd42792447566347b641d5 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 d0204ab367f5ceb5eab89e2273b897975acbfe5a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 ++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'indra/llui') 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 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 mPopupMenuHandle; - typedef std::deque selected_items_t; selected_items_t mSelectedItems; BOOL mKeyboardSelection; BOOL mAllowMultiSelect; -- cgit v1.2.3 From 977d318ac8ccb756bb90a8572f01bc6825b5d0a3 Mon Sep 17 00:00:00 2001 From: Cho 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 +++++ 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'indra/llui') 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 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 autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // // Text manipulation // -- cgit v1.2.3 From d67804543d4042c1196c05db5303b76089d4ade2 Mon Sep 17 00:00:00 2001 From: Cho 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 ++++---- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'indra/llui') 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 autoreplace_callback_t; - autoreplace_callback_t mAutoreplaceCallback; - void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // Autoreplace (formerly part of LLLineEditor) + typedef boost::function autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } // // Text manipulation -- cgit v1.2.3 From 163f3de73d93be8f5e482be03a1952244cadee68 Mon Sep 17 00:00:00 2001 From: Cho 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 +- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'indra/llui') 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 autoreplace_callback_t; + typedef boost::function autoreplace_callback_t; autoreplace_callback_t mAutoreplaceCallback; void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } -- cgit v1.2.3 From c418d616276ce16d910c6e5528f6aa058803e1c7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales 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 +++ 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'indra/llui') 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 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 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; -- cgit v1.2.3 From 1192abd7eb0dff000be69f21d4d7cc7e0ecef561 Mon Sep 17 00:00:00 2001 From: Cho 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/llui') 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 6a68f16f2e908838b89216543b36f07e2a71c360 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 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::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 f944608ab93199a5588ec2c969268b094b8be7c8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine 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/llui') 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 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 7ed270ff9dfdbc905dbee70907d3057a5ae490e7 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 --- 2 files changed, 26 deletions(-) (limited to 'indra/llui') 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 -- cgit v1.2.3 From dac026a7d6ad932ef185b4e5c5b5efd7b059e911 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 -------------- 1 file changed, 14 deletions(-) (limited to 'indra/llui') 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; } -- cgit v1.2.3 From c55e4a61242cd3cf94e0a28398fd33a4eb8ea683 Mon Sep 17 00:00:00 2001 From: Cho 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 instead of a LLView* to fix crash (from accessing deleted LLView) --- indra/llui/lldockcontrol.cpp | 31 ++++++++++++++++++------------- indra/llui/lldockcontrol.h | 4 ++-- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'indra/llui') 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(); 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 mDockWidget; LLRect mPrevDockRect; LLRect mRootRect; LLRect mFloaterRect; -- cgit v1.2.3 From 4a0dd9ec76bfc9a3207b0e75608343f29fb26358 Mon Sep 17 00:00:00 2001 From: Cho 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/llui') 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(); + mDockWidgetHandle = LLHandle(); 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 mDockWidget; + LLHandle mDockWidgetHandle; LLRect mPrevDockRect; LLRect mRootRect; LLRect mFloaterRect; -- cgit v1.2.3 From 46294bdcaca5ea259dee95256179653779697e21 Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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/llui') 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(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(word_start, word_end)); + } } // Find the start of the next word -- cgit v1.2.3 From 4b4367269058c8ba10d284b48ffae9e24fd086ce Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine 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/llui') 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 96bc3d206d890255300d367a70493f93cd0dc5f8 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 floaters_to_move; + std::vector 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(*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::iterator view_it; - for(view_it = floaters_to_move.begin(); view_it != floaters_to_move.end(); ++view_it) + std::vector::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 50d50019d8b8350bc7b04b0b49c6107cde62f4b0 Mon Sep 17 00:00:00 2001 From: maksymsproductengine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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); -- cgit v1.2.3 From 86150b4019d1a84b4af73f0ea18c47baff955562 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++++++++------------ 3 files changed, 52 insertions(+), 14 deletions(-) (limited to 'indra/llui') 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(); } } -- cgit v1.2.3 From 7f51bd7897a3ced0edc74a32b9148febd7866721 Mon Sep 17 00:00:00 2001 From: Merov Linden 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 ++++++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 34 deletions(-) (limited to 'indra/llui') 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(); + } } } -- cgit v1.2.3 From 9530b9d2b717d338af79108c60c2aa67e33ba6e5 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') 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); } -- cgit v1.2.3 From e42e6bc68ae0b0f7a0bd2ca6f500ba783cc201a3 Mon Sep 17 00:00:00 2001 From: Merov Linden 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/llui') 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 477920b13834c977659d11d91d8f2d52e05f54b8 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine 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 + 3 files changed, 16 insertions(+) (limited to 'indra/llui') 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 url_callback_t; -- cgit v1.2.3 From 34fe6ad59161e0dcd57dfdc1feb6cfd1fcaa4794 Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Tue, 12 Mar 2013 22:34:15 +0000 Subject: SH-3944 WIP CHUI merge fixing re-introduced don's refactor of low-level openGL calls pulling out of llui and putting them into llrender. Took the new code from their updated versions from the CHUI merge, but put them in a place accessible to appearance utility. --- indra/llui/CMakeLists.txt | 2 - indra/llui/llcombobox.cpp | 2 +- indra/llui/lllineeditor.cpp | 6 +- indra/llui/lllocalcliprect.cpp | 8 +- indra/llui/lltextbase.cpp | 4 +- indra/llui/lltexteditor.cpp | 2 +- indra/llui/llui.cpp | 1567 +--------------------------------------- indra/llui/llui.h | 130 +--- indra/llui/lluiimage.cpp | 243 ------- indra/llui/lluiimage.h | 126 ---- 10 files changed, 39 insertions(+), 2051 deletions(-) delete mode 100644 indra/llui/lluiimage.cpp delete mode 100644 indra/llui/lluiimage.h (limited to 'indra/llui') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 01c42e07a2..34a08603fa 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -117,7 +117,6 @@ set(llui_SOURCE_FILES lluicolortable.cpp lluictrl.cpp lluictrlfactory.cpp - lluiimage.cpp lluistring.cpp llundo.cpp llurlaction.cpp @@ -231,7 +230,6 @@ set(llui_HEADER_FILES lluifwd.h llui.h lluicolor.h - lluiimage.h lluistring.h llundo.h llurlaction.h diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 41e5d74042..d4e14d9419 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -551,7 +551,7 @@ void LLComboBox::showList() LLCoordWindow window_size; getWindow()->getSize(&window_size); //HACK: shouldn't have to know about scale here - mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); + mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); // Make sure that we can see the whole list LLRect root_view_local; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 2e64be89fa..f8b84e39b5 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2015,8 +2015,8 @@ void LLLineEditor::draw() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } @@ -2563,7 +2563,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length) S32 LLLineEditor::getPreeditFontSize() const { - return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace) diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index 31ceb0766a..0620e0f52d 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion() LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; - x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); - y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); - w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; - h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; + x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); + y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); + w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; + h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; glScissor( x,y,w,h ); stop_glerror(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7cee9f5b46..e22b806a74 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -521,8 +521,8 @@ void LLTextBase::drawCursor() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d5e08fa29b..3dc1b99edb 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2911,7 +2911,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 2a774d54a3..0ddb149738 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -39,6 +39,7 @@ #include "llrect.h" #include "lldir.h" #include "llgl.h" +#include "llsd.h" // Project includes #include "llcommandmanager.h" @@ -69,16 +70,13 @@ // // Globals // -const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); // Language for UI construction std::map gTranslation; std::list 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; /*static*/ BOOL LLUI::sDirty = FALSE; @@ -158,1474 +156,6 @@ void make_ui_sound_deferred(const char* namep) } } -BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) -{ - if (x < left || right < x) return FALSE; - if (y < bottom || top < y) return FALSE; - return TRUE; -} - - -// Puts GL into 2D drawing mode by turning off lighting, setting to an -// orthographic projection, etc. -void gl_state_for_2d(S32 width, S32 height) -{ - stop_glerror(); - F32 window_width = (F32) width;//gViewerWindow->getWindowWidth(); - F32 window_height = (F32) height;//gViewerWindow->getWindowHeight(); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadIdentity(); - gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadIdentity(); - stop_glerror(); -} - - -void gl_draw_x(const LLRect& rect, const LLColor4& color) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin( LLRender::LINES ); - gGL.vertex2i( rect.mLeft, rect.mTop ); - gGL.vertex2i( rect.mRight, rect.mBottom ); - gGL.vertex2i( rect.mLeft, rect.mBottom ); - gGL.vertex2i( rect.mRight, rect.mTop ); - gGL.end(); -} - - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled) -{ - gGL.color4fv(color.mV); - gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled); -} - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled) -{ - gGL.pushUIMatrix(); - left += LLFontGL::sCurOrigin.mX; - right += LLFontGL::sCurOrigin.mX; - bottom += LLFontGL::sCurOrigin.mY; - top += LLFontGL::sCurOrigin.mY; - - gGL.loadUIIdentity(); - gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset, - llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset, - llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset, - llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset, - filled); - gGL.popUIMatrix(); -} - - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Counterclockwise quad will face the viewer - if( filled ) - { - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - if( gGLManager.mATIOffsetVerticalLines ) - { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - gGL.begin( LLRender::LINES ); - - // Verticals - gGL.vertex2i(left + 1, top); - gGL.vertex2i(left + 1, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - - // Horizontals - top--; - right--; - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - - gGL.vertex2i(left, top); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - top--; - right--; - gGL.begin( LLRender::LINE_STRIP ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.vertex2i(left, top); - gGL.end(); - } - } - stop_glerror(); -} - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( left, top, right, bottom, filled ); -} - - -void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -// Given a rectangle on the screen, draws a drop shadow _outside_ -// the right and bottom edges of it. Along the right it has width "lines" -// and along the bottom it has height "lines". -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // HACK: Overlap with the rectangle by a single pixel. - right--; - bottom++; - lines++; - - LLColor4 end_color = start_color; - end_color.mV[VALPHA] = 0.f; - - gGL.begin(LLRender::QUADS); - - // Right edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right+lines, bottom); - gGL.vertex2i(right+lines, top-lines); - - // Bottom edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); - - // bottom left Corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); - // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); - - // bottom right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); - // make the rightmost corner not sharp - gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); - - // top right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); - gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); - // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); - - gGL.end(); - stop_glerror(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv(color.mV); - - if (filled) - { - gGL.begin(LLRender::TRIANGLES); - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.vertex2i(x3, y3); - gGL.end(); -} - -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - length = llmin((S32)(max_frac*(right - left)), length); - length = llmin((S32)(max_frac*(top - bottom)), length); - gGL.begin(LLRender::LINES); - gGL.vertex2i(left, top); - gGL.vertex2i(left + length, top); - - gGL.vertex2i(left, top); - gGL.vertex2i(left, top - length); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left + length, bottom); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left, bottom + length); - - gGL.vertex2i(right, top); - gGL.vertex2i(right - length, top); - - gGL.vertex2i(right, top); - gGL.vertex2i(right, top - length); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right - length, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, bottom + length); - gGL.end(); -} - - -void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect ) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // scale screen size of borders down - F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); - F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); - - LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); - gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) -{ - stop_glerror(); - - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // add in offset of current image to current UI translation - const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - - F32 uv_width = uv_outer_rect.getWidth(); - F32 uv_height = uv_outer_rect.getHeight(); - - // shrink scaling region to be proportional to clipped image region - LLRectf uv_center_rect( - uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), - uv_outer_rect.mBottom + (center_rect.mTop * uv_height), - uv_outer_rect.mLeft + (center_rect.mRight * uv_width), - uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); - - S32 image_natural_width = llround(image_width * uv_width); - S32 image_natural_height = llround(image_height * uv_height); - - LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, - uv_center_rect.mTop * image_height, - uv_center_rect.mRight * image_width, - uv_center_rect.mBottom * image_height); - - { // scale fixed region of image to drawn region - draw_center_rect.mRight += width - image_natural_width; - draw_center_rect.mTop += height - image_natural_height; - - F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); - F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); - - F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); - F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); - - F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); - - draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); - draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); - draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); - draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); - } - - LLRectf draw_outer_rect(ui_translation.mV[VX], - ui_translation.mV[VY] + height * ui_scale.mV[VY], - ui_translation.mV[VX] + width * ui_scale.mV[VX], - ui_translation.mV[VY]); - - LLGLSUIDefault gls_ui; - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gSolidColorProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - } - } - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - const S32 NUM_VERTICES = 9 * 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - S32 index = 0; - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom right - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - // draw left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - // draw top left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - } -} - -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); -} - -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - LLGLSUIDefault gls_ui; - - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - if (degrees == 0.f) - { - const S32 NUM_VERTICES = 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - gGL.begin(LLRender::QUADS); - { - LLVector3 ui_scale = gGL.getUIScale(); - LLVector3 ui_translation = gGL.getUITranslation(); - ui_translation.mV[VX] += x; - ui_translation.mV[VY] += y; - ui_translation.scaleVec(ui_scale); - S32 index = 0; - S32 scaled_width = llround(width * ui_scale.mV[VX]); - S32 scaled_height = llround(height * ui_scale.mV[VY]); - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - } - else - { - gGL.pushUIMatrix(); - gGL.translateUI((F32)x, (F32)y, 0.f); - - F32 offset_x = F32(width/2); - F32 offset_y = F32(height/2); - - gGL.translateUI(offset_x, offset_y, 0.f); - - LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - gGL.begin(LLRender::QUADS); - { - LLVector3 v; - - v = LLVector3(offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - } - gGL.end(); - gGL.popUIMatrix(); - } -} - - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) -{ - phase = fmod(phase, 1.f); - - S32 shift = S32(phase * 4.f) % 4; - - // Stippled line - LLGLEnable stipple(GL_LINE_STIPPLE); - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - - gGL.flush(); - glLineWidth(2.5f); - - if (!LLGLSLShader::sNoFixedFunction) - { - glLineStipple(2, 0x3333 << shift); - } - - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv( start.mV ); - gGL.vertex3fv( end.mV ); - } - gGL.end(); - - LLUI::setLineWidth(1.f); -} - -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle) -{ - if (end_angle < start_angle) - { - end_angle += F_TWO_PI; - } - - gGL.pushUIMatrix(); - { - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = (end_angle - start_angle) / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = cosf(start_angle) * radius; - F32 y = sinf(start_angle) * radius; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_STRIP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled) -{ - gGL.pushUIMatrix(); - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = F_TWO_PI / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = radius; - F32 y = 0.f; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -// Renders a ring with sides (tube shape) -void gl_deep_circle( F32 radius, F32 depth, S32 steps ) -{ - F32 x = radius; - F32 y = 0.f; - F32 angle_delta = F_TWO_PI / (F32)steps; - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - S32 step = steps + 1; // An extra step to close the circle. - while( step-- ) - { - gGL.vertex3f( x, y, depth ); - gGL.vertex3f( x, y, 0.f ); - - F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta); - y = x * sinf(angle_delta) + y * cosf(angle_delta); - x = x_new; - } - } - gGL.end(); -} - -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ) -{ - gGL.pushUIMatrix(); - { - gGL.translateUI(0.f, 0.f, -width / 2); - if( render_center ) - { - gGL.color4fv(center_color.mV); - gGL.diffuseColor4fv(center_color.mV); - gl_deep_circle( radius, width, steps ); - } - else - { - gGL.diffuseColor4fv(side_color.mV); - gl_washer_2d(radius, radius - width, steps, side_color, side_color); - gGL.translateUI(0.f, 0.f, width); - gl_washer_2d(radius - width, radius, steps, side_color, side_color); - } - } - gGL.popUIMatrix(); -} - -// Draw gray and white checkerboard with black border -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) -{ - if (!LLGLSLShader::sNoFixedFunction) - { - // Initialize the first time this is called. - const S32 PIXELS = 32; - static GLubyte checkerboard[PIXELS * PIXELS]; - static BOOL first = TRUE; - if( first ) - { - for( S32 i = 0; i < PIXELS; i++ ) - { - for( S32 j = 0; j < PIXELS; j++ ) - { - checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; - } - } - first = FALSE; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // ...white squares - gGL.color4f( 1.f, 1.f, 1.f, alpha ); - gl_rect_2d(rect); - - // ...gray squares - gGL.color4f( .7f, .7f, .7f, alpha ); - gGL.flush(); - - glPolygonStipple( checkerboard ); - - LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); - gl_rect_2d(rect); - } - else - { //polygon stipple is deprecated, use "Checker" texture - LLPointer img = LLUI::getUIImage("Checker"); - gGL.getTexUnit(0)->bind(img->getImage()); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - - LLColor4 color(1.f, 1.f, 1.f, alpha); - LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); - - gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), - img->getImage(), color, uv_rect); - } - - gGL.flush(); -} - - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = F_TWO_PI / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius; - F32 y1 = 0.f; - F32 x2 = inner_radius; - F32 y2 = 0.f; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = (end_radians - start_radians) / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius * cos( start_radians ); - F32 y1 = outer_radius * sin( start_radians ); - F32 x2 = inner_radius * cos( start_radians ); - F32 y2 = inner_radius * sin( start_radians ); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -void gl_rect_2d_simple_tex( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(width, height); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(0, height); - - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(0, 0); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(width, 0); - - gGL.end(); -} - -void gl_rect_2d_simple( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(width, height); - gGL.vertex2i(0, height); - gGL.vertex2i(0, 0); - gGL.vertex2i(width, 0); - gGL.end(); -} - -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) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2f(0.f, 0.f); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - // draw bottom right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2fv(width_vec.mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - // draw right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - // draw top right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2fv((width_vec + height_vec).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - } - gGL.end(); - - gGL.popUIMatrix(); -} - -//FIXME: rewrite to use scissor? -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) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - F32 middle_start = border_scale / (F32)width; - F32 middle_end = 1.f - middle_start; - - F32 u_min; - F32 u_max; - LLVector2 x_min; - LLVector2 x_max; - - gGL.begin(LLRender::QUADS); - { - if (start_fragment < middle_start) - { - u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; - u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; - x_min = (start_fragment / middle_start) * border_width_left; - x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; - - // draw bottom left - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_start || start_fragment < middle_end) - { - x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; - x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((x_max).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_end) - { - u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; - u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; - x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); - x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); - - // draw bottom right - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv((x_min).mV); - - gGL.texCoord2f(u_max, 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw right - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top right - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - } - gGL.end(); - - gGL.popUIMatrix(); -} - -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) -{ - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); - gGL.vertex3f(0.f, 0.f, 0.f); - - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec).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(clip_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - - // draw bottom middle - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec).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(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(center_uv_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv(width_vec.mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).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(clip_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mBottom * height_vec).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(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(clip_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - - // draw middle - 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(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(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(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(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(clip_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).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(clip_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mTop * height_vec).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(center_uv_rect.mLeft, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - - gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); - gGL.vertex3fv((height_vec).mV); - - // draw top middle - 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(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(center_uv_rect.mRight, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + 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(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(clip_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); - gGL.vertex3fv((width_vec + 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 LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback, @@ -1633,6 +163,7 @@ void LLUI::initClass(const settings_map_t& settings, const LLVector2* scale_factor, const std::string& language) { + LLRender2D::initClass(image_provider,scale_factor); sSettingGroups = settings; if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) || @@ -1642,10 +173,8 @@ void LLUI::initClass(const settings_map_t& settings, llerrs << "Failure to initialize configuration groups" << llendl; } - 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"); @@ -1679,10 +208,7 @@ void LLUI::initClass(const settings_map_t& settings, void LLUI::cleanupClass() { - if(sImageProvider) - { - sImageProvider->cleanUp(); -} + LLRender2D::cleanupClass(); } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) @@ -1706,60 +232,12 @@ void LLUI::dirtyRect(LLRect rect) } } - -//static -void LLUI::translate(F32 x, F32 y, F32 z) -{ - gGL.translateUI(x,y,z); - LLFontGL::sCurOrigin.mX += (S32) x; - LLFontGL::sCurOrigin.mY += (S32) y; - LLFontGL::sCurDepth += z; -} - -//static -void LLUI::pushMatrix() -{ - gGL.pushUIMatrix(); - LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); -} - -//static -void LLUI::popMatrix() -{ - gGL.popUIMatrix(); - LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; - LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; - LLFontGL::sOriginStack.pop_back(); -} - -//static -void LLUI::loadIdentity() -{ - gGL.loadUIIdentity(); - LLFontGL::sCurOrigin.mX = 0; - LLFontGL::sCurOrigin.mY = 0; - LLFontGL::sCurDepth = 0.f; -} - -//static -void LLUI::setScaleFactor(const LLVector2 &scale_factor) -{ - sGLScaleFactor = scale_factor; -} - -//static -void LLUI::setLineWidth(F32 width) -{ - gGL.flush(); - glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); -} - //static void LLUI::setMousePositionScreen(S32 x, S32 y) { S32 screen_x, screen_y; - screen_x = llround((F32)x * sGLScaleFactor.mV[VX]); - screen_y = llround((F32)y * sGLScaleFactor.mV[VY]); + screen_x = llround((F32)x * getScaleFactor().mV[VX]); + screen_y = llround((F32)y * getScaleFactor().mV[VY]); LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } @@ -1770,8 +248,8 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); - *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]); - *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]); + *x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); + *y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]); } //static @@ -1885,21 +363,21 @@ LLVector2 LLUI::getWindowSize() LLCoordWindow window_rect; sWindow->getSize(&window_rect); - return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]); + return LLVector2(window_rect.mX / getScaleFactor().mV[VX], window_rect.mY / getScaleFactor().mV[VY]); } //static void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y) { - *gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]); - *gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]); + *gl_x = llround((F32)screen_x * getScaleFactor().mV[VX]); + *gl_y = llround((F32)screen_y * getScaleFactor().mV[VY]); } //static void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y) { - *screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]); - *screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]); + *screen_x = llround((F32)gl_x / getScaleFactor().mV[VX]); + *screen_y = llround((F32)gl_y / getScaleFactor().mV[VY]); } //static @@ -1916,27 +394,6 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen) glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom); } -//static -LLPointer LLUI::getUIImageByID(const LLUUID& image_id, S32 priority) -{ - if (sImageProvider) - { - return sImageProvider->getUIImageByID(image_id, priority); - } - else - { - return NULL; - } -} - -//static -LLPointer LLUI::getUIImage(const std::string& name, S32 priority) -{ - if (!name.empty() && sImageProvider) - return sImageProvider->getUIImage(name, priority); - else - return NULL; -} LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 4c1703392a..83831e4799 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -1,6 +1,6 @@ /** * @file llui.h - * @brief GL function declarations and other general static UI services. + * @brief General static UI services. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,122 +24,38 @@ * $/LicenseInfo$ */ -// All immediate-mode gl drawing should happen here. #ifndef LL_LLUI_H #define LL_LLUI_H -#include "llpointer.h" // LLPointer<> #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" -#include "llglslshader.h" +#include "v2math.h" #include "llinitparam.h" #include "llregistry.h" +#include "llrender2dutils.h" +#include "llpointer.h" #include "lluicolor.h" #include "lluicolortable.h" +#include "lluiimage.h" #include #include "lllazyvalue.h" #include "llframetimer.h" #include -// LLUIFactory -#include "llsd.h" - // for initparam specialization #include "llfontgl.h" -class LLColor4; -class LLVector3; -class LLVector2; -class LLUIImage; class LLUUID; class LLWindow; class LLView; 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); - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2); -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ); -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled); -void gl_rect_2d_simple( S32 width, S32 height ); - -void gl_draw_x(const LLRect& rect, const LLColor4& color); - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE ); -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE ); -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f); - -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines); - -void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled); -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle); -void gl_deep_circle( F32 radius, F32 depth ); -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ); -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac); -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); - -void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); - -void gl_rect_2d_simple_tex( S32 width, S32 height ); - -// segmented rectangles - -/* - TL |______TOP_________| TR - /| |\ - _/_|__________________|_\_ - L| | MIDDLE | |R - _|_|__________________|_|_ - \ | BOTTOM | / - BL\|__________________|/ BR - | | -*/ - -typedef enum e_rounded_edge -{ - ROUNDED_RECT_LEFT = 0x1, - ROUNDED_RECT_TOP = 0x2, - ROUNDED_RECT_RIGHT = 0x4, - ROUNDED_RECT_BOTTOM = 0x8, - ROUNDED_RECT_ALL = 0xf -}ERoundedEdge; - - -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 LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); - -inline void gl_rect_2d( const LLRect& rect, BOOL filled ) -{ - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled) -{ - gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); -} - class LLImageProviderInterface; typedef void (*LLUIAudioCallback)(const LLUUID& uuid); @@ -281,10 +197,10 @@ public: static void cleanupClass(); static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& ); - static void pushMatrix(); - static void popMatrix(); - static void loadIdentity(); - static void translate(F32 x, F32 y, F32 z = 0.0f); + static void pushMatrix() { LLRender2D::pushMatrix(); } + static void popMatrix() { LLRender2D::popMatrix(); } + static void loadIdentity() { LLRender2D::loadIdentity(); } + static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); } static LLRect sDirtyRect; static BOOL sDirty; @@ -329,10 +245,13 @@ public: static void getMousePositionScreen(S32 *x, S32 *y); static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y); static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y); - static void setScaleFactor(const LLVector2& scale_factor); - static void setLineWidth(F32 width); - static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0); - static LLPointer getUIImage(const std::string& name, S32 priority = 0); + static LLVector2& getScaleFactor() { return LLRender2D::sGLScaleFactor; } + static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::setScaleFactor(scale_factor); } + static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); } + static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0) + { return LLRender2D::getUIImageByID(image_id, priority); } + static LLPointer getUIImage(const std::string& name, S32 priority = 0) + { return LLRender2D::getUIImage(name, priority); } static LLVector2 getWindowSize(); static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y); static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y); @@ -362,12 +281,10 @@ public: static settings_map_t sSettingGroups; static LLUIAudioCallback sAudioCallback; static LLUIAudioCallback sDeferredAudioCallback; - static LLVector2 sGLScaleFactor; static LLWindow* sWindow; static LLView* sRootView; static LLHelp* sHelpImpl; private: - static LLImageProviderInterface* sImageProvider; static std::vector sXUIPaths; static LLFrameTimer sMouseIdleTimer; static add_popup_t sAddPopupFunc; @@ -378,18 +295,6 @@ private: // Moved LLLocalClipRect to lllocalcliprect.h -//RN: maybe this needs to moved elsewhere? -class LLImageProviderInterface -{ -protected: - LLImageProviderInterface() {}; - virtual ~LLImageProviderInterface() {}; -public: - virtual LLPointer getUIImage(const std::string& name, S32 priority) = 0; - virtual LLPointer getUIImageByID(const LLUUID& id, S32 priority) = 0; - virtual void cleanUp() = 0; -}; - class LLCallbackRegistry { public: @@ -600,7 +505,4 @@ namespace LLInitParam }; } -extern LLGLSLShader gSolidColorProgram; -extern LLGLSLShader gUIProgram; - #endif diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp deleted file mode 100644 index 9ed98f941f..0000000000 --- a/indra/llui/lluiimage.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file lluiimage.cpp - * @brief UI implementation - * - * $LicenseInfo:firstyear=2007&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$ - */ - -// Utilities functions the user interface needs - -//#include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -// Project includes -#include "lluiimage.h" -#include "llui.h" - -LLUIImage::LLUIImage(const std::string& name, LLPointer image) -: mName(name), - mImage(image), - mScaleRegion(0.f, 1.f, 1.f, 0.f), - mClipRegion(0.f, 1.f, 1.f, 0.f), - mUniformScaling(TRUE), - mNoClip(TRUE), - mImageLoaded(NULL) -{ -} - -LLUIImage::~LLUIImage() -{ - delete mImageLoaded; -} - -void LLUIImage::setClipRegion(const LLRectf& region) -{ - mClipRegion = region; - mNoClip = mClipRegion.mLeft == 0.f - && mClipRegion.mRight == 1.f - && mClipRegion.mBottom == 0.f - && mClipRegion.mTop == 1.f; -} - -void LLUIImage::setScaleRegion(const LLRectf& region) -{ - mScaleRegion = region; - mUniformScaling = mScaleRegion.mLeft == 0.f - && mScaleRegion.mRight == 1.f - && mScaleRegion.mBottom == 0.f - && mScaleRegion.mTop == 1.f; -} - -//TODO: move drawing implementation inside class -void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const -{ - gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion); -} - -void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const -{ - if (mUniformScaling) - { - gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); - } - else - { - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - FALSE, - mClipRegion, - mScaleRegion); - } -} - -void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const -{ - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - TRUE, - mClipRegion, - mScaleRegion); -} - -void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const -{ - LLRect border_rect; - border_rect.setOriginAndSize(x, y, width, height); - border_rect.stretch(border_width, border_width); - 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 / (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); - - } LLUI::popMatrix(); -} - - -S32 LLUIImage::getWidth() const -{ - // return clipped dimensions of actual image area - return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); -} - -S32 LLUIImage::getHeight() const -{ - // return clipped dimensions of actual image area - return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); -} - -S32 LLUIImage::getTextureWidth() const -{ - return mImage->getWidth(0); -} - -S32 LLUIImage::getTextureHeight() const -{ - return mImage->getHeight(0); -} - -boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) -{ - if (!mImageLoaded) - { - mImageLoaded = new image_loaded_signal_t(); - } - return mImageLoaded->connect(cb); -} - - -void LLUIImage::onImageLoaded() -{ - if (mImageLoaded) - { - (*mImageLoaded)(); - } -} - - -namespace LLInitParam -{ - void ParamValue::updateValueFromBlock() - { - // The keyword "none" is specifically requesting a null image - // do not default to current value. Used to overwrite template images. - if (name() == "none") - { - updateValue(NULL); - return; - } - - LLUIImage* imagep = LLUI::getUIImage(name()); - if (imagep) - { - updateValue(imagep); - } - } - - void ParamValue::updateBlockFromValue(bool make_block_authoritative) - { - if (getValue() == NULL) - { - name.set("none", make_block_authoritative); - } - else - { - name.set(getValue()->getName(), make_block_authoritative); - } - } - - - bool ParamCompare::equals( - LLUIImage* const &a, - LLUIImage* const &b) - { - // force all LLUIImages for XML UI export to be "non-default" - if (!a && !b) - return false; - else - return (a == b); - } -} - diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h deleted file mode 100644 index 7817ba1c7b..0000000000 --- a/indra/llui/lluiimage.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file lluiimage.h - * @brief wrapper for images used in the UI that handles smart scaling, etc. - * - * $LicenseInfo:firstyear=2007&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_LLUIIMAGE_H -#define LL_LLUIIMAGE_H - -#include "v4color.h" -#include "llpointer.h" -#include "llrefcount.h" -#include "llrefcount.h" -#include "llrect.h" -#include -#include -#include "llinitparam.h" -#include "lltexture.h" - -extern const LLColor4 UI_VERTEX_COLOR; - -class LLUIImage : public LLRefCount -{ -public: - typedef boost::signals2::signal image_loaded_signal_t; - - LLUIImage(const std::string& name, LLPointer image); - virtual ~LLUIImage(); - - void setClipRegion(const LLRectf& region); - void setScaleRegion(const LLRectf& region); - - LLPointer getImage() { return mImage; } - const LLPointer& getImage() const { return mImage; } - - void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; - void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; - void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } - - void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; - void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } - void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); } - - 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; - virtual S32 getHeight() const; - - // returns dimensions of underlying textures, which might not be equal to ui image portion - S32 getTextureWidth() const; - S32 getTextureHeight() const; - - boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb ); - - void onImageLoaded(); - -protected: - image_loaded_signal_t* mImageLoaded; - - std::string mName; - LLRectf mScaleRegion; - LLRectf mClipRegion; - LLPointer mImage; - BOOL mUniformScaling; - BOOL mNoClip; -}; - -namespace LLInitParam -{ - template<> - class ParamValue - : public CustomParamValue - { - typedef boost::add_reference::type>::type T_const_ref; - typedef CustomParamValue super_t; - public: - Optional name; - - ParamValue(LLUIImage* const& image = NULL) - : super_t(image) - { - updateBlockFromValue(false); - addSynonym(name, "name"); - } - - void updateValueFromBlock(); - void updateBlockFromValue(bool make_block_authoritative); - }; - - // Need custom comparison function for our test app, which only loads - // LLUIImage* as NULL. - template<> - struct ParamCompare - { - static bool equals(LLUIImage* const &a, LLUIImage* const &b); - }; -} - -typedef LLPointer LLUIImagePtr; -#endif -- cgit v1.2.3