summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/message.xml18
-rw-r--r--indra/llcharacter/llhandmotion.h2
-rw-r--r--indra/llcommon/lldefs.h18
-rw-r--r--indra/llcommon/llevent.h2
-rw-r--r--indra/llcommon/llmortician.cpp12
-rw-r--r--indra/llcommon/llmortician.h2
-rw-r--r--indra/llcommon/llsdutil.cpp120
-rw-r--r--indra/llcommon/llsdutil.h10
-rw-r--r--indra/llcommon/llstring.h39
-rw-r--r--indra/llcommon/roles_constants.h20
-rw-r--r--indra/llinventory/lluserrelations.cpp5
-rw-r--r--indra/llinventory/lluserrelations.h15
-rw-r--r--indra/llmath/llrect.h7
-rw-r--r--indra/llmath/v3color.h1
-rw-r--r--indra/llmath/v4color.h1
-rw-r--r--indra/llmessage/lliohttpserver.cpp2
-rw-r--r--indra/llmessage/message.cpp50
-rw-r--r--indra/llrender/llimagegl.h10
-rw-r--r--indra/llui/llbutton.cpp277
-rw-r--r--indra/llui/llbutton.h68
-rw-r--r--indra/llui/llcheckboxctrl.cpp19
-rw-r--r--indra/llui/llcombobox.cpp476
-rw-r--r--indra/llui/llcombobox.h53
-rw-r--r--indra/llui/lldraghandle.h1
-rw-r--r--indra/llui/llfloater.cpp32
-rw-r--r--indra/llui/llfocusmgr.cpp41
-rw-r--r--indra/llui/llfocusmgr.h9
-rw-r--r--indra/llui/lliconctrl.cpp16
-rw-r--r--indra/llui/lliconctrl.h2
-rw-r--r--indra/llui/lllineeditor.cpp12
-rw-r--r--indra/llui/lllineeditor.h2
-rw-r--r--indra/llui/llmenugl.cpp3
-rw-r--r--indra/llui/llmodaldialog.cpp2
-rw-r--r--indra/llui/llpanel.cpp215
-rw-r--r--indra/llui/llpanel.h9
-rw-r--r--indra/llui/llresizehandle.cpp2
-rw-r--r--indra/llui/llscrollbar.cpp44
-rw-r--r--indra/llui/llscrollbar.h3
-rw-r--r--indra/llui/llscrollcontainer.cpp38
-rw-r--r--indra/llui/llscrolllistctrl.cpp787
-rw-r--r--indra/llui/llscrolllistctrl.h109
-rw-r--r--indra/llui/llslider.cpp145
-rw-r--r--indra/llui/llslider.h7
-rw-r--r--indra/llui/llsliderctrl.cpp4
-rw-r--r--indra/llui/llsliderctrl.h2
-rw-r--r--indra/llui/llspinctrl.cpp6
-rw-r--r--indra/llui/llspinctrl.h2
-rw-r--r--indra/llui/llstyle.cpp2
-rw-r--r--indra/llui/lltabcontainer.cpp39
-rw-r--r--indra/llui/lltabcontainer.h3
-rw-r--r--indra/llui/lltextbox.cpp8
-rw-r--r--indra/llui/lltextbox.h2
-rw-r--r--indra/llui/lltexteditor.cpp92
-rw-r--r--indra/llui/lltexteditor.h13
-rw-r--r--indra/llui/llui.cpp429
-rw-r--r--indra/llui/llui.h82
-rw-r--r--indra/llui/lluictrl.cpp194
-rw-r--r--indra/llui/lluictrl.h55
-rw-r--r--indra/llui/lluictrlfactory.cpp7
-rw-r--r--indra/llui/llview.cpp436
-rw-r--r--indra/llui/llview.h32
-rw-r--r--indra/llui/llviewborder.cpp2
-rw-r--r--indra/llui/llviewquery.cpp61
-rw-r--r--indra/llui/llviewquery.h32
-rw-r--r--indra/newview/llagent.cpp102
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/llassetuploadresponders.cpp3
-rw-r--r--indra/newview/llchatbar.cpp166
-rw-r--r--indra/newview/llchatbar.h16
-rw-r--r--indra/newview/llfloateranimpreview.cpp2
-rw-r--r--indra/newview/llfloateravatarpicker.cpp13
-rw-r--r--indra/newview/llfloaterchat.cpp30
-rw-r--r--indra/newview/llfloaterchat.h1
-rw-r--r--indra/newview/llfloaterchatterbox.cpp103
-rw-r--r--indra/newview/llfloaterchatterbox.h4
-rw-r--r--indra/newview/llfloaterfriends.cpp443
-rw-r--r--indra/newview/llfloaterfriends.h24
-rw-r--r--indra/newview/llfloaterinspect.cpp1
-rw-r--r--indra/newview/llfloaterland.cpp88
-rw-r--r--indra/newview/llfloaterland.h2
-rw-r--r--indra/newview/llfloaterpostcard.cpp5
-rw-r--r--indra/newview/llfloaterpostcard.h2
-rw-r--r--indra/newview/llfloaterregioninfo.cpp84
-rw-r--r--indra/newview/llfloaterregioninfo.h18
-rw-r--r--indra/newview/llfloaterscriptdebug.cpp4
-rw-r--r--indra/newview/llfloatertools.cpp3
-rw-r--r--indra/newview/llfloatertopobjects.cpp8
-rw-r--r--indra/newview/llfloaterworldmap.cpp8
-rw-r--r--indra/newview/llfloaterworldmap.h1
-rw-r--r--indra/newview/llfolderview.cpp18
-rw-r--r--indra/newview/llfolderview.h2
-rw-r--r--indra/newview/llhudview.cpp4
-rw-r--r--indra/newview/llhudview.h6
-rw-r--r--indra/newview/llimpanel.cpp564
-rw-r--r--indra/newview/llimpanel.h54
-rw-r--r--indra/newview/llimview.cpp466
-rw-r--r--indra/newview/llimview.h32
-rw-r--r--indra/newview/llinventorybridge.cpp2
-rw-r--r--indra/newview/llinventorymodel.cpp2
-rw-r--r--indra/newview/lljoystickbutton.cpp12
-rw-r--r--indra/newview/llmutelist.cpp54
-rw-r--r--indra/newview/llmutelist.h6
-rw-r--r--indra/newview/llnameeditor.cpp2
-rw-r--r--indra/newview/llnameeditor.h2
-rw-r--r--indra/newview/llnamelistctrl.cpp4
-rw-r--r--indra/newview/lloverlaybar.cpp493
-rw-r--r--indra/newview/lloverlaybar.h20
-rw-r--r--indra/newview/llpanelavatar.cpp2
-rw-r--r--indra/newview/llpanelclassified.cpp8
-rw-r--r--indra/newview/llpanelclassified.h2
-rw-r--r--indra/newview/llpanelface.cpp2
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp12
-rw-r--r--indra/newview/llpanelgroupgeneral.h1
-rw-r--r--indra/newview/llpanelgrouplandmoney.cpp2
-rw-r--r--indra/newview/llpanelgrouproles.cpp15
-rw-r--r--indra/newview/llpanelgrouproles.h1
-rw-r--r--indra/newview/llpanellogin.cpp2
-rw-r--r--indra/newview/llpanelobject.cpp2
-rw-r--r--indra/newview/llpanelvolume.cpp2
-rw-r--r--indra/newview/llpreviewgesture.cpp2
-rw-r--r--indra/newview/llpreviewscript.cpp2
-rw-r--r--indra/newview/llpreviewsound.cpp2
-rw-r--r--indra/newview/llstartup.cpp2
-rw-r--r--indra/newview/llstatusbar.cpp88
-rw-r--r--indra/newview/lltextureview.cpp1
-rw-r--r--indra/newview/lltoolbar.cpp182
-rw-r--r--indra/newview/lltoolbar.h9
-rw-r--r--indra/newview/lltoolplacer.cpp2
-rw-r--r--indra/newview/llvieweraudio.cpp14
-rw-r--r--indra/newview/llviewermenu.cpp11
-rw-r--r--indra/newview/llviewermessage.cpp20
-rw-r--r--indra/newview/llviewerobject.cpp6
-rw-r--r--indra/newview/llviewerparcelmgr.cpp17
-rw-r--r--indra/newview/llviewerparcelmgr.h2
-rw-r--r--indra/newview/llviewerregion.cpp5
-rw-r--r--indra/newview/llviewerregion.h2
-rw-r--r--indra/newview/llviewertexteditor.cpp86
-rw-r--r--indra/newview/llviewerwindow.cpp209
-rw-r--r--indra/newview/llviewerwindow.h9
-rw-r--r--indra/newview/llvoavatar.cpp4
-rw-r--r--indra/newview/llvoiceclient.cpp184
-rw-r--r--indra/newview/llvoiceclient.h10
-rw-r--r--indra/newview/llvoicevisualizer.cpp2
-rw-r--r--indra/newview/llworldmapview.cpp5
-rwxr-xr-xindra/newview/viewer_manifest.py2
-rw-r--r--scripts/messages/message_template.msg2
146 files changed, 4865 insertions, 3151 deletions
diff --git a/etc/message.xml b/etc/message.xml
index 4534be6db8..ddbfa58ddb 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -284,6 +284,14 @@
<boolean>true</boolean>
</map>
+ <key>AgentDropGroup</key>
+ <map>
+ <key>flavor</key>
+ <string>llsd</string>
+ <key>trusted-sender</key>
+ <boolean>true</boolean>
+ </map>
+
<key>ChatterBoxSessionStartReply</key>
<map>
<key>flavor</key>
@@ -315,7 +323,15 @@
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
-
+
+ <key>ChatterBoxSessionUpdate</key>
+ <map>
+ <key>flavor</key>
+ <string>llsd</string>
+ <key>trusted-sender</key>
+ <boolean>true</boolean>
+ </map>
+
<key>ChatterBoxInvitation</key>
<map>
<key>flavor</key>
diff --git a/indra/llcharacter/llhandmotion.h b/indra/llcharacter/llhandmotion.h
index 39c61b2154..662800784b 100644
--- a/indra/llcharacter/llhandmotion.h
+++ b/indra/llcharacter/llhandmotion.h
@@ -124,6 +124,8 @@ public:
// called when a motion is deactivated
virtual void onDeactivate();
+ virtual BOOL canDeprecate() { return FALSE; }
+
static LLString getHandPoseName(eHandPose pose);
static eHandPose getHandPose(LLString posename);
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index cd8c79a84d..96b2ab169b 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -183,7 +183,15 @@ template <class LLDATATYPE>
inline LLDATATYPE llmax(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3)
{
LLDATATYPE r = llmax(d1,d2);
- return (r > d3 ? r : d3);
+ return llmax(r, d3);
+}
+
+template <class LLDATATYPE>
+inline LLDATATYPE llmax(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3, const LLDATATYPE& d4)
+{
+ LLDATATYPE r1 = llmax(d1,d2);
+ LLDATATYPE r2 = llmax(d3,d4);
+ return llmax(r1, r2);
}
template <class LLDATATYPE>
@@ -200,6 +208,14 @@ inline LLDATATYPE llmin(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATA
}
template <class LLDATATYPE>
+inline LLDATATYPE llmin(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3, const LLDATATYPE& d4)
+{
+ LLDATATYPE r1 = llmin(d1,d2);
+ LLDATATYPE r2 = llmin(d3,d4);
+ return llmin(r1, r2);
+}
+
+template <class LLDATATYPE>
inline LLDATATYPE llclamp(const LLDATATYPE& a, const LLDATATYPE& minval, const LLDATATYPE& maxval)
{
return llmin(llmax(a, minval), maxval);
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 3018cc671b..8ba883a0ee 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -179,7 +179,7 @@ public:
if (mDispatcher.notNull()) mDispatcher->removeListener(listener);
}
// Notifies the dispatcher of an event being fired.
- void fireEvent(LLPointer<LLEvent> event, LLSD filter);
+ void fireEvent(LLPointer<LLEvent> event, LLSD filter = LLSD());
protected:
LLPointer<LLEventDispatcher> mDispatcher;
diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp
index cab3a7f973..b3e25104cb 100644
--- a/indra/llcommon/llmortician.cpp
+++ b/indra/llcommon/llmortician.cpp
@@ -33,20 +33,20 @@
#include <list>
-std::list<LLMortician*> gGraveyard;
+std::list<LLMortician*> LLMortician::sGraveyard;
BOOL LLMortician::sDestroyImmediate = FALSE;
LLMortician::~LLMortician()
{
- gGraveyard.remove(this);
+ sGraveyard.remove(this);
}
void LLMortician::updateClass()
{
- while (!gGraveyard.empty())
+ while (!sGraveyard.empty())
{
- LLMortician* dead = gGraveyard.front();
+ LLMortician* dead = sGraveyard.front();
delete dead;
}
}
@@ -56,7 +56,7 @@ void LLMortician::die()
// It is valid to call die() more than once on something that hasn't died yet
if (sDestroyImmediate)
{
- // *NOTE: This is a hack to ensure destruction order on shutdown.
+ // *NOTE: This is a hack to ensure destruction order on shutdown (relative to non-mortician controlled classes).
mIsDead = TRUE;
delete this;
return;
@@ -64,7 +64,7 @@ void LLMortician::die()
else if (!mIsDead)
{
mIsDead = TRUE;
- gGraveyard.push_back(this);
+ sGraveyard.push_back(this);
}
}
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index 24a38520e9..606ac0dc39 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -50,6 +50,8 @@ private:
static BOOL sDestroyImmediate;
BOOL mIsDead;
+
+ static std::list<LLMortician*> sGraveyard;
};
#endif
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index a0f337c2de..992c883a7e 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -301,3 +301,123 @@ char* ll_pretty_print_sd(const LLSD& sd)
buffer[bufferSize - 1] = '\0';
return buffer;
}
+
+//compares the structure of an LLSD to a template LLSD and stores the
+//"valid" values in a 3rd LLSD. Default values are stored in the template
+//
+//If the llsd to test has a specific key to a map and the values
+//are not of the same type, false is returned or if the LLSDs are not
+//of the same value. Ordering of arrays matters
+//Otherwise, returns true
+BOOL compare_llsd_with_template(
+ const LLSD& llsd_to_test,
+ const LLSD& template_llsd,
+ LLSD& resultant_llsd)
+{
+ if (
+ llsd_to_test.isUndefined() &&
+ template_llsd.isDefined() )
+ {
+ resultant_llsd = template_llsd;
+ return TRUE;
+ }
+ else if ( llsd_to_test.type() != template_llsd.type() )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+
+ if ( llsd_to_test.isArray() )
+ {
+ //they are both arrays
+ //we loop over all the items in the template
+ //verifying that the to_test has a subset (in the same order)
+ //any shortcoming in the testing_llsd are just taken
+ //to be the rest of the template
+ LLSD data;
+ LLSD::array_const_iterator test_iter;
+ LLSD::array_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyArray();
+ test_iter = llsd_to_test.beginArray();
+
+ for (
+ template_iter = template_llsd.beginArray();
+ (template_iter != template_llsd.endArray() &&
+ test_iter != llsd_to_test.endArray());
+ ++template_iter)
+ {
+ if ( !compare_llsd_with_template(
+ *test_iter,
+ *template_iter,
+ data) )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+
+ ++test_iter;
+ }
+
+ //so either the test or the template ended
+ //we do another loop now to the end of the template
+ //grabbing the default values
+ for (;
+ template_iter != template_llsd.endArray();
+ ++template_iter)
+ {
+ resultant_llsd.append(*template_iter);
+ }
+ }
+ else if ( llsd_to_test.isMap() )
+ {
+ //now we loop over the keys of the two maps
+ //any excess is taken from the template
+ //excess is ignored in the test
+ LLSD value;
+ LLSD::map_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyMap();
+ for (
+ template_iter = template_llsd.beginMap();
+ template_iter != template_llsd.endMap();
+ ++template_iter)
+ {
+ if ( llsd_to_test.has(template_iter->first) )
+ {
+ //the test LLSD has the same key
+ if ( !compare_llsd_with_template(
+ llsd_to_test[template_iter->first],
+ template_iter->second,
+ value) )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+ else
+ {
+ resultant_llsd[template_iter->first] = value;
+ }
+ }
+ else
+ {
+ //test llsd doesn't have it...take the
+ //template as default value
+ resultant_llsd[template_iter->first] =
+ template_iter->second;
+ }
+ }
+ }
+ else
+ {
+ //of same type...take the test llsd's value
+ resultant_llsd = llsd_to_test;
+ }
+
+
+ return TRUE;
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 699d5093e1..17a881d9cb 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -91,4 +91,14 @@ char* ll_print_sd(const LLSD& sd);
// Serializes sd to static buffer and returns pointer, using "pretty printing" mode.
char* ll_pretty_print_sd(const LLSD& sd);
+//compares the structure of an LLSD to a template LLSD and stores the
+//"valid" values in a 3rd LLSD. Default values
+//are pulled from the template. Ordering of arrays matters
+//Returns false if the test is of same type but values differ in type
+//Otherwise, returns true
+BOOL compare_llsd_with_template(
+ const LLSD& llsd_to_test,
+ const LLSD& template_llsd,
+ LLSD& resultant_llsd);
+
#endif // LL_LLSDUTIL_H
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index ec4ff335c9..d4925d8bee 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -299,6 +299,10 @@ public:
// a.k.a. strdictcmp()
static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
+ // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
+ // a.k.a. strdictcmp()
+ static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
+
// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
@@ -310,7 +314,7 @@ public:
// Copies src into dst at a given offset.
static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
-#ifdef _DEBUG
+#ifdef _DEBUG
static void testHarness();
#endif
@@ -678,6 +682,39 @@ S32 LLStringBase<T>::compareDict(const std::basic_string<T>& astr, const std::ba
return ca-cb;
}
+template<class T>
+S32 LLStringBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
+{
+ const T* a = astr.c_str();
+ const T* b = bstr.c_str();
+ T ca, cb;
+ S32 ai, bi, cnt = 0;
+
+ ca = *(a++);
+ cb = *(b++);
+ while( ca && cb ){
+ if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
+ if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
+ if( LLStringOps::isDigit(ca) ){
+ if( cnt-->0 ){
+ if( cb!=ca ) break;
+ }else{
+ if( !LLStringOps::isDigit(cb) ) break;
+ for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
+ for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
+ if( ai<bi ){ ca=0; break; }
+ if( bi<ai ){ cb=0; break; }
+ if( ca!=cb ) break;
+ cnt = ai;
+ }
+ }else if( ca!=cb ){ break;
+ }
+ ca = *(a++);
+ cb = *(b++);
+ }
+ return ca-cb;
+}
+
// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
// static
template<class T>
diff --git a/indra/llcommon/roles_constants.h b/indra/llcommon/roles_constants.h
index 1a7c977f21..12bd21ec20 100644
--- a/indra/llcommon/roles_constants.h
+++ b/indra/llcommon/roles_constants.h
@@ -56,12 +56,12 @@ enum LLRoleChangeType
// Powers
//
-// KNOWN HOLES:
-// bit 0x1 << 37 (GP_OBJECT_RETURN)
+// KNOWN HOLES: use these for any single bit powers you need
+// bit 0x1 << 41
+// bit 0x1 << 46
+// bit 0x1 << 49 and above
// These powers were removed to make group roles simpler
-// bit 0x1 << 27 (GP_LAND_ALLOW_SCRIPTS)
-// bit 0x1 << 16 (GP_LAND_VIEW_OWNED)
// bit 0x1 << 41 (GP_ACCOUNTING_VIEW)
// bit 0x1 << 46 (GP_PROPOSAL_VIEW)
@@ -116,18 +116,19 @@ const U64 GP_LAND_MANAGE_PASSES = 0x1LL << 31; // Change Sell Pass Settings
const U64 GP_LAND_ADMIN = 0x1LL << 32; // Eject and Freeze Users on the land
// Parcel Content
-const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48; // Return objects on parcel that are owned by the group
const U64 GP_LAND_RETURN_GROUP_SET = 0x1LL << 33; // Return objects on parcel that are set to group
const U64 GP_LAND_RETURN_NON_GROUP = 0x1LL << 34; // Return objects on parcel that are not set to group
+const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48; // Return objects on parcel that are owned by the group
+
// Select a power-bit based on an object's relationship to a parcel.
const U64 GP_LAND_RETURN = GP_LAND_RETURN_GROUP_OWNED
| GP_LAND_RETURN_GROUP_SET
| GP_LAND_RETURN_NON_GROUP;
+
const U64 GP_LAND_GARDENING = 0x1LL << 35; // Parcel Gardening - plant and move linden trees
// Object Management
const U64 GP_OBJECT_DEED = 0x1LL << 36; // Deed Object
-// HOLE -- 0x1LL << 37
const U64 GP_OBJECT_MANIPULATE = 0x1LL << 38; // Manipulate Group Owned Objects (Move, Copy, Mod)
const U64 GP_OBJECT_SET_SALE = 0x1LL << 39; // Set Group Owned Object for Sale
@@ -142,9 +143,10 @@ const U64 GP_NOTICES_RECEIVE = 0x1LL << 43; // Receive Notices and View Notice
const U64 GP_PROPOSAL_START = 0x1LL << 44; // Start Proposal
const U64 GP_PROPOSAL_VOTE = 0x1LL << 45; // Vote on Proposal
-const U64 GP_SESSION_JOIN = 0x1LL << 46; //can join session
-const U64 GP_SESSION_VOICE = 0x1LL << 47; //can hear/talk
-const U64 GP_SESSION_MODERATOR = 0x1LL << 49; //can mute people's session
+// Group chat moderation related
+const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
+const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
+const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE
| GP_LAND_ALLOW_SET_HOME
diff --git a/indra/llinventory/lluserrelations.cpp b/indra/llinventory/lluserrelations.cpp
index 0f1b48ecd1..e96cb1e1c1 100644
--- a/indra/llinventory/lluserrelations.cpp
+++ b/indra/llinventory/lluserrelations.cpp
@@ -41,6 +41,7 @@ const LLRelationship LLRelationship::DEFAULT_RELATIONSHIP = LLRelationship(GRANT
LLRelationship::LLRelationship() :
mGrantToAgent(0),
mGrantFromAgent(0),
+ mChangeSerialNum(0),
mIsOnline(false)
{
}
@@ -48,6 +49,7 @@ LLRelationship::LLRelationship() :
LLRelationship::LLRelationship(S32 grant_to, S32 grant_from, bool is_online) :
mGrantToAgent(grant_to),
mGrantFromAgent(grant_from),
+ mChangeSerialNum(0),
mIsOnline(is_online)
{
}
@@ -60,6 +62,7 @@ bool LLRelationship::isOnline() const
void LLRelationship::online(bool is_online)
{
mIsOnline = is_online;
+ mChangeSerialNum++;
}
bool LLRelationship::isRightGrantedTo(S32 rights) const
@@ -86,12 +89,14 @@ void LLRelationship::grantRights(S32 to_agent, S32 from_agent)
{
mGrantToAgent |= to_agent;
mGrantFromAgent |= from_agent;
+ mChangeSerialNum++;
}
void LLRelationship::revokeRights(S32 to_agent, S32 from_agent)
{
mGrantToAgent &= ~to_agent;
mGrantFromAgent &= ~from_agent;
+ mChangeSerialNum++;
}
diff --git a/indra/llinventory/lluserrelations.h b/indra/llinventory/lluserrelations.h
index 448301383e..36472215f6 100644
--- a/indra/llinventory/lluserrelations.h
+++ b/indra/llinventory/lluserrelations.h
@@ -142,8 +142,18 @@ public:
*/
S32 getRightsGrantedFrom() const;
- void setRightsTo(S32 to_agent) { mGrantToAgent = to_agent; }
- void setRightsFrom(S32 from_agent) { mGrantFromAgent = from_agent; }
+ void setRightsTo(S32 to_agent) { mGrantToAgent = to_agent; mChangeSerialNum++; }
+ void setRightsFrom(S32 from_agent) { mGrantFromAgent = from_agent; mChangeSerialNum++;}
+
+ /**
+ * @brief Get the change count for this agent
+ *
+ * Every change to rights will increment the serial number
+ * allowing listeners to determine when a relationship value is actually new
+ *
+ * @return change serial number for relationship
+ */
+ S32 getChangeSerialNum() const { return mChangeSerialNum; }
/**
* @brief Grant a set of rights.
@@ -171,6 +181,7 @@ public:
protected:
S32 mGrantToAgent;
S32 mGrantFromAgent;
+ S32 mChangeSerialNum;
bool mIsOnline;
};
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 00a1b03335..e7b15dcc58 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -215,7 +215,12 @@ public:
mLeft = llmin(mLeft, mRight);
mBottom = llmin(mBottom, mTop);
}
-
+
+ bool isNull() const
+ {
+ return mLeft == mRight || mBottom == mTop;
+ }
+
void unionWith(const LLRectBase &other)
{
mLeft = llmin(mLeft, other.mLeft);
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index b80fa069c7..d09af7a8c4 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -163,6 +163,7 @@ inline LLColor3::LLColor3(F32 r, F32 g, F32 b)
mV[VZ] = b;
}
+
inline LLColor3::LLColor3(const F32 *vec)
{
mV[VX] = vec[VX];
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 1e6232fc9d..0514870ef6 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -260,6 +260,7 @@ inline LLColor4::LLColor4(U32 clr)
mV[VW] = (clr>>24) * (1.0f/255.0f);
}
+
inline LLColor4::LLColor4(const F32 *vec)
{
mV[VX] = vec[VX];
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 473eaea76d..85a1e229ab 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -723,7 +723,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
const LLHTTPNode* node = mRootNode.traverse(mPath, context);
if(node)
{
- llinfos << "LLHTTPResponder::process_impl found node for "
+ lldebugs << "LLHTTPResponder::process_impl found node for "
<< mAbsPathAndQuery << llendl;
// Copy everything after mLast read to the out.
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index a1b63ead75..aca7a60bf1 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -705,21 +705,28 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
// But we don't want to acknowledge UseCircuitCode until the circuit is
// available, which is why the acknowledgement test is done above. JC
- valid_packet = mTemplateMessageReader->validateMessage(buffer,
- receive_size,
- host);
+ valid_packet = mTemplateMessageReader->validateMessage(
+ buffer,
+ receive_size,
+ host);
// UseCircuitCode is allowed in even from an invalid circuit, so that
// we can toss circuits around.
- if(valid_packet && !cdp &&
- (mTemplateMessageReader->getMessageName() != _PREHASH_UseCircuitCode))
+ if(
+ valid_packet &&
+ !cdp &&
+ (mTemplateMessageReader->getMessageName() !=
+ _PREHASH_UseCircuitCode))
{
logMsgFromInvalidCircuit( host, recv_reliable );
clearReceiveState();
valid_packet = FALSE;
}
- if(valid_packet && cdp && !cdp->getTrusted() &&
+ if(
+ valid_packet &&
+ cdp &&
+ !cdp->getTrusted() &&
mTemplateMessageReader->isTrusted())
{
logTrustedMsgFromUntrustedCircuit( host );
@@ -729,8 +736,9 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
valid_packet = FALSE;
}
- if (valid_packet
- && mTemplateMessageReader->isBanned(cdp && cdp->getTrusted()))
+ if (
+ valid_packet &&
+ mTemplateMessageReader->isBanned(cdp && cdp->getTrusted()))
{
llwarns << "LLMessageSystem::checkMessages "
<< "received banned message "
@@ -1159,9 +1167,10 @@ LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& n
{
if(mSendReliable)
{
- return new LLFnPtrResponder(mReliablePacketParams.mCallback,
- mReliablePacketParams.mCallbackData,
- name);
+ return new LLFnPtrResponder(
+ mReliablePacketParams.mCallback,
+ mReliablePacketParams.mCallbackData,
+ name);
}
else
{
@@ -1170,8 +1179,10 @@ LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& n
// llwarns << "LLMessageSystem::sendMessage: Sending unreliable "
// << mMessageBuilder->getMessageName() << " message via HTTP"
// << llendl;
- return new LLFnPtrResponder(NULL, NULL,
- mMessageBuilder->getMessageName());
+ return new LLFnPtrResponder(
+ NULL,
+ NULL,
+ mMessageBuilder->getMessageName());
}
}
@@ -1241,8 +1252,11 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
LLSD message = mLLSDMessageBuilder->getMessage();
const LLHTTPSender& sender = LLHTTPSender::getSender(host);
- sender.send(host, mLLSDMessageBuilder->getMessageName(),
- message, createResponder(mLLSDMessageBuilder->getMessageName()));
+ sender.send(
+ host,
+ mLLSDMessageBuilder->getMessageName(),
+ message,
+ createResponder(mLLSDMessageBuilder->getMessageName()));
mSendReliable = FALSE;
mReliablePacketParams.clear();
@@ -1423,8 +1437,10 @@ void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_re
}
}
-S32 LLMessageSystem::sendMessage(const LLHost &host, const char* name,
- const LLSD& message)
+S32 LLMessageSystem::sendMessage(
+ const LLHost &host,
+ const char* name,
+ const LLSD& message)
{
if (!(host.isOk()))
{
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 491fbb586a..cbfa3c2202 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -196,14 +196,4 @@ public:
#endif
};
-//RN: maybe this needs to moved elsewhere?
-class LLImageProviderInterface
-{
-public:
- LLImageProviderInterface() {};
- virtual ~LLImageProviderInterface() {};
-
- virtual LLImageGL* getUIImageByID(const LLUUID& id, BOOL clamped = TRUE) = 0;
-};
-
#endif // LL_LLIMAGEGL_H
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 26ce473e08..ce3a4b64c7 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -59,9 +59,6 @@ S32 BTN_HEIGHT = 0;
S32 BTN_GRID = 12;
S32 BORDER_SIZE = 1;
-// static
-LLFrameTimer LLButton::sFlashingTimer;
-
LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data)
: LLUICtrl(name, rect, TRUE, NULL, NULL),
mClickedCallback( click_callback ),
@@ -79,6 +76,7 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
mImageDisabled( NULL ),
mImageDisabledSelected( NULL ),
mToggleState( FALSE ),
+ mIsToggle( FALSE ),
mScaleImage( TRUE ),
mDropShadowedText( TRUE ),
mBorderEnabled( FALSE ),
@@ -86,8 +84,6 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
mHAlign( LLFontGL::HCENTER ),
mLeftHPad( LLBUTTON_H_PAD ),
mRightHPad( LLBUTTON_H_PAD ),
- mFixedWidth( 16 ),
- mFixedHeight( 16 ),
mHoverGlowStrength(0.15f),
mCurGlowStrength(0.f),
mNeedsHighlight(FALSE),
@@ -134,6 +130,7 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
mImageDisabled( NULL ),
mImageDisabledSelected( NULL ),
mToggleState( FALSE ),
+ mIsToggle( FALSE ),
mScaleImage( TRUE ),
mDropShadowedText( TRUE ),
mBorderEnabled( FALSE ),
@@ -141,8 +138,6 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
mHAlign( LLFontGL::HCENTER ),
mLeftHPad( LLBUTTON_H_PAD ),
mRightHPad( LLBUTTON_H_PAD ),
- mFixedWidth( 16 ),
- mFixedHeight( 16 ),
mHoverGlowStrength(0.25f),
mCurGlowStrength(0.f),
mNeedsHighlight(FALSE),
@@ -158,15 +153,11 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
if( unselected_image_name != "" )
{
+ // user-specified image - don't use fixed borders unless requested
setImageUnselected(unselected_image_name);
setImageDisabled(unselected_image_name);
mDisabledImageColor.mV[VALPHA] = 0.5f;
- mImageDisabled = mImageUnselected;
- mDisabledImageColor.mV[VALPHA] = 0.5f;
- // user-specified image - don't use fixed borders unless requested
- mFixedWidth = 0;
- mFixedHeight = 0;
mScaleImage = FALSE;
}
else
@@ -177,13 +168,11 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
if( selected_image_name != "" )
{
+ // user-specified image - don't use fixed borders unless requested
setImageSelected(selected_image_name);
setImageDisabledSelected(selected_image_name);
mDisabledImageColor.mV[VALPHA] = 0.5f;
- // user-specified image - don't use fixed borders unless requested
- mFixedWidth = 0;
- mFixedHeight = 0;
mScaleImage = FALSE;
}
else
@@ -273,6 +262,12 @@ void LLButton::onCommit()
make_ui_sound("UISndClickRelease");
}
+ if (mIsToggle)
+ {
+ toggleState();
+ }
+
+ // do this last, as it can result in destroying this button
if (mClickedCallback)
{
(*mClickedCallback)( mCallbackUserData );
@@ -286,6 +281,11 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
BOOL handled = FALSE;
if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char && !gKeyboard->getKeyRepeated(' '))
{
+ if (mIsToggle)
+ {
+ toggleState();
+ }
+
if (mClickedCallback)
{
(*mClickedCallback)( mCallbackUserData );
@@ -302,11 +302,17 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
{
if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
{
+ if (mIsToggle)
+ {
+ toggleState();
+ }
+
+ handled = TRUE;
+
if (mClickedCallback)
{
(*mClickedCallback)( mCallbackUserData );
}
- handled = TRUE;
}
}
return handled;
@@ -354,6 +360,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
(*mMouseUpCallback)(mCallbackUserData);
}
+ mMouseDownTimer.stop();
+ mMouseDownTimer.reset();
+
// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
// If mouseup in the widget, it's been clicked
if (pointInView(x, y))
@@ -363,6 +372,11 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
make_ui_sound("UISndClickRelease");
}
+ if (mIsToggle)
+ {
+ toggleState();
+ }
+
if (mClickedCallback)
{
(*mClickedCallback)( mCallbackUserData );
@@ -422,8 +436,10 @@ void LLButton::draw()
BOOL flash = FALSE;
if( mFlashing )
{
- F32 elapsed = LLButton::sFlashingTimer.getElapsedTimeF32();
- flash = S32(elapsed * 2) & 1;
+ F32 elapsed = mFlashingTimer.getElapsedTimeF32();
+ S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f);
+ // flash on or off?
+ flash = (flash_count % 2 == 0) || flash_count > (F32)LLUI::sConfigGroup->getS32("ButtonFlashCount");
}
BOOL pressed_by_keyboard = FALSE;
@@ -443,24 +459,14 @@ void LLButton::draw()
cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
- BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y));
-
- BOOL display_state = FALSE;
- if( pressed )
- {
- mImagep = mImageSelected;
- // show the resulting state after releasing the mouse button while it is down
- display_state = mToggleState ? FALSE : TRUE;
- }
- else
- {
- display_state = mToggleState || flash;
- }
+ BOOL pressed = pressed_by_keyboard
+ || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
+ || mToggleState;
BOOL use_glow_effect = FALSE;
- if ( mNeedsHighlight )
+ if ( mNeedsHighlight || flash )
{
- if (display_state)
+ if (pressed)
{
if (mImageHoverSelected)
{
@@ -485,7 +491,7 @@ void LLButton::draw()
}
}
}
- else if ( display_state )
+ else if ( pressed )
{
mImagep = mImageSelected;
}
@@ -499,11 +505,11 @@ void LLButton::draw()
// enabled and tentative
// or
// disabled but checked
- if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && display_state ) ) )
+ if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && pressed ) ) )
{
mImagep = mImageDisabledSelected;
}
- else if (!mImageDisabled.isNull() && !mEnabled && !display_state)
+ else if (!mImageDisabled.isNull() && !mEnabled && !pressed)
{
mImagep = mImageDisabled;
}
@@ -516,33 +522,34 @@ void LLButton::draw()
// Figure out appropriate color for the text
LLColor4 label_color;
+ // label changes when button state changes, not when pressed
if ( mEnabled )
{
- if ( !display_state )
+ if ( mToggleState )
{
- label_color = mUnselectedLabelColor;
+ label_color = mSelectedLabelColor;
}
else
{
- label_color = mSelectedLabelColor;
+ label_color = mUnselectedLabelColor;
}
}
else
{
- if ( !display_state )
+ if ( mToggleState )
{
- label_color = mDisabledLabelColor;
+ label_color = mDisabledSelectedLabelColor;
}
else
{
- label_color = mDisabledSelectedLabelColor;
+ label_color = mDisabledLabelColor;
}
}
// Unselected label assignments
LLWString label;
- if( display_state )
+ if( mToggleState )
{
if( mEnabled || mDisabledSelectedLabel.empty() )
{
@@ -591,24 +598,22 @@ void LLButton::draw()
// Otherwise draw basic rectangular button.
if( mImagep.notNull() && !mScaleImage)
{
- gl_draw_image( 0, 0, mImagep, mEnabled ? mImageColor : mDisabledImageColor );
+ mImagep->draw(0, 0, mEnabled ? mImageColor : mDisabledImageColor );
if (mCurGlowStrength > 0.01f)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- gl_draw_scaled_image_with_border(0, 0, 0, 0, mImagep->getWidth(), mImagep->getHeight(), mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
+ mImagep->drawSolid(0, 0, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
else
if ( mImagep.notNull() && mScaleImage)
{
- gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(),
- mImagep, mEnabled ? mImageColor : mDisabledImageColor );
+ mImagep->draw(0, 0, mRect.getWidth(), mRect.getHeight(), mEnabled ? mImageColor : mDisabledImageColor );
if (mCurGlowStrength > 0.01f)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(),
- mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
+ mImagep->drawSolid(0, 0, mRect.getWidth(), mRect.getHeight(), LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
@@ -620,13 +625,17 @@ void LLButton::draw()
gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE);
}
+ // let overlay image and text play well together
+ S32 text_left = mLeftHPad;
+ S32 text_right = mRect.getWidth() - mRightHPad;
+ S32 text_width = mRect.getWidth() - mLeftHPad - mRightHPad;
+
// draw overlay image
if (mImageOverlay.notNull())
{
- const S32 IMG_PAD = 5;
// get max width and height (discard level 0)
- S32 overlay_width = mImageOverlay->getWidth(0);
- S32 overlay_height = mImageOverlay->getHeight(0);
+ S32 overlay_width = mImageOverlay->getWidth();
+ S32 overlay_height = mImageOverlay->getHeight();
F32 scale_factor = llmin((F32)mRect.getWidth() / (F32)overlay_width, (F32)mRect.getHeight() / (F32)overlay_height, 1.f);
overlay_width = llround((F32)overlay_width * scale_factor);
@@ -635,34 +644,49 @@ void LLButton::draw()
S32 center_x = getLocalRect().getCenterX();
S32 center_y = getLocalRect().getCenterY();
+ //FUGLY HACK FOR "DEPRESSED" BUTTONS
+ if (pressed)
+ {
+ center_y--;
+ center_x++;
+ }
+
+ // fade out overlay images on disabled buttons
+ LLColor4 overlay_color = mImageOverlayColor;
+ if (!getEnabled())
+ {
+ overlay_color.mV[VALPHA] = 0.5f;
+ }
+
switch(mImageOverlayAlignment)
{
case LLFontGL::LEFT:
- gl_draw_scaled_image(
- IMG_PAD,
+ text_left += overlay_width + 1;
+ text_width -= overlay_width + 1;
+ mImageOverlay->draw(
+ mLeftHPad,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,
- mImageOverlay,
- mImageOverlayColor);
+ overlay_color);
break;
case LLFontGL::HCENTER:
- gl_draw_scaled_image(
+ mImageOverlay->draw(
center_x - (overlay_width / 2),
center_y - (overlay_height / 2),
overlay_width,
overlay_height,
- mImageOverlay,
- mImageOverlayColor);
+ overlay_color);
break;
case LLFontGL::RIGHT:
- gl_draw_scaled_image(
- mRect.getWidth() - IMG_PAD - overlay_width,
+ text_right -= overlay_width + 1;
+ text_width -= overlay_width + 1;
+ mImageOverlay->draw(
+ mRect.getWidth() - mRightHPad - overlay_width,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,
- mImageOverlay,
- mImageOverlayColor);
+ overlay_color);
break;
default:
// draw nothing
@@ -673,28 +697,26 @@ void LLButton::draw()
// Draw label
if( !label.empty() )
{
- S32 drawable_width = mRect.getWidth() - mLeftHPad - mRightHPad;
-
LLWString::trim(label);
S32 x;
switch( mHAlign )
{
case LLFontGL::RIGHT:
- x = mRect.getWidth() - mRightHPad;
+ x = text_right;
break;
case LLFontGL::HCENTER:
x = mRect.getWidth() / 2;
break;
case LLFontGL::LEFT:
default:
- x = mLeftHPad;
+ x = text_left;
break;
}
S32 y_offset = 2 + (mRect.getHeight() - 20)/2;
- if (pressed || display_state)
+ if (pressed)
{
y_offset--;
x++;
@@ -704,7 +726,7 @@ void LLButton::draw()
label_color,
mHAlign, LLFontGL::BOTTOM,
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
- U32_MAX, drawable_width,
+ U32_MAX, text_width,
NULL, FALSE, FALSE);
}
@@ -733,13 +755,11 @@ void LLButton::drawBorder(const LLColor4& color, S32 size)
if (mScaleImage)
{
- gl_draw_scaled_image_with_border(left, bottom, mFixedWidth, mFixedHeight, right-left, top-bottom,
- mImagep, color, TRUE );
+ mImagep->drawSolid(left, bottom, right-left, top-bottom, color);
}
else
{
- gl_draw_scaled_image_with_border(left, bottom, 0, 0, mImagep->getWidth() + size * 2,
- mImagep->getHeight() + size * 2, mImagep, color, TRUE );
+ mImagep->drawSolid(left, bottom, mImagep->getWidth() + size * 2, mImagep->getHeight() + size * 2, color);
}
}
@@ -763,6 +783,22 @@ void LLButton::setToggleState(BOOL b)
}
}
+void LLButton::setFlashing( BOOL b )
+{
+ if (b != mFlashing)
+ {
+ mFlashing = b;
+ mFlashingTimer.reset();
+ }
+}
+
+
+BOOL LLButton::toggleState()
+{
+ setToggleState( !mToggleState );
+ return mToggleState;
+}
+
void LLButton::setValue(const LLSD& value )
{
mToggleState = value.asBoolean();
@@ -770,7 +806,7 @@ void LLButton::setValue(const LLSD& value )
LLSD LLButton::getValue() const
{
- return mToggleState;
+ return mToggleState == TRUE;
}
void LLButton::setLabel( const LLStringExplicit& label )
@@ -807,10 +843,9 @@ void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label )
mDisabledSelectedLabel = label;
}
-void LLButton::setImageUnselectedID( const LLUUID &image_id )
-{
- mImageUnselectedName = "";
- mImageUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
+void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
+{
+ mImageUnselected = image;
}
void LLButton::setImages( const LLString &image_name, const LLString &selected_name )
@@ -820,10 +855,9 @@ void LLButton::setImages( const LLString &image_name, const LLString &selected_n
}
-void LLButton::setImageSelectedID( const LLUUID &image_id )
+void LLButton::setImageSelected(LLPointer<LLUIImage> image)
{
- mImageSelectedName = "";
- mImageSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+ mImageSelected = image;
}
void LLButton::setImageColor(const LLColor4& c)
@@ -831,19 +865,22 @@ void LLButton::setImageColor(const LLColor4& c)
mImageColor = c;
}
+void LLButton::setColor(const LLColor4& color)
+{
+ setImageColor(color);
+}
+
-void LLButton::setImageDisabledID( const LLUUID &image_id )
+void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
{
- mImageDisabledName = "";
- mImageDisabled = LLUI::sImageProvider->getUIImageByID(image_id);
+ mImageDisabled = image;
mDisabledImageColor = mImageColor;
mDisabledImageColor.mV[VALPHA] *= 0.5f;
}
-void LLButton::setImageDisabledSelectedID( const LLUUID &image_id )
-{
- mImageDisabledSelectedName = "";
- mImageDisabledSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+void LLButton::setImageDisabledSelected(LLPointer<LLUIImage> image)
+{
+ mImageDisabledSelected = image;
mDisabledImageColor = mImageColor;
mDisabledImageColor.mV[VALPHA] *= 0.5f;
}
@@ -855,11 +892,9 @@ void LLButton::setDisabledImages( const LLString &image_name, const LLString &se
mDisabledImageColor = c;
}
-
-void LLButton::setImageHoverSelectedID( const LLUUID& image_id )
+void LLButton::setImageHoverSelected(LLPointer<LLUIImage> image)
{
- mImageHoverSelectedName = "";
- mImageHoverSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+ mImageHoverSelected = image;
}
void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name)
@@ -869,10 +904,9 @@ void LLButton::setDisabledImages( const LLString &image_name, const LLString &se
setDisabledImages( image_name, selected_name, clr );
}
-void LLButton::setImageHoverUnselectedID( const LLUUID& image_id )
+void LLButton::setImageHoverUnselected(LLPointer<LLUIImage> image)
{
- mImageHoverUnselectedName = "";
- mImageHoverUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
+ mImageHoverUnselected = image;
}
void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name )
@@ -889,8 +923,7 @@ void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alig
}
else
{
- LLUUID overlay_image_id = LLUI::findAssetUUIDByName(image_name);
- mImageOverlay = LLUI::sImageProvider->getUIImageByID(overlay_image_id);
+ mImageOverlay = LLUI::getUIImageByName(image_name);
mImageOverlayAlignment = alignment;
mImageOverlayColor = color;
}
@@ -904,34 +937,6 @@ void LLButton::onMouseCaptureLost()
}
//-------------------------------------------------------------------------
-// LLSquareButton
-//-------------------------------------------------------------------------
-LLSquareButton::LLSquareButton(const LLString& name, const LLRect& rect,
- const LLString& label,
- const LLFontGL *font,
- const LLString& control_name,
- void (*click_callback)(void*),
- void *callback_data,
- const LLString& selected_label )
-: LLButton(name, rect, "","",
- control_name,
- click_callback, callback_data,
- font,
- label,
- (selected_label.empty() ? label : selected_label) )
-{
- setImageUnselected("square_btn_32x128.tga");
- // mImageUnselected = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
- setImageSelected("square_btn_selected_32x128.tga");
- // mImageSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
- setImageDisabled("square_btn_32x128.tga");
- //mDisabledImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
- setImageDisabledSelected("square_btn_selected_32x128.tga");
- //mDisabledSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
- mImageColor = LLUI::sColorsGroup->getColor("ButtonColor");
-}
-
-//-------------------------------------------------------------------------
// Utilities
//-------------------------------------------------------------------------
S32 round_up(S32 grid, S32 value)
@@ -951,37 +956,37 @@ S32 round_up(S32 grid, S32 value)
void LLButton::setImageUnselected(const LLString &image_name)
{
- setImageUnselectedID(LLUI::findAssetUUIDByName(image_name));
+ setImageUnselected(LLUI::getUIImageByName(image_name));
mImageUnselectedName = image_name;
}
void LLButton::setImageSelected(const LLString &image_name)
{
- setImageSelectedID(LLUI::findAssetUUIDByName(image_name));
+ setImageSelected(LLUI::getUIImageByName(image_name));
mImageSelectedName = image_name;
}
void LLButton::setImageHoverSelected(const LLString &image_name)
{
- setImageHoverSelectedID(LLUI::findAssetUUIDByName(image_name));
+ setImageHoverSelected(LLUI::getUIImageByName(image_name));
mImageHoverSelectedName = image_name;
}
void LLButton::setImageHoverUnselected(const LLString &image_name)
{
- setImageHoverUnselectedID(LLUI::findAssetUUIDByName(image_name));
+ setImageHoverUnselected(LLUI::getUIImageByName(image_name));
mImageHoverUnselectedName = image_name;
}
void LLButton::setImageDisabled(const LLString &image_name)
{
- setImageDisabledID(LLUI::findAssetUUIDByName(image_name));
+ setImageDisabled(LLUI::getUIImageByName(image_name));
mImageDisabledName = image_name;
}
void LLButton::setImageDisabledSelected(const LLString &image_name)
{
- setImageDisabledSelectedID(LLUI::findAssetUUIDByName(image_name));
+ setImageDisabledSelected(LLUI::getUIImageByName(image_name));
mImageDisabledSelectedName = image_name;
}
@@ -1009,8 +1014,6 @@ LLXMLNodePtr LLButton::getXML(bool save_children) const
node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected());
node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
- node->createChild("border_width", TRUE)->setIntValue(mFixedWidth);
- node->createChild("border_height", TRUE)->setIntValue(mFixedHeight);
addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected");
addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected");
@@ -1092,8 +1095,12 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
label,
label_selected);
- node->getAttributeS32("border_width", button->mFixedWidth);
- node->getAttributeS32("border_height", button->mFixedHeight);
+ node->getAttributeS32("pad_right", button->mRightHPad);
+ node->getAttributeS32("pad_left", button->mLeftHPad);
+
+ BOOL is_toggle = button->getIsToggle();
+ node->getAttributeBOOL("toggle", is_toggle);
+ button->setIsToggle(is_toggle);
if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected);
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 5f7d917b4e..0e140a45a6 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -114,11 +114,13 @@ public:
F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); }
- BOOL toggleState() { setToggleState( !mToggleState ); return mToggleState; }
+ BOOL getIsToggle() const { return mIsToggle; }
+ void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; }
+ BOOL toggleState();
BOOL getToggleState() const { return mToggleState; }
void setToggleState(BOOL b);
- void setFlashing( BOOL b ) { mFlashing = b; }
+ void setFlashing( BOOL b );
BOOL getFlashing() const { return mFlashing; }
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
@@ -128,14 +130,11 @@ public:
const LLString getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); }
const LLString getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); }
-
- // HACK to allow images to be freed when the caller knows he's done with it.
- LLImageGL* getImageUnselected() const { return mImageUnselected; }
-
void setImageColor(const LLString& color_control);
- void setImages(const LLString &image_name, const LLString &selected_name);
void setImageColor(const LLColor4& c);
-
+ virtual void setColor(const LLColor4& c);
+
+ void setImages(const LLString &image_name, const LLString &selected_name);
void setDisabledImages(const LLString &image_name, const LLString &selected_name);
void setDisabledImages(const LLString &image_name, const LLString &selected_name, const LLColor4& c);
@@ -146,7 +145,7 @@ public:
void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
- LLPointer<LLImageGL> getImageOverlay() { return mImageOverlay; }
+ LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
virtual void setValue(const LLSD& value );
@@ -170,16 +169,8 @@ public:
static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
- void setFixedBorder(S32 width, S32 height) { mFixedWidth = width; mFixedHeight = height; }
void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; }
-private:
- void setImageUnselectedID(const LLUUID &image_id);
- void setImageSelectedID(const LLUUID &image_id);
- void setImageHoverSelectedID(const LLUUID &image_id);
- void setImageHoverUnselectedID(const LLUUID &image_id);
- void setImageDisabledID(const LLUUID &image_id);
- void setImageDisabledSelectedID(const LLUUID &image_id);
public:
void setImageUnselected(const LLString &image_name);
void setImageSelected(const LLString &image_name);
@@ -187,6 +178,14 @@ public:
void setImageHoverUnselected(const LLString &image_name);
void setImageDisabled(const LLString &image_name);
void setImageDisabledSelected(const LLString &image_name);
+
+ void setImageUnselected(LLPointer<LLUIImage> image);
+ void setImageSelected(LLPointer<LLUIImage> image);
+ void setImageHoverSelected(LLPointer<LLUIImage> image);
+ void setImageHoverUnselected(LLPointer<LLUIImage> image);
+ void setImageDisabled(LLPointer<LLUIImage> image);
+ void setImageDisabledSelected(LLPointer<LLUIImage> image);
+
void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
BOOL getCommitOnReturn() { return mCommitOnReturn; }
@@ -209,27 +208,27 @@ protected:
F32 mHeldDownDelay; // seconds, after which held-down callbacks get called
S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called
- LLPointer<LLImageGL> mImageOverlay;
+ LLPointer<LLUIImage> mImageOverlay;
LLFontGL::HAlign mImageOverlayAlignment;
LLColor4 mImageOverlayColor;
- LLPointer<LLImageGL> mImageUnselected;
+ LLPointer<LLUIImage> mImageUnselected;
LLUIString mUnselectedLabel;
LLColor4 mUnselectedLabelColor;
- LLPointer<LLImageGL> mImageSelected;
+ LLPointer<LLUIImage> mImageSelected;
LLUIString mSelectedLabel;
LLColor4 mSelectedLabelColor;
- LLPointer<LLImageGL> mImageHoverSelected;
+ LLPointer<LLUIImage> mImageHoverSelected;
- LLPointer<LLImageGL> mImageHoverUnselected;
+ LLPointer<LLUIImage> mImageHoverUnselected;
- LLPointer<LLImageGL> mImageDisabled;
+ LLPointer<LLUIImage> mImageDisabled;
LLUIString mDisabledLabel;
LLColor4 mDisabledLabelColor;
- LLPointer<LLImageGL> mImageDisabledSelected;
+ LLPointer<LLUIImage> mImageDisabledSelected;
LLUIString mDisabledSelectedLabel;
LLColor4 mDisabledSelectedLabelColor;
@@ -254,6 +253,7 @@ protected:
LLColor4 mImageColor;
LLColor4 mDisabledImageColor;
+ BOOL mIsToggle;
BOOL mToggleState;
BOOL mScaleImage;
@@ -267,9 +267,6 @@ protected:
S32 mLeftHPad;
S32 mRightHPad;
- S32 mFixedWidth;
- S32 mFixedHeight;
-
F32 mHoverGlowStrength;
F32 mCurGlowStrength;
@@ -278,22 +275,9 @@ protected:
LLString mHelpURL;
- LLPointer<LLImageGL> mImagep;
-
- static LLFrameTimer sFlashingTimer;
-};
+ LLPointer<LLUIImage> mImagep;
-class LLSquareButton
-: public LLButton
-{
-public:
- LLSquareButton(const LLString& name, const LLRect& rect,
- const LLString& label,
- const LLFontGL *font = NULL,
- const LLString& control_name = LLString(),
- void (*click_callback)(void*) = NULL,
- void *callback_data = NULL,
- const LLString& selected_label = LLString::null );
+ LLFrameTimer mFlashingTimer;
};
// Helpful functions
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index 504b342003..b0a7e9d27f 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -75,7 +75,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLString& name, const LLRect& rect,
}
// must be big enough to hold all children
- setSpanChildren(TRUE);
+ setUseBoundingRect(TRUE);
mKeyboardFocusOnClick = TRUE;
@@ -130,6 +130,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLString& name, const LLRect& rect,
mButton->setDisabledImages( inactive_false_id, inactive_true_id );
mButton->setHoverGlowStrength(0.35f);
}
+ mButton->setIsToggle(TRUE);
mButton->setToggleState( initial_value );
mButton->setFollowsLeft();
mButton->setFollowsBottom();
@@ -150,16 +151,11 @@ void LLCheckBoxCtrl::onButtonPress( void *userdata )
if (self->mRadioStyle)
{
- if (!self->getValue())
- {
- self->setValue(TRUE);
- }
- }
- else
- {
- self->toggle();
+ self->setValue(TRUE);
}
+
self->setControlValue(self->getValue());
+ // HACK: because buttons don't normally commit
self->onCommit();
if (self->mKeyboardFocusOnClick)
@@ -232,14 +228,13 @@ void LLCheckBoxCtrl::draw()
//virtual
void LLCheckBoxCtrl::setValue(const LLSD& value )
{
- mSetValue = value.asBoolean();
- mButton->setToggleState( mSetValue );
+ mButton->setValue( value );
}
//virtual
LLSD LLCheckBoxCtrl::getValue() const
{
- return mButton->getToggleState();
+ return mButton->getValue();
}
void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label )
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 5f76cfc94b..6063fc155a 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -55,17 +55,16 @@
// Globals
S32 LLCOMBOBOX_HEIGHT = 0;
S32 LLCOMBOBOX_WIDTH = 0;
-
+S32 MAX_COMBO_WIDTH = 500;
+
LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString& label,
void (*commit_callback)(LLUICtrl*,void*),
void *callback_userdata
)
: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata,
FOLLOWS_LEFT | FOLLOWS_TOP),
- mDrawArrow(TRUE),
mTextEntry(NULL),
mArrowImage(NULL),
- mArrowImageWidth(8),
mAllowTextEntry(FALSE),
mMaxChars(20),
mTextEntryTentative(TRUE),
@@ -73,55 +72,43 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
mPrearrangeCallback( NULL ),
mTextEntryCallback( NULL )
{
- // For now, all comboboxes don't take keyboard focus when clicked.
- // This might change if it is part of a modal dialog.
- // mKeyboardFocusOnClick = FALSE;
-
- // Revert to standard behavior. When this control's parent is hidden, it needs to
- // hide this ctrl--which won't just happen automatically since when LLComboBox is
- // showing its list, it's also set to TopCtrl. When keyboard focus is cleared all
- // controls (including this one) know that they are no longer editing.
- mKeyboardFocusOnClick = TRUE;
-
- LLRect r;
- r.setOriginAndSize(0, 0, rect.getWidth(), rect.getHeight());
-
// Always use text box
// Text label button
- mButton = new LLSquareButton("comboxbox button",
- r, label, NULL, LLString::null,
+ mButton = new LLButton("comboxbox button",
+ LLRect(), label, NULL, LLString::null,
NULL, this);
+ mButton->setImageUnselected("square_btn_32x128.tga");
+ mButton->setImageSelected("square_btn_selected_32x128.tga");
+ mButton->setImageDisabled("square_btn_32x128.tga");
+ mButton->setImageDisabledSelected("square_btn_selected_32x128.tga");
+ mButton->setScaleImage(TRUE);
+
mButton->setMouseDownCallback(onButtonDown);
mButton->setFont(LLFontGL::sSansSerifSmall);
mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
mButton->setHAlign( LLFontGL::LEFT );
-
- const S32 ARROW_WIDTH = 16;
- mButton->setRightHPad( ARROW_WIDTH );
+ mButton->setRightHPad(2);
addChild(mButton);
- // Default size, will be set by arrange() call in button callback.
- S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE;
- r.setOriginAndSize(0, 16, list_width, 220);
-
// disallow multiple selection
mList = new LLScrollListCtrl(
- "ComboBox", r,
+ "ComboBox", LLRect(),
&LLComboBox::onItemSelected, this, FALSE);
mList->setVisible(FALSE);
mList->setBgWriteableColor( LLColor4(1,1,1,1) );
mList->setCommitOnKeyboardMovement(FALSE);
- mList->setFocusChangedCallback(onListFocusChanged);
addChild(mList);
LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
mBorder = new LLViewBorder( "combo border", border_rect );
addChild( mBorder );
- mBorder->setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
+ mBorder->setFollowsAll();
LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
- mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id);
- mArrowImageWidth = llmax(8,mArrowImage->getWidth(0)); // In case image hasn't loaded yet
+ mArrowImage = LLUI::sImageProvider->getImageByID(arrow_image_id);
+ mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT);
+
+ updateLayout();
}
@@ -155,7 +142,7 @@ LLXMLNodePtr LLComboBox::getXML(bool save_children) const
LLSD value = item->getValue();
item_node->createChild("value", TRUE)->setStringValue(value.asString());
item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled());
- item_node->setStringValue(cell->getText());
+ item_node->setStringValue(cell->getValue().asString());
}
}
@@ -272,34 +259,42 @@ void LLComboBox::resetDirty()
// add item "name" to menu
-void LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled)
+LLScrollListItem* LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled)
{
- mList->addSimpleItem(name, pos, enabled);
+ LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled);
mList->selectFirstItem();
+ return item;
}
// add item "name" with a unique id to menu
-void LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled )
+LLScrollListItem* LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled )
{
- mList->addSimpleItem(name, LLSD(id), pos, enabled);
+ LLScrollListItem* item = mList->addSimpleItem(name, LLSD(id), pos, enabled);
mList->selectFirstItem();
+ return item;
}
// add item "name" with attached userdata
-void LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled )
+LLScrollListItem* LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled )
{
LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled);
item->setUserdata( userdata );
mList->selectFirstItem();
+ return item;
}
// add item "name" with attached generic data
-void LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled )
+LLScrollListItem* LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled )
{
- mList->addSimpleItem(name, value, pos, enabled);
+ LLScrollListItem* item = mList->addSimpleItem(name, value, pos, enabled);
mList->selectFirstItem();
+ return item;
}
+LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos)
+{
+ return mList->addSeparator(pos);
+}
void LLComboBox::sortByName()
{
@@ -335,9 +330,9 @@ void LLComboBox::setValue(const LLSD& value)
}
}
-const LLString& LLComboBox::getSimple() const
+const LLString LLComboBox::getSimple() const
{
- const LLString& res = mList->getSimpleSelectedItem();
+ const LLString res = mList->getSimpleSelectedItem();
if (res.empty() && mAllowTextEntry)
{
return mTextEntry->getText();
@@ -348,7 +343,7 @@ const LLString& LLComboBox::getSimple() const
}
}
-const LLString& LLComboBox::getSimpleSelectedItem(S32 column) const
+const LLString LLComboBox::getSimpleSelectedItem(S32 column) const
{
return mList->getSimpleSelectedItem(column);
}
@@ -373,7 +368,7 @@ LLSD LLComboBox::getValue() const
void LLComboBox::setLabel(const LLStringExplicit& name)
{
- if ( mAllowTextEntry )
+ if ( mTextEntry )
{
mTextEntry->setText(name);
if (mList->selectSimpleItem(name, FALSE))
@@ -385,7 +380,8 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
mTextEntry->setTentative(mTextEntryTentative);
}
}
- else
+
+ if (!mAllowTextEntry)
{
mButton->setLabelUnselected(name);
mButton->setLabelSelected(name);
@@ -433,16 +429,21 @@ void LLComboBox::onFocusLost()
LLUICtrl::onFocusLost();
}
+void LLComboBox::onLostTop()
+{
+ hideList();
+}
+
+
void LLComboBox::setButtonVisible(BOOL visible)
{
mButton->setVisible(visible);
- mDrawArrow = visible;
if (mTextEntry)
{
LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
if (visible)
{
- text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
+ text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth(0)) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
}
//mTextEntry->setRect(text_entry_rect);
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
@@ -457,22 +458,8 @@ void LLComboBox::draw()
mButton->setEnabled(mEnabled /*&& !mList->isEmpty()*/);
- // Draw children
+ // Draw children normally
LLUICtrl::draw();
-
- if (mDrawArrow)
- {
- // Paste the graphic on the right edge
- if (!mArrowImage.isNull())
- {
- S32 arrow_height = llmin(mRect.getHeight(), mArrowImage->getHeight());
- S32 arrow_width = llround((F32)mArrowImage->getWidth() * ((F32)arrow_height / (F32)mArrowImage->getHeight()));
-
- S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton");
-
- gl_draw_scaled_image( left, 0, arrow_width, arrow_height, mArrowImage, LLColor4::white);
- }
- }
}
}
@@ -497,6 +484,67 @@ S32 LLComboBox::getCurrentIndex() const
}
+void LLComboBox::updateLayout()
+{
+ LLRect rect = getLocalRect();
+ if (mAllowTextEntry)
+ {
+ S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
+ mButton->setRect(LLRect( mRect.getWidth() - llmax(8,mArrowImage->getWidth(0)) - 2 * shadow_size,
+ rect.mTop, rect.mRight, rect.mBottom));
+ mButton->setTabStop(FALSE);
+
+ if (!mTextEntry)
+ {
+ LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
+ text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth(0)) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
+ // clear label on button
+ LLString cur_label = mButton->getLabelSelected();
+ mTextEntry = new LLLineEditor("combo_text_entry",
+ text_entry_rect,
+ "",
+ LLFontGL::sSansSerifSmall,
+ mMaxChars,
+ onTextCommit,
+ onTextEntry,
+ NULL,
+ this,
+ NULL, // prevalidate func
+ LLViewBorder::BEVEL_NONE,
+ LLViewBorder::STYLE_LINE,
+ 0); // no border
+ mTextEntry->setSelectAllonFocusReceived(TRUE);
+ mTextEntry->setHandleEditKeysDirectly(TRUE);
+ mTextEntry->setCommitOnFocusLost(FALSE);
+ mTextEntry->setText(cur_label);
+ mTextEntry->setIgnoreTab(TRUE);
+ mTextEntry->setFollowsAll();
+ addChild(mTextEntry);
+ }
+ else
+ {
+ mTextEntry->setVisible(TRUE);
+ mTextEntry->setMaxTextLength(mMaxChars);
+ }
+
+ // clear label on button
+ setLabel(LLString::null);
+
+ mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
+ }
+ else if (!mAllowTextEntry)
+ {
+ mButton->setRect(rect);
+ mButton->setTabStop(TRUE);
+
+ if (mTextEntry)
+ {
+ mTextEntry->setVisible(FALSE);
+ }
+ mButton->setFollowsAll();
+ }
+}
+
void* LLComboBox::getCurrentUserdata()
{
LLScrollListItem* item = mList->getFirstSelected();
@@ -514,7 +562,7 @@ void LLComboBox::showList()
LLCoordWindow window_size;
getWindow()->getSize(&window_size);
//HACK: shouldn't have to know about scale here
- mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
+ mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
// Make sure that we can see the whole list
LLRect root_view_local;
@@ -523,7 +571,9 @@ void LLComboBox::showList()
LLRect rect = mList->getRect();
- S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE;
+ S32 min_width = mRect.getWidth();
+ S32 max_width = llmax(min_width, MAX_COMBO_WIDTH);
+ S32 list_width = llclamp(mList->getMaxContentWidth(), min_width, max_width);
if (mListPosition == BELOW)
{
@@ -583,12 +633,6 @@ void LLComboBox::showList()
mList->translate(0, -y);
}
- // pass mouse capture on to list if button is depressed
- if (mButton->hasMouseCapture())
- {
- gFocusMgr.setMouseCapture(mList);
- }
-
// NB: this call will trigger the focuslost callback which will hide the list, so do it first
// before finally showing the list
@@ -604,24 +648,29 @@ void LLComboBox::showList()
mButton->setToggleState(TRUE);
mList->setVisible(TRUE);
- gFocusMgr.setTopCtrl(mList);
+ setUseBoundingRect(TRUE);
+ gFocusMgr.setTopCtrl(this);
}
void LLComboBox::hideList()
{
+ //*HACK: store the original value explicitly somewhere, not just in label
+ LLString orig_selection = mAllowTextEntry ? mTextEntry->getText() : mButton->getLabelSelected();
+
+ // assert selection in list
+ mList->selectSimpleItem(orig_selection, FALSE);
+
mButton->setToggleState(FALSE);
mList->setVisible(FALSE);
mList->highlightNthItem(-1);
- if( gFocusMgr.getTopCtrl() == mList )
+ setUseBoundingRect(FALSE);
+ if( gFocusMgr.getTopCtrl() == this )
{
gFocusMgr.setTopCtrl(NULL);
}
-
- //mList->setFocus(FALSE);
}
-
//------------------------------------------------------------------
// static functions
//------------------------------------------------------------------
@@ -650,21 +699,20 @@ void LLComboBox::onButtonDown(void *userdata)
self->showList();
}
- if (self->mKeyboardFocusOnClick && !self->hasFocus())
+ self->setFocus( TRUE );
+
+ // pass mouse capture on to list if button is depressed
+ if (self->mButton->hasMouseCapture())
{
- self->setFocus( TRUE );
+ gFocusMgr.setMouseCapture(self->mList);
}
}
else
{
- // hide and release keyboard focus
self->hideList();
-
- self->onCommit();
}
-}
-
+}
// static
void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
@@ -672,7 +720,7 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
// Note: item is the LLScrollListCtrl
LLComboBox *self = (LLComboBox *) userdata;
- const LLString& name = self->mList->getSimpleSelectedItem();
+ const LLString name = self->mList->getSimpleSelectedItem();
S32 cur_id = self->getCurrentIndex();
if (cur_id != -1)
@@ -681,40 +729,24 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
if (self->mAllowTextEntry)
{
- gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL);
+ gFocusMgr.setKeyboardFocus(self->mTextEntry);
self->mTextEntry->selectAll();
}
}
else
{
// invalid selection, just restore existing value
- self->mList->selectSimpleItem(self->mButton->getLabelSelected());
+ LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
+
+ self->mList->selectSimpleItem(orig_selection);
}
self->onCommit();
self->hideList();
}
-// static
-void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data)
-{
- LLComboBox *self = (LLComboBox *) list->getParent();
- // user not manipulating list or clicking on drop down button
- if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture())
- {
- //*HACK: store the original value explicitly somewhere, not just in label
- LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
-
- self->hideList();
-
- // reassert original selection
- self->mList->selectSimpleItem(orig_selection, FALSE);
- }
-}
-
BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
{
-
LLString tool_tip;
if (LLUI::sShowXUINames)
@@ -726,23 +758,19 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_
tool_tip = mToolTipMsg;
}
- if( getVisible() && pointInView( x, y ) )
+ if( !tool_tip.empty() )
{
- if( !tool_tip.empty() )
- {
- msg = tool_tip;
-
- // Convert rect local to screen coordinates
- localPointToScreen(
- 0, 0,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- mRect.getWidth(), mRect.getHeight(),
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
- }
- return TRUE;
+ msg = tool_tip;
+
+ // Convert rect local to screen coordinates
+ localPointToScreen(
+ 0, 0,
+ &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
+ localPointToScreen(
+ mRect.getWidth(), mRect.getHeight(),
+ &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
}
- return FALSE;
+ return TRUE;
}
BOOL LLComboBox::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
@@ -793,63 +821,11 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent
void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
{
- LLRect rect( 0, mRect.getHeight(), mRect.getWidth(), 0);
- if (allow && !mAllowTextEntry)
- {
- S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
- mButton->setRect(LLRect( mRect.getWidth() - mArrowImageWidth - 2 * shadow_size,
- rect.mTop, rect.mRight, rect.mBottom));
- mButton->setTabStop(FALSE);
-
- // clear label on button
- LLString cur_label = mButton->getLabelSelected();
- setLabel(LLString::null);
- if (!mTextEntry)
- {
- LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
- text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
- mTextEntry = new LLLineEditor("combo_text_entry",
- text_entry_rect,
- "",
- LLFontGL::sSansSerifSmall,
- max_chars,
- onTextCommit,
- onTextEntry,
- NULL,
- this,
- NULL, // prevalidate func
- LLViewBorder::BEVEL_NONE,
- LLViewBorder::STYLE_LINE,
- 0); // no border
- mTextEntry->setSelectAllonFocusReceived(TRUE);
- mTextEntry->setHandleEditKeysDirectly(TRUE);
- mTextEntry->setCommitOnFocusLost(FALSE);
- mTextEntry->setText(cur_label);
- mTextEntry->setIgnoreTab(TRUE);
- mTextEntry->setFollowsAll();
- addChild(mTextEntry);
- mMaxChars = max_chars;
- }
- else
- {
- mTextEntry->setVisible(TRUE);
- }
-
- mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
- }
- else if (!allow && mAllowTextEntry)
- {
- mButton->setRect(rect);
- mButton->setTabStop(TRUE);
-
- if (mTextEntry)
- {
- mTextEntry->setVisible(FALSE);
- }
- mButton->setFollowsAll();
- }
mAllowTextEntry = allow;
- mTextEntryTentative = set_tentative;
+ mTextEntryTentative = set_tentative;
+ mMaxChars = max_chars;
+
+ updateLayout();
}
void LLComboBox::setTextEntry(const LLStringExplicit& text)
@@ -993,6 +969,10 @@ void LLComboBox::setFocus(BOOL b)
if (b)
{
mList->clearSearchString();
+ if (mList->getVisible())
+ {
+ mList->setFocus(TRUE);
+ }
}
}
@@ -1097,3 +1077,155 @@ BOOL LLComboBox::operateOnAll(EOperation op)
}
return FALSE;
}
+
+
+
+//
+// LLFlyoutButton
+//
+
+const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24;
+
+LLFlyoutButton::LLFlyoutButton(
+ const LLString& name,
+ const LLRect &rect,
+ const LLString& label,
+ void (*commit_callback)(LLUICtrl*, void*) ,
+ void *callback_userdata)
+: LLComboBox(name, rect, LLString::null, commit_callback, callback_userdata),
+ mToggleState(FALSE),
+ mActionButton(NULL)
+{
+ // Always use text box
+ // Text label button
+ mActionButton = new LLButton("flyout_button_main",
+ LLRect(), label, NULL, LLString::null,
+ NULL, this);
+ mActionButton->setScaleImage(TRUE);
+
+ mActionButton->setClickedCallback(onActionButtonClick);
+ mActionButton->setFollowsAll();
+ mActionButton->setHAlign( LLFontGL::HCENTER );
+ mActionButton->setLabel(label);
+ addChild(mActionButton);
+
+ mActionButtonImage = LLUI::getUIImageByName("flyout_btn_left.tga");
+ mExpanderButtonImage = LLUI::getUIImageByName("flyout_btn_right.tga");
+ mActionButtonImageSelected = LLUI::getUIImageByName("flyout_btn_left_selected.tga");
+ mExpanderButtonImageSelected = LLUI::getUIImageByName("flyout_btn_right_selected.tga");
+
+ mActionButton->setImageSelected(mActionButtonImageSelected);
+ mActionButton->setImageUnselected(mActionButtonImage);
+ mActionButton->setImageDisabled(LLPointer<LLUIImage>(NULL));
+ mActionButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
+
+ mButton->setImageSelected(mExpanderButtonImageSelected);
+ mButton->setImageUnselected(mExpanderButtonImage);
+ mButton->setImageDisabled(LLPointer<LLUIImage>(NULL));
+ mButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
+ mButton->setRightHPad(6);
+
+ mBorder->setVisible(FALSE);
+
+ updateLayout();
+}
+
+//static
+LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+{
+ LLString name = "flyout_button";
+ node->getAttributeString("name", name);
+
+ LLString label("");
+ node->getAttributeString("label", label);
+
+ LLRect rect;
+ createRect(node, rect, parent, LLRect());
+
+ LLUICtrlCallback callback = NULL;
+
+ LLFlyoutButton* flyout_button = new LLFlyoutButton(name,
+ rect,
+ label,
+ callback,
+ NULL);
+
+ LLString list_position;
+ node->getAttributeString("list_position", list_position);
+ if (list_position == "below")
+ {
+ flyout_button->mListPosition = BELOW;
+ }
+ else if (list_position == "above")
+ {
+ flyout_button->mListPosition = ABOVE;
+ }
+
+
+ flyout_button->initFromXML(node, parent);
+
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ if (child->hasName("flyout_button_item"))
+ {
+ LLString label = child->getTextContents();
+
+ LLString value = label;
+ child->getAttributeString("value", value);
+
+ flyout_button->add(label, LLSD(value) );
+ }
+ }
+
+ flyout_button->updateLayout();
+
+ return flyout_button;
+}
+
+void LLFlyoutButton::updateLayout()
+{
+ LLComboBox::updateLayout();
+
+ mButton->setOrigin(mRect.getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0);
+ mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, mRect.getHeight());
+ mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+ mButton->setTabStop(FALSE);
+ mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT);
+
+ mActionButton->setOrigin(0, 0);
+ mActionButton->reshape(mRect.getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, mRect.getHeight());
+}
+
+//static
+void LLFlyoutButton::onActionButtonClick(void *user_data)
+{
+ LLFlyoutButton* buttonp = (LLFlyoutButton*)user_data;
+ // remember last list selection?
+ buttonp->mList->deselect();
+ buttonp->onCommit();
+}
+
+void LLFlyoutButton::draw()
+{
+ mActionButton->setToggleState(mToggleState);
+ mButton->setToggleState(mToggleState);
+
+ //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or
+ // the label reflects the last selected item, for now we have to manually remove the label
+ mButton->setLabel(LLString::null);
+ LLComboBox::draw();
+}
+
+void LLFlyoutButton::setEnabled(BOOL enabled)
+{
+ mActionButton->setEnabled(enabled);
+ LLComboBox::setEnabled(enabled);
+}
+
+
+void LLFlyoutButton::setToggleState(BOOL state)
+{
+ mToggleState = state;
+}
+
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index ff17d2874f..6e77007aef 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -80,6 +80,7 @@ public:
virtual void draw();
virtual void onFocusLost();
+ virtual void onLostTop();
virtual void setEnabled(BOOL enabled);
@@ -107,10 +108,11 @@ public:
void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE);
void setTextEntry(const LLStringExplicit& text);
- void add(const LLString& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu
- void add(const LLString& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
- void add(const LLString& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
- void add(const LLString& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
+ LLScrollListItem* add(const LLString& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu
+ LLScrollListItem* add(const LLString& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
+ LLScrollListItem* add(const LLString& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
+ LLScrollListItem* add(const LLString& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
+ LLScrollListItem* addSeparator(EAddPosition pos = ADD_BOTTOM);
BOOL remove( S32 index ); // remove item by index, return TRUE if found and removed
void removeall() { clearRows(); }
@@ -119,9 +121,9 @@ public:
// Select current item by name using selectSimpleItem. Returns FALSE if not found.
BOOL setSimple(const LLStringExplicit& name);
// Get name of current item. Returns an empty string if not found.
- const LLString& getSimple() const;
+ const LLString getSimple() const;
// Get contents of column x of selected row
- const LLString& getSimpleSelectedItem(S32 column = 0) const;
+ const LLString getSimpleSelectedItem(S32 column = 0) const;
// Sets the label, which doesn't have to exist in the label.
// This is probably a UI abuse.
@@ -132,6 +134,8 @@ public:
BOOL setCurrentByIndex( S32 index );
S32 getCurrentIndex() const;
+ virtual void updateLayout();
+
//========================================================================
LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)this; };
@@ -172,7 +176,6 @@ public:
static void onButtonDown(void *userdata);
static void onItemSelected(LLUICtrl* item, void *userdata);
- static void onListFocusChanged(LLUICtrl* item, void *userdata);
static void onTextEntry(LLLineEditor* line_editor, void* user_data);
static void onTextCommit(LLUICtrl* caller, void* user_data);
@@ -183,12 +186,10 @@ public:
protected:
LLButton* mButton;
LLScrollListCtrl* mList;
+ S32 mButtonPadding;
LLViewBorder* mBorder;
- BOOL mKeyboardFocusOnClick;
- BOOL mDrawArrow;
LLLineEditor* mTextEntry;
LLPointer<LLImageGL> mArrowImage;
- S32 mArrowImageWidth;
BOOL mAllowTextEntry;
S32 mMaxChars;
BOOL mTextEntryTentative;
@@ -197,4 +198,36 @@ protected:
void (*mTextEntryCallback)(LLLineEditor*, void*);
};
+class LLFlyoutButton : public LLComboBox
+{
+public:
+ LLFlyoutButton(
+ const LLString& name,
+ const LLRect &rect,
+ const LLString& label,
+ void (*commit_callback)(LLUICtrl*, void*) = NULL,
+ void *callback_userdata = NULL);
+
+ virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_FLYOUT_BUTTON; }
+ virtual LLString getWidgetTag() const { return LL_FLYOUT_BUTTON_TAG; }
+
+ virtual void updateLayout();
+ virtual void draw();
+ virtual void setEnabled(BOOL enabled);
+
+ void setToggleState(BOOL state);
+
+ static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ static void onActionButtonClick(void *userdata);
+ static void onSelectAction(LLUICtrl* ctrl, void *userdata);
+
+protected:
+ LLButton* mActionButton;
+ LLPointer<LLUIImage> mActionButtonImage;
+ LLPointer<LLUIImage> mExpanderButtonImage;
+ LLPointer<LLUIImage> mActionButtonImageSelected;
+ LLPointer<LLUIImage> mExpanderButtonImageSelected;
+ BOOL mToggleState;
+};
+
#endif
diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h
index 50d199fac5..cd3ce04718 100644
--- a/indra/llui/lldraghandle.h
+++ b/indra/llui/lldraghandle.h
@@ -54,7 +54,6 @@ public:
virtual void setTitle( const LLString& title ) = 0;
virtual const LLString& getTitle() const = 0;
- virtual void draw() = 0;
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) = 0;
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 6f1c281eb2..59741a799a 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -128,7 +128,11 @@ LLFloater::handle_map_t LLFloater::sFloaterMap;
LLFloaterView* gFloaterView = NULL;
-LLFloater::LLFloater()
+LLFloater::LLFloater() :
+ //FIXME: we should initialize *all* member variables here
+ mResizable(FALSE),
+ mDragOnLeft(FALSE)
+
{
// automatically take focus when opened
mAutoFocus = TRUE;
@@ -215,9 +219,14 @@ void LLFloater::init(const LLString& title,
}
mButtonScale = 1.f;
- LLPanel::deleteAllChildren();
+ BOOL need_border = mBorder != NULL;
+
+ // this will delete mBorder too
+ deleteAllChildren();
+ // make sure we don't have a pointer to an old, deleted border
+ mBorder = NULL;
//sjb: HACK! we had a border which was just deleted, so re-create it
- if (mBorder != NULL)
+ if (need_border)
{
addBorder();
}
@@ -609,7 +618,7 @@ void LLFloater::releaseFocus()
if( gFocusMgr.childHasKeyboardFocus( this ) )
{
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
if( gFocusMgr.childHasMouseCapture( this ) )
@@ -1023,13 +1032,10 @@ void LLFloater::setHost(LLMultiFloater* host)
{
mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE;
}
-
- mIsFocusRoot = FALSE;
}
else if (!mHostHandle.isDead() && !host)
{
mButtonScale = 1.f;
- mIsFocusRoot = TRUE;
//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;
}
updateButtons();
@@ -1257,6 +1263,7 @@ void LLFloater::show(LLFloater* floaterp)
{
if (floaterp)
{
+ gFocusMgr.triggerFocusFlash();
floaterp->open();
if (floaterp->getHost())
{
@@ -2594,9 +2601,9 @@ void LLMultiFloater::draw()
for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
- if (floaterp->getTitle() != mTabContainer->getPanelTitle(i))
+ if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
{
- mTabContainer->setPanelTitle(i, floaterp->getTitle());
+ mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
}
}
LLFloater::draw();
@@ -2714,7 +2721,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
if ( select_added_floater )
{
- mTabContainer->selectLastTab();
+ mTabContainer->selectTabPanel(floaterp);
}
floaterp->setHost(this);
@@ -2959,8 +2966,9 @@ void LLMultiFloater::updateResizeLimits()
// make sure upper left corner doesn't move
translate(0, cur_height - mRect.getHeight());
- // Try to keep whole view onscreen, don't allow partial offscreen.
- gFloaterView->adjustToFitScreen(this, FALSE);
+ // make sure this window is visible on screen when it has been modified
+ // (tab added, etc)
+ gFloaterView->adjustToFitScreen(this, TRUE);
}
}
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 6358ccbdd7..e3337eb588 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -42,11 +42,10 @@ LLFocusMgr gFocusMgr;
LLFocusMgr::LLFocusMgr()
:
mLockedView( NULL ),
- mKeyboardLockedFocusLostCallback( NULL ),
mMouseCaptor( NULL ),
mKeyboardFocus( NULL ),
+ mLastKeyboardFocus( NULL ),
mDefaultKeyboardFocus( NULL ),
- mKeyboardFocusLostCallback( NULL ),
mTopCtrl( NULL ),
mFocusWeight(0.f),
mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true
@@ -75,12 +74,11 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
if (view == mLockedView)
{
mLockedView = NULL;
- mKeyboardLockedFocusLostCallback = NULL;
- setKeyboardFocus( NULL, NULL );
+ setKeyboardFocus( NULL );
}
else
{
- setKeyboardFocus( mLockedView, mKeyboardLockedFocusLostCallback );
+ setKeyboardFocus( mLockedView );
}
}
@@ -91,7 +89,7 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
}
-void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focus_lost, BOOL lock)
+void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock)
{
if (mLockedView &&
(new_focus == NULL ||
@@ -101,28 +99,27 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
// or one of its descendants
return;
}
- FocusLostCallback old_callback = mKeyboardFocusLostCallback;
- mKeyboardFocusLostCallback = on_focus_lost;
//llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl;
if( new_focus != mKeyboardFocus )
{
- LLUICtrl* old_focus = mKeyboardFocus;
+ mLastKeyboardFocus = mKeyboardFocus;
mKeyboardFocus = new_focus;
+ if( mLastKeyboardFocus )
+ {
+ mLastKeyboardFocus->onFocusLost();
+ }
+
// clear out any existing flash
if (new_focus)
{
mFocusWeight = 0.f;
+ new_focus->onFocusReceived();
}
mFocusTimer.reset();
- if( old_callback )
- {
- old_callback( old_focus );
- }
-
#ifdef _DEBUG
mKeyboardFocusName = new_focus ? new_focus->getName() : "none";
#endif
@@ -204,13 +201,11 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( LLView* focus )
if (focus == mLockedView)
{
mLockedView = NULL;
- mKeyboardLockedFocusLostCallback = NULL;
}
if( mKeyboardFocus == focus )
{
mKeyboardFocus = NULL;
- mKeyboardFocusLostCallback = NULL;
#ifdef _DEBUG
mKeyboardFocusName = "none";
#endif
@@ -293,13 +288,19 @@ BOOL LLFocusMgr::childIsTopCtrl( LLView* parent )
// set new_top = NULL to release top_view.
void LLFocusMgr::setTopCtrl( LLUICtrl* new_top )
{
- if( new_top != mTopCtrl )
+ LLUICtrl* old_top = mTopCtrl;
+ if( new_top != old_top )
{
mTopCtrl = new_top;
#ifdef _DEBUG
mTopCtrlName = new_top ? new_top->getName() : "none";
#endif
+
+ if (old_top)
+ {
+ old_top->onLostTop();
+ }
}
}
@@ -317,13 +318,11 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view )
void LLFocusMgr::lockFocus()
{
mLockedView = mKeyboardFocus;
- mKeyboardLockedFocusLostCallback = mKeyboardFocusLostCallback;
}
void LLFocusMgr::unlockFocus()
{
mLockedView = NULL;
- mKeyboardLockedFocusLostCallback = NULL;
}
F32 LLFocusMgr::getFocusFlashAmt()
@@ -356,9 +355,9 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)
}
// release focus from "top ctrl"s, which generally hides them
- if (!focus && mTopCtrl && mTopCtrl->hasFocus())
+ if (!focus && mTopCtrl)
{
- mTopCtrl->setFocus(FALSE);
+ setTopCtrl(NULL);
}
mAppHasFocus = focus;
}
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 1c25153fbe..20dc21fc3a 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -44,8 +44,6 @@ class LLMouseHandler;
class LLFocusMgr
{
public:
- typedef void (*FocusLostCallback)(LLUICtrl*);
-
LLFocusMgr();
~LLFocusMgr();
@@ -56,11 +54,11 @@ public:
BOOL childHasMouseCapture( LLView* parent );
// Keyboard Focus
- void setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focus_lost, BOOL lock = FALSE); // new_focus = NULL to release the focus.
+ void setKeyboardFocus(LLUICtrl* new_focus, BOOL lock = FALSE); // new_focus = NULL to release the focus.
LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; }
+ LLUICtrl* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
BOOL childHasKeyboardFocus( const LLView* parent ) const;
void removeKeyboardFocusWithoutCallback( LLView* focus );
- FocusLostCallback getFocusCallback() { return mKeyboardFocusLostCallback; }
F32 getFocusTime() const { return mFocusTimer.getElapsedTimeF32(); }
F32 getFocusFlashAmt();
LLColor4 getFocusColor();
@@ -90,15 +88,14 @@ public:
protected:
LLUICtrl* mLockedView;
- FocusLostCallback mKeyboardLockedFocusLostCallback;
// Mouse Captor
LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object
// Keyboard Focus
LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object
+ LLUICtrl* mLastKeyboardFocus; // who last had focus
LLUICtrl* mDefaultKeyboardFocus;
- FocusLostCallback mKeyboardFocusLostCallback; // The object to which keyboard events are routed is called before another object takes its place
// Top View
LLUICtrl* mTopCtrl;
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 1e49210565..a063ebcd25 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -88,18 +88,11 @@ void LLIconCtrl::draw()
{
if( getVisible() )
{
- // Border
- BOOL has_image = !mImageID.isNull();
-
- if( has_image )
+ if( mImagep.notNull() )
{
- if( mImagep.notNull() )
- {
- gl_draw_scaled_image(0, 0,
- mRect.getWidth(), mRect.getHeight(),
- mImagep,
- mColor );
- }
+ mImagep->draw(0, 0,
+ mRect.getWidth(), mRect.getHeight(),
+ mColor );
}
LLUICtrl::draw();
@@ -154,6 +147,7 @@ LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
LLUICtrlFactory::getAttributeColor(node,"color", color);
LLIconCtrl* icon = new LLIconCtrl(name, rect, image_id);
+
icon->setColor(color);
icon->initFromXML(node, parent);
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index b789269558..1e474d0935 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -73,7 +73,7 @@ protected:
LLColor4 mColor;
LLString mImageName;
LLUUID mImageID;
- LLPointer<LLImageGL> mImagep;
+ LLPointer<LLUIImage> mImagep;
};
#endif
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 3c7cd17b92..4297f5fef8 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -128,7 +128,7 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
S32 max_length_bytes,
void (*commit_callback)(LLUICtrl* caller, void* user_data ),
void (*keystroke_callback)(LLLineEditor* caller, void* user_data ),
- void (*focus_lost_callback)(LLUICtrl* caller, void* user_data ),
+ void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data ),
void* userdata,
LLLinePrevalidateFunc prevalidate_func,
LLViewBorder::EBevel border_bevel,
@@ -351,10 +351,14 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
// Check to see if entire field is selected.
S32 len = mText.length();
- BOOL allSelected = (len > 0) && (( mSelectionStart == 0 && mSelectionEnd == len )
- || ( mSelectionStart == len && mSelectionEnd == 0 ));
+ BOOL all_selected = (len > 0)
+ && (( mSelectionStart == 0 && mSelectionEnd == len )
+ || ( mSelectionStart == len && mSelectionEnd == 0 ));
// Do safe truncation so we don't split multi-byte characters
+ // also consider entire string selected when mSelectAllonFocusReceived is set on an empty, focused line editor
+ all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
+
LLString truncated_utf8 = new_text;
if (truncated_utf8.size() > (U32)mMaxLengthBytes)
{
@@ -362,7 +366,7 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
mText.assign(truncated_utf8);
- if (allSelected)
+ if (all_selected)
{
// ...keep whole thing selected
selectAll();
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index a019353856..0739315c4d 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -77,7 +77,7 @@ public:
S32 max_length_bytes = 254,
void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
- void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL,
+ void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL,
void* userdata = NULL,
LLLinePrevalidateFunc prevalidate_func = NULL,
LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 46f9f515d7..19a5085a25 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -4514,7 +4514,7 @@ BOOL LLMenuHolderGL::hideMenus()
}
//if (gFocusMgr.childHasKeyboardFocus(this))
//{
- // gFocusMgr.setKeyboardFocus(NULL, NULL);
+ // gFocusMgr.setKeyboardFocus(NULL);
//}
return menu_visible;
@@ -4599,6 +4599,7 @@ void LLTearOffMenu::onFocusReceived()
break;
}
}
+ LLFloater::onFocusReceived();
}
void LLTearOffMenu::onFocusLost()
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index b8b8bf9443..ca8020fe70 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -287,7 +287,7 @@ void LLModalDialog::onAppFocusLost()
if( gFocusMgr.childHasKeyboardFocus( instance ) )
{
- gFocusMgr.setKeyboardFocus( NULL, NULL );
+ gFocusMgr.setKeyboardFocus( NULL );
}
}
}
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 6d000f3e7f..294ce5df18 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -64,7 +64,6 @@ LLPanel::panel_map_t LLPanel::sPanelMap;
LLPanel::alert_queue_t LLPanel::sAlertQueue;
const S32 RESIZE_BAR_OVERLAP = 1;
-const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
void LLPanel::init()
{
@@ -88,6 +87,7 @@ LLPanel::LLPanel()
: mRectControl()
{
init();
+ setName("panel");
}
LLPanel::LLPanel(const LLString& name)
@@ -124,6 +124,7 @@ LLPanel::LLPanel(const LLString& name, const LLString& rect_control, BOOL border
void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
LLViewBorder::EStyle border_style, S32 border_thickness)
{
+ removeBorder();
mBorder = new LLViewBorder( "panel border",
LLRect(0, mRect.getHeight(), mRect.getWidth(), 0),
border_bevel, border_style, border_thickness );
@@ -361,12 +362,6 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
{
BOOL handled = FALSE;
- if( getVisible() && getEnabled() && gFocusMgr.childHasKeyboardFocus(this) && KEY_ESCAPE == key )
- {
- gFocusMgr.setKeyboardFocus(NULL, NULL);
- return TRUE;
- }
-
if( getVisible() && getEnabled() &&
gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent )
{
@@ -472,7 +467,7 @@ void LLPanel::setFocus(BOOL b)
{
if( this == gFocusMgr.getKeyboardFocus() )
{
- gFocusMgr.setKeyboardFocus( NULL, NULL );
+ gFocusMgr.setKeyboardFocus( NULL );
}
else
{
@@ -595,7 +590,8 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
{
LLRect rect;
createRect(node, rect, parent, LLRect());
- panelp = new LLPanel(name, rect);
+ // create a new panel without a border, by default
+ panelp = new LLPanel(name, rect, FALSE);
panelp->initPanelXML(node, parent, factory);
// preserve panel's width and height, but override the location
const LLRect& panelrect = panelp->getRect();
@@ -608,12 +604,13 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
{
panelp->initPanelXML(node, parent, factory);
}
+
return panelp;
}
BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
- LLString name("panel");
+ LLString name = getName();
node->getAttributeString("name", name);
setName(name);
@@ -628,13 +625,15 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
if (!xml_filename.empty())
{
- // Preserve postion of embedded panel but allow panel to dictate width/height
- LLRect rect(getRect());
didPost = factory->buildPanel(this, xml_filename, NULL);
- S32 w = getRect().getWidth();
- S32 h = getRect().getHeight();
- rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
- setRect(rect);
+
+ LLRect new_rect = getRect();
+ // override rectangle with embedding parameters as provided
+ createRect(node, new_rect, parent);
+ setOrigin(new_rect.mLeft, new_rect.mBottom);
+ reshape(new_rect.getWidth(), new_rect.getHeight());
+ // optionally override follows flags from including nodes
+ parseFollowsFlags(node);
}
else
{
@@ -678,7 +677,7 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
initFromXML(node, parent);
/////// Border attributes ///////
- BOOL border = FALSE;
+ BOOL border = mBorder != NULL;
node->getAttributeBOOL("border", border);
if (border)
{
@@ -706,24 +705,24 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
}
/////// Background attributes ///////
- BOOL background_visible = FALSE;
+ BOOL background_visible = mBgVisible;
node->getAttributeBOOL("background_visible", background_visible);
setBackgroundVisible(background_visible);
- BOOL background_opaque = FALSE;
+ BOOL background_opaque = mBgOpaque;
node->getAttributeBOOL("background_opaque", background_opaque);
setBackgroundOpaque(background_opaque);
LLColor4 color;
- color = LLUI::sColorsGroup->getColor( "FocusBackgroundColor" );
+ color = mBgColorOpaque;
LLUICtrlFactory::getAttributeColor(node,"bg_opaque_color", color);
setBackgroundColor(color);
- color = LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" );
+ color = mBgColorAlpha;
LLUICtrlFactory::getAttributeColor(node,"bg_alpha_color", color);
setTransparentColor(color);
- LLString label;
+ LLString label = getLabel();
node->getAttributeString("label", label);
setLabel(label);
}
@@ -853,12 +852,12 @@ BOOL LLPanel::childHasFocus(const LLString& id)
}
-void LLPanel::childSetFocusChangedCallback(const LLString& id, void (*cb)(LLUICtrl*, void*))
+void LLPanel::childSetFocusChangedCallback(const LLString& id, void (*cb)(LLFocusableElement*, void*), void* user_data)
{
LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
if (child)
{
- child->setFocusChangedCallback(cb);
+ child->setFocusChangedCallback(cb, user_data);
}
}
@@ -1165,11 +1164,12 @@ void LLPanel::storeRectControl()
//
struct LLLayoutStack::LLEmbeddedPanel
{
- LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) :
+ LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
mPanel(panelp),
mMinWidth(min_width),
mMinHeight(min_height),
mAutoResize(auto_resize),
+ mUserResize(user_resize),
mOrientation(orientation),
mVisibleAmt(1.f) // default to fully visible
{
@@ -1205,6 +1205,7 @@ struct LLLayoutStack::LLEmbeddedPanel
S32 mMinWidth;
S32 mMinHeight;
BOOL mAutoResize;
+ BOOL mUserResize;
LLResizeBar* mResizeBar;
eLayoutOrientation mOrientation;
F32 mVisibleAmt;
@@ -1213,7 +1214,8 @@ struct LLLayoutStack::LLEmbeddedPanel
LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
mOrientation(orientation),
mMinWidth(0),
- mMinHeight(0)
+ mMinHeight(0),
+ mPanelSpacing(RESIZE_BAR_HEIGHT)
{
}
@@ -1226,24 +1228,26 @@ void LLLayoutStack::draw()
{
updateLayout();
{
- // clip if outside nominal bounds
- LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
+ // clip to layout rectangle, not bounding rectangle
LLRect clip_rect = (*panel_it)->mPanel->getRect();
// scale clipping rectangle by visible amount
if (mOrientation == HORIZONTAL)
{
- clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
+ clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
}
else
{
- clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
+ clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
}
- LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f);
+
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ LLLocalClipRect clip(clip_rect);
// only force drawing invisible children if visible amount is non-zero
- drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f);
+ drawChild(panelp, 0, 0, !clip_rect.isNull());
}
}
}
@@ -1258,17 +1262,13 @@ void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
delete embedded_panelp;
}
+ // need to update resizebars
+
calcMinExtents();
LLView::removeCtrl(ctrl);
}
-void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLView::reshape(width, height, called_from_parent);
- //updateLayout();
-}
-
LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
{
LLXMLNodePtr node = LLView::getXML();
@@ -1298,6 +1298,14 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
+ node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
+ // don't allow negative spacing values
+ layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
+
+ LLString name("stack");
+ node->getAttributeString("name", name);
+
+ layout_stackp->setName(name);
layout_stackp->initFromXML(node, parent);
LLXMLNodePtr child;
@@ -1308,16 +1316,18 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
S32 min_width = 0;
S32 min_height = 0;
BOOL auto_resize = TRUE;
+ BOOL user_resize = TRUE;
child->getAttributeS32("min_width", min_width);
child->getAttributeS32("min_height", min_height);
child->getAttributeBOOL("auto_resize", auto_resize);
+ child->getAttributeBOOL("user_resize", user_resize);
LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
if (panelp)
{
panelp->setFollowsNone();
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize);
+ layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
}
}
}
@@ -1335,11 +1345,36 @@ S32 LLLayoutStack::getMinHeight()
return mMinHeight;
}
-void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index)
+S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
{
- LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize);
+ // if we are spanning our children (crude upward propagation of size)
+ // then don't enforce our size on our children
+ if (mOrientation == HORIZONTAL)
+ {
+ cur_height = llmax(mMinHeight, mRect.getHeight());
+ }
+
+ return cur_height;
+}
+
+S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
+{
+ // if we are spanning our children (crude upward propagation of size)
+ // then don't enforce our size on our children
+ if (mOrientation == VERTICAL)
+ {
+ cur_width = llmax(mMinWidth, mRect.getWidth());
+ }
+
+ return cur_width;
+}
+
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index)
+{
+ LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
+
addChild(panel);
addChild(embedded_panel->mResizeBar);
@@ -1347,29 +1382,15 @@ void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL
// with a bit of overlap
for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- e_panel_list_t::iterator next_it = panel_it;
- ++next_it;
-
LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
sendChildToFront(resize_barp);
- // last resize bar is disabled, since its not between any two panels
- if ( next_it == mPanels.end() )
- {
- resize_barp->setEnabled(FALSE);
- }
- else
- {
- resize_barp->setEnabled(TRUE);
- }
}
- //updateLayout();
}
void LLLayoutStack::removePanel(LLPanel* panel)
{
removeChild(panel);
- //updateLayout();
}
void LLLayoutStack::updateLayout(BOOL force_resize)
@@ -1377,11 +1398,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
calcMinExtents();
// calculate current extents
- S32 cur_width = 0;
- S32 cur_height = 0;
+ S32 total_width = 0;
+ S32 total_height = 0;
const F32 ANIM_OPEN_TIME = 0.02f;
- const F32 ANIM_CLOSE_TIME = 0.02f;
+ const F32 ANIM_CLOSE_TIME = 0.03f;
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
@@ -1403,23 +1424,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
(*panel_it)->mVisibleAmt = 0.f;
}
}
+
if (mOrientation == HORIZONTAL)
{
- // all panels get expanded to max of all the minimum dimensions
- cur_height = llmax(mMinHeight, panelp->getRect().getHeight());
- cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
- if (panel_it != mPanels.end())
+ total_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
+ // want n-1 panel gaps for n panels
+ if (panel_it != mPanels.begin())
{
- cur_width += PANEL_STACK_GAP;
+ total_width += mPanelSpacing;
}
}
else //VERTICAL
{
- cur_width = llmax(mMinWidth, panelp->getRect().getWidth());
- cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
- if (panel_it != mPanels.end())
+ total_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
+ if (panel_it != mPanels.begin())
{
- cur_height += PANEL_STACK_GAP;
+ total_height += mPanelSpacing;
}
}
}
@@ -1465,11 +1485,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
S32 pixels_to_distribute;
if (mOrientation == HORIZONTAL)
{
- pixels_to_distribute = mRect.getWidth() - cur_width;
+ pixels_to_distribute = mRect.getWidth() - total_width;
}
else //VERTICAL
{
- pixels_to_distribute = mRect.getHeight() - cur_height;
+ pixels_to_distribute = mRect.getHeight() - total_height;
}
S32 cur_x = 0;
@@ -1482,7 +1502,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
- S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
+ S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
S32 delta_size = 0;
@@ -1502,11 +1522,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
// grow all elements equally
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
}
- new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size);
+ new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
}
else
{
- new_width = llmax(mMinWidth, mRect.getWidth());
+ new_width = getDefaultWidth(new_width);
}
if (mOrientation == VERTICAL)
@@ -1520,22 +1540,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
}
- new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size);
+ new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
}
else
{
- new_height = llmax(mMinHeight, mRect.getHeight());
+ new_height = getDefaultHeight(new_height);
}
}
- else // don't resize
+ else
{
if (mOrientation == HORIZONTAL)
{
- new_height = llmax(mMinHeight, mRect.getHeight());
+ new_height = getDefaultHeight(new_height);
}
else // VERTICAL
{
- new_width = llmax(mMinWidth, mRect.getWidth());
+ new_width = getDefaultWidth(new_width);
}
}
@@ -1550,22 +1570,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (mOrientation == HORIZONTAL)
{
resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
- resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
}
else
{
resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
- resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
}
(*panel_it)->mResizeBar->setRect(resize_bar_rect);
if (mOrientation == HORIZONTAL)
{
- cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + mPanelSpacing;
}
else //VERTICAL
{
- cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + mPanelSpacing;
}
}
@@ -1577,29 +1597,38 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (mOrientation == HORIZONTAL)
{
- (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total);
+ (*panel_it)->mResizeBar->setResizeLimits(
+ (*panel_it)->mMinWidth,
+ (*panel_it)->mMinWidth + shrink_headroom_total);
}
else //VERTICAL
{
- (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total);
+ (*panel_it)->mResizeBar->setResizeLimits(
+ (*panel_it)->mMinHeight,
+ (*panel_it)->mMinHeight + shrink_headroom_total);
}
- // hide resize bars for invisible panels
- (*panel_it)->mResizeBar->setVisible(panelp->getVisible());
- if (panelp->getVisible())
+
+ // toggle resize bars based on panel visibility, resizability, etc
+ BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
+ (*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
+
+ if (resize_bar_enabled)
{
last_resize_bar = (*panel_it)->mResizeBar;
}
}
// hide last resize bar as there is nothing past it
+ // resize bars need to be in between two resizable panels
if (last_resize_bar)
{
last_resize_bar->setVisible(FALSE);
}
// not enough room to fit existing contents
- if (!force_resize &&
- ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP)))
+ if (!force_resize
+ && ((cur_y != -mPanelSpacing)
+ || (cur_x != mRect.getWidth() + mPanelSpacing)))
{
// do another layout pass with all stacked elements contributing
// even those that don't usually resize
@@ -1631,20 +1660,22 @@ void LLLayoutStack::calcMinExtents()
{
if (mOrientation == HORIZONTAL)
{
- mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight);
+ mMinHeight = llmax( mMinHeight,
+ (*panel_it)->mMinHeight);
mMinWidth += (*panel_it)->mMinWidth;
if (panel_it != mPanels.begin())
{
- mMinWidth += PANEL_STACK_GAP;
+ mMinWidth += mPanelSpacing;
}
}
else //VERTICAL
{
- mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth);
+ mMinWidth = llmax( mMinWidth,
+ (*panel_it)->mMinWidth);
mMinHeight += (*panel_it)->mMinHeight;
if (panel_it != mPanels.begin())
{
- mMinHeight += PANEL_STACK_GAP;
+ mMinHeight += mPanelSpacing;
}
}
}
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 78aa7cfc21..88b4ecb76b 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -173,7 +173,7 @@ public:
// LLUICtrl
void childSetFocus(const LLString& id, BOOL focus = TRUE);
BOOL childHasFocus(const LLString& id);
- void childSetFocusChangedCallback(const LLString& id, void (*cb)(LLUICtrl*, void*));
+ void childSetFocusChangedCallback(const LLString& id, void (*cb)(LLFocusableElement*, void*), void* user_data = NULL);
void childSetCommitCallback(const LLString& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL );
void childSetDoubleClickCallback(const LLString& id, void (*cb)(void*), void* userdata = NULL );
@@ -277,9 +277,9 @@ public:
virtual ~LLLayoutStack();
/*virtual*/ void draw();
- /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void removeCtrl(LLUICtrl* ctrl);
+
virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LAYOUT_STACK; }
virtual LLString getWidgetTag() const { return LL_LAYOUT_STACK_TAG; }
@@ -288,7 +288,7 @@ public:
S32 getMinWidth();
S32 getMinHeight();
- void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index = S32_MAX);
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
void updateLayout(BOOL force_resize = FALSE);
@@ -299,6 +299,8 @@ protected:
void calcMinExtents();
S32 getMinStackSize();
S32 getCurStackSize();
+ S32 getDefaultHeight(S32 cur_height);
+ S32 getDefaultWidth(S32 cur_width);
protected:
eLayoutOrientation mOrientation;
@@ -308,6 +310,7 @@ protected:
S32 mMinWidth;
S32 mMinHeight;
+ S32 mPanelSpacing;
};
#endif
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index 17b76def71..120323e7d1 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -60,7 +60,7 @@ LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 mi
if( RIGHT_BOTTOM == mCorner)
{
LLUUID image_id(LLUI::sConfigGroup->getString("UIImgResizeBottomRightUUID"));
- mImage = LLUI::sImageProvider->getUIImageByID(image_id);
+ mImage = LLUI::sImageProvider->getImageByID(image_id);
}
switch( mCorner )
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 99908a6bc0..b106bb570d 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -159,30 +159,50 @@ void LLScrollbar::setDocParams( S32 size, S32 pos )
void LLScrollbar::setDocPos(S32 pos)
{
- mDocPos = llclamp( pos, 0, getDocPosMax() );
- mDocChanged = TRUE;
+ if (pos != mDocPos)
+ {
+ mDocPos = llclamp( pos, 0, getDocPosMax() );
+ mDocChanged = TRUE;
- updateThumbRect();
+ updateThumbRect();
+ }
}
void LLScrollbar::setDocSize(S32 size)
{
- mDocSize = size;
- mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
- mDocChanged = TRUE;
+ if (size != mDocSize)
+ {
+ mDocSize = size;
+ mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
+ mDocChanged = TRUE;
- updateThumbRect();
+ updateThumbRect();
+ }
}
void LLScrollbar::setPageSize( S32 page_size )
{
- mPageSize = page_size;
- mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
- mDocChanged = TRUE;
+ if (page_size != mPageSize)
+ {
+ mPageSize = page_size;
+ mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
+ mDocChanged = TRUE;
- updateThumbRect();
+ updateThumbRect();
+ }
+}
+
+BOOL LLScrollbar::isAtBeginning()
+{
+ return mDocPos == 0;
+}
+
+BOOL LLScrollbar::isAtEnd()
+{
+ return mDocPos == getDocPosMax();
}
+
void LLScrollbar::updateThumbRect()
{
// llassert( 0 <= mDocSize );
@@ -479,7 +499,7 @@ void LLScrollbar::draw()
// Draw background and thumb.
LLUUID rounded_rect_image_id;
rounded_rect_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
- LLImageGL* rounded_rect_imagep = LLUI::sImageProvider->getUIImageByID(rounded_rect_image_id);
+ LLImageGL* rounded_rect_imagep = LLUI::sImageProvider->getImageByID(rounded_rect_image_id);
if (!rounded_rect_imagep)
{
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index 353935cfb8..50aa3cafe9 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -88,6 +88,9 @@ public:
void setDocPos( S32 pos );
S32 getDocPos() { return mDocPos; }
+ BOOL isAtBeginning();
+ BOOL isAtEnd();
+
// How many "lines" of the "document" is can appear on a page.
void setPageSize( S32 page_size );
S32 getPageSize() { return mPageSize; }
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 8b5d009b95..34a29cef51 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -394,33 +394,29 @@ BOOL LLScrollableContainerView::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect)
{
- if( getVisible() && pointInView(x,y) )
+ S32 local_x, local_y;
+ for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
{
- S32 local_x, local_y;
- for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
+ local_x = x - mScrollbar[i]->getRect().mLeft;
+ local_y = y - mScrollbar[i]->getRect().mBottom;
+ if( mScrollbar[i]->handleToolTip(local_x, local_y, msg, sticky_rect) )
{
- local_x = x - mScrollbar[i]->getRect().mLeft;
- local_y = y - mScrollbar[i]->getRect().mBottom;
- if( mScrollbar[i]->handleToolTip(local_x, local_y, msg, sticky_rect) )
- {
- return TRUE;
- }
+ return TRUE;
}
- // Handle 'child' view.
- if( mScrolledView )
+ }
+ // Handle 'child' view.
+ if( mScrolledView )
+ {
+ local_x = x - mScrolledView->getRect().mLeft;
+ local_y = y - mScrolledView->getRect().mBottom;
+ if( mScrolledView->handleToolTip(local_x, local_y, msg, sticky_rect) )
{
- local_x = x - mScrolledView->getRect().mLeft;
- local_y = y - mScrolledView->getRect().mBottom;
- if( mScrolledView->handleToolTip(local_x, local_y, msg, sticky_rect) )
- {
- return TRUE;
- }
+ return TRUE;
}
-
- // Opaque
- return TRUE;
}
- return FALSE;
+
+ // Opaque
+ return TRUE;
}
void LLScrollableContainerView::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar )
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 96a739418f..0c81b2da08 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -61,43 +61,55 @@ const S32 LIST_SNAP_PADDING = 5;
// local structures & classes.
struct SortScrollListItem
{
- SortScrollListItem(const S32 sort_col, BOOL sort_ascending)
- {
- mSortCol = sort_col;
- mSortAscending = sort_ascending;
- }
+ SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders)
+ : mSortOrders(sort_orders)
+ {}
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
{
- const LLScrollListCell *cell1;
- const LLScrollListCell *cell2;
-
- cell1 = i1->getColumn(mSortCol);
- cell2 = i2->getColumn(mSortCol);
+ if ( mSortOrders.empty() ) return true;
+
+ const LLScrollListCell *cell1 = NULL;
+ const LLScrollListCell *cell2 = NULL;
- S32 order = 1;
- if (!mSortAscending)
+ sort_order_t::const_reverse_iterator end_it = mSortOrders.rend();
+ sort_order_t::const_reverse_iterator it;
+
+ // sort over all columns in order specified by mSortOrders
+ S32 sort_result = 0;
+ for (it = mSortOrders.rbegin(); it != end_it; ++it)
{
- order = -1;
- }
+ S32 col_idx = it->first;
+ BOOL sort_ascending = it->second;
- BOOL retval = FALSE;
+ cell1 = i1->getColumn(col_idx);
+ cell2 = i2->getColumn(col_idx);
+ // ascending or descending sort for this column?
+ S32 order = 1;
+ if (!sort_ascending)
+ {
+ order = -1;
+ }
- if (cell1 && cell2)
- {
- retval = ((order * LLString::compareDict(cell1->getText(), cell2->getText())) < 0);
+ if (cell1 && cell2)
+ {
+ sort_result = (order * LLString::compareDict(cell1->getValue().asString(), cell2->getValue().asString()));
+ if (sort_result != 0)
+ {
+ // we have a sort order!
+ break;
+ }
+ }
}
- return (retval ? TRUE : FALSE);
+ return sort_result < 0;
}
-protected:
- S32 mSortCol;
- S32 mSortAscending;
+ typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
+ const sort_order_t& mSortOrders;
};
-
//
// LLScrollListIcon
//
@@ -120,6 +132,14 @@ LLScrollListIcon::~LLScrollListIcon()
{
}
+void LLScrollListIcon::setValue(LLSD value)
+{
+ mImageUUID = value.asUUID();
+ // don't use default image specified by LLUUID::null, use no image in that case
+ mIcon = mImageUUID.isNull() ? NULL : LLUI::sImageProvider->getImageByID(value.asUUID());
+}
+
+
void LLScrollListIcon::setColor(const LLColor4& color)
{
mColor = color;
@@ -127,7 +147,10 @@ void LLScrollListIcon::setColor(const LLColor4& color)
void LLScrollListIcon::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
{
- gl_draw_image(0, 0, mIcon, mColor);
+ if (mIcon)
+ {
+ gl_draw_image(0, 0, mIcon, mColor);
+ }
}
//
@@ -158,15 +181,15 @@ LLScrollListCheck::~LLScrollListCheck()
void LLScrollListCheck::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
{
mCheckBox->draw();
-
}
BOOL LLScrollListCheck::handleClick()
{
- if ( mCheckBox->getEnabled() )
+ if (mCheckBox->getEnabled())
{
- LLCheckBoxCtrl::onButtonPress(mCheckBox);
+ mCheckBox->toggle();
}
+ // don't change selection when clicking on embedded checkbox
return TRUE;
}
@@ -213,7 +236,7 @@ LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font,
// initialize rounded rect image
if (!mRoundedRectImage)
{
- mRoundedRectImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga")));
+ mRoundedRectImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga")));
}
}
@@ -223,6 +246,12 @@ LLScrollListText::~LLScrollListText()
delete mColor;
}
+S32 LLScrollListText::getContentWidth() const
+{
+ return mFont->getWidth(mText.getString());
+}
+
+
void LLScrollListText::setColor(const LLColor4& color)
{
if (!mColor)
@@ -314,31 +343,6 @@ LLScrollListItem::~LLScrollListItem()
std::for_each(mColumns.begin(), mColumns.end(), DeletePointer());
}
-BOOL LLScrollListItem::handleClick(S32 x, S32 y, MASK mask)
-{
- BOOL handled = FALSE;
-
- S32 left = 0;
- S32 right = 0;
- S32 width = 0;
-
- std::vector<LLScrollListCell *>::iterator iter = mColumns.begin();
- std::vector<LLScrollListCell *>::iterator end = mColumns.end();
- for ( ; iter != end; ++iter)
- {
- width = (*iter)->getWidth();
- right += width;
- if (left <= x && x < right )
- {
- handled = (*iter)->handleClick();
- break;
- }
-
- left += width;
- }
- return handled;
-}
-
void LLScrollListItem::setNumColumns(S32 columns)
{
S32 prev_columns = mColumns.size();
@@ -375,7 +379,7 @@ LLString LLScrollListItem::getContentsCSV()
S32 count = getNumColumns();
for (S32 i=0; i<count; ++i)
{
- ret += getColumn(i)->getText();
+ ret += getColumn(i)->getValue().asString();
if (i < count-1)
{
ret += ", ";
@@ -387,16 +391,7 @@ LLString LLScrollListItem::getContentsCSV()
void LLScrollListItem::setEnabled(BOOL b)
{
- if (b != mEnabled)
- {
- std::vector<LLScrollListCell *>::iterator iter = mColumns.begin();
- std::vector<LLScrollListCell *>::iterator end = mColumns.end();
- for ( ; iter != end; ++iter)
- {
- (*iter)->setEnabled(b);
- }
- mEnabled = b;
- }
+ mEnabled = b;
}
//---------------------------------------------------------------------------
@@ -424,9 +419,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mCanSelect(TRUE),
mDisplayColumnHeaders(FALSE),
mCollapseEmptyColumns(FALSE),
- mIsPopup(FALSE),
mMaxItemCount(INT_MAX),
- //mItemCount(0),
+ mMaxContentWidth(0),
mBackgroundVisible( TRUE ),
mDrawStripes(TRUE),
mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ),
@@ -443,12 +437,13 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mOnSortChangedCallback( NULL ),
mHighlightedItem(-1),
mBorder(NULL),
- mDefaultColumn("SIMPLE"),
+ mDefaultColumnName("SIMPLE"),
mSearchColumn(0),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
- mSortColumn(-1),
mSortAscending(TRUE),
+ mSecondarySortColumn(-1),
+ mSecondarySortAscending(TRUE),
mSorted(TRUE),
mDirty(FALSE),
mOriginalSelection(-1),
@@ -457,7 +452,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mItemListRect.setOriginAndSize(
mBorderThickness + LIST_BORDER_PAD,
mBorderThickness + LIST_BORDER_PAD,
- mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE,
+ mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ),
mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) );
updateLineHeight();
@@ -481,7 +476,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mScrollbar->setFollowsTop();
mScrollbar->setFollowsBottom();
mScrollbar->setEnabled( TRUE );
- mScrollbar->setVisible( TRUE );
+ // scrollbar is visible only when needed
+ mScrollbar->setVisible(FALSE);
addChild(mScrollbar);
// Border
@@ -539,7 +535,8 @@ void LLScrollListCtrl::clearRows()
mScrollLines = 0;
mLastSelected = NULL;
- updateMaxContentWidth(NULL);
+ calcMaxContentWidth(NULL);
+ updateLayout();
mDirty = FALSE;
}
@@ -620,38 +617,64 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const
return ret;
}
+// returns first matching item
+LLScrollListItem* LLScrollListCtrl::getItem(const LLSD& sd) const
+{
+ LLString string_val = sd.asString();
+
+ item_list::const_iterator iter;
+ for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ {
+ LLScrollListItem* item = *iter;
+ // assumes string representation is good enough for comparison
+ if (item->getValue().asString() == string_val)
+ {
+ return item;
+ }
+ }
+ return NULL;
+}
+
void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
{
- S32 old_height = mRect.getHeight();
LLUICtrl::reshape( width, height, called_from_parent );
- S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
+ updateLayout();
+}
+void LLScrollListCtrl::updateLayout()
+{
+ // reserve room for column headers, if needed
+ S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
mItemListRect.setOriginAndSize(
mBorderThickness + LIST_BORDER_PAD,
mBorderThickness + LIST_BORDER_PAD,
- mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE,
+ mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ),
mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) - heading_size );
+ // how many lines of content in a single "page"
mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0;
- if(old_height < height && getScrollPos() == mScrollbar->getDocPosMax())
+ BOOL scrollbar_visible = getItemCount() > mPageLines;
+ if (scrollbar_visible)
{
- setScrollPos(mScrollbar->getDocPosMax());
+ // provide space on the right for scrollbar
+ mItemListRect.mRight = mRect.getWidth() - ( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE;
}
- mScrollbar->setVisible(mPageLines < getItemCount());
+
+ mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
mScrollbar->setPageSize( mPageLines );
-
+ mScrollbar->setDocSize( getItemCount() );
+ mScrollbar->setVisible(scrollbar_visible);
+
updateColumns();
}
// Attempt to size the control to show all items.
// Do not make larger than width or height.
-void LLScrollListCtrl::arrange(S32 max_width, S32 max_height)
+void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
{
- S32 height = mLineHeight * (getItemCount() + 1);
- height = llmin( height, max_height );
-
+ S32 height = llmin( getRequiredRect().getHeight(), max_height );
S32 width = mRect.getWidth();
reshape( width, height );
@@ -660,7 +683,10 @@ void LLScrollListCtrl::arrange(S32 max_width, S32 max_height)
LLRect LLScrollListCtrl::getRequiredRect()
{
- S32 height = mLineHeight * (getItemCount() + 1);
+ S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
+ S32 height = (mLineHeight * getItemCount())
+ + (2 * ( mBorderThickness + LIST_BORDER_PAD ))
+ + heading_size;
S32 width = mRect.getWidth();
return LLRect(0, height, width, 0);
@@ -680,15 +706,22 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
break;
case ADD_SORTED:
- if (mSortColumn == -1)
{
- mSortColumn = 0;
- mSortAscending = TRUE;
- }
- mItemList.push_back(item);
- std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
- break;
-
+ // sort by column 0, in ascending order
+ std::vector<sort_column_t> single_sort_column;
+ single_sort_column.push_back(std::make_pair(0, TRUE));
+
+ mItemList.push_back(item);
+ std::stable_sort(
+ mItemList.begin(),
+ mItemList.end(),
+ SortScrollListItem(single_sort_column));
+
+ // ADD_SORTED just sorts by first column...
+ // this might not match user sort criteria, so flag list as being in unsorted state
+ setSorted(FALSE);
+ break;
+ }
case ADD_BOTTOM:
mItemList.push_back(item);
setSorted(FALSE);
@@ -702,33 +735,31 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
}
updateLineHeightInsert(item);
- mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0;
- BOOL scrollbar_visible = mPageLines < getItemCount();
-
- if (scrollbar_visible != mScrollbar->getVisible())
- {
- mScrollbar->setVisible(mPageLines < getItemCount());
- updateColumns();
- }
- mScrollbar->setPageSize( mPageLines );
-
- mScrollbar->setDocSize( getItemCount() );
+ calcMaxContentWidth(item);
- updateMaxContentWidth(item);
+ updateLayout();
}
return not_too_big;
}
-void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
+void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item)
{
const S32 HEADING_TEXT_PADDING = 30;
const S32 COLUMN_TEXT_PADDING = 20;
- std::map<LLString, LLScrollListColumn>::iterator column_itor;
- for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
+ if (added_item == NULL)
+ {
+ mMaxContentWidth = 0;
+ }
+
+ S32 item_content_width = 0;
+
+ ordered_columns_t::iterator column_itor;
+ for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor)
{
- LLScrollListColumn* column = &column_itor->second;
+ LLScrollListColumn* column = *column_itor;
+ if (!column) continue;
if (!added_item)
{
@@ -740,7 +771,7 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
if (!cellp) continue;
- column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
+ column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
}
}
else
@@ -748,9 +779,13 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
LLScrollListCell* cellp = added_item->getColumn(column->mIndex);
if (!cellp) continue;
- column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
+ column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
}
+
+ item_content_width += column->mMaxContentWidth;
}
+
+ mMaxContentWidth = llmax(mMaxContentWidth, item_content_width);
}
const S32 SCROLL_LIST_ROW_PAD = 2;
@@ -789,7 +824,6 @@ void LLScrollListCtrl::updateColumns()
mColumnsIndexed.resize(mColumns.size());
std::map<LLString, LLScrollListColumn>::iterator column_itor;
- bool first_dynamic = true;
for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
{
LLScrollListColumn *column = &column_itor->second;
@@ -801,11 +835,6 @@ void LLScrollListCtrl::updateColumns()
else if (column->mDynamicWidth)
{
new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
- if(first_dynamic)
- {
- first_dynamic = false;
- new_width += (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE);
- }
}
if (new_width != column->mWidth)
@@ -854,43 +883,38 @@ void LLScrollListCtrl::updateColumns()
}
right = llmax(left, llmin(mItemListRect.getWidth(), right));
S32 header_width = right - left;
-
+
last_header->reshape(header_width, mHeadingHeight);
- last_header->translate(left - last_header->getRect().mLeft, top - last_header->getRect().mBottom);
+ last_header->translate(
+ left - last_header->getRect().mLeft,
+ top - last_header->getRect().mBottom);
last_header->setVisible(mDisplayColumnHeaders && header_width > 0);
left = right;
}
}
// expand last column header we encountered to full list width
-
if (last_header)
{
- S32 header_strip_width = mItemListRect.getWidth() + (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE);
- S32 new_width = llmax(0, mItemListRect.mLeft + header_strip_width - last_header->getRect().mLeft);
+ S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft);
last_header->reshape(new_width, last_header->getRect().getHeight());
last_header->setVisible(mDisplayColumnHeaders && new_width > 0);
}
-
}
void LLScrollListCtrl::setDisplayHeading(BOOL display)
{
mDisplayColumnHeaders = display;
- updateColumns();
-
- setHeadingHeight(mHeadingHeight);
+ updateLayout();
}
void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
{
mHeadingHeight = heading_height;
- reshape(mRect.getWidth(), mRect.getHeight());
+ updateLayout();
- // Resize
- mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
}
void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse)
@@ -934,6 +958,8 @@ BOOL LLScrollListCtrl::selectFirstItem()
BOOL LLScrollListCtrl::selectNthItem( S32 target_index )
{
+ if (mItemList.empty()) return FALSE;
+
// Deselects all other items
BOOL success = FALSE;
S32 index = 0;
@@ -1012,7 +1038,32 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
}
delete itemp;
mItemList.erase(mItemList.begin() + target_index);
- updateMaxContentWidth(NULL);
+ calcMaxContentWidth(NULL);
+}
+
+//FIXME: refactor item deletion
+void LLScrollListCtrl::deleteItems(const LLSD& sd)
+{
+ item_list::iterator iter;
+ for (iter = mItemList.begin(); iter < mItemList.end(); )
+ {
+ LLScrollListItem* itemp = *iter;
+ if (itemp->getValue().asString() == sd.asString())
+ {
+ if (itemp == mLastSelected)
+ {
+ mLastSelected = NULL;
+ }
+ delete itemp;
+ mItemList.erase(iter++);
+ }
+ else
+ {
+ iter++;
+ }
+ }
+
+ calcMaxContentWidth(NULL);
}
void LLScrollListCtrl::deleteSelectedItems()
@@ -1032,7 +1083,7 @@ void LLScrollListCtrl::deleteSelectedItems()
}
}
mLastSelected = NULL;
- updateMaxContentWidth(NULL);
+ calcMaxContentWidth(NULL);
}
void LLScrollListCtrl::highlightNthItem(S32 target_index)
@@ -1108,7 +1159,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
if (!getFirstSelected())
{
- selectFirstItem();
+ // select last item
+ selectNthItem(getItemCount() - 1);
}
else
{
@@ -1130,7 +1182,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
break;
}
- prev_item = cur_item;
+ // don't allow navigation to disabled elements
+ prev_item = cur_item->getEnabled() ? cur_item : prev_item;
}
}
@@ -1145,32 +1198,34 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
{
+ LLScrollListItem* next_item = NULL;
+
if (!getFirstSelected())
{
selectFirstItem();
}
else
{
- item_list::iterator iter;
- for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ item_list::reverse_iterator iter;
+ for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++)
{
- LLScrollListItem* item = *iter;
- if (item->getSelected())
+ LLScrollListItem* cur_item = *iter;
+
+ if (cur_item->getSelected())
{
- if (++iter != mItemList.end())
+ if (next_item)
{
- LLScrollListItem *next_item = *iter;
- if (next_item)
- {
- selectItem(next_item, !extend_selection);
- }
- else
- {
- reportInvalidInput();
- }
+ selectItem(next_item, !extend_selection);
+ }
+ else
+ {
+ reportInvalidInput();
}
break;
}
+
+ // don't allow navigation to disabled items
+ next_item = cur_item->getEnabled() ? cur_item : next_item;
}
}
@@ -1213,10 +1268,29 @@ LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, EAd
item->setEnabled(enabled);
item->addColumn( item_text, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) );
addItem( item, pos );
+
+ // create new column on demand for "simple" items
+ if (mColumns.empty())
+ {
+ LLSD new_column;
+ new_column["name"] = mDefaultColumnName;
+ new_column["label"] = "";
+ new_column["dynamicwidth"] = TRUE;
+ addColumn(new_column);
+ }
}
return item;
}
+LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)
+{
+ LLSD item;
+ item["enabled"] = FALSE;
+ item["columns"][0]["type"] = "separator";
+ item["columns"][0]["column"] = mDefaultColumnName;
+
+ return addElement(item, pos);
+}
// Selects first enabled item of the given name.
// Returns false if item not found.
@@ -1242,7 +1316,7 @@ BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensiti
{
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
- LLString item_text = item->getColumn(0)->getText();
+ LLString item_text = item->getColumn(0)->getValue().asString();
if (!case_sensitive)
{
LLString::toLower(item_text);
@@ -1288,7 +1362,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
LLScrollListCell* cellp = item->getColumn(mSearchColumn);
- BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getText()[0]) : FALSE;
+ BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
selectItem(item);
@@ -1315,7 +1389,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
{
continue;
}
- LLWString item_label = utf8str_to_wstring(cellp->getText());
+ LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
if (!case_sensitive)
{
LLWString::toLower(item_label);
@@ -1346,14 +1420,14 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
return found;
}
-const LLString& LLScrollListCtrl::getSimpleSelectedItem(S32 column) const
+const LLString LLScrollListCtrl::getSimpleSelectedItem(S32 column) const
{
LLScrollListItem* item;
item = getFirstSelected();
if (item)
{
- return item->getColumn(column)->getText();
+ return item->getColumn(column)->getValue().asString();
}
return LLString::null;
@@ -1384,6 +1458,16 @@ LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, LLS
item->setEnabled(enabled);
item->addColumn(item_text, gResMgr->getRes(LLFONT_SANSSERIF_SMALL), column_width);
addItem( item, pos );
+
+ // create new column on demand
+ if (mColumns.empty())
+ {
+ LLSD new_column;
+ new_column["name"] = "default_column";
+ new_column["label"] = "";
+ new_column["dynamicwidth"] = TRUE;
+ addColumn(new_column);
+ }
}
return item;
}
@@ -1481,9 +1565,7 @@ void LLScrollListCtrl::drawItems()
LLGLSUIDefault gls_ui;
{
- LLRect clip_rect = mItemListRect;
- if(!mScrollbar->getVisible()) clip_rect.mRight += SCROLLBAR_SIZE;
- LLLocalClipRect clip(clip_rect);
+ LLLocalClipRect clip(mItemListRect);
S32 cur_x = x;
S32 cur_y = y;
@@ -1491,7 +1573,6 @@ void LLScrollListCtrl::drawItems()
mDrewSelected = FALSE;
S32 line = 0;
- LLColor4 color;
S32 max_columns = 0;
item_list::iterator iter;
@@ -1502,7 +1583,7 @@ void LLScrollListCtrl::drawItems()
item_rect.setOriginAndSize(
cur_x,
cur_y,
- mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + SCROLLBAR_SIZE,
+ mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + mScrollbar->getRect().getWidth(),
mLineHeight );
//llinfos << item_rect.getWidth() << llendl;
@@ -1514,37 +1595,43 @@ void LLScrollListCtrl::drawItems()
max_columns = llmax(max_columns, item->getNumColumns());
+ LLColor4 fg_color;
LLRect bg_rect = item_rect;
// pad background rectangle to separate it from contents
bg_rect.stretch(LIST_BORDER_PAD, 0);
+ LLColor4 bg_color(0.f, 0.f, 0.f, 0.f);
if( mScrollLines <= line && line < mScrollLines + num_page_lines )
{
if( item->getSelected() && mCanSelect)
{
// Draw background of selected item
- LLGLSNoTexture no_texture;
- glColor4fv(mBgSelectedColor.mV);
- gl_rect_2d( bg_rect );
-
- color = mFgSelectedColor;
+ bg_color = mBgSelectedColor;
+ fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor);
}
else if (mHighlightedItem == line && mCanSelect)
{
- LLGLSNoTexture no_texture;
- glColor4fv(mHighlightedColor.mV);
- gl_rect_2d( bg_rect );
- color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
+ bg_color = mHighlightedColor;
+ fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
}
else
{
- color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
if (mDrawStripes && (line%2 == 0) && (max_columns > 1))
{
- LLGLSNoTexture no_texture;
- glColor4fv(mBgStripeColor.mV);
- gl_rect_2d( bg_rect );
+ bg_color = mBgStripeColor;
}
+ fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
+ }
+
+ if (!item->getEnabled())
+ {
+ bg_color = mBgReadOnlyColor;
+ }
+ // draw background rect
+ {
+ LLGLSNoTexture no_texture;
+ glColor4fv(bg_color.mV);
+ gl_rect_2d( bg_rect );
}
S32 line_x = cur_x;
@@ -1553,7 +1640,6 @@ void LLScrollListCtrl::drawItems()
S32 cur_col = 0;
S32 dynamic_width = 0;
S32 dynamic_remainder = 0;
- bool first_dynamic = true;
if(mNumDynamicWidthColumns > 0)
{
dynamic_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
@@ -1563,15 +1649,9 @@ void LLScrollListCtrl::drawItems()
for (LLScrollListCell* cell = item->getColumn(0); cur_col < num_cols; cell = item->getColumn(++cur_col))
{
S32 cell_width = cell->getWidth();
-
if(mColumnsIndexed.size() > (U32)cur_col && mColumnsIndexed[cur_col] && mColumnsIndexed[cur_col]->mDynamicWidth)
{
cell_width = dynamic_width + (--dynamic_remainder ? 1 : 0);
- if(first_dynamic)
- {
- cell_width += mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE;
- first_dynamic = false;
- }
cell->setWidth(cell_width);
}
// Two ways a cell could be hidden
@@ -1585,7 +1665,7 @@ void LLScrollListCtrl::drawItems()
F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
- cell->drawToWidth( space_left, color, highlight_color );
+ cell->drawToWidth( space_left, fg_color, highlight_color );
LLUI::popMatrix();
cur_x += cell_width + mColumnPadding;
@@ -1605,6 +1685,12 @@ void LLScrollListCtrl::draw()
{
if( getVisible() )
{
+ // if user specifies sort, make sure it is maintained
+ if (needsSorting() && !isSorted())
+ {
+ sortItems();
+ }
+
if (mNeedsScroll)
{
scrollToShowSelected();
@@ -1645,6 +1731,54 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
+BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
+{
+ S32 column_index = getColumnIndexFromOffset(x);
+ LLScrollListColumn* columnp = getColumn(column_index);
+
+ if (columnp == NULL) return FALSE;
+
+ BOOL handled = FALSE;
+ // show tooltip for full name of hovered item if it has been truncated
+ LLScrollListItem* hit_item = hitItem(x, y);
+ if (hit_item)
+ {
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (!hit_cell) return FALSE;
+ S32 cell_required_width = hit_cell->getContentWidth();
+ if (hit_cell
+ && hit_cell->isText()
+ && cell_required_width > columnp->mWidth)
+ {
+
+ S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
+ S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item));
+ LLRect cell_rect;
+ cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->mWidth, mLineHeight);
+ // Convert rect local to screen coordinates
+ localPointToScreen(
+ cell_rect.mLeft, cell_rect.mBottom,
+ &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
+ localPointToScreen(
+ cell_rect.mRight, cell_rect.mTop,
+ &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
+
+ msg = hit_cell->getValue().asString();
+ handled = TRUE;
+ }
+ }
+
+ // otherwise, look for a tooltip associated with this column
+ LLColumnHeader* headerp = columnp->mHeader;
+ if (headerp && !handled)
+ {
+ headerp->handleToolTip(x, y, msg, sticky_rect_screen);
+ handled = !msg.empty();
+ }
+
+ return handled;
+}
+
BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if (!mCanSelect) return FALSE;
@@ -1652,6 +1786,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
BOOL selection_changed = FALSE;
LLScrollListItem* hit_item = hitItem(x, y);
+
if( hit_item )
{
if( mAllowMultipleSelection )
@@ -1686,6 +1821,11 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
selectItem(item, FALSE);
selecting = !selecting;
+ if (hit_item == lastSelected)
+ {
+ // stop selecting now, since we just clicked on our last selected item
+ selecting = FALSE;
+ }
}
if (selecting)
{
@@ -1726,9 +1866,6 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
selectItem(hit_item);
}
- hit_item->handleClick(x - mBorderThickness - LIST_BORDER_PAD,
- 1, mask);
-
selection_changed = mSelectionChanged;
if (mCommitOnSelectionChange)
{
@@ -1750,19 +1887,17 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
+ BOOL handled = childrenHandleMouseDown(x, y, mask) != NULL;
if( !handled )
{
// set keyboard focus first, in case click action wants to move focus elsewhere
setFocus(TRUE);
- // clear selection changed flag so because user is starting a selection operation
+ // clear selection changed flag because user is starting a selection operation
mSelectionChanged = FALSE;
- gFocusMgr.setMouseCapture(this);
- selectItemAt(x, y, mask);
- mNeedsScroll = TRUE;
+ handleClick(x, y, mask);
}
return TRUE;
@@ -1798,19 +1933,74 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
//BOOL handled = FALSE;
if(getVisible())
{
- // Offer the click to the children, even if we aren't enabled
- // so the scroll bars will work.
- if (NULL == LLView::childrenHandleDoubleClick(x, y, mask))
+ BOOL handled = handleClick(x, y, mask);
+
+ if (!handled)
{
- if( mCanSelect && mOnDoubleClickCallback )
+ // Offer the click to the children, even if we aren't enabled
+ // so the scroll bars will work.
+ if (NULL == LLView::childrenHandleDoubleClick(x, y, mask))
{
- mOnDoubleClickCallback( mCallbackUserData );
+ if( mCanSelect && mOnDoubleClickCallback )
+ {
+ mOnDoubleClickCallback( mCallbackUserData );
+ }
}
}
}
return TRUE;
}
+BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask)
+{
+ // which row was clicked on?
+ LLScrollListItem* hit_item = hitItem(x, y);
+ if (!hit_item) return FALSE;
+
+ // get appropriate cell from that row
+ S32 column_index = getColumnIndexFromOffset(x);
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (!hit_cell) return FALSE;
+
+ // select item (thus deselecting any currently selected item)
+ // only if item is not already selected
+ if (!hit_item->getSelected())
+ {
+ selectItemAt(x, y, mask);
+ gFocusMgr.setMouseCapture(this);
+ mNeedsScroll = TRUE;
+ }
+
+ if (hit_cell->handleClick())
+ {
+ // propagate value of this cell to other selected items
+ // and commit the respective widgets
+ LLSD item_value = hit_cell->getValue();
+ for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ {
+ LLScrollListItem* item = *iter;
+ if (item->getSelected())
+ {
+ LLScrollListCell* cellp = item->getColumn(column_index);
+ cellp->setValue(item_value);
+ cellp->onCommit();
+ }
+ }
+ //FIXME: find a better way to signal cell changes
+ onCommit();
+ return TRUE;
+ }
+ else
+ {
+ // treat this as a normal single item selection
+ selectItemAt(x, y, mask);
+ gFocusMgr.setMouseCapture(this);
+ mNeedsScroll = TRUE;
+ // do not stop click processing (click callback, etc)
+ return FALSE;
+ }
+}
+
LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
{
// Excludes disabled items.
@@ -1847,6 +2037,59 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
return hit_item;
}
+S32 LLScrollListCtrl::getColumnIndexFromOffset(S32 x)
+{
+ // which column did we hit?
+ S32 left = 0;
+ S32 right = 0;
+ S32 width = 0;
+ S32 column_index = 0;
+
+ ordered_columns_t::const_iterator iter = mColumnsIndexed.begin();
+ ordered_columns_t::const_iterator end = mColumnsIndexed.end();
+ for ( ; iter != end; ++iter)
+ {
+ width = (*iter)->mWidth + mColumnPadding;
+ right += width;
+ if (left <= x && x < right )
+ {
+ break;
+ }
+
+ // set left for next column as right of current column
+ left = right;
+ column_index++;
+ }
+
+ return llclamp(column_index, 0, getNumColumns() - 1);
+}
+
+
+S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index)
+{
+ S32 column_offset = 0;
+ ordered_columns_t::const_iterator iter = mColumnsIndexed.begin();
+ ordered_columns_t::const_iterator end = mColumnsIndexed.end();
+ for ( ; iter != end; ++iter)
+ {
+ if (index-- <= 0)
+ {
+ return column_offset;
+ }
+ column_offset += (*iter)->mWidth + mColumnPadding;
+ }
+
+ // when running off the end, return the rightmost pixel
+ return mItemListRect.mRight;
+}
+
+S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index)
+{
+ S32 row_bottom = ((mItemListRect.mTop - (index - mScrollLines)) * mLineHeight)
+ - mLineHeight;
+ return row_bottom;
+}
+
BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
{
@@ -1860,7 +2103,8 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
mNeedsScroll = TRUE;
}
}
- else if (mCanSelect)
+ else
+ if (mCanSelect)
{
LLScrollListItem* item = hitItem(x, y);
if (item)
@@ -1875,13 +2119,6 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
handled = LLUICtrl::handleHover( x, y, mask );
- //if( !handled )
- //{
- // // Opaque
- // getWindow()->setCursor(UI_CURSOR_ARROW);
- // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- // handled = TRUE;
- //}
return handled;
}
@@ -2082,7 +2319,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
if (cellp)
{
// Only select enabled items with matching first characters
- LLWString item_label = utf8str_to_wstring(cellp->getText());
+ LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
selectItem(item);
@@ -2176,7 +2413,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp)
LLScrollListCell* cellp = itemp->getColumn(mSearchColumn);
if (cellp)
{
- cellp->highlightText(0, 0);
+ cellp->highlightText(0, 0);
}
mSelectionChanged = TRUE;
}
@@ -2202,38 +2439,52 @@ BOOL LLScrollListCtrl::isSorted()
return mSorted;
}
-// Called by scrollbar
-//static
-void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
+struct SameSortColumn
{
- LLScrollListCtrl* self = (LLScrollListCtrl*) userdata;
- self->mScrollLines = new_pos;
-}
+ SameSortColumn(S32 column) : mColumn(column) {}
+ S32 mColumn;
+ bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; }
+};
-// First column is column 0
-void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
+BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending)
{
- if (!mSorted || mSortColumn != column)
+ sort_column_t new_sort_column(column, ascending);
+
+ if (mSortColumns.empty())
{
- mSortColumn = column;
- std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
- setSorted(TRUE);
+ mSortColumns.push_back(new_sort_column);
+ return TRUE;
}
+ else
+ {
+ // grab current sort column
+ sort_column_t cur_sort_column = mSortColumns.back();
+
+ // remove any existing sort criterion referencing this column
+ // and add the new one
+ remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column));
+ mSortColumns.push_back(new_sort_column);
- // just reverse the list if changing sort order
- if(mSortAscending != ascending)
- {
- std::reverse(mItemList.begin(), mItemList.end());
- mSortAscending = ascending;
+ // did the sort criteria change?
+ return (cur_sort_column != new_sort_column);
}
}
+// Called by scrollbar
+//static
+void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
+{
+ LLScrollListCtrl* self = (LLScrollListCtrl*) userdata;
+ self->mScrollLines = new_pos;
+}
+
+
void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending)
{
if (name.empty())
{
- sortByColumn(mSortColumn, mSortAscending);
+ sortItems();
return;
}
@@ -2244,6 +2495,26 @@ void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending)
}
}
+// First column is column 0
+void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
+{
+ if (setSort(column, ascending))
+ {
+ sortItems();
+ }
+}
+
+void LLScrollListCtrl::sortItems()
+{
+ // do stable sort to preserve any previous sorts
+ std::stable_sort(
+ mItemList.begin(),
+ mItemList.end(),
+ SortScrollListItem(mSortColumns));
+
+ setSorted(TRUE);
+}
+
S32 LLScrollListCtrl::getScrollPos()
{
return mScrollbar->getDocPos();
@@ -2465,7 +2736,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
LLSD columns;
S32 index = 0;
LLXMLNodePtr child;
- S32 total_static = 0, num_dynamic = 0;
+ S32 total_static = 0;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
if (child->hasName("column"))
@@ -2491,8 +2762,10 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
S32 columnwidth = -1;
child->getAttributeS32("width", columnwidth);
+ LLString tooltip;
+ child->getAttributeString("tool_tip", tooltip);
+
if(!columndynamicwidth) total_static += columnwidth;
- else ++num_dynamic;
F32 columnrelwidth = 0.f;
child->getAttributeF32("relwidth", columnrelwidth);
@@ -2509,10 +2782,11 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
columns[index]["relwidth"] = columnrelwidth;
columns[index]["dynamicwidth"] = columndynamicwidth;
columns[index]["halign"] = (S32)h_align;
+ columns[index]["tool_tip"] = tooltip;
+
index++;
}
}
- scroll_list->setNumDynamicColumns(num_dynamic);
scroll_list->setTotalStaticColumnWidth(total_static);
scroll_list->setColumnHeadings(columns);
@@ -2665,7 +2939,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
LLString name = column["name"].asString();
if (mColumns.empty())
{
- mDefaultColumn = 0;
+ mDefaultColumnName = name;
}
// if no column name provided, just use ordinal as name
if (name.empty())
@@ -2691,6 +2965,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
}
else if(new_column->mDynamicWidth)
{
+ mNumDynamicWidthColumns++;
new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
}
S32 top = mItemListRect.mTop;
@@ -2724,17 +2999,16 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
new_column->mHeader->setLabel(new_column->mLabel);
//new_column->mHeader->setLabel(new_column->mLabel);
}
+
+ new_column->mHeader->setToolTip(column["tool_tip"].asString());
+
//RN: although it might be useful to change sort order with the keyboard,
// mixing tab stops on child items along with the parent item is not supported yet
new_column->mHeader->setTabStop(FALSE);
addChild(new_column->mHeader);
new_column->mHeader->setVisible(mDisplayColumnHeaders);
-
- // Move scroll to front
- removeChild(mScrollbar);
- addChild(mScrollbar);
-
+ sendChildToFront(mScrollbar);
}
}
updateColumns();
@@ -2753,18 +3027,18 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
bool ascending = column->mSortAscending;
- if (column->mSortingColumn != column->mName)
+ if (column->mSortingColumn != column->mName
+ && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
{
- if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
- {
- LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn];
- column_index = info_redir.mIndex;
- }
+ LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn];
+ column_index = info_redir.mIndex;
}
- if (column_index == parent->mSortColumn)
+ // if this column is the primary sort key, reverse the direction
+ sort_column_t cur_sort_column;
+ if (!parent->mSortColumns.empty() && parent->mSortColumns.back().first == column_index)
{
- ascending = !parent->mSortAscending;
+ ascending = !parent->mSortColumns.back().second;
}
parent->sortByColumn(column_index, ascending);
@@ -2777,12 +3051,17 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
std::string LLScrollListCtrl::getSortColumnName()
{
- LLScrollListColumn* column = mSortColumn >= 0 ? mColumnsIndexed[mSortColumn] : NULL;
+ LLScrollListColumn* column = mSortColumns.empty() ? NULL : mColumnsIndexed[mSortColumns.back().first];
if (column) return column->mName;
else return "";
}
+BOOL LLScrollListCtrl::needsSorting()
+{
+ return !mSortColumns.empty();
+}
+
void LLScrollListCtrl::clearColumns()
{
std::map<LLString, LLScrollListColumn>::iterator itor;
@@ -2796,6 +3075,7 @@ void LLScrollListCtrl::clearColumns()
}
}
mColumns.clear();
+ mSortColumns.clear();
}
void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& label)
@@ -2851,11 +3131,6 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
{
LLString column = (*itor)["column"].asString();
- if (mColumns.size() == 0)
- {
- mDefaultColumn = 0;
- }
-
LLScrollListColumn* columnp = NULL;
// empty columns strings index by ordinal
@@ -2895,6 +3170,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
LLString type = (*itor)["type"].asString();
BOOL has_color = (*itor).has("color");
LLColor4 color = ((*itor)["color"]);
+ BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true;
const LLFontGL *font = gResMgr->getRes(fontname);
if (!font)
@@ -2906,7 +3182,8 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
if (type == "icon")
{
LLUUID image_id = value.asUUID();
- LLImageGL* icon = LLUI::sImageProvider->getUIImageByID(image_id);
+ // don't use special image with UUID::null, just don't draw an image
+ LLImageGL* icon = image_id.isNull() ? NULL : LLUI::sImageProvider->getImageByID(image_id);
LLScrollListIcon* cell = new LLScrollListIcon(icon, width, image_id);
if (has_color)
{
@@ -2916,8 +3193,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
}
else if (type == "checkbox")
{
- LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(value.asString(),
- LLRect(0, 0, width, width), "label");
+ LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl("check",
+ LLRect(0, width, width, 0), " ");
+ ctrl->setEnabled(enabled);
+ ctrl->setValue(value);
LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width);
if (has_color)
{
@@ -3070,18 +3349,12 @@ void LLScrollListCtrl::onFocusReceived()
{
// forget latent selection changes when getting focus
mSelectionChanged = FALSE;
+ LLUICtrl::onFocusReceived();
}
//virtual
void LLScrollListCtrl::onFocusLost()
{
- if (mIsPopup)
- {
- if (getParent())
- {
- getParent()->onFocusLost();
- }
- }
if (hasMouseCapture())
{
gFocusMgr.setMouseCapture(NULL);
@@ -3133,11 +3406,11 @@ void LLColumnHeader::draw()
{
if( getVisible() )
{
- mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
+ BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
- mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga")))
- : LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("down_arrow.tga")));
+ mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent);
+ mArrowImage = mButton->getImageOverlay()->getImage();
//BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth();
//LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE);
@@ -3237,11 +3510,11 @@ void LLColumnHeader::showList()
{
if (mColumn->mParentCtrl->getSortAscending())
{
- low_item_text = cell->getText();
+ low_item_text = cell->getValue().asString();
}
else
{
- high_item_text = cell->getText();
+ high_item_text = cell->getValue().asString();
}
}
}
@@ -3254,11 +3527,11 @@ void LLColumnHeader::showList()
{
if (mColumn->mParentCtrl->getSortAscending())
{
- high_item_text = cell->getText();
+ high_item_text = cell->getValue().asString();
}
else
{
- low_item_text = cell->getText();
+ low_item_text = cell->getValue().asString();
}
}
}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index a98a411efa..001e10184b 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -59,14 +59,16 @@ public:
virtual ~LLScrollListCell() {};
virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible
virtual S32 getWidth() const = 0;
+ virtual S32 getContentWidth() const { return 0; }
virtual S32 getHeight() const = 0;
- virtual const LLString& getText() const { return LLString::null; }
- virtual const LLString& getTextLower() const { return LLString::null; }
+ virtual const LLSD getValue() const { return LLString::null; }
+ virtual void setValue(LLSD value) { }
virtual BOOL getVisible() const { return TRUE; }
virtual void setWidth(S32 width) = 0;
virtual void highlightText(S32 offset, S32 num_chars) {}
virtual BOOL isText() = 0;
virtual void setColor(const LLColor4&) = 0;
+ virtual void onCommit() {};
virtual BOOL handleClick() { return FALSE; }
virtual void setEnabled(BOOL enable) { }
@@ -96,20 +98,24 @@ public:
virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;
virtual S32 getWidth() const { return mWidth; }
+ virtual S32 getContentWidth() const;
virtual void setWidth(S32 width) { mWidth = width; }
virtual S32 getHeight() const { return llround(mFont->getLineHeight()); }
- virtual const LLString& getText() const { return mText.getString(); }
+ virtual const LLSD getValue() const { return LLSD(mText.getString()); }
virtual BOOL getVisible() const { return mVisible; }
virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;}
- void setText(const LLStringExplicit& text);
+
virtual void setColor(const LLColor4&);
virtual BOOL isText() { return TRUE; }
+ void setText(const LLStringExplicit& text);
+ void setFontStyle(const U8 font_style) { mFontStyle = font_style; }
+
private:
LLUIString mText;
const LLFontGL* mFont;
LLColor4* mColor;
- const U8 mFontStyle;
+ U8 mFontStyle;
LLFontGL::HAlign mFontAlignment;
S32 mWidth;
BOOL mVisible;
@@ -128,16 +134,16 @@ public:
/*virtual*/ ~LLScrollListIcon();
virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const;
virtual S32 getWidth() const { return mWidth; }
- virtual S32 getHeight() const { return mIcon->getHeight(); }
- virtual const LLString& getText() const { return mImageUUID; }
- virtual const LLString& getTextLower() const { return mImageUUID; }
+ virtual S32 getHeight() const { return mIcon ? mIcon->getHeight() : 0; }
+ virtual const LLSD getValue() const { return LLSD(mImageUUID); }
virtual void setWidth(S32 width) { mWidth = width; }
virtual void setColor(const LLColor4&);
virtual BOOL isText() { return FALSE; }
+ virtual void setValue(LLSD value);
private:
LLPointer<LLImageGL> mIcon;
- LLString mImageUUID;
+ LLUUID mImageUUID;
S32 mWidth;
LLColor4 mColor;
};
@@ -151,9 +157,12 @@ public:
virtual S32 getWidth() const { return mWidth; }
virtual S32 getHeight() const { return 0; }
virtual void setWidth(S32 width) { mWidth = width; }
+ virtual const LLSD getValue() const { return mCheckBox->getValue(); }
+ virtual void setValue(LLSD value) { mCheckBox->setValue(value); }
+ virtual void onCommit() { mCheckBox->onCommit(); }
virtual BOOL handleClick();
- virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); }
+ virtual void setEnabled(BOOL enable) { mCheckBox->setEnabled(enable); }
virtual void setColor(const LLColor4& color) {};
LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
@@ -266,6 +275,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+
/*virtual*/ void showList();
/*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
/*virtual*/ void userSetShape(const LLRect& new_rect);
@@ -333,8 +343,6 @@ public:
LLScrollListCell *getColumn(const S32 i) const { if (0 <= i && i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; }
- virtual BOOL handleClick(S32 x, S32 y, MASK mask);
-
LLString getContentsCSV();
private:
@@ -370,9 +378,8 @@ public:
void deleteAllItems() { clearRows(); }
// Sets an array of column descriptors
- void setColumnHeadings(LLSD headings);
- // Numerical based sort by column function (used by LLComboBox)
- void sortByColumn(U32 column, BOOL ascending);
+ void setColumnHeadings(LLSD headings);
+ void sortByColumn(U32 column, BOOL ascending);
// LLCtrlListInterface functions
virtual S32 getItemCount() const;
@@ -421,18 +428,20 @@ public:
BOOL isSorted();
virtual BOOL isSelected(LLSD value);
-
+
+ BOOL handleClick(S32 x, S32 y, MASK mask);
BOOL selectFirstItem();
BOOL selectNthItem( S32 index );
BOOL selectItemAt(S32 x, S32 y, MASK mask);
- void deleteSingleItem( S32 index ) ;
+ void deleteSingleItem( S32 index );
+ void deleteItems(const LLSD& sd);
void deleteSelectedItems();
void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change
void highlightNthItem( S32 index );
void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; }
- void setMaxiumumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; }
+ void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; }
void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; }
void swapWithNext(S32 index);
@@ -449,11 +458,12 @@ public:
LLScrollListItem* addSimpleItem( const LLString& item_text, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE );
// Add an item with an associated LLSD
LLScrollListItem* addSimpleItem(const LLString& item_text, LLSD sd, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0 );
+ LLScrollListItem* addSeparator(EAddPosition pos);
BOOL selectSimpleItem( const LLString& item, BOOL case_sensitive = TRUE ); // FALSE if item not found
BOOL selectSimpleItemByPrefix(const LLString& target, BOOL case_sensitive);
BOOL selectSimpleItemByPrefix(const LLWString& target, BOOL case_sensitive);
- const LLString& getSimpleSelectedItem(S32 column = 0) const;
+ const LLString getSimpleSelectedItem(S32 column = 0) const;
LLSD getSimpleSelectedValue();
// DEPRECATED: Use LLSD versions of addSimpleItem() and getSimpleSelectedValue().
@@ -472,6 +482,8 @@ public:
LLScrollListItem* getFirstData() const;
LLScrollListItem* getLastData() const;
std::vector<LLScrollListItem*> getAllData() const;
+
+ LLScrollListItem* getItem(const LLSD& sd) const;
void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; }
@@ -501,28 +513,34 @@ public:
S32 getSearchColumn() { return mSearchColumn; }
void setSearchColumn(S32 column) { mSearchColumn = column; }
+ S32 getColumnIndexFromOffset(S32 x);
+ S32 getColumnOffsetFromIndex(S32 index);
+ S32 getRowOffsetFromIndex(S32 index);
void clearSearchString() { mSearchString.clear(); }
// Overridden from LLView
- virtual void draw();
- virtual BOOL handleMouseDown(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 BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
- virtual BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- virtual void setEnabled(BOOL enabled);
- virtual void setFocus( BOOL b );
- virtual void onFocusReceived();
- virtual void onFocusLost();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleMouseDown(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*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
+ /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect);
+ /*virtual*/ void setEnabled(BOOL enabled);
+ /*virtual*/ void setFocus( BOOL b );
+ /*virtual*/ void onFocusReceived();
+ /*virtual*/ void onFocusLost();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual BOOL isDirty() const;
virtual void resetDirty(); // Clear dirty state
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- virtual void arrange(S32 max_width, S32 max_height);
+ virtual void updateLayout();
+ virtual void fitContents(S32 max_width, S32 max_height);
+
virtual LLRect getRequiredRect();
static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row);
@@ -534,12 +552,12 @@ public:
static void onClickColumn(void *userdata);
void updateColumns();
- void updateMaxContentWidth(LLScrollListItem* changed_item);
+ void calcMaxContentWidth(LLScrollListItem* changed_item);
+ S32 getMaxContentWidth() { return mMaxContentWidth; }
void setDisplayHeading(BOOL display);
void setHeadingHeight(S32 heading_height);
void setCollapseEmptyColumns(BOOL collapse);
- void setIsPopup(BOOL is_popup) { mIsPopup = is_popup; }
LLScrollListItem* hitItem(S32 x,S32 y);
virtual void scrollToShowSelected();
@@ -564,9 +582,11 @@ public:
void setTotalStaticColumnWidth(int width) { mTotalStaticColumnWidth = width; }
std::string getSortColumnName();
- BOOL getSortAscending() { return mSortAscending; }
+ BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
+ BOOL needsSorting();
S32 selectMultiple( LLDynamicArray<LLUUID> ids );
+ void sortItems();
protected:
// "Full" interface: use this when you're creating a list that has one or more of the following:
@@ -596,6 +616,7 @@ protected:
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
void setSorted(BOOL sorted);
+ BOOL setSort(S32 column, BOOL ascending);
protected:
S32 mCurIndex; // For get[First/Next]Data
@@ -616,7 +637,6 @@ protected:
BOOL mCanSelect;
BOOL mDisplayColumnHeaders;
BOOL mCollapseEmptyColumns;
- BOOL mIsPopup;
typedef std::deque<LLScrollListItem *> item_list;
item_list mItemList;
@@ -626,7 +646,7 @@ protected:
S32 mMaxItemCount;
LLRect mItemListRect;
-
+ S32 mMaxContentWidth;
S32 mColumnPadding;
BOOL mBackgroundVisible;
@@ -652,22 +672,29 @@ protected:
LLWString mSearchString;
LLFrameTimer mSearchTimer;
- LLString mDefaultColumn;
+ LLString mDefaultColumnName;
S32 mSearchColumn;
S32 mNumDynamicWidthColumns;
S32 mTotalStaticColumnWidth;
S32 mSortColumn;
+ S32 mSecondarySortColumn;
+ BOOL mSecondarySortAscending;
BOOL mSortAscending;
BOOL mSorted;
-
+
std::map<LLString, LLScrollListColumn> mColumns;
- std::vector<LLScrollListColumn*> mColumnsIndexed;
BOOL mDirty;
S32 mOriginalSelection;
+ typedef std::vector<LLScrollListColumn*> ordered_columns_t;
+ ordered_columns_t mColumnsIndexed;
+
+ typedef std::pair<S32, BOOL> sort_column_t;
+ std::vector<sort_column_t> mSortColumns;
+
public:
// HACK: Did we draw one selected item this frame?
BOOL mDrewSelected;
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 29626c25d6..bd91d562aa 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -41,9 +41,6 @@
#include "llcontrol.h"
#include "llimagegl.h"
-const S32 THUMB_WIDTH = 8;
-const S32 TRACK_HEIGHT = 6;
-
LLSlider::LLSlider(
const LLString& name,
const LLRect& rect,
@@ -65,20 +62,24 @@ LLSlider::LLSlider(
mIncrement( increment ),
mVolumeSlider( volume ),
mMouseOffset( 0 ),
- mDragStartThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
- mThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ),
mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ),
mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ),
- mDisabledThumbColor(LLUI::sColorsGroup->getColor( "SliderDisabledThumbColor" ) ),
mMouseDownCallback( NULL ),
mMouseUpCallback( NULL )
{
+ mThumbImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-thumb_dark.tga")));
+ mTrackImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-groove_dark.tga")));
+ mTrackHighlightImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-highlight.tga")));
+
// properly handle setting the starting thumb rect
// do it this way to handle both the operating-on-settings
// and standalone ways of using this
setControlName(control_name, NULL);
setValue(getValueF32());
+
+ updateThumbRect();
+ mDragStartThumbRect = mThumbRect;
}
EWidgetType LLSlider::getWidgetType() const
@@ -107,17 +108,26 @@ void LLSlider::setValue(F32 value, BOOL from_event)
}
mValue = value;
+ updateThumbRect();
+}
+void LLSlider::updateThumbRect()
+{
F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
- S32 left_edge = THUMB_WIDTH/2;
- S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2);
+ S32 thumb_width = mThumbImage->getWidth();
+ S32 thumb_height = mThumbImage->getHeight();
+ S32 left_edge = (thumb_width / 2);
+ S32 right_edge = mRect.getWidth() - (thumb_width / 2);
S32 x = left_edge + S32( t * (right_edge - left_edge) );
- mThumbRect.mLeft = x - (THUMB_WIDTH/2);
- mThumbRect.mRight = x + (THUMB_WIDTH/2);
+ mThumbRect.mLeft = x - (thumb_width / 2);
+ mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
+ mThumbRect.mBottom = getLocalRect().getCenterY() - (thumb_height / 2);
+ mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
}
+
void LLSlider::setValueAndCommit(F32 value)
{
F32 old_value = mValue;
@@ -139,8 +149,9 @@ BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
{
if( hasMouseCapture() )
{
- S32 left_edge = THUMB_WIDTH/2;
- S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2);
+ S32 thumb_half_width = mThumbImage->getWidth()/2;
+ S32 left_edge = thumb_half_width;
+ S32 right_edge = mRect.getWidth() - (thumb_half_width);
x += mMouseOffset;
x = llclamp( x, left_edge, right_edge );
@@ -203,7 +214,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
// Find the offset of the actual mouse location from the center of the thumb.
if (mThumbRect.pointInRect(x,y))
{
- mMouseOffset = (mThumbRect.mLeft + THUMB_WIDTH/2) - x;
+ mMouseOffset = (mThumbRect.mLeft + mThumbImage->getWidth()/2) - x;
}
else
{
@@ -251,6 +262,9 @@ void LLSlider::draw()
{
if( getVisible() )
{
+ // since thumb image might still be decoding, need thumb to accomodate image size
+ updateThumbRect();
+
// Draw background and thumb.
// drawing solids requires texturing be disabled
@@ -260,104 +274,37 @@ void LLSlider::draw()
F32 opacity = mEnabled ? 1.f : 0.3f;
LLColor4 center_color = (mThumbCenterColor % opacity);
- LLColor4 outline_color = (mThumbOutlineColor % opacity);
LLColor4 track_color = (mTrackColor % opacity);
- LLImageGL* thumb_imagep = NULL;
-
// Track
- if (mVolumeSlider)
- {
- LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0);
-
- track.mBottom += 3;
- track.mTop -= 1;
- track.mRight -= 1;
-
- gl_triangle_2d(track.mLeft, track.mBottom,
- track.mRight, track.mBottom,
- track.mRight, track.mTop,
- center_color,
- TRUE);
- gl_triangle_2d(track.mLeft, track.mBottom,
- track.mRight, track.mBottom,
- track.mRight, track.mTop,
- outline_color,
- FALSE);
- }
- else
- {
- LLUUID thumb_image_id;
- thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
- thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
+ LLRect track_rect(mThumbImage->getWidth() / 2,
+ getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
+ mRect.getWidth() - mThumbImage->getWidth() / 2,
+ getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
- S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
- LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
+ gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 3, 3, track_rect.getWidth(), track_rect.getHeight(),
+ mTrackImage, track_color);
+ gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 3, 3, mThumbRect.mLeft, track_rect.getHeight(),
+ mTrackHighlightImage, track_color);
- track_rect.stretch(-1);
- gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
- thumb_imagep, track_color);
- }
// Thumb
- if (!thumb_imagep)
- {
- if (mVolumeSlider)
- {
- if (hasMouseCapture())
- {
- LLRect rect(mDragStartThumbRect);
- gl_rect_2d( rect, outline_color );
- rect.stretch(-1);
- gl_rect_2d( rect, mThumbCenterColor % 0.3f );
-
- if (hasFocus())
- {
- LLRect thumb_rect = mThumbRect;
- thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
- gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
- }
- gl_rect_2d( mThumbRect, mThumbOutlineColor );
- }
- else
- {
- if (hasFocus())
- {
- LLRect thumb_rect = mThumbRect;
- thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
- gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
- }
- LLRect rect(mThumbRect);
- gl_rect_2d(rect, outline_color);
- rect.stretch(-1);
- gl_rect_2d( rect, center_color);
- }
- }
- else
- {
- gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
- if (hasMouseCapture())
- {
- gl_rect_2d(mDragStartThumbRect, center_color, FALSE);
- }
- }
- }
- else if( hasMouseCapture() )
+ if( hasMouseCapture() )
{
- gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
- thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
+ gl_draw_scaled_image(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
+ mThumbImage, mThumbCenterColor % 0.3f);
if (hasFocus())
{
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
- gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 0, 0, highlight_rect.getWidth(), highlight_rect.getHeight(),
+ mThumbImage, gFocusMgr.getFocusColor(), TRUE);
}
- gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, mThumbOutlineColor, TRUE);
+ gl_draw_scaled_image(mThumbRect.mLeft, mThumbRect.mBottom, mThumbRect.getWidth(), mThumbRect.getHeight(),
+ mThumbImage, mThumbOutlineColor);
}
else
@@ -367,12 +314,12 @@ void LLSlider::draw()
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
- gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 0, 0, highlight_rect.getWidth(), highlight_rect.getHeight(),
+ mThumbImage, gFocusMgr.getFocusColor(), TRUE);
}
- gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, center_color, TRUE);
+ gl_draw_scaled_image(mThumbRect.mLeft, mThumbRect.mBottom, mThumbRect.getWidth(), mThumbRect.getHeight(),
+ mThumbImage, center_color);
}
LLUICtrl::draw();
}
diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h
index 2641eaac74..55be2afbcc 100644
--- a/indra/llui/llslider.h
+++ b/indra/llui/llslider.h
@@ -36,6 +36,7 @@
#include "v4color.h"
class LLUICtrlFactory;
+class LLImageGL;
class LLSlider : public LLUICtrl
{
@@ -85,6 +86,7 @@ public:
protected:
void setValueAndCommit(F32 value);
+ void updateThumbRect();
protected:
F32 mValue;
@@ -97,11 +99,14 @@ protected:
S32 mMouseOffset;
LLRect mDragStartThumbRect;
+ LLImageGL* mThumbImage;
+ LLImageGL* mTrackImage;
+ LLImageGL* mTrackHighlightImage;
+
LLRect mThumbRect;
LLColor4 mTrackColor;
LLColor4 mThumbOutlineColor;
LLColor4 mThumbCenterColor;
- LLColor4 mDisabledThumbColor;
void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata);
void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata);
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index dd4a9941c5..3ff3a4f884 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -125,7 +125,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
&LLLineEditor::prevalidateFloat );
mEditor->setFollowsLeft();
mEditor->setFollowsBottom();
- mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus );
+ mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus, this );
mEditor->setIgnoreTab(TRUE);
// don't do this, as selecting the entire text is single clicking in some cases
// and double clicking in others
@@ -150,7 +150,7 @@ LLSliderCtrl::~LLSliderCtrl()
}
// static
-void LLSliderCtrl::onEditorGainFocus( LLUICtrl* caller, void *userdata )
+void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
{
LLSliderCtrl* self = (LLSliderCtrl*) userdata;
llassert( caller == self->mEditor );
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index fa6c0bccae..de1c09639c 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -117,7 +117,7 @@ public:
static void onSliderMouseUp(LLUICtrl* caller,void* userdata);
static void onEditorCommit(LLUICtrl* caller, void* userdata);
- static void onEditorGainFocus(LLUICtrl* caller, void *userdata);
+ static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
private:
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 2be2814080..c4b7de768a 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -128,7 +128,7 @@ LLSpinCtrl::LLSpinCtrl( const LLString& name, const LLRect& rect, const LLString
&LLLineEditor::prevalidateFloat );
mEditor->setFollowsLeft();
mEditor->setFollowsBottom();
- mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus );
+ mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus, this );
//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
@@ -137,7 +137,7 @@ LLSpinCtrl::LLSpinCtrl( const LLString& name, const LLRect& rect, const LLString
addChild(mEditor);
updateEditor();
- setSpanChildren( TRUE );
+ setUseBoundingRect( TRUE );
}
LLSpinCtrl::~LLSpinCtrl()
@@ -230,7 +230,7 @@ void LLSpinCtrl::onDownBtn( void *userdata )
}
// static
-void LLSpinCtrl::onEditorGainFocus( LLUICtrl* caller, void *userdata )
+void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
{
LLSpinCtrl* self = (LLSpinCtrl*) userdata;
llassert( caller == self->mEditor );
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index f2c7b40cfe..5fc3ccdcc1 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -113,7 +113,7 @@ public:
virtual void draw();
static void onEditorCommit(LLUICtrl* caller, void* userdata);
- static void onEditorGainFocus(LLUICtrl* caller, void *userdata);
+ static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
static void onUpBtn(void *userdata);
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 1f932f758c..2d3534e7be 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -230,7 +230,7 @@ void LLStyle::setImage(const LLString& src)
}
else
{
- mImagep = LLUI::sImageProvider->getUIImageByID(LLUUID(src));
+ mImagep = LLUI::sImageProvider->getImageByID(LLUUID(src));
}
}
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 1ab11f3644..148060359f 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -156,7 +156,12 @@ void LLTabContainerCommon::lockTabs(S32 num_tabs)
{
// count current tabs or use supplied value and ensure no new tabs get
// inserted between them
- mLockedTabCount = num_tabs > 0 ? num_tabs : getTabCount();
+ mLockedTabCount = num_tabs > 0 ? llmin(getTabCount(), num_tabs) : getTabCount();
+}
+
+void LLTabContainerCommon::unlockTabs()
+{
+ mLockedTabCount = 0;
}
void LLTabContainerCommon::removeTabPanel(LLPanel* child)
@@ -557,7 +562,7 @@ void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name, con
}
void LLTabContainerCommon::setTitle(const LLString& title)
-{
+{
if (mTitleBox)
{
mTitleBox->setText( title );
@@ -721,6 +726,14 @@ void LLTabContainerCommon::insertTuple(LLTabTuple * tuple, eInsertionPoint inser
// insert the new tab in the front of the list
mTabList.insert(mTabList.begin() + mLockedTabCount, tuple);
break;
+ case LEFT_OF_CURRENT:
+ // insert the new tab before the current tab (but not before mLockedTabCount)
+ {
+ tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx);
+ mTabList.insert(current_iter, tuple);
+ }
+ break;
+
case RIGHT_OF_CURRENT:
// insert the new tab after the current tab (but not before mLockedTabCount)
{
@@ -946,14 +959,14 @@ void LLTabContainer::addTabPanel(LLPanel* child,
if( LLTabContainer::TOP == mTabPosition )
{
btn_rect.setLeftTopAndSize( 0, mRect.getHeight() - mTopBorderHeight + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "UIImgBtnTabTopOutUUID";
- tab_selected_img = "UIImgBtnTabTopInUUID";
+ tab_img = "tab_top_blue.tga";
+ tab_selected_img = "tab_top_selected_blue.tga";
}
else
{
btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "UIImgBtnTabBottomOutUUID";
- tab_selected_img = "UIImgBtnTabBottomInUUID";
+ tab_img = "tab_bottom_blue.tga";
+ tab_selected_img = "tab_bottom_selected_blue.tga";
}
if (placeholder)
@@ -979,7 +992,7 @@ void LLTabContainer::addTabPanel(LLPanel* child,
LLButton* btn = new LLButton(
LLString(child->getName()) + " tab",
btn_rect,
- tab_img, tab_selected_img, "",
+ "", "", "",
&LLTabContainer::onTabBtn, NULL, // set userdata below
font,
trimmed_label, trimmed_label );
@@ -987,7 +1000,7 @@ void LLTabContainer::addTabPanel(LLPanel* child,
btn->setVisible( FALSE );
btn->setToolTip( tooltip );
btn->setScaleImage(TRUE);
- btn->setFixedBorder(14, 14);
+ btn->setImages(tab_img, tab_selected_img);
// Try to squeeze in a bit more text
btn->setLeftHPad( 4 );
@@ -1139,7 +1152,7 @@ BOOL LLTabContainer::selectTab(S32 which)
//if( gFocusMgr.childHasKeyboardFocus( this ) )
//{
- // gFocusMgr.setKeyboardFocus( NULL, NULL );
+ // gFocusMgr.setKeyboardFocus( NULL );
//}
LLTabTuple* selected_tuple = mTabList[which];
@@ -1370,7 +1383,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
{
LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
gFocusMgr.setMouseCapture(this);
- gFocusMgr.setKeyboardFocus(tab_button, NULL);
+ gFocusMgr.setKeyboardFocus(tab_button);
}
}
return handled;
@@ -1475,7 +1488,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
{
BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
- if (!handled && mTabList.size() > 0 && getVisible() && pointInView( x, y ) )
+ if (!handled && mTabList.size() > 0)
{
LLTabTuple* firsttuple = mTabList[0];
@@ -1645,12 +1658,12 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getWidth(0) :
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
0;
tuple->mPadding = image_overlay_width;
- tuple->mButton->setRightHPad(tuple->mPadding + LLBUTTON_H_PAD);
+ tuple->mButton->setRightHPad(6);
tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index c77547a771..b72ecb8126 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -54,6 +54,7 @@ public:
{
START,
END,
+ LEFT_OF_CURRENT,
RIGHT_OF_CURRENT
} eInsertionPoint;
@@ -91,6 +92,8 @@ public:
eInsertionPoint insertion_point = END) = 0;
virtual void addPlaceholder(LLPanel* child, const LLString& label);
virtual void lockTabs(S32 num_tabs = 0);
+ virtual void unlockTabs();
+ S32 getNumLockedTabs() { return mLockedTabCount; }
virtual void enableTabButton(S32 which, BOOL enable);
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 8bd7b1509f..3b15e3a25f 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -56,6 +56,7 @@ LLTextBox::LLTextBox(const LLString& name, const LLRect& rect, const LLString& t
mBorderVisible( FALSE ),
mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
mBorderDropShadowVisible( FALSE ),
+ mUseEllipses( FALSE ),
mHPad(0),
mVPad(0),
mHAlign( LLFontGL::LEFT ),
@@ -84,6 +85,7 @@ LLTextBox::LLTextBox(const LLString& name, const LLString& text, F32 max_width,
mBorderVisible(FALSE),
mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
mBorderDropShadowVisible(FALSE),
+ mUseEllipses( FALSE ),
mHPad(0),
mVPad(0),
mHAlign(LLFontGL::LEFT),
@@ -393,7 +395,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
mHAlign, mVAlign,
mFontStyle,
- line_length, mRect.getWidth(), NULL, TRUE );
+ line_length, mRect.getWidth(), NULL, TRUE, mUseEllipses );
cur_pos += line_length + 1;
y -= llfloor(mFontGL->getLineHeight());
}
@@ -403,7 +405,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
mHAlign, mVAlign,
mFontStyle,
- S32_MAX, mRect.getWidth(), NULL, TRUE);
+ S32_MAX, mRect.getWidth(), NULL, TRUE, mUseEllipses);
}
}
@@ -481,7 +483,7 @@ LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
}
- BOOL mouse_opaque;
+ BOOL mouse_opaque = text_box->getMouseOpaque();
if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
{
text_box->setMouseOpaque(mouse_opaque);
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index c7c79464a0..d25452b941 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -79,6 +79,7 @@ public:
void setText( const LLStringExplicit& text );
void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.0);
// default width means use existing control width
+ void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
@@ -124,6 +125,7 @@ protected:
U8 mFontStyle; // style bit flags for font
BOOL mBorderDropShadowVisible;
+ BOOL mUseEllipses;
S32 mHPad;
S32 mVPad;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 5c8b7c7281..8b9353eb8e 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -310,9 +310,9 @@ LLTextEditor::LLTextEditor(
mWordWrap( FALSE ),
mTabToNextField( TRUE ),
mCommitOnFocusLost( FALSE ),
- mTakesFocus( TRUE ),
mHideScrollbarForShortDocs( FALSE ),
mTakesNonScrollClicks( TRUE ),
+ mTrackBottom( TRUE ),
mAllowEmbeddedItems( allow_embedded_items ),
mAcceptCallingCardNames(FALSE),
mHandleEditKeysDirectly( FALSE ),
@@ -1141,46 +1141,42 @@ void LLTextEditor::selectAll()
BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
{
- if (pointInView(x, y) && getVisible())
+ for ( child_list_const_iter_t child_it = getChildList()->begin();
+ child_it != getChildList()->end(); ++child_it)
{
- for ( child_list_const_iter_t child_it = getChildList()->begin();
- child_it != getChildList()->end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- return TRUE;
- }
- }
-
- if( mSegments.empty() )
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
{
return TRUE;
}
+ }
- LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
- {
- BOOL has_tool_tip = FALSE;
- has_tool_tip = cur_segment->getToolTip( msg );
+ if( mSegments.empty() )
+ {
+ return TRUE;
+ }
- if( has_tool_tip )
- {
- // Just use a slop area around the cursor
- // Convert rect local to screen coordinates
- S32 SLOP = 8;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
- }
+ LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
+ if( cur_segment )
+ {
+ BOOL has_tool_tip = FALSE;
+ has_tool_tip = cur_segment->getToolTip( msg );
+
+ if( has_tool_tip )
+ {
+ // Just use a slop area around the cursor
+ // Convert rect local to screen coordinates
+ S32 SLOP = 8;
+ localPointToScreen(
+ x - SLOP, y - SLOP,
+ &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
+ sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
+ sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
}
- return TRUE;
}
- return FALSE;
+ return TRUE;
}
BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks)
@@ -1263,7 +1259,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
handled = TRUE;
}
- if (mTakesFocus)
+ if (hasTabStop())
{
setFocus( TRUE );
handled = TRUE;
@@ -1436,11 +1432,6 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
if( !handled && mTakesNonScrollClicks)
{
- if (mTakesFocus)
- {
- setFocus( TRUE );
- }
-
setCursorAtLocalPos( x, y, FALSE );
deselect();
@@ -3160,6 +3151,9 @@ void LLTextEditor::draw()
}
LLView::draw(); // Draw children (scrollbar and border)
}
+
+ // remember if we are supposed to be at the bottom of the buffer
+ mScrolledToBottom = isScrolledToBottom();
}
void LLTextEditor::reportBadKeystroke()
@@ -3328,6 +3322,17 @@ void LLTextEditor::changeLine( S32 delta )
unbindEmbeddedChars( mGLFont );
}
+BOOL LLTextEditor::isScrolledToTop()
+{
+ return mScrollbar->isAtBeginning();
+}
+
+BOOL LLTextEditor::isScrolledToBottom()
+{
+ return mScrollbar->isAtEnd();
+}
+
+
void LLTextEditor::startOfLine()
{
S32 line, offset;
@@ -3448,6 +3453,13 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLView::reshape( width, height, called_from_parent );
+ // if scrolled to bottom, stay at bottom
+ // unless user is editing text
+ if (mScrolledToBottom && mTrackBottom && !hasFocus())
+ {
+ endOfDoc();
+ }
+
updateTextRect();
S32 line_height = llround( mGLFont->getLineHeight() );
@@ -4234,6 +4246,8 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
node->getAttributeBOOL("word_wrap", word_wrap);
setWordWrap(word_wrap);
+ node->getAttributeBOOL("track_bottom", mTrackBottom);
+
LLColor4 color;
if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
{
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 7049de7b89..a2ce0d2c47 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -206,13 +206,13 @@ public:
void setTabToNextField(BOOL b) { mTabToNextField = b; }
void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
- // If takes focus, will take keyboard focus on click.
- void setTakesFocus(BOOL b) { mTakesFocus = b; }
-
// Hack to handle Notecards
virtual BOOL importBuffer(const LLString& buffer );
virtual BOOL exportBuffer(LLString& buffer );
+ // If takes focus, will take keyboard focus on click.
+ void setTakesFocus(BOOL b) { mTakesFocus = b; }
+
void setSourceID(const LLUUID& id) { mSourceID = id; }
void setAcceptCallingCardNames(BOOL enable) { mAcceptCallingCardNames = enable; }
@@ -244,7 +244,10 @@ public:
void startOfLine();
void endOfLine();
void endOfDoc();
-
+
+ BOOL isScrolledToTop();
+ BOOL isScrolledToBottom();
+
// Getters
const LLWString& getWText() const;
llwchar getWChar(S32 pos);
@@ -439,6 +442,8 @@ protected:
BOOL mTakesFocus;
BOOL mHideScrollbarForShortDocs;
BOOL mTakesNonScrollClicks;
+ BOOL mTrackBottom; // if true, keeps scroll position at bottom during resize
+ BOOL mScrolledToBottom;
BOOL mAllowEmbeddedItems;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 00a230dff3..7561fe8b48 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -79,7 +79,7 @@ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
LLWindow* LLUI::sWindow = NULL;
LLHtmlHelp* LLUI::sHtmlHelp = NULL;
BOOL LLUI::sShowXUINames = FALSE;
-std::stack<LLRect> LLUI::sClipRectStack;
+std::stack<LLRect> LLScreenClipRect::sClipRectStack;
//
// Functions
@@ -410,39 +410,76 @@ void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max
}
-void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color )
+void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect )
{
- gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color );
+ 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, LLImageGL* image, const LLColor4& color)
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
{
- gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color );
+ 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, LLImageGL* image, const LLColor4& color, BOOL solid_color)
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
{
- stop_glerror();
- F32 border_scale = 1.f;
-
if (NULL == image)
{
llwarns << "image == NULL; aborting function" << llendl;
return;
}
- if (border_height * 2 > height)
- {
- border_scale = (F32)height / ((F32)border_height * 2.f);
- }
- if (border_width * 2 > width)
+ // 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, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
+{
+ stop_glerror();
+
+ if (NULL == image)
{
- border_scale = llmin(border_scale, (F32)width / ((F32)border_width * 2.f));
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
}
// scale screen size of borders down
- S32 scaled_border_width = llfloor(border_scale * (F32)border_width);
- S32 scaled_border_height = llfloor(border_scale * (F32)border_height);
+ LLRectf clipped_scale_rect = uv_rect;
+ clipped_scale_rect.intersectWith(scale_rect);
+
+ LLRect draw_rect(0, height, width, 0);
+ LLRect draw_scale_rect(llround((F32)image->getWidth() * scale_rect.mLeft),
+ llround((F32)image->getHeight() * scale_rect.mTop),
+ llround((F32)image->getWidth() * scale_rect.mRight),
+ llround((F32)image->getHeight() * scale_rect.mBottom));
+ // scale fixed region of image up with drawn region
+ draw_scale_rect.mRight += width - image->getWidth();
+ draw_scale_rect.mTop += height - image->getHeight();
+
+ S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight);
+ S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop);
+
+ F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image->getWidth() * (1.f - scale_rect.getWidth()));
+ F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image->getHeight() * (1.f - scale_rect.getHeight()));
+
+ F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+ draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale);
+ draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale));
+ draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale));
+ draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale);
LLGLSUIDefault gls_ui;
@@ -470,127 +507,124 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
glColor4fv(color.mV);
- F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
- F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
-
glBegin(GL_QUADS);
{
// draw bottom left
- glTexCoord2f(0.f, 0.f);
+ glTexCoord2d(uv_rect.mLeft, uv_rect.mBottom);
glVertex2i(0, 0);
- glTexCoord2f(border_width_fraction, 0.f);
- glVertex2i(scaled_border_width, 0);
+ glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, 0);
- glTexCoord2f(border_width_fraction, border_height_fraction);
- glVertex2i(scaled_border_width, scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
- glTexCoord2f(0.f, border_height_fraction);
- glVertex2i(0, scaled_border_height);
+ glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(0, draw_scale_rect.mBottom);
// draw bottom middle
- glTexCoord2f(border_width_fraction, 0.f);
- glVertex2i(scaled_border_width, 0);
+ glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, 0);
- glTexCoord2f(1.f - border_width_fraction, 0.f);
- glVertex2i(width - scaled_border_width, 0);
+ glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, 0);
- glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
- glVertex2i(width - scaled_border_width, scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
- glTexCoord2f(border_width_fraction, border_height_fraction);
- glVertex2i(scaled_border_width, scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
// draw bottom right
- glTexCoord2f(1.f - border_width_fraction, 0.f);
- glVertex2i(width - scaled_border_width, 0);
+ glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, 0);
- glTexCoord2f(1.f, 0.f);
+ glTexCoord2d(uv_rect.mRight, uv_rect.mBottom);
glVertex2i(width, 0);
- glTexCoord2f(1.f, border_height_fraction);
- glVertex2i(width, scaled_border_height);
+ glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(width, draw_scale_rect.mBottom);
- glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
- glVertex2i(width - scaled_border_width, scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
// draw left
- glTexCoord2f(0.f, border_height_fraction);
- glVertex2i(0, scaled_border_height);
+ glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(0, draw_scale_rect.mBottom);
- glTexCoord2f(border_width_fraction, border_height_fraction);
- glVertex2i(scaled_border_width, scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
- glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(scaled_border_width, height - scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
- glTexCoord2f(0.f, 1.f - border_height_fraction);
- glVertex2i(0, height - scaled_border_height);
+ glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(0, draw_scale_rect.mTop);
// draw middle
- glTexCoord2f(border_width_fraction, border_height_fraction);
- glVertex2i(scaled_border_width, scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
- glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
- glVertex2i(width - scaled_border_width, scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
- glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(width - scaled_border_width, height - scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
- glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(scaled_border_width, height - scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
// draw right
- glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
- glVertex2i(width - scaled_border_width, scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
- glTexCoord2f(1.f, border_height_fraction);
- glVertex2i(width, scaled_border_height);
+ glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mBottom);
+ glVertex2i(width, draw_scale_rect.mBottom);
- glTexCoord2f(1.f, 1.f - border_height_fraction);
- glVertex2i(width, height - scaled_border_height);
+ glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(width, draw_scale_rect.mTop);
- glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(width - scaled_border_width, height - scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
// draw top left
- glTexCoord2f(0.f, 1.f - border_height_fraction);
- glVertex2i(0, height - scaled_border_height);
+ glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(0, draw_scale_rect.mTop);
- glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(scaled_border_width, height - scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
- glTexCoord2f(border_width_fraction, 1.f);
- glVertex2i(scaled_border_width, height);
+ glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, height);
- glTexCoord2f(0.f, 1.f);
+ glTexCoord2d(uv_rect.mLeft, uv_rect.mTop);
glVertex2i(0, height);
// draw top middle
- glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(scaled_border_width, height - scaled_border_height);
+ glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
- glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(width - scaled_border_width, height - scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
- glTexCoord2f(1.f - border_width_fraction, 1.f);
- glVertex2i(width - scaled_border_width, height);
+ glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, height);
- glTexCoord2f(border_width_fraction, 1.f);
- glVertex2i(scaled_border_width, height);
+ glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mTop);
+ glVertex2i(draw_scale_rect.mLeft, height);
// draw top right
- glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
- glVertex2i(width - scaled_border_width, height - scaled_border_height);
+ glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
- glTexCoord2f(1.f, 1.f - border_height_fraction);
- glVertex2i(width, height - scaled_border_height);
+ glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mTop);
+ glVertex2i(width, draw_scale_rect.mTop);
- glTexCoord2f(1.f, 1.f);
+ glTexCoord2d(uv_rect.mRight, uv_rect.mTop);
glVertex2i(width, height);
- glTexCoord2f(1.f - border_width_fraction, 1.f);
- glVertex2i(width - scaled_border_width, height);
+ glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mTop);
+ glVertex2i(draw_scale_rect.mRight, height);
}
glEnd();
}
@@ -602,12 +636,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
}
}
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color)
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
{
- gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color );
+ 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, LLImageGL* image, const LLColor4& color)
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
{
if (NULL == image)
{
@@ -635,16 +669,16 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
glBegin(GL_QUADS);
{
- glTexCoord2f(1.f, 1.f);
+ glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
glVertex2i(width, height );
- glTexCoord2f(0.f, 1.f);
+ glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
glVertex2i(0, height );
- glTexCoord2f(0.f, 0.f);
+ glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
glVertex2i(0, 0);
- glTexCoord2f(1.f, 0.f);
+ glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
glVertex2i(width, 0);
}
glEnd();
@@ -653,7 +687,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
}
-void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color)
+void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
{
if (NULL == image)
{
@@ -673,16 +707,16 @@ void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageG
glBegin(GL_QUADS);
{
- glTexCoord2f(1.f, 0.f);
+ glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
glVertex2i(width, height );
- glTexCoord2f(0.f, 0.f);
+ glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
glVertex2i(0, height );
- glTexCoord2f(0.f, 1.f);
+ glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
glVertex2i(0, 0);
- glTexCoord2f(1.f, 1.f);
+ glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
glVertex2i(width, 0);
}
glEnd();
@@ -1584,40 +1618,6 @@ void LLUI::loadIdentity()
LLFontGL::sCurOrigin.mZ = 0;
}
-//static
-void LLUI::setScissorRegionScreen(const LLRect& rect)
-{
- stop_glerror();
- S32 x,y,w,h;
- x = llround(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
- y = llround(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
- w = llround(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
- h = llround(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
- glScissor( x,y,w,h );
- stop_glerror();
-}
-
-//static
-void LLUI::setScissorRegionLocal(const LLRect& rect)
-{
- stop_glerror();
- S32 screen_left = LLFontGL::sCurOrigin.mX + rect.mLeft;
- S32 screen_bottom = LLFontGL::sCurOrigin.mY + rect.mBottom;
-
- S32 x,y,w,h;
-
- x = llround((F32)screen_left * LLUI::sGLScaleFactor.mV[VX]);
- y = llround((F32)screen_bottom * LLUI::sGLScaleFactor.mV[VY]);
- w = llround((F32)rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
- h = llround((F32)rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
-
- w = llmax(0,w);
- h = llmax(0,h);
-
- glScissor(x,y,w,h);
- stop_glerror();
-}
-
//static
void LLUI::setScaleFactor(const LLVector2 &scale_factor)
{
@@ -1738,64 +1738,169 @@ LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name)
return LLUUID( foundValue );
}
+//static
+LLUIImage* LLUI::getUIImageByName(const LLString& name)
+{
+ return sImageProvider->getUIImageByID(findAssetUUIDByName(name));
+}
+
+
// static
void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
{
LLUI::sHtmlHelp = html_help;
}
+LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ pushClipRect(rect);
+ }
+ mScissorState.setEnabled(!sClipRectStack.empty());
+ updateScissorRegion();
+}
+
+LLScreenClipRect::~LLScreenClipRect()
+{
+ if (mEnabled)
+ {
+ popClipRect();
+ }
+ updateScissorRegion();
+}
+
//static
-void LLUI::pushClipRect(const LLRect& rect)
+void LLScreenClipRect::pushClipRect(const LLRect& rect)
{
LLRect combined_clip_rect = rect;
if (!sClipRectStack.empty())
{
- combined_clip_rect.intersectWith(sClipRectStack.top());
+ LLRect top = sClipRectStack.top();
+ combined_clip_rect.intersectWith(top);
}
sClipRectStack.push(combined_clip_rect);
- setScissorRegionScreen(combined_clip_rect);
}
//static
-void LLUI::popClipRect()
+void LLScreenClipRect::popClipRect()
{
sClipRectStack.pop();
- if (!sClipRectStack.empty())
- {
- setScissorRegionScreen(sClipRectStack.top());
- }
}
-LLClipRect::LLClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+//static
+void LLScreenClipRect::updateScissorRegion()
{
- if (mEnabled)
- {
- LLUI::pushClipRect(rect);
- }
+ if (sClipRectStack.empty()) return;
+
+ 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;
+ glScissor( x,y,w,h );
+ stop_glerror();
}
-LLClipRect::~LLClipRect()
+
+LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled)
+: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY),
+ enabled)
{
- if (mEnabled)
- {
- LLUI::popClipRect();
- }
}
-LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+
+//
+// LLUIImage
+//
+
+LLUIImage::LLUIImage(LLPointer<LLImageGL> image) :
+ mImage(image),
+ mScaleRegion(0.f, 1.f, 1.f, 0.f),
+ mClipRegion(0.f, 1.f, 1.f, 0.f),
+ mUniformScaling(TRUE),
+ mNoClip(TRUE)
+{
+}
+
+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)
{
- if (mEnabled)
- {
- LLRect scissor_rect = rect;
- scissor_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY);
- LLUI::pushClipRect(scissor_rect);
- }
+ gl_draw_image(x, y, mImage, color, mClipRegion);
}
-LLLocalClipRect::~LLLocalClipRect()
+void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color)
{
- if (mEnabled)
+ if (mUniformScaling)
{
- LLUI::popClipRect();
+ 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)
+{
+ gl_draw_scaled_image_with_border(
+ x, y,
+ width, height,
+ mImage,
+ color,
+ TRUE,
+ mClipRegion,
+ mScaleRegion);
+}
+
+void LLUIImage::drawSolid(S32 x, S32 y, const LLColor4& color)
+{
+ gl_draw_scaled_image_with_border(
+ x, y,
+ getWidth(), getHeight(),
+ mImage,
+ color,
+ TRUE,
+ mClipRegion,
+ mScaleRegion);
+}
+
+S32 LLUIImage::getWidth()
+{
+ return mImage->getWidth(0);
+}
+
+S32 LLUIImage::getHeight()
+{
+ return mImage->getHeight(0);
}
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index b98f4d5de2..05982aa9e2 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -41,14 +41,15 @@
#include "llhtmlhelp.h"
#include "llgl.h"
#include <stack>
+#include "llimagegl.h"
class LLColor4;
class LLVector3;
class LLVector2;
-class LLImageGL;
class LLUUID;
class LLWindow;
class LLView;
+class LLUIImage;
// UI colors
extern const LLColor4 UI_VERTEX_COLOR;
@@ -83,13 +84,14 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4&
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_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);
-void gl_draw_image(S32 x, S32 y, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR);
-void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR);
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR);
-void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR);
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE);
+void gl_draw_image(S32 x, S32 y, LLImageGL* 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, LLImageGL* 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, LLImageGL* 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,LLImageGL* 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, LLImageGL* 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, LLImageGL* 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));
// Flip vertical, used for LLFloaterHTML
-void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR);
+void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom);
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
@@ -166,13 +168,12 @@ public:
//helper functions (should probably move free standing rendering helper functions here)
static LLString locateSkin(const LLString& filename);
- static void pushClipRect(const LLRect& rect);
- static void popClipRect();
static void setCursorPositionScreen(S32 x, S32 y);
static void setCursorPositionLocal(LLView* viewp, S32 x, S32 y);
static void setScaleFactor(const LLVector2& scale_factor);
static void setLineWidth(F32 width);
static LLUUID findAssetUUIDByName(const LLString& name);
+ static LLUIImage* getUIImageByName(const LLString& name);
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);
@@ -180,10 +181,6 @@ public:
static void glRectToScreen(const LLRect& gl, LLRect *screen);
static void setHtmlHelp(LLHtmlHelp* html_help);
-private:
- static void setScissorRegionScreen(const LLRect& rect);
- static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
-
public:
static LLControlGroup* sConfigGroup;
static LLControlGroup* sColorsGroup;
@@ -194,7 +191,6 @@ public:
static LLWindow* sWindow;
static BOOL sShowXUINames;
static LLHtmlHelp* sHtmlHelp;
- static std::stack<LLRect> sClipRectStack;
};
@@ -286,6 +282,7 @@ typedef enum e_widget_type
WIDGET_TYPE_MEMORY_VIEW,
WIDGET_TYPE_FRAME_STAT_VIEW,
WIDGET_TYPE_LAYOUT_STACK,
+ WIDGET_TYPE_FLYOUT_BUTTON,
WIDGET_TYPE_DONTCARE,
WIDGET_TYPE_COUNT
} EWidgetType;
@@ -382,24 +379,65 @@ protected:
template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL;
-class LLClipRect
+class LLScreenClipRect
{
public:
- LLClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLClipRect();
-protected:
+ LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLScreenClipRect();
+
+private:
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
+ static void updateScissorRegion();
+
+private:
LLGLState mScissorState;
BOOL mEnabled;
+
+ static std::stack<LLRect> sClipRectStack;
};
-class LLLocalClipRect
+class LLLocalClipRect : public LLScreenClipRect
{
public:
LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLLocalClipRect();
+};
+
+class LLUIImage : public LLRefCount
+{
+public:
+ LLUIImage(LLPointer<LLImageGL> image);
+
+ void setClipRegion(const LLRectf& region);
+ void setScaleRegion(const LLRectf& region);
+
+ LLPointer<LLImageGL> getImage() { return mImage; }
+
+ void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR);
+ void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR);
+ void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color);
+ void drawSolid(S32 x, S32 y, const LLColor4& color);
+
+ S32 getWidth();
+ S32 getHeight();
+
protected:
- LLGLState mScissorState;
- BOOL mEnabled;
+ LLRectf mScaleRegion;
+ LLRectf mClipRegion;
+ LLPointer<LLImageGL> mImage;
+ BOOL mUniformScaling;
+ BOOL mNoClip;
+};
+
+//RN: maybe this needs to moved elsewhere?
+class LLImageProviderInterface
+{
+public:
+ LLImageProviderInterface() {};
+ virtual ~LLImageProviderInterface() {};
+
+ virtual LLUIImage* getUIImageByID(const LLUUID& id, BOOL clamped = TRUE) = 0;
+ virtual LLImageGL* getImageByID(const LLUUID& id, BOOL clamped = TRUE) = 0;
};
#endif
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 7d354753d3..8645f50764 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -47,11 +47,53 @@
const U32 MAX_STRING_LENGTH = 10;
-LLUICtrl::LLUICtrl() :
- mCommitCallback(NULL),
- mFocusLostCallback(NULL),
+LLFocusableElement::LLFocusableElement()
+: mFocusLostCallback(NULL),
mFocusReceivedCallback(NULL),
mFocusChangedCallback(NULL),
+ mFocusCallbackUserData(NULL)
+{
+}
+
+void LLFocusableElement::onFocusReceived()
+{
+ if( mFocusReceivedCallback )
+ {
+ mFocusReceivedCallback( this, mFocusCallbackUserData );
+ }
+ if( mFocusChangedCallback )
+ {
+ mFocusChangedCallback( this, mFocusCallbackUserData );
+ }
+}
+
+void LLFocusableElement::onFocusLost()
+{
+ if( mFocusLostCallback )
+ {
+ mFocusLostCallback( this, mFocusCallbackUserData );
+ }
+
+ if( mFocusChangedCallback )
+ {
+ mFocusChangedCallback( this, mFocusCallbackUserData );
+ }
+}
+
+BOOL LLFocusableElement::hasFocus() const
+{
+ return FALSE;
+}
+
+void LLFocusableElement::setFocus(BOOL b)
+{
+}
+
+
+
+LLUICtrl::LLUICtrl() :
+ mCommitCallback(NULL),
+ mLostTopCallback(NULL),
mValidateCallback(NULL),
mCallbackUserData(NULL),
mTentative(FALSE),
@@ -68,9 +110,7 @@ LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque,
// of buttons in the UI. JC 7/20/2002
LLView( name, rect, mouse_opaque, reshape ),
mCommitCallback( on_commit_callback) ,
- mFocusLostCallback( NULL ),
- mFocusReceivedCallback( NULL ),
- mFocusChangedCallback( NULL ),
+ mLostTopCallback( NULL ),
mValidateCallback( NULL ),
mCallbackUserData( callback_userdata ),
mTentative( FALSE ),
@@ -128,6 +168,86 @@ LLCtrlScrollInterface* LLUICtrl::getScrollInterface()
return NULL;
}
+BOOL LLUICtrl::hasFocus() const
+{
+ return (gFocusMgr.childHasKeyboardFocus(this));
+}
+
+void LLUICtrl::setFocus(BOOL b)
+{
+ // focus NEVER goes to ui ctrls that are disabled!
+ if (!mEnabled)
+ {
+ return;
+ }
+ if( b )
+ {
+ if (!hasFocus())
+ {
+ gFocusMgr.setKeyboardFocus( this );
+ }
+ }
+ else
+ {
+ if( gFocusMgr.childHasKeyboardFocus(this))
+ {
+ gFocusMgr.setKeyboardFocus( NULL );
+ }
+ }
+}
+
+void LLUICtrl::onFocusReceived()
+{
+ // trigger callbacks
+ LLFocusableElement::onFocusReceived();
+
+ // find first view in hierarchy above new focus that is a LLUICtrl
+ LLView* viewp = getParent();
+ LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus();
+
+ while (viewp && !viewp->isCtrl())
+ {
+ viewp = viewp->getParent();
+ }
+
+ // and if it has newly gained focus, call onFocusReceived()
+ LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
+ if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp)))
+ {
+ ctrlp->onFocusReceived();
+ }
+}
+
+void LLUICtrl::onFocusLost()
+{
+ // trigger callbacks
+ LLFocusableElement::onFocusLost();
+
+ // find first view in hierarchy above old focus that is a LLUICtrl
+ LLView* viewp = getParent();
+ while (viewp && !viewp->isCtrl())
+ {
+ viewp = viewp->getParent();
+ }
+
+ // and if it has just lost focus, call onFocusReceived()
+ LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
+ // hasFocus() includes any descendants
+ if (ctrlp && !ctrlp->hasFocus())
+ {
+ ctrlp->onFocusLost();
+ }
+}
+
+void LLUICtrl::onLostTop()
+{
+ if (mLostTopCallback)
+ {
+ mLostTopCallback(this, mCallbackUserData);
+ }
+}
+
+
// virtual
void LLUICtrl::setTabStop( BOOL b )
{
@@ -168,67 +288,6 @@ BOOL LLUICtrl::getIsChrome() const
return mIsChrome;
}
-void LLUICtrl::onFocusReceived()
-{
- if( mFocusReceivedCallback )
- {
- mFocusReceivedCallback( this, mCallbackUserData );
- }
- if( mFocusChangedCallback )
- {
- mFocusChangedCallback( this, mCallbackUserData );
- }
-}
-
-void LLUICtrl::onFocusLost()
-{
- if( mFocusLostCallback )
- {
- mFocusLostCallback( this, mCallbackUserData );
- }
-
- if( mFocusChangedCallback )
- {
- mFocusChangedCallback( this, mCallbackUserData );
- }
-}
-
-BOOL LLUICtrl::hasFocus() const
-{
- return (gFocusMgr.childHasKeyboardFocus(this));
-}
-
-void LLUICtrl::setFocus(BOOL b)
-{
- // focus NEVER goes to ui ctrls that are disabled!
- if (!mEnabled)
- {
- return;
- }
- if( b )
- {
- if (!hasFocus())
- {
- gFocusMgr.setKeyboardFocus( this, &LLUICtrl::onFocusLostCallback );
- onFocusReceived();
- }
- }
- else
- {
- if( gFocusMgr.childHasKeyboardFocus(this))
- {
- gFocusMgr.setKeyboardFocus( NULL, NULL );
- onFocusLost();
- }
- }
-}
-
-// static
-void LLUICtrl::onFocusLostCallback( LLUICtrl* old_focus )
-{
- old_focus->onFocusLost();
-}
-
// this comparator uses the crazy disambiguating logic of LLCompareByTabOrder,
// but to switch up the order so that children that have the default tab group come first
// and those that are prior to the default tab group come last
@@ -262,6 +321,7 @@ public:
}
};
+
BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields)
{
// try to select default tab group child
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 00f78748a7..ae360f401f 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -53,8 +53,31 @@ class LLCtrlScrollInterface;
typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata);
+class LLFocusableElement
+{
+ friend class LLFocusMgr; // allow access to focus change handlers
+public:
+ LLFocusableElement();
+ virtual ~LLFocusableElement() {};
+
+ virtual void setFocus( BOOL b );
+ virtual BOOL hasFocus() const;
+
+ void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; }
+ void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; }
+ void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; }
+
+protected:
+ virtual void onFocusReceived();
+ virtual void onFocusLost();
+ void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata );
+ void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata );
+ void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata );
+ void* mFocusCallbackUserData;
+};
+
class LLUICtrl
-: public LLView
+: public LLView, public LLFocusableElement
{
public:
LLUICtrl();
@@ -85,6 +108,11 @@ public:
virtual void setFocus( BOOL b );
virtual BOOL hasFocus() const;
+ virtual void onFocusReceived();
+ virtual void onFocusLost();
+
+ virtual void onLostTop(); // called when registered as top ctrl and user clicks elsewhere
+
virtual void setTabStop( BOOL b );
virtual BOOL hasTabStop() const;
@@ -115,6 +143,7 @@ public:
void setCommitCallback( void (*cb)(LLUICtrl*, void*) ) { mCommitCallback = cb; }
void setValidateBeforeCommit( BOOL(*cb)(LLUICtrl*, void*) ) { mValidateCallback = cb; }
+ void setLostTopCallback( void (*cb)(LLUICtrl*, void*) ) { mLostTopCallback = cb; }
// Defaults to no-op!
virtual void setDoubleClickCallback( void (*cb)(void*) );
@@ -126,23 +155,8 @@ public:
virtual void setMinValue(LLSD min_value);
virtual void setMaxValue(LLSD max_value);
- // In general, only LLPanel uses these.
- void setFocusLostCallback(void (*cb)(LLUICtrl* caller, void* user_data)) { mFocusLostCallback = cb; }
- void setFocusReceivedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusReceivedCallback = cb; }
- void setFocusChangedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusChangedCallback = cb; }
-
- static void onFocusLostCallback(LLUICtrl* old_focus);
-
/*virtual*/ BOOL focusFirstItem(BOOL prefer_text_fields = FALSE );
- class LLTabStopPostFilter : public LLQueryFilter, public LLSingleton<LLTabStopPostFilter>
- {
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
- {
- return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->hasTabStop() && children.size() == 0, TRUE);
- }
- };
-
class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
@@ -157,16 +171,9 @@ public:
virtual void resetDirty() {};
protected:
- virtual void onFocusReceived();
- virtual void onFocusLost();
- void onChangeFocus( S32 direction );
-
-protected:
void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
- void (*mFocusLostCallback)( LLUICtrl* caller, void* userdata );
- void (*mFocusReceivedCallback)( LLUICtrl* ctrl, void* userdata );
- void (*mFocusChangedCallback)( LLUICtrl* ctrl, void* userdata );
+ void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata );
BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
void* mCallbackUserData;
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 88e4e89a2b..1e8798e7f7 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -173,7 +173,7 @@ std::vector<LLString> LLUICtrlFactory::mXUIPaths;
class LLUICtrlLocate : public LLUICtrl
{
public:
- LLUICtrlLocate() : LLUICtrl("locate", LLRect(0,0,0,0), FALSE, NULL, NULL) {}
+ LLUICtrlLocate() : LLUICtrl("locate", LLRect(0,0,0,0), FALSE, NULL, NULL) { setTabStop(FALSE); }
virtual void draw() { }
virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LOCATE; }
@@ -181,7 +181,11 @@ public:
static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
+ LLString name("pad");
+ node->getAttributeString("name", name);
+
LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
+ new_ctrl->setName(name);
new_ctrl->initFromXML(node, parent);
return new_ctrl;
}
@@ -196,6 +200,7 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator<LLButton>::registerCreator(LL_BUTTON_TAG, this);
LLUICtrlCreator<LLCheckBoxCtrl>::registerCreator(LL_CHECK_BOX_CTRL_TAG, this);
LLUICtrlCreator<LLComboBox>::registerCreator(LL_COMBO_BOX_TAG, this);
+ LLUICtrlCreator<LLFlyoutButton>::registerCreator(LL_FLYOUT_BUTTON_TAG, this);
LLUICtrlCreator<LLLineEditor>::registerCreator(LL_LINE_EDITOR_TAG, this);
LLUICtrlCreator<LLSearchEditor>::registerCreator(LL_SEARCH_EDITOR_TAG, this);
LLUICtrlCreator<LLScrollListCtrl>::registerCreator(LL_SCROLL_LIST_CTRL_TAG, this);
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index a047f9912e..370288e949 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -113,7 +113,7 @@ LLView::LLView() :
mSaveToXML(TRUE),
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
- mSpanChildren(FALSE),
+ mUseBoundingRect(FALSE),
mVisible(TRUE),
mHidden(FALSE),
mNextInsertionOrdinal(0)
@@ -133,7 +133,7 @@ LLView::LLView(const LLString& name, BOOL mouse_opaque) :
mSaveToXML(TRUE),
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
- mSpanChildren(FALSE),
+ mUseBoundingRect(FALSE),
mVisible(TRUE),
mHidden(FALSE),
mNextInsertionOrdinal(0)
@@ -148,6 +148,7 @@ LLView::LLView(
mParentView(NULL),
mName(name),
mRect(rect),
+ mBoundingRect(rect),
mReshapeFlags(reshape),
mDefaultTabGroup(0),
mEnabled(TRUE),
@@ -156,7 +157,7 @@ LLView::LLView(
mSaveToXML(TRUE),
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
- mSpanChildren(FALSE),
+ mUseBoundingRect(FALSE),
mVisible(TRUE),
mHidden(FALSE),
mNextInsertionOrdinal(0)
@@ -235,10 +236,16 @@ BOOL LLView::setToolTipArg(const LLStringExplicit& key, const LLStringExplicit&
return TRUE;
}
+void LLView::setToolTipArgs( const LLString::format_map_t& args )
+{
+ mToolTipMsg.setArgList(args);
+}
+
// virtual
void LLView::setRect(const LLRect& rect)
{
mRect = rect;
+ updateBoundingRect();
}
@@ -287,9 +294,18 @@ void LLView::setName(LLString name)
mName = name;
}
-void LLView::setSpanChildren( BOOL span_children )
+void LLView::setUseBoundingRect( BOOL use_bounding_rect )
+{
+ if (mUseBoundingRect != use_bounding_rect)
+ {
+ mUseBoundingRect = use_bounding_rect;
+ updateBoundingRect();
+ }
+}
+
+BOOL LLView::getUseBoundingRect()
{
- mSpanChildren = span_children; updateRect();
+ return mUseBoundingRect;
}
const LLString& LLView::getToolTip()
@@ -306,7 +322,7 @@ const LLString& LLView::getName() const
void LLView::sendChildToFront(LLView* child)
{
- if (child->mParentView == this)
+ if (child && child->getParent() == this)
{
mChildList.remove( child );
mChildList.push_front(child);
@@ -315,7 +331,7 @@ void LLView::sendChildToFront(LLView* child)
void LLView::sendChildToBack(LLView* child)
{
- if (child->mParentView == this)
+ if (child && child->getParent() == this)
{
mChildList.remove( child );
mChildList.push_back(child);
@@ -330,6 +346,14 @@ void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
}
}
+void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
+{
+ if(mCtrlOrder.find(child) != mCtrlOrder.end())
+ {
+ mCtrlOrder[child].second = mNextInsertionOrdinal++;
+ }
+}
+
void LLView::addChild(LLView* child, S32 tab_group)
{
if (mParentView == child)
@@ -353,7 +377,7 @@ void LLView::addChild(LLView* child, S32 tab_group)
}
child->mParentView = this;
- updateRect();
+ updateBoundingRect();
}
@@ -380,7 +404,7 @@ void LLView::addChildAtEnd(LLView* child, S32 tab_group)
}
child->mParentView = this;
- updateRect();
+ updateBoundingRect();
}
// remove the specified child from the view, and set it's parent to NULL.
@@ -403,6 +427,7 @@ void LLView::removeChild(LLView* child, BOOL deleteIt)
{
llerrs << "LLView::removeChild called with non-child" << llendl;
}
+ updateBoundingRect();
}
void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group)
@@ -782,6 +807,7 @@ void LLView::setVisible(BOOL visible)
// tell all children of this view that the visibility may have changed
onVisibilityChange( visible );
}
+ updateBoundingRect();
}
}
@@ -815,6 +841,7 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
void LLView::translate(S32 x, S32 y)
{
mRect.translate(x, y);
+ updateBoundingRect();
}
// virtual
@@ -831,7 +858,8 @@ void LLView::snappedTo(LLView* snap_view)
BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleHover( x, y, mask ) != NULL;
- if( !handled && mMouseOpaque && pointInView( x, y ) )
+ if( !handled
+ && blockMouseEvent(x, y) )
{
LLUI::sWindow->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
@@ -876,45 +904,46 @@ BOOL LLView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_scre
LLString tool_tip;
- if ( getVisible() && getEnabled())
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->mRect.mLeft;
+ S32 local_y = y - viewp->mRect.mBottom;
+ if( viewp->pointInView(local_x, local_y)
+ && viewp->getVisible()
+ && viewp->getEnabled()
+ && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ))
{
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->mRect.mLeft;
- S32 local_y = y - viewp->mRect.mBottom;
- if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- handled = TRUE;
- break;
- }
+ handled = TRUE;
+ break;
}
+ }
- tool_tip = mToolTipMsg.getString();
- if (LLUI::sShowXUINames && (tool_tip.find(".xml", 0) == LLString::npos) &&
- (mName.find("Drag", 0) == LLString::npos))
- {
- tool_tip = getShowNamesToolTip();
- }
-
+ tool_tip = mToolTipMsg.getString();
+ if (
+ LLUI::sShowXUINames &&
+ (tool_tip.find(".xml", 0) == LLString::npos) &&
+ (mName.find("Drag", 0) == LLString::npos))
+ {
+ tool_tip = getShowNamesToolTip();
+ }
- BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX);
+ BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX);
- if( !handled && (mMouseOpaque || showNamesTextBox) && pointInView( x, y ) && !tool_tip.empty())
- {
+ if( !handled && (blockMouseEvent(x, y) || showNamesTextBox) && !tool_tip.empty())
+ {
- msg = tool_tip;
+ msg = tool_tip;
- // Convert rect local to screen coordinates
- localPointToScreen(
- 0, 0,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- mRect.getWidth(), mRect.getHeight(),
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
-
- handled = TRUE;
- }
+ // Convert rect local to screen coordinates
+ localPointToScreen(
+ 0, 0,
+ &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
+ localPointToScreen(
+ mRect.getWidth(), mRect.getHeight(),
+ &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
+
+ handled = TRUE;
}
return handled;
@@ -1025,7 +1054,7 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
cargo_data,
accept,
tooltip_msg) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
*accept = ACCEPT_NO;
handled = TRUE;
@@ -1081,7 +1110,7 @@ BOOL LLView::hasMouseCapture()
BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handled = TRUE;
}
@@ -1092,7 +1121,7 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLView* handled_view = childrenHandleMouseDown( x, y, mask );
BOOL handled = (handled_view != NULL);
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handled = TRUE;
handled_view = this;
@@ -1118,7 +1147,7 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handleMouseDown(x, y, mask);
handled = TRUE;
@@ -1132,7 +1161,7 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
if( getVisible() && mEnabled )
{
handled = childrenHandleScrollWheel( x, y, clicks ) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handled = TRUE;
}
@@ -1143,7 +1172,7 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handled = TRUE;
}
@@ -1153,7 +1182,7 @@ BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL;
- if( !handled && mMouseOpaque )
+ if( !handled && blockMouseEvent(x, y) )
{
handled = TRUE;
}
@@ -1428,10 +1457,10 @@ void LLView::draw()
focus_view = NULL;
}
+ ++sDepth;
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
{
LLView *viewp = *child_iter;
- ++sDepth;
if (viewp->getVisible() && viewp != focus_view)
{
@@ -1449,8 +1478,8 @@ void LLView::draw()
}
}
- --sDepth;
}
+ --sDepth;
if (focus_view && focus_view->getVisible())
{
@@ -1467,50 +1496,61 @@ void LLView::draw()
//Draw a box for debugging.
void LLView::drawDebugRect()
{
- // drawing solids requires texturing be disabled
- LLGLSNoTexture no_texture;
-
- // draw red rectangle for the border
- LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
- if (sEditingUI)
+ LLUI::pushMatrix();
{
- border_color.mV[0] = 1.f;
- }
- else
- {
- border_color.mV[sDepth%3] = 1.f;
- }
+ // drawing solids requires texturing be disabled
+ LLGLSNoTexture no_texture;
- glColor4fv( border_color.mV );
+ if (mUseBoundingRect)
+ {
+ LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f);
+ }
- glBegin(GL_LINES);
- glVertex2i(0, mRect.getHeight() - 1);
- glVertex2i(0, 0);
+ LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
- glVertex2i(0, 0);
- glVertex2i(mRect.getWidth() - 1, 0);
+ // draw red rectangle for the border
+ LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
+ if (sEditingUI)
+ {
+ border_color.mV[0] = 1.f;
+ }
+ else
+ {
+ border_color.mV[sDepth%3] = 1.f;
+ }
- glVertex2i(mRect.getWidth() - 1, 0);
- glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1);
+ glColor4fv( border_color.mV );
- glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1);
- glVertex2i(0, mRect.getHeight() - 1);
- glEnd();
+ glBegin(GL_LINES);
+ glVertex2i(0, debug_rect.getHeight() - 1);
+ glVertex2i(0, 0);
- // Draw the name if it's not a leaf node
- if (mChildList.size() && !sEditingUI)
- {
- //char temp[256];
- S32 x, y;
- glColor4fv( border_color.mV );
- x = mRect.getWidth()/2;
- y = mRect.getHeight()/2;
- LLString debug_text = llformat("%s (%d x %d)", getName().c_str(),
- mRect.getWidth(), mRect.getHeight());
- LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
- LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL,
- S32_MAX, S32_MAX, NULL, FALSE);
+ glVertex2i(0, 0);
+ glVertex2i(debug_rect.getWidth() - 1, 0);
+
+ glVertex2i(debug_rect.getWidth() - 1, 0);
+ glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
+
+ glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
+ glVertex2i(0, debug_rect.getHeight() - 1);
+ glEnd();
+
+ // Draw the name if it's not a leaf node
+ if (mChildList.size() && !sEditingUI)
+ {
+ //char temp[256];
+ S32 x, y;
+ glColor4fv( border_color.mV );
+ x = debug_rect.getWidth()/2;
+ y = debug_rect.getHeight()/2;
+ LLString debug_text = llformat("%s (%d x %d)", getName().c_str(),
+ debug_rect.getWidth(), debug_rect.getHeight());
+ LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
+ LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL,
+ S32_MAX, S32_MAX, NULL, FALSE);
+ }
}
+ LLUI::popMatrix();
}
void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw)
@@ -1537,9 +1577,6 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- // make sure this view contains all its children
- updateRect();
-
// compute how much things changed and apply reshape logic to children
S32 delta_width = width - mRect.getWidth();
S32 delta_height = height - mRect.getHeight();
@@ -1608,6 +1645,8 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
mParentView->reshape(mParentView->getRect().getWidth(), mParentView->getRect().getHeight(), FALSE);
}
}
+
+ updateBoundingRect();
}
LLRect LLView::getRequiredRect()
@@ -1615,6 +1654,53 @@ LLRect LLView::getRequiredRect()
return mRect;
}
+void LLView::updateBoundingRect()
+{
+ if (isDead()) return;
+
+ if (mUseBoundingRect)
+ {
+ LLRect local_bounding_rect = LLRect::null;
+
+ child_list_const_iter_t child_it;
+ for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ {
+ LLView* childp = *child_it;
+ if (!childp->getVisible()) continue;
+
+ LLRect child_bounding_rect = childp->getBoundingRect();
+
+ if (local_bounding_rect.isNull())
+ {
+ // start out with bounding rect equal to first visible child's bounding rect
+ local_bounding_rect = child_bounding_rect;
+ }
+ else
+ {
+ // accumulate non-null children rectangles
+ if (!child_bounding_rect.isNull())
+ {
+ local_bounding_rect.unionWith(child_bounding_rect);
+ }
+ }
+ }
+
+ mBoundingRect = local_bounding_rect;
+ // translate into parent-relative coordinates
+ mBoundingRect.translate(mRect.mLeft, mRect.mBottom);
+ }
+ else
+ {
+ mBoundingRect = mRect;
+ }
+
+ // give parent view a chance to resize, in case we just moved, for example
+ if (getParent() && getParent()->mUseBoundingRect)
+ {
+ getParent()->updateBoundingRect();
+ }
+}
+
const LLRect LLView::getScreenRect() const
{
// *FIX: check for one-off error
@@ -1624,6 +1710,15 @@ const LLRect LLView::getScreenRect() const
return screen_rect;
}
+const LLRect LLView::getLocalBoundingRect() const
+{
+ LLRect local_bounding_rect = getBoundingRect();
+ local_bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
+
+ return local_bounding_rect;
+}
+
+
const LLRect LLView::getLocalRect() const
{
LLRect local_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
@@ -1637,38 +1732,7 @@ const LLRect LLView::getLocalSnapRect() const
return local_snap_rect;
}
-void LLView::updateRect()
-{
- if (mSpanChildren && mChildList.size())
- {
- LLView* first_child = (*mChildList.begin());
- LLRect child_spanning_rect = first_child->mRect;
-
- for ( child_list_iter_t child_it = ++mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- if (viewp->getVisible())
- {
- child_spanning_rect.unionWith(viewp->mRect);
- }
- }
-
- S32 translate_x = llmin(0, child_spanning_rect.mLeft);
- S32 translate_y = llmin(0, child_spanning_rect.mBottom);
- S32 new_width = llmax(mRect.getWidth() + translate_x, child_spanning_rect.getWidth());
- S32 new_height = llmax(mRect.getHeight() + translate_y, child_spanning_rect.getHeight());
-
- mRect.setOriginAndSize(mRect.mLeft + translate_x, mRect.mBottom + translate_y, new_width, new_height);
-
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- viewp->mRect.translate(-translate_x, -translate_y);
- }
- }
-}
-
-BOOL LLView::hasAncestor(LLView* parentp)
+BOOL LLView::hasAncestor(const LLView* parentp)
{
if (!parentp)
{
@@ -1743,14 +1807,23 @@ LLView* LLView::getChildByName(const LLString& name, BOOL recurse) const
return NULL;
}
-// virtual
-void LLView::onFocusLost()
-{
+BOOL LLView::parentPointInView(S32 x, S32 y, EHitTestType type) const
+{
+ return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ ? mBoundingRect.pointInRect( x, y )
+ : mRect.pointInRect( x, y );
}
-// virtual
-void LLView::onFocusReceived()
+BOOL LLView::pointInView(S32 x, S32 y, EHitTestType type) const
+{
+ return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ ? mBoundingRect.pointInRect( x + mRect.mLeft, y + mRect.mBottom )
+ : mRect.localPointInRect( x, y );
+}
+
+BOOL LLView::blockMouseEvent(S32 x, S32 y) const
{
+ return mMouseOpaque && pointInView(x, y, HIT_TEST_IGNORE_BOUNDING_RECT);
}
// virtual
@@ -2024,9 +2097,9 @@ LLXMLNodePtr LLView::getXML(bool save_children) const
// Export all widgets as enabled and visible - code must disable.
node->createChild("hidden", TRUE)->setBoolValue(mHidden);
node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque );
- if (!mToolTipMsg.empty())
+ if (!mToolTipMsg.getString().empty())
{
- node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg);
+ node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg.getString());
}
if (mSoundFlags != MOUSE_UP)
{
@@ -2116,7 +2189,7 @@ const LLCtrlQuery & LLView::getTabOrderQuery()
query.addPreFilter(LLVisibleFilter::getInstance());
query.addPreFilter(LLEnabledFilter::getInstance());
query.addPreFilter(LLTabStopFilter::getInstance());
- query.addPostFilter(LLUICtrl::LLTabStopPostFilter::getInstance());
+ query.addPostFilter(LLLeavesFilter::getInstance());
}
return query;
}
@@ -2129,6 +2202,7 @@ const LLCtrlQuery & LLView::getFocusRootsQuery()
query.addPreFilter(LLVisibleFilter::getInstance());
query.addPreFilter(LLEnabledFilter::getInstance());
query.addPreFilter(LLView::LLFocusRootsFilter::getInstance());
+ query.addPostFilter(LLRootsFilter::getInstance());
}
return query;
}
@@ -2593,10 +2667,10 @@ const S32 VPAD = 4;
U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
{
U32 follows = 0;
- S32 x = FLOATER_H_MARGIN;
- S32 y = 0;
- S32 w = 0;
- S32 h = 0;
+ S32 x = rect.mLeft;
+ S32 y = rect.mBottom;
+ S32 w = rect.getWidth();
+ S32 h = rect.getHeight();
U32 last_x = 0;
U32 last_y = 0;
@@ -2639,8 +2713,15 @@ U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, con
// view if you don't specify a width.
if (parent_view)
{
- w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x);
- h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight());
+ if(w == 0)
+ {
+ w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x);
+ }
+
+ if(h == 0)
+ {
+ h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight());
+ }
}
if (node->hasAttribute("width"))
@@ -2765,44 +2846,7 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
setRect(view_rect);
setFollows(follows_flags);
- if (node->hasAttribute("follows"))
- {
- setFollowsNone();
-
- LLString follows;
- node->getAttributeString("follows", follows);
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("|");
- tokenizer tokens(follows, sep);
- tokenizer::iterator token_iter = tokens.begin();
-
- while(token_iter != tokens.end())
- {
- const std::string& token_str = *token_iter;
- if (token_str == "left")
- {
- setFollowsLeft();
- }
- else if (token_str == "right")
- {
- setFollowsRight();
- }
- else if (token_str == "top")
- {
- setFollowsTop();
- }
- else if (token_str == "bottom")
- {
- setFollowsBottom();
- }
- else if (token_str == "all")
- {
- setFollowsAll();
- }
- ++token_iter;
- }
- }
+ parseFollowsFlags(node);
if (node->hasAttribute("control_name"))
{
@@ -2839,11 +2883,57 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
setHidden(hidden);
}
+ node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect);
+ node->getAttributeBOOL("mouse_opaque", mMouseOpaque);
+
node->getAttributeS32("default_tab_group", mDefaultTabGroup);
reshape(view_rect.getWidth(), view_rect.getHeight());
}
+void LLView::parseFollowsFlags(LLXMLNodePtr node)
+{
+ if (node->hasAttribute("follows"))
+ {
+ setFollowsNone();
+
+ LLString follows;
+ node->getAttributeString("follows", follows);
+
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("|");
+ tokenizer tokens(follows, sep);
+ tokenizer::iterator token_iter = tokens.begin();
+
+ while(token_iter != tokens.end())
+ {
+ const std::string& token_str = *token_iter;
+ if (token_str == "left")
+ {
+ setFollowsLeft();
+ }
+ else if (token_str == "right")
+ {
+ setFollowsRight();
+ }
+ else if (token_str == "top")
+ {
+ setFollowsTop();
+ }
+ else if (token_str == "bottom")
+ {
+ setFollowsBottom();
+ }
+ else if (token_str == "all")
+ {
+ setFollowsAll();
+ }
+ ++token_iter;
+ }
+ }
+}
+
+
// static
LLFontGL* LLView::selectFont(LLXMLNodePtr node)
{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 8248d50d9d..e54983d67d 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -50,6 +50,7 @@
#include "llviewquery.h"
#include "llxmlnode.h"
#include "stdenums.h"
+#include "lluistring.h"
class LLColor4;
class LLWindow;
@@ -146,6 +147,7 @@ protected:
LLString mName;
// location in pixels, relative to surrounding structure, bottom,left=0,0
LLRect mRect;
+ LLRect mBoundingRect;
U32 mReshapeFlags;
@@ -161,11 +163,11 @@ protected:
BOOL mSaveToXML;
BOOL mIsFocusRoot;
+ BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements
public:
LLViewHandle mViewHandle;
BOOL mLastVisible;
- BOOL mSpanChildren;
private:
BOOL mVisible;
@@ -217,6 +219,7 @@ public:
void setMouseOpaque( BOOL b );
void setToolTip( const LLStringExplicit& msg );
BOOL setToolTipArg( const LLStringExplicit& key, const LLStringExplicit& text );
+ void setToolTipArgs( const LLString::format_map_t& args );
virtual void setRect(const LLRect &rect);
void setFollows(U32 flags);
@@ -231,13 +234,15 @@ public:
void setSoundFlags(U8 flags);
void setName(LLString name);
- void setSpanChildren( BOOL span_children );
+ void setUseBoundingRect( BOOL use_bounding_rect );
+ BOOL getUseBoundingRect();
const LLString& getToolTip();
void sendChildToFront(LLView* child);
void sendChildToBack(LLView* child);
void moveChildToFrontOfTabGroup(LLUICtrl* child);
+ void moveChildToBackOfTabGroup(LLUICtrl* child);
void addChild(LLView* view, S32 tab_group = 0);
void addChildAtEnd(LLView* view, S32 tab_group = 0);
@@ -264,7 +269,7 @@ public:
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
{
- return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot());
+ return filterResult_t(view->isCtrl() && view->isFocusRoot(), TRUE);
}
};
@@ -312,20 +317,22 @@ public:
BOOL followsAll() const { return mReshapeFlags & FOLLOWS_ALL; }
const LLRect& getRect() const { return mRect; }
+ const LLRect& getBoundingRect() const { return mBoundingRect; }
+ const LLRect getLocalBoundingRect() const;
const LLRect getScreenRect() const;
const LLRect getLocalRect() const;
virtual const LLRect getSnapRect() const { return mRect; }
virtual const LLRect getLocalSnapRect() const;
virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care.
- virtual void updateRect(); // apply procedural updates to own rectangle
+ void updateBoundingRect();
LLView* getRootView();
LLView* getParent() const { return mParentView; }
LLView* getFirstChild() { return (mChildList.empty()) ? NULL : *(mChildList.begin()); }
S32 getChildCount() const { return (S32)mChildList.size(); }
template<class _Pr3> void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); }
- BOOL hasAncestor(LLView* parentp);
+ BOOL hasAncestor(const LLView* parentp);
BOOL hasChild(const LLString& childname, BOOL recurse = FALSE) const;
@@ -390,6 +397,7 @@ public:
static U32 createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect = LLRect());
virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
+ void parseFollowsFlags(LLXMLNodePtr node);
static LLFontGL* selectFont(LLXMLNodePtr node);
static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node);
@@ -428,12 +436,16 @@ public:
BOOL getVisible() const { return mVisible && !mHidden; }
U8 getSoundFlags() const { return mSoundFlags; }
- // Default to no action
- virtual void onFocusLost();
- virtual void onFocusReceived();
+ typedef enum e_hit_test_type
+ {
+ HIT_TEST_USE_BOUNDING_RECT,
+ HIT_TEST_IGNORE_BOUNDING_RECT
+ }EHitTestType;
+
+ BOOL parentPointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
+ BOOL pointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
+ BOOL blockMouseEvent(S32 x, S32 y) const;
- BOOL parentPointInView(S32 x, S32 y) const { return mRect.pointInRect( x, y ); }
- BOOL pointInView(S32 x, S32 y) const { return mRect.localPointInRect( x, y ); }
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
virtual BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view);
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index f6cbe3aac1..8fbe671613 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -84,7 +84,7 @@ void LLViewBorder::setColorsExtended( const LLColor4& shadow_light, const LLColo
void LLViewBorder::setTexture( const LLUUID &image_id )
{
- mTexture = LLUI::sImageProvider->getUIImageByID(image_id);
+ mTexture = LLUI::sImageProvider->getImageByID(image_id);
}
diff --git a/indra/llui/llviewquery.cpp b/indra/llui/llviewquery.cpp
index c07587f0ff..db00c76821 100644
--- a/indra/llui/llviewquery.cpp
+++ b/indra/llui/llviewquery.cpp
@@ -37,9 +37,14 @@
void LLQuerySorter::operator() (LLView * parent, viewList_t &children) const {}
-filterResult_t LLNoLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const
+filterResult_t LLLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const
{
- return filterResult_t(!(view->getChildList()->size() == 0), TRUE);
+ return filterResult_t(children.empty(), TRUE);
+}
+
+filterResult_t LLRootsFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(TRUE, FALSE);
}
filterResult_t LLVisibleFilter::operator() (const LLView* const view, const viewList_t & children) const
@@ -56,6 +61,16 @@ filterResult_t LLTabStopFilter::operator() (const LLView* const view, const view
view->canFocusChildren());
}
+filterResult_t LLCtrlFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(view->isCtrl(),TRUE);
+}
+
+filterResult_t LLWidgetTypeFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(view->getWidgetType() == mType, TRUE);
+}
+
// LLViewQuery
LLViewQuery::LLViewQuery(): mPreFilters(), mPostFilters(), mSorterp()
@@ -73,45 +88,53 @@ const LLViewQuery::filterList_t & LLViewQuery::getPostFilters() const { return m
void LLViewQuery::setSorter(const LLQuerySorter* sorterp) { mSorterp = sorterp; }
const LLQuerySorter* LLViewQuery::getSorter() const { return mSorterp; }
-viewList_t LLViewQuery::run(LLView * view) const
+viewList_t LLViewQuery::run(LLView* view) const
{
viewList_t result;
- filterResult_t pre = runFilters(view, viewList_t(), mPreFilters);
+ // prefilter gets immediate children of view
+ filterResult_t pre = runFilters(view, *view->getChildList(), mPreFilters);
if(!pre.first && !pre.second)
{
- // skip post filters completely if we're not including ourselves or the children
+ // not including ourselves or the children
+ // nothing more to do
return result;
}
+
+ viewList_t filtered_children;
+ filterResult_t post(TRUE, TRUE);
if(pre.second)
{
// run filters on children
- viewList_t filtered_children;
filterChildren(view, filtered_children);
- filterResult_t post = runFilters(view, filtered_children, mPostFilters);
- if(pre.first && post.first)
- {
- result.push_back(view);
- }
- if(post.second)
+ // only run post filters if this element passed pre filters
+ // so if you failed to pass the pre filter, you can't filter out children in post
+ if (pre.first)
{
- result.insert(result.end(), filtered_children.begin(), filtered_children.end());
+ post = runFilters(view, filtered_children, mPostFilters);
}
}
- else
+
+ if(pre.first && post.first)
{
- if(pre.first)
- {
- result.push_back(view);
- }
+ result.push_back(view);
+ }
+
+ if(pre.second && post.second)
+ {
+ result.insert(result.end(), filtered_children.begin(), filtered_children.end());
}
+
return result;
}
void LLViewQuery::filterChildren(LLView * view, viewList_t & filtered_children) const
{
LLView::child_list_t views(*(view->getChildList()));
- (*mSorterp)(view, views); // sort the children per the sorter
+ if (mSorterp)
+ {
+ (*mSorterp)(view, views); // sort the children per the sorter
+ }
for(LLView::child_list_iter_t iter = views.begin();
iter != views.end();
iter++)
diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h
index 3919ba4bcb..63559e8240 100644
--- a/indra/llui/llviewquery.h
+++ b/indra/llui/llviewquery.h
@@ -35,6 +35,7 @@
#include <list>
#include "llmemory.h"
+#include "llui.h"
class LLView;
@@ -42,35 +43,60 @@ typedef std::list<LLView *> viewList_t;
typedef std::pair<BOOL, BOOL> filterResult_t;
// Abstract base class for all filters.
-class LLQueryFilter : public LLRefCount
+class LLQueryFilter
{
public:
+ virtual ~LLQueryFilter() {};
virtual filterResult_t operator() (const LLView* const view, const viewList_t & children) const =0;
};
-class LLQuerySorter : public LLRefCount
+class LLQuerySorter
{
public:
+ virtual ~LLQuerySorter() {};
virtual void operator() (LLView * parent, viewList_t &children) const;
};
-class LLNoLeavesFilter : public LLQueryFilter, public LLSingleton<LLNoLeavesFilter>
+class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter>
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
+
+class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+
class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
+
class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
+
class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
{
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
+class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+
+class LLWidgetTypeFilter : public LLQueryFilter
+{
+public:
+ LLWidgetTypeFilter(EWidgetType type) : mType(type) {};
+private:
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+
+ EWidgetType mType;
+};
+
// Algorithm for flattening
class LLViewQuery
{
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 5aaf9d0097..a692ef6a3e 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -2880,7 +2880,7 @@ void LLAgent::endAnimationUpdateUI()
mCameraLag.clearVec();
// JC - Added for always chat in third person option
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
gToolMgr->setCurrentToolset(gMouselookToolset);
@@ -4004,7 +4004,7 @@ void LLAgent::changeCameraToMouselook(BOOL animate)
if( mCameraMode != CAMERA_MODE_MOUSELOOK )
{
- gViewerWindow->setKeyboardFocus( NULL, NULL );
+ gViewerWindow->setKeyboardFocus( NULL );
mLastCameraMode = mCameraMode;
mCameraMode = CAMERA_MODE_MOUSELOOK;
@@ -4225,7 +4225,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL animate)
mbFlagsDirty = TRUE;
}
- gViewerWindow->setKeyboardFocus( NULL, NULL );
+ gViewerWindow->setKeyboardFocus( NULL );
gViewerWindow->setMouseCapture( NULL );
LLVOAvatar::onCustomizeStart();
@@ -5225,6 +5225,102 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
}
}
+class LLAgentDropGroupViewerNode : public LLHTTPNode
+{
+ virtual void post(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+
+ if (
+ !input.isMap() ||
+ !input.has("body") )
+ {
+ //what to do with badly formed message?
+ response->status(400);
+ response->result(LLSD("Invalid message parameters"));
+ }
+
+ LLSD body = input["body"];
+ if ( body.has("body") )
+ {
+ //stupid message system doubles up the "body"s
+ body = body["body"];
+ }
+
+ if (
+ body.has("AgentData") &&
+ body["AgentData"].isArray() &&
+ body["AgentData"][0].isMap() )
+ {
+ llinfos << "VALID DROP GROUP" << llendl;
+
+ //there is only one set of data in the AgentData block
+ LLSD agent_data = body["AgentData"][0];
+ LLUUID agent_id;
+ LLUUID group_id;
+
+ agent_id = agent_data["AgentID"].asUUID();
+ group_id = agent_data["GroupID"].asUUID();
+
+ if (agent_id != gAgentID)
+ {
+ llwarns
+ << "AgentDropGroup for agent other than me" << llendl;
+
+ response->notFound();
+ return;
+ }
+
+ // Remove the group if it already exists remove it
+ // and add the new data to pick up changes.
+ LLGroupData gd;
+ gd.mID = group_id;
+ S32 index = gAgent.mGroups.find(gd);
+ if (index != -1)
+ {
+ gAgent.mGroups.remove(index);
+ if (gAgent.getGroupID() == group_id)
+ {
+ gAgent.mGroupID.setNull();
+ gAgent.mGroupPowers = 0;
+ gAgent.mGroupName[0] = '\0';
+ gAgent.mGroupTitle[0] = '\0';
+ }
+
+ // refresh all group information
+ gAgent.sendAgentDataUpdateRequest();
+
+ gGroupMgr->clearGroupData(group_id);
+ // close the floater for this group, if any.
+ LLFloaterGroupInfo::closeGroup(group_id);
+ // refresh the group panel of the search window,
+ //if necessary.
+ LLFloaterDirectory::refreshGroup(group_id);
+ }
+ else
+ {
+ llwarns
+ << "AgentDropGroup, agent is not part of group "
+ << group_id << llendl;
+ }
+
+ response->result(LLSD());
+ }
+ else
+ {
+ //what to do with badly formed message?
+ response->status(400);
+ response->result(LLSD("Invalid message parameters"));
+ }
+ }
+};
+
+LLHTTPRegistration<LLAgentDropGroupViewerNode>
+ gHTTPRegistrationAgentDropGroupViewerNode(
+ "/message/AgentDropGroup");
+
// static
void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **)
{
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ad934abfa7..8b126b7597 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -425,7 +425,7 @@ static void ui_audio_callback(const LLUUID& uuid)
{
if (gAudiop)
{
- F32 volume = gSavedSettings.getF32("AudioLevelUI");
+ F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
gAudiop->triggerSound(uuid, gAgent.getID(), volume);
}
}
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index c3c892a572..76cfe92c4c 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -252,7 +252,6 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
if(view)
{
LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback();
view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
if((LLAssetType::AT_TEXTURE == asset_type)
@@ -262,7 +261,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
}
//LLInventoryView::dumpSelectionInformation((void*)view);
// restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus_ctrl, callback);
+ gFocusMgr.setKeyboardFocus(focus_ctrl);
}
}
else
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 3517c1e18a..78365e66f1 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -93,51 +93,20 @@ private:
// Functions
//
-//inline constructor
-// for chat bars embedded in floaters, etc
-LLChatBar::LLChatBar(const std::string& name)
-: LLPanel(name, LLRect(), BORDER_NO),
+LLChatBar::LLChatBar()
+: LLPanel("", LLRect(), BORDER_NO),
mInputEditor(NULL),
mGestureLabelTimer(),
mLastSpecialChatChannel(0),
mIsBuilt(FALSE),
- mDynamicLayout(FALSE),
- mGestureCombo(NULL),
- mObserver(NULL)
-{
-}
-
-LLChatBar::LLChatBar(const std::string& name, const LLRect& rect)
-: LLPanel(name, rect, BORDER_NO),
- mInputEditor(NULL),
- mGestureLabelTimer(),
- mLastSpecialChatChannel(0),
- mIsBuilt(FALSE),
- mDynamicLayout(TRUE),
mGestureCombo(NULL),
mObserver(NULL)
{
setIsChrome(TRUE);
- gUICtrlFactory->buildPanel(this,"panel_chat_bar.xml");
-
- mIsFocusRoot = TRUE;
-
- setRect(rect); // override xml rect
-
- setBackgroundOpaque(TRUE);
- setBackgroundVisible(TRUE);
-
- // Start visible if we left the app while chatting.
- setVisible( gSavedSettings.getBOOL("ChatVisible") );
-
- // Apply custom layout.
- layout();
-
-#if !LL_RELEASE_FOR_DOWNLOAD
+ #if !LL_RELEASE_FOR_DOWNLOAD
childDisplayNotFound();
#endif
-
}
@@ -151,25 +120,18 @@ LLChatBar::~LLChatBar()
BOOL LLChatBar::postBuild()
{
childSetAction("History", toggleChatHistory, this);
- childSetAction("Say", onClickSay, this);
- childSetAction("Shout", onClickShout, this);
+ childSetCommitCallback("Say", onClickSay, this);
// attempt to bind to an existing combo box named gesture
setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture"));
- LLButton * sayp = static_cast<LLButton*>(getChildByName("Say", TRUE));
- if(sayp)
- {
- setDefaultBtn(sayp);
- }
-
mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "Chat Editor");
if (mInputEditor)
{
mInputEditor->setCallbackUserData(this);
mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke);
- mInputEditor->setFocusLostCallback(&onInputEditorFocusLost);
- mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus );
+ mInputEditor->setFocusLostCallback(&onInputEditorFocusLost, this);
+ mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus, this );
mInputEditor->setCommitOnFocusLost( FALSE );
mInputEditor->setRevertOnEsc( FALSE );
mInputEditor->setIgnoreTab(TRUE);
@@ -189,16 +151,6 @@ BOOL LLChatBar::postBuild()
//-----------------------------------------------------------------------
// virtual
-void LLChatBar::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLPanel::reshape(width, height, called_from_parent);
- if (mIsBuilt)
- {
- layout();
- }
-}
-
-// virtual
BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
{
BOOL handled = FALSE;
@@ -208,13 +160,6 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
// ALT-RETURN is reserved for windowed/fullscreen toggle
if( KEY_RETURN == key )
{
- //if (childGetValue("Chat Editor").asString().empty())
- //{
- // // no text, just close chat bar
- // stopChat();
- // return TRUE;
- //}
-
if (mask == MASK_CONTROL)
{
// shout
@@ -239,78 +184,8 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
return handled;
}
-
-void LLChatBar::layout()
-{
- if (!mDynamicLayout) return;
-
- S32 rect_width = mRect.getWidth();
- S32 count = 9; // number of elements in LLToolBar
- S32 pad = 4;
-
- LLRect gesture_rect;
- S32 gesture_width = 0;
- if (childGetRect("Gesture", gesture_rect))
- {
- gesture_width = gesture_rect.getWidth();
- }
- F32 segment_width = (F32)(rect_width - (pad + gesture_width)) / (F32)count;
-
- S32 btn_width = lltrunc(segment_width-pad);
-
- S32 x = 0;
- S32 y = 1;
- LLRect r;
-
- x = llround(0 * segment_width);
- r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
- childSetRect("History", r);
-
- x = llround(1 * segment_width);
- // Hack this one up so it looks nice.
- if (mInputEditor)
- {
- r.setOriginAndSize(x, y+2, llfloor(6*segment_width-pad), 18);
- mInputEditor->reshape(r.getWidth(), r.getHeight(), TRUE);
- mInputEditor->setRect(r);
- }
-
- x = llround(7 * segment_width);
- r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
- childSetRect("Say", r);
-
- x = llround(8 * segment_width);
- r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
- childSetRect("Shout", r);
-
- x = rect_width - (pad + gesture_width);
- r.setOriginAndSize(x, y, gesture_width, BTN_HEIGHT);
- childSetRect("Gesture", r);
-}
-
-
void LLChatBar::refresh()
{
- //BOOL chat_mode = gSavedSettings.getBOOL("ChatVisible");
-
- //// Grab focus when no one else has it, and we're in chat mode.
- //if (!gFocusMgr.getKeyboardFocus()
- // && chat_mode)
- //{
- // childSetFocus("Chat Editor", TRUE);
- //}
-
- // Only show this view when user wants to be chatting
- //setVisible(chat_mode);
-
- // hide in mouselook, but keep previous visibility state
- //BOOL mouselook = gAgent.cameraMouselook();
- // call superclass setVisible so that we don't overwrite the saved setting
- if (mDynamicLayout)
- {
- LLPanel::setVisible(gSavedSettings.getBOOL("ChatVisible"));
- }
-
// HACK: Leave the name of the gesture in place for a few seconds.
const F32 SHOW_GESTURE_NAME_TIME = 2.f;
if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME)
@@ -584,12 +459,7 @@ void LLChatBar::stopChat()
// hide chat bar so it doesn't grab focus back
gChatBar->setVisible(FALSE);
-}
-
-void LLChatBar::setVisible(BOOL visible)
-{
- gSavedSettings.setBOOL("ChatVisible", visible);
- LLPanel::setVisible(visible);
+ gSavedSettings.setBOOL("ChatVisible", FALSE);
}
// static
@@ -663,30 +533,30 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
}
// static
-void LLChatBar::onInputEditorFocusLost( LLUICtrl* caller, void* userdata)
+void LLChatBar::onInputEditorFocusLost( LLFocusableElement* caller, void* userdata)
{
// stop typing animation
gAgent.stopTyping();
}
// static
-void LLChatBar::onInputEditorGainFocus( LLUICtrl* caller, void* userdata )
+void LLChatBar::onInputEditorGainFocus( LLFocusableElement* caller, void* userdata )
{
LLFloaterChat::setHistoryCursorAndScrollToEnd();
}
// static
-void LLChatBar::onClickSay( void* userdata )
+void LLChatBar::onClickSay( LLUICtrl* ctrl, void* userdata )
{
LLChatBar* self = (LLChatBar*) userdata;
- self->sendChat( CHAT_TYPE_NORMAL );
-}
-
-// static
-void LLChatBar::onClickShout( void* userdata )
-{
- LLChatBar *self = (LLChatBar *)userdata;
- self->sendChat( CHAT_TYPE_SHOUT );
+ if (ctrl->getValue().asString() == "shout")
+ {
+ self->sendChat( CHAT_TYPE_SHOUT );
+ }
+ else
+ {
+ self->sendChat( CHAT_TYPE_NORMAL );
+ }
}
void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
diff --git a/indra/newview/llchatbar.h b/indra/newview/llchatbar.h
index 76a80125ae..f198574dcd 100644
--- a/indra/newview/llchatbar.h
+++ b/indra/newview/llchatbar.h
@@ -49,17 +49,12 @@ class LLChatBar
{
public:
// constructor for inline chat-bars (e.g. hosted in chat history window)
- LLChatBar(const std::string& name);
- LLChatBar(const std::string& name, const LLRect& rect);
+ LLChatBar();
~LLChatBar();
virtual BOOL postBuild();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
- // Adjust buttons and input field for width
- void layout();
-
void refresh();
void refreshGestures();
@@ -86,20 +81,18 @@ public:
LLWString stripChannelNumber(const LLWString &mesg, S32* channel);
// callbacks
- static void onClickSay( void* userdata );
- static void onClickShout( void* userdata );
+ static void onClickSay( LLUICtrl*, void* userdata );
static void onTabClick( void* userdata );
static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
- static void onInputEditorFocusLost(LLUICtrl* caller,void* userdata);
- static void onInputEditorGainFocus(LLUICtrl* caller,void* userdata);
+ static void onInputEditorFocusLost(LLFocusableElement* caller,void* userdata);
+ static void onInputEditorGainFocus(LLFocusableElement* caller,void* userdata);
static void onCommitGesture(LLUICtrl* ctrl, void* data);
static void startChat(void*);
static void stopChat();
- /*virtual*/ void setVisible(BOOL visible);
protected:
void sendChat(EChatType type);
void updateChat();
@@ -113,7 +106,6 @@ protected:
S32 mLastSpecialChatChannel;
BOOL mIsBuilt;
- BOOL mDynamicLayout;
LLComboBox* mGestureCombo;
LLChatBarGestureObserver* mObserver;
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index 693ffe091b..18c3983b9a 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -155,7 +155,6 @@ BOOL LLFloaterAnimPreview::postBuild()
mPlayButton->setDisabledImages("","");
mPlayButton->setScaleImage(TRUE);
- mPlayButton->setFixedBorder(0, 0);
mStopButton = LLViewerUICtrlFactory::getButtonByName(this, "stop_btn");
if (!mStopButton)
@@ -170,7 +169,6 @@ BOOL LLFloaterAnimPreview::postBuild()
mStopButton->setDisabledImages("","");
mStopButton->setScaleImage(TRUE);
- mStopButton->setFixedBorder(0, 0);
r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT);
childSetCommitCallback("playback_slider", onSliderMove, this);
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index a2ea8c2794..8dcd38c0bb 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -189,12 +189,15 @@ void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata)
return;
}
- std::vector<LLScrollListItem*> items = self->mListNames->getAllSelected();
- for (std::vector<LLScrollListItem*>::iterator iter = items.begin();
- iter != items.end(); ++iter)
+ std::vector<LLScrollListItem*> items =
+ self->mListNames->getAllSelected();
+ for (
+ std::vector<LLScrollListItem*>::iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
{
LLScrollListItem* item = *iter;
- self->mAvatarNames.push_back(item->getColumn(0)->getText());
+ self->mAvatarNames.push_back(item->getColumn(0)->getValue().asString());
self->mAvatarIDs.push_back(item->getUUID());
self->childSetEnabled("Select", TRUE);
}
@@ -225,8 +228,8 @@ void LLFloaterAvatarPicker::doSelectionChange(const std::deque<LLFolderViewItem*
mAvatarNames.clear();
childSetEnabled("Select", FALSE);
}
+ BOOL first_calling_card = TRUE;
- BOOL first_calling_card = TRUE;
std::deque<LLFolderViewItem*>::const_iterator item_it;
for (item_it = items.begin(); item_it != items.end(); ++item_it)
{
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 5fdbf7d408..82fe16172b 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -164,10 +164,16 @@ void LLFloaterChat::onVisibilityChange(BOOL new_visibility)
{
// Hide the chat overlay when our history is visible.
gConsole->setVisible( !new_visibility );
+
+ // stop chat history tab from flashing when it appears
+ if (new_visibility)
+ {
+ LLFloaterChatterBox::getInstance()->setFloaterFlashing(this, FALSE);
+ }
+
LLFloater::onVisibilityChange(new_visibility);
}
-
void add_timestamped_line(LLViewerTextEditor* edit, const LLString& line, const LLColor4& color)
{
bool prepend_newline = true;
@@ -238,6 +244,12 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
{
chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT);
}
+
+ // start tab flashing on incoming text from other users (ignoring system text, etc)
+ if (!chat_floater->isInVisibleChain() && chat.mSourceType == CHAT_SOURCE_AGENT)
+ {
+ LLFloaterChatterBox::getInstance()->setFloaterFlashing(chat_floater, TRUE);
+ }
}
// static
@@ -246,8 +258,14 @@ void LLFloaterChat::setHistoryCursorAndScrollToEnd()
LLViewerTextEditor* history_editor = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor", TRUE);
LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor with mute", TRUE);
- history_editor->setCursorAndScrollToEnd();
- history_editor_with_mute->setCursorAndScrollToEnd();
+ if (history_editor)
+ {
+ history_editor->setCursorAndScrollToEnd();
+ }
+ if (history_editor_with_mute)
+ {
+ history_editor_with_mute->setCursorAndScrollToEnd();
+ }
}
@@ -269,7 +287,7 @@ void LLFloaterChat::onClickMute(void *data)
if (gFloaterMute)
{
- gFloaterMute->show();
+ LLFloaterMute::showInstance();
}
}
@@ -433,7 +451,7 @@ void* LLFloaterChat::createSpeakersPanel(void* data)
//static
void* LLFloaterChat::createChatPanel(void* data)
{
- LLChatBar* chatp = new LLChatBar("floating_chat_bar");
+ LLChatBar* chatp = new LLChatBar();
return chatp;
}
@@ -441,7 +459,7 @@ void* LLFloaterChat::createChatPanel(void* data)
void LLFloaterChat::hideInstance(const LLSD& id)
{
LLFloaterChat* floaterp = LLFloaterChat::getInstance(LLSD());
- // don't do anything when hosted in the chatterbox
+
if(floaterp->getHost())
{
LLFloaterChatterBox::hideInstance(LLSD());
diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h
index 808393b267..58fa607b38 100644
--- a/indra/newview/llfloaterchat.h
+++ b/indra/newview/llfloaterchat.h
@@ -82,6 +82,7 @@ public:
protected:
LLPanelActiveSpeakers* mPanel;
+ BOOL mScrolledToEnd;
};
#endif
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index bdd30906d2..85bc8182a5 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -86,9 +86,15 @@ LLFloaterMyFriends* LLFloaterMyFriends::showInstance(const LLSD& id)
//static
void LLFloaterMyFriends::hideInstance(const LLSD& id)
{
- if(instanceVisible(id))
+ LLFloaterMyFriends* floaterp = LLFloaterMyFriends::getInstance();
+
+ if(floaterp->getHost())
{
- LLFloaterChatterBox::hideInstance(LLSD());
+ LLFloaterChatterBox::hideInstance();
+ }
+ else
+ {
+ LLUISingleton<LLFloaterMyFriends>::hideInstance(id);
}
}
@@ -124,10 +130,23 @@ LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) :
mAutoResize = FALSE;
gUICtrlFactory->buildFloater(this, "floater_chatterbox.xml", NULL, FALSE);
- addFloater(LLFloaterMyFriends::getInstance(0), TRUE);
+ if (gSavedSettings.getBOOL("ContactsTornOff"))
+ {
+ LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(0);
+ // add then remove to set up relationship for re-attach
+ addFloater(floater_contacts, FALSE);
+ removeFloater(floater_contacts);
+ // reparent to floater view
+ gFloaterView->addChild(floater_contacts);
+ }
+ else
+ {
+ addFloater(LLFloaterMyFriends::getInstance(0), TRUE);
+ }
+
if (gSavedSettings.getBOOL("ChatHistoryTornOff"))
{
- LLFloaterChat* floater_chat = LLFloaterChat::getInstance(LLSD());
+ LLFloaterChat* floater_chat = LLFloaterChat::getInstance();
// add then remove to set up relationship for re-attach
addFloater(floater_chat, FALSE);
removeFloater(floater_chat);
@@ -217,7 +236,7 @@ void LLFloaterChatterBox::draw()
mActiveVoiceFloater = current_active_floater;
- LLFloater::draw();
+ LLMultiFloater::draw();
}
void LLFloaterChatterBox::onOpen()
@@ -236,10 +255,17 @@ void LLFloaterChatterBox::removeFloater(LLFloater* floaterp)
if (floaterp->getName() == "chat floater")
{
// only my friends floater now locked
- mTabContainer->lockTabs(1);
+ mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1);
gSavedSettings.setBOOL("ChatHistoryTornOff", TRUE);
floaterp->setCanClose(TRUE);
}
+ else if (floaterp->getName() == "floater_my_friends")
+ {
+ // only chat floater now locked
+ mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1);
+ gSavedSettings.setBOOL("ContactsTornOff", TRUE);
+ floaterp->setCanClose(TRUE);
+ }
LLMultiFloater::removeFloater(floaterp);
}
@@ -247,19 +273,43 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainerCommon::eInsertionPoint insertion_point)
{
+ S32 num_locked_tabs = mTabContainer->getNumLockedTabs();
+
+ // already here
+ if (floaterp->getHost() == this) return;
+
// make sure my friends and chat history both locked when re-attaching chat history
if (floaterp->getName() == "chat floater")
{
- // select my friends tab
- mTabContainer->selectFirstTab();
- // add chat history to the right of the my friends tab
- //*TODO: respect select_added_floater so that we don't leave first tab selected
- LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT);
+ mTabContainer->unlockTabs();
+ // add chat history as second tab if contact window is present, first tab otherwise
+ if (getChildByName("floater_my_friends", TRUE))
+ {
+ // assuming contacts window is first tab, select it
+ mTabContainer->selectFirstTab();
+ // and add ourselves after
+ LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT);
+ }
+ else
+ {
+ LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START);
+ }
+
// make sure first two tabs are now locked
- mTabContainer->lockTabs(2);
+ mTabContainer->lockTabs(num_locked_tabs + 1);
gSavedSettings.setBOOL("ChatHistoryTornOff", FALSE);
floaterp->setCanClose(FALSE);
}
+ else if (floaterp->getName() == "floater_my_friends")
+ {
+ mTabContainer->unlockTabs();
+ // add contacts window as first tab
+ LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START);
+ // make sure first two tabs are now locked
+ mTabContainer->lockTabs(num_locked_tabs + 1);
+ gSavedSettings.setBOOL("ContactsTornOff", FALSE);
+ floaterp->setCanClose(FALSE);
+ }
else
{
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
@@ -276,24 +326,27 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp,
//static
LLFloaterChatterBox* LLFloaterChatterBox::showInstance(const LLSD& seed)
{
- LLFloaterChatterBox* floater = LLUISingleton<LLFloaterChatterBox>::showInstance(seed);
+ LLFloaterChatterBox* chatterbox_floater = LLUISingleton<LLFloaterChatterBox>::showInstance(seed);
// if TRUE, show tab for active voice channel, otherwise, just show last tab
- if (seed.asBoolean())
+ LLFloater* floater_to_show = NULL;
+ LLUUID session_id = seed.asUUID();
+ if (session_id.notNull())
{
- LLFloater* floater_to_show = getCurrentVoiceFloater();
- if (floater_to_show)
- {
- floater_to_show->open();
- }
- else
- {
- // just open chatterbox if there is no active voice window
- LLUISingleton<LLFloaterChatterBox>::getInstance(seed)->open();
- }
+ floater_to_show = gIMMgr->findFloaterBySession(session_id);
+ }
+
+ if (floater_to_show)
+ {
+ floater_to_show->open();
+ }
+ else
+ {
+ // just open chatterbox to the last selected tab
+ chatterbox_floater->open();
}
- return floater;
+ return chatterbox_floater;
}
//static
diff --git a/indra/newview/llfloaterchatterbox.h b/indra/newview/llfloaterchatterbox.h
index 34410935f2..bf06ee9d38 100644
--- a/indra/newview/llfloaterchatterbox.h
+++ b/indra/newview/llfloaterchatterbox.h
@@ -50,7 +50,7 @@ public:
void onClose(bool app_quitting);
// override LLUISingleton behavior
- static LLFloaterMyFriends* showInstance(const LLSD& id);
+ static LLFloaterMyFriends* showInstance(const LLSD& id = LLSD());
static void hideInstance(const LLSD& id);
static BOOL instanceVisible(const LLSD& id);
@@ -77,7 +77,7 @@ public:
BOOL select_added_floater,
LLTabContainerCommon::eInsertionPoint insertion_point = LLTabContainerCommon::END);
- static LLFloaterChatterBox* showInstance(const LLSD& seed);
+ static LLFloaterChatterBox* showInstance(const LLSD& seed = LLSD());
static BOOL instanceVisible(const LLSD& seed);
static LLFloater* getCurrentVoiceFloater();
diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp
index 6f4945e54b..9d52107a20 100644
--- a/indra/newview/llfloaterfriends.cpp
+++ b/indra/newview/llfloaterfriends.cpp
@@ -104,7 +104,6 @@ LLPanelFriends::LLPanelFriends() :
LLPanel(),
LLEventTimer(1000000),
mObserver(NULL),
- mMenuState(0),
mShowMaxSelectWarning(TRUE),
mAllowRightsChange(TRUE),
mNumRightsChanged(0)
@@ -182,16 +181,13 @@ BOOL LLPanelFriends::postBuild()
{
mFriendsList = LLUICtrlFactory::getScrollListByName(this, "friend_list");
mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT);
- mFriendsList->setMaxiumumSelectCallback(onMaximumSelect);
+ mFriendsList->setMaximumSelectCallback(onMaximumSelect);
mFriendsList->setCommitOnSelectionChange(TRUE);
childSetCommitCallback("friend_list", onSelectName, this);
childSetDoubleClickCallback("friend_list", onClickIM);
refreshNames();
- childSetCommitCallback("online_status_cb", onClickOnlineStatus, this);
- childSetCommitCallback("map_status_cb", onClickMapStatus, this);
- childSetCommitCallback("modify_status_cb", onClickModifyStatus, this);
childSetAction("im_btn", onClickIM, this);
childSetAction("profile_btn", onClickProfile, this);
childSetAction("offer_teleport_btn", onClickOfferTeleport, this);
@@ -204,6 +200,10 @@ BOOL LLPanelFriends::postBuild()
updateFriends(LLFriendObserver::ADD);
refreshUI();
+ // primary sort = online status, secondary sort = name
+ mFriendsList->sortByColumn("friend_name", TRUE);
+ mFriendsList->sortByColumn("icon_online_status", TRUE);
+
return TRUE;
}
@@ -222,64 +222,63 @@ void LLPanelFriends::addFriend(const std::string& name, const LLUUID& agent_id)
element["columns"][LIST_FRIEND_NAME]["font"] = "SANSSERIF";
element["columns"][LIST_FRIEND_NAME]["font-style"] = "NORMAL";
element["columns"][LIST_ONLINE_STATUS]["column"] = "icon_online_status";
- element["columns"][LIST_ONLINE_STATUS]["type"] = "text";
+ element["columns"][LIST_ONLINE_STATUS]["type"] = "icon";
if (online)
{
element["columns"][LIST_FRIEND_NAME]["font-style"] = "BOLD";
- element["columns"][LIST_ONLINE_STATUS]["type"] = "icon";
element["columns"][LIST_ONLINE_STATUS]["value"] = gViewerArt.getString("icon_avatar_online.tga");
}
-
element["columns"][LIST_VISIBLE_ONLINE]["column"] = "icon_visible_online";
- element["columns"][LIST_VISIBLE_ONLINE]["type"] = "text";
- if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
- {
- element["columns"][LIST_VISIBLE_ONLINE]["type"] = "icon";
- element["columns"][LIST_VISIBLE_ONLINE]["value"] = gViewerArt.getString("ff_visible_online.tga");
- }
+ element["columns"][LIST_VISIBLE_ONLINE]["type"] = "checkbox";
+ element["columns"][LIST_VISIBLE_ONLINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS);
+
element["columns"][LIST_VISIBLE_MAP]["column"] = "icon_visible_map";
- element["columns"][LIST_VISIBLE_MAP]["type"] = "text";
- if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION))
- {
- element["columns"][LIST_VISIBLE_MAP]["type"] = "icon";
- element["columns"][LIST_VISIBLE_MAP]["value"] = gViewerArt.getString("ff_visible_map.tga");
- }
+ element["columns"][LIST_VISIBLE_MAP]["type"] = "checkbox";
+ element["columns"][LIST_VISIBLE_MAP]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION);
+
element["columns"][LIST_EDIT_MINE]["column"] = "icon_edit_mine";
- element["columns"][LIST_EDIT_MINE]["type"] = "text";
- if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS))
- {
- element["columns"][LIST_EDIT_MINE]["type"] = "icon";
- element["columns"][LIST_EDIT_MINE]["value"] = gViewerArt.getString("ff_edit_mine.tga");
- }
+ element["columns"][LIST_EDIT_MINE]["type"] = "checkbox";
+ element["columns"][LIST_EDIT_MINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
+
element["columns"][LIST_EDIT_THEIRS]["column"] = "icon_edit_theirs";
- element["columns"][LIST_EDIT_THEIRS]["type"] = "text";
- if(relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS))
- {
- element["columns"][LIST_EDIT_THEIRS]["type"] = "icon";
- element["columns"][LIST_EDIT_THEIRS]["value"] = gViewerArt.getString("ff_edit_theirs.tga");
- }
+ element["columns"][LIST_EDIT_THEIRS]["type"] = "checkbox";
+ element["columns"][LIST_EDIT_THEIRS]["enabled"] = "";
+ element["columns"][LIST_EDIT_THEIRS]["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS);
+
+ element["columns"][LIST_FRIEND_UPDATE_GEN]["column"] = "friend_last_update_generation";
+ element["columns"][LIST_FRIEND_UPDATE_GEN]["value"] = relationInfo->getChangeSerialNum();
+
mFriendsList->addElement(element, ADD_BOTTOM);
}
+// propagate actual relationship to UI
+void LLPanelFriends::updateFriendItem(LLScrollListItem* itemp, const LLRelationship* info)
+{
+ if (!itemp) return;
+ if (!info) return;
+
+ itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? gViewerArt.getString("icon_avatar_online.tga") : LLString());
+ // render name of online friends in bold text
+ ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
+ itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
+ itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
+ itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
+ itemp->getColumn(LIST_FRIEND_UPDATE_GEN)->setValue(info->getChangeSerialNum());
+
+ // enable this item, in case it was disabled after user input
+ itemp->setEnabled(TRUE);
+
+ // changed item in place, need to request sort
+ mFriendsList->sortItems();
+}
+
void LLPanelFriends::refreshRightsChangeList()
{
LLDynamicArray<LLUUID> friends = getSelectedIDs();
S32 num_selected = friends.size();
- LLSD row;
bool can_offer_teleport = num_selected >= 1;
-
- // aggregate permissions over all selected friends
- bool friends_see_online = true;
- bool friends_see_on_map = true;
- bool friends_modify_objects = true;
-
- // do at least some of the friends selected have these rights?
- bool some_friends_see_online = false;
- bool some_friends_see_on_map = false;
- bool some_friends_modify_objects = false;
-
bool selected_friends_online = true;
LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label");
@@ -294,12 +293,9 @@ void LLPanelFriends::refreshRightsChangeList()
num_selected = 0;
}
}
- else
+ else if(processing_label)
{
- if(processing_label)
- {
- processing_label->setVisible(false);
- }
+ processing_label->setVisible(false);
}
const LLRelationship* friend_status = NULL;
@@ -308,20 +304,6 @@ void LLPanelFriends::refreshRightsChangeList()
friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr);
if (friend_status)
{
- bool can_see_online = friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS);
- bool can_see_on_map = friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION);
- bool can_modify_objects = friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
-
- // aggregate rights of this friend into total selection
- friends_see_online &= can_see_online;
- friends_see_on_map &= can_see_on_map;
- friends_modify_objects &= can_modify_objects;
-
- // can at least one of your selected friends do any of these?
- some_friends_see_online |= can_see_online;
- some_friends_see_on_map |= can_see_on_map;
- some_friends_modify_objects |= can_modify_objects;
-
if(!friend_status->isOnline())
{
can_offer_teleport = false;
@@ -331,44 +313,13 @@ void LLPanelFriends::refreshRightsChangeList()
else // missing buddy info, don't allow any operations
{
can_offer_teleport = false;
-
- friends_see_online = false;
- friends_see_on_map = false;
- friends_modify_objects = false;
-
- some_friends_see_online = false;
- some_friends_see_on_map = false;
- some_friends_modify_objects = false;
}
}
-
- // seeing a friend on the map requires seeing online status as a prerequisite
- friends_see_on_map &= friends_see_online;
-
- mMenuState = 0;
-
- // make checkboxes visible after we have finished processing rights
- childSetVisible("online_status_cb", mAllowRightsChange);
- childSetVisible("map_status_cb", mAllowRightsChange);
- childSetVisible("modify_status_cb", mAllowRightsChange);
-
if (num_selected == 0) // nothing selected
{
childSetEnabled("im_btn", FALSE);
childSetEnabled("offer_teleport_btn", FALSE);
-
- childSetEnabled("online_status_cb", FALSE);
- childSetValue("online_status_cb", FALSE);
- childSetTentative("online_status_cb", FALSE);
-
- childSetEnabled("map_status_cb", FALSE);
- childSetValue("map_status_cb", FALSE);
- childSetTentative("map_status_cb", FALSE);
-
- childSetEnabled("modify_status_cb", FALSE);
- childSetValue("modify_status_cb", FALSE);
- childSetTentative("modify_status_cb", FALSE);
}
else // we have at least one friend selected...
{
@@ -376,61 +327,76 @@ void LLPanelFriends::refreshRightsChangeList()
// to be consistent with context menus in inventory and because otherwise
// offline friends would be silently dropped from the session
childSetEnabled("im_btn", selected_friends_online || num_selected == 1);
-
childSetEnabled("offer_teleport_btn", can_offer_teleport);
-
- childSetEnabled("online_status_cb", TRUE);
- childSetValue("online_status_cb", some_friends_see_online);
- childSetTentative("online_status_cb", some_friends_see_online != friends_see_online);
- if (friends_see_online)
- {
- mMenuState |= LLRelationship::GRANT_ONLINE_STATUS;
- }
-
- childSetEnabled("map_status_cb", TRUE);
- childSetValue("map_status_cb", some_friends_see_on_map);
- childSetTentative("map_status_cb", some_friends_see_on_map != friends_see_on_map);
- if(friends_see_on_map)
- {
- mMenuState |= LLRelationship::GRANT_MAP_LOCATION;
- }
-
- // for now, don't allow modify rights change for multiple select
- childSetEnabled("modify_status_cb", num_selected == 1);
- childSetValue("modify_status_cb", some_friends_modify_objects);
- childSetTentative("modify_status_cb", some_friends_modify_objects != friends_modify_objects);
- if(friends_modify_objects)
- {
- mMenuState |= LLRelationship::GRANT_MODIFY_OBJECTS;
- }
}
}
+struct SortFriendsByID
+{
+ bool SortFriendsByID::operator() (const LLScrollListItem* const a, const LLScrollListItem* const b) const
+ {
+ return a->getValue().asUUID() < b->getValue().asUUID();
+ }
+};
+
void LLPanelFriends::refreshNames()
{
LLDynamicArray<LLUUID> selected_ids = getSelectedIDs();
S32 pos = mFriendsList->getScrollPos();
- mFriendsList->operateOnAll(LLCtrlListInterface::OP_DELETE);
- LLCollectAllBuddies collect;
- LLAvatarTracker::instance().applyFunctor(collect);
- LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
- LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
+ // get all buddies we know about
+ LLAvatarTracker::buddy_map_t all_buddies;
+ LLAvatarTracker::instance().copyBuddyList(all_buddies);
- for ( ; it != end; ++it)
- {
- const std::string& name = it->first;
- const LLUUID& agent_id = it->second;
- addFriend(name, agent_id);
- }
- it = collect.mOffline.begin();
- end = collect.mOffline.end();
- for ( ; it != end; ++it)
+ // get all friends in list and sort by UUID
+ std::vector<LLScrollListItem*> items = mFriendsList->getAllData();
+ std::sort(items.begin(), items.end(), SortFriendsByID());
+
+ std::vector<LLScrollListItem*>::iterator item_it = items.begin();
+ std::vector<LLScrollListItem*>::iterator item_end = items.end();
+
+ LLAvatarTracker::buddy_map_t::iterator buddy_it;
+ for (buddy_it = all_buddies.begin() ; buddy_it != all_buddies.end(); ++buddy_it)
{
- const std::string& name = it->first;
- const LLUUID& agent_id = it->second;
- addFriend(name, agent_id);
+ // erase any items that reflect residents who are no longer buddies
+ while(item_it != item_end && buddy_it->first > (*item_it)->getValue().asUUID())
+ {
+ mFriendsList->deleteItems((*item_it)->getValue());
+ ++item_it;
+ }
+
+ // update existing friends with new info
+ if (item_it != item_end && buddy_it->first == (*item_it)->getValue().asUUID())
+ {
+ const LLRelationship* info = buddy_it->second;
+ if (!info)
+ {
+ ++item_it;
+ continue;
+ }
+
+ S32 last_change_generation = (*item_it)->getColumn(LIST_FRIEND_UPDATE_GEN)->getValue().asInteger();
+ if (last_change_generation < info->getChangeSerialNum())
+ {
+ // update existing item in UI
+ updateFriendItem(mFriendsList->getItem(buddy_it->first), info);
+ }
+ ++item_it;
+ }
+ // add new friend to list
+ else
+ {
+ const LLUUID& buddy_id = buddy_it->first;
+ char first_name[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
+ char last_name[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
+
+ gCacheName->getName(buddy_id, first_name, last_name);
+ std::ostringstream fullname;
+ fullname << first_name << " " << last_name;
+ addFriend(fullname.str(), buddy_id);
+ }
}
+
mFriendsList->selectMultiple(selected_ids);
mFriendsList->setScrollPos(pos);
}
@@ -451,7 +417,7 @@ void LLPanelFriends::refreshUI()
}
else
{
- childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getText() + "...");
+ childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getValue().asString() + "...");
}
}
else
@@ -493,6 +459,8 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
if(panelp)
{
panelp->refreshUI();
+ // check to see if rights have changed
+ panelp->applyRightsToFriends();
}
}
@@ -687,35 +655,22 @@ void LLPanelFriends::onClickPay(void* user_data)
}
}
-void LLPanelFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data)
-{
- LLPanelFriends* panelp = (LLPanelFriends*)user_data;
-
- bool checked = ctrl->getValue();
- panelp->updateMenuState(LLRelationship::GRANT_ONLINE_STATUS, checked);
- panelp->applyRightsToFriends(LLRelationship::GRANT_ONLINE_STATUS, checked);
-}
-
-void LLPanelFriends::onClickMapStatus(LLUICtrl* ctrl, void* user_data)
-{
- LLPanelFriends* panelp = (LLPanelFriends*)user_data;
- bool checked = ctrl->getValue();
- panelp->updateMenuState(LLRelationship::GRANT_MAP_LOCATION, checked);
- panelp->applyRightsToFriends(LLRelationship::GRANT_MAP_LOCATION, checked);
-}
-
-void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data)
+void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command)
{
- LLPanelFriends* panelp = (LLPanelFriends*)user_data;
-
- bool checked = ctrl->getValue();
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
+ if (ids.empty()) return;
+
LLStringBase<char>::format_map_t args;
if(ids.size() > 0)
{
+ // copy map of ids onto heap
+ rights_map_t* rights = new rights_map_t(ids);
+ // package with panel pointer
+ std::pair<LLPanelFriends*, rights_map_t*>* user_data = new std::pair<LLPanelFriends*, rights_map_t*>(this, rights);
+
+ // for single friend, show their name
if(ids.size() == 1)
{
- LLUUID agent_id = ids[0];
+ LLUUID agent_id = ids.begin()->first;
char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
if(gCacheName->getName(agent_id, first, last))
@@ -723,56 +678,174 @@ void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data)
args["[FIRST_NAME]"] = first;
args["[LAST_NAME]"] = last;
}
- if(checked) gViewerWindow->alertXml("GrantModifyRights", args, handleModifyRights, user_data);
- else gViewerWindow->alertXml("RevokeModifyRights", args, handleModifyRights, user_data);
+ if (command == GRANT)
+ {
+ gViewerWindow->alertXml("GrantModifyRights", args, modifyRightsConfirmation, user_data);
+ }
+ else
+ {
+ gViewerWindow->alertXml("RevokeModifyRights", args, modifyRightsConfirmation, user_data);
+ }
+ }
+ else
+ {
+ if (command == GRANT)
+ {
+ gViewerWindow->alertXml("GrantModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
+ }
+ else
+ {
+ gViewerWindow->alertXml("RevokeModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
+ }
}
- else return;
}
}
-void LLPanelFriends::handleModifyRights(S32 option, void* user_data)
+// static
+void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data)
{
- LLPanelFriends* panelp = (LLPanelFriends*)user_data;
+ std::pair<LLPanelFriends*, rights_map_t*>* data = (std::pair<LLPanelFriends*, rights_map_t*>*)user_data;
+ LLPanelFriends* panelp = data->first;
if(panelp)
{
- if(!option)
+ if(0 == option)
{
- panelp->updateMenuState(LLRelationship::GRANT_MODIFY_OBJECTS, !((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0));
- panelp->applyRightsToFriends(LLRelationship::GRANT_MODIFY_OBJECTS, ((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0));
+ panelp->sendRightsGrant(*(data->second));
+ }
+ else
+ {
+ // need to resync view with model, since user cancelled operation
+ rights_map_t* rights = data->second;
+ rights_map_t::iterator rights_it;
+ for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it)
+ {
+ LLScrollListItem* itemp = panelp->mFriendsList->getItem(rights_it->first);
+ const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
+ panelp->updateFriendItem(itemp, info);
+ }
}
panelp->refreshUI();
}
+
+ delete data->second;
+ delete data;
}
-void LLPanelFriends::updateMenuState(S32 flag, BOOL value)
+void LLPanelFriends::applyRightsToFriends()
{
- if(value) mMenuState |= flag;
- else mMenuState &= ~flag;
+ BOOL rights_changed = FALSE;
+
+ // store modify rights separately for confirmation
+ rights_map_t rights_updates;
+
+ BOOL need_confirmation = FALSE;
+ EGrantRevoke confirmation_type = GRANT;
+
+ // this assumes that changes only happened to selected items
+ std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected();
+ for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
+ {
+ LLUUID id = (*itr)->getValue();
+ const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(id);
+ if (buddy_relationship == NULL) continue;
+
+ bool show_online_staus = (*itr)->getColumn(LIST_VISIBLE_ONLINE)->getValue().asBoolean();
+ bool show_map_location = (*itr)->getColumn(LIST_VISIBLE_MAP)->getValue().asBoolean();
+ bool allow_modify_objects = (*itr)->getColumn(LIST_EDIT_MINE)->getValue().asBoolean();
+
+ S32 rights = buddy_relationship->getRightsGrantedTo();
+ if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) != show_online_staus)
+ {
+ rights_changed = TRUE;
+ if(show_online_staus)
+ {
+ rights |= LLRelationship::GRANT_ONLINE_STATUS;
+ }
+ else
+ {
+ // ONLINE_STATUS necessary for MAP_LOCATION
+ rights &= ~LLRelationship::GRANT_ONLINE_STATUS;
+ rights &= ~LLRelationship::GRANT_MAP_LOCATION;
+ // propagate rights constraint to UI
+ (*itr)->getColumn(LIST_VISIBLE_MAP)->setValue(FALSE);
+ }
+ }
+ if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) != show_map_location)
+ {
+ rights_changed = TRUE;
+ if(show_map_location)
+ {
+ // ONLINE_STATUS necessary for MAP_LOCATION
+ rights |= LLRelationship::GRANT_MAP_LOCATION;
+ rights |= LLRelationship::GRANT_ONLINE_STATUS;
+ (*itr)->getColumn(LIST_VISIBLE_ONLINE)->setValue(TRUE);
+ }
+ else
+ {
+ rights &= ~LLRelationship::GRANT_MAP_LOCATION;
+ }
+ }
+
+ // now check for change in modify object rights, which requires confirmation
+ if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects)
+ {
+ rights_changed = TRUE;
+ need_confirmation = TRUE;
+
+ if(allow_modify_objects)
+ {
+ rights |= LLRelationship::GRANT_MODIFY_OBJECTS;
+ confirmation_type = GRANT;
+ }
+ else
+ {
+ rights &= ~LLRelationship::GRANT_MODIFY_OBJECTS;
+ confirmation_type = REVOKE;
+ }
+ }
+
+ if (rights_changed)
+ {
+ rights_updates.insert(std::make_pair(id, rights));
+ // disable these ui elements until response from server
+ // to avoid race conditions
+ (*itr)->setEnabled(FALSE);
+ }
+ }
+
+ // separately confirm grant and revoke of modify rights
+ if (need_confirmation)
+ {
+ confirmModifyRights(rights_updates, confirmation_type);
+ }
+ else
+ {
+ sendRightsGrant(rights_updates);
+ }
}
-void LLPanelFriends::applyRightsToFriends(S32 flag, BOOL value)
+void LLPanelFriends::sendRightsGrant(rights_map_t& ids)
{
+ if (ids.empty()) return;
+
LLMessageSystem* msg = gMessageSystem;
+
+ // setup message header
msg->newMessageFast(_PREHASH_GrantUserRights);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
- LLDynamicArray<LLUUID> ids = getSelectedIDs();
- S32 rights;
- for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
+ rights_map_t::iterator id_it;
+ rights_map_t::iterator end_it = ids.end();
+ for(id_it = ids.begin(); id_it != end_it; ++id_it)
{
- rights = LLAvatarTracker::instance().getBuddyInfo(*itr)->getRightsGrantedTo();
- if(LLAvatarTracker::instance().getBuddyInfo(*itr)->isRightGrantedTo(flag) != (bool)value)
- {
- if(value) rights |= flag;
- else rights &= ~flag;
- msg->nextBlockFast(_PREHASH_Rights);
- msg->addUUID(_PREHASH_AgentRelated, *itr);
- msg->addS32(_PREHASH_RelatedRights, rights);
- }
+ msg->nextBlockFast(_PREHASH_Rights);
+ msg->addUUID(_PREHASH_AgentRelated, id_it->first);
+ msg->addS32(_PREHASH_RelatedRights, id_it->second);
}
+
mNumRightsChanged = ids.size();
gAgent.sendReliableMessage();
}
diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h
index 3d0b7a9bba..46e4eaaf79 100644
--- a/indra/newview/llfloaterfriends.h
+++ b/indra/newview/llfloaterfriends.h
@@ -40,6 +40,7 @@
#include "lltimer.h"
class LLFriendObserver;
+class LLRelationship;
/**
@@ -88,19 +89,27 @@ private:
LIST_VISIBLE_ONLINE,
LIST_VISIBLE_MAP,
LIST_EDIT_MINE,
- LIST_EDIT_THEIRS
+ LIST_EDIT_THEIRS,
+ LIST_FRIEND_UPDATE_GEN
};
// protected members
-
+ typedef std::map<LLUUID, S32> rights_map_t;
void reloadNames();
void refreshNames();
void refreshUI();
void refreshRightsChangeList();
- void applyRightsToFriends(S32 flag, BOOL value);
- void updateMenuState(S32 flag, BOOL value);
- S32 getMenuState() { return mMenuState; }
+ void applyRightsToFriends();
void addFriend(const std::string& name, const LLUUID& agent_id);
+ void updateFriendItem(LLScrollListItem* itemp, const LLRelationship* relationship);
+
+ typedef enum
+ {
+ GRANT,
+ REVOKE
+ } EGrantRevoke;
+ void confirmModifyRights(rights_map_t& ids, EGrantRevoke command);
+ void sendRightsGrant(rights_map_t& ids);
// return LLUUID::null if nothing is selected
LLDynamicArray<LLUUID> getSelectedIDs();
@@ -119,12 +128,10 @@ private:
static void onClickOfferTeleport(void* user_data);
static void onClickPay(void* user_data);
- static void onClickOnlineStatus(LLUICtrl* ctrl, void* user_data);
- static void onClickMapStatus(LLUICtrl* ctrl, void* user_data);
static void onClickModifyStatus(LLUICtrl* ctrl, void* user_data);
static void handleRemove(S32 option, void* user_data);
- static void handleModifyRights(S32 option, void* user_data);
+ static void modifyRightsConfirmation(S32 option, void* user_data);
private:
// member data
@@ -132,7 +139,6 @@ private:
LLUUID mAddFriendID;
LLString mAddFriendName;
LLScrollListCtrl* mFriendsList;
- S32 mMenuState;
BOOL mShowMaxSelectWarning;
BOOL mAllowRightsChange;
S32 mNumRightsChanged;
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index 0ce91ef740..9f1624d20c 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -262,6 +262,7 @@ void LLFloaterInspect::refresh()
void LLFloaterInspect::onFocusReceived()
{
gToolMgr->setTransientTool(gToolInspect);
+ LLFloater::onFocusReceived();
}
void LLFloaterInspect::dirty()
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3b96a4ce5e..2a352dfc3d 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1045,8 +1045,10 @@ BOOL LLPanelLandObjects::postBuild()
mSelectedObjects = LLUICtrlFactory::getTextBoxByName(this, "selected_objects_text");
mCleanOtherObjectsTime = LLUICtrlFactory::getLineEditorByName(this, "clean other time");
- mCleanOtherObjectsTime->setFocusLostCallback(onLostFocus);
+
+ mCleanOtherObjectsTime->setFocusLostCallback(onLostFocus, this);
mCleanOtherObjectsTime->setCommitCallback(onCommitClean);
+
childSetPrevalidate("clean other time", LLLineEditor::prevalidateNonNegativeS32);
childSetUserData("clean other time", this);
@@ -1135,7 +1137,7 @@ void LLPanelLandObjects::onDoubleClickOwner(void *userdata)
return;
}
// Is this a group?
- BOOL is_group = cell->getText() == OWNER_GROUP;
+ BOOL is_group = cell->getValue().asString() == OWNER_GROUP;
if (is_group)
{
LLFloaterGroupInfo::showFromUUID(owner_id);
@@ -1180,19 +1182,16 @@ void LLPanelLandObjects::refresh()
}
else
{
- S32 sw_max = 0;
- S32 sw_total = 0;
- S32 max = 0;
- S32 total = 0;
- S32 owned = 0;
- S32 group = 0;
- S32 other = 0;
- S32 selected = 0;
- F32 parcel_object_bonus = 0.f;
-
- gParcelMgr->getPrimInfo(sw_max, sw_total,
- max, total, owned, group, other, selected,
- parcel_object_bonus, mOtherTime);
+ S32 sw_max = parcel->getSimWideMaxPrimCapacity();
+ S32 sw_total = parcel->getSimWidePrimCount();
+ S32 max = llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus());
+ S32 total = parcel->getPrimCount();
+ S32 owned = parcel->getOwnerPrimCount();
+ S32 group = parcel->getGroupPrimCount();
+ S32 other = parcel->getOtherPrimCount();
+ S32 selected = parcel->getSelectedPrimCount();
+ F32 parcel_object_bonus = parcel->getParcelPrimBonus();
+ mOtherTime = parcel->getCleanOtherTime();
// Can't have more than region max tasks, regardless of parcel
// object bonus factor.
@@ -1442,14 +1441,6 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata)
{
LLPanelLandObjects *self = (LLPanelLandObjects *)userdata;
- S32 sw_max, sw_total;
- S32 max, total;
- S32 owned, group, other, selected;
- F32 parcel_object_bonus;
- S32 other_time;
-
- gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
-
LLParcel* parcelp = self->mParcel->getParcel();
if (!parcelp) return;
@@ -1632,11 +1623,11 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data)
return;
}
// Is this a group?
- self->mSelectedIsGroup = cell->getText() == OWNER_GROUP;
+ self->mSelectedIsGroup = cell->getValue().asString() == OWNER_GROUP;
cell = item->getColumn(2);
- self->mSelectedName = cell->getText();
+ self->mSelectedName = cell->getValue().asString();
cell = item->getColumn(3);
- self->mSelectedCount = atoi(cell->getText().c_str());
+ self->mSelectedCount = atoi(cell->getValue().asString().c_str());
// Set the selection, and enable the return button.
self->mSelectedOwners.clear();
@@ -1700,18 +1691,14 @@ void LLPanelLandObjects::onClickShowOtherObjects(void* userdata)
// static
void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
{
- S32 sw_max=0, sw_total=0;
- S32 max=0, total=0;
- S32 owned=0, group=0, other=0, selected=0;
- F32 parcel_object_bonus=0;
- S32 other_time=0;
-
- gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
+ S32 owned = 0;
LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
LLParcel* parcel = panelp->mParcel->getParcel();
if (!parcel) return;
+ owned = parcel->getOwnerPrimCount();
+
send_parcel_select_objects(parcel->getLocalID(), RT_OWNER);
LLUUID owner_id = parcel->getOwnerID();
@@ -1739,14 +1726,6 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
// static
void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
{
- S32 sw_max=0, sw_total=0;
- S32 max=0, total=0;
- S32 owned=0, group=0, other=0, selected=0;
- F32 parcel_object_bonus=0;
- S32 other_time=0;
-
- gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
-
LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
LLParcel* parcel = panelp->mParcel->getParcel();
if (!parcel) return;
@@ -1758,7 +1737,7 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
LLStringBase<char>::format_map_t args;
args["[NAME]"] = group_name;
- args["[N]"] = llformat("%d",group);
+ args["[N]"] = llformat("%d", parcel->getGroupPrimCount());
// create and show confirmation textbox
gViewerWindow->alertXml("ReturnObjectsDeededToGroup", args, callbackReturnGroupObjects, userdata);
@@ -1767,17 +1746,13 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
// static
void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
{
- S32 sw_max=0, sw_total=0;
- S32 max=0, total=0;
- S32 owned=0, group=0, other=0, selected=0;
- F32 parcel_object_bonus=0;
- S32 other_time=0;
-
- gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
+ S32 other = 0;
LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
LLParcel* parcel = panelp->mParcel->getParcel();
if (!parcel) return;
+
+ other = parcel->getOtherPrimCount();
send_parcel_select_objects(parcel->getLocalID(), RT_OTHER);
@@ -1817,9 +1792,9 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
}
// static
-void LLPanelLandObjects::onLostFocus(LLUICtrl *caller, void* user_data)
+void LLPanelLandObjects::onLostFocus(LLFocusableElement* caller, void* user_data)
{
- onCommitClean(caller, user_data);
+ onCommitClean((LLUICtrl*)caller, user_data);
}
// static
@@ -2408,6 +2383,13 @@ void LLPanelLandMedia::refresh()
mCheckSoundLocal->set( parcel->getSoundLocal() );
mCheckSoundLocal->setEnabled( can_change_media );
+ LLViewerRegion* selection_region = gParcelMgr->getSelectionRegion();
+ BOOL region_allows_voice = FALSE;
+ if (selection_region)
+ {
+ region_allows_voice = selection_region->isVoiceEnabled();
+ }
+
if(parcel->getVoiceEnabled())
{
if(parcel->getVoiceUseEstateChannel())
@@ -2420,7 +2402,7 @@ void LLPanelLandMedia::refresh()
mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable);
}
- mRadioVoiceChat->setEnabled( can_change_media );
+ mRadioVoiceChat->setEnabled( can_change_media && region_allows_voice );
// don't display urls if you're not able to change it
// much requested change in forums so people can't 'steal' urls
@@ -2535,7 +2517,7 @@ void LLPanelLandMedia::onClickStopMedia ( void* data )
void LLPanelLandMedia::onClickStartMedia ( void* data )
{
// force a commit
- gFocusMgr.setKeyboardFocus ( NULL, NULL );
+ gFocusMgr.setKeyboardFocus ( NULL );
// force a reload
LLMediaEngine::getInstance ()->convertImageAndLoadUrl ( true, false, std::string());
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index fa941caf78..4bb88aa127 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -257,7 +257,7 @@ public:
static void onDoubleClickOwner(void*);
static void onCommitList(LLUICtrl* ctrl, void* data);
- static void onLostFocus(LLUICtrl* caller, void* user_data);
+ static void onLostFocus(LLFocusableElement* caller, void* user_data);
static void onCommitClean(LLUICtrl* caller, void* user_data);
static void processParcelObjectOwnersReply(LLMessageSystem *msg, void **);
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index a00f512515..5306ce11b1 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -137,8 +137,7 @@ BOOL LLFloaterPostcard::postBuild()
MsgField->setWordWrap(TRUE);
// For the first time a user focusess to .the msg box, all text will be selected.
- MsgField->setFocusChangedCallback(onMsgFormFocusRecieved);
- MsgField->setCallbackUserData(this);
+ MsgField->setFocusChangedCallback(onMsgFormFocusRecieved, this);
}
childSetFocus("to_form", TRUE);
@@ -347,7 +346,7 @@ void LLFloaterPostcard::updateUserInfo(const char *email)
}
}
-void LLFloaterPostcard::onMsgFormFocusRecieved(LLUICtrl* receiver, void* data)
+void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data)
{
LLFloaterPostcard* self = (LLFloaterPostcard *)data;
if(self)
diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h
index 78da8b55d8..287d34c706 100644
--- a/indra/newview/llfloaterpostcard.h
+++ b/indra/newview/llfloaterpostcard.h
@@ -65,7 +65,7 @@ public:
static void updateUserInfo(const char *email);
- static void onMsgFormFocusRecieved(LLUICtrl* receiver, void* data);
+ static void onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data);
static void missingSubjMsgAlertCallback(S32 option, void* data);
void sendPostcard();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 3306142856..eaf7832eab 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -161,50 +161,55 @@ bool estate_dispatch_initialized = false;
/// LLFloaterRegionInfo
///----------------------------------------------------------------------------
-LLFloaterRegionInfo* LLFloaterRegionInfo::sInstance = NULL;
//S32 LLFloaterRegionInfo::sRequestSerial = 0;
LLUUID LLFloaterRegionInfo::sRequestInvoice;
-LLFloaterRegionInfo::LLFloaterRegionInfo(const LLRect& rect) :
- LLFloater("regioninfo", rect, "Region/Estate")
+LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
{
- LLRect tr(0, rect.getHeight() - LLFLOATER_HEADER_SIZE, rect.getWidth(), 0);
- mTab = new LLTabContainer("tab", tr, LLTabContainer::TOP, NULL,NULL,"");
- mTab->setBorderVisible(FALSE);
- addChild(mTab);
+ gUICtrlFactory->buildFloater(this, "floater_region_info.xml", NULL, FALSE);
+}
+
+BOOL LLFloaterRegionInfo::postBuild()
+{
+ mTab = gUICtrlFactory->getTabContainerByName(this, "region_panels");
// contruct the panels
- LLPanel* panel;
+ LLPanelRegionInfo* panel;
panel = new LLPanelRegionGeneralInfo;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_general.xml");
mTab->addTabPanel(panel, panel->getLabel(), TRUE);
panel = new LLPanelRegionDebugInfo;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_debug.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelRegionTextureInfo;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_texture.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelRegionTerrainInfo;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_terrain.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelEstateInfo;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_estate.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelEstateCovenant;
- mInfoPanels.push_back((LLPanelRegionInfo*)panel);
+ mInfoPanels.push_back(panel);
gUICtrlFactory->buildPanel(panel, "panel_region_covenant.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ gMessageSystem->setHandlerFunc(
+ "EstateOwnerMessage",
+ &processEstateOwnerRequest);
+
+ return TRUE;
}
LLFloaterRegionInfo::~LLFloaterRegionInfo()
@@ -212,23 +217,20 @@ LLFloaterRegionInfo::~LLFloaterRegionInfo()
sInstance = NULL;
}
-// static
-void LLFloaterRegionInfo::show(LLViewerRegion* region)
+void LLFloaterRegionInfo::onOpen()
{
- if (!sInstance)
- {
- LLRect rect = gSavedSettings.getRect("FloaterRegionInfo");
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- rect.translate(left,top);
- sInstance = new LLFloaterRegionInfo(rect);
- gMessageSystem->setHandlerFunc(
- "EstateOwnerMessage",
- &processEstateOwnerRequest);
- }
- sInstance->open(); /* Flawfinder: ignore*/
- sInstance->refreshFromRegion(region);
+ LLRect rect = gSavedSettings.getRect("FloaterRegionInfo");
+ S32 left, top;
+ gFloaterView->getNewFloaterPosition(&left, &top);
+ rect.translate(left,top);
+
+ requestRegionInfo();
+ refreshFromRegion(gAgent.getRegion());
+ LLFloater::onOpen();
+}
+void LLFloaterRegionInfo::requestRegionInfo()
+{
// Must allow anyone to request the RegionInfo data
// so non-owners/non-gods can see the values.
// Therefore can't use an EstateOwnerMessage JC
@@ -242,18 +244,6 @@ void LLFloaterRegionInfo::show(LLViewerRegion* region)
}
// static
-void LLFloaterRegionInfo::show(void*)
-{
- show(gAgent.getRegion());
-}
-
-// static
-LLFloaterRegionInfo* LLFloaterRegionInfo::getInstance()
-{
- return sInstance;
-}
-
-// static
void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
{
static LLDispatcher dispatch;
@@ -264,7 +254,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
LLPanelEstateInfo::initDispatch(dispatch);
}
- LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "tab");
+ LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "region_panels");
if (!tab) return;
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab, "Estate");
@@ -293,7 +283,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl;
if(!sInstance) return;
- LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "tab");
+ LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "region_panels");
if(!tab) return;
// extract message
@@ -376,7 +366,7 @@ LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return NULL;
- LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab");
+ LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels");
if (!tab) return NULL;
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab,"Estate");
return panel;
@@ -387,7 +377,7 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return NULL;
- LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab");
+ LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels");
if (!tab) return NULL;
LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)LLUICtrlFactory::getPanelByName(tab, "Covenant");
return panel;
@@ -1241,7 +1231,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return true;
- LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab");
+ LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels");
if (!tab) return true;
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab, "Estate");
@@ -2803,7 +2793,7 @@ bool LLDispatchSetEstateOwner::operator()(
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return true;
- LLTabContainer* tab = (LLTabContainer*)(floater->getChildByName("tab"));
+ LLTabContainer* tab = (LLTabContainer*)(floater->getChildByName("region_panels"));
if (!tab) return true;
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)(tab->getChildByName("Estate"));
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index abf4789b6d..6f9ed1fc34 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -58,14 +58,15 @@ class LLPanelRegionTerrainInfo;
class LLPanelEstateInfo;
class LLPanelEstateCovenant;
-class LLFloaterRegionInfo : public LLFloater
+class LLFloaterRegionInfo : public LLFloater, public LLUISingleton<LLFloaterRegionInfo>
{
+ friend class LLUISingleton<LLFloaterRegionInfo>;
public:
~LLFloaterRegionInfo();
- static void show(LLViewerRegion* region);
- static void show(void*);
- static LLFloaterRegionInfo* getInstance();
+ /*virtual*/ void onOpen();
+ /*virtual*/ BOOL postBuild();
+
static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
// get and process region info if necessary.
@@ -82,15 +83,14 @@ public:
// from LLPanel
virtual void refresh();
+ void requestRegionInfo();
+
protected:
- LLFloaterRegionInfo(const LLRect& rect);
+ LLFloaterRegionInfo(const LLSD& seed);
void refreshFromRegion(LLViewerRegion* region);
- // static data
- static LLFloaterRegionInfo* sInstance;
-
// member data
- LLTabContainer* mTab;
+ LLTabContainerCommon* mTab;
typedef std::vector<LLPanelRegionInfo*> info_panels_t;
info_panels_t mInfoPanels;
//static S32 sRequestSerial; // serial # of last EstateOwnerRequest
diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp
index 9d600befdb..80a686d162 100644
--- a/indra/newview/llfloaterscriptdebug.cpp
+++ b/indra/newview/llfloaterscriptdebug.cpp
@@ -177,7 +177,7 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id)
mHistoryEditor->setWordWrap( TRUE );
mHistoryEditor->setFollowsAll();
mHistoryEditor->setEnabled( FALSE );
- mHistoryEditor->setTakesFocus( TRUE ); // We want to be able to cut or copy from the history.
+ mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history.
addChild(mHistoryEditor);
}
@@ -200,7 +200,7 @@ void LLFloaterScriptDebugOutput::init(const LLString& title, BOOL resizable,
mHistoryEditor->setWordWrap( TRUE );
mHistoryEditor->setFollowsAll();
mHistoryEditor->setEnabled( FALSE );
- mHistoryEditor->setTakesFocus( TRUE ); // We want to be able to cut or copy from the history.
+ mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history.
addChild(mHistoryEditor);
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 22581c6576..d03ce373cc 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -942,7 +942,7 @@ void commit_select_component(LLUICtrl *ctrl, void *data)
//forfeit focus
if (gFocusMgr.childHasKeyboardFocus(floaterp))
{
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
BOOL select_individuals = floaterp->mCheckSelectIndividual->get();
@@ -992,4 +992,5 @@ void LLFloaterTools::setEditTool(void* tool_pointer)
void LLFloaterTools::onFocusReceived()
{
gToolMgr->setCurrentToolset(gBasicToolset);
+ LLFloater::onFocusReceived();
}
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index e3f236becc..6bbb748a10 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -257,8 +257,8 @@ void LLFloaterTopObjects::updateSelectionInfo()
std::string object_id_string = object_id.asString();
childSetValue("id_editor", LLSD(object_id_string));
- childSetValue("object_name_editor", list->getFirstSelected()->getColumn(1)->getText());
- childSetValue("owner_name_editor", list->getFirstSelected()->getColumn(2)->getText());
+ childSetValue("object_name_editor", list->getFirstSelected()->getColumn(1)->getValue().asString());
+ childSetValue("owner_name_editor", list->getFirstSelected()->getColumn(2)->getValue().asString());
}
// static
@@ -451,8 +451,8 @@ void LLFloaterTopObjects::showBeacon()
LLScrollListItem* first_selected = list->getFirstSelected();
if (!first_selected) return;
- LLString name = first_selected->getColumn(1)->getText();
- LLString pos_string = first_selected->getColumn(3)->getText();
+ LLString name = first_selected->getColumn(1)->getValue().asString();
+ LLString pos_string = first_selected->getColumn(3)->getValue().asString();
F32 x, y, z;
S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 4c03a15619..b1bbb341fd 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -234,7 +234,7 @@ BOOL LLFloaterWorldMap::postBuild()
childSetAction("DoSearch", onLocationCommit, this);
- childSetFocusChangedCallback("location", updateSearchEnabled);
+ childSetFocusChangedCallback("location", onLocationFocusChanged, this);
LLLineEditor *location_editor = LLUICtrlFactory::getLineEditorByName(this, "location");
if (location_editor)
@@ -1221,6 +1221,12 @@ void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata )
}
}
+//static
+void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus, void* userdata )
+{
+ updateSearchEnabled((LLUICtrl*)focus, userdata);
+}
+
// static
void LLFloaterWorldMap::updateSearchEnabled( LLUICtrl* ctrl, void* userdata )
{
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index c069b40929..6f3c583557 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -153,6 +153,7 @@ protected:
void teleportToAvatar();
static void updateSearchEnabled( LLUICtrl* ctrl, void* userdata );
+ static void onLocationFocusChanged( LLFocusableElement* ctrl, void* userdata );
static void onLocationCommit( void* userdata );
static void onCommitLocation( LLUICtrl* ctrl, void* userdata );
static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata );
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 2577474e24..deffca3b79 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -94,7 +94,7 @@ void copy_selected_item(void* user_data);
void open_selected_items(void* user_data);
void properties_selected_items(void* user_data);
void paste_items(void* user_data);
-void renamer_focus_lost( LLUICtrl* handler, void* user_data );
+void renamer_focus_lost( LLFocusableElement* handler, void* user_data );
///----------------------------------------------------------------------------
/// Class LLFolderViewItem
@@ -693,7 +693,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
// Release keyboard focus, so that if stuff is dropped into the
// world, pressing the delete key won't blow away the inventory
// item.
- gViewerWindow->setKeyboardFocus(NULL, NULL);
+ gViewerWindow->setKeyboardFocus(NULL);
return gToolDragAndDrop->handleHover( x, y, mask );
}
@@ -3164,7 +3164,7 @@ void LLFolderView::draw()
}
if(gViewerWindow->hasKeyboardFocus(this) && !getVisible())
{
- gViewerWindow->setKeyboardFocus( NULL, NULL );
+ gViewerWindow->setKeyboardFocus( NULL );
}
// while dragging, update selection rendering to reflect single/multi drag status
@@ -3656,7 +3656,7 @@ void LLFolderView::startRenamingSelectedItem( void )
mRenamer->setVisible( TRUE );
// set focus will fail unless item is visible
mRenamer->setFocus( TRUE );
- mRenamer->setFocusLostCallback(renamer_focus_lost);
+ mRenamer->setLostTopCallback(onRenamerLost);
gViewerWindow->setTopCtrl( mRenamer );
}
}
@@ -3730,7 +3730,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
{
if( gViewerWindow->childHasKeyboardFocus( this ) )
{
- gViewerWindow->setKeyboardFocus( NULL, NULL );
+ gViewerWindow->setKeyboardFocus( NULL );
}
}
mSearchString.clear();
@@ -4438,12 +4438,10 @@ bool LLInventorySort::operator()(LLFolderViewItem* a, LLFolderViewItem* b)
}
}
-void renamer_focus_lost( LLUICtrl* ctrl, void* userdata)
+//static
+void LLFolderView::onRenamerLost( LLUICtrl* renamer, void* user_data)
{
- if( ctrl )
- {
- ctrl->setVisible( FALSE );
- }
+ renamer->setVisible(FALSE);
}
void delete_selected_item(void* user_data)
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index dd0dd21705..9fcf94d802 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -876,6 +876,8 @@ protected:
LLScrollableContainerView* mScrollContainer; // NULL if this is not a child of a scroll container.
static void commitRename( LLUICtrl* renamer, void* user_data );
+ static void onRenamerLost( LLUICtrl* renamer, void* user_data);
+
void finishRenamingItem( void );
void revertRenamingItem( void );
diff --git a/indra/newview/llhudview.cpp b/indra/newview/llhudview.cpp
index e40e84b9da..7f549bb2eb 100644
--- a/indra/newview/llhudview.cpp
+++ b/indra/newview/llhudview.cpp
@@ -52,8 +52,8 @@ LLHUDView *gHUDView = NULL;
const S32 HUD_ARROW_SIZE = 32;
-LLHUDView::LLHUDView(const std::string& name, const LLRect& rect)
-: LLView(name, rect, FALSE)
+LLHUDView::LLHUDView()
+: LLPanel()
{ }
LLHUDView::~LLHUDView()
diff --git a/indra/newview/llhudview.h b/indra/newview/llhudview.h
index b2353ad5df..cbefdc121e 100644
--- a/indra/newview/llhudview.h
+++ b/indra/newview/llhudview.h
@@ -32,16 +32,16 @@
#ifndef LL_LLHUDVIEW_H
#define LL_LLHUDVIEW_H
-#include "llview.h"
+#include "llpanel.h"
#include "v4color.h"
class LLVector3d;
class LLHUDView
-: public LLView
+: public LLPanel
{
public:
- LLHUDView(const std::string& name, const LLRect& rect);
+ LLHUDView();
virtual ~LLHUDView();
virtual EWidgetType getWidgetType() const;
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 810d3a26a1..b1fefc4f5d 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -63,6 +63,7 @@
#include "llviewerstats.h"
#include "llviewercontrol.h"
#include "llvieweruictrlfactory.h"
+#include "llviewerwindow.h"
#include "lllogchat.h"
#include "llfloaterhtml.h"
#include "llweb.h"
@@ -92,10 +93,14 @@ static LLString sSessionStartString = "Starting session with [NAME] please wait.
LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
+LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
-void session_starter_helper(const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- EInstantMessage im_type)
+BOOL LLVoiceChannel::sSuspended = FALSE;
+
+void session_starter_helper(
+ const LLUUID& temp_session_id,
+ const LLUUID& other_participant_id,
+ EInstantMessage im_type)
{
LLMessageSystem *msg = gMessageSystem;
@@ -122,47 +127,111 @@ void session_starter_helper(const LLUUID& temp_session_id,
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
}
+void start_deprecated_conference_chat(
+ const LLUUID& temp_session_id,
+ const LLUUID& creator_id,
+ const LLUUID& other_participant_id,
+ const LLSD& agents_to_invite)
+{
+ U8* bucket;
+ U8* pos;
+ S32 count;
+ S32 bucket_size;
+
+ // *FIX: this could suffer from endian issues
+ count = agents_to_invite.size();
+ bucket_size = UUID_BYTES * count;
+ bucket = new U8[bucket_size];
+ pos = bucket;
+
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLUUID agent_id = agents_to_invite[i].asUUID();
+
+ memcpy(pos, &agent_id, UUID_BYTES);
+ pos += UUID_BYTES;
+ }
+
+ session_starter_helper(
+ temp_session_id,
+ other_participant_id,
+ IM_SESSION_CONFERENCE_START);
+
+ gMessageSystem->addBinaryDataFast(
+ _PREHASH_BinaryBucket,
+ bucket,
+ bucket_size);
+
+ gAgent.sendReliableMessage();
+
+ delete[] bucket;
+}
+
+class LLStartConferenceChatResponder : public LLHTTPClient::Responder
+{
+public:
+ LLStartConferenceChatResponder(
+ const LLUUID& temp_session_id,
+ const LLUUID& creator_id,
+ const LLUUID& other_participant_id,
+ const LLSD& agents_to_invite)
+ {
+ mTempSessionID = temp_session_id;
+ mCreatorID = creator_id;
+ mOtherParticipantID = other_participant_id;
+ mAgents = agents_to_invite;
+ }
+
+ virtual void error(U32 statusNum, const std::string& reason)
+ {
+ //try an "old school" way.
+ if ( statusNum == 400 )
+ {
+ start_deprecated_conference_chat(
+ mTempSessionID,
+ mCreatorID,
+ mOtherParticipantID,
+ mAgents);
+ }
+
+ //else throw an error back to the client?
+ //in theory we should have just have these error strings
+ //etc. set up in this file as opposed to the IMMgr,
+ //but the error string were unneeded here previously
+ //and it is not worth the effort switching over all
+ //the possible different language translations
+ }
+
+private:
+ LLUUID mTempSessionID;
+ LLUUID mCreatorID;
+ LLUUID mOtherParticipantID;
+
+ LLSD mAgents;
+};
+
// Returns true if any messages were sent, false otherwise.
// Is sort of equivalent to "does the server need to do anything?"
-bool send_start_session_messages(const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids,
- EInstantMessage dialog)
+bool send_start_session_messages(
+ const LLUUID& temp_session_id,
+ const LLUUID& other_participant_id,
+ const LLDynamicArray<LLUUID>& ids,
+ EInstantMessage dialog)
{
- if ( (dialog == IM_SESSION_GROUP_START) ||
- (dialog == IM_SESSION_CONFERENCE_START) )
+ if ( dialog == IM_SESSION_GROUP_START )
{
- S32 count = ids.size();
- S32 bucket_size = UUID_BYTES * count;
- U8* bucket;
- U8* pos;
-
- session_starter_helper(temp_session_id,
- other_participant_id,
- dialog);
+ session_starter_helper(
+ temp_session_id,
+ other_participant_id,
+ dialog);
switch(dialog)
{
case IM_SESSION_GROUP_START:
- gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket,
- EMPTY_BINARY_BUCKET,
- EMPTY_BINARY_BUCKET_SIZE);
- break;
- case IM_SESSION_CONFERENCE_START:
- bucket = new U8[bucket_size];
- pos = bucket;
-
- // *FIX: this could suffer from endian issues
- for(S32 i = 0; i < count; ++i)
- {
- memcpy(pos, &(ids.get(i)), UUID_BYTES);
- pos += UUID_BYTES;
- }
- gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket,
- bucket,
- bucket_size);
- delete[] bucket;
-
+ gMessageSystem->addBinaryDataFast(
+ _PREHASH_BinaryBucket,
+ EMPTY_BINARY_BUCKET,
+ EMPTY_BINARY_BUCKET_SIZE);
break;
default:
break;
@@ -171,6 +240,44 @@ bool send_start_session_messages(const LLUUID& temp_session_id,
return true;
}
+ else if ( dialog == IM_SESSION_CONFERENCE_START )
+ {
+ LLSD agents;
+ for (int i = 0; i < (S32) ids.size(); i++)
+ {
+ agents.append(ids.get(i));
+ }
+
+ //we have a new way of starting conference calls now
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string url = region->getCapability(
+ "ChatSessionRequest");
+ LLSD data;
+ data["method"] = "start conference";
+ data["session-id"] = temp_session_id;
+
+ data["params"] = agents;
+
+ LLHTTPClient::post(
+ url,
+ data,
+ new LLStartConferenceChatResponder(
+ temp_session_id,
+ gAgent.getID(),
+ other_participant_id,
+ data["params"]));
+ }
+ else
+ {
+ start_deprecated_conference_chat(
+ temp_session_id,
+ gAgent.getID(),
+ other_participant_id,
+ agents);
+ }
+ }
return false;
}
@@ -194,8 +301,20 @@ void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
<< status << ": " << reason << ")"
<< llendl;
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
- if (channelp)
+ if ( channelp )
{
+ if ( 403 == status )
+ {
+ LLNotifyBox::showXml(
+ "VoiceNotAllowed",
+ channelp->getNotifyArgs());
+ }
+ else
+ {
+ LLNotifyBox::showXml(
+ "VoiceCallGenericError",
+ channelp->getNotifyArgs());
+ }
channelp->deactivate();
}
}
@@ -242,10 +361,6 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const LLString& session
LLVoiceChannel::~LLVoiceChannel()
{
- // CANNOT do this here, since it will crash on quit in the LLVoiceChannelProximal singleton destructor.
- // Do it in all other subclass destructors instead.
- // deactivate();
-
// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
if(gVoiceClient)
{
@@ -266,7 +381,19 @@ void LLVoiceChannel::setChannelInfo(
if (mState == STATE_NO_CHANNEL_INFO)
{
- if(!mURI.empty() && !mCredentials.empty())
+ if (mURI.empty())
+ {
+ LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty URI for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else if (mCredentials.empty())
+ {
+ LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty credentials for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else
{
setState(STATE_READY);
@@ -279,12 +406,6 @@ void LLVoiceChannel::setChannelInfo(
activate();
}
}
- else
- {
- //*TODO: notify user
- llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
- deactivate();
- }
}
}
@@ -325,7 +446,7 @@ void LLVoiceChannel::handleStatusChange(EStatusType type)
}
break;
case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave)
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
{
// if forceably removed from channel
// update the UI and revert to default channel
@@ -496,6 +617,38 @@ void LLVoiceChannel::initClass()
sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
}
+
+//static
+void LLVoiceChannel::suspend()
+{
+ if (!sSuspended)
+ {
+ sSuspendedVoiceChannel = sCurrentVoiceChannel;
+ sSuspended = TRUE;
+ }
+}
+
+//static
+void LLVoiceChannel::resume()
+{
+ if (sSuspended)
+ {
+ if (gVoiceClient->voiceEnabled())
+ {
+ if (sSuspendedVoiceChannel)
+ {
+ sSuspendedVoiceChannel->activate();
+ }
+ else
+ {
+ LLVoiceChannelProximal::getInstance()->activate();
+ }
+ }
+ sSuspended = FALSE;
+ }
+}
+
+
//
// LLVoiceChannelGroup
//
@@ -507,11 +660,6 @@ LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const LLStrin
mIsRetrying = FALSE;
}
-LLVoiceChannelGroup::~LLVoiceChannelGroup()
-{
- deactivate();
-}
-
void LLVoiceChannelGroup::deactivate()
{
if (callStarted())
@@ -635,6 +783,7 @@ void LLVoiceChannelGroup::handleError(EStatusType status)
}
break;
+
case ERROR_UNKNOWN:
default:
break;
@@ -677,11 +826,6 @@ LLVoiceChannelProximal::LLVoiceChannelProximal() :
activate();
}
-LLVoiceChannelProximal::~LLVoiceChannelProximal()
-{
- // DO NOT call deactivate() here, since this will only happen at atexit() time.
-}
-
BOOL LLVoiceChannelProximal::isActive()
{
return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
@@ -725,6 +869,9 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
case STATUS_LEFT_CHANNEL:
// do not notify user when leaving proximal channel
return;
+ case STATUS_VOICE_DISABLED:
+ gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
+ return;
default:
break;
}
@@ -762,29 +909,26 @@ void LLVoiceChannelProximal::deactivate()
}
}
+
//
// LLVoiceChannelP2P
//
LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const LLString& session_name, const LLUUID& other_user_id) :
LLVoiceChannelGroup(session_id, session_name),
- mOtherUserID(other_user_id)
+ mOtherUserID(other_user_id),
+ mReceivedCall(FALSE)
{
// make sure URI reflects encoded version of other user's agent id
setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
}
-LLVoiceChannelP2P::~LLVoiceChannelP2P()
-{
- deactivate();
-}
-
void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
{
// status updates
switch(type)
{
case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave)
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
{
if (mState == STATE_RINGING)
{
@@ -832,6 +976,7 @@ void LLVoiceChannelP2P::activate()
// no session handle yet, we're starting the call
if (mSessionHandle.empty())
{
+ mReceivedCall = FALSE;
LLVoiceClient::getInstance()->callUser(mOtherUserID);
}
// otherwise answering the call
@@ -879,24 +1024,37 @@ void LLVoiceChannelP2P::setSessionHandle(const LLString& handle)
mSessionHandle = handle;
// The URI of a p2p session should always be the other end's SIP URI.
setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
-
+ mReceivedCall = TRUE;
+
if (needs_activate)
{
activate();
}
}
+void LLVoiceChannelP2P::setState(EState state)
+{
+ // you only "answer" voice invites in p2p mode
+ // so provide a special purpose message here
+ if (mReceivedCall && state == STATE_RINGING)
+ {
+ gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
+ mState = state;
+ return;
+ }
+ LLVoiceChannel::setState(state);
+}
+
+
//
// LLFloaterIMPanel
//
LLFloaterIMPanel::LLFloaterIMPanel(
- const std::string& name,
- const LLRect& rect,
const std::string& session_label,
const LLUUID& session_id,
const LLUUID& other_participant_id,
EInstantMessage dialog) :
- LLFloater(name, rect, session_label),
+ LLFloater(session_label, LLRect(), session_label),
mInputEditor(NULL),
mHistoryEditor(NULL),
mSessionUUID(session_id),
@@ -909,6 +1067,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(
mOtherTyping(FALSE),
mTypingLineStartIndex(0),
mSentTypingState(TRUE),
+ mNumUnreadMessages(0),
mShowSpeakersOnConnect(TRUE),
mAutoConnect(FALSE),
mSpeakerPanel(NULL),
@@ -919,14 +1078,12 @@ LLFloaterIMPanel::LLFloaterIMPanel(
}
LLFloaterIMPanel::LLFloaterIMPanel(
- const std::string& name,
- const LLRect& rect,
const std::string& session_label,
const LLUUID& session_id,
const LLUUID& other_participant_id,
const LLDynamicArray<LLUUID>& ids,
EInstantMessage dialog) :
- LLFloater(name, rect, session_label),
+ LLFloater(session_label, LLRect(), session_label),
mInputEditor(NULL),
mHistoryEditor(NULL),
mSessionUUID(session_id),
@@ -952,13 +1109,15 @@ LLFloaterIMPanel::LLFloaterIMPanel(
void LLFloaterIMPanel::init(const LLString& session_label)
{
+ mSessionLabel = session_label;
+
LLString xml_filename;
switch(mDialog)
{
case IM_SESSION_GROUP_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_group.xml";
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label);
+ mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_INVITE:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
@@ -970,21 +1129,21 @@ void LLFloaterIMPanel::init(const LLString& session_label)
{
xml_filename = "floater_instant_message_ad_hoc.xml";
}
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label);
+ mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_P2P_INVITE:
xml_filename = "floater_instant_message.xml";
- mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID);
+ mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
case IM_SESSION_CONFERENCE_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_ad_hoc.xml";
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label);
+ mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
// just received text from another user
case IM_NOTHING_SPECIAL:
xml_filename = "floater_instant_message.xml";
- mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID);
+ mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
default:
llwarns << "Unknown session type" << llendl;
@@ -999,15 +1158,14 @@ void LLFloaterIMPanel::init(const LLString& session_label)
&getFactoryMap(),
FALSE);
- setLabel(session_label);
- setTitle(session_label);
+ setTitle(mSessionLabel);
mInputEditor->setMaxTextLength(1023);
// enable line history support for instant message bar
mInputEditor->setEnableLineHistory(TRUE);
if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
{
- LLLogChat::loadHistory(session_label,
+ LLLogChat::loadHistory(mSessionLabel,
&chatFromLogFile,
(void *)this);
}
@@ -1060,16 +1218,12 @@ BOOL LLFloaterIMPanel::postBuild()
{
requires("chat_editor", WIDGET_TYPE_LINE_EDITOR);
requires("im_history", WIDGET_TYPE_TEXT_EDITOR);
- requires("live_help_dialog", WIDGET_TYPE_TEXT_BOX);
- requires("title_string", WIDGET_TYPE_TEXT_BOX);
- requires("typing_start_string", WIDGET_TYPE_TEXT_BOX);
- requires("session_start_string", WIDGET_TYPE_TEXT_BOX);
if (checkRequirements())
{
mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "chat_editor");
- mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived );
- mInputEditor->setFocusLostCallback( onInputEditorFocusLost );
+ mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this );
+ mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this );
mInputEditor->setKeystrokeCallback( onInputEditorKeystroke );
mInputEditor->setCommitCallback( onCommitChat );
mInputEditor->setCallbackUserData(this);
@@ -1084,6 +1238,7 @@ BOOL LLFloaterIMPanel::postBuild()
childSetAction("send_btn", onClickSend, this);
childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
+ childSetAction("moderator_kick_speaker", onKickSpeaker, this);
//LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn");
//close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this);
@@ -1094,17 +1249,11 @@ BOOL LLFloaterIMPanel::postBuild()
{
childSetEnabled("profile_btn", FALSE);
}
- LLTextBox* title = LLUICtrlFactory::getTextBoxByName(this, "title_string");
- sTitleString = title->getText();
-
- LLTextBox* typing_start = LLUICtrlFactory::getTextBoxByName(this, "typing_start_string");
-
- sTypingStartString = typing_start->getText();
-
- LLTextBox* session_start = LLUICtrlFactory::getTextBoxByName(
- this,
- "session_start_string");
- sSessionStartString = session_start->getText();
+
+ sTitleString = getFormattedUIString("title_string");
+ sTypingStartString = getFormattedUIString("typing_start_string");
+ sSessionStartString = getFormattedUIString("session_start_string");
+
if (mSpeakerPanel)
{
mSpeakerPanel->refreshSpeakers();
@@ -1112,7 +1261,7 @@ BOOL LLFloaterIMPanel::postBuild()
if (mDialog == IM_NOTHING_SPECIAL)
{
- childSetCommitCallback("mute_btn", onClickMuteVoice, this);
+ childSetAction("mute_btn", onClickMuteVoice, this);
childSetCommitCallback("speaker_volume", onVolumeChange, this);
}
@@ -1131,7 +1280,7 @@ void* LLFloaterIMPanel::createSpeakersPanel(void* data)
}
//static
-void LLFloaterIMPanel::onClickMuteVoice(LLUICtrl* source, void* user_data)
+void LLFloaterIMPanel::onClickMuteVoice(void* user_data)
{
LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)user_data;
if (floaterp)
@@ -1171,10 +1320,22 @@ void LLFloaterIMPanel::draw()
&& LLVoiceClient::voiceEnabled();
// hide/show start call and end call buttons
- childSetVisible("end_call_btn", mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
- childSetVisible("start_call_btn", mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
+ childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
childSetEnabled("start_call_btn", enable_connect);
childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty());
+
+ LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID());
+ if (self_speaker.notNull() && self_speaker->mModeratorMutedText)
+ {
+ mInputEditor->setEnabled(FALSE);
+ mInputEditor->setLabel(getFormattedUIString("muted_text_label"));
+ }
+ else
+ {
+ mInputEditor->setEnabled(TRUE);
+ mInputEditor->setLabel(getFormattedUIString("default_text_label"));
+ }
if (mAutoConnect && enable_connect)
{
@@ -1215,11 +1376,11 @@ void LLFloaterIMPanel::draw()
else
{
// refresh volume and mute checkbox
- childSetEnabled("speaker_volume", mVoiceChannel->isActive());
+ childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID));
childSetValue("mute_btn", gMuteListp->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
- childSetEnabled("mute_btn", mVoiceChannel->isActive());
+ childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
}
LLFloater::draw();
}
@@ -1235,7 +1396,6 @@ public:
void error(U32 statusNum, const std::string& reason)
{
llinfos << "Error inviting all agents to session" << llendl;
-
//throw something back to the viewer here?
}
@@ -1243,6 +1403,48 @@ private:
LLUUID mSessionID;
};
+class LLSessionImmediateInviteResponder : public LLHTTPClient::Responder
+{
+public:
+ LLSessionImmediateInviteResponder(
+ const LLUUID& session_id,
+ const std::string& chat_req_url,
+ const LLSD& post_data)
+ {
+ mSessionID = session_id;
+ mURL = chat_req_url;
+ mPostData = post_data;
+ }
+
+ void error(U32 statusNum, const std::string& reason)
+ {
+ if ( statusNum == 400 )
+ {
+ //hrm 400 indicates invalid parameters...more
+ //than likely the method doesn't exist
+ //so try a soon to be deprecated old school way of doing this
+ mPostData["method"] = "invite";
+
+ LLHTTPClient::post(
+ mURL,
+ mPostData,
+ new LLSessionInviteResponder(mSessionID));
+ }
+ else
+ {
+ //throw something back to the viewer here?
+ llinfos << "Error inviting all agents to session" << llendl;
+ }
+ }
+
+private:
+ LLUUID mSessionID;
+ LLSD mPostData;
+
+ std::string mURL;
+};
+
+
BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
{
LLViewerRegion* region = gAgent.getRegion();
@@ -1267,12 +1469,15 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
data["params"].append(ids.get(i));
}
- data["method"] = "invite";
+ data["method"] = "immediate invite";
data["session-id"] = mSessionUUID;
LLHTTPClient::post(
url,
data,
- new LLSessionInviteResponder(mSessionUUID));
+ new LLSessionImmediateInviteResponder(
+ mSessionUUID,
+ url,
+ data));
}
else
@@ -1289,6 +1494,15 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
void LLFloaterIMPanel::addHistoryLine(const LLUUID& source, const std::string &utf8msg, const LLColor4& color, bool log_to_file)
{
+ // start tab flashing when receiving im for background session from user
+ LLMultiFloater* hostp = getHost();
+ if( !isInVisibleChain()
+ && hostp
+ && source != gAgent.getID())
+ {
+ hostp->setFloaterFlashing(this, TRUE);
+ }
+
addHistoryLine(utf8msg, color, log_to_file);
mSpeakers->speakerChatted(source);
mSpeakers->setSpeakerTyping(source, FALSE);
@@ -1296,14 +1510,6 @@ void LLFloaterIMPanel::addHistoryLine(const LLUUID& source, const std::string &u
void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4& color, bool log_to_file)
{
- LLMultiFloater* hostp = getHost();
- if( !getVisible() && hostp && log_to_file)
- {
- // Only flash for logged ("real") messages
- LLTabContainer* parent = (LLTabContainer*) getParent();
- parent->setTabPanelFlashing( this, TRUE );
- }
-
// Now we're adding the actual line of text, so erase the
// "Foo is typing..." text segment, and the optional timestamp
// if it was present. JC
@@ -1330,6 +1536,11 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
LLLogChat::saveHistory(getTitle(),histstr);
}
+
+ if (!isInVisibleChain())
+ {
+ mNumUnreadMessages++;
+ }
}
@@ -1340,10 +1551,7 @@ void LLFloaterIMPanel::setVisible(BOOL b)
LLMultiFloater* hostp = getHost();
if( b && hostp )
{
- LLTabContainer* parent = (LLTabContainer*) getParent();
-
- // When this tab is displayed, you can stop flashing.
- parent->setTabPanelFlashing( this, FALSE );
+ hostp->setFloaterFlashing(this, FALSE);
/* Don't change containing floater title - leave it "Instant Message" JC
LLUIString title = sTitleString;
@@ -1392,7 +1600,7 @@ BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_paren
else if ( KEY_ESCAPE == key )
{
handled = TRUE;
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
// Close talk panel with escape
if( !gSavedSettings.getBOOL("PinTalkViewOpen") )
@@ -1573,14 +1781,14 @@ void LLFloaterIMPanel::onCommitChat(LLUICtrl* caller, void* userdata)
}
// static
-void LLFloaterIMPanel::onInputEditorFocusReceived( LLUICtrl* caller, void* userdata )
+void LLFloaterIMPanel::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata )
{
LLFloaterIMPanel* self= (LLFloaterIMPanel*) userdata;
self->mHistoryEditor->setCursorAndScrollToEnd();
}
// static
-void LLFloaterIMPanel::onInputEditorFocusLost(LLUICtrl* caller, void* userdata)
+void LLFloaterIMPanel::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
self->setTyping(FALSE);
@@ -1628,6 +1836,14 @@ void LLFloaterIMPanel::onClose(bool app_quitting)
destroy();
}
+void LLFloaterIMPanel::onVisibilityChange(BOOL new_visibility)
+{
+ if (new_visibility)
+ {
+ mNumUnreadMessages = 0;
+ }
+}
+
void deliver_message(const std::string& utf8_text,
const LLUUID& im_session_id,
const LLUUID& other_participant_id,
@@ -1739,19 +1955,37 @@ void LLFloaterIMPanel::sendMsg()
mSentTypingState = TRUE;
}
-void LLFloaterIMPanel::updateSpeakersList(LLSD speaker_updates)
-{
- mSpeakers->processSpeakerListUpdate(speaker_updates);
+void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates)
+{
+ mSpeakers->updateSpeakers(speaker_updates);
}
-void LLFloaterIMPanel::setSpeakersListFromMap(LLSD speaker_map)
+void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
{
- mSpeakers->processSpeakerMap(speaker_map);
+ if (
+ session_update.has("moderated_mode") &&
+ session_update["moderated_mode"].has("voice") )
+ {
+ BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+
+ if (voice_moderated)
+ {
+ setTitle(mSessionLabel + LLString(" ") + getFormattedUIString("moderated_chat_label"));
+ }
+ else
+ {
+ setTitle(mSessionLabel);
+ }
+
+
+ //update the speakers dropdown too
+ mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ }
}
-void LLFloaterIMPanel::setSpeakersList(LLSD speaker_list)
+void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list)
{
- mSpeakers->processSpeakerList(speaker_list);
+ mSpeakers->setSpeakers(speaker_list);
}
void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
@@ -1897,5 +2131,77 @@ void LLFloaterIMPanel::chatFromLogFile(LLString line, void* userdata)
//self->addHistoryLine(line, LLColor4::grey, FALSE);
self->mHistoryEditor->appendColoredText(line, false, true, LLColor4::grey);
+}
+
+void LLFloaterIMPanel::showSessionStartError(
+ const std::string& error_string)
+{
+ //the error strings etc. should be really be static and local
+ //to this file instead of in the LLFloaterIM
+ //but they were in llimview.cpp first and unfortunately
+ //some translations into non English languages already occurred
+ //thus making it a tad harder to change over to a
+ //"correct" solution. The best solution
+ //would be to store all of the misc. strings into
+ //their own XML file which would be read in by any LLIMPanel
+ //post build function instead of repeating the same info
+ //in the group, adhoc and normal IM xml files.
+ LLString::format_map_t args;
+ args["[REASON]"] =
+ LLFloaterIM::sErrorStringsMap[error_string];
+ args["[RECIPIENT]"] = getTitle();
+ gViewerWindow->alertXml(
+ "ChatterBoxSessionStartError",
+ args,
+ onConfirmForceCloseError,
+ this);
}
+
+void LLFloaterIMPanel::showSessionEventError(
+ const std::string& event_string,
+ const std::string& error_string)
+{
+ LLString::format_map_t args;
+ args["[REASON]"] =
+ LLFloaterIM::sErrorStringsMap[error_string];
+ args["[EVENT]"] =
+ LLFloaterIM::sEventStringsMap[event_string];
+ args["[RECIPIENT]"] = getTitle();
+
+ gViewerWindow->alertXml(
+ "ChatterBoxSessionEventError",
+ args);
+}
+
+void LLFloaterIMPanel::showSessionForceClose(
+ const std::string& reason_string)
+{
+ LLString::format_map_t args;
+
+ args["[NAME]"] = getTitle();
+ args["[REASON]"] = LLFloaterIM::sForceCloseSessionMap[reason_string];
+
+ gViewerWindow->alertXml(
+ "ForceCloseChatterBoxSession",
+ args,
+ LLFloaterIMPanel::onConfirmForceCloseError,
+ this);
+
+}
+
+//static
+void LLFloaterIMPanel::onKickSpeaker(void* user_data)
+{
+
+}
+
+void LLFloaterIMPanel::onConfirmForceCloseError(S32 option, void* data)
+{
+ //only 1 option really
+ LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data);
+
+ if ( floater ) floater->close(FALSE);
+}
+
+
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index c1ad18dd3c..ef36ff4a33 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -74,14 +74,20 @@ public:
virtual void getChannelInfo();
virtual BOOL isActive();
virtual BOOL callStarted();
+
+ const LLUUID getSessionID() { return mSessionID; }
EState getState() { return mState; }
void updateSessionID(const LLUUID& new_session_id);
+ const LLString::format_map_t& getNotifyArgs() { return mNotifyArgs; }
static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
static LLVoiceChannel* getChannelByURI(LLString uri);
static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
static void initClass();
+
+ static void suspend();
+ static void resume();
protected:
virtual void setState(EState state);
@@ -103,13 +109,14 @@ protected:
static voice_channel_map_uri_t sVoiceChannelURIMap;
static LLVoiceChannel* sCurrentVoiceChannel;
+ static LLVoiceChannel* sSuspendedVoiceChannel;
+ static BOOL sSuspended;
};
class LLVoiceChannelGroup : public LLVoiceChannel
{
public:
LLVoiceChannelGroup(const LLUUID& session_id, const LLString& session_name);
- virtual ~LLVoiceChannelGroup();
/*virtual*/ void handleStatusChange(EStatusType status);
/*virtual*/ void handleError(EStatusType status);
@@ -132,8 +139,7 @@ class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoice
{
public:
LLVoiceChannelProximal();
- virtual ~LLVoiceChannelProximal();
-
+
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void handleStatusChange(EStatusType status);
/*virtual*/ void handleError(EStatusType status);
@@ -147,7 +153,6 @@ class LLVoiceChannelP2P : public LLVoiceChannelGroup
{
public:
LLVoiceChannelP2P(const LLUUID& session_id, const LLString& session_name, const LLUUID& other_user_id);
- virtual ~LLVoiceChannelP2P();
/*virtual*/ void handleStatusChange(EStatusType status);
/*virtual*/ void handleError(EStatusType status);
@@ -156,9 +161,13 @@ public:
void setSessionHandle(const LLString& handle);
+protected:
+ virtual void setState(EState state);
+
private:
LLString mSessionHandle;
LLUUID mOtherUserID;
+ BOOL mReceivedCall;
};
class LLFloaterIMPanel : public LLFloater
@@ -170,15 +179,11 @@ public:
// the default. For example, if you open a session though a
// calling card, a new session id will be generated, but the
// target_id will be the agent referenced by the calling card.
- LLFloaterIMPanel(const std::string& name,
- const LLRect& rect,
- const std::string& session_label,
+ LLFloaterIMPanel(const std::string& session_label,
const LLUUID& session_id,
const LLUUID& target_id,
EInstantMessage dialog);
- LLFloaterIMPanel(const std::string& name,
- const LLRect& rect,
- const std::string& session_label,
+ LLFloaterIMPanel(const std::string& session_label,
const LLUUID& session_id,
const LLUUID& target_id,
const LLDynamicArray<LLUUID>& ids,
@@ -189,8 +194,8 @@ public:
// Check typing timeout timer.
/*virtual*/ void draw();
-
/*virtual*/ void onClose(bool app_quitting = FALSE);
+ /*virtual*/ void onVisibilityChange(BOOL new_visibility);
// add target ids to the session.
// Return TRUE if successful, otherwise FALSE.
@@ -209,14 +214,16 @@ public:
void selectNone();
void setVisible(BOOL b);
+ S32 getNumUnreadMessages() { return mNumUnreadMessages; }
+
BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type,
void *cargo_data, EAcceptance *accept,
LLString& tooltip_msg);
- static void onInputEditorFocusReceived( LLUICtrl* caller, void* userdata );
- static void onInputEditorFocusLost(LLUICtrl* caller, void* userdata);
+ static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
+ static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
static void onCommitChat(LLUICtrl* caller, void* userdata);
static void onTabClick( void* userdata );
@@ -229,16 +236,17 @@ public:
static void onClickSend( void* userdata );
static void onClickToggleActiveSpeakers( void* userdata );
static void* createSpeakersPanel(void* data);
+ static void onKickSpeaker(void* user_data);
//callbacks for P2P muting and volume control
- static void onClickMuteVoice(LLUICtrl* source, void* user_data);
+ static void onClickMuteVoice(void* user_data);
static void onVolumeChange(LLUICtrl* source, void* user_data);
const LLUUID& getSessionID() const { return mSessionUUID; }
const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; }
- void updateSpeakersList(LLSD speaker_updates);
- void setSpeakersListFromMap(LLSD speaker_list);
- void setSpeakersList(LLSD speaker_list);
+ void updateSpeakersList(const LLSD& speaker_updates);
+ void processSessionUpdate(const LLSD& update);
+ void setSpeakers(const LLSD& speaker_list);
LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
EInstantMessage getDialogType() const { return mDialog; }
@@ -250,6 +258,15 @@ public:
void processIMTyping(const LLIMInfo* im_info, BOOL typing);
static void chatFromLogFile(LLString line, void* userdata);
+ //show error statuses to the user
+ void showSessionStartError(const std::string& error_string);
+ void showSessionEventError(
+ const std::string& event_string,
+ const std::string& error_string);
+ void showSessionForceClose(const std::string& reason);
+
+ static void onConfirmForceCloseError(S32 option, void* data);
+
private:
// called by constructors
void init(const LLString& session_label);
@@ -289,6 +306,7 @@ private:
// 911 ==> Gaurdian_Angel_Group_ID ^ gAgent.getID()
LLUUID mSessionUUID;
+ LLString mSessionLabel;
LLVoiceChannel* mVoiceChannel;
BOOL mSessionInitialized;
@@ -318,6 +336,8 @@ private:
// Where does the "Starting session..." line start?
S32 mSessionStartMsgPos;
+ S32 mNumUnreadMessages;
+
BOOL mSentTypingState;
BOOL mShowSpeakersOnConnect;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 9c37f1f333..f93f5810c5 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -46,7 +46,6 @@
#include "llagent.h"
#include "llcallingcard.h"
#include "llchat.h"
-#include "llviewerwindow.h"
#include "llresmgr.h"
#include "llfloaterchat.h"
#include "llfloaterchatterbox.h"
@@ -65,6 +64,7 @@
#include "llcallingcard.h"
#include "lltoolbar.h"
#include "llviewermessage.h"
+#include "llviewerwindow.h"
#include "llnotify.h"
#include "llviewerregion.h"
@@ -84,11 +84,12 @@ LLIMMgr* gIMMgr = NULL;
//*FIXME: make these all either UIStrings or Strings
static LLString sOnlyUserMessage;
static LLUIString sOfflineMessage;
-
-static std::map<std::string,LLString> sEventStringsMap;
-static std::map<std::string,LLString> sErrorStringsMap;
-static std::map<std::string,LLString> sForceCloseSessionMap;
static LLUIString sInviteMessage;
+
+std::map<std::string,LLString> LLFloaterIM::sEventStringsMap;
+std::map<std::string,LLString> LLFloaterIM::sErrorStringsMap;
+std::map<std::string,LLString> LLFloaterIM::sForceCloseSessionMap;
+
//
// Helper Functions
//
@@ -160,22 +161,54 @@ BOOL LLFloaterIM::postBuild()
sOnlyUserMessage = getFormattedUIString("only_user_message");
sOfflineMessage = getUIString("offline_message");
- sErrorStringsMap["generic"] =
- getFormattedUIString("generic_request_error");
- sErrorStringsMap["unverified"] =
- getFormattedUIString("insufficient_perms_error");
- sErrorStringsMap["no_user_911"] =
- getFormattedUIString("user_no_help");
+ sInviteMessage = getUIString("invite_message");
- sEventStringsMap["add"] =
- getFormattedUIString("add_session_event");
- sEventStringsMap["message"] =
- getFormattedUIString("message_session_event");
+ if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() )
+ {
+ sErrorStringsMap["generic"] =
+ getFormattedUIString("generic_request_error");
+ }
- sForceCloseSessionMap["removed"] =
- getFormattedUIString("removed_from_group");
+ if ( sErrorStringsMap.find("unverified") ==
+ sErrorStringsMap.end() )
+ {
+ sErrorStringsMap["unverified"] =
+ getFormattedUIString("insufficient_perms_error");
+ }
+
+ if ( sErrorStringsMap.end() ==
+ sErrorStringsMap.find("does not exist") )
+ {
+ sErrorStringsMap["does not exist"] =
+ getFormattedUIString("session_does_not_exist_error");
+ }
+
+ if ( sEventStringsMap.end() == sEventStringsMap.find("add") )
+ {
+ sEventStringsMap["add"] =
+ getFormattedUIString("add_session_event");
+ }
+
+ if ( sEventStringsMap.end() == sEventStringsMap.find("message") )
+ {
+ sEventStringsMap["message"] =
+ getFormattedUIString("message_session_event");
+ }
+
+ if ( sForceCloseSessionMap.end() ==
+ sForceCloseSessionMap.find("removed") )
+ {
+ sForceCloseSessionMap["removed"] =
+ getFormattedUIString("removed_from_group");
+ }
+
+ if ( sForceCloseSessionMap.end() ==
+ sForceCloseSessionMap.find("no ability") )
+ {
+ sForceCloseSessionMap["no ability"] =
+ getFormattedUIString("close_on_no_ability");
+ }
- sInviteMessage = getUIString("invite_message");
return TRUE;
}
@@ -205,21 +238,31 @@ protected:
class LLIMMgr::LLIMSessionInvite
{
public:
- LLIMSessionInvite(const LLUUID& session_id, const LLString& session_name, const LLUUID& caller_id,const LLString& caller_name, EInstantMessage type, const LLString& session_handle, const LLString& notify_box) :
- mSessionID(session_id),
- mSessionName(session_name),
- mCallerID(caller_id),
- mCallerName(caller_name),
- mType(type),
- mSessionHandle(session_handle),
- mNotifyBox(notify_box)
- {};
+ LLIMSessionInvite(
+ const LLUUID& session_id,
+ const LLString& session_name,
+ const LLUUID& caller_id,
+ const LLString& caller_name,
+ EInstantMessage type,
+ EInvitationType inv_type,
+ const LLString& session_handle,
+ const LLString& notify_box) :
+ mSessionID(session_id),
+ mSessionName(session_name),
+ mCallerID(caller_id),
+ mCallerName(caller_name),
+ mType(type),
+ mInvType(inv_type),
+ mSessionHandle(session_handle),
+ mNotifyBox(notify_box)
+ {};
LLUUID mSessionID;
LLString mSessionName;
LLUUID mCallerID;
LLString mCallerName;
EInstantMessage mType;
+ EInvitationType mInvType;
LLString mSessionHandle;
LLString mNotifyBox;
};
@@ -309,7 +352,7 @@ LLIMMgr::LLIMMgr() :
LLFloaterIM* dummy_floater = new LLFloaterIM();
delete dummy_floater;
- mPendingVoiceInvitations = LLSD::emptyMap();
+ mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
}
@@ -413,7 +456,6 @@ void LLIMMgr::addMessage(
if ( is_from_system ) // chat came from system
{
floater->addHistoryLine(
- other_participant_id,
msg,
gSavedSettings.getColor4("SystemChatColor"));
}
@@ -521,9 +563,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
// the session, dialog specifies the type of session. If the session
// exists, it is brought forward. Specifying id = NULL results in an
// im session to everyone. Returns the uuid of the session.
-LLUUID LLIMMgr::addSession(const std::string& name,
- EInstantMessage dialog,
- const LLUUID& other_participant_id)
+LLUUID LLIMMgr::addSession(
+ const std::string& name,
+ EInstantMessage dialog,
+ const LLUUID& other_participant_id)
{
LLUUID session_id = computeSessionID(dialog, other_participant_id);
@@ -533,15 +576,16 @@ LLUUID LLIMMgr::addSession(const std::string& name,
LLDynamicArray<LLUUID> ids;
ids.put(other_participant_id);
- floater = createFloater(session_id,
- other_participant_id,
- name,
- ids,
- dialog,
- TRUE);
+ floater = createFloater(
+ session_id,
+ other_participant_id,
+ name,
+ ids,
+ dialog,
+ TRUE);
noteOfflineUsers(floater, ids);
- LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
+ LLFloaterChatterBox::showInstance(session_id);
}
else
{
@@ -554,36 +598,43 @@ LLUUID LLIMMgr::addSession(const std::string& name,
// Adds a session using the given session_id. If the session already exists
// the dialog type is assumed correct. Returns the uuid of the session.
-LLUUID LLIMMgr::addSession(const std::string& name,
- EInstantMessage dialog,
- const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids)
+LLUUID LLIMMgr::addSession(
+ const std::string& name,
+ EInstantMessage dialog,
+ const LLUUID& other_participant_id,
+ const LLDynamicArray<LLUUID>& ids)
{
if (0 == ids.getLength())
{
return LLUUID::null;
}
- LLUUID session_id = computeSessionID(dialog,
- other_participant_id);
+ LLUUID session_id = computeSessionID(
+ dialog,
+ other_participant_id);
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(!floater)
{
// On creation, use the first element of ids as the
// "other_participant_id"
- floater = createFloater(session_id,
- other_participant_id,
- name,
- ids,
- dialog,
- TRUE);
+ floater = createFloater(
+ session_id,
+ other_participant_id,
+ name,
+ ids,
+ dialog,
+ TRUE);
if ( !floater ) return LLUUID::null;
noteOfflineUsers(floater, ids);
+ LLFloaterChatterBox::showInstance(session_id);
+ }
+ else
+ {
+ floater->open();
}
- LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
//mTabContainer->selectTabPanel(panel);
floater->setInputFocus(TRUE);
return floater->getSessionID();
@@ -599,6 +650,9 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
mFloaters.erase(floater->getHandle());
LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
//mTabContainer->removeTabPanel(floater);
+
+ clearPendingInviation(session_id);
+ clearPendingAgentListUpdates(session_id);
}
}
@@ -608,9 +662,10 @@ void LLIMMgr::inviteToSession(
const LLUUID& caller_id,
const LLString& caller_name,
EInstantMessage type,
+ EInvitationType inv_type,
const LLString& session_handle)
{
- //ignore voice invites from voice-muted residents
+ //ignore invites from muted residents
if (gMuteListp->isMuted(caller_id))
{
return;
@@ -621,17 +676,26 @@ void LLIMMgr::inviteToSession(
BOOL ad_hoc_invite = FALSE;
if(type == IM_SESSION_P2P_INVITE)
{
+ //P2P is different...they only have voice invitations
notify_box_type = "VoiceInviteP2P";
}
- else if (gAgent.isInGroup(session_id))
+ else if ( gAgent.isInGroup(session_id) )
{
+ //only really old school groups have voice invitations
notify_box_type = "VoiceInviteGroup";
}
- else
+ else if ( inv_type == INVITATION_TYPE_VOICE )
{
+ //else it's an ad-hoc
+ //and a voice ad-hoc
notify_box_type = "VoiceInviteAdHoc";
ad_hoc_invite = TRUE;
}
+ else if ( inv_type == INVITATION_TYPE_IMMEDIATE )
+ {
+ notify_box_type = "InviteAdHoc";
+ ad_hoc_invite = TRUE;
+ }
LLIMSessionInvite* invite = new LLIMSessionInvite(
session_id,
@@ -639,6 +703,7 @@ void LLIMMgr::inviteToSession(
caller_id,
caller_name,
type,
+ inv_type,
session_handle,
notify_box_type);
@@ -666,7 +731,7 @@ void LLIMMgr::inviteToSession(
}
}
- if ( !mPendingVoiceInvitations.has(session_id.asString()) )
+ if ( !mPendingInvitations.has(session_id.asString()) )
{
if (caller_name.empty())
{
@@ -684,7 +749,7 @@ void LLIMMgr::inviteToSession(
(void*)invite);
}
- mPendingVoiceInvitations[session_id.asString()] = LLSD();
+ mPendingInvitations[session_id.asString()] = LLSD();
}
}
@@ -699,10 +764,11 @@ void LLIMMgr::onInviteNameLookup(const LLUUID& id, const char* first, const char
LLString::format_map_t args;
args["[NAME]"] = invite->mCallerName;
- LLNotifyBox::showXml(invite->mNotifyBox,
- args,
- inviteUserResponse,
- (void*)invite);
+ LLNotifyBox::showXml(
+ invite->mNotifyBox,
+ args,
+ inviteUserResponse,
+ (void*)invite);
}
class LLViewerChatterBoxInvitationAcceptResponder :
@@ -711,10 +777,10 @@ class LLViewerChatterBoxInvitationAcceptResponder :
public:
LLViewerChatterBoxInvitationAcceptResponder(
const LLUUID& session_id,
- bool is_voice_invitation)
+ LLIMMgr::EInvitationType invitation_type)
{
mSessionID = session_id;
- mIsVoiceInvitiation = is_voice_invitation;
+ mInvitiationType = invitation_type;
}
void result(const LLSD& content)
@@ -738,48 +804,67 @@ public:
//but unfortunately, our base that we are receiving here
//may not be the most up to date. It was accurate at
//some point in time though.
- floaterp->setSpeakersList(content["agents"]);
+ floaterp->setSpeakers(content);
//we now have our base of users in the session
//that was accurate at some point, but maybe not now
//so now we apply all of the udpates we've received
//in case of race conditions
-
- //reapplying a user entrance will do nothing
- //reapplying a user leaving will not have the user
- //in our base. So it's all good
floaterp->updateSpeakersList(
gIMMgr->getPendingAgentListUpdates(mSessionID));
- if ( mIsVoiceInvitiation )
+ if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
{
floaterp->requestAutoConnect();
LLFloaterIMPanel::onClickStartCall(floaterp);
// always open IM window when connecting to voice
LLFloaterChatterBox::showInstance(TRUE);
}
+ else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
+ {
+ LLFloaterChatterBox::showInstance(TRUE);
+ }
}
gIMMgr->clearPendingAgentListUpdates(mSessionID);
- if ( mIsVoiceInvitiation )
- {
- gIMMgr->clearPendingVoiceInviation(mSessionID);
- }
+ gIMMgr->clearPendingInviation(mSessionID);
}
}
void error(U32 statusNum, const std::string& reason)
{
+
//throw something back to the viewer here?
- if ( gIMMgr && mIsVoiceInvitiation )
+ if ( gIMMgr )
{
- gIMMgr->clearPendingVoiceInviation(mSessionID);
+ gIMMgr->clearPendingAgentListUpdates(mSessionID);
+ gIMMgr->clearPendingInviation(mSessionID);
+
+ LLFloaterIMPanel* floaterp =
+ gIMMgr->findFloaterBySession(mSessionID);
+
+ if (floaterp)
+ {
+ std::string error_string;
+
+ if ( 404 == statusNum )
+ {
+ error_string = "does not exist";
+ }
+ else
+ {
+ error_string = "generic_request_error";
+ }
+
+ floaterp->showSessionStartError(
+ error_string);
+ }
}
}
private:
LLUUID mSessionID;
- bool mIsVoiceInvitiation;
+ LLIMMgr::EInvitationType mInvitiationType;
};
//static
@@ -807,10 +892,11 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
im_floater->requestAutoConnect();
LLFloaterIMPanel::onClickStartCall(im_floater);
// always open IM window when connecting to voice
- LLFloaterChatterBox::showInstance(TRUE);
+ LLFloaterChatterBox::showInstance(invitep->mSessionID);
}
-
- gIMMgr->clearPendingVoiceInviation(invitep->mSessionID);
+
+ gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
+ gIMMgr->clearPendingInviation(invitep->mSessionID);
}
else
{
@@ -830,34 +916,50 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
data,
new LLViewerChatterBoxInvitationAcceptResponder(
invitep->mSessionID,
- true));
+ invitep->mInvType));
}
}
break;
case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
+ {
+ // mute the sender of this invite
+ if (!gMuteListp->isMuted(invitep->mCallerID))
{
- // mute the sender of this invite
- if (!gMuteListp->isMuted(invitep->mCallerID))
- {
- LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
- gMuteListp->add(mute);
- }
+ LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
+ gMuteListp->add(mute);
}
+ }
/* FALLTHROUGH */
- case 1: // ignore
+ case 1: // decline
+ {
+ if (invitep->mType == IM_SESSION_P2P_INVITE)
{
- if (invitep->mType == IM_SESSION_P2P_INVITE)
+ if(gVoiceClient)
{
- if(gVoiceClient)
- {
- gVoiceClient->declineInvite(invitep->mSessionHandle);
- }
+ gVoiceClient->declineInvite(invitep->mSessionHandle);
}
}
- break;
+ else
+ {
+ std::string url = gAgent.getRegion()->getCapability(
+ "ChatSessionRequest");
+
+ LLSD data;
+ data["method"] = "decline invitation";
+ data["session-id"] = invitep->mSessionID;
+ LLHTTPClient::post(
+ url,
+ data,
+ NULL);
+ }
}
+ gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
+ gIMMgr->clearPendingInviation(invitep->mSessionID);
+ break;
+ }
+
delete invitep;
}
@@ -869,11 +971,11 @@ void LLIMMgr::setFloaterOpen(BOOL set_open)
{
if (set_open)
{
- LLFloaterChatterBox::showInstance(LLSD());
+ LLFloaterChatterBox::showInstance();
}
else
{
- LLFloaterChatterBox::hideInstance(LLSD());
+ LLFloaterChatterBox::hideInstance();
}
}
@@ -932,11 +1034,11 @@ BOOL LLIMMgr::hasSession(const LLUUID& session_id)
return (findFloaterBySession(session_id) != NULL);
}
-void LLIMMgr::clearPendingVoiceInviation(const LLUUID& session_id)
+void LLIMMgr::clearPendingInviation(const LLUUID& session_id)
{
- if ( mPendingVoiceInvitations.has(session_id.asString()) )
+ if ( mPendingInvitations.has(session_id.asString()) )
{
- mPendingVoiceInvitations.erase(session_id.asString());
+ mPendingInvitations.erase(session_id.asString());
}
}
@@ -958,13 +1060,57 @@ void LLIMMgr::addPendingAgentListUpdates(
{
LLSD::map_const_iterator iter;
- for ( iter = updates.beginMap();
- iter != updates.endMap();
- iter++)
+ if ( !mPendingAgentListUpdates.has(session_id.asString()) )
{
- //we only want to include the last update for a given agent
- mPendingAgentListUpdates[session_id.asString()][iter->first] =
- iter->second;
+ //this is a new agent list update for this session
+ mPendingAgentListUpdates[session_id.asString()] = LLSD::emptyMap();
+ }
+
+ if (
+ updates.has("agent_updates") &&
+ updates["agent_updates"].isMap() &&
+ updates.has("updates") &&
+ updates["updates"].isMap() )
+ {
+ //new school update
+ LLSD update_types = LLSD::emptyArray();
+ LLSD::array_iterator array_iter;
+
+ update_types.append("agent_updates");
+ update_types.append("updates");
+
+ for (
+ array_iter = update_types.beginArray();
+ array_iter != update_types.endArray();
+ ++array_iter)
+ {
+ //we only want to include the last update for a given agent
+ for (
+ iter = updates[array_iter->asString()].beginMap();
+ iter != updates[array_iter->asString()].endMap();
+ ++iter)
+ {
+ mPendingAgentListUpdates[session_id.asString()][array_iter->asString()][iter->first] =
+ iter->second;
+ }
+ }
+ }
+ else if (
+ updates.has("updates") &&
+ updates["updates"].isMap() )
+ {
+ //old school update where the SD contained just mappings
+ //of agent_id -> "LEAVE"/"ENTER"
+
+ //only want to keep last update for each agent
+ for (
+ iter = updates["updates"].beginMap();
+ iter != updates["updates"].endMap();
+ ++iter)
+ {
+ mPendingAgentListUpdates[session_id.asString()]["updates"][iter->first] =
+ iter->second;
+ }
}
}
@@ -995,8 +1141,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
llinfos << "LLIMMgr::createFloater: from " << other_participant_id
<< " in session " << session_id << llendl;
LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
- LLRect(),
- session_label,
session_id,
other_participant_id,
dialog);
@@ -1022,8 +1166,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
llinfos << "LLIMMgr::createFloater: from " << other_participant_id
<< " in session " << session_id << llendl;
LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
- LLRect(),
- session_label,
session_id,
other_participant_id,
ids,
@@ -1034,8 +1176,9 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
return floater;
}
-void LLIMMgr::noteOfflineUsers(LLFloaterIMPanel* floater,
- const LLDynamicArray<LLUUID>& ids)
+void LLIMMgr::noteOfflineUsers(
+ LLFloaterIMPanel* floater,
+ const LLDynamicArray<LLUUID>& ids)
{
S32 count = ids.count();
if(count == 0)
@@ -1099,14 +1242,6 @@ LLFloaterChatterBox* LLIMMgr::getFloater()
return LLFloaterChatterBox::getInstance(LLSD());
}
-void onConfirmForceCloseError(S32 option, void* data)
-{
- //only 1 option really
- LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data);
-
- if ( floater ) floater->close(FALSE);
-}
-
class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
{
public:
@@ -1141,7 +1276,16 @@ public:
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
if (floaterp)
{
- floaterp->setSpeakersList(body["agents"]);
+ floaterp->setSpeakers(body);
+
+ //apply updates we've possibly received previously
+ floaterp->updateSpeakersList(
+ gIMMgr->getPendingAgentListUpdates(session_id));
+
+ if ( body.has("session_info") )
+ {
+ floaterp->processSessionUpdate(body["session_info"]);
+ }
//aply updates we've possibly received previously
floaterp->updateSpeakersList(
@@ -1155,20 +1299,14 @@ public:
//floater
LLFloaterIMPanel* floater =
gIMMgr->findFloaterBySession(temp_session_id);
- if (floater)
- {
- LLString::format_map_t args;
- args["[REASON]"] =
- sErrorStringsMap[body["error"].asString()];
- args["[RECIPIENT]"] = floater->getTitle();
-
- gViewerWindow->alertXml("ChatterBoxSessionStartError",
- args,
- onConfirmForceCloseError,
- floater);
+ if ( floater )
+ {
+ floater->showSessionStartError(body["error"].asString());
}
}
+
+ gIMMgr->clearPendingAgentListUpdates(session_id);
}
};
@@ -1200,17 +1338,12 @@ public:
//throw an error dialog
LLFloaterIMPanel* floater =
gIMMgr->findFloaterBySession(session_id);
+
if (floater)
{
- LLString::format_map_t args;
- args["[REASON]"] =
- sErrorStringsMap[body["error"].asString()];
- args["[EVENT]"] =
- sEventStringsMap[body["event"].asString()];
- args["[RECIPIENT]"] = floater->getTitle();
-
- gViewerWindow->alertXml("ChatterBoxSessionEventError",
- args);
+ floater->showSessionEventError(
+ body["event"].asString(),
+ body["error"].asString());
}
}
}
@@ -1234,15 +1367,7 @@ public:
if ( floater )
{
- LLString::format_map_t args;
-
- args["[NAME]"] = floater->getTitle();
- args["[REASON]"] = sForceCloseSessionMap[reason];
-
- gViewerWindow->alertXml("ForceCloseChatterBoxSession",
- args,
- onConfirmForceCloseError,
- floater);
+ floater->showSessionForceClose(reason);
}
}
};
@@ -1258,7 +1383,8 @@ public:
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
if (floaterp)
{
- floaterp->updateSpeakersList(input["body"]["updates"]);
+ floaterp->updateSpeakersList(
+ input["body"]);
}
else
{
@@ -1267,11 +1393,28 @@ public:
//a start or an acceptance of an invitation. Race condition.
gIMMgr->addPendingAgentListUpdates(
input["body"]["session_id"].asUUID(),
- input["body"]["updates"]);
+ input["body"]);
+ }
+ }
+};
+
+class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
+{
+public:
+ virtual void post(
+ ResponsePtr responder,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
+ if (floaterp)
+ {
+ floaterp->processSessionUpdate(input["body"]["info"]);
}
}
};
+
class LLViewerChatterBoxInvitation : public LLHTTPNode
{
public:
@@ -1281,6 +1424,8 @@ public:
const LLSD& context,
const LLSD& input) const
{
+ //for backwards compatiblity reasons...we need to still
+ //check for 'text' or 'voice' invitations...bleh
if ( input["body"].has("instantmessage") )
{
LLString capability = input["body"]["capabilities"]["call"].asString();
@@ -1397,8 +1542,8 @@ public:
url,
data,
new LLViewerChatterBoxInvitationAcceptResponder(
- input["body"]["session_id"],
- false));
+ input["body"]["session_id"].asUUID(),
+ LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
}
} //end if invitation has instant message
else if ( input["body"].has("voice") )
@@ -1419,7 +1564,18 @@ public:
input["body"]["session_name"].asString(),
input["body"]["from_id"].asUUID(),
input["body"]["from_name"].asString(),
- IM_SESSION_INVITE);
+ IM_SESSION_INVITE,
+ LLIMMgr::INVITATION_TYPE_VOICE);
+ }
+ else if ( input["body"].has("immediate") )
+ {
+ gIMMgr->inviteToSession(
+ input["body"]["session_id"].asUUID(),
+ input["body"]["session_name"].asString(),
+ input["body"]["from_id"].asUUID(),
+ input["body"]["from_name"].asString(),
+ IM_SESSION_INVITE,
+ LLIMMgr::INVITATION_TYPE_IMMEDIATE);
}
}
};
@@ -1440,6 +1596,10 @@ LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates>
gHTTPRegistrationMessageChatterboxsessionagentlistupdates(
"/message/ChatterBoxSessionAgentListUpdates");
+LLHTTPRegistration<LLViewerChatterBoxSessionUpdate>
+ gHTTPRegistrationMessageChatterBoxSessionUpdate(
+ "/message/ChatterBoxSessionUpdate");
+
LLHTTPRegistration<LLViewerChatterBoxInvitation>
gHTTPRegistrationMessageChatterBoxInvitation(
"/message/ChatterBoxInvitation");
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index f5356ef926..11a6905a63 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -45,6 +45,13 @@ class LLFloaterIM;
class LLIMMgr : public LLSingleton<LLIMMgr>
{
public:
+ enum EInvitationType
+ {
+ INVITATION_TYPE_INSTANT_MESSAGE = 0,
+ INVITATION_TYPE_VOICE = 1,
+ INVITATION_TYPE_IMMEDIATE = 2
+ };
+
LLIMMgr();
virtual ~LLIMMgr();
@@ -96,12 +103,14 @@ public:
// deleted.
void removeSession(const LLUUID& session_id);
- void inviteToSession(const LLUUID& session_id,
- const LLString& session_name,
- const LLUUID& caller,
- const LLString& caller_name,
- EInstantMessage type,
- const LLString& session_handle = LLString::null);
+ void inviteToSession(
+ const LLUUID& session_id,
+ const LLString& session_name,
+ const LLUUID& caller,
+ const LLString& caller_name,
+ EInstantMessage type,
+ EInvitationType inv_type,
+ const LLString& session_handle = LLString::null);
//Updates a given session's session IDs. Does not open,
//create or do anything new. If the old session doesn't
@@ -147,7 +156,7 @@ public:
static LLUUID computeSessionID(EInstantMessage dialog, const LLUUID& other_participant_id);
- void clearPendingVoiceInviation(const LLUUID& session_id);
+ void clearPendingInviation(const LLUUID& session_id);
LLSD getPendingAgentListUpdates(const LLUUID& session_id);
void addPendingAgentListUpdates(
@@ -155,6 +164,9 @@ public:
const LLSD& updates);
void clearPendingAgentListUpdates(const LLUUID& session_id);
+ //HACK: need a better way of enumerating existing session, or listening to session create/destroy events
+ const std::set<LLViewHandle>& getIMFloaterHandles() { return mFloaters; }
+
private:
class LLIMSessionInvite;
@@ -193,7 +205,7 @@ private:
// An IM has been received that you haven't seen yet.
BOOL mIMReceived;
- LLSD mPendingVoiceInvitations;
+ LLSD mPendingInvitations;
LLSD mPendingAgentListUpdates;
};
@@ -203,6 +215,10 @@ class LLFloaterIM : public LLMultiFloater
public:
LLFloaterIM();
/*virtual*/ BOOL postBuild();
+
+ static std::map<std::string,LLString> sEventStringsMap;
+ static std::map<std::string,LLString> sErrorStringsMap;
+ static std::map<std::string,LLString> sForceCloseSessionMap;
};
// Globals
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 9c9b1ad257..d8841afe22 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3165,7 +3165,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
std::string(),
cb);
}
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
else if ("detach" == action)
{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index ca65b879bc..7b27a830c4 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2606,7 +2606,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
// }
//
// // restore keyboard focus
- // gFocusMgr.setKeyboardFocus(focus_view, callback);
+ // gFocusMgr.setKeyboardFocus(focus_view);
//}
}
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index 20c4a25003..30106443c0 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -607,26 +607,26 @@ void LLJoystickCameraRotate::draw()
{
LLGLSUIDefault gls_ui;
- gl_draw_image( 0, 0, mImageUnselected );
+ mImageUnselected->draw( 0, 0 );
if( mInTop )
{
- drawRotatedImage( mImageSelected, 0 );
+ drawRotatedImage( mImageSelected->getImage(), 0 );
}
if( mInRight )
{
- drawRotatedImage( mImageSelected, 1 );
+ drawRotatedImage( mImageSelected->getImage(), 1 );
}
if( mInBottom )
{
- drawRotatedImage( mImageSelected, 2 );
+ drawRotatedImage( mImageSelected->getImage(), 2 );
}
if( mInLeft )
{
- drawRotatedImage( mImageSelected, 3 );
+ drawRotatedImage( mImageSelected->getImage(), 3 );
}
if (sDebugRects)
@@ -801,7 +801,7 @@ void LLJoystickCameraZoom::draw()
}
else
{
- gl_draw_image( 0, 0, mImageUnselected );
+ mImageUnselected->draw( 0, 0 );
}
if (sDebugRects)
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 4d02af8fae..60d39b62bd 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -52,10 +52,11 @@
#include <boost/tokenizer.hpp>
#include "llcrc.h"
+#include "lldir.h"
#include "lldispatcher.h"
+#include "llsdserialize.h"
#include "llxfermanager.h"
#include "message.h"
-#include "lldir.h"
#include "llagent.h"
#include "llfloatermute.h"
@@ -67,6 +68,9 @@
LLMuteList* gMuteListp = NULL;
+std::map<LLUUID, F32> LLMuteList::sUserVolumeSettings;
+
+
// "emptymutelist"
class LLDispatchEmptyMuteList : public LLDispatchHandler
{
@@ -168,6 +172,24 @@ LLMuteList::LLMuteList() :
msg->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList);
gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
+
+ // load per-resident voice volume information
+ // conceptually, this is part of the mute list information, although it is only stored locally
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
+
+ LLSD settings_llsd;
+ llifstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(settings_llsd, file);
+ }
+
+ for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+ iter != settings_llsd.endMap(); ++iter)
+ {
+ sUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal()));
+ }
}
//-----------------------------------------------------------------------------
@@ -175,6 +197,17 @@ LLMuteList::LLMuteList() :
//-----------------------------------------------------------------------------
LLMuteList::~LLMuteList()
{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
+ LLSD settings_llsd;
+
+ for(user_volume_map_t::iterator iter = sUserVolumeSettings.begin(); iter != sUserVolumeSettings.end(); ++iter)
+ {
+ settings_llsd[iter->first.asString()] = iter->second;
+ }
+
+ llofstream file;
+ file.open(filename.c_str());
+ LLSDSerialize::toPrettyXML(settings_llsd, file);
}
BOOL LLMuteList::isLinden(const LLString& name) const
@@ -588,6 +621,25 @@ void LLMuteList::cache(const LLUUID& agent_id)
}
}
+void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume)
+{
+ // store new value in volume settings file
+ sUserVolumeSettings[id] = volume;
+}
+
+F32 LLMuteList::getSavedResidentVolume(const LLUUID& id)
+{
+ const F32 DEFAULT_VOLUME = 0.5f;
+
+ user_volume_map_t::iterator found_it = sUserVolumeSettings.find(id);
+ if (found_it != sUserVolumeSettings.end())
+ {
+ return found_it->second;
+ }
+ //FIXME: assumes default, should get this from somewhere
+ return DEFAULT_VOLUME;
+}
+
//-----------------------------------------------------------------------------
// Static message handlers
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 23e0620ade..413a2933b3 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -112,6 +112,9 @@ public:
// call this method on logout to save everything.
void cache(const LLUUID& agent_id);
+ void setSavedResidentVolume(const LLUUID& id, F32 volume);
+ F32 getSavedResidentVolume(const LLUUID& id);
+
private:
BOOL loadFromFile(const LLString& filename);
BOOL saveToFile(const LLString& filename);
@@ -155,6 +158,9 @@ private:
BOOL mIsLoaded;
friend class LLDispatchEmptyMuteList;
+
+ typedef std::map<LLUUID, F32> user_volume_map_t;
+ static user_volume_map_t sUserVolumeSettings;
};
class LLMuteListObserver
diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp
index ba1280550f..1ca702b0a7 100644
--- a/indra/newview/llnameeditor.cpp
+++ b/indra/newview/llnameeditor.cpp
@@ -53,7 +53,7 @@ LLNameEditor::LLNameEditor(const std::string& name, const LLRect& rect,
S32 max_text_length,
void (*commit_callback)(LLUICtrl* caller, void* user_data),
void (*keystroke_callback)(LLLineEditor* caller, void* user_data),
- void (*focus_lost_callback)(LLUICtrl* caller, void* user_data),
+ void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data),
void* userdata,
LLLinePrevalidateFunc prevalidate_func,
LLViewBorder::EBevel border_bevel,
diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h
index 526b76b9c0..9c89454c33 100644
--- a/indra/newview/llnameeditor.h
+++ b/indra/newview/llnameeditor.h
@@ -53,7 +53,7 @@ public:
S32 max_text_length = 254,
void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
- void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL,
+ void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL,
void* userdata = NULL,
LLLinePrevalidateFunc prevalidate_func = NULL,
LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index adcc141bb1..a47721be9d 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -224,7 +224,7 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos
LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
((LLScrollListText*)cell)->setText( fullname );
- updateMaxContentWidth(item);
+ calcMaxContentWidth(item);
// this column is resizable
LLScrollListColumn* columnp = getColumn(mNameColumnIndex);
@@ -277,7 +277,7 @@ void LLNameListCtrl::refresh(const LLUUID& id, const char* first,
cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
((LLScrollListText*)cell)->setText( fullname );
- updateMaxContentWidth(item);
+ calcMaxContentWidth(item);
}
}
}
diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp
index 15c993e552..e7c313638b 100644
--- a/indra/newview/lloverlaybar.cpp
+++ b/indra/newview/lloverlaybar.cpp
@@ -39,6 +39,7 @@
#include "audioengine.h"
#include "llagent.h"
#include "llbutton.h"
+#include "llchatbar.h"
#include "llfocusmgr.h"
#include "llimview.h"
#include "llmediaengine.h"
@@ -71,37 +72,14 @@ extern S32 MENU_BAR_HEIGHT;
//
-//static
-void* LLOverlayBar::createMasterRemote(void* userdata)
-{
- LLOverlayBar *self = (LLOverlayBar*)userdata;
- self->mMasterRemote = new LLMediaRemoteCtrl ( "master_volume",
- "volume",
- LLRect(),
- "panel_master_volume.xml");
- return self->mMasterRemote;
-}
void* LLOverlayBar::createMediaRemote(void* userdata)
{
LLOverlayBar *self = (LLOverlayBar*)userdata;
- self->mMediaRemote = new LLMediaRemoteCtrl ( "media_remote",
- "media",
- LLRect(),
- "panel_media_remote.xml");
+ self->mMediaRemote = new LLMediaRemoteCtrl ();
return self->mMediaRemote;
}
-void* LLOverlayBar::createMusicRemote(void* userdata)
-{
- LLOverlayBar *self = (LLOverlayBar*)userdata;
- self->mMusicRemote = new LLMediaRemoteCtrl ( "music_remote",
- "music",
- LLRect(),
- "panel_music_remote.xml" );
- return self->mMusicRemote;
-}
-
void* LLOverlayBar::createVoiceRemote(void* userdata)
{
LLOverlayBar *self = (LLOverlayBar*)userdata;
@@ -109,13 +87,14 @@ void* LLOverlayBar::createVoiceRemote(void* userdata)
return self->mVoiceRemote;
}
+void* LLOverlayBar::createChatBar(void* userdata)
+{
+ gChatBar = new LLChatBar();
+ return gChatBar;
+}
-
-
-LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect)
- : LLPanel(name, rect, FALSE), // not bordered
- mMasterRemote(NULL),
- mMusicRemote(NULL),
+LLOverlayBar::LLOverlayBar()
+ : LLPanel(),
mMediaRemote(NULL),
mVoiceRemote(NULL),
mMediaState(STOPPED),
@@ -127,25 +106,27 @@ LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect)
mBuilt = false;
LLCallbackMap::map_t factory_map;
- factory_map["master_volume"] = LLCallbackMap(LLOverlayBar::createMasterRemote, this);
factory_map["media_remote"] = LLCallbackMap(LLOverlayBar::createMediaRemote, this);
- factory_map["music_remote"] = LLCallbackMap(LLOverlayBar::createMusicRemote, this);
factory_map["voice_remote"] = LLCallbackMap(LLOverlayBar::createVoiceRemote, this);
+ factory_map["chat_bar"] = LLCallbackMap(LLOverlayBar::createChatBar, this);
gUICtrlFactory->buildPanel(this, "panel_overlaybar.xml", &factory_map);
-
+}
+
+BOOL LLOverlayBar::postBuild()
+{
childSetAction("IM Received",onClickIMReceived,this);
childSetAction("Set Not Busy",onClickSetNotBusy,this);
childSetAction("Release Keys",onClickReleaseKeys,this);
childSetAction("Mouselook",onClickMouselook,this);
childSetAction("Stand Up",onClickStandUp,this);
+ childSetVisible("chat_bar", gSavedSettings.getBOOL("ChatVisible"));
mIsFocusRoot = TRUE;
mBuilt = true;
- // make overlay bar conform to window size
- setRect(rect);
layoutButtons();
+ return TRUE;
}
LLOverlayBar::~LLOverlayBar()
@@ -176,146 +157,45 @@ void LLOverlayBar::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLOverlayBar::layoutButtons()
{
- S32 width = mRect.getWidth();
- if (width > 1024) width = 1024;
-
- S32 count = getChildCount();
- const S32 PAD = gSavedSettings.getS32("StatusBarPad");
-
- const S32 num_media_controls = 3;
- S32 media_remote_width = mMediaRemote ? mMediaRemote->getRect().getWidth() : 0;
- S32 music_remote_width = mMusicRemote ? mMusicRemote->getRect().getWidth() : 0;
- S32 voice_remote_width = mVoiceRemote ? mVoiceRemote->getRect().getWidth() : 0;
- S32 master_remote_width = mMasterRemote ? mMasterRemote->getRect().getWidth() : 0;
-
- // total reserved width for all media remotes
- const S32 ENDPAD = 20;
- S32 remote_total_width = media_remote_width + PAD + music_remote_width + PAD + voice_remote_width + PAD + master_remote_width + ENDPAD;
+ LLView* state_buttons_panel = getChildByName("state_buttons", TRUE);
- // calculate button widths
- F32 segment_width = (F32)(width - remote_total_width) / (F32)(count - num_media_controls);
-
- S32 btn_width = lltrunc(segment_width - PAD);
-
- // Evenly space all views
- LLRect r;
- S32 i = 0;
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ if (state_buttons_panel)
{
- LLView *view = *child_iter;
- r = view->getRect();
- r.mLeft = (width) - llround(remote_total_width + (i-num_media_controls+1)*segment_width);
- r.mRight = r.mLeft + btn_width;
- view->setRect(r);
- i++;
- }
+ LLViewQuery query;
+ LLWidgetTypeFilter widget_filter(WIDGET_TYPE_BUTTON);
+ query.addPreFilter(LLVisibleFilter::getInstance());
+ query.addPreFilter(LLEnabledFilter::getInstance());
+ query.addPreFilter(&widget_filter);
- // Fix up remotes to have constant width because they can't shrink
- S32 right = mRect.getWidth() - remote_total_width - PAD;
- if (mMediaRemote)
- {
- r = mMediaRemote->getRect();
- r.mLeft = right + PAD;
- right = r.mLeft + media_remote_width;
- r.mRight = right;
- mMediaRemote->setRect(r);
- }
- if (mMusicRemote)
- {
- r = mMusicRemote->getRect();
- r.mLeft = right + PAD;
- right = r.mLeft + music_remote_width;
- r.mRight = right;
- mMusicRemote->setRect(r);
- }
- if (mVoiceRemote)
- {
- r = mVoiceRemote->getRect();
- r.mLeft = right + PAD;
- right = r.mLeft + voice_remote_width;
- r.mRight = right;
- mVoiceRemote->setRect(r);
- }
- if (mMasterRemote)
- {
- r = mMasterRemote->getRect();
- r.mLeft = right + PAD;
- right = r.mLeft + master_remote_width;
- r.mRight = right;
- mMasterRemote->setRect(r);
- }
-
- updateRect();
-}
+ child_list_t button_list = query(state_buttons_panel);
-void LLOverlayBar::draw()
-{
- // retrieve rounded rect image
- LLUUID image_id;
- image_id.set(gViewerArt.getString("rounded_square.tga"));
- LLViewerImage* imagep = gImageList.getImage(image_id, MIPMAP_FALSE, TRUE);
+ const S32 MAX_BAR_WIDTH = 600;
+ S32 bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH);
- if (imagep)
- {
- LLGLSTexture texture_enabled;
- LLViewerImage::bindTexture(imagep);
+ // calculate button widths
+ const S32 MAX_BUTTON_WIDTH = 150;
+ S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_list.size()), 0, MAX_BUTTON_WIDTH);
+ S32 btn_width = segment_width - gSavedSettings.getS32("StatusBarPad");
- const S32 PAD = gSavedSettings.getS32("StatusBarPad");
+ // Evenly space all buttons, starting from left
+ S32 left = 0;
+ S32 bottom = 1;
- // draw rounded rect tabs behind all children
- LLRect r;
- // focus highlights
- LLColor4 color = gColors.getColor("FloaterFocusBorderColor");
- glColor4fv(color.mV);
- if(gFocusMgr.childHasKeyboardFocus(gBottomPanel))
- {
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
- {
- LLView *view = *child_iter;
- if(view->getEnabled() && view->getVisible())
- {
- r = view->getRect();
- gl_segmented_rect_2d_tex(r.mLeft - PAD/3 - 1,
- r.mTop + 3,
- r.mRight + PAD/3 + 1,
- r.mBottom,
- imagep->getWidth(),
- imagep->getHeight(),
- 16,
- ROUNDED_RECT_TOP);
- }
- }
- }
-
- // main tabs
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ for (child_list_reverse_iter_t child_iter = button_list.rbegin();
+ child_iter != button_list.rend(); ++child_iter)
{
LLView *view = *child_iter;
- if(view->getEnabled() && view->getVisible())
- {
- r = view->getRect();
- // draw a nice little pseudo-3D outline
- color = gColors.getColor("DefaultShadowDark");
- glColor4fv(color.mV);
- gl_segmented_rect_2d_tex(r.mLeft - PAD/3 + 1, r.mTop + 2, r.mRight + PAD/3, r.mBottom,
- imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP);
- color = gColors.getColor("DefaultHighlightLight");
- glColor4fv(color.mV);
- gl_segmented_rect_2d_tex(r.mLeft - PAD/3, r.mTop + 2, r.mRight + PAD/3 - 3, r.mBottom,
- imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP);
- // here's the main background. Note that it overhangs on the bottom so as to hide the
- // focus highlight on the bottom panel, thus producing the illusion that the focus highlight
- // continues around the tabs
- color = gColors.getColor("FocusBackgroundColor");
- glColor4fv(color.mV);
- gl_segmented_rect_2d_tex(r.mLeft - PAD/3 + 1, r.mTop + 1, r.mRight + PAD/3 - 1, r.mBottom - 1,
- imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP);
- }
+ LLRect r = view->getRect();
+ r.setOriginAndSize(left, bottom, btn_width, r.getHeight());
+ view->setRect(r);
+ left += segment_width;
}
}
+}
+
+void LLOverlayBar::draw()
+{
+ childSetVisible("chat_bar", gSavedSettings.getBOOL("ChatVisible"));
// draw children on top
LLPanel::draw();
@@ -325,79 +205,74 @@ void LLOverlayBar::draw()
// Per-frame updates of visibility
void LLOverlayBar::refresh()
{
+ BOOL buttons_changed = FALSE;
+
BOOL im_received = gIMMgr->getIMReceived();
- childSetVisible("IM Received", im_received);
- childSetEnabled("IM Received", im_received);
+ LLButton* button = LLUICtrlFactory::getButtonByName(this, "IM Received");
+ if (button && button->getVisible() != im_received)
+ {
+ button->setVisible(im_received);
+ sendChildToFront(button);
+ moveChildToBackOfTabGroup(button);
+ buttons_changed = TRUE;
+ }
BOOL busy = gAgent.getBusy();
- childSetVisible("Set Not Busy", busy);
- childSetEnabled("Set Not Busy", busy);
+ button = LLUICtrlFactory::getButtonByName(this, "Set Not Busy");
+ if (button && button->getVisible() != busy)
+ {
+ button->setVisible(busy);
+ sendChildToFront(button);
+ moveChildToBackOfTabGroup(button);
+ buttons_changed = TRUE;
+ }
BOOL controls_grabbed = gAgent.anyControlGrabbed();
+ button = LLUICtrlFactory::getButtonByName(this, "Release Keys");
- childSetVisible("Release Keys", controls_grabbed);
- childSetEnabled("Release Keys", controls_grabbed);
-
+ if (button && button->getVisible() != controls_grabbed)
+ {
+ button->setVisible(controls_grabbed);
+ sendChildToFront(button);
+ moveChildToBackOfTabGroup(button);
+ buttons_changed = TRUE;
+ }
BOOL mouselook_grabbed;
mouselook_grabbed = gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_DOWN_INDEX)
|| gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_UP_INDEX);
+ button = LLUICtrlFactory::getButtonByName(this, "Mouselook");
-
- childSetVisible("Mouselook", mouselook_grabbed);
- childSetEnabled("Mouselook", mouselook_grabbed);
+ if (button && button->getVisible() != mouselook_grabbed)
+ {
+ button->setVisible(mouselook_grabbed);
+ sendChildToFront(button);
+ moveChildToBackOfTabGroup(button);
+ buttons_changed = TRUE;
+ }
BOOL sitting = FALSE;
if (gAgent.getAvatarObject())
{
sitting = gAgent.getAvatarObject()->mIsSitting;
- childSetVisible("Stand Up", sitting);
- childSetEnabled("Stand Up", sitting);
-
}
+ button = LLUICtrlFactory::getButtonByName(this, "Stand Up");
- if ( mMusicRemote && gAudiop )
+ if (button && button->getVisible() != sitting)
{
- LLParcel* parcel = gParcelMgr->getAgentParcel();
- if (!parcel
- || parcel->getMusicURL().empty()
- || !gSavedSettings.getBOOL("AudioStreamingMusic"))
- {
- mMusicRemote->setVisible(FALSE);
- mMusicRemote->setEnabled(FALSE);
- }
- else
- {
- mMusicRemote->setVisible(TRUE);
- mMusicRemote->setEnabled(TRUE);
- }
+ button->setVisible(sitting);
+ sendChildToFront(button);
+ moveChildToBackOfTabGroup(button);
+ buttons_changed = TRUE;
}
- // if there is a url and a texture and media is enabled and available and media streaming is on... (phew!)
- if ( mMediaRemote )
- {
- if (LLMediaEngine::getInstance () &&
- LLMediaEngine::getInstance ()->getUrl ().length () &&
- LLMediaEngine::getInstance ()->getImageUUID ().notNull () &&
- LLMediaEngine::getInstance ()->isEnabled () &&
- LLMediaEngine::getInstance ()->isAvailable () &&
- gSavedSettings.getBOOL ( "AudioStreamingVideo" ) )
- {
- // display remote control
- mMediaRemote->setVisible ( TRUE );
- mMediaRemote->setEnabled ( TRUE );
- }
- else
- {
- mMediaRemote->setVisible ( FALSE );
- mMediaRemote->setEnabled ( FALSE );
- }
- }
- if (mVoiceRemote)
- {
- mVoiceRemote->setVisible(LLVoiceClient::voiceEnabled());
- }
-
+ // update "remotes"
+ childSetVisible("voice_remote_container", LLVoiceClient::voiceEnabled());
+ enableMediaButtons();
+
+ moveChildToBackOfTabGroup(mMediaRemote);
+ moveChildToBackOfTabGroup(mVoiceRemote);
+
// turn off the whole bar in mouselook
if (gAgent.cameraMouselook())
{
@@ -407,6 +282,11 @@ void LLOverlayBar::refresh()
{
setVisible(TRUE);
}
+
+ if (buttons_changed)
+ {
+ layoutButtons();
+ }
}
//-----------------------------------------------------------------------
@@ -462,33 +342,25 @@ void LLOverlayBar::mediaPlay(void*)
{
return;
}
- gOverlayBar->mMediaState = PLAYING; // desired state
- LLParcel* parcel = gParcelMgr->getAgentParcel();
- if (parcel)
- {
- LLString path("");
- LLMediaEngine::getInstance()->convertImageAndLoadUrl( true, false, path );
- }
-}
-//static
-void LLOverlayBar::mediaPause(void*)
-{
- if (!gOverlayBar)
+
+ if (gOverlayBar->mMediaState != PLAYING)
{
- return;
+ gOverlayBar->mMediaState = PLAYING; // desired state
+ LLParcel* parcel = gParcelMgr->getAgentParcel();
+ if (parcel)
+ {
+ LLString path("");
+ LLMediaEngine::getInstance()->convertImageAndLoadUrl( true, false, path );
+ }
}
- gOverlayBar->mMediaState = PAUSED; // desired state
- LLMediaEngine::getInstance()->pause();
-}
-//static
-void LLOverlayBar::mediaStop(void*)
-{
- if (!gOverlayBar)
+ else
{
- return;
+ gOverlayBar->mMediaState = PAUSED; // desired state
+ LLMediaEngine::getInstance()->pause();
}
- gOverlayBar->mMediaState = STOPPED; // desired state
- LLMediaEngine::getInstance()->stop();
+
+ //gOverlayBar->mMediaState = STOPPED; // desired state
+ //LLMediaEngine::getInstance()->stop();
}
//static
@@ -498,116 +370,75 @@ void LLOverlayBar::musicPlay(void*)
{
return;
}
- gOverlayBar->mMusicState = PLAYING; // desired state
- if (gAudiop)
+
+ if (gOverlayBar->mMusicState != PLAYING)
{
- LLParcel* parcel = gParcelMgr->getAgentParcel();
- if ( parcel )
+ gOverlayBar->mMusicState = PLAYING; // desired state
+ if (gAudiop)
{
- // this doesn't work properly when crossing parcel boundaries - even when the
- // stream is stopped, it doesn't return the right thing - commenting out for now.
-// if ( gAudiop->isInternetStreamPlaying() == 0 )
+ LLParcel* parcel = gParcelMgr->getAgentParcel();
+ if ( parcel )
{
- gAudiop->startInternetStream(parcel->getMusicURL().c_str());
+ // this doesn't work properly when crossing parcel boundaries - even when the
+ // stream is stopped, it doesn't return the right thing - commenting out for now.
+ // if ( gAudiop->isInternetStreamPlaying() == 0 )
+ {
+ gAudiop->startInternetStream(parcel->getMusicURL().c_str());
+ }
}
}
}
-}
-//static
-void LLOverlayBar::musicPause(void*)
-{
- if (!gOverlayBar)
- {
- return;
- }
- gOverlayBar->mMusicState = PAUSED; // desired state
- if (gAudiop)
- {
- gAudiop->pauseInternetStream(1);
- }
-}
-//static
-void LLOverlayBar::musicStop(void*)
-{
- if (!gOverlayBar)
- {
- return;
- }
- gOverlayBar->mMusicState = STOPPED; // desired state
- if (gAudiop)
+ //else
+ //{
+ // gOverlayBar->mMusicState = PAUSED; // desired state
+ // if (gAudiop)
+ // {
+ // gAudiop->pauseInternetStream(1);
+ // }
+ //}
+ else
{
- gAudiop->stopInternetStream();
+ gOverlayBar->mMusicState = STOPPED; // desired state
+ if (gAudiop)
+ {
+ gAudiop->stopInternetStream();
+ }
}
}
-//static
-void LLOverlayBar::enableMusicButtons(LLPanel* panel)
-{
- BOOL play_enabled = FALSE;
- BOOL play_visible = TRUE;
- BOOL pause_visible = FALSE;
- BOOL stop_enabled = FALSE;
- if ( gAudiop && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingMusic"))
+void LLOverlayBar::enableMediaButtons()
+{
+ if (mMediaRemote)
{
- play_enabled = TRUE;
- S32 is_playing = gAudiop->isInternetStreamPlaying();
- if (is_playing == 1)
+ // Music
+ LLParcel* parcel = gParcelMgr->getAgentParcel();
+ if (parcel
+ && gAudiop
+ && !parcel->getMusicURL().empty()
+ && gSavedSettings.getBOOL("AudioStreamingMusic"))
{
- play_visible = FALSE;
- pause_visible = TRUE;
- stop_enabled = TRUE;
+ mMediaRemote->childSetEnabled("music_play", TRUE);
}
- else if (is_playing == 2)
+ else
{
- play_visible = TRUE;
- pause_visible = FALSE;
- stop_enabled = TRUE;
+ mMediaRemote->childSetEnabled("music_play", FALSE);
}
- }
- panel->childSetEnabled("music_play", play_enabled);
- panel->childSetEnabled("music_pause", play_enabled);
- panel->childSetVisible("music_play", play_visible);
- panel->childSetVisible("music_pause", pause_visible);
- panel->childSetEnabled("music_stop", stop_enabled);
-}
-//static
-void LLOverlayBar::enableMediaButtons(LLPanel* panel)
-{
- // Media
- BOOL play_enabled = FALSE;
- BOOL play_visible = TRUE;
- BOOL pause_visible = FALSE;
- BOOL stop_enabled = FALSE;
-
- if ( LLMediaEngine::getInstance() && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingVideo") )
- {
- play_enabled = TRUE;
- if (LLMediaEngine::getInstance()->getMediaRenderer())
+ // Media
+ // if there is a url and a texture and media is enabled and available and media streaming is on... (phew!)
+ if (LLMediaEngine::getInstance()
+ && LLMediaEngine::getInstance()->getUrl ().length ()
+ && LLMediaEngine::getInstance()->getImageUUID ().notNull ()
+ && LLMediaEngine::getInstance()->isEnabled ()
+ && LLMediaEngine::getInstance()->isAvailable ()
+ && gSavedSettings.getBOOL ( "AudioStreamingVideo" ) )
{
- if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPlaying() ||
- LLMediaEngine::getInstance()->getMediaRenderer()->isLooping() )
- {
- play_visible = FALSE;
- pause_visible = TRUE;
- stop_enabled = TRUE;
- }
- else if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPaused() )
- {
- play_visible = TRUE;
- pause_visible = FALSE;
- stop_enabled = TRUE;
- }
+ mMediaRemote->childSetEnabled("media_play", TRUE);
+ }
+ else
+ {
+ mMediaRemote->childSetEnabled("media_play", FALSE);
}
}
- panel->childSetEnabled("media_play", play_enabled);
- panel->childSetEnabled("media_pause", play_enabled);
- panel->childSetVisible("media_play", play_visible);
- panel->childSetVisible("media_pause", pause_visible);
- panel->childSetEnabled("media_stop", stop_enabled);
}
-void LLOverlayBar::toggleAudioVolumeFloater(void* user_data)
-{
- LLFloaterAudioVolume::toggleInstance(LLSD());
-}
diff --git a/indra/newview/lloverlaybar.h b/indra/newview/lloverlaybar.h
index 229346340a..18ff07e71b 100644
--- a/indra/newview/lloverlaybar.h
+++ b/indra/newview/lloverlaybar.h
@@ -54,7 +54,7 @@ class LLOverlayBar
: public LLPanel
{
public:
- LLOverlayBar(const std::string& name, const LLRect& rect );
+ LLOverlayBar();
~LLOverlayBar();
virtual EWidgetType getWidgetType() const;
@@ -63,6 +63,7 @@ public:
/*virtual*/ void refresh();
/*virtual*/ void draw();
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+ /*virtual*/ BOOL postBuild();
void layoutButtons();
@@ -79,27 +80,16 @@ public:
//static media helper functions
static void mediaPlay(void*);
- static void mediaPause(void*);
- static void mediaStop(void*);
-
static void musicPlay(void*);
- static void musicPause(void*);
- static void musicStop(void*);
- static void toggleAudioVolumeFloater(void*);
-
- static void enableMediaButtons(LLPanel* panel);
- static void enableMusicButtons(LLPanel* panel);
-
protected:
- static void* createMasterRemote(void* userdata);
- static void* createMusicRemote(void* userdata);
static void* createMediaRemote(void* userdata);
static void* createVoiceRemote(void* userdata);
+ static void* createChatBar(void* userdata);
+
+ void enableMediaButtons();
protected:
- LLMediaRemoteCtrl* mMasterRemote;
- LLMediaRemoteCtrl* mMusicRemote;
LLMediaRemoteCtrl* mMediaRemote;
LLVoiceRemoteCtrl* mVoiceRemote;
bool mBuilt; // dialog constructed yet?
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index c090fd9749..46af3ec74f 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -1638,7 +1638,7 @@ void LLPanelAvatar::onClickMute(void *userdata)
if (name_edit)
{
std::string agent_name = name_edit->getText();
- gFloaterMute->show();
+ LLFloaterMute::showInstance();
if (gMuteListp->isMuted(agent_id))
{
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 7163a71bc3..7263b11d96 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -189,14 +189,14 @@ BOOL LLPanelClassified::postBuild()
mNameEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "given_name_editor");
mNameEditor->setMaxTextLength(DB_PARCEL_NAME_LEN);
mNameEditor->setCommitOnFocusLost(TRUE);
- mNameEditor->setFocusReceivedCallback(onFocusReceived);
+ mNameEditor->setFocusReceivedCallback(onFocusReceived, this);
mNameEditor->setCommitCallback(onCommitAny);
mNameEditor->setCallbackUserData(this);
mNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII );
mDescEditor = LLUICtrlFactory::getTextEditorByName(this, "desc_editor");
mDescEditor->setCommitOnFocusLost(TRUE);
- mDescEditor->setFocusReceivedCallback(onFocusReceived);
+ mDescEditor->setFocusReceivedCallback(onFocusReceived, this);
mDescEditor->setCommitCallback(onCommitAny);
mDescEditor->setCallbackUserData(this);
mDescEditor->setTabToNextField(TRUE);
@@ -929,10 +929,10 @@ void LLPanelClassified::onCommitAny(LLUICtrl* ctrl, void* data)
}
// static
-void LLPanelClassified::onFocusReceived(LLUICtrl* ctrl, void* data)
+void LLPanelClassified::onFocusReceived(LLFocusableElement* ctrl, void* data)
{
// allow the data to be saved
- onCommitAny(ctrl, data);
+ onCommitAny((LLUICtrl*)ctrl, data);
}
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index a2bb29b224..8884d1a25e 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -111,7 +111,7 @@ protected:
static void onClickProfile(void* data);
static void onClickSet(void* data);
- static void onFocusReceived(LLUICtrl* ctrl, void* data);
+ static void onFocusReceived(LLFocusableElement* ctrl, void* data);
static void onCommitAny(LLUICtrl* ctrl, void* data);
void sendClassifiedClickMessage(const char* type);
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 8dbe72fdfe..8ce2ae5d9c 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -870,7 +870,7 @@ void LLPanelFace::onClickApply(void* userdata)
{
LLPanelFace* self = (LLPanelFace*) userdata;
- gFocusMgr.setKeyboardFocus( NULL, NULL );
+ gFocusMgr.setKeyboardFocus( NULL );
//F32 repeats_per_meter = self->mCtrlRepeatsPerMeter->get();
F32 repeats_per_meter = (F32)self->childGetValue( "rptctrl" ).asReal();//self->mCtrlRepeatsPerMeter->get();
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 3ad65b5e68..31688256f5 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -114,8 +114,8 @@ BOOL LLPanelGroupGeneral::postBuild()
if(mEditCharter)
{
mEditCharter->setCommitCallback(onCommitAny);
- mEditCharter->setFocusReceivedCallback(onCommitAny);
- mEditCharter->setFocusChangedCallback(onCommitAny);
+ mEditCharter->setFocusReceivedCallback(onFocusEdit, this);
+ mEditCharter->setFocusChangedCallback(onFocusEdit, this);
mEditCharter->setCallbackUserData(this);
}
@@ -259,6 +259,14 @@ BOOL LLPanelGroupGeneral::postBuild()
}
// static
+void LLPanelGroupGeneral::onFocusEdit(LLFocusableElement* ctrl, void* data)
+{
+ LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data;
+ self->mChanged = TRUE;
+ self->notifyObservers();
+}
+
+// static
void LLPanelGroupGeneral::onCommitAny(LLUICtrl* ctrl, void* data)
{
LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data;
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index e7a27b6c0b..b17a66d0a3 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -66,6 +66,7 @@ public:
virtual void draw();
private:
+ static void onFocusEdit(LLFocusableElement* ctrl, void* data);
static void onCommitAny(LLUICtrl* ctrl, void* data);
static void onCommitUserOnly(LLUICtrl* ctrl, void* data);
static void onCommitTitle(LLUICtrl* ctrl, void* data);
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 0152990798..dbe24d40e0 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -238,7 +238,7 @@ void LLPanelGroupLandMoney::impl::onMapButton()
F32 global_x = 0.f;
F32 global_y = 0.f;
- sscanf(cellp->getText().c_str(), "%f %f", &global_x, &global_y);
+ sscanf(cellp->getValue().asString().c_str(), "%f %f", &global_x, &global_y);
// Hack: Use the agent's z-height
F64 global_z = gAgent.getPositionGlobal().mdV[VZ];
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index ce824cbb6d..a67692afa6 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -790,7 +790,6 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
{
row["columns"][column_index]["column"] = "checkbox";
row["columns"][column_index]["type"] = "checkbox";
- row["columns"][column_index]["value"] = (*ra_it)->mName;
check_box_index = column_index;
++column_index;
}
@@ -1058,7 +1057,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
if (mi == gdatap->mMembers.end()) continue;
LLGroupMemberData* member_data = (*mi).second;
// Is the member an owner?
- if ( member_data->isInRole(gdatap->mOwnerRole) )
+ if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
{
// Can't remove other owners.
cb_enable = FALSE;
@@ -1870,7 +1869,7 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
mRoleDescription->setCommitOnFocusLost(TRUE);
mRoleDescription->setCallbackUserData(this);
mRoleDescription->setCommitCallback(onDescriptionCommit);
- mRoleDescription->setFocusReceivedCallback(onDescriptionCommit);
+ mRoleDescription->setFocusReceivedCallback(onDescriptionFocus, this);
setFooterEnabled(FALSE);
@@ -2329,6 +2328,16 @@ void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_dat
}
// static
+void LLPanelGroupRolesSubTab::onDescriptionFocus(LLFocusableElement* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self) return;
+
+ self->mHasRoleChange = TRUE;
+ self->notifyObservers();
+}
+
+// static
void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data)
{
LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index b0b635eb57..13d64d4edb 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -256,6 +256,7 @@ public:
static void onPropertiesKey(LLLineEditor*, void*);
static void onDescriptionCommit(LLUICtrl*, void*);
+ static void onDescriptionFocus(LLFocusableElement*, void*);
static void onMemberVisibilityChange(LLUICtrl*, void*);
void handleMemberVisibilityChange(bool value);
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index bc297354f7..74936dce0c 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -496,7 +496,7 @@ void LLPanelLogin::show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data)
{
- new LLPanelLogin(rect, show_server, callback, callback_data);
+ new LLPanelLogin(rect, show_server, callback, callback_data);
LLWebBrowserCtrl* web_browser = LLUICtrlFactory::getWebBrowserCtrlByName(sInstance, "login_html");
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index c3d949d3df..2463e62d7f 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -350,7 +350,7 @@ void LLPanelObject::getState( )
//forfeit focus
if (gFocusMgr.childHasKeyboardFocus(this))
{
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
// Disable all text input fields
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index c288c6aaed..e7b5e79377 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -171,7 +171,7 @@ void LLPanelVolume::getState( )
//forfeit focus
if (gFocusMgr.childHasKeyboardFocus(this))
{
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
// Disable all text input fields
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 9fa364a339..61bda9dfc0 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1607,7 +1607,7 @@ void LLPreviewGesture::onClickAdd(void* data)
if (!library_item) return;
const LLScrollListCell* library_cell = library_item->getColumn(0);
- const std::string& library_text = library_cell->getText();
+ const std::string& library_text = library_cell->getValue().asString();
self->addStep(library_text);
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 6c377009f2..06286927d4 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -960,7 +960,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
S32 row = 0;
S32 column = 0;
const LLScrollListCell* cell = item->getColumn(0);
- LLString line(cell->getText());
+ LLString line(cell->getValue().asString());
line.erase(0, 1);
LLString::replaceChar(line, ',',' ');
LLString::replaceChar(line, ')',' ');
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index fae04871be..b92a6d58c8 100644
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -106,7 +106,7 @@ void LLPreviewSound::auditionSound( void *userdata )
if(item && gAudiop)
{
LLVector3d lpos_global = gAgent.getPositionGlobal();
- F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX");
gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), volume, lpos_global);
}
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index f12f5763ef..b0b9fd33d1 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2304,7 +2304,7 @@ BOOL idle_startup()
audio_update_volume();
// reset keyboard focus to sane state of pointing at world
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
#if 0 // sjb: enable for auto-enabling timer display
gDebugView->mFastTimerView->setVisible(TRUE);
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 4d49d33184..8c4fc833db 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -100,7 +100,6 @@ const LLColor4 SIM_WARN_COLOR(1.f, 1.f, 0.f, 1.f);
const LLColor4 SIM_FULL_COLOR(1.f, 0.f, 0.f, 1.f);
const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons should flash after a change.
const F32 ICON_FLASH_FREQUENCY = 2.f;
-const S32 GRAPHIC_FUDGE = 4;
const S32 TEXT_HEIGHT = 18;
static void onClickParcelInfo(void*);
@@ -153,13 +152,13 @@ LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect)
childSetAction("scriptout", onClickScriptDebug, this);
childSetAction("health", onClickHealth, this);
- childSetAction("fly", onClickFly, this);
+ childSetAction("no_fly", onClickFly, this);
childSetAction("buyland", onClickBuyLand, this );
childSetAction("buycurrency", onClickBuyCurrency, this );
- childSetAction("build", onClickBuild, this );
- childSetAction("scripts", onClickScripts, this );
+ childSetAction("no_build", onClickBuild, this );
+ childSetAction("no_scripts", onClickScripts, this );
childSetAction("restrictpush", onClickPush, this );
- childSetAction("status_voice", onClickVoice, this );
+ childSetAction("status_no_voice", onClickVoice, this );
childSetCommitCallback("search_editor", onCommitSearch, this);
childSetAction("search_btn", onClickSearch, this);
@@ -304,7 +303,7 @@ void LLStatusBar::refresh()
// Health
childGetRect( "health", buttonRect );
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
childSetRect("health", r);
x += buttonRect.getWidth();
@@ -324,27 +323,32 @@ void LLStatusBar::refresh()
(parcel && !parcel->getAllowFly()) )
{
// No Fly Zone
- childGetRect( "fly", buttonRect );
- childSetVisible( "fly", true );
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "fly", r );
+ childGetRect( "no_fly", buttonRect );
+ childSetVisible( "no_fly", true );
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
+ childSetRect( "no_fly", r );
x += buttonRect.getWidth();
}
else
{
- childSetVisible("fly", false);
+ // Fly Zone
+ childSetVisible("no_fly", false);
}
BOOL no_build = parcel && !parcel->getAllowModify();
- childSetVisible("build", no_build);
if (no_build)
{
- childGetRect( "build", buttonRect );
+ childSetVisible("no_build", TRUE);
+ childGetRect( "no_build", buttonRect );
// No Build Zone
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "build", r );
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
+ childSetRect( "no_build", r );
x += buttonRect.getWidth();
}
+ else
+ {
+ childSetVisible("no_build", FALSE);
+ }
BOOL no_scripts = FALSE;
if((region
@@ -354,35 +358,56 @@ void LLStatusBar::refresh()
{
no_scripts = TRUE;
}
- childSetVisible("scripts", no_scripts);
if (no_scripts)
{
// No scripts
- childGetRect( "scripts", buttonRect );
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "scripts", r );
+ childSetVisible("no_scripts", TRUE);
+ childGetRect( "no_scripts", buttonRect );
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
+ childSetRect( "no_scripts", r );
x += buttonRect.getWidth();
}
+ else
+ {
+ // Yes scripts
+ childSetVisible("no_scripts", FALSE);
+ }
BOOL no_region_push = (region && region->getRestrictPushObject());
BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject());
- childSetVisible("restrictpush", no_push);
if (no_push)
{
+ childSetVisible("restrictpush", TRUE);
childGetRect( "restrictpush", buttonRect );
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
childSetRect( "restrictpush", r );
x += buttonRect.getWidth();
}
+ else
+ {
+ childSetVisible("restrictpush", FALSE);
+ }
+ BOOL voice_enabled = gVoiceClient->voiceEnabled();
BOOL have_voice = parcel && parcel->getVoiceEnabled();
- childSetVisible("status_voice", have_voice);
- if (have_voice)
+ if (!voice_enabled)
{
- childGetRect( "status_voice", buttonRect );
- r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "status_voice", r );
- x += buttonRect.getWidth();
+ childSetVisible("status_no_voice", FALSE);
+ }
+ else
+ {
+ if (have_voice)
+ {
+ childSetVisible("status_no_voice", FALSE);
+ }
+ else if (!have_voice)
+ {
+ childSetVisible("status_no_voice", TRUE);
+ childGetRect( "status_no_voice", buttonRect );
+ r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
+ childSetRect( "status_no_voice", r );
+ x += buttonRect.getWidth();
+ }
}
BOOL canBuyLand = parcel
@@ -512,7 +537,7 @@ void LLStatusBar::refresh()
mTextParcelName->setText(location_name);
// Adjust region name and parcel name
- x += 4;
+ x += 8;
const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5);
r.set(x+4, mRect.getHeight() - 2, PARCEL_RIGHT, 0);
@@ -672,8 +697,7 @@ static void onClickPush(void* )
static void onClickVoice(void* )
{
- LLNotifyBox::showXml("VoiceAvailablity");
- //LLFirstUse::useVoice();
+ LLNotifyBox::showXml("NoVoice");
}
static void onClickBuild(void*)
@@ -708,7 +732,7 @@ static void onClickBuyLand(void*)
void LLStatusBar::setupDate()
{
// fill the day array with what's in the xui
- LLString day_list = childGetText("StatBarDaysOfWeek");
+ LLString day_list = getFormattedUIString("StatBarDaysOfWeek");
size_t length = day_list.size();
// quick input check
@@ -732,7 +756,7 @@ void LLStatusBar::setupDate()
}
// fill the day array with what's in the xui
- LLString month_list = childGetText( "StatBarMonthsOfYear" );
+ LLString month_list = getFormattedUIString( "StatBarMonthsOfYear" );
length = month_list.size();
// quick input check
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 06a4ea097f..465a40c1ef 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -373,7 +373,6 @@ public:
{
S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f);
setRect(LLRect(0,0,100,line_height * 4));
- updateRect();
}
virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEX_MEM_BAR; };
diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
index e7a5445ef6..c80edd0eab 100644
--- a/indra/newview/lltoolbar.cpp
+++ b/indra/newview/lltoolbar.cpp
@@ -60,6 +60,11 @@
#include "llvieweruictrlfactory.h"
#include "llviewerwindow.h"
#include "lltoolgrab.h"
+#include "llcombobox.h"
+#include "llfloaterchat.h"
+#include "llfloatermute.h"
+#include "llimpanel.h"
+#include "llscrolllistctrl.h"
#if LL_DARWIN
@@ -100,24 +105,20 @@ F32 LLToolBar::sInventoryAutoOpenTime = 1.f;
// Functions
//
-LLToolBar::LLToolBar(const std::string& name, const LLRect& r)
-: LLPanel(name, r, BORDER_NO)
+LLToolBar::LLToolBar()
+: LLPanel()
#if LL_DARWIN
, mResizeHandle(NULL)
#endif // LL_DARWIN
{
setIsChrome(TRUE);
- setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM );
-
- gUICtrlFactory->buildPanel(this, "panel_toolbar.xml");
- mIsFocusRoot = TRUE;
-
+ setFocusRoot(TRUE);
}
BOOL LLToolBar::postBuild()
{
- childSetAction("communicate_btn", onClickCommunicate, this);
+ childSetCommitCallback("communicate_btn", onClickCommunicate, this);
childSetControlName("communicate_btn", "ShowCommunicate");
childSetAction("chat_btn", onClickChat, this);
@@ -270,29 +271,47 @@ void LLToolBar::layoutButtons()
}
#endif // LL_DARWIN
+ LLButton* chat_button = LLUICtrlFactory::getButtonByName(this, "chat_btn");
+ if (chat_button)
+ {
+ width -= chat_button->getRect().getWidth() + pad;
+ }
+
// We actually want to extend "pad" pixels off the right edge of the
// screen, such that the rightmost button is aligned.
- F32 segment_width = (F32)(width + pad) / (F32)count;
- S32 btn_width = lltrunc(segment_width - pad);
+ S32 segment_width = llround((F32)(width) / ((F32)count - 1.f));
+ S32 btn_width = segment_width - pad;
// Evenly space all views
S32 height = -1;
S32 i = count - 1;
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ S32 x = pad;
+ for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin();
+ child_iter != getChildList()->rend(); ++child_iter)
{
LLView *btn_view = *child_iter;
- if(btn_view->getWidgetType() == WIDGET_TYPE_BUTTON)
+ if(btn_view->getWidgetType() == WIDGET_TYPE_BUTTON || btn_view->getWidgetType() == WIDGET_TYPE_FLYOUT_BUTTON)
{
if (height < 0)
{
height = btn_view->getRect().getHeight();
}
- S32 x = llround(i*segment_width);
- S32 y = 0;
- LLRect r;
- r.setOriginAndSize(x, y, btn_width, height);
- btn_view->setRect(r);
+
+ LLRect r;
+
+ if (btn_view->getName() == "chat_btn")
+ {
+ r.setOriginAndSize(x, 0, btn_view->getRect().getWidth(), height);
+ x += btn_view->getRect().getWidth() + pad;
+ }
+ else
+ {
+ r.setOriginAndSize(x, 0, btn_width, height);
+ x += segment_width;
+ }
+
+ btn_view->setOrigin(r.mLeft, r.mBottom);
+ btn_view->reshape(r.getWidth(), r.getHeight());
i--;
}
}
@@ -321,6 +340,7 @@ void LLToolBar::refresh()
childSetEnabled("build_btn", gParcelMgr->agentCanBuild() );
+
// Check to see if we're in build mode
BOOL build_mode = gToolMgr->inEdit();
// And not just clicking on a scripted object
@@ -329,13 +349,135 @@ void LLToolBar::refresh()
build_mode = FALSE;
}
gSavedSettings.setBOOL("BuildBtnState", build_mode);
+
+ updateCommunicateList();
+}
+
+void LLToolBar::updateCommunicateList()
+{
+ LLFlyoutButton* communicate_button = (LLFlyoutButton*)getChildByName("communicate_btn", TRUE);
+ if (communicate_button)
+ {
+ LLSD selected = communicate_button->getValue();
+
+ communicate_button->removeall();
+
+ LLFloater* frontmost_floater = LLFloaterChatterBox::getInstance()->getActiveFloater();
+ LLScrollListItem* itemp = NULL;
+
+ itemp = communicate_button->add(LLFloaterMyFriends::getInstance()->getShortTitle(), LLSD("contacts"), ADD_TOP);
+ if (LLFloaterMyFriends::getInstance() == frontmost_floater)
+ {
+ ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
+ // make sure current tab is selected in list
+ if (selected.isUndefined())
+ {
+ selected = itemp->getValue();
+ }
+ }
+ itemp = communicate_button->add(LLFloaterChat::getInstance()->getShortTitle(), LLSD("local chat"), ADD_TOP);
+ if (LLFloaterChat::getInstance() == frontmost_floater)
+ {
+ ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
+ if (selected.isUndefined())
+ {
+ selected = itemp->getValue();
+ }
+ }
+ communicate_button->addSeparator(ADD_TOP);
+ communicate_button->add(getUIString("Redock Windows"), LLSD("redock"), ADD_TOP);
+ communicate_button->addSeparator(ADD_TOP);
+ communicate_button->add(LLFloaterMute::getInstance()->getShortTitle(), LLSD("mute list"), ADD_TOP);
+
+ std::set<LLViewHandle>::const_iterator floater_handle_it;
+
+ if (gIMMgr->getIMFloaterHandles().size() > 0)
+ {
+ communicate_button->addSeparator(ADD_TOP);
+ }
+
+ for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
+ {
+ LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)LLFloater::getFloaterByHandle(*floater_handle_it);
+ if (im_floaterp)
+ {
+ LLString floater_title = im_floaterp->getNumUnreadMessages() > 0 ? "*" : "";
+ floater_title.append(im_floaterp->getShortTitle());
+ itemp = communicate_button->add(floater_title, im_floaterp->getSessionID(), ADD_TOP);
+ if (im_floaterp == frontmost_floater)
+ {
+ ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
+ if (selected.isUndefined())
+ {
+ selected = itemp->getValue();
+ }
+ }
+ }
+ }
+
+ communicate_button->setToggleState(gSavedSettings.getBOOL("ShowCommunicate"));
+ communicate_button->setValue(selected);
+ }
}
// static
-void LLToolBar::onClickCommunicate(void* user_data)
+void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, void* user_data)
{
- LLFloaterChatterBox::toggleInstance(LLSD());
+ LLToolBar* toolbar = (LLToolBar*)user_data;
+ LLFlyoutButton* communicate_button = (LLFlyoutButton*)toolbar->getChildByName("communicate_btn", TRUE);
+
+ LLSD selected_option = communicate_button->getValue();
+
+ if (selected_option.asString() == "contacts")
+ {
+ LLFloaterMyFriends::showInstance();
+ }
+ else if (selected_option.asString() == "local chat")
+ {
+ LLFloaterChat::showInstance();
+ }
+ else if (selected_option.asString() == "redock")
+ {
+ LLFloaterChatterBox::getInstance()->addFloater(LLFloaterMyFriends::getInstance(), FALSE);
+ LLFloaterChatterBox::getInstance()->addFloater(LLFloaterChat::getInstance(), FALSE);
+ LLUUID session_to_show;
+
+ std::set<LLViewHandle>::const_iterator floater_handle_it;
+ for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
+ {
+ LLFloater* im_floaterp = LLFloater::getFloaterByHandle(*floater_handle_it);
+ if (im_floaterp)
+ {
+ if (im_floaterp->isFrontmost())
+ {
+ session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID();
+ }
+ LLFloaterChatterBox::getInstance()->addFloater(im_floaterp, FALSE);
+ }
+ }
+
+ LLFloaterChatterBox::showInstance(session_to_show);
+ }
+ else if (selected_option.asString() == "mute list")
+ {
+ LLFloaterMute::showInstance();
+ }
+ else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle
+ {
+ if (LLFloaterChatterBox::getInstance()->getFloaterCount() == 0)
+ {
+ LLFloaterMyFriends::toggleInstance();
+ }
+ else
+ {
+ LLFloaterChatterBox::toggleInstance();
+ }
+ }
+ else // otherwise selection_option is a specific IM session id
+ {
+ LLFloaterChatterBox::showInstance(selected_option);
+ }
}
diff --git a/indra/newview/lltoolbar.h b/indra/newview/lltoolbar.h
index c43c80b095..85adba8c55 100644
--- a/indra/newview/lltoolbar.h
+++ b/indra/newview/lltoolbar.h
@@ -47,7 +47,7 @@ class LLToolBar
: public LLPanel
{
public:
- LLToolBar(const std::string& name, const LLRect& rect );
+ LLToolBar();
~LLToolBar();
/*virtual*/ BOOL postBuild();
@@ -70,7 +70,7 @@ public:
void refresh();
// callbacks
- static void onClickCommunicate(void*);
+ static void onClickCommunicate(LLUICtrl*, void*);
static void onClickChat(void* data);
static void onClickAppearance(void* data);
static void onClickClothing(void* data);
@@ -86,8 +86,13 @@ public:
static F32 sInventoryAutoOpenTime;
private:
+ void updateCommunicateList();
+
+
+private:
BOOL mInventoryAutoOpen;
LLFrameTimer mInventoryAutoOpenTimer;
+ S32 mNumUnreadIMs;
#if LL_DARWIN
LLFakeResizeHandle *mResizeHandle;
#endif // LL_DARWIN
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index d26bdab921..a27053faa3 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -216,7 +216,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
// Play creation sound
if (gAudiop)
{
- F32 volume = gSavedSettings.getF32("AudioLevelUI");
+ F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume);
}
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index ac90a06a57..8e742bd655 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -122,8 +122,10 @@ void audio_update_volume(bool force_update)
if (gAudiop)
{
F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
+ BOOL music_muted = gSavedSettings.getBOOL("MuteMusic");
music_volume = mute_volume * master_volume * (music_volume*music_volume);
- gAudiop->setInternetStreamGain ( music_volume );
+ gAudiop->setInternetStreamGain ( music_muted ? 0.f : music_volume );
+
}
// Streaming Media
@@ -131,7 +133,8 @@ void audio_update_volume(bool force_update)
{
F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
media_volume = mute_volume * master_volume * (media_volume*media_volume);
- LLMediaEngine::getInstance()->setVolume(media_volume);
+ BOOL media_muted = gSavedSettings.getBOOL("MuteMedia");
+ LLMediaEngine::getInstance()->setVolume(media_muted ? 0.f : media_volume);
}
// Voice
@@ -139,8 +142,9 @@ void audio_update_volume(bool force_update)
{
F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
voice_volume = mute_volume * master_volume * voice_volume;
- gVoiceClient->setVoiceVolume(voice_volume);
- gVoiceClient->setMicGain(gSavedSettings.getF32("AudioLevelMic"));
+ BOOL voice_mute = gSavedSettings.getBOOL("MuteVoice");
+ gVoiceClient->setVoiceVolume(voice_mute ? 0.f : voice_volume);
+ gVoiceClient->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
{
@@ -206,7 +210,7 @@ void audio_update_wind(bool force_update)
// don't use the setter setMaxWindGain() because we don't
// want to screw up the fade-in on startup by setting actual source gain
// outside the fade-in.
- gAudiop->mMaxWindGain = gSavedSettings.getF32("AudioLevelAmbient");
+ gAudiop->mMaxWindGain = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient");
last_camera_water_height = camera_water_height;
gAudiop->updateWind(gRelativeWindVec, camera_water_height);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2fccdcd153..fdc0047f95 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2103,7 +2103,7 @@ class LLObjectMute : public view_listener_t
else
{
gMuteListp->add(mute);
- gFloaterMute->show();
+ LLFloaterMute::showInstance();
}
return true;
@@ -5309,7 +5309,7 @@ class LLShowFloater : public view_listener_t
}
else if (floater_name == "mute list")
{
- LLFloaterMute::toggle(NULL);
+ LLFloaterMute::toggleInstance();
}
else if (floater_name == "camera controls")
{
@@ -5355,7 +5355,7 @@ class LLShowFloater : public view_listener_t
}
else if (floater_name == "about region")
{
- LLFloaterRegionInfo::show((void *)NULL);
+ LLFloaterRegionInfo::showInstance();
}
else if (floater_name == "grid options")
{
@@ -5447,7 +5447,7 @@ class LLFloaterVisible : public view_listener_t
}
else if (floater_name == "mute list")
{
- new_value = LLFloaterMute::visible(NULL);
+ new_value = LLFloaterMute::instanceVisible();
}
else if (floater_name == "camera controls")
{
@@ -6963,13 +6963,12 @@ void handle_grab_texture(void* data)
if(view)
{
LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback();
view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO);
view->getPanel()->openSelected();
//LLInventoryView::dumpSelectionInformation((void*)view);
// restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus_ctrl, callback);
+ gFocusMgr.setKeyboardFocus(focus_ctrl);
}
}
else
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ebb0da016f..8a4cd16c08 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -888,10 +888,8 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name)
//highlight item
LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- LLFocusMgr::FocusLostCallback callback;
- callback = gFocusMgr.getFocusCallback();
view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO);
- gFocusMgr.setKeyboardFocus(focus_ctrl, callback);
+ gFocusMgr.setKeyboardFocus(focus_ctrl);
}
}
@@ -920,7 +918,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
LLMute mute(blocked_id, from_name, type);
if (gMuteListp->add(mute))
{
- gFloaterMute->show();
+ LLFloaterMute::showInstance();
gFloaterMute->selectMute(blocked_id);
}
@@ -2192,9 +2190,13 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
BOOL is_linden = FALSE;
if (gMuteListp)
{
- is_muted = gMuteListp->isMuted(from_id, from_name, LLMute::flagTextChat)
- || gMuteListp->isMuted(owner_id, LLMute::flagTextChat);
- is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && gMuteListp->isLinden(from_name);
+ is_muted = gMuteListp->isMuted(
+ from_id,
+ from_name,
+ LLMute::flagTextChat)
+ || gMuteListp->isMuted(owner_id, LLMute::flagTextChat);
+ is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
+ gMuteListp->isLinden(from_name);
}
BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible);
@@ -2235,7 +2237,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
BOOL visible_in_chat_bubble = FALSE;
std::string verb;
- color.setVec(1,1,1,1);
+ color.setVec(1.f,1.f,1.f,1.f);
msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, DB_CHAT_MSG_BUF_SIZE, mesg);
BOOL ircstyle = FALSE;
@@ -3332,7 +3334,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
return;
}
- F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (gain * gSavedSettings.getF32("AudioLevelSFX"));
gAudiop->triggerSound(sound_id, owner_id, volume, pos_global);
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 4c6f27944f..9243263794 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2717,7 +2717,7 @@ BOOL LLViewerObject::updateLOD()
// Update volume of looping sounds
if (mAudioSourcep && mAudioSourcep->isLoop())
{
- F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (mAudioGain * gSavedSettings.getF32("AudioLevelSFX"));
mAudioSourcep->setGain(volume);
}
return FALSE;
@@ -4228,7 +4228,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
{
BOOL queue = flags & LL_SOUND_FLAG_QUEUE;
mAudioGain = gain;
- F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gain * gSavedSettings.getF32("AudioLevelSFX");
mAudioSourcep->setGain(volume);
mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP);
mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER);
@@ -4267,7 +4267,7 @@ void LLViewerObject::adjustAudioGain(const F32 gain)
if (mAudioSourcep)
{
mAudioGain = gain;
- F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : mAudioGain * gSavedSettings.getF32("AudioLevelSFX");
mAudioSourcep->setGain(volume);
}
}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index b0d1d3daca..0ffa37525f 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -266,23 +266,6 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
*dwell_out = dwell;
}
-void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean)
-{
- if (mSelected && mCurrentParcel)
- {
- sw_max = mCurrentParcel->getSimWideMaxPrimCapacity();
- sw_total = mCurrentParcel->getSimWidePrimCount();
- max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus());
- total = mCurrentParcel->getPrimCount();
- owner = mCurrentParcel->getOwnerPrimCount();
- group = mCurrentParcel->getGroupPrimCount();
- other = mCurrentParcel->getOtherPrimCount();
- selected = mCurrentParcel->getSelectedPrimCount();
- parcel_object_bonus = mCurrentParcel->getParcelPrimBonus();
- other_clean = mCurrentParcel->getCleanOtherTime();
- }
-}
-
S32 LLViewerParcelMgr::getSelectedArea() const
{
S32 rv = 0;
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 2dd4f28169..640c8c5c57 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -134,8 +134,6 @@ public:
void getDisplayInfo(S32* area, S32* claim, S32* rent, BOOL* for_sale, F32* dwell);
- void getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean);
-
// Returns selected area
S32 getSelectedArea() const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ad4b6fd616..6001cd3e58 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -366,6 +366,11 @@ F32 LLViewerRegion::getWaterHeight() const
return mLandp->getWaterHeight();
}
+BOOL LLViewerRegion::isVoiceEnabled() const
+{
+ return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE);
+}
+
void LLViewerRegion::setRegionFlags(U32 flags)
{
mRegionFlags = flags;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a0953e561e..e42c0015df 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -109,6 +109,8 @@ public:
void setWaterHeight(F32 water_level);
F32 getWaterHeight() const;
+ BOOL isVoiceEnabled() const;
+
void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; }
F32 getBillableFactor() const { return mBillableFactor; }
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 81de1eb9a8..18f07efb44 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -605,54 +605,50 @@ void LLViewerTextEditor::makePristine()
BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
{
- if (pointInView(x, y) && getVisible())
+ for (child_list_const_iter_t child_iter = getChildList()->begin();
+ child_iter != getChildList()->end(); ++child_iter)
{
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ LLView *viewp = *child_iter;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
{
- LLView *viewp = *child_iter;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- return TRUE;
- }
+ return TRUE;
}
+ }
+
+ if( mSegments.empty() )
+ {
+ return TRUE;
+ }
- if( mSegments.empty() )
+ LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
+ if( cur_segment )
+ {
+ BOOL has_tool_tip = FALSE;
+ if( cur_segment->getStyle().getIsEmbeddedItem() )
{
- return TRUE;
+ LLWString wtip;
+ has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip);
+ msg = wstring_to_utf8str(wtip);
}
-
- LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
+ else
{
- BOOL has_tool_tip = FALSE;
- if( cur_segment->getStyle().getIsEmbeddedItem() )
- {
- LLWString wtip;
- has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip);
- msg = wstring_to_utf8str(wtip);
- }
- else
- {
- has_tool_tip = cur_segment->getToolTip( msg );
- }
- if( has_tool_tip )
- {
- // Just use a slop area around the cursor
- // Convert rect local to screen coordinates
- S32 SLOP = 8;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
- }
+ has_tool_tip = cur_segment->getToolTip( msg );
+ }
+ if( has_tool_tip )
+ {
+ // Just use a slop area around the cursor
+ // Convert rect local to screen coordinates
+ S32 SLOP = 8;
+ localPointToScreen(
+ x - SLOP, y - SLOP,
+ &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
+ sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
+ sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
}
- return TRUE;
}
- return FALSE;
+ return TRUE;
}
BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -759,9 +755,9 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
handled = TRUE;
}
- if (mTakesFocus)
+ if (hasTabStop())
{
- setFocus( TRUE );
+ setFocus(TRUE);
handled = TRUE;
}
@@ -1016,11 +1012,7 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
}
}
- if (mTakesFocus)
- {
- setFocus( TRUE );
- }
-
+
setCursorAtLocalPos( x, y, FALSE );
deselect();
@@ -1390,7 +1382,7 @@ void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item )
const F32 SOUND_GAIN = 1.0f;
if(gAudiop)
{
- F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"));
gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global);
}
showCopyToInvDialog( item );
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a3611b2272..4c96083337 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -266,6 +266,8 @@ const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1;
const F32 MIN_DISPLAY_SCALE = 0.85f;
+const S32 CONSOLE_BOTTOM_PAD = 20;
+
#ifdef SABINRIG
/// ALL RIG STUFF
bool rigControl = false;
@@ -663,18 +665,17 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
// Topmost view gets a chance before the hierarchy
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- BOOL mouse_over_top_ctrl = FALSE;
if (top_ctrl)
{
S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
if (top_ctrl->pointInView(local_x, local_y))
{
- mouse_over_top_ctrl = TRUE;
- if(top_ctrl->handleMouseDown(local_x, local_y, mask))
- {
- return TRUE;
- }
+ return top_ctrl->handleMouseDown(local_x, local_y, mask);
+ }
+ else
+ {
+ setTopCtrl(NULL);
}
}
@@ -686,11 +687,6 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl;
LLView::sMouseHandlerMessage = "";
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
return TRUE;
}
else if (LLView::sDebugMouseHandling)
@@ -698,12 +694,6 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
llinfos << "Left Mouse Down not handled by view" << llendl;
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
-
if (gDisconnected)
{
return FALSE;
@@ -716,7 +706,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
// This is necessary to force clicks in the world to cause edit
// boxes that might have keyboard focus to relinquish it, and hence
// cause a commit to update their value. JC
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
return TRUE;
}
}
@@ -760,18 +750,17 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
// Check for hit on UI.
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- BOOL mouse_over_top_ctrl = FALSE;
if (top_ctrl)
{
S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
if (top_ctrl->pointInView(local_x, local_y))
{
- mouse_over_top_ctrl = TRUE;
- if(top_ctrl->handleDoubleClick(local_x, local_y, mask))
- {
- return TRUE;
- }
+ return top_ctrl->handleDoubleClick(local_x, local_y, mask);
+ }
+ else
+ {
+ setTopCtrl(NULL);
}
}
@@ -782,11 +771,6 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl;
LLView::sMouseHandlerMessage = "";
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
return TRUE;
}
else if (LLView::sDebugMouseHandling)
@@ -794,12 +778,6 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
llinfos << "Left Mouse Down not handled by view" << llendl;
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
-
// Why is this here? JC 9/3/2002
if (gNoRender)
{
@@ -970,18 +948,17 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK
}
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- BOOL mouse_over_top_ctrl = FALSE;
if (top_ctrl)
{
S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
if (top_ctrl->pointInView(local_x, local_y))
{
- mouse_over_top_ctrl = TRUE;
- if(top_ctrl->handleRightMouseDown(local_x, local_y, mask))
- {
- return TRUE;
- }
+ return top_ctrl->handleRightMouseDown(local_x, local_y, mask);
+ }
+ else
+ {
+ setTopCtrl(NULL);
}
}
@@ -992,11 +969,6 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK
llinfos << "Right Mouse Down" << LLView::sMouseHandlerMessage << llendl;
LLView::sMouseHandlerMessage = "";
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
return TRUE;
}
else if (LLView::sDebugMouseHandling)
@@ -1004,12 +976,6 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK
llinfos << "Right Mouse Down not handled by view" << llendl;
}
- if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl)
- {
- // always defocus top view if we click off of it
- top_ctrl->setFocus(FALSE);
- }
-
if (gToolMgr)
{
if(gToolMgr->getCurrentTool()->handleRightMouseDown( x, y, mask ) )
@@ -1017,7 +983,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK
// This is necessary to force clicks in the world to cause edit
// boxes that might have keyboard focus to relinquish it, and hence
// cause a commit to update their value. JC
- gFocusMgr.setKeyboardFocus(NULL, NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
return TRUE;
}
}
@@ -1266,7 +1232,7 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
// JC - Leave keyboard focus, so if you're popping in and out editing
// a script, you don't have to click in the editor again and again.
- // gFocusMgr.setKeyboardFocus( NULL, NULL );
+ // gFocusMgr.setKeyboardFocus( NULL );
gShowTextEditCursor = FALSE;
// If losing focus while keys are down, reset them.
@@ -1746,14 +1712,6 @@ void LLViewerWindow::initBase()
gDebugView->setVisible(TRUE);
mRootView->addChild(gDebugView);
- // HUD elements just below floaters
- LLRect hud_rect = full_window;
- hud_rect.mTop -= 24;
- hud_rect.mBottom += STATUS_BAR_HEIGHT;
- gHUDView = new LLHUDView("hud_view", hud_rect);
- gHUDView->setFollowsAll();
- mRootView->addChild(gHUDView);
-
// Add floater view at the end so it will be on top, and give it tab priority over others
mRootView->addChild(gFloaterView, -1);
mRootView->addChild(gSnapshotFloaterView);
@@ -1871,27 +1829,10 @@ void LLViewerWindow::initWorldUI()
S32 width = mRootView->getRect().getWidth();
LLRect full_window(0, height, width, 0);
- if ( gToolBar == NULL ) // Don't re-enter if objects are alreay created
+ if ( gBottomPanel == NULL ) // Don't re-enter if objects are alreay created
{
- LLRect bar_rect(-1, STATUS_BAR_HEIGHT, width+1, -1);
- gToolBar = new LLToolBar("toolbar", bar_rect);
-
- LLRect chat_bar_rect(-1,CHAT_BAR_HEIGHT, width+1, -1);
- chat_bar_rect.translate(0, STATUS_BAR_HEIGHT-1);
- gChatBar = new LLChatBar("chat", chat_bar_rect);
-
- bar_rect.translate(0, STATUS_BAR_HEIGHT-1);
- bar_rect.translate(0, CHAT_BAR_HEIGHT-1);
- gOverlayBar = new LLOverlayBar("overlay", bar_rect);
-
// panel containing chatbar, toolbar, and overlay, over floaters
- LLRect bottom_rect(-1, 2*STATUS_BAR_HEIGHT + CHAT_BAR_HEIGHT, width+1, -1);
- gBottomPanel = new LLBottomPanel("bottom panel", bottom_rect);
-
- // the order here is important
- gBottomPanel->addChild(gChatBar);
- gBottomPanel->addChild(gToolBar);
- gBottomPanel->addChild(gOverlayBar);
+ gBottomPanel = new LLBottomPanel(mRootView->getRect());
mRootView->addChild(gBottomPanel);
// View for hover information
@@ -1933,8 +1874,7 @@ void LLViewerWindow::initWorldUI()
mRootView->addChild(gMorphView);
gMorphView->setVisible(FALSE);
- gFloaterMute = new LLFloaterMute();
- gFloaterMute->setVisible(FALSE);
+ gFloaterMute = LLFloaterMute::getInstance();
LLWorldMapView::initClass();
@@ -2450,6 +2390,12 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
if(LLMenuGL::getKeyboardMode())
LLMenuGL::setKeyboardMode(FALSE);
+ if (gFocusMgr.getTopCtrl())
+ {
+ gFocusMgr.setTopCtrl(NULL);
+ return TRUE;
+ }
+
// *TODO: get this to play well with mouselook and hidden
// cursor modes, etc, and re-enable.
//if (gFocusMgr.getMouseCapture())
@@ -2979,23 +2925,9 @@ BOOL LLViewerWindow::handlePerFrameHover()
}
// Update rectangles for the various toolbars
- if (gToolBar && gChatBar && gOverlayBar && gNotifyBoxView && gConsole)
+ if (gOverlayBar && gNotifyBoxView && gConsole)
{
LLRect bar_rect(-1, STATUS_BAR_HEIGHT, getWindowWidth()+1, -1);
- if (gToolBar->getVisible())
- {
- gToolBar->setRect(bar_rect);
- bar_rect.translate(0, STATUS_BAR_HEIGHT-1);
- }
-
- if (gChatBar->getVisible())
- {
- // fix up the height
- LLRect chat_bar_rect = bar_rect;
- chat_bar_rect.mTop = chat_bar_rect.mBottom + CHAT_BAR_HEIGHT + 1;
- gChatBar->setRect(chat_bar_rect);
- bar_rect.translate(0, CHAT_BAR_HEIGHT-1);
- }
LLRect notify_box_rect = gNotifyBoxView->getRect();
notify_box_rect.mBottom = bar_rect.mBottom;
@@ -3015,42 +2947,16 @@ BOOL LLViewerWindow::handlePerFrameHover()
if (gOverlayBar->getVisible())
{
- LLRect overlay_rect = bar_rect;
- overlay_rect.mTop = overlay_rect.mBottom + OVERLAY_BAR_HEIGHT;
-
- // Fitt's Law: Push buttons flush with bottom of screen if
- // nothing else visible.
- if (!gToolBar->getVisible()
- && !gChatBar->getVisible())
- {
- // *NOTE: this is highly depenent on the XML
- // describing the position of the buttons
- overlay_rect.translate(0, 0);
- }
-
- gOverlayBar->setRect(overlay_rect);
- gOverlayBar->updateRect();
- bar_rect.translate(0, gOverlayBar->getRect().getHeight());
-
- gFloaterView->setSnapOffsetBottom(OVERLAY_BAR_HEIGHT);
+ gFloaterView->setSnapOffsetBottom(gHUDView->getRect().mBottom);
}
else
{
gFloaterView->setSnapOffsetBottom(0);
}
- // fix rectangle of bottom panel focus indicator
- if(gBottomPanel && gBottomPanel->getFocusIndicator())
- {
- LLRect focus_rect = gBottomPanel->getFocusIndicator()->getRect();
- focus_rect.mTop = (gToolBar->getVisible() ? STATUS_BAR_HEIGHT : 0) +
- (gChatBar->getVisible() ? CHAT_BAR_HEIGHT : 0) - 2;
- gBottomPanel->getFocusIndicator()->setRect(focus_rect);
- }
-
// Always update console
LLRect console_rect = gConsole->getRect();
- console_rect.mBottom = bar_rect.mBottom + 8;
+ console_rect.mBottom = gHUDView->getRect().mBottom + CONSOLE_BOTTOM_PAD;
gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
gConsole->setRect(console_rect);
}
@@ -3628,13 +3534,6 @@ void LLViewerWindow::performPick()
// if you are the parent
parent = objectp;
}
- std::vector<LLPointer<LLViewerObject>,std::allocator<LLPointer<LLViewerObject> > > children = parent->getChildren();
- for( std::vector<LLPointer<LLViewerObject>,std::allocator<LLPointer<LLViewerObject> > >::iterator i= children.begin(); i!= children.end(); ++i )
- {
- //go through
- LLViewerObject* foo = *i;
- foo->getRotation();
- }
if (objectp->mbCanSelect)
{
te_offset = (te_offset == 16) ? NO_FACE : te_offset;
@@ -4561,9 +4460,9 @@ void LLViewerWindow::drawMouselookInstructions()
// These functions are here only because LLViewerWindow used to do the work that gFocusMgr does now.
// They let other objects continue to work without change.
-void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus,void (*on_focus_lost)(LLUICtrl* old_focus))
+void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus)
{
- gFocusMgr.setKeyboardFocus( new_focus, on_focus_lost );
+ gFocusMgr.setKeyboardFocus( new_focus );
}
LLUICtrl* LLViewerWindow::getKeyboardFocus()
@@ -5033,7 +4932,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
}
mIgnoreActivate = FALSE;
- gFocusMgr.setKeyboardFocus(keyboard_focus, NULL);
+ gFocusMgr.setKeyboardFocus(keyboard_focus);
mWantFullscreen = mWindow->getFullscreen();
mShowFullscreenProgress = FALSE;
@@ -5233,16 +5132,22 @@ LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename,
////////////////////////////////////////////////////////////////////////////
-LLBottomPanel::LLBottomPanel(const LLString &name, const LLRect &rect) :
- LLPanel(name, rect, FALSE),
+LLBottomPanel::LLBottomPanel(const LLRect &rect) :
+ LLPanel("", rect, FALSE),
mIndicator(NULL)
{
// bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay
setFocusRoot(TRUE);
- // don't capture mouse clicks that don't hit a child
- setMouseOpaque(FALSE);
- setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+ // flag this panel as chrome so buttons don't grab keyboard focus
setIsChrome(TRUE);
+
+ mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL);
+ mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL);
+ mFactoryMap["hud"] = LLCallbackMap(createHUD, NULL);
+ gUICtrlFactory->buildPanel(this, "panel_bars.xml", &getFactoryMap());
+
+ setOrigin(rect.mLeft, rect.mBottom);
+ reshape(rect.getWidth(), rect.getHeight());
}
void LLBottomPanel::setFocusIndicator(LLView * indicator)
@@ -5260,3 +5165,25 @@ void LLBottomPanel::draw()
}
LLPanel::draw();
}
+
+void* LLBottomPanel::createHUD(void* data)
+{
+ delete gHUDView;
+ gHUDView = new LLHUDView();
+ return gHUDView;
+}
+
+
+void* LLBottomPanel::createOverlayBar(void* data)
+{
+ delete gOverlayBar;
+ gOverlayBar = new LLOverlayBar();
+ return gOverlayBar;
+}
+
+void* LLBottomPanel::createToolBar(void* data)
+{
+ delete gToolBar;
+ gToolBar = new LLToolBar();
+ return gToolBar;
+}
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index faab518879..36225cb7d3 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -185,7 +185,7 @@ public:
// Handle the application becoming active (frontmost) or inactive
//BOOL handleActivate(BOOL activate);
- void setKeyboardFocus(LLUICtrl* new_focus,void (*on_focus_lost)(LLUICtrl* old_focus)); // new_focus = NULL to release the focus.
+ void setKeyboardFocus(LLUICtrl* new_focus); // new_focus = NULL to release the focus.
LLUICtrl* getKeyboardFocus();
BOOL hasKeyboardFocus( const LLUICtrl* possible_focus ) const;
BOOL childHasKeyboardFocus( const LLView* parent ) const;
@@ -363,10 +363,15 @@ protected:
class LLBottomPanel : public LLPanel
{
public:
- LLBottomPanel(const LLString& name, const LLRect& rect);
+ LLBottomPanel(const LLRect& rect);
void setFocusIndicator(LLView * indicator);
LLView * getFocusIndicator() { return mIndicator; }
/*virtual*/ void draw();
+
+ static void* createHUD(void* data);
+ static void* createOverlayBar(void* data);
+ static void* createToolBar(void* data);
+
protected:
LLView * mIndicator;
};
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index fc159ddc48..c6a3ff192b 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3426,7 +3426,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED,
// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN );
- F32 gain = .30f * gSavedSettings.getF32("AudioLevelAmbient");
+ F32 gain = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : (.30f * gSavedSettings.getF32("AudioLevelAmbient"));
LLUUID& step_sound_id = getStepSound();
LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent);
@@ -4401,7 +4401,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
//else
{
LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping"));
- F32 volume = gSavedSettings.getF32("AudioLevelSFX");
+ F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX");
gAudiop->triggerSound(sound_id, getID(), volume, char_pos_global);
}
}
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index cf6b13e74c..1cbb1adada 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -43,7 +43,6 @@
#include "llcallbacklist.h"
#include "llviewerregion.h"
#include "llviewernetwork.h" // for gGridChoice
-#include "llfloateractivespeakers.h" // for LLSpeakerMgr
#include "llbase64.h"
#include "llviewercontrol.h"
#include "llkeyboard.h"
@@ -532,7 +531,7 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length)
void LLVivoxProtocolParser::processResponse(std::string tag)
{
-// llinfos << tag << llendl;
+ //llinfos << tag << llendl;
if (isEvent)
{
@@ -768,7 +767,7 @@ static HANDLE sGatewayHandle = 0;
static bool isGatewayRunning()
{
bool result = false;
- if(sGatewayHandle != 0)
+ if(sGatewayHandle != 0)
{
DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0);
if(waitresult != WAIT_OBJECT_0)
@@ -854,7 +853,7 @@ LLVoiceClient::LLVoiceClient()
setPTTKey(keyString);
mPTTIsToggle = gSavedSettings.getBOOL("PushToTalkToggle");
mEarLocation = gSavedSettings.getS32("VoiceEarLocation");
- setVoiceVolume(gSavedSettings.getF32("AudioLevelVoice"));
+ setVoiceVolume(gSavedSettings.getBOOL("MuteVoice") ? 0.f : gSavedSettings.getF32("AudioLevelVoice"));
std::string captureDevice = gSavedSettings.getString("VoiceInputAudioDevice");
setCaptureDevice(captureDevice);
std::string renderDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
@@ -876,7 +875,6 @@ LLVoiceClient::LLVoiceClient()
mTuningMicVolumeDirty = true;
mTuningSpeakerVolume = 0;
mTuningSpeakerVolumeDirty = true;
- mTuningCaptureRunning = false;
// gMuteListp isn't set up at this point, so we defer this until later.
// gMuteListp->addObserver(&mutelist_listener);
@@ -1138,14 +1136,15 @@ const char *LLVoiceClient::state2string(LLVoiceClient::state inState)
CASE(stateConnectorStart);
CASE(stateConnectorStarting);
CASE(stateConnectorStarted);
- CASE(stateMicTuningNoLogin);
CASE(stateLoginRetry);
CASE(stateLoginRetryWait);
CASE(stateNeedsLogin);
CASE(stateLoggingIn);
CASE(stateLoggedIn);
CASE(stateNoChannel);
- CASE(stateMicTuningLoggedIn);
+ CASE(stateMicTuningStart);
+ CASE(stateMicTuningRunning);
+ CASE(stateMicTuningStop);
CASE(stateSessionCreate);
CASE(stateSessionConnect);
CASE(stateJoiningSession);
@@ -1164,6 +1163,7 @@ const char *LLVoiceClient::state2string(LLVoiceClient::state inState)
CASE(stateJoinSessionFailed);
CASE(stateJoinSessionFailedWaiting);
CASE(stateJail);
+ CASE(stateMicTuningNoLogin);
}
#undef CASE
@@ -1483,7 +1483,8 @@ void LLVoiceClient::stateMachine()
}
else if(mTuningMode)
{
- setState(stateMicTuningNoLogin);
+ mTuningExitState = stateConnectorStart;
+ setState(stateMicTuningStart);
}
break;
@@ -1515,24 +1516,63 @@ void LLVoiceClient::stateMachine()
}
break;
- case stateMicTuningNoLogin:
- case stateMicTuningLoggedIn:
- {
- // Both of these behave essentially the same. The only difference is where the exit transition goes to.
- if(mTuningMode && mVoiceEnabled && !mSessionTerminateRequested)
- {
- if(!mTuningCaptureRunning)
+ case stateMicTuningStart:
+ if(mUpdateTimer.hasExpired())
+ {
+ if(mCaptureDeviceDirty || mRenderDeviceDirty)
+ {
+ // These can't be changed while in tuning mode. Set them before starting.
+ std::ostringstream stream;
+
+ if(mCaptureDeviceDirty)
+ {
+ buildSetCaptureDevice(stream);
+ }
+
+ if(mRenderDeviceDirty)
+ {
+ buildSetRenderDevice(stream);
+ }
+
+ mCaptureDeviceDirty = false;
+ mRenderDeviceDirty = false;
+
+ if(!stream.str().empty())
+ {
+ writeString(stream.str());
+ }
+
+ // This will come around again in the same state and start the capture, after the timer expires.
+ mUpdateTimer.start();
+ mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+ }
+ else
{
// duration parameter is currently unused, per Mike S.
tuningCaptureStartSendMessage(10000);
+
+ setState(stateMicTuningRunning);
}
-
- if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty || mCaptureDeviceDirty || mRenderDeviceDirty)
+ }
+
+ break;
+
+ case stateMicTuningRunning:
+ if(!mTuningMode || !mVoiceEnabled || mSessionTerminateRequested || mCaptureDeviceDirty || mRenderDeviceDirty)
+ {
+ // All of these conditions make us leave tuning mode.
+ setState(stateMicTuningStop);
+ }
+ else
+ {
+ // process mic/speaker volume changes
+ if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty)
{
std::ostringstream stream;
if(mTuningMicVolumeDirty)
{
+ llinfos << "setting tuning mic level to " << mTuningMicVolume << llendl;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetMicLevel.1\">"
<< "<Level>" << mTuningMicVolume << "</Level>"
@@ -1547,20 +1587,8 @@ void LLVoiceClient::stateMachine()
<< "</Request>\n\n\n";
}
- if(mCaptureDeviceDirty)
- {
- buildSetCaptureDevice(stream);
- }
-
- if(mRenderDeviceDirty)
- {
- buildSetRenderDevice(stream);
- }
-
mTuningMicVolumeDirty = false;
mTuningSpeakerVolumeDirty = false;
- mCaptureDeviceDirty = false;
- mRenderDeviceDirty = false;
if(!stream.str().empty())
{
@@ -1568,23 +1596,19 @@ void LLVoiceClient::stateMachine()
}
}
}
- else
- {
- // transition out of mic tuning
- if(mTuningCaptureRunning)
- {
- tuningCaptureStopSendMessage();
- }
-
- if(getState() == stateMicTuningNoLogin)
- {
- setState(stateConnectorStart);
- }
- else
- {
- setState(stateNoChannel);
- }
- }
+ break;
+
+ case stateMicTuningStop:
+ {
+ // transition out of mic tuning
+ tuningCaptureStopSendMessage();
+
+ setState(mTuningExitState);
+
+ // if we exited just to change devices, this will keep us from re-entering too fast.
+ mUpdateTimer.start();
+ mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+
}
break;
@@ -1654,7 +1678,8 @@ void LLVoiceClient::stateMachine()
}
else if(mTuningMode)
{
- setState(stateMicTuningLoggedIn);
+ mTuningExitState = stateNoChannel;
+ setState(stateMicTuningStart);
}
else if(!mNextSessionHandle.empty())
{
@@ -1880,6 +1905,12 @@ void LLVoiceClient::stateMachine()
case stateJail:
// We have given up. Do nothing.
break;
+
+ case stateMicTuningNoLogin:
+ // *TODO: Implement me.
+ llwarns << "stateMicTuningNoLogin not handled"
+ << llendl;
+ break;
}
if(mParticipantMapChanged)
@@ -2183,9 +2214,9 @@ bool LLVoiceClient::inTuningMode()
bool result = false;
switch(getState())
{
- case stateMicTuningNoLogin:
- case stateMicTuningLoggedIn:
+ case stateMicTuningRunning:
result = true;
+ break;
default:
break;
}
@@ -2193,10 +2224,7 @@ bool LLVoiceClient::inTuningMode()
}
void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop)
-{
- if(!inTuningMode())
- return;
-
+{
mTuningAudioFile = name;
std::ostringstream stream;
stream
@@ -2210,9 +2238,6 @@ void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool l
void LLVoiceClient::tuningRenderStopSendMessage()
{
- if(!inTuningMode())
- return;
-
std::ostringstream stream;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">"
@@ -2224,9 +2249,8 @@ void LLVoiceClient::tuningRenderStopSendMessage()
void LLVoiceClient::tuningCaptureStartSendMessage(int duration)
{
- if(!inTuningMode())
- return;
-
+ llinfos << "sending CaptureAudioStart" << llendl;
+
std::ostringstream stream;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStart.1\">"
@@ -2234,15 +2258,12 @@ void LLVoiceClient::tuningCaptureStartSendMessage(int duration)
<< "</Request>\n\n\n";
writeString(stream.str());
-
- mTuningCaptureRunning = true;
}
void LLVoiceClient::tuningCaptureStopSendMessage()
{
- if(!inTuningMode())
- return;
-
+ llinfos << "sending CaptureAudioStop" << llendl;
+
std::ostringstream stream;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">"
@@ -2250,7 +2271,7 @@ void LLVoiceClient::tuningCaptureStopSendMessage()
writeString(stream.str());
- mTuningCaptureRunning = false;
+ mTuningEnergy = 0.0f;
}
void LLVoiceClient::tuningSetMicVolume(float volume)
@@ -2914,12 +2935,16 @@ void LLVoiceClient::sessionNewEvent(
LLUUID caller_id;
if(IDFromName(nameString, caller_id))
{
- gIMMgr->inviteToSession(LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, caller_id),
- LLString::null,
- caller_id,
- LLString::null,
- IM_SESSION_P2P_INVITE,
- eventSessionHandle);
+ gIMMgr->inviteToSession(
+ LLIMMgr::computeSessionID(
+ IM_SESSION_P2P_INVITE,
+ caller_id),
+ LLString::null,
+ caller_id,
+ LLString::null,
+ IM_SESSION_P2P_INVITE,
+ LLIMMgr::INVITATION_TYPE_VOICE,
+ eventSessionHandle);
}
else
{
@@ -2985,6 +3010,7 @@ void LLVoiceClient::participantPropertiesEvent(
{
participant->mPTT = !isLocallyMuted;
participant->mIsSpeaking = isSpeaking;
+ participant->mIsModeratorMuted = isModeratorMuted;
if (isSpeaking)
{
participant->mSpeakingTimeout.reset();
@@ -3022,7 +3048,7 @@ void LLVoiceClient::muteListChanged()
/////////////////////////////
// Managing list of participants
LLVoiceClient::participantState::participantState(const std::string &uri) :
- mURI(uri), mPTT(false), mIsSpeaking(false), mPower(0.0), mServiceType(serviceTypeUnknown),
+ mURI(uri), mPTT(false), mIsSpeaking(false), mIsModeratorMuted(false), mPower(0.0), mServiceType(serviceTypeUnknown),
mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false)
{
}
@@ -3265,6 +3291,7 @@ void LLVoiceClient::switchChannel(
{
// Leave any channel we may be in
llinfos << "leaving channel" << llendl;
+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
}
else
{
@@ -3786,6 +3813,19 @@ BOOL LLVoiceClient::getIsSpeaking(const LLUUID& id)
return result;
}
+BOOL LLVoiceClient::getIsModeratorMuted(const LLUUID& id)
+{
+ BOOL result = FALSE;
+
+ participantState *participant = findParticipantByID(id);
+ if(participant)
+ {
+ result = participant->mIsModeratorMuted;
+ }
+
+ return result;
+}
+
F32 LLVoiceClient::getCurrentPower(const LLUUID& id)
{
F32 result = 0;
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index ed256b6f8c..5179bc099c 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -63,6 +63,7 @@ public:
STATUS_JOINING,
STATUS_JOINED,
STATUS_LEFT_CHANNEL,
+ STATUS_VOICE_DISABLED,
BEGIN_ERROR_STATUS,
ERROR_CHANNEL_FULL,
ERROR_CHANNEL_LOCKED,
@@ -139,6 +140,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
void tuningStart();
void tuningStop();
bool inTuningMode();
+ bool inTuningStates();
void tuningRenderStartSendMessage(const std::string& name, bool loop);
void tuningRenderStopSendMessage();
@@ -218,6 +220,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
// Accessors for data related to nearby speakers
BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar
BOOL getIsSpeaking(const LLUUID& id);
+ BOOL getIsModeratorMuted(const LLUUID& id);
F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property.
BOOL getOnMuteList(const LLUUID& id);
@@ -242,6 +245,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
std::string mDisplayName;
bool mPTT;
bool mIsSpeaking;
+ bool mIsModeratorMuted;
LLFrameTimer mSpeakingTimeout;
F32 mLastSpokeTimestamp;
F32 mPower;
@@ -316,7 +320,9 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
stateLoggingIn, // waiting for account handle
stateLoggedIn, // account handle received
stateNoChannel, //
- stateMicTuningLoggedIn, // mic tuning for a logged in user
+ stateMicTuningStart,
+ stateMicTuningRunning,
+ stateMicTuningStop,
stateSessionCreate, // need to send Session.Create command
stateSessionConnect, // need to send Session.Connect command
stateJoiningSession, // waiting for session handle
@@ -387,7 +393,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
bool mTuningMicVolumeDirty;
int mTuningSpeakerVolume;
bool mTuningSpeakerVolumeDirty;
- bool mTuningCaptureRunning;
+ state mTuningExitState; // state to return to when we leave tuning mode.
std::string mSpatialSessionURI;
diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp
index e6676639e2..39f2f63066 100644
--- a/indra/newview/llvoicevisualizer.cpp
+++ b/indra/newview/llvoicevisualizer.cpp
@@ -111,7 +111,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
{
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
- mSoundSymbol.mTexture [i] = gImageList.getUIImageByID(sound_level_img[i]);
+ mSoundSymbol.mTexture [i] = gImageList.getImageByID(sound_level_img[i]);
mSoundSymbol.mWaveActive [i] = false;
mSoundSymbol.mWaveOpacity [i] = 1.0f;
mSoundSymbol.mWaveExpansion [i] = 1.0f;
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index dac693885f..ec277b1a1b 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -1117,11 +1117,6 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen )
{
- if( !getVisible() || !pointInView( x, y ) )
- {
- return FALSE;
- }
-
LLVector3d pos_global = viewPosToGlobal(x, y);
LLSimInfo* info = gWorldMap->simInfoFromPosGlobal(pos_global);
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 7bb12f7853..5775af68a1 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -435,7 +435,7 @@ class DarwinManifest(ViewerManifest):
self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
# Unmount the image
- self.run_command('hdiutil detach "' + devfile + '"')
+ self.run_command('hdiutil detach -force "' + devfile + '"')
print "Converting temp disk image to final disk image"
self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname})
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index c7ce013dcd..5332b1263d 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -8178,7 +8178,7 @@ version 2.0
// dataserver -> userserver
// reliable
{
- AgentDropGroup Low 390 Trusted Zerocoded
+ AgentDropGroup Low 390 Trusted Zerocoded UDPDeprecated
{
AgentData Single
{ AgentID LLUUID }