summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/GoogleMock.cmake27
-rw-r--r--indra/cmake/LLAddBuildTest.cmake11
-rw-r--r--indra/integration_tests/llui_libtest/CMakeLists.txt2
-rw-r--r--indra/lib/python/indra/base/llsd.py2
-rw-r--r--indra/lib/python/indra/util/llsubprocess.py11
-rw-r--r--indra/lib/python/indra/util/named_query.py4
-rw-r--r--indra/linux_updater/linux_updater.cpp2
-rw-r--r--indra/llaudio/CMakeLists.txt3
-rw-r--r--indra/llcharacter/llkeyframestandmotion.cpp2
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/linden_common.h3
-rw-r--r--indra/llcommon/llassettype.cpp27
-rw-r--r--indra/llcommon/llassettype.h1
-rw-r--r--indra/llcommon/llchat.h10
-rw-r--r--indra/llcommon/lldate.cpp68
-rw-r--r--indra/llcommon/lldate.h2
-rw-r--r--indra/llcommon/llkeythrottle.h57
-rw-r--r--indra/llcommon/llstat.cpp51
-rw-r--r--indra/llcommon/llstat.h21
-rw-r--r--indra/llcommon/llstring.cpp324
-rw-r--r--indra/llcommon/llstring.h303
-rw-r--r--indra/llcommon/llversionserver.h4
-rw-r--r--indra/llcommon/llversionviewer.h2
-rw-r--r--indra/llcommon/metapropertyt.h13
-rw-r--r--indra/llimage/llimagej2c.cpp48
-rw-r--r--indra/llimage/llimagej2c.h4
-rw-r--r--indra/llinventory/llinventory.cpp33
-rw-r--r--indra/llinventory/llinventory.h7
-rw-r--r--indra/llinventory/llparcel.h6
-rw-r--r--indra/llinventory/llpermissions.cpp13
-rw-r--r--indra/llinventory/llpermissions.h4
-rw-r--r--indra/llinventory/lltransactiontypes.h12
-rw-r--r--indra/llmath/llcoord.h9
-rw-r--r--indra/llmath/llquaternion.cpp6
-rw-r--r--indra/llmath/llquaternion.h34
-rw-r--r--indra/llmessage/CMakeLists.txt4
-rw-r--r--indra/llmessage/llcachename.h1
-rw-r--r--indra/llmessage/llcurl.cpp13
-rw-r--r--indra/llmessage/llcurl.h6
-rw-r--r--indra/llmessage/llhttpclient.cpp5
-rw-r--r--indra/llmessage/llhttpclientadapter.cpp2
-rw-r--r--indra/llmessage/llhttpclientadapter.h2
-rw-r--r--indra/llmessage/llhttpclientinterface.h2
-rw-r--r--indra/llmessage/lliohttpserver.cpp14
-rw-r--r--indra/llmessage/llmail.cpp18
-rw-r--r--indra/llmessage/llmessagesenderinterface.h2
-rw-r--r--indra/llmessage/llregionpresenceverifier.cpp88
-rw-r--r--indra/llmessage/llregionpresenceverifier.h39
-rw-r--r--indra/llmessage/llstoredmessage.cpp2
-rw-r--r--indra/llmessage/llstoredmessage.h2
-rw-r--r--indra/llmessage/llthrottle.cpp25
-rw-r--r--indra/llmessage/llthrottle.h2
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp1
-rw-r--r--indra/llmessage/llurlrequest.cpp54
-rw-r--r--indra/llmessage/llurlrequest.h8
-rw-r--r--indra/llmessage/llxfermanager.cpp36
-rw-r--r--indra/llmessage/tests/llmockhttpclient.h61
-rw-r--r--indra/llmessage/tests/llregionpresenceverifier_test.cpp113
-rw-r--r--indra/llplugin/llpluginclassmedia.h2
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h1
-rw-r--r--indra/llprimitive/llprimitive.cpp265
-rw-r--r--indra/llprimitive/llprimitive.h25
-rw-r--r--indra/llprimitive/llprimtexturelist.cpp19
-rw-r--r--indra/llrender/llfontbitmapcache.cpp18
-rw-r--r--indra/llrender/llfontbitmapcache.h1
-rw-r--r--indra/llrender/llfontfreetype.cpp4
-rw-r--r--indra/llrender/llfontfreetype.h190
-rw-r--r--indra/llrender/llfontregistry.cpp2
-rw-r--r--indra/llui/CMakeLists.txt49
-rw-r--r--indra/llui/llbutton.cpp48
-rw-r--r--indra/llui/llbutton.h1
-rw-r--r--indra/llui/llcombobox.cpp35
-rw-r--r--indra/llui/llcombobox.h6
-rw-r--r--indra/llui/lldockablefloater.cpp133
-rw-r--r--indra/llui/lldockablefloater.h75
-rw-r--r--indra/llui/lldockcontrol.cpp143
-rw-r--r--indra/llui/lldockcontrol.h81
-rw-r--r--indra/llui/llfiltereditor.cpp73
-rw-r--r--indra/llui/llfiltereditor.h30
-rw-r--r--indra/llui/llflatlistview.cpp494
-rw-r--r--indra/llui/llflatlistview.h262
-rw-r--r--indra/llui/llfloater.cpp96
-rw-r--r--indra/llui/llfloater.h3
-rw-r--r--indra/llui/lliconctrl.cpp10
-rw-r--r--indra/llui/lliconctrl.h2
-rw-r--r--indra/llui/lllayoutstack.cpp2
-rw-r--r--indra/llui/lllineeditor.cpp3
-rw-r--r--indra/llui/lllineeditor.h3
-rw-r--r--indra/llui/lllocalcliprect.cpp143
-rw-r--r--indra/llui/lllocalcliprect.h53
-rw-r--r--indra/llui/llmenugl.cpp36
-rw-r--r--indra/llui/llmenugl.h4
-rw-r--r--indra/llui/llpanel.cpp28
-rw-r--r--indra/llui/llpanel.h13
-rw-r--r--indra/llui/llscrollbar.cpp2
-rw-r--r--indra/llui/llscrollcontainer.cpp4
-rw-r--r--indra/llui/llscrolllistctrl.cpp125
-rw-r--r--indra/llui/llscrolllistctrl.h27
-rw-r--r--indra/llui/llsdparam.cpp10
-rw-r--r--indra/llui/llsearcheditor.cpp82
-rw-r--r--indra/llui/llsearcheditor.h24
-rw-r--r--indra/llui/llslider.cpp16
-rw-r--r--indra/llui/llstyle.cpp8
-rw-r--r--indra/llui/llstyle.h8
-rw-r--r--indra/llui/lltabcontainer.cpp18
-rw-r--r--indra/llui/lltabcontainer.h2
-rw-r--r--indra/llui/lltextbase.cpp457
-rw-r--r--indra/llui/lltextbase.h198
-rw-r--r--indra/llui/lltextbox.cpp516
-rw-r--r--indra/llui/lltextbox.h53
-rw-r--r--indra/llui/lltexteditor.cpp702
-rw-r--r--indra/llui/lltexteditor.h131
-rw-r--r--indra/llui/lltooltip.cpp445
-rw-r--r--indra/llui/lltooltip.h127
-rw-r--r--indra/llui/llui.cpp121
-rw-r--r--indra/llui/llui.h73
-rw-r--r--indra/llui/lluictrl.cpp11
-rw-r--r--indra/llui/lluictrl.h6
-rw-r--r--indra/llui/lluictrlfactory.cpp14
-rw-r--r--indra/llui/llurlaction.cpp137
-rw-r--r--indra/llui/llurlaction.h93
-rw-r--r--indra/llui/llurlentry.cpp567
-rw-r--r--indra/llui/llurlentry.h242
-rw-r--r--indra/llui/llurlmatch.cpp61
-rw-r--r--indra/llui/llurlmatch.h98
-rw-r--r--indra/llui/llurlregistry.cpp164
-rw-r--r--indra/llui/llurlregistry.h87
-rw-r--r--indra/llui/llview.cpp326
-rw-r--r--indra/llui/llview.h127
-rw-r--r--indra/llui/llviewborder.cpp2
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp64
-rw-r--r--indra/llui/tests/llurlentry_test.cpp531
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp177
-rwxr-xr-xindra/llvfs/llpidlock.cpp2
-rw-r--r--indra/llwindow/llmousehandler.h6
-rw-r--r--indra/llxuixml/llinitparam.cpp8
-rw-r--r--indra/llxuixml/llinitparam.h8
-rw-r--r--indra/lscript/lscript_byteformat.h2
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.cpp12
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.h1
-rw-r--r--indra/lscript/lscript_execute.h3
-rw-r--r--indra/lscript/lscript_execute/lscript_execute.cpp122
-rw-r--r--indra/media_plugins/base/media_plugin_base.exp3
-rw-r--r--indra/newview/CMakeLists.txt17
-rw-r--r--indra/newview/English.lproj/InfoPlist.strings4
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/settings.xml166
-rw-r--r--indra/newview/fonts/DejaVuSans-Bold.ttfbin0 -> 573136 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-BoldOblique.ttfbin0 -> 524056 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-Oblique.ttfbin0 -> 523804 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans.ttfbin0 -> 622280 bytes
-rw-r--r--indra/newview/fonts/DejaVuSansMono.ttfbin319388 -> 321524 bytes
-rw-r--r--indra/newview/llagent.cpp23
-rw-r--r--indra/newview/llagentwearables.cpp148
-rw-r--r--indra/newview/llagentwearables.h1
-rw-r--r--indra/newview/llappearancemgr.cpp793
-rw-r--r--indra/newview/llappearancemgr.h70
-rw-r--r--indra/newview/llappviewer.cpp29
-rw-r--r--indra/newview/llavataractions.cpp1
-rw-r--r--indra/newview/llavatariconctrl.cpp2
-rw-r--r--indra/newview/llavatarlist.cpp226
-rw-r--r--indra/newview/llavatarlist.h42
-rw-r--r--indra/newview/llavatarlistitem.cpp221
-rw-r--r--indra/newview/llavatarlistitem.h94
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp303
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h61
-rw-r--r--indra/newview/llbottomtray.cpp114
-rw-r--r--indra/newview/llbottomtray.h22
-rw-r--r--indra/newview/llchatbar.cpp2
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp1
-rw-r--r--indra/newview/llchatmsgbox.cpp371
-rw-r--r--indra/newview/llchatmsgbox.h129
-rw-r--r--indra/newview/llchiclet.cpp497
-rw-r--r--indra/newview/llchiclet.h298
-rw-r--r--indra/newview/llcolorswatch.cpp7
-rw-r--r--indra/newview/llcommandhandler.cpp51
-rw-r--r--indra/newview/llcommandhandler.h11
-rw-r--r--indra/newview/llconfirmationmanager.cpp3
-rw-r--r--indra/newview/llfasttimerview.cpp19
-rw-r--r--indra/newview/llfasttimerview.h2
-rw-r--r--indra/newview/llfavoritesbar.cpp412
-rw-r--r--indra/newview/llfavoritesbar.h49
-rw-r--r--indra/newview/llfloaterabout.cpp52
-rw-r--r--indra/newview/llfloateranimpreview.cpp2
-rw-r--r--indra/newview/llfloatercamera.cpp18
-rw-r--r--indra/newview/llfloatercamera.h5
-rw-r--r--indra/newview/llfloaterchat.cpp4
-rw-r--r--indra/newview/llfloaterfriends.cpp1
-rw-r--r--indra/newview/llfloatergroups.cpp19
-rw-r--r--indra/newview/llfloaterhandler.h2
-rw-r--r--indra/newview/llfloaterimagepreview.cpp2
-rw-r--r--indra/newview/llfloaterimagepreview.h2
-rw-r--r--indra/newview/llfloaterland.cpp7
-rw-r--r--indra/newview/llfloaterparcel.cpp2
-rw-r--r--indra/newview/llfloaterpreference.cpp65
-rw-r--r--indra/newview/llfloatersnapshot.cpp1
-rw-r--r--indra/newview/llfloatertestinspectors.cpp109
-rw-r--r--indra/newview/llfloatertestinspectors.h64
-rw-r--r--indra/newview/llfloatertools.cpp4
-rw-r--r--indra/newview/llfolderviewitem.cpp6
-rw-r--r--indra/newview/llfolderviewitem.h1
-rw-r--r--indra/newview/llfriendcard.cpp13
-rw-r--r--indra/newview/llfriendcard.h5
-rw-r--r--indra/newview/llglsandbox.cpp2
-rw-r--r--indra/newview/llgroupactions.cpp2
-rw-r--r--indra/newview/llgrouplist.cpp10
-rw-r--r--indra/newview/llimhandler.cpp9
-rw-r--r--indra/newview/llimpanel.cpp71
-rw-r--r--indra/newview/llimpanel.h12
-rw-r--r--indra/newview/llimview.cpp127
-rw-r--r--indra/newview/llimview.h16
-rw-r--r--indra/newview/llinspectavatar.cpp173
-rw-r--r--indra/newview/llinspectavatar.h38
-rw-r--r--indra/newview/llinventorybridge.cpp889
-rw-r--r--indra/newview/llinventorybridge.h9
-rw-r--r--indra/newview/llinventoryfilter.h1
-rw-r--r--indra/newview/llinventorymodel.cpp57
-rw-r--r--indra/newview/llinventorymodel.h28
-rw-r--r--indra/newview/lllocationhistory.cpp78
-rw-r--r--indra/newview/lllocationhistory.h77
-rw-r--r--indra/newview/lllocationinputctrl.cpp83
-rw-r--r--indra/newview/lllocationinputctrl.h4
-rw-r--r--indra/newview/llloginhandler.h2
-rw-r--r--indra/newview/llmaniprotate.cpp2
-rw-r--r--indra/newview/llmaniptranslate.cpp2
-rw-r--r--indra/newview/llmediactrl.cpp9
-rw-r--r--indra/newview/llmemoryview.cpp2
-rw-r--r--indra/newview/llnamelistctrl.cpp4
-rw-r--r--indra/newview/llnavigationbar.cpp210
-rw-r--r--indra/newview/llnavigationbar.h15
-rw-r--r--indra/newview/llnearbychat.cpp10
-rw-r--r--indra/newview/llnearbychatbar.cpp22
-rw-r--r--indra/newview/llnearbychatbar.h1
-rw-r--r--indra/newview/llnetmap.cpp25
-rw-r--r--indra/newview/llnetmap.h2
-rw-r--r--indra/newview/lloutputmonitorctrl.cpp48
-rw-r--r--indra/newview/lloutputmonitorctrl.h18
-rw-r--r--indra/newview/llpanelavatar.cpp90
-rw-r--r--indra/newview/llpanelavatar.h5
-rw-r--r--indra/newview/llpanelblockedlist.cpp279
-rw-r--r--indra/newview/llpanelblockedlist.h115
-rw-r--r--indra/newview/llpanelclassified.cpp2
-rw-r--r--indra/newview/llpanelgroup.cpp2
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp15
-rw-r--r--indra/newview/llpanelgrouproles.cpp38
-rw-r--r--indra/newview/llpanelgrouproles.h9
-rw-r--r--indra/newview/llpanellogin.cpp2
-rw-r--r--indra/newview/llpanelobject.cpp2
-rw-r--r--indra/newview/llpanelpeople.cpp102
-rw-r--r--indra/newview/llpanelpeople.h3
-rw-r--r--indra/newview/llpanelpick.cpp23
-rw-r--r--indra/newview/llpanelpicks.cpp271
-rw-r--r--indra/newview/llpanelpicks.h30
-rw-r--r--indra/newview/llpanelplaceinfo.cpp452
-rw-r--r--indra/newview/llpanelplaceinfo.h56
-rw-r--r--indra/newview/llpanelplaces.cpp178
-rw-r--r--indra/newview/llpanelplaces.h33
-rw-r--r--indra/newview/llpanelprofile.cpp2
-rw-r--r--indra/newview/llpanelprofileview.cpp42
-rw-r--r--indra/newview/llpanelprofileview.h7
-rw-r--r--indra/newview/llpanelteleporthistory.cpp181
-rw-r--r--indra/newview/llpanelteleporthistory.h21
-rw-r--r--indra/newview/llpreviewnotecard.cpp3
-rw-r--r--indra/newview/llprogressview.cpp6
-rw-r--r--indra/newview/llprogressview.h1
-rw-r--r--indra/newview/llrecentpeople.cpp7
-rw-r--r--indra/newview/llrecentpeople.h7
-rw-r--r--indra/newview/llscreenchannel.cpp11
-rw-r--r--indra/newview/llsearchcombobox.cpp265
-rw-r--r--indra/newview/llsearchcombobox.h110
-rw-r--r--indra/newview/llsearchhistory.cpp154
-rw-r--r--indra/newview/llsearchhistory.h138
-rw-r--r--indra/newview/llselectmgr.cpp48
-rw-r--r--indra/newview/llselectmgr.h4
-rw-r--r--indra/newview/llsidetray.cpp7
-rw-r--r--indra/newview/llstartup.cpp7
-rw-r--r--indra/newview/llstatusbar.cpp2
-rw-r--r--indra/newview/llsyswellwindow.cpp271
-rw-r--r--indra/newview/llsyswellwindow.h47
-rw-r--r--indra/newview/llteleporthistorystorage.cpp98
-rw-r--r--indra/newview/llteleporthistorystorage.h35
-rw-r--r--indra/newview/lltextureview.cpp20
-rw-r--r--indra/newview/lltoast.cpp10
-rw-r--r--indra/newview/lltoast.h4
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp61
-rw-r--r--indra/newview/lltoastgroupnotifypanel.h2
-rw-r--r--indra/newview/lltoastimpanel.cpp47
-rw-r--r--indra/newview/lltoastimpanel.h6
-rw-r--r--indra/newview/lltoastpanel.cpp31
-rw-r--r--indra/newview/lltoastpanel.h2
-rw-r--r--indra/newview/lltool.cpp16
-rw-r--r--indra/newview/lltool.h5
-rw-r--r--indra/newview/lltoolbar.cpp46
-rw-r--r--indra/newview/lltooldraganddrop.cpp13
-rw-r--r--indra/newview/lltooldraganddrop.h2
-rw-r--r--indra/newview/lltoolfocus.cpp8
-rw-r--r--indra/newview/lltoolgrab.cpp8
-rw-r--r--indra/newview/lltoolmgr.cpp1
-rw-r--r--indra/newview/lltoolpie.cpp461
-rw-r--r--indra/newview/lltoolpie.h3
-rw-r--r--indra/newview/lltoolpipette.cpp13
-rw-r--r--indra/newview/lltoolpipette.h2
-rw-r--r--indra/newview/lltoolplacer.cpp1
-rw-r--r--indra/newview/llurldispatcher.cpp14
-rw-r--r--indra/newview/llviewerdisplay.cpp4
-rw-r--r--indra/newview/llviewerfloaterreg.cpp8
-rw-r--r--indra/newview/llviewerinventory.cpp140
-rw-r--r--indra/newview/llviewerinventory.h18
-rw-r--r--indra/newview/llviewermedia.cpp3
-rw-r--r--indra/newview/llviewermedia.h3
-rw-r--r--indra/newview/llviewermenu.cpp39
-rw-r--r--indra/newview/llviewermessage.cpp41
-rw-r--r--indra/newview/llviewerobject.cpp16
-rw-r--r--indra/newview/llviewerobject.h4
-rw-r--r--indra/newview/llviewerobjectlist.cpp12
-rw-r--r--indra/newview/llviewerparcelmedia.cpp2
-rw-r--r--indra/newview/llviewerparcelmgr.cpp8
-rw-r--r--indra/newview/llviewerparcelmgr.h2
-rw-r--r--indra/newview/llviewerprecompiledheaders.h2
-rw-r--r--indra/newview/llviewertexteditor.cpp84
-rw-r--r--indra/newview/llviewertexteditor.h5
-rw-r--r--indra/newview/llviewertexture.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp538
-rw-r--r--indra/newview/llviewerwindow.h52
-rw-r--r--indra/newview/llvograss.cpp2
-rw-r--r--indra/newview/llvoiceclient.cpp3
-rw-r--r--indra/newview/llweb.cpp10
-rw-r--r--indra/newview/llweb.h20
-rw-r--r--indra/newview/llworldmapview.cpp20
-rw-r--r--indra/newview/llworldmapview.h2
-rw-r--r--indra/newview/res/viewerRes.rc10
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.pngbin0 -> 527 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.pngbin0 -> 365 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.pngbin0 -> 532 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.pngbin0 -> 275 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.pngbin0 -> 3271 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.pngbin0 -> 787 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/CameraView_Press.pngbin0 -> 489 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Run_Off.pngbin0 -> 496 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.pngbin0 -> 515 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.pngbin0 -> 354 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.pngbin0 -> 353 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.pngbin0 -> 419 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Down_On.pngbin0 -> 417 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.pngbin0 -> 322 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.pngbin0 -> 321 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.pngbin0 -> 431 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.pngbin0 -> 430 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.pngbin0 -> 432 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.pngbin0 -> 427 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.pngbin0 -> 371 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Up_On.pngbin0 -> 370 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Snapshot_Off.pngbin0 -> 332 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AddItem_Disabled.pngbin0 -> 186 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/DragHandle.pngbin0 -> 163 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Group.pngbin0 -> 550 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Group_Large.pngbin0 -> 2282 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Person.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Person_Large.pngbin0 -> 1630 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Animation.pngbin0 -> 486 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_BodyShape.pngbin0 -> 571 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_CallingCard.pngbin0 -> 295 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Clothing.pngbin0 -> 255 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Eye.pngbin0 -> 439 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderClosed.pngbin0 -> 215 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderOpen.pngbin0 -> 351 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gesture.pngbin0 -> 413 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gloves.pngbin0 -> 385 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Hair.pngbin0 -> 366 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Jacket.pngbin0 -> 573 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Landmark.pngbin0 -> 494 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Notecard.pngbin0 -> 238 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Object.pngbin0 -> 327 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Pants.pngbin0 -> 375 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Script.pngbin0 -> 463 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shirt.pngbin0 -> 397 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shoe.pngbin0 -> 284 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skin.pngbin0 -> 382 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skirt.pngbin0 -> 449 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Snapshot.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Socks.pngbin0 -> 347 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Sound.pngbin0 -> 359 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Texture.pngbin0 -> 157 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Underpants.pngbin0 -> 397 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Undershirt.pngbin0 -> 208 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Lock.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Refresh_Off.pngbin0 -> 483 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/TrashItem_Disabled.pngbin0 -> 196 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Over.pngbin0 -> 263 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Press.pngbin0 -> 249 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_adult.tgabin0 -> 648 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_mature.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_pg.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml626
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Help_Foreground.pngbin0 -> 363 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Help_Press.pngbin0 -> 355 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.pngbin0 -> 151 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Minimize_Press.pngbin0 -> 146 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_Background.pngbin0 -> 400 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_Hover.pngbin0 -> 414 bytes
-rw-r--r--indra/newview/skins/default/xui/en/floater_activeim.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml90
-rw-r--r--indra/newview/skins/default/xui/en/floater_font_test.xml26
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_browser.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml148
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_preview.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_sys_well.xml55
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_inspectors.xml110
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml737
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml82
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml43
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml26
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_agent.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_group.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_http.xml37
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_objectim.xml37
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_parcel.xml21
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_slapp.xml21
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_slurl.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_teleport.xml21
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml604
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml75
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml152
-rw-r--r--indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml84
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml48
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pick.xml134
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_profile.xml50
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml51
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml80
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml38
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml40
-rw-r--r--indra/newview/skins/default/xui/en/panel_navigation_bar.xml13
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml232
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_info.xml151
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_list_item.xml29
-rw-r--r--indra/newview/skins/default/xui/en/panel_picks.xml47
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml132
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_view.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_progress.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml40
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history.xml162
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml4
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1874
-rw-r--r--indra/newview/skins/default/xui/en/widgets/accordion_tab.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/filter_editor.xml24
-rw-r--r--indra/newview/skins/default/xui/en/widgets/flat_list_view.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/floater.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/list.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/location_input.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_combo_box.xml28
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_editor.xml5
-rw-r--r--indra/test/CMakeLists.txt5
-rw-r--r--indra/test/llhttpdate_tut.cpp69
-rwxr-xr-xindra/test/llsdmessagebuilder_tut.cpp50
-rw-r--r--indra/test/test.cpp10
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp2
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.h3
474 files changed, 19697 insertions, 8486 deletions
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
new file mode 100644
index 0000000000..ca5a8034ba
--- /dev/null
+++ b/indra/cmake/GoogleMock.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Prebuilt)
+include(Linking)
+
+use_prebuilt_binary(googlemock)
+
+set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include)
+
+if (LINUX)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+elseif(WINDOWS)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock)
+ set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include
+ ${LIBS_PREBUILT_DIR}/include/gmock
+ ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1)
+elseif(DARWIN)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+endif(LINUX)
+
+
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 8cd5796849..ca8da05bbb 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -14,6 +14,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
#
# WARNING: do NOT modify this code without working with poppy or daveh -
# there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
IF(LL_TEST_VERBOSE)
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
@@ -33,8 +35,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${LLMATH_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LIBS_OPEN_DIR}/test
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
SET(alltest_LIBRARIES
+ ${GOOGLEMOCK_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
)
@@ -43,6 +47,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${CMAKE_SOURCE_DIR}/test/test.h
)
+ # Use the default flags
+ if (LINUX)
+ SET(CMAKE_EXE_LINKER_FLAGS "")
+ endif (LINUX)
+
# start the source test executable definitions
SET(${project}_TEST_OUTPUT "")
FOREACH (source ${sources})
@@ -85,9 +94,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
ENDIF(LL_TEST_VERBOSE)
+
# Setup target
ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
-
#
# Per-codefile additional / external project dep and lib dep property extraction
#
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index 1ccdb0f20b..84e3477ce6 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -11,6 +11,7 @@ include(LLCommon)
include(LLImage)
include(LLImageJ2COJ) # ugh, needed for images
include(LLMath)
+include(LLMessage)
include(LLRender)
include(LLWindow)
include(LLUI)
@@ -67,6 +68,7 @@ endif (DARWIN)
# Sort by high-level to low-level
target_link_libraries(llui_libtest
llui
+ llmessage
${OS_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663..4527b115f9 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ class LLSDXMLFormatter(object):
def MAP(self, v):
return self.elt(
'map',
- ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+ ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
for key, value in v.items()]))
typeof = type
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec..7e0e115d14 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ all the output, and get the result.
child.tochild.close()
result = child.poll()
if result != -1:
+ # At this point, the child process has exited and result
+ # is the return value from the process. Between the time
+ # we called select() and poll() the process may have
+ # exited so read all the data left on the child process
+ # stdout and stderr.
+ last = child.fromchild.read()
+ if last:
+ out.append(last)
+ last = child.childerr.read()
+ if last:
+ err.append(last)
child.tochild.close()
child.fromchild.close()
child.childerr.close()
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f79..5c19368240 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@ from indra.base import llsd
from indra.base import config
DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
_g_named_manager = None
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
index b93890ab32..4b0bf6a2d9 100644
--- a/indra/linux_updater/linux_updater.cpp
+++ b/indra/linux_updater/linux_updater.cpp
@@ -90,7 +90,7 @@ bool translate_init(std::string comma_delim_path_list,
// extract paths string vector from comma-delimited flat string
std::vector<std::string> paths;
- LLStringUtil::getTokens(comma_delim_path_list, paths); // split over ','
+ LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ','
// suck the translation xml files into memory
LLXMLNodePtr root;
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index 80245fd569..9e9e1aaeae 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -62,7 +62,8 @@ if (FMOD)
if (LINUX)
if (${CXX_VERSION} MATCHES "4.[23]")
set_source_files_properties(llaudioengine_fmod.cpp
- COMPILE_FLAGS -Wno-error=write-strings)
+ llstreamingaudio_fmod.cpp
+ COMPILE_FLAGS -Wno-write-strings)
endif (${CXX_VERSION} MATCHES "4.[23]")
endif (LINUX)
endif (FMOD)
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d..1ae0ddeea0 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
{
mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
- mLastGoodPelvisRotation.normQuat();
+ mLastGoodPelvisRotation.normalize();
mTrackAnkles = TRUE;
}
else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index baf374ee38..1c84c9e21e 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -295,7 +295,7 @@ SET(llcommon_TEST_SOURCE_FILES
LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
-set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
# Have to treat lllazy test as an integration test until this issue is resolved:
# https://jira.lindenlab.com/jira/browse/DEV-29456
LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index d0ab5e969f..c2eb867795 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -81,7 +81,8 @@
#include "lldefs.h"
#include "llerror.h"
#include "llextendedstatus.h"
-#include "llfasttimer.h"
+// Don't do this, adds 15K lines of header code to every library file.
+//#include "llfasttimer.h"
#include "llfile.h"
#include "llformat.h"
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index e595cc1f8b..78aa6f4f37 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -80,27 +80,27 @@ LLAssetDictionary::LLAssetDictionary()
{
// DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED?
// |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------|
- addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE, TRUE));
- addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE, TRUE));
- addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE, TRUE));
- addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE, TRUE));
- addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, TRUE, TRUE));
+ addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, TRUE, TRUE));
+ addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, TRUE, TRUE));
+ addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, TRUE, TRUE));
+ addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, TRUE, TRUE));
addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE));
addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE));
- addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE, TRUE));
+ addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, TRUE, TRUE));
addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE));
addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE));
- addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE, TRUE));
- addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, TRUE, TRUE));
+ addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, TRUE, TRUE));
+ addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE));
addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, TRUE, TRUE));
+ addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
+ addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
+ addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, TRUE, TRUE));
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, TRUE, TRUE));
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
@@ -289,6 +289,7 @@ bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
asset_type <= AT_FOLDER_ENSEMBLE_END);
}
+
// static. Generate a good default description
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
std::string& description)
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 8b29c8defa..33705cd2b1 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -150,6 +150,7 @@ public:
AT_COUNT = 49,
+
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +*********************************************************+
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index 7b010d6739..acd0da61a4 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -65,6 +65,12 @@ typedef enum e_chat_audible_level
CHAT_AUDIBLE_FULLY = 1
} EChatAudible;
+typedef enum e_chat_style
+{
+ CHAT_STYLE_NORMAL,
+ CHAT_STYLE_IRC
+}EChatStyle;
+
// A piece of chat
class LLChat
{
@@ -79,7 +85,8 @@ public:
mMuted(FALSE),
mTime(0.0),
mPosAgent(),
- mURL()
+ mURL(),
+ mChatStyle(CHAT_STYLE_NORMAL)
{ }
std::string mText; // UTF-8 line of text
@@ -92,6 +99,7 @@ public:
F64 mTime; // viewer only, seconds from viewer start
LLVector3 mPosAgent;
std::string mURL;
+ EChatStyle mChatStyle;
};
#endif
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 7bc9e16bc9..7c0ac6c554 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -38,7 +38,7 @@
#include "apr_time.h"
#include <time.h>
-#include <locale>
+#include <locale.h>
#include <string>
#include <iomanip>
#include <sstream>
@@ -94,33 +94,34 @@ std::string LLDate::asRFC1123() const
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
+LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
+
std::string LLDate::toHTTPDateString (std::string fmt) const
{
- std::ostringstream stream;
+ LLFastTimer ft1(FT_DATE_FORMAT);
+
time_t locSeconds = (time_t) mSecondsSinceEpoch;
struct tm * gmt = gmtime (&locSeconds);
-
- stream.imbue (std::locale(LLStringUtil::getLocale().c_str()));
- toHTTPDateStream (stream, gmt, fmt);
- return stream.str();
+ return toHTTPDateString(gmt, fmt);
}
std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
{
- std::ostringstream stream;
- stream.imbue (std::locale(LLStringUtil::getLocale().c_str()));
- toHTTPDateStream (stream, gmt, fmt);
- return stream.str();
-}
+ LLFastTimer ft1(FT_DATE_FORMAT);
-void LLDate::toHTTPDateStream(std::ostream& s, tm * gmt, std::string fmt)
-{
- using namespace std;
+ // avoid calling setlocale() unnecessarily - it's expensive.
+ static std::string prev_locale = "";
+ std::string this_locale = LLStringUtil::getLocale();
+ if (this_locale != prev_locale)
+ {
+ setlocale(LC_TIME, this_locale.c_str());
+ prev_locale = this_locale;
+ }
- const char * pBeg = fmt.c_str();
- const char * pEnd = pBeg + fmt.length();
- const time_put<char>& tp = use_facet<time_put<char> >(s.getloc());
- tp.put (s, s, s.fill(), gmt, pBeg, pEnd);
+ // use strftime() as it appears to be faster than std::time_put
+ char buffer[128];
+ strftime(buffer, 128, fmt.c_str(), gmt);
+ return std::string(buffer);
}
void LLDate::toStream(std::ostream& s) const
@@ -154,6 +155,37 @@ void LLDate::toStream(std::ostream& s) const
s << 'Z';
}
+bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const
+{
+ apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
+
+ apr_time_exp_t exp_time;
+ if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (year)
+ *year = exp_time.tm_year + 1900;
+
+ if (month)
+ *month = exp_time.tm_mon + 1;
+
+ if (day)
+ *day = exp_time.tm_mday;
+
+ if (hour)
+ *hour = exp_time.tm_hour;
+
+ if (min)
+ *min = exp_time.tm_min;
+
+ if (sec)
+ *sec = exp_time.tm_sec;
+
+ return true;
+}
+
bool LLDate::fromString(const std::string& iso8601_date)
{
std::istringstream stream(iso8601_date);
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 4dffaafc7d..1f14093390 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -84,9 +84,9 @@ public:
std::string asString() const;
std::string asRFC1123() const;
void toStream(std::ostream&) const;
+ bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
std::string toHTTPDateString (std::string fmt) const;
static std::string toHTTPDateString (tm * gmt, std::string fmt);
- static void toHTTPDateStream(std::ostream&, tm *, std::string);
/**
* @brief Set the date from an ISO-8601 string.
*
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65e..7544ab1d11 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ public:
THROTTLE_BLOCKED, // rate exceed, block key
};
+ F64 getActionCount(const T& id)
+ {
+ U64 now = 0;
+ if ( mIsRealtime )
+ {
+ now = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ now = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if (now >= (m.startTime + m.intervalLength))
+ {
+ if (now < (m.startTime + 2 * m.intervalLength))
+ {
+ // prune old data
+ delete m.prevMap;
+ m.prevMap = m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime += m.intervalLength;
+ }
+ else
+ {
+ // lots of time has passed, all data is stale
+ delete m.prevMap;
+ delete m.currMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime = now;
+ }
+ }
+
+ U32 prevCount = 0;
+
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+ if (prev != m.prevMap->end())
+ {
+ prevCount = prev->second.count;
+ }
+
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+ // curr.count is the number of keys in
+ // this current 'time slice' from the beginning of it until now
+ // prevCount is the number of keys in the previous
+ // time slice scaled to be one full time slice back from the current
+ // (now) time.
+
+ // compute current, windowed rate
+ F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+ F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+ return averageCount;
+ }
+
// call each time the key wants use
State noteAction(const T& id, S32 weight = 1)
{
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 90dae11793..0bd2609f4a 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
// statics
-BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
+S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded
LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
LLStat::stat_map_t LLStat::sStatList;
@@ -130,6 +130,7 @@ bool LLStatsConfigFile::loadFile()
F32 duration = 0.f;
F32 interval = 0.f;
+ S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
const char * w = "duration";
if (stats_config.has(w))
@@ -141,8 +142,18 @@ bool LLStatsConfigFile::loadFile()
{
interval = (F32)stats_config[w].asReal();
}
+ w = "flags";
+ if (stats_config.has(w))
+ {
+ flags = (S32)stats_config[w].asInteger();
+ if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+ duration > 0)
+ { // No flags passed in, but have a duration, so reset to basic stats
+ flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+ }
+ }
- mStatsp->setReportPerformanceDuration( duration );
+ mStatsp->setReportPerformanceDuration( duration, flags );
mStatsp->setReportPerformanceInterval( interval );
if ( duration > 0 )
@@ -254,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
}
}
-// Set length of performance stat recording
-void LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.
+// If turning stats on, caller must provide flags
+void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
{
if ( seconds <= 0.f )
{
mReportPerformanceStatEnd = 0.0;
- LLPerfBlock::setStatsEnabled( FALSE );
+ LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off
mFrameStatsFile.close();
LLPerfBlock::clearDynamicStats();
}
@@ -269,8 +281,8 @@ void LLPerfStats::setReportPerformanceDuration( F32 seconds )
mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
// Clear failure flag to try and create the log file once
mFrameStatsFileFailure = FALSE;
- LLPerfBlock::setStatsEnabled( TRUE );
mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
+ LLPerfBlock::setStatsFlags(flags);
}
}
@@ -612,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
}
}
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
{
- if (!sStatsEnabled) return;
+ if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+ { // These are off unless the base set is enabled
+ return;
+ }
+
+ initDynamicStat(key);
+}
+
+
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+ if ((sStatsFlags & flags) == 0)
+ {
+ return;
+ }
if (NULL == key2 || strlen(key2) == 0)
{
@@ -630,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
}
}
+// Set up the result data map if dynamic stats are enabled
void LLPerfBlock::initDynamicStat(const std::string& key)
{
// Early exit if dynamic stats aren't enabled.
- if (!sStatsEnabled) return;
+ if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS)
+ return;
mLastPath = sCurrentStatPath; // Save and restore current path
sCurrentStatPath += "/" + key; // Add key to current path
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index 64ea8e5b40..bd73c9a6bb 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -192,14 +192,23 @@ public:
// Use this constructor for pre-defined LLStatTime objects
LLPerfBlock(LLStatTime* stat);
- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
- LLPerfBlock( const char* key1, const char* key2 = NULL);
+ // Use this constructor for normal, optional LLPerfBlock time slices
+ LLPerfBlock( const char* key );
+ // Use this constructor for dynamically created LLPerfBlock time slices
+ // that are only enabled by specific control flags
+ LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
~LLPerfBlock();
- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
- static S32 getStatsEnabled() { return sStatsEnabled; };
+ enum
+ { // Stats bitfield flags
+ LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects
+ LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats
+ LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls
+ };
+ static void setStatsFlags( S32 flags ) { sStatsFlags = flags; };
+ static S32 getStatsFlags() { return sStatsFlags; };
static void clearDynamicStats(); // Reset maps to clear out dynamic objects
static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
@@ -213,7 +222,7 @@ private:
LLStatTime * mPredefinedStat; // LLStatTime object to get data
StatEntry * mDynamicStat; // StatEntryobject to get data
- static BOOL sStatsEnabled; // Normally FALSE
+ static S32 sStatsFlags; // Control what is being recorded
static stat_map_t sStatMap; // Map full path string to LLStatTime objects
static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
};
@@ -236,7 +245,7 @@ public:
BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
- void setReportPerformanceDuration( F32 seconds );
+ void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
void setProcessName(const std::string& process_name) { mProcessName = process_name; }
void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index d7da40d645..8052da2450 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -42,7 +42,7 @@
#include <winnls.h> // for WideCharToMultiByte
#endif
-LLFastTimer::DeclareTimer STRING_LOCALIZATION("String Localization");
+LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
std::string ll_safe_string(const char* in)
@@ -776,12 +776,12 @@ namespace LLStringFn
// https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on
// allowable code points for XML. Specifically, they are:
// 0x09, 0x0a, 0x0d, and 0x20 on up. JC
- std::string strip_invalid_xml(const std::string& input)
+ std::string strip_invalid_xml(const std::string& instr)
{
std::string output;
- output.reserve( input.size() );
- std::string::const_iterator it = input.begin();
- while (it != input.end())
+ output.reserve( instr.size() );
+ std::string::const_iterator it = instr.begin();
+ while (it != instr.end())
{
// Must compare as unsigned for >=
// Test most likely match first
@@ -817,6 +817,320 @@ namespace LLStringFn
}
}
+////////////////////////////////////////////////////////////
+
+//static
+template<>
+void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
+{
+ std::string currToken;
+ std::string::size_type begIdx, endIdx;
+
+ begIdx = instr.find_first_not_of (delims);
+ while (begIdx != std::string::npos)
+ {
+ endIdx = instr.find_first_of (delims, begIdx);
+ if (endIdx == std::string::npos)
+ {
+ endIdx = instr.length();
+ }
+
+ currToken = instr.substr(begIdx, endIdx - begIdx);
+ LLStringUtil::trim (currToken);
+ tokens.push_back(currToken);
+ begIdx = instr.find_first_not_of (delims, endIdx);
+ }
+}
+
+template<>
+LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector<std::string>& tokens)
+{
+ const std::string delims (",");
+
+ // Find the first ]
+ size_type pos2 = instr.find(']', start);
+ if (pos2 == std::string::npos)
+ return std::string::npos;
+
+ // Find the last [ before ]
+ size_type pos1 = instr.find_last_of('[', pos2-1);
+ if (pos1 == std::string::npos || pos1 < start)
+ return std::string::npos;
+
+ getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims);
+ start = pos2+1;
+
+ return pos1;
+}
+
+// static
+template<>
+bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions)
+{
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ format_map_t::const_iterator iter = substitutions.find(token);
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ iter = substitutions.find(std::string("[" + token + "]"));
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+
+ return false;
+}
+
+// static
+template<>
+bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions)
+{
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ if (substitutions.has(token))
+ {
+ replacement = substitutions[token].asString();
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ else if (substitutions.has(std::string("[" + token + "]")))
+ {
+ replacement = substitutions[std::string("[" + token + "]")].asString();
+ return true;
+ }
+
+ return false;
+}
+
+// static
+template<>
+void LLStringUtil::formatNumber(std::string& numStr, std::string decimals)
+{
+ std::stringstream strStream;
+ S32 intDecimals = 0;
+
+ convertToS32 (decimals, intDecimals);
+ if (!sLocale.empty())
+ {
+ strStream.imbue (std::locale(sLocale.c_str()));
+ }
+
+ if (!intDecimals)
+ {
+ S32 intStr;
+
+ if (convertToS32(numStr, intStr))
+ {
+ strStream << intStr;
+ numStr = strStream.str();
+ }
+ }
+ else
+ {
+ F32 floatStr;
+
+ if (convertToF32(numStr, floatStr))
+ {
+ strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
+ numStr = strStream.str();
+ }
+ }
+}
+
+// static
+template<>
+bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
+ std::string param, S32 secFromEpoch)
+{
+ if (param == "local") // local
+ {
+ secFromEpoch -= LLStringOps::getLocalTimeOffset();
+ }
+ else if (param != "utc") // slt
+ {
+ secFromEpoch -= LLStringOps::getSltOffset();
+ }
+
+ // if never fell into those two ifs above, param must be utc
+ if (secFromEpoch < 0) secFromEpoch = 0;
+
+ LLDate * datetime = new LLDate((F64)secFromEpoch);
+ std::string code = LLStringOps::getDatetimeCode (token);
+
+ // special case to handle timezone
+ if (code == "%Z") {
+ if (param == "utc")
+ replacement = "GMT";
+ else if (param == "slt")
+ replacement = "SLT";
+ else if (param != "local") // *TODO Vadim: not local? then what?
+ replacement = LLStringOps::getDaylightSavings() ? "PDT" : "PST";
+
+ return true;
+ }
+ replacement = datetime->toHTTPDateString(code);
+
+ if (code.empty())
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// LLStringUtil::format recogizes the following patterns.
+// All substitutions *must* be encased in []'s in the input string.
+// The []'s are optional in the substitution map.
+// [FOO_123]
+// [FOO,number,precision]
+// [FOO,datetime,format]
+
+
+// static
+template<>
+S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
+{
+ LLFastTimer ft(FT_STRING_FORMAT);
+ S32 res = 0;
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ format_map_t::const_iterator iter = substitutions.find("datetime");
+ if (iter != substitutions.end())
+ {
+ S32 secFromEpoch = 0;
+ BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
+ if (r)
+ {
+ found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
+ }
+ }
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, so leave the string we searched for so that it gets noticed by QA
+ // "hello [NAME_NOT_FOUND]" is output
+ output += std::string("[") + tokens[0] + std::string("]");
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
+}
+
+//static
+template<>
+S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
+{
+ LLFastTimer ft(FT_STRING_FORMAT);
+ S32 res = 0;
+
+ if (!substitutions.isMap())
+ {
+ return res;
+ }
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
+ found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, so leave the string we searched for so that it gets noticed by QA
+ // "hello [NAME_NOT_FOUND]" is output
+ output += std::string("[") + tokens[0] + std::string("]");
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
+}
////////////////////////////////////////////////////////////
// Testing
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index d2de499996..181d6fd33f 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -36,7 +36,6 @@
#include <string>
#include <locale>
#include <iomanip>
-#include <boost/regex.hpp>
#include "llsd.h"
#include "llfasttimer.h"
@@ -231,7 +230,7 @@ public:
static std::basic_string<T> null;
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- static void getTokens (std::basic_string<T> input, std::vector<std::basic_string<T> >& tokens);
+ static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
@@ -346,6 +345,8 @@ public:
static void testHarness();
#endif
+private:
+ static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
};
template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
@@ -604,302 +605,12 @@ namespace LLStringFn
}
////////////////////////////////////////////////////////////
+// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
+// There is no LLWStringUtil::format implementation currently.
+// Calling thse for anything other than LLStringUtil will produce link errors.
-//static
-template<class T>
-void LLStringUtilBase<T>::getTokens (std::basic_string<T> input, std::vector<std::basic_string<T> >& tokens)
-{
- const std::basic_string<T> delims (",");
- std::basic_string<T> currToken;
- size_type begIdx, endIdx;
-
- begIdx = input.find_first_not_of (delims);
- while (begIdx != std::basic_string<T>::npos)
- {
- endIdx = input.find_first_of (delims, begIdx);
- if (endIdx == std::basic_string<T>::npos)
- {
- endIdx = input.length();
- }
-
- currToken = input.substr(begIdx, endIdx - begIdx);
- trim (currToken);
- tokens.push_back(currToken);
- begIdx = input.find_first_not_of (delims, endIdx);
- }
-}
-
-extern LL_COMMON_API LLFastTimer::DeclareTimer STRING_LOCALIZATION;
-
-// static
-template<class T>
-S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& substitutions)
-{
- LLFastTimer ft(STRING_LOCALIZATION);
- S32 res = 0;
-
- std::basic_ostringstream<T> output;
- // match strings like [NAME,number,3]
- const boost::regex key("\\[((\\s)*([0-9_A-Za-z]+)((\\s)*,(\\s)*[0-9_A-Za-z\\s]*){0,2}(\\s)*)]");
-
-
- typename std::basic_string<T>::const_iterator start = s.begin();
- typename std::basic_string<T>::const_iterator end = s.end();
- boost::smatch match;
-
-
- while (boost::regex_search(start, end, match, key, boost::match_default))
- {
- bool found_replacement = false;
- std::vector<std::basic_string<T> > tokens;
- std::basic_string<T> replacement;
-
- getTokens (std::basic_string<T>(match[1].first, match[1].second), tokens);
-
- if (tokens.size() == 1)
- {
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- }
- else if (tokens[1] == "number")
- {
- std::basic_string<T> param = "0";
-
- if (tokens.size() > 2) param = tokens[2];
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- if (found_replacement) formatNumber (replacement, param);
- }
- else if (tokens[1] == "datetime")
- {
- std::basic_string<T> param;
- if (tokens.size() > 2) param = tokens[2];
-
- format_map_t::const_iterator iter = substitutions.find("datetime");
- if (iter != substitutions.end())
- {
- S32 secFromEpoch = 0;
- BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
- if (r)
- {
- found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
- }
- }
- }
-
- if (found_replacement)
- {
- output << std::basic_string<T>(start, match[0].first) << replacement;
- res++;
- }
- else
- {
- // we had no replacement, so leave the string we searched for so that it gets noticed by QA
- // "hello [NAME_NOT_FOUND]" is output
- output << std::basic_string<T>(start, match[0].second);
- }
-
- // update search position
- start = match[0].second;
- }
- // send the remainder of the string (with no further matches for bracketed names)
- output << std::basic_string<T>(start, end);
- s = output.str();
- return res;
-}
-
-//static
-template<class T>
-S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const LLSD& substitutions)
-{
- LLFastTimer ft(STRING_LOCALIZATION);
-
- S32 res = 0;
-
- if (!substitutions.isMap())
- {
- return res;
- }
-
- std::basic_ostringstream<T> output;
- // match strings like [NAME,number,3]
- const boost::regex key("\\[((\\s)*([0-9_A-Za-z]+)((\\s)*,(\\s)*[0-9_A-Za-z\\s]*){0,2}(\\s)*)]");
-
-
- typename std::basic_string<T>::const_iterator start = s.begin();
- typename std::basic_string<T>::const_iterator end = s.end();
- boost::smatch match;
-
-
- while (boost::regex_search(start, end, match, key, boost::match_default))
- {
- bool found_replacement = false;
- std::vector<std::basic_string<T> > tokens;
- std::basic_string<T> replacement;
-
- getTokens (std::basic_string<T>(match[1].first, match[1].second), tokens);
-
- if (tokens.size() == 1)
- {
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- }
- else if (tokens[1] == "number")
- {
- std::basic_string<T> param = "0";
-
- if (tokens.size() > 2) param = tokens[2];
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- if (found_replacement) formatNumber (replacement, param);
- }
- else if (tokens[1] == "datetime")
- {
- std::basic_string<T> param;
- if (tokens.size() > 2) param = tokens[2];
-
- S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
- found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
- }
-
- if (found_replacement)
- {
- output << std::basic_string<T>(start, match[0].first) << replacement;
- res++;
- }
- else
- {
- // we had no replacement, so leave the string we searched for so that it gets noticed by QA
- // "hello [NAME_NOT_FOUND]" is output
- output << std::basic_string<T>(start, match[0].second);
- }
-
- // update search position
- start = match[0].second;
- }
- // send the remainder of the string (with no further matches for bracketed names)
- output << std::basic_string<T>(start, end);
- s = output.str();
- return res;
-}
-
-// static
-template<class T>
-bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const format_map_t& substitutions)
-{
- // see if we have a replacement for the bracketed string (without the brackets)
- // test first using has() because if we just look up with operator[] we get back an
- // empty string even if the value is missing. We want to distinguish between
- // missing replacements and deliberately empty replacement strings.
- format_map_t::const_iterator iter = substitutions.find(token);
- if (iter != substitutions.end())
- {
- replacement = iter->second;
- return true;
- }
- // if not, see if there's one WITH brackets
- iter = substitutions.find(std::basic_string<T>("[" + token + "]"));
- if (iter != substitutions.end())
- {
- replacement = iter->second;
- return true;
- }
-
- return false;
-}
-
-// static
-template<class T>
-bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const LLSD& substitutions)
-{
- // see if we have a replacement for the bracketed string (without the brackets)
- // test first using has() because if we just look up with operator[] we get back an
- // empty string even if the value is missing. We want to distinguish between
- // missing replacements and deliberately empty replacement strings.
- if (substitutions.has(token))
- {
- replacement = substitutions[token].asString();
- return true;
- }
- // if not, see if there's one WITH brackets
- else if (substitutions.has(std::basic_string<T>("[" + token + "]")))
- {
- replacement = substitutions[std::basic_string<T>("[" + token + "]")].asString();
- return true;
- }
-
- return false;
-}
-
-// static
-template<class T>
-void LLStringUtilBase<T>::formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals)
-{
- typedef typename std::basic_string<T>::size_type string_size_type_t;
- std::basic_stringstream<T> strStream;
- S32 intDecimals = 0;
-
- convertToS32 (decimals, intDecimals);
- if (!sLocale.empty())
- {
- strStream.imbue (std::locale(sLocale.c_str()));
- }
-
- if (!intDecimals)
- {
- S32 intStr;
-
- if (convertToS32(numStr, intStr))
- {
- strStream << intStr;
- numStr = strStream.str();
- }
- }
- else
- {
- F32 floatStr;
-
- if (convertToF32(numStr, floatStr))
- {
- strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
- numStr = strStream.str();
- }
- }
-}
-
-// static
-template<class T>
-bool LLStringUtilBase<T>::formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token,
- std::basic_string<T> param, S32 secFromEpoch)
-{
- if (param == "local") // local
- {
- secFromEpoch -= LLStringOps::getLocalTimeOffset();
- }
- else if (param != "utc") // slt
- {
- secFromEpoch -= LLStringOps::getSltOffset();
- }
-
- // if never fell into those two ifs above, param must be utc
- if (secFromEpoch < 0) secFromEpoch = 0;
-
- LLDate * datetime = new LLDate((F64)secFromEpoch);
- std::string code = LLStringOps::getDatetimeCode (token);
-
- // special case to handle timezone
- if (code == "%Z") {
- if (param == "utc") replacement = "GMT";
- else if (param != "local") replacement = LLStringOps::getDaylightSavings()? "PDT" : "PST";
- return true;
- }
+////////////////////////////////////////////////////////////
- replacement = datetime->toHTTPDateString(code);
- if (code.empty())
- {
- return false;
- }
- else
- {
- return true;
- }
-}
// static
template<class T>
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index e9e21cffb6..77a03879bf 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,9 +34,9 @@
#define LL_LLVERSIONSERVER_H
const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 29;
+const S32 LL_VERSION_MINOR = 31;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 2425;
+const S32 LL_VERSION_BUILD = 2639;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 04cf98ce19..ccea101cd6 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -36,7 +36,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 2425;
+const S32 LL_VERSION_BUILD = 2639;
const char * const LL_CHANNEL = "Second Life 2009";
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
index 79a536a224..5ad230d1d5 100644
--- a/indra/llcommon/metapropertyt.h
+++ b/indra/llcommon/metapropertyt.h
@@ -94,6 +94,13 @@ inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* obje
}
template <>
+inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
+{
+ checkObjectClass(object);
+ return NULL;
+}
+
+template <>
inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
{
return *(getProperty(object));
@@ -111,6 +118,12 @@ inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
return *(getProperty(object));
}
+template <>
+inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
+{
+ return *(getProperty(object));
+}
+
template<class TObject, class TProperty>
class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
{
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 363486fb9c..2352c8edd7 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mMaxBytes(0),
mRawDiscardLevel(-1),
mRate(0.0f),
- mReversible(FALSE)
-
+ mReversible(FALSE),
+ mAreaUsedForDataSizeCalcs(0)
{
//We assume here that if we wanted to create via
//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
}
mImpl = j2cimpl_create_func();
+
+ // Clear data size table
+ for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+ { // Array size is MAX_DISCARD_LEVEL+1
+ mDataSizes[i] = 0;
+ }
}
// virtual
@@ -367,9 +373,45 @@ S32 LLImageJ2C::calcHeaderSize()
return calcHeaderSizeJ2C();
}
+
+// calcDataSize() returns how many bytes to read
+// to load discard_level (including header and higher discard levels)
S32 LLImageJ2C::calcDataSize(S32 discard_level)
{
- return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+ discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+ if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth())
+ || mDataSizes[0] == 0)
+ {
+ mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ {
+ mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ level--;
+ }
+
+ /* This is technically a more correct way to calculate the size required
+ for each discard level, since they should include the size needed for
+ lower levels. Unfortunately, this doesn't work well and will lead to
+ download stalls. The true correct way is to parse the header. This will
+ all go away with http textures at some point.
+
+ // Calculate the size for each discard level. Lower levels (higher quality)
+ // contain the cumulative size of higher levels
+ S32 total_size = calcHeaderSizeJ2C();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ { // Add in this discard level and all before it
+ total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ mDataSizes[level] = total_size;
+ level--;
+ }
+ */
+ }
+ return mDataSizes[discard_level];
}
S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd1..55df7f4429 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ protected:
void updateRawDiscardLevel();
S32 mMaxBytes; // Maximum number of bytes of data to use...
+
+ S32 mDataSizes[MAX_DISCARD_LEVEL+1]; // Size of data required to reach a given level
+ U32 mAreaUsedForDataSizeCalcs; // Height * width used to calculate mDataSizes
+
S8 mRawDiscardLevel;
F32 mRate;
BOOL mReversible;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e2a77f1d1e..5d3fbe5128 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -458,6 +458,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
mCreationDate = creation_date_utc;
}
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+ // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags
+ // because we now detect when they should be set.
+ setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+ // Enforce the PERM_OVERWRITE flags for any masks that are different
+ // but only for AT_OBJECT's since that is the only asset type that can
+ // exist in-world (instead of only in-inventory or in-object-contents).
+ if (LLAssetType::AT_OBJECT == getType())
+ {
+ LLPermissions old_permissions = old_item.getPermissions();
+ U32 flags_to_be_set = 0;
+ if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ LLSaleInfo old_sale_info = old_item.getSaleInfo();
+ if(old_sale_info != getSaleInfo())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ }
+ setFlags(getFlags() | flags_to_be_set);
+ }
+}
const LLSaleInfo& LLInventoryItem::getSaleInfo() const
{
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 2b4d8ed831..bd581e860f 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -93,14 +93,13 @@ public:
virtual const LLUUID& getUUID() const;
const LLUUID& getParentUUID() const;
virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
-
virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
BOOL getIsLinkType() const;
// mutators - will not call updateServer();
void setUUID(const LLUUID& new_uuid);
- void rename(const std::string& new_name);
+ virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
void setType(LLAssetType::EType type);
@@ -263,6 +262,10 @@ public:
void setInventoryType(LLInventoryType::EType inv_type);
void setFlags(U32 flags);
void setCreationDate(time_t creation_date_utc);
+
+ // Check for changes in permissions masks and sale info
+ // and set the corresponding bits in mFlags
+ void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
// This is currently only used in the Viewer to handle calling cards
// where the creator is actually used to store the target.
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index aa8391230c..2a9a596912 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -136,9 +136,9 @@ class LLSD;
class LLAccessEntry
{
public:
- LLUUID mID;
- S32 mTime;
- U32 mFlags;
+ LLUUID mID; // Agent ID
+ S32 mTime; // Time (unix seconds) when entry expires
+ U32 mFlags; // Not used - currently should always be zero
};
typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 0babf26457..d2e5034734 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -288,6 +288,17 @@ BOOL LLPermissions::setOwnerAndGroup(
return allowed;
}
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now,
+//limiting the functionality of this routine to objects which are
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+ if (isGroupOwned())
+ mLastOwner = last_owner;
+}
+
+
// only call this if you know what you're doing
// there are usually perm-bit consequences when the
// ownerhsip changes
@@ -895,6 +906,8 @@ void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
{
reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
+ reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
+ reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
}
// virtual
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 864088148f..d5a0881c8f 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -232,6 +232,10 @@ public:
// ownerhsip changes
void yesReallySetOwner(const LLUUID& owner, bool group_owned);
+ // Last owner doesn't have much in the way of permissions so it's
+ //not too dangerous to do this.
+ void setLastOwner(const LLUUID& last_owner);
+
// saves last owner, sets owner to uuid null, sets group
// owned. group_id must be the group of the object (that's who it
// is being deeded to) and the object must be group
diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h
index 1cb7308bd4..2c699bcb87 100644
--- a/indra/llinventory/lltransactiontypes.h
+++ b/indra/llinventory/lltransactiontypes.h
@@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE = 2003;
const S32 TRANS_GROUP_TAX = 2004; // Taxes incurred as part of group membership
const S32 TRANS_CLASSIFIED_RENEW = 2005;
+// Codes 2100-2999 reserved for recurring billing services
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC = 2100;
+
// Codes 3000-3999 reserved for inventory transactions
const S32 TRANS_GIVE_INVENTORY = 3000;
@@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS = 5007;
const S32 TRANS_PAY_OBJECT = 5008;
const S32 TRANS_OBJECT_PAYS = 5009;
+// Codes 5100-5999 reserved for recurring billing transfers between users
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC_USER = 5100;
+
// Codes 6000-6999 reserved for group transactions
//const S32 TRANS_GROUP_JOIN = 6000; //reserved for future use
const S32 TRANS_GROUP_LAND_DEED = 6001;
diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h
index 9d46a8b454..9e38fddbd7 100644
--- a/indra/llmath/llcoord.h
+++ b/indra/llmath/llcoord.h
@@ -59,8 +59,11 @@ public:
{}
LLCoordGL(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordGL& other) const { return !(*this == other); }
};
+//bool operator ==(const LLCoordGL& a, const LLCoordGL& b);
// Window coords include things like window borders,
// menu regions, etc.
@@ -71,6 +74,8 @@ public:
{}
LLCoordWindow(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordWindow& other) const { return !(*this == other); }
};
@@ -82,6 +87,8 @@ public:
{}
LLCoordScreen(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordScreen& other) const { return !(*this == other); }
};
class LLCoordFont : public LLCoord
@@ -96,6 +103,8 @@ public:
void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; }
void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; }
+ bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordFont& other) const { return !(*this == other); }
};
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec4..fdcc19d657 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void LLQuaternion::quantize16(F32 lower, F32 upper)
mQ[VZ] = z;
mQ[VS] = s;
- normQuat();
+ normalize();
}
void LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
- normQuat();
+ normalize();
}
// LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
//#endif
//
-// normQuat();
+// normalize();
// return (*this);
}
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2e..0769f29f23 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
return a;
}
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
inline F32 LLQuaternion::normalize()
{
F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ // Floating point error can prevent some quaternions from achieving
+ // exact unity length. When trying to renormalize such quaternions we
+ // can oscillate between multiple quantized states. To prevent such
+ // drifts we only renomalize if the length is far enough from unity.
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
+ // we were given a very bad quaternion so we set it to identity
mQ[VX] = 0.f;
mQ[VY] = 0.f;
mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32 LLQuaternion::normQuat()
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ // only renormalize if length not close enough to 1.0 already
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 571b2fc3c6..3eceda7901 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,7 @@
project(llmessage)
include(00-Common)
+include(GoogleMock)
include(LLAddBuildTest)
include(LLCommon)
include(LLMath)
@@ -223,6 +224,7 @@ IF (NOT LINUX AND VIEWER)
# llhttpclientadapter.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
+ llregionpresenceverifier.cpp
)
# set(TEST_DEBUG on)
@@ -232,6 +234,7 @@ IF (NOT LINUX AND VIEWER)
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(
@@ -244,3 +247,4 @@ IF (NOT LINUX AND VIEWER)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 792f1aeb0a..8641437d86 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -100,7 +100,6 @@ public:
// LEGACY
boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
-
// This method needs to be called from time to time to send out
// requests.
void processPending();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a4af8e989b..5ff41322b7 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -131,7 +131,7 @@ void LLCurl::Responder::errorWithContent(
// virtual
void LLCurl::Responder::error(U32 status, const std::string& reason)
{
- llinfos << status << ": " << reason << llendl;
+ llinfos << mURL << " [" << status << "]: " << reason << llendl;
}
// virtual
@@ -139,6 +139,11 @@ void LLCurl::Responder::result(const LLSD& content)
{
}
+void LLCurl::Responder::setURL(const std::string& url)
+{
+ mURL = url;
+}
+
// virtual
void LLCurl::Responder::completedRaw(
U32 status,
@@ -148,7 +153,11 @@ void LLCurl::Responder::completedRaw(
{
LLSD content;
LLBufferStream istr(channels, buffer.get());
- LLSDSerialize::fromXML(content, istr);
+ if (!LLSDSerialize::fromXML(content, istr))
+ {
+ llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+ }
+
completed(status, reason, content);
}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fbd3077cbf..0b58e7c4a5 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -120,8 +120,14 @@ public:
// of the header can be parsed. In the ::completed call above only the body is contained in the LLSD.
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
+ // Used internally to set the url for debugging later.
+ void setURL(const std::string& url);
+
public: /* but not really -- don't touch this */
U32 mReferenceCount;
+
+ private:
+ std::string mURL;
};
typedef boost::intrusive_ptr<Responder> ResponderPtr;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5ca..12ecbb36eb 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -265,6 +265,11 @@ static void request(
}
}
+ if (responder)
+ {
+ responder->setURL(url);
+ }
+
req->setCallback(new LLHTTPClientURLAdaptor(responder));
if (method == LLURLRequest::HTTP_POST && gMessageSystem)
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index b6988224ce..9d3c83f828 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadapter.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 7f76390d0c..a205a2f260 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadepter.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 42a8e5cd0a..085a59cf27 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index a00dbd1809..97134bd336 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -521,7 +521,7 @@ protected:
* seek orfor string assignment.
* @returns Returns true if a line was found.
*/
- bool readLine(
+ bool readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -592,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
//lldebugs << "destroying LLHTTPResponder" << llendl;
}
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -670,7 +670,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
#endif
PUMP_DEBUG;
- if(readLine(channels, buffer, (U8*)buf, len))
+ if(readHeaderLine(channels, buffer, (U8*)buf, len))
{
bool read_next_line = false;
bool parse_all = true;
@@ -734,7 +734,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
if(read_next_line)
{
len = HEADER_BUFFER_SIZE;
- readLine(channels, buffer, (U8*)buf, len);
+ if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ // Failed to read the header line, probably too long.
+ // readHeaderLine already marked the channel/buffer as bad.
+ keep_parsing = false;
+ break;
+ }
}
if(0 == len)
{
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8..ce206d8d7d 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
// static
bool LLMail::send(
const std::string& header,
- const std::string& message,
+ const std::string& raw_message,
const char* from_address,
const char* to_address)
{
@@ -276,8 +276,20 @@ bool LLMail::send(
return false;
}
- // *FIX: this translation doesn't deal with a single period on a
- // line by itself.
+ // remove any "." SMTP commands to prevent injection (DEV-35777)
+ // we don't need to worry about "\r\n.\r\n" because of the
+ // "\n" --> "\n\n" conversion going into rfc2822_msg below
+ std::string message = raw_message;
+ std::string bad_string = "\n.\n";
+ std::string good_string = "\n..\n";
+ while (1)
+ {
+ int index = message.find(bad_string);
+ if (index == std::string::npos) break;
+ message.replace(index, bad_string.size(), good_string);
+ }
+
+ // convert all "\n" into "\r\n"
std::ostringstream rfc2822_msg;
for(U32 i = 0; i < message.size(); ++i)
{
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 119eb1d7f7..af6733fa05 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llmessagesenderinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index e6be4af07b..b1868e6a00 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -38,11 +38,40 @@
#include "net.h"
#include "message.h"
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+ {
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
{
}
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+ uri,
+ ResponsePtr data,
+ S32 retry_count) :
+ mUri(uri),
+ mSharedData(data),
+ mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
{
@@ -51,30 +80,36 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
LLHost destination(host, port);
LLUUID id = content["region_id"];
- llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+ lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
std::stringstream uri;
uri << "http://" << destination.getString() << "/state/basic/";
- mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+ mSharedData->getHttpClient().get(
+ uri.str(),
+ new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
}
-void LLRegionPresenceVerifier::RegionResponder::completed(
- U32 status,
- const std::string& reason,
- const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+ const std::string& reason)
{
- LLHTTPClient::Responder::completed(status, reason, content);
-
- mSharedData->onCompletedRegionRequest();
+ // TODO: babbage: distinguish between region presence service and
+ // region verification errors?
+ mSharedData->onRegionVerificationFailed();
}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+ S32 retry_count):
+ mUri(uri),
+ mSharedData(data),
+ mContent(content),
+ mRetryCount(retry_count)
{
}
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
{
@@ -89,13 +124,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
{
mSharedData->onRegionVerified(mContent);
}
- else if (mSharedData->shouldRetry())
+ else if (mRetryCount > 0)
{
retry();
}
else
{
- llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+ llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
}
}
@@ -103,13 +139,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
{
LLSD headers;
headers["Cache-Control"] = "no-cache, max-age=0";
- llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
- mSharedData->decrementRetries();
- mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+ llinfos << "Requesting region information, get uncached for region "
+ << mUri << llendl;
+ --mRetryCount;
+ mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
{
- retry();
+ if(mRetryCount > 0)
+ {
+ retry();
+ }
+ else
+ {
+ llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
+ }
}
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index 54ad6226d6..f57a62a731 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -37,7 +37,7 @@
#include "llhttpclient.h"
#include <string>
#include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface;
@@ -47,49 +47,58 @@ public:
class Response
{
public:
- virtual ~Response() {}
+ virtual ~Response() = 0;
virtual bool checkValidity(const LLSD& content) const = 0;
virtual void onRegionVerified(const LLSD& region_details) = 0;
-
- virtual void decrementRetries() = 0;
+ virtual void onRegionVerificationFailed() = 0;
virtual LLHTTPClientInterface& getHttpClient() = 0;
- virtual std::string getRegionUri() const = 0;
- virtual bool shouldRetry() const = 0;
- virtual void onCompletedRegionRequest() {}
+ public: /* but not really -- don't touch this */
+ U32 mReferenceCount;
};
- typedef boost::shared_ptr<Response> ResponsePtr;
+ typedef boost::intrusive_ptr<Response> ResponsePtr;
class RegionResponder : public LLHTTPClient::Responder
{
public:
- RegionResponder(ResponsePtr data);
+ RegionResponder(const std::string& uri, ResponsePtr data,
+ S32 retry_count);
+ virtual ~RegionResponder();
virtual void result(const LLSD& content);
- virtual void completed(
- U32 status,
- const std::string& reason,
- const LLSD& content);
+ virtual void error(U32 status, const std::string& reason);
private:
ResponsePtr mSharedData;
+ std::string mUri;
+ S32 mRetryCount;
};
class VerifiedDestinationResponder : public LLHTTPClient::Responder
{
public:
- VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+ VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+ const LLSD& content, S32 retry_count);
+ virtual ~VerifiedDestinationResponder();
virtual void result(const LLSD& content);
virtual void error(U32 status, const std::string& reason);
+
private:
void retry();
ResponsePtr mSharedData;
LLSD mContent;
+ std::string mUri;
+ S32 mRetryCount;
};
};
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 32cbb15cb3..d6b2f45d04 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 5069c2cb2e..359e4c5aea 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.h
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62..0872efba50 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
return changed;
}
+// Return bits available in the channel
+S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+ S32 retval = 0;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+ if (bits_available >= lookahead_bits)
+ {
+ retval = (S32) gThrottleMaximumBPS[throttle_cat];
+ }
+ else
+ {
+ retval = (S32) bits_available;
+ }
+
+ return retval;
+}
+
BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
{
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb2..47a7c653b2 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ public:
BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different
+ S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
+
void packThrottle(LLDataPacker &dp) const;
void unpackThrottle(LLDataPacker &dp);
public:
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 5a1cd95ffc..41f3f3f607 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_GESTURE:
- case LLAssetType::AT_FAVORITE:
rv = true;
break;
default:
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb..81b7761ed5 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
* String constants
*/
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
//llinfos << "LLURLRequest::process_impl()" << llendl;
- if(!buffer) return STATUS_ERROR;
+ if (!buffer) return STATUS_ERROR;
+
+ // we're still waiting or prcessing, check how many
+ // bytes we have accumulated.
+ const S32 MIN_ACCUMULATION = 100000;
+ if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+ {
+ // This is a pretty sloppy calculation, but this
+ // tries to make the gross assumption that if data
+ // is coming in at 56kb/s, then this transfer will
+ // probably succeed. So, if we're accumlated
+ // 100,000 bytes (MIN_ACCUMULATION) then let's
+ // give this client another 2s to complete.
+ const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+ mDetail->mByteAccumulator = 0;
+ pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+ lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+ if (mState == STATE_INITIALIZED)
+ {
+ llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+ }
+ }
+
switch(mState)
{
case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
bool newmsg = mDetail->mCurlRequest->getResult(&result);
if(!newmsg)
{
- // we're still waiting or prcessing, check how many
- // bytes we have accumulated.
- const S32 MIN_ACCUMULATION = 100000;
- if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
- {
- // This is a pretty sloppy calculation, but this
- // tries to make the gross assumption that if data
- // is coming in at 56kb/s, then this transfer will
- // probably succeed. So, if we're accumlated
- // 100,000 bytes (MIN_ACCUMULATION) then let's
- // give this client another 2s to complete.
- const F32 TIMEOUT_ADJUSTMENT = 2.0f;
- mDetail->mByteAccumulator = 0;
- pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
- }
-
// keep processing
break;
}
mState = STATE_HAVE_RESPONSE;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
switch(result)
{
case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
// we already stuffed everything into channel in in the curl
// callback, so we are done.
eos = true;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_DONE;
default:
PUMP_DEBUG;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_ERROR;
}
}
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+ mRequestTransferedBytes = 0;
+ mResponseTransferedBytes = 0;
}
bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mResponseTransferedBytes += bytes;
req->mDetail->mByteAccumulator += bytes;
return bytes;
}
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
req->mDetail->mLastRead,
(U8*)data,
bytes);
+ req->mRequestTransferedBytes += bytes;
return bytes;
}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085..cb3c466440 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
#include "llchainio.h"
#include "llerror.h"
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
class LLURLRequestDetail;
class LLURLRequestComplete;
@@ -208,6 +214,8 @@ protected:
ERequestAction mAction;
LLURLRequestDetail* mDetail;
LLIOPipe::ptr_t mCompletionCallback;
+ S32 mRequestTransferedBytes;
+ S32 mResponseTransferedBytes;
private:
/**
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 08c9192c9f..209bdb2249 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix)
static bool verify_cache_filename(const std::string& filename)
{
//NOTE: This routine is only used to check file names that our own
- // code places in the cache directory. As such, it can be limited
- // to this very restrictive file name pattern. It does not need to
- // handle other characters.
-
+ // code places in the cache directory. As such, it can be limited
+ // to this very restrictive file name pattern. It does not need to
+ // handle other characters. The only known uses of this are (with examples):
+ // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+ // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+ // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+
+ //IMPORTANT: Do not broaden the filenames accepted by this routine
+ // without careful analysis. Anything allowed by this function can
+ // be downloaded by the viewer.
+
size_t len = filename.size();
- //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>");
- if (len < 1 || len > 50)
- {
+ //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+ if (len < 5 || len > 50)
+ {
return false;
}
- for(unsigned i=0; i<len; ++i)
- {
+ for(size_t i=0; i<(len-4); ++i)
+ {
char c = filename[i];
- bool ok = isalnum(c);
- if (!ok && i > 0)
- {
- ok = '_'==c || '-'==c || '.'==c;
- }
+ bool ok = isalnum(c) || '_'==c || '-'==c;
if (!ok)
{
return false;
}
}
- return true;
+ return filename[len-4] == '.'
+ && filename[len-3] == 't'
+ && filename[len-2] == 'm'
+ && filename[len-1] == 'p';
}
void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000..2f55e97fcc
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+ MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+ MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+ MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+ bool operator()(LLCurl::ResponderPtr ptr) const
+ {
+ T* p = dynamic_cast<T*>(ptr.get());
+ return p != NULL;
+ }
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+ std::ostringstream ls, rs;
+ ls << l;
+ rs << r;
+ return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000..c86126406e
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+ virtual bool checkValidity(const LLSD& content) const
+ {
+ return true;
+ }
+
+ virtual void onRegionVerified(const LLSD& region_details)
+ {
+ }
+
+ virtual void onRegionVerificationFailed()
+ {
+ }
+
+ virtual LLHTTPClientInterface& getHttpClient()
+ {
+ return mHttpInterface;
+ }
+
+ LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+ struct LLRegionPresenceVerifierData
+ {
+ LLRegionPresenceVerifierData() :
+ mResponse(new LLTestResponse()),
+ mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+ LLSD(), 3)
+ {
+ }
+
+ LLTestResponse* mResponse;
+ LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+ };
+
+ typedef test_group<LLRegionPresenceVerifierData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+ // Test that VerifiedDestinationResponder does retry
+ // on error when shouldRetry returns true.
+ template<> template<>
+ void object::test<1>()
+ {
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+ }
+
+ // Test that VerifiedDestinationResponder only retries
+ // on error until shouldRetry returns false.
+ template<> template<>
+ void object::test<2>()
+ {
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+ }
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 7a8586fe2f..665a423d07 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -32,7 +32,7 @@
#ifndef LL_LLPLUGINCLASSMEDIA_H
#define LL_LLPLUGINCLASSMEDIA_H
-#include "llgl.h"
+#include "llgltypes.h"
#include "llpluginprocessparent.h"
#include "llrect.h"
#include "llpluginclassmediaowner.h"
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index 3ae176cbeb..df6de0925e 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -32,7 +32,6 @@
#ifndef LL_LLPLUGINCLASSMEDIAOWNER_H
#define LL_LLPLUGINCLASSMEDIAOWNER_H
-#include "llgl.h"
#include "llpluginprocessparent.h"
#include "llrect.h"
#include <queue>
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 9b0fd81ed3..9d84d3706b 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
U32 old_face_mask = mVolumep->mFaceMask;
+ S32 face_bit = 0;
+ S32 cur_mask = 0;
+
+ // Grab copies of the old faces from the original shape, ordered by type.
+ // We will use these to figure out what old texture info gets mapped to new
+ // faces in the new shape.
+ std::vector<LLProfile::Face> old_faces;
+ for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+ {
+ old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+ }
+
+ // Copy the old texture info off to the side, but not in the order in which
+ // they live in the mTextureList, rather in order of ther "face id" which
+ // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+ //
+ // Hence, some elements of old_tes::mEntryList will be invalid. It is
+ // initialized to a size of 9 (max number of possible faces on a volume?)
+ // and only the ones with valid types are filled in.
+ LLPrimTextureList old_tes;
+ old_tes.setSize(9);
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (old_face_mask & cur_mask)
+ {
+ S32 te_index = face_index_from_id(cur_mask, old_faces);
+ old_tes.copyTexture(face_bit, *(getTE(te_index)));
+ //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+ }
+ }
+
+
// build the new object
sVolumeManager->unrefVolume(mVolumep);
mVolumep = volumep;
U32 new_face_mask = mVolumep->mFaceMask;
- if (old_face_mask != new_face_mask)
+ S32 i;
+
+ if (old_face_mask == new_face_mask)
+ {
+ // nothing to do
+ return TRUE;
+ }
+
+ if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
{
+ llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
setNumTEs(mVolumep->getNumFaces());
+ return TRUE;
+ }
+
+ // initialize face_mapping
+ S32 face_mapping[9];
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ face_mapping[face_bit] = face_bit;
+ }
+
+ // The new shape may have more faces than the original, but we can't just
+ // add them to the end -- the ordering matters and it may be that we must
+ // insert the new faces in the middle of the list. When we add a face it
+ // will pick up the texture/color info of one of the old faces an so we
+ // now figure out which old face info gets mapped to each new face, and
+ // store in the face_mapping lookup table.
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (!(new_face_mask & cur_mask))
+ {
+ // Face doesn't exist in new map.
+ face_mapping[face_bit] = -1;
+ continue;
+ }
+ else if (old_face_mask & cur_mask)
+ {
+ // Face exists in new and old map.
+ face_mapping[face_bit] = face_bit;
+ continue;
+ }
+
+ // OK, how we've got a mismatch, where we have to fill a new face with one from
+ // the old face.
+ if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+ {
+ // It's a top/bottom/hollow interior face.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+ {
+ // A cut slice. Use the hollow interior if we have it.
+ if (old_face_mask & LL_FACE_INNER_SIDE)
+ {
+ face_mapping[face_bit] = 2;
+ continue;
+ }
+
+ // No interior, use the bottom face.
+ // Could figure out which of the outer faces was nearest, but that would be harder.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ // OK, the face that's missing is an outer face...
+ // Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+ S32 cur_outer = face_bit - 5;
+ S32 min_dist = 5;
+ S32 min_outer_bit = -1;
+ S32 i;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+ {
+ S32 dist = abs(i - cur_outer);
+ if (dist < min_dist)
+ {
+ min_dist = dist;
+ min_outer_bit = i + 5;
+ }
+ }
+ }
+ if (-1 == min_outer_bit)
+ {
+ llinfos << (LLVolume *)mVolumep << llendl;
+ llwarns << "Bad! No outer faces, impossible!" << llendl;
+ }
+ face_mapping[face_bit] = min_outer_bit;
}
+
+
+ setNumTEs(mVolumep->getNumFaces());
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ // For each possible face type on the new shape we check to see if that
+ // face exists and if it does we create a texture entry that is a copy
+ // of one of the originals. Since the originals might not have a
+ // matching face, we use the face_mapping lookup table to figure out
+ // which face information to copy.
+ cur_mask = 0x1 << face_bit;
+ if (new_face_mask & cur_mask)
+ {
+ if (-1 == face_mapping[face_bit])
+ {
+ llwarns << "No mapping from old face to new face!" << llendl;
+ }
+ S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+ setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+ }
+ }
return TRUE;
}
@@ -1314,6 +1499,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 16);
case PARAMS_SCULPT:
return (size == 17);
+ case PARAMS_LIGHT_IMAGE:
+ return (size == 28);
}
return FALSE;
@@ -1646,3 +1833,79 @@ bool LLSculptParams::fromLLSD(LLSD& sd)
return false;
}
+//============================================================================
+
+LLLightImageParams::LLLightImageParams()
+{
+ mType = PARAMS_LIGHT_IMAGE;
+ mParams.setVec(F_PI*0.5f, 0.f, 0.f);
+}
+
+BOOL LLLightImageParams::pack(LLDataPacker &dp) const
+{
+ dp.packUUID(mLightTexture, "texture");
+ dp.packVector3(mParams, "params");
+
+ return TRUE;
+}
+
+BOOL LLLightImageParams::unpack(LLDataPacker &dp)
+{
+ dp.unpackUUID(mLightTexture, "texture");
+ dp.unpackVector3(mParams, "params");
+
+ return TRUE;
+}
+
+bool LLLightImageParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_LIGHT_IMAGE)
+ {
+ return false;
+ }
+
+ const LLLightImageParams *param = (const LLLightImageParams*)&data;
+ if ( (param->mLightTexture != mLightTexture) )
+ {
+ return false;
+ }
+
+ if ( (param->mParams != mParams ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void LLLightImageParams::copy(const LLNetworkData& data)
+{
+ const LLLightImageParams *param = (LLLightImageParams*)&data;
+ mLightTexture = param->mLightTexture;
+ mParams = param->mParams;
+}
+
+
+
+LLSD LLLightImageParams::asLLSD() const
+{
+ LLSD sd;
+
+ sd["texture"] = mLightTexture;
+ sd["params"] = mParams.getValue();
+
+ return sd;
+}
+
+bool LLLightImageParams::fromLLSD(LLSD& sd)
+{
+ if (sd.has("texture"))
+ {
+ setLightTexture( sd["texture"] );
+ setParams( LLVector3( sd["params"] ) );
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index b3a337ce5d..53095cc925 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -107,7 +107,8 @@ public:
{
PARAMS_FLEXIBLE = 0x10,
PARAMS_LIGHT = 0x20,
- PARAMS_SCULPT = 0x30
+ PARAMS_SCULPT = 0x30,
+ PARAMS_LIGHT_IMAGE = 0x40,
};
public:
@@ -267,6 +268,28 @@ public:
U8 getSculptType() { return mSculptType; }
};
+class LLLightImageParams : public LLNetworkData
+{
+protected:
+ LLUUID mLightTexture;
+ LLVector3 mParams;
+
+public:
+ LLLightImageParams();
+ /*virtual*/ BOOL pack(LLDataPacker &dp) const;
+ /*virtual*/ BOOL unpack(LLDataPacker &dp);
+ /*virtual*/ bool operator==(const LLNetworkData& data) const;
+ /*virtual*/ void copy(const LLNetworkData& data);
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setLightTexture(const LLUUID& id) { mLightTexture = id; }
+ LLUUID getLightTexture() const { return mLightTexture; }
+ void setParams(const LLVector3& params) { mParams = params; }
+ LLVector3 getParams() const { return mParams; }
+
+};
class LLPrimitive : public LLXform
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index d03150fc78..1c7de95975 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -135,13 +135,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
{
if (S32(index) >= mEntryList.size())
{
- // TODO -- assert here
S32 current_size = mEntryList.size();
- llerrs << "index = " << S32(index) << " current_size = " << current_size << llendl;
+ llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl;
return TEM_CHANGE_NONE;
}
- // we're changing an existing entry
+ // we're changing an existing entry
llassert(mEntryList[index]);
delete (mEntryList[index]);
if (&te)
@@ -387,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
mEntryList.resize(new_size);
for (S32 index = current_size; index < new_size; ++index)
{
- LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
- mEntryList[index] = new_entry;
+ if (current_size > 0
+ && mEntryList[current_size - 1])
+ {
+ // copy the last valid entry for the new one
+ mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+ }
+ else
+ {
+ // no valid enries to copy, so we new one up
+ LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+ mEntryList[index] = new_entry;
+ }
}
}
else if (new_size < current_size)
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index 052510e6ed..f01878642a 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -37,13 +37,13 @@
LLFontBitmapCache::LLFontBitmapCache():
mNumComponents(0),
- mMaxCharWidth(0),
- mMaxCharHeight(0),
mBitmapWidth(0),
mBitmapHeight(0),
+ mBitmapNum(-1),
+ mMaxCharWidth(0),
+ mMaxCharHeight(0),
mCurrentOffsetX(1),
- mCurrentOffsetY(1),
- mCurrentBitmapNum(-1)
+ mCurrentOffsetY(1)
{
}
@@ -160,10 +160,10 @@ void LLFontBitmapCache::reset()
mImageRawVec.clear();
mImageGLVec.clear();
- mBitmapWidth = 0,
- mBitmapHeight = 0,
- mCurrentOffsetX = 0,
- mCurrentOffsetY = 0,
- mCurrentBitmapNum = -1;
+ mBitmapWidth = 0;
+ mBitmapHeight = 0;
+ mBitmapNum = -1;
+ mCurrentOffsetX = 1;
+ mCurrentOffsetY = 1;
}
diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h
index 4a57052b91..b044ba2b16 100644
--- a/indra/llrender/llfontbitmapcache.h
+++ b/indra/llrender/llfontbitmapcache.h
@@ -71,7 +71,6 @@ private:
S32 mMaxCharHeight;
S32 mCurrentOffsetX;
S32 mCurrentOffsetY;
- S32 mCurrentBitmapNum;
std::vector<LLPointer<LLImageRaw> > mImageRawVec;
std::vector<LLPointer<LLImageGL> > mImageGLVec;
};
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 0be6bedbee..44e997340e 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -533,6 +533,7 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
+ resetBitmapCache();
if (!mIsFallback)
{
// This is the head of the list - need to rebuild ourself and all fallbacks.
@@ -552,7 +553,6 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
}
}
}
- resetBitmapCache();
}
void LLFontFreetype::resetBitmapCache()
@@ -568,7 +568,7 @@ void LLFontFreetype::resetBitmapCache()
}
mFontBitmapCachep->reset();
- // Add the empty glyph`5
+ // Add the empty glyph
addGlyph(0, 0);
}
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index 0520ef2cd6..5adaab3a88 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -188,193 +188,3 @@ private:
};
#endif // LL_FONTFREETYPE_H
-/**
- * @file llfontfreetype.h
- * @brief Font library wrapper
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFONTFREETYPE_H
-#define LL_LLFONTFREETYPE_H
-
-#include <map>
-#include "llpointer.h"
-#include "llstl.h"
-
-#include "llimagegl.h"
-#include "llfontbitmapcache.h"
-
-// Hack. FT_Face is just a typedef for a pointer to a struct,
-// but there's no simple forward declarations file for FreeType,
-// and the main include file is 200K.
-// We'll forward declare the struct here. JC
-struct FT_FaceRec_;
-typedef struct FT_FaceRec_* LLFT_Face;
-
-class LLFontManager
-{
-public:
- static void initClass();
- static void cleanupClass();
-
-private:
- LLFontManager();
- ~LLFontManager();
-};
-
-class LLFontGlyphInfo
-{
-public:
- LLFontGlyphInfo(U32 index);
-
- U32 mGlyphIndex;
-
- // Metrics
- S32 mWidth; // In pixels
- S32 mHeight; // In pixels
- F32 mXAdvance; // In pixels
- F32 mYAdvance; // In pixels
- BOOL mMetricsValid; // We have up-to-date metrics for this glyph
-
- // Information for actually rendering
- BOOL mIsRendered; // We actually have rendered this glyph
- S32 mXBitmapOffset; // Offset to the origin in the bitmap
- S32 mYBitmapOffset; // Offset to the origin in the bitmap
- S32 mXBearing; // Distance from baseline to left in pixels
- S32 mYBearing; // Distance from baseline to top in pixels
- S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph
-};
-
-extern LLFontManager *gFontManagerp;
-
-class LLFontFreetype : public LLRefCount
-{
-public:
- LLFontFreetype();
- ~LLFontFreetype();
-
- // is_fallback should be true for fallback fonts that aren't used
- // to render directly (Unicode backup, primarily)
- BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback);
-
- typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t;
-
- void setFallbackFonts(const font_vector_t &font);
- const font_vector_t &getFallbackFonts() const;
-
- // Global font metrics - in units of pixels
- F32 getLineHeight() const;
- F32 getAscenderHeight() const;
- F32 getDescenderHeight() const;
-
-
-// For a lowercase "g":
-//
-// ------------------------------
-// ^ ^
-// | |
-// xxx x |Ascender
-// x x v |
-// --------- xxxx-------------- Baseline
-// ^ x |
-// | Descender x |
-// v xxxx |LineHeight
-// ----------------------- |
-// v
-// ------------------------------
-
- enum
- {
- FIRST_CHAR = 32,
- NUM_CHARS = 127 - 32,
- LAST_CHAR_BASIC = 127,
-
- // Need full 8-bit ascii range for spanish
- NUM_CHARS_FULL = 255 - 32,
- LAST_CHAR_FULL = 255
- };
-
- F32 getXAdvance(llwchar wc) const;
- F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
-
- BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
- BOOL addChar(llwchar wch) const; // Add a new character to the font if necessary
- BOOL addGlyph(llwchar wch, U32 glyph_index) const; // Add a new glyph to the existing font
- BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
-
- LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
-
- void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
- void renderGlyph(U32 glyph_index) const;
-
- void reset(F32 vert_dpi, F32 horz_dpi);
- void resetBitmapCache();
-
- void destroyGL();
-
- BOOL getIsFallback() const;
-
- const std::string& getName() const;
-
- F32 getPointSize() const;
-
- const LLPointer<LLFontBitmapCache> getFontBitmapCache() const;
-
- void setStyle(U8 style);
- U8 getStyle() const;
-
-private:
- void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
-
- std::string mName;
-
- U8 mStyle;
-
- F32 mPointSize;
- F32 mAscender;
- F32 mDescender;
- F32 mLineHeight;
-
- LLFT_Face mFTFace;
-
- BOOL mIsFallback;
- font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
-
- BOOL mValid;
-
- typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
- mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
-
- mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep;
-
- mutable S32 mRenderGlyphCount;
- mutable S32 mAddGlyphCount;
-};
-
-#endif // LL_FONTFREETYPE_H
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 99f364a589..45573cd817 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -105,7 +105,7 @@ bool removeSubString(std::string& str, const std::string& substr)
size_t pos = str.find(substr);
if (pos != string::npos)
{
- str.erase(pos);
+ str.erase(pos, substr.size());
return true;
}
return false;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 753c1fe9e2..65ccb655dd 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -34,10 +34,13 @@ set(llui_SOURCE_FILES
llconsole.cpp
llcontainerview.cpp
llctrlselectioninterface.cpp
+ lldockablefloater.cpp
+ lldockcontrol.cpp
lldraghandle.cpp
lleditmenuhandler.cpp
llf32uictrl.cpp
llfiltereditor.cpp
+ llflatlistview.cpp
llfloater.cpp
llfloaterreg.cpp
llfloaterreglistener.cpp
@@ -48,7 +51,8 @@ set(llui_SOURCE_FILES
llkeywords.cpp
lllayoutstack.cpp
lllineeditor.cpp
- lllink.cpp
+ lllistctrl.cpp
+ lllocalcliprect.cpp
llmenugl.cpp
llmodaldialog.cpp
llmultifloater.cpp
@@ -80,10 +84,12 @@ set(llui_SOURCE_FILES
llstatview.cpp
llstyle.cpp
lltabcontainer.cpp
+ lltextbase.cpp
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
lltransutil.cpp
+ lltooltip.cpp
llui.cpp
lluicolortable.cpp
lluictrl.cpp
@@ -91,6 +97,10 @@ set(llui_SOURCE_FILES
lluiimage.cpp
lluistring.cpp
llundo.cpp
+ llurlaction.cpp
+ llurlentry.cpp
+ llurlmatch.cpp
+ llurlregistry.cpp
llviewborder.cpp
llviewmodel.cpp
llview.cpp
@@ -110,9 +120,12 @@ set(llui_HEADER_FILES
llcontainerview.h
llctrlselectioninterface.h
lldraghandle.h
+ lldockablefloater.h
+ lldockcontrol.h
lleditmenuhandler.h
llf32uictrl.h
llfiltereditor.h
+ llflatlistview.h
llfloater.h
llfloaterreg.h
llfloaterreglistener.h
@@ -126,7 +139,8 @@ set(llui_HEADER_FILES
lllayoutstack.h
lllazyvalue.h
lllineeditor.h
- lllink.h
+ lllistctrl.h
+ lllocalcliprect.h
llmenugl.h
llmodaldialog.h
llmultifloater.h
@@ -158,9 +172,11 @@ set(llui_HEADER_FILES
llstatview.h
llstyle.h
lltabcontainer.h
+ lltextbase.h
lltextbox.h
lltexteditor.h
lltextparser.h
+ lltooltip.h
lltransutil.h
lluicolortable.h
lluiconstants.h
@@ -171,6 +187,10 @@ set(llui_HEADER_FILES
lluiimage.h
lluistring.h
llundo.h
+ llurlaction.h
+ llurlentry.h
+ llurlmatch.h
+ llurlregistry.h
llviewborder.h
llviewmodel.h
llview.h
@@ -186,12 +206,21 @@ add_library (llui ${llui_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries(llui
- llrender
- llwindow
- llimage
- llvfs # ugh, just for LLDir
- llxuixml
- llxml
- llcommon # must be after llimage, llwindow, llrender
- llmath
+ ${LLMESSAGE_LIBRARIES}
+ ${LLRENDER_LIBRARIES}
+ ${LLWINDOW_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLVFS_LIBRARIES} # ugh, just for LLDir
+ ${LLXUIXML_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender
)
+
+# Add tests
+include(LLAddBuildTest)
+SET(llui_TEST_SOURCE_FILES
+ llurlmatch.cpp
+ llurlentry.cpp
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 98e8c9a988..fa13ced037 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -355,11 +355,19 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
setFocus(TRUE);
}
+ /*
+ * ATTENTION! This call fires another mouse down callback.
+ * If you wish to remove this call emit that signal directly
+ * by calling LLUICtrl::mMouseDownSignal(x, y, mask);
+ */
+ LLUICtrl::handleMouseDown(x, y, mask);
+
mMouseDownSignal(this, LLSD());
mMouseDownTimer.start();
mMouseDownFrame = (S32) LLFrameTimer::getFrameCount();
mMouseHeldDownCount = 0;
+
if (getSoundFlags() & MOUSE_DOWN)
{
@@ -378,6 +386,13 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
// Always release the mouse
gFocusMgr.setMouseCapture( NULL );
+ /*
+ * ATTENTION! This call fires another mouse up callback.
+ * If you wish to remove this call emit that signal directly
+ * by calling LLUICtrl::mMouseUpSignal(x, y, mask);
+ */
+ LLUICtrl::handleMouseUp(x, y, mask);
+
// Regardless of where mouseup occurs, handle callback
mMouseUpSignal(this, LLSD());
@@ -460,12 +475,16 @@ BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)
{
+ LLUICtrl::onMouseEnter(x, y, mask);
+
if (isInEnabledChain())
mNeedsHighlight = TRUE;
}
void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
{
+ LLUICtrl::onMouseLeave(x, y, mask);
+
mNeedsHighlight = FALSE;
}
@@ -495,6 +514,7 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
// virtual
void LLButton::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
bool flash = FALSE;
static LLUICachedControl<F32> button_flash_rate("ButtonFlashRate", 0);
static LLUICachedControl<S32> button_flash_count("ButtonFlashCount", 0);
@@ -516,7 +536,7 @@ void LLButton::draw()
// Unselected image assignments
S32 local_mouse_x;
S32 local_mouse_y;
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
bool enabled = isInEnabledChain();
@@ -643,7 +663,7 @@ void LLButton::draw()
if (hasFocus())
{
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
- drawBorder(imagep, gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
+ drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, llround(lerp(1.f, 3.f, lerp_amt)));
}
if (use_glow_effect)
@@ -666,21 +686,21 @@ void LLButton::draw()
LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get();
if ( mScaleImage)
{
- imagep->draw(getLocalRect(), enabled ? mImageColor.get() : disabled_color );
+ imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha );
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % mCurGlowStrength);
+ imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
else
{
- imagep->draw(0, 0, enabled ? mImageColor.get() : disabled_color );
+ imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha );
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- imagep->drawSolid(0, 0, glow_color % mCurGlowStrength);
+ imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
@@ -690,7 +710,7 @@ void LLButton::draw()
// no image
lldebugs << "No image for button " << getName() << llendl;
// draw it in pink so we can find it
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE);
}
// let overlay image and text play well together
@@ -725,6 +745,7 @@ void LLButton::draw()
{
overlay_color.mV[VALPHA] = 0.5f;
}
+ overlay_color.mV[VALPHA] *= alpha;
switch(mImageOverlayAlignment)
{
@@ -796,7 +817,7 @@ void LLButton::draw()
// Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
- label_color,
+ label_color % alpha,
mHAlign, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
@@ -937,17 +958,6 @@ void LLButton::setColor(const LLColor4& color)
setImageColor(color);
}
-void LLButton::setAlpha(F32 alpha)
-{
- LLColor4 temp = mImageColor.get();
- temp.setAlpha(alpha);
- mImageColor.set(temp);
-
- temp = mDisabledImageColor.get();
- temp.setAlpha(alpha * 0.5f);
- mDisabledImageColor.set(temp);
-}
-
void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
{
mImageDisabled = image;
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index e51cd443fa..06e1dac914 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -191,7 +191,6 @@ public:
void setImageColor(const std::string& color_control);
void setImageColor(const LLColor4& c);
/*virtual*/ void setColor(const LLColor4& c);
- /*virtual*/ void setAlpha(F32 alpha);
void setImages(const std::string &image_name, const std::string &selected_name);
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index ac56d15d1b..58aeb61728 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -55,6 +55,7 @@
#include "lllineeditor.h"
#include "v2math.h"
#include "lluictrlfactory.h"
+#include "lltooltip.h"
// Globals
S32 LLCOMBOBOX_HEIGHT = 0;
@@ -77,6 +78,7 @@ LLComboBox::ItemParams::ItemParams()
LLComboBox::Params::Params()
: allow_text_entry("allow_text_entry", false),
+ allow_new_values("allow_new_values", false),
show_text_as_tentative("show_text_as_tentative", true),
max_chars("max_chars", 20),
list_position("list_position", BELOW),
@@ -96,6 +98,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)
mTextEntryTentative(p.show_text_as_tentative),
mHasAutocompletedText(false),
mAllowTextEntry(p.allow_text_entry),
+ mAllowNewValues(p.allow_new_values),
mMaxChars(p.max_chars),
mPrearrangeCallback(p.prearrange_callback()),
mTextEntryCallback(p.text_entry_callback()),
@@ -620,7 +623,15 @@ void LLComboBox::hideList()
if (mList->getVisible())
{
// assert selection in list
- mList->selectNthItem(mLastSelectedIndex);
+ if(mAllowNewValues)
+ {
+ // mLastSelectedIndex = -1 means that we entered a new value, don't select
+ // any of existing items in this case.
+ if(mLastSelectedIndex >= 0)
+ mList->selectNthItem(mLastSelectedIndex);
+ }
+ else
+ mList->selectNthItem(mLastSelectedIndex);
mButton->setToggleState(FALSE);
mList->setVisible(FALSE);
@@ -704,7 +715,7 @@ void LLComboBox::onItemSelected(const LLSD& data)
}
}
-BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
std::string tool_tip;
@@ -713,25 +724,17 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_re
return TRUE;
}
- if (LLUI::sShowXUINames)
+ tool_tip = getToolTip();
+ if (tool_tip.empty())
{
- tool_tip = getShowNamesToolTip();
- }
- else
- {
- tool_tip = getToolTip();
- if (tool_tip.empty())
- {
- tool_tip = getSelectedItemLabel();
- }
+ tool_tip = getSelectedItemLabel();
}
if( !tool_tip.empty() )
{
- msg = tool_tip;
-
- // Convert rect local to screen coordinates
- *sticky_rect_screen = calcScreenRect();
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(tool_tip)
+ .sticky_rect(calcScreenRect()));
}
return TRUE;
}
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 4becda195f..68cbfeeeeb 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -78,7 +78,8 @@ public:
: public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<bool> allow_text_entry,
- show_text_as_tentative;
+ show_text_as_tentative,
+ allow_new_values;
Optional<S32> max_chars;
Optional<commit_callback_t> prearrange_callback,
text_entry_callback,
@@ -112,7 +113,7 @@ public:
// LLView interface
virtual void onFocusLost();
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
@@ -224,6 +225,7 @@ protected:
private:
BOOL mAllowTextEntry;
+ BOOL mAllowNewValues;
S32 mMaxChars;
BOOL mTextEntryTentative;
commit_callback_t mPrearrangeCallback;
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
new file mode 100644
index 0000000000..ed15d9d922
--- /dev/null
+++ b/indra/llui/lldockablefloater.cpp
@@ -0,0 +1,133 @@
+/**
+ * @file lldockablefloater.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldockablefloater.h"
+
+//static
+LLHandle<LLFloater> LLDockableFloater::instanceHandle;
+
+LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
+ const LLSD& key, const Params& params) :
+ LLFloater(key, params), mDockControl(dockControl)
+{
+ resetInstance();
+}
+
+LLDockableFloater::~LLDockableFloater()
+{
+}
+
+BOOL LLDockableFloater::postBuild()
+{
+ mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
+ LLFloater::setDocked(true);
+ return LLView::postBuild();
+}
+
+void LLDockableFloater::resetInstance()
+{
+ if (instanceHandle.get() != this)
+ {
+ if (instanceHandle.get() != NULL && instanceHandle.get()->isDocked())
+ {
+ //closeFloater() is not virtual
+ if (instanceHandle.get()->canClose())
+ {
+ instanceHandle.get()->closeFloater();
+ }
+ else
+ {
+ instanceHandle.get()->setVisible(FALSE);
+ }
+ }
+ instanceHandle = getHandle();
+ }
+}
+
+void LLDockableFloater::setVisible(BOOL visible)
+{
+ if(visible && isDocked())
+ {
+ resetInstance();
+ }
+ LLFloater::setVisible(visible);
+}
+
+void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ if (mDockControl.get() != NULL)
+ {
+ if (docked)
+ {
+ resetInstance();
+ mDockControl.get()->on();
+ }
+ else
+ {
+ mDockControl.get()->off();
+ }
+ }
+
+ if (!docked && pop_on_undock)
+ {
+ // visually pop up a little bit to emphasize the undocking
+ translate(0, UNDOCK_LEAP_HEIGHT);
+ }
+
+ LLFloater::setDocked(docked, pop_on_undock);
+}
+
+void LLDockableFloater::draw()
+{
+ if (mDockControl.get() != NULL)
+ {
+ mDockControl.get()->repositionDockable();
+ mDockControl.get()->drawToungue();
+ }
+ LLFloater::draw();
+}
+
+void LLDockableFloater::setDockControl(LLDockControl* dockControl)
+{
+ mDockControl.reset(dockControl);
+}
+const LLUIImagePtr& LLDockableFloater::getDockTongue()
+{
+ return mDockTongue;
+}
+
+LLDockControl* LLDockableFloater::getDockControl()
+{
+ return mDockControl.get();
+}
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
new file mode 100644
index 0000000000..1d0e89cef5
--- /dev/null
+++ b/indra/llui/lldockablefloater.h
@@ -0,0 +1,75 @@
+/**
+ * @file lldockablefloater.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DOCKABLEFLOATER_H
+#define LL_DOCKABLEFLOATER_H
+
+#include "llerror.h"
+#include "llfloater.h"
+#include "lldockcontrol.h"
+
+/**
+ * Represents floater that can dock.
+ * In case impossibility deriving from LLDockableFloater use LLDockControl.
+ */
+class LLDockableFloater : public LLFloater
+{
+ static const U32 UNDOCK_LEAP_HEIGHT = 12;
+public:
+ LOG_CLASS(LLDockableFloater);
+ LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params = getDefaultParams());
+ virtual ~LLDockableFloater();
+
+ /* virtula */BOOL postBuild();
+ /* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+ /* virtual */void draw();
+ /*virtual*/ void setVisible(BOOL visible);
+
+private:
+ /**
+ * Provides unique of dockable floater.
+ * If dockable floater already exists it should be closed.
+ */
+ void resetInstance();
+
+protected:
+ void setDockControl(LLDockControl* dockControl);
+ LLDockControl* getDockControl();
+ const LLUIImagePtr& getDockTongue();
+
+private:
+ std::auto_ptr<LLDockControl> mDockControl;
+ LLUIImagePtr mDockTongue;
+ static LLHandle<LLFloater> instanceHandle;
+};
+
+#endif /* LL_DOCKABLEFLOATER_H */
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
new file mode 100644
index 0000000000..d666f2be56
--- /dev/null
+++ b/indra/llui/lldockcontrol.cpp
@@ -0,0 +1,143 @@
+/**
+ * @file lldockcontrol.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldockcontrol.h"
+
+LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
+ const LLUIImagePtr& dockTongue, DocAt dockAt, bool enabled) :
+ mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(
+ dockTongue)
+{
+ mDockAt = dockAt;
+ if (enabled)
+ {
+ on();
+ }
+ else
+ {
+ off();
+ }
+
+ if (dockWidget != NULL) {
+ repositionDockable();
+ }
+}
+
+LLDockControl::~LLDockControl()
+{
+}
+
+void LLDockControl::setDock(LLView* dockWidget)
+{
+ mDockWidget = dockWidget;
+ if (mDockWidget != NULL)
+ {
+ repositionDockable();
+ }
+}
+
+void LLDockControl::repositionDockable()
+{
+ if (mEnabled)
+ {
+ calculateDockablePosition();
+ }
+}
+
+void LLDockControl::calculateDockablePosition()
+{
+ LLRect dockRect = mDockWidget->calcScreenRect();
+ LLRect rootRect = mDockableFloater->getRootView()->getRect();
+
+ // recalculate dockable position if dock position changed
+ // or root view rect changed or recalculation is forced
+ if (mPrevDockRect != dockRect || mRootRect != rootRect
+ || mRecalculateDocablePosition)
+ {
+ LLRect dockableRect = mDockableFloater->calcScreenRect();
+ S32 x = 0;
+ S32 y = 0;
+ switch (mDockAt)
+ {
+ case TOP:
+ x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
+ y = dockRect.mTop + mDockTongue->getHeight()
+ + dockableRect.getHeight();
+ if (x < rootRect.mLeft)
+ {
+ x = rootRect.mLeft;
+ }
+ if (x + dockableRect.getWidth() > rootRect.mRight)
+ {
+ x = rootRect.mRight - dockableRect.getWidth();
+ }
+ mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
+ mDockTongueY = dockRect.mTop;
+ break;
+ }
+ dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
+ dockableRect.getHeight());
+ LLRect localDocableParentRect;
+ mDockableFloater->getParent()->screenRectToLocal(dockableRect,
+ &localDocableParentRect);
+ mDockableFloater->setRect(localDocableParentRect);
+
+ mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
+ &mDockTongueX, &mDockTongueY);
+ mPrevDockRect = dockRect;
+ mRootRect = rootRect;
+ mRecalculateDocablePosition = false;
+ }
+}
+
+void LLDockControl::on()
+{
+ mDockableFloater->setCanDrag(false);
+ mEnabled = true;
+ mRecalculateDocablePosition = true;
+}
+
+void LLDockControl::off()
+{
+ mDockableFloater->setCanDrag(true);
+ mEnabled = false;
+}
+
+void LLDockControl::drawToungue()
+{
+ if (mEnabled)
+ {
+ mDockTongue->draw(mDockTongueX, mDockTongueY);
+ }
+}
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
new file mode 100644
index 0000000000..7d8d5c7653
--- /dev/null
+++ b/indra/llui/lldockcontrol.h
@@ -0,0 +1,81 @@
+/**
+ * @file lldockcontrol.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DOCKCONTROL_H
+#define LL_DOCKCONTROL_H
+
+#include "llerror.h"
+#include "llview.h"
+#include "llfloater.h"
+#include "lluiimage.h"
+
+/**
+ * Provides services for docking of specified floater.
+ * This class should be used in case impossibility deriving from LLDockableFloater.
+ */
+class LLDockControl
+{
+public:
+ enum DocAt
+ {
+ TOP
+ };
+
+public:
+ LOG_CLASS(LLDockControl);
+ LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
+ const LLUIImagePtr& dockTongue, DocAt dockAt,
+ bool enabled);
+ virtual ~LLDockControl();
+
+public:
+ void on();
+ void off();
+ void setDock(LLView* dockWidget);
+ void repositionDockable();
+ void drawToungue();
+protected:
+ virtual void calculateDockablePosition();
+private:
+ bool mEnabled;
+ bool mRecalculateDocablePosition;
+ DocAt mDockAt;
+ LLView* mDockWidget;
+ LLRect mPrevDockRect;
+ LLRect mRootRect;
+ LLFloater* mDockableFloater;
+ LLUIImagePtr mDockTongue;
+ S32 mDockTongueX;
+ S32 mDockTongueY;
+};
+
+#endif /* LL_DOCKCONTROL_H */
diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp
index 7d6a4007a2..390504234d 100644
--- a/indra/llui/llfiltereditor.cpp
+++ b/indra/llui/llfiltereditor.cpp
@@ -37,80 +37,15 @@
#include "llfiltereditor.h"
LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p)
-: LLUICtrl(p)
+: LLSearchEditor(p)
{
- LLLineEditor::Params line_editor_p(p);
- line_editor_p.name("filter edit box");
- line_editor_p.rect(getLocalRect());
- line_editor_p.follows.flags(FOLLOWS_ALL);
- line_editor_p.text_pad_right(getRect().getHeight());
- line_editor_p.keystroke_callback(boost::bind(&LLUICtrl::onCommit, this));
-
- mFilterEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_p);
- addChild(mFilterEditor);
-
- S32 btn_width = getRect().getHeight(); // button is square, and as tall as search editor
- LLRect clear_btn_rect(getRect().getWidth() - btn_width, getRect().getHeight(), getRect().getWidth(), 0);
- LLButton::Params button_params(p.clear_filter_button);
- button_params.name(std::string("clear filter"));
- button_params.rect(clear_btn_rect) ;
- button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
- button_params.tab_stop(false);
- button_params.click_callback.function(boost::bind(&LLFilterEditor::onClearFilter, this, _2));
-
- mClearFilterButton = LLUICtrlFactory::create<LLButton>(button_params);
- mFilterEditor->addChild(mClearFilterButton);
-}
-
-//virtual
-void LLFilterEditor::setValue(const LLSD& value )
-{
- mFilterEditor->setValue(value);
-}
-
-//virtual
-LLSD LLFilterEditor::getValue() const
-{
- return mFilterEditor->getValue();
-}
-
-//virtual
-BOOL LLFilterEditor::setTextArg( const std::string& key, const LLStringExplicit& text )
-{
- return mFilterEditor->setTextArg(key, text);
}
-//virtual
-BOOL LLFilterEditor::setLabelArg( const std::string& key, const LLStringExplicit& text )
-{
- return mFilterEditor->setLabelArg(key, text);
-}
-
-//virtual
-void LLFilterEditor::setLabel( const LLStringExplicit &new_label )
-{
- mFilterEditor->setLabel(new_label);
-}
-
-//virtual
-void LLFilterEditor::clear()
-{
- if (mFilterEditor)
- {
- mFilterEditor->clear();
- }
-}
-void LLFilterEditor::draw()
+void LLFilterEditor::handleKeystroke()
{
- mClearFilterButton->setVisible(!mFilterEditor->getWText().empty());
-
- LLUICtrl::draw();
-}
+ this->LLSearchEditor::handleKeystroke();
-void LLFilterEditor::onClearFilter(const LLSD& data)
-{
- setText(LLStringUtil::null);
+ // Commit on every keystroke.
onCommit();
}
-
diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h
index fceb82af8d..c43a76b130 100644
--- a/indra/llui/llfiltereditor.h
+++ b/indra/llui/llfiltereditor.h
@@ -42,18 +42,14 @@
#ifndef LL_FILTEREDITOR_H
#define LL_FILTEREDITOR_H
-#include "lllineeditor.h"
-#include "llbutton.h"
+#include "llsearcheditor.h"
-class LLFilterEditor : public LLUICtrl
+class LLFilterEditor : public LLSearchEditor
{
public:
- struct Params : public LLInitParam::Block<Params, LLLineEditor::Params>
+ struct Params : public LLInitParam::Block<Params, LLSearchEditor::Params>
{
- Optional<LLButton::Params> clear_filter_button;
-
Params()
- : clear_filter_button("clear_filter_button")
{
name = "filter_editor";
}
@@ -62,26 +58,8 @@ public:
protected:
LLFilterEditor(const Params&);
friend class LLUICtrlFactory;
-public:
- virtual ~LLFilterEditor() {}
-
- /*virtual*/ void draw();
-
- void setText(const LLStringExplicit &new_text) { mFilterEditor->setText(new_text); }
-
- // LLUICtrl interface
- virtual void setValue(const LLSD& value );
- virtual LLSD getValue() const;
- virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
- virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- virtual void setLabel( const LLStringExplicit &new_label );
- virtual void clear();
-
-private:
- void onClearFilter(const LLSD& data);
- LLLineEditor* mFilterEditor;
- LLButton* mClearFilterButton;
+ /*virtual*/ void handleKeystroke();
};
#endif // LL_FILTEREDITOR_H
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
new file mode 100644
index 0000000000..75334acb39
--- /dev/null
+++ b/indra/llui/llflatlistview.cpp
@@ -0,0 +1,494 @@
+/**
+ * @file llflatlistview.cpp
+ * @brief LLFlatListView base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llpanel.h"
+
+#include "llflatlistview.h"
+
+static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("flat_list_view");
+
+const LLSD SELECTED_EVENT = LLSD().insert("selected", true);
+const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false);
+
+LLFlatListView::Params::Params()
+: item_pad("item_pad"),
+ allow_select("allow_select"),
+ multi_select("multi_select"),
+ keep_one_selected("keep_one_selected")
+{};
+
+void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+ LLScrollContainer::reshape(width, height, called_from_parent);
+ setItemsNoScrollWidth(width);
+ rearrangeItems();
+}
+
+bool LLFlatListView::addItem(LLPanel* item, LLSD value /* = LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/)
+{
+ if (!item) return false;
+ if (value.isUndefined()) return false;
+
+ //force uniqueness of items, easiest check but unreliable
+ if (item->getParent() == mItemsPanel) return false;
+
+ item_pair_t* new_pair = new item_pair_t(item, value);
+ switch (pos)
+ {
+ case ADD_TOP:
+ mItemPairs.push_front(new_pair);
+ //in LLView::draw() children are iterated in backorder
+ mItemsPanel->addChildInBack(item);
+ break;
+ case ADD_BOTTOM:
+ mItemPairs.push_back(new_pair);
+ mItemsPanel->addChild(item);
+ break;
+ default:
+ break;
+ }
+
+ //_4 is for MASK
+ item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+
+ rearrangeItems();
+ return true;
+}
+
+
+bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, LLSD value /*= LLUUID::null*/)
+{
+ if (!after_item) return false;
+ if (!item_to_add) return false;
+ if (value.isUndefined()) return false;
+
+ if (mItemPairs.empty()) return false;
+
+ //force uniqueness of items, easiest check but unreliable
+ if (item_to_add->getParent() == mItemsPanel) return false;
+
+ item_pair_t* after_pair = getItemPair(after_item);
+ if (!after_pair) return false;
+
+ item_pair_t* new_pair = new item_pair_t(item_to_add, value);
+ if (after_pair == mItemPairs.back())
+ {
+ mItemPairs.push_back(new_pair);
+ mItemsPanel->addChild(item_to_add);
+ }
+ else
+ {
+ pairs_iterator_t it = mItemPairs.begin();
+ ++it;
+ while (it != mItemPairs.end())
+ {
+ if (*it == after_pair)
+ {
+ mItemPairs.insert(++it, new_pair);
+ mItemsPanel->addChild(item_to_add);
+ break;
+ }
+ }
+ }
+
+ //_4 is for MASK
+ item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+
+ rearrangeItems();
+ return true;
+}
+
+
+bool LLFlatListView::removeItem(LLPanel* item)
+{
+ if (!item) return false;
+ if (item->getParent() != mItemsPanel) return false;
+
+ item_pair_t* item_pair = getItemPair(item);
+ if (!item_pair) return false;
+
+ return removeItemPair(item_pair);
+}
+
+bool LLFlatListView::removeItemByValue(const LLSD& value)
+{
+ if (value.isUndefined()) return false;
+
+ item_pair_t* item_pair = getItemPair(value);
+ if (!item_pair) return false;
+
+ return removeItemPair(item_pair);
+}
+
+bool LLFlatListView::removeItemByUUID(LLUUID& uuid)
+{
+ return removeItemByValue(LLSD(uuid));
+}
+
+LLPanel* LLFlatListView::getItemByValue(LLSD& value) const
+{
+ if (value.isDefined()) return NULL;
+
+ item_pair_t* pair = getItemPair(value);
+ if (pair) return pair->first;
+ return NULL;
+}
+
+bool LLFlatListView::selectItem(LLPanel* item, bool select /*= true*/)
+{
+ if (!item) return false;
+ if (item->getParent() != mItemsPanel) return false;
+
+ item_pair_t* item_pair = getItemPair(item);
+ if (!item_pair) return false;
+
+ return selectItemPair(item_pair, select);
+}
+
+bool LLFlatListView::selectItemByValue(const LLSD& value, bool select /*= true*/)
+{
+ if (value.isUndefined()) return false;
+
+ item_pair_t* item_pair = getItemPair(value);
+ if (!item_pair) return false;
+
+ return selectItemPair(item_pair, select);
+}
+
+bool LLFlatListView::selectItemByUUID(LLUUID& uuid, bool select /* = true*/)
+{
+ return selectItemByValue(LLSD(uuid), select);
+}
+
+
+LLSD LLFlatListView::getSelectedValue() const
+{
+ if (mSelectedItemPairs.empty()) return LLSD();
+
+ item_pair_t* first_selected_pair = mSelectedItemPairs.front();
+ return first_selected_pair->second;
+}
+
+void LLFlatListView::getSelectedValues(std::vector<LLSD>& selected_values) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_values.push_back((*it)->second);
+ }
+}
+
+LLUUID LLFlatListView::getSelectedUUID() const
+{
+ const LLSD& value = getSelectedValue();
+ if (value.isDefined() && value.isUUID())
+ {
+ return value.asUUID();
+ }
+ else
+ {
+ return LLUUID::null;
+ }
+}
+
+void LLFlatListView::getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_uuids.push_back((*it)->second.asUUID());
+ }
+}
+
+LLPanel* LLFlatListView::getSelectedItem() const
+{
+ if (mSelectedItemPairs.empty()) return NULL;
+
+ return mSelectedItemPairs.front()->first;
+}
+
+void LLFlatListView::getSelectedItems(std::vector<LLPanel*>& selected_items) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_items.push_back((*it)->first);
+ }
+}
+
+void LLFlatListView::resetSelection()
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ item_pair_t* pair_to_deselect = *it;
+ LLPanel* item = pair_to_deselect->first;
+ item->setValue(UNSELECTED_EVENT);
+ }
+
+ mSelectedItemPairs.clear();
+}
+
+void LLFlatListView::clear()
+{
+ // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex.
+ for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ mItemsPanel->removeChild((*it)->first);
+ delete (*it)->first;
+ delete *it;
+ }
+ mItemPairs.clear();
+ mSelectedItemPairs.clear();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED STUFF
+//////////////////////////////////////////////////////////////////////////
+
+
+LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
+: LLScrollContainer(p),
+ mItemsPanel(NULL),
+ mItemPad(p.item_pad),
+ mAllowSelection(p.allow_select),
+ mMultipleSelection(p.multi_select),
+ mKeepOneItemSelected(p.keep_one_selected)
+{
+ mBorderThickness = getBorderWidth();
+
+ LLRect scroll_rect = getRect();
+ LLRect items_rect;
+
+ setItemsNoScrollWidth(scroll_rect.getWidth());
+ items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0);
+
+ LLPanel::Params pp;
+ pp.rect(items_rect);
+ mItemsPanel = LLUICtrlFactory::create<LLPanel> (pp);
+ addChild(mItemsPanel);
+
+ //we don't need to stretch in vertical direction on reshaping by a parent
+ //no bottom following!
+ mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
+};
+
+void LLFlatListView::rearrangeItems()
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ if (mItemPairs.empty()) return;
+
+ //calculating required height - assuming items can be of different height
+ //list should accommodate all its items
+ S32 height = 0;
+
+ pairs_iterator_t it = mItemPairs.begin();
+ for (; it != mItemPairs.end(); ++it)
+ {
+ LLPanel* item = (*it)->first;
+ height += item->getRect().getHeight();
+ }
+ height += mItemPad * (mItemPairs.size() - 1);
+
+ LLRect rc = mItemsPanel->getRect();
+ S32 width = mItemsNoScrollWidth;
+
+ // update width to avoid horizontal scrollbar
+ if (height > getRect().getHeight() - 2 * mBorderThickness)
+ width -= scrollbar_size;
+
+ //changes the bottom, end of the list goes down in the scroll container
+ rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height);
+ mItemsPanel->setRect(rc);
+
+ //reshaping items
+ S32 item_new_top = height;
+ pairs_iterator_t it2, first_it = mItemPairs.begin();
+ for (it2 = first_it; it2 != mItemPairs.end(); ++it2)
+ {
+ LLPanel* item = (*it2)->first;
+ LLRect rc = item->getRect();
+ if(it2 != first_it)
+ {
+ item_new_top -= (rc.getHeight() + mItemPad);
+ }
+ rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight());
+ item->reshape(rc.getWidth(), rc.getHeight());
+ item->setRect(rc);
+ }
+}
+
+void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
+{
+ if (!item_pair) return;
+
+ bool select_item = !isSelected(item_pair);
+
+ //*TODO find a better place for that enforcing stuff
+ if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return;
+
+ if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection();
+ selectItemPair(item_pair, select_item);
+}
+
+LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const
+{
+ llassert(item);
+
+ for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* item_pair = *it;
+ if (item_pair->first == item) return item_pair;
+ }
+ return NULL;
+}
+
+//compares two LLSD's
+bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2)
+{
+ llassert(llsd_1.isDefined());
+ llassert(llsd_2.isDefined());
+
+ if (llsd_1.type() != llsd_2.type()) return false;
+
+ if (!llsd_1.isMap())
+ {
+ if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID();
+
+ //assumptions that string representaion is enough for other types
+ return llsd_1.asString() == llsd_2.asString();
+ }
+
+ if (llsd_1.size() != llsd_2.size()) return false;
+
+ LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap();
+ LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap();
+ for (S32 i = 0; i < llsd_1.size(); ++i)
+ {
+ if ((*llsd_1_it).first != (*llsd_2_it).first) return false;
+ if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false;
+ ++llsd_1_it;
+ ++llsd_2_it;
+ }
+ return true;
+}
+
+LLFlatListView::item_pair_t* LLFlatListView::getItemPair(const LLSD& value) const
+{
+ llassert(value.isDefined());
+
+ for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* item_pair = *it;
+ if (llsds_are_equal(item_pair->second, value)) return item_pair;
+ }
+ return NULL;
+}
+
+bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
+{
+ llassert(item_pair);
+
+ if (!mAllowSelection && select) return false;
+
+ if (isSelected(item_pair) == select) return true; //already in specified selection state
+ if (select)
+ {
+ mSelectedItemPairs.push_back(item_pair);
+ }
+ else
+ {
+ mSelectedItemPairs.remove(item_pair);
+ }
+
+ //a way of notifying panel of selection state changes
+ LLPanel* item = item_pair->first;
+ item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT);
+ return true;
+}
+
+bool LLFlatListView::isSelected(item_pair_t* item_pair) const
+{
+ llassert(item_pair);
+
+ pairs_const_iterator_t it_end = mSelectedItemPairs.end();
+ return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end;
+}
+
+bool LLFlatListView::removeItemPair(item_pair_t* item_pair)
+{
+ llassert(item_pair);
+
+ bool deleted = false;
+ for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* _item_pair = *it;
+ if (_item_pair == item_pair)
+ {
+ mItemPairs.erase(it);
+ deleted = true;
+ break;
+ }
+ }
+
+ if (!deleted) return false;
+
+ for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ item_pair_t* selected_item_pair = *it;
+ if (selected_item_pair == item_pair)
+ {
+ it = mSelectedItemPairs.erase(it);
+ break;
+ }
+ }
+
+ mItemsPanel->removeChild(item_pair->first);
+ delete item_pair->first;
+ delete item_pair;
+
+ rearrangeItems();
+
+ return true;
+}
+
+
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
new file mode 100644
index 0000000000..bd0b419f4f
--- /dev/null
+++ b/indra/llui/llflatlistview.h
@@ -0,0 +1,262 @@
+/**
+ * @file llflatlistview.h
+ * @brief LLFlatListView base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLATLISTVIEW_H
+#define LL_LLFLATLISTVIEW_H
+
+#include "llscrollcontainer.h"
+
+
+class LLPanel;
+
+/**
+ * LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's.
+ * LLSD can be associated with each added item, it can keep data from an item in digested form.
+ * Associated LLSD's can be of any type (singular, a map etc.).
+ * Items (LLPanel's subclasses) can be of different height.
+ * The list is LLPanel created in itself and grows in height while new items are added.
+ *
+ * The control can manage selection of its items when the flag "allow_select" is set. Also ability to select
+ * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag
+ * is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items)
+ * since any item of the list was selected.
+ *
+ * Examples of using this control are presented in Picks panel (Me Profile and Profile View), where this control is used to
+ * manage the list of pick items.
+ *
+ * ASSUMPTIONS AND STUFF
+ * - NULL pointers and undefined LLSD's are not accepted by any method of this class unless specified otherwise
+ * - Order of returned selected items are not guaranteed
+ * - The control assumes that all items being added are unique.
+ */
+class LLFlatListView : public LLScrollContainer
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLScrollContainer::Params>
+ {
+ /** turning on/off selection support */
+ Optional<bool> allow_select;
+
+ /** turning on/off multiple selection (works while clicking and holding CTRL)*/
+ Optional<bool> multi_select;
+
+ /** don't allow to deselect all selected items (for mouse events on items only) */
+ Optional<bool> keep_one_selected;
+
+ /** padding between items */
+ Optional<U32> item_pad;
+
+ Params();
+ };
+
+ virtual ~LLFlatListView() { clear(); };
+
+
+ /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+
+ /**
+ * Adds and item and LLSD value associated with it to the list at specified position
+ * @return true if the item was added, false otherwise
+ */
+ virtual bool addItem(LLPanel* item, LLSD value = LLUUID::null, EAddPosition pos = ADD_BOTTOM);
+
+ /**
+ * Insert item_to_add along with associated value to the list right after the after_item.
+ * @return true if the item was successfully added, false otherwise
+ */
+ virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, LLSD value = LLUUID::null);
+
+ /**
+ * Remove specified item
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItem(LLPanel* item);
+
+ /**
+ * Remove an item specified by value
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItemByValue(const LLSD& value);
+
+ /**
+ * Remove an item specified by uuid
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItemByUUID(LLUUID& uuid);
+
+ /**
+ * Get an item by value
+ * @return the item as LLPanel if associated with value, NULL otherwise
+ */
+ virtual LLPanel* getItemByValue(LLSD& value) const;
+
+ /**
+ * Select or deselect specified item based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItem(LLPanel* item, bool select = true);
+
+ /**
+ * Select or deselect an item by associated value based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItemByValue(const LLSD& value, bool select = true);
+
+ /**
+ * Select or deselect an item by associated uuid based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItemByUUID(LLUUID& uuid, bool select = true);
+
+
+
+ /**
+ * Get LLSD associated with the first selected item
+ */
+ virtual LLSD getSelectedValue() const;
+
+ /**
+ * Get LLSD's associated with selected items.
+ * @param selected_values std::vector being populated with LLSD associated with selected items
+ */
+ virtual void getSelectedValues(std::vector<LLSD>& selected_values) const;
+
+
+ /**
+ * Get LLUUID associated with selected item
+ * @return LLUUID if such was associated with selected item
+ */
+ virtual LLUUID getSelectedUUID() const;
+
+ /**
+ * Get LLUUIDs associated with selected items
+ * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items
+ */
+ virtual void getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const;
+
+ /** Get the top selected item */
+ virtual LLPanel* getSelectedItem() const;
+
+ /**
+ * Get selected items
+ * @param selected_items An std::vector being populated with pointers to selected items
+ */
+ virtual void getSelectedItems(std::vector<LLPanel*>& selected_items) const;
+
+
+ /** Resets selection of items */
+ virtual void resetSelection();
+
+
+ /** Turn on/off multiple selection support */
+ void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; }
+
+ /** Turn on/off selection support */
+ void setAllowSelection(bool can_select) { mAllowSelection = can_select; }
+
+
+ /** Get number of selected items in the list */
+ U32 numSelected() const {return mSelectedItemPairs.size(); }
+
+ /** Get number of items in the list */
+ U32 size() const { return mItemPairs.size(); }
+
+
+ /** Removes all items from the list */
+ virtual void clear();
+
+
+protected:
+
+ /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
+ typedef std::pair<LLPanel*, LLSD> item_pair_t;
+
+ typedef std::list<item_pair_t*> pairs_list_t;
+ typedef pairs_list_t::iterator pairs_iterator_t;
+ typedef pairs_list_t::const_iterator pairs_const_iterator_t;
+
+
+ friend class LLUICtrlFactory;
+ LLFlatListView(const LLFlatListView::Params& p);
+
+ /** Manage selection on mouse events */
+ void onItemMouseClick(item_pair_t* item_pair, MASK mask);
+
+ /** Updates position of items */
+ virtual void rearrangeItems();
+
+ virtual item_pair_t* getItemPair(LLPanel* item) const;
+
+ virtual item_pair_t* getItemPair(const LLSD& value) const;
+
+ virtual bool selectItemPair(item_pair_t* item_pair, bool select);
+
+ virtual bool isSelected(item_pair_t* item_pair) const;
+
+ virtual bool removeItemPair(item_pair_t* item_pair);
+
+
+private:
+
+ void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;}
+
+
+private:
+
+ LLPanel* mItemsPanel;
+
+ S32 mItemsNoScrollWidth;
+
+ S32 mBorderThickness;
+
+ /** Items padding */
+ U32 mItemPad;
+
+ /** Selection support flag */
+ bool mAllowSelection;
+
+ /** Multiselection support flag, ignored if selection is not supported */
+ bool mMultipleSelection;
+
+ bool mKeepOneItemSelected;
+
+ /** All pairs of the list */
+ pairs_list_t mItemPairs;
+
+ /** Selected pairs for faster access */
+ pairs_list_t mSelectedItemPairs;
+};
+
+#endif
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index a372bac497..4690c54c15 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -208,9 +208,6 @@ LLFloater::Params::Params()
close_callback("close_callback"),
can_dock("can_dock", false)
{
- name = "floater";
- // defaults that differ from LLPanel:
- background_visible = true;
visible = false;
}
@@ -231,41 +228,39 @@ void LLFloater::initClass()
}
}
+// defaults for floater param block pulled from widgets/floater.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
+
LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
- : LLPanel(),
- mDragHandle(NULL),
- mTitle(p.title),
- mShortTitle(p.short_title),
- mSingleInstance(p.single_instance),
- mKey(key),
- mAutoTile(p.auto_tile),
- mCanTearOff(p.can_tear_off),
- mCanMinimize(p.can_minimize),
- mCanClose(p.can_close),
- mDragOnLeft(p.can_drag_on_left),
- mResizable(p.can_resize),
- mMinWidth(p.min_width),
- mMinHeight(p.min_height),
- mMinimized(FALSE),
- mForeground(FALSE),
- mFirstLook(TRUE),
- mEditing(FALSE),
- mButtonScale(1.0f),
- mAutoFocus(TRUE), // automatically take focus when opened
- mCanDock(false),
- mDocked(false),
- mHasBeenDraggedWhileMinimized(FALSE),
- mPreviousMinimizedBottom(0),
- mPreviousMinimizedLeft(0),
- mNotificationContext(NULL)
-{
- static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor");
- static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor");
-
+: LLPanel(),
+ mDragHandle(NULL),
+ mTitle(p.title),
+ mShortTitle(p.short_title),
+ mSingleInstance(p.single_instance),
+ mKey(key),
+ mAutoTile(p.auto_tile),
+ mCanTearOff(p.can_tear_off),
+ mCanMinimize(p.can_minimize),
+ mCanClose(p.can_close),
+ mDragOnLeft(p.can_drag_on_left),
+ mResizable(p.can_resize),
+ mMinWidth(p.min_width),
+ mMinHeight(p.min_height),
+ mMinimized(FALSE),
+ mForeground(FALSE),
+ mFirstLook(TRUE),
+ mEditing(FALSE),
+ mButtonScale(1.0f),
+ mAutoFocus(TRUE), // automatically take focus when opened
+ mCanDock(false),
+ mDocked(false),
+ mHasBeenDraggedWhileMinimized(FALSE),
+ mPreviousMinimizedBottom(0),
+ mPreviousMinimizedLeft(0),
+ mNotificationContext(NULL)
+{
mHandle.bind(this);
mNotificationContext = new LLFloaterNotificationContext(getHandle());
- mBgColorAlpha = default_background_color;
- mBgColorOpaque = focus_background_color;
// Clicks stop here.
setMouseOpaque(TRUE);
@@ -769,11 +764,6 @@ void LLFloater::applyRectControl()
void LLFloater::applyTitle()
{
- if (gNoRender)
- {
- return;
- }
-
if (!mDragHandle)
{
return;
@@ -1491,7 +1481,8 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()
// The focused floater may not be closable,
// Find and close a parental floater that is closeable, if any.
- for(LLFloater* floater_to_close = focused_floater;
+ LLFloater* prev_floater = NULL;
+ for(LLFloater* floater_to_close = focused_floater;
NULL != floater_to_close;
floater_to_close = gFloaterView->getParentFloater(floater_to_close))
{
@@ -1499,6 +1490,14 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()
{
return floater_to_close;
}
+
+ // If floater has as parent root view
+ // gFloaterView->getParentFloater(floater_to_close) returns
+ // the same floater_to_close, so we need to check this.
+ if (prev_floater == floater_to_close) {
+ break;
+ }
+ prev_floater = floater_to_close;
}
return NULL;
@@ -1536,6 +1535,7 @@ void LLFloater::onClickClose( LLFloater* self )
// virtual
void LLFloater::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
// draw background
if( isBackgroundVisible() )
{
@@ -1555,27 +1555,29 @@ void LLFloater::draw()
shadow_color.mV[VALPHA] *= 0.5f;
}
gl_drop_shadow(left, top, right, bottom,
- shadow_color,
+ shadow_color % alpha,
llround(shadow_offset));
// No transparent windows in simple UI
if (isBackgroundOpaque())
{
- gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
+ gl_rect_2d( left, top, right, bottom, getBackgroundColor() % alpha );
}
else
{
- gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
+ gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha );
}
- if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty())
+ if(hasFocus()
+ && !getIsChrome()
+ && !getCurrentTitle().empty())
{
static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
// draw highlight on title bar to indicate focus. RDW
const LLFontGL* font = LLFontGL::getFontSansSerif();
LLRect r = getRect();
gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,
- titlebar_focus_color, 0, TRUE);
+ titlebar_focus_color % alpha, 0, TRUE);
}
}
@@ -1633,7 +1635,7 @@ void LLFloater::draw()
static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor");
LLUI::setLineWidth(1.5f);
LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color;
- gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor, -LLPANEL_BORDER_WIDTH, FALSE);
+ gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE);
LLUI::setLineWidth(1.f);
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index cace13939f..6208d52135 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -375,9 +375,6 @@ private:
S32 mPreviousMinimizedBottom;
S32 mPreviousMinimizedLeft;
- LLColor4 mBgColorAlpha;
- LLColor4 mBgColorOpaque;
-
LLFloaterNotificationContext* mNotificationContext;
LLRootHandle<LLFloater> mHandle;
};
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 673c742e7a..0330a2b374 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -74,20 +74,12 @@ void LLIconCtrl::draw()
{
if( mImagep.notNull() )
{
- mImagep->draw(getLocalRect(), mColor.get() );
+ mImagep->draw(getLocalRect(), mColor.get() % getDrawContext().mAlpha );
}
LLUICtrl::draw();
}
-// virtual
-void LLIconCtrl::setAlpha(F32 alpha)
-{
- LLColor4 temp = mColor.get();
- temp.setAlpha(alpha);
- mColor.set(temp);
-}
-
// virtual
// value might be a string or a UUID
void LLIconCtrl::setValue(const LLSD& value )
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index aceb70b9d5..ff25b0d53e 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -71,8 +71,6 @@ public:
std::string getImageName() const;
- /*virtual*/ void setAlpha(F32 alpha);
-
void setColor(const LLColor4& color) { mColor = color; }
private:
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index f98edec1f3..2d582c0568 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -35,6 +35,7 @@
#include "linden_common.h"
#include "lllayoutstack.h"
+#include "lllocalcliprect.h"
#include "llresizebar.h"
#include "llcriticaldamp.h"
@@ -297,6 +298,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
FALSE, output_child);
LLPanel::Params p;
+ p.mouse_opaque(false);
LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p);
LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child);
if (new_child)
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 5435b9ffbf..ede67ad17d 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -97,6 +97,7 @@ LLLineEditor::Params::Params()
background_image_focused("background_image_focused"),
select_on_focus("select_on_focus", false),
handle_edit_keys_directly("handle_edit_keys_directly", false),
+ revert_on_esc("revert_on_esc", true),
commit_on_focus_lost("commit_on_focus_lost", true),
ignore_tab("ignore_tab", true),
cursor_color("cursor_color"),
@@ -130,7 +131,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mMinHPixels(0), // computed in updateTextPadding() below
mMaxHPixels(0), // computed in updateTextPadding() below
mCommitOnFocusLost( p.commit_on_focus_lost ),
- mRevertOnEsc( TRUE ),
+ mRevertOnEsc( p.revert_on_esc ),
mKeystrokeCallback( p.keystroke_callback() ),
mIsSelecting( FALSE ),
mSelectionStart( 0 ),
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 0986ce5a87..339aad30fb 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -90,6 +90,7 @@ public:
Optional<bool> select_on_focus,
handle_edit_keys_directly,
+ revert_on_esc,
commit_on_focus_lost,
ignore_tab;
@@ -188,6 +189,7 @@ public:
// Selects characters 'start' to 'end'.
void setSelection(S32 start, S32 end);
+ virtual void getSelectionRange(S32 *position, S32 *length) const;
void setCommitOnFocusLost( BOOL b ) { mCommitOnFocusLost = b; }
void setRevertOnEsc( BOOL b ) { mRevertOnEsc = b; }
@@ -276,7 +278,6 @@ private:
const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
virtual void markAsPreedit(S32 position, S32 length);
virtual void getPreeditRange(S32 *position, S32 *length) const;
- virtual void getSelectionRange(S32 *position, S32 *length) const;
virtual BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
new file mode 100644
index 0000000000..058b6ae178
--- /dev/null
+++ b/indra/llui/lllocalcliprect.cpp
@@ -0,0 +1,143 @@
+/**
+* @file lllocalcliprect.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "linden_common.h"
+
+#include "lllocalcliprect.h"
+
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+
+#include <stack>
+
+//---------------------------------------------------------------------------
+// LLScreenClipRect
+// implementation class in screen space
+//---------------------------------------------------------------------------
+class LLScreenClipRect
+{
+public:
+ 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;
+};
+
+/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
+
+
+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 LLScreenClipRect::pushClipRect(const LLRect& rect)
+{
+ LLRect combined_clip_rect = rect;
+ if (!sClipRectStack.empty())
+ {
+ LLRect top = sClipRectStack.top();
+ combined_clip_rect.intersectWith(top);
+
+ if(combined_clip_rect.isEmpty())
+ {
+ // avoid artifacts where zero area rects show up as lines
+ combined_clip_rect = LLRect::null;
+ }
+ }
+ sClipRectStack.push(combined_clip_rect);
+}
+
+//static
+void LLScreenClipRect::popClipRect()
+{
+ sClipRectStack.pop();
+}
+
+//static
+void LLScreenClipRect::updateScissorRegion()
+{
+ 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();
+}
+
+//---------------------------------------------------------------------------
+// LLLocalClipRect
+//---------------------------------------------------------------------------
+LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
+{
+ LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY);
+ mScreenClipRect = new LLScreenClipRect(screen, enabled);
+}
+
+LLLocalClipRect::~LLLocalClipRect()
+{
+ delete mScreenClipRect;
+ mScreenClipRect = NULL;
+}
diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h
new file mode 100644
index 0000000000..cd0c55ca72
--- /dev/null
+++ b/indra/llui/lllocalcliprect.h
@@ -0,0 +1,53 @@
+/**
+* @file lllocalcliprect.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLLOCALCLIPRECT_H
+#define LLLOCALCLIPRECT_H
+
+#include "llrect.h" // can't forward declare, it's templated
+
+// Clip rendering to a specific rectangle using GL scissor
+// Just create one of these on the stack:
+// {
+// LLLocalClipRect(rect);
+// draw();
+// }
+class LLLocalClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ ~LLLocalClipRect();
+
+private:
+ // implementation class
+ class LLScreenClipRect* mScreenClipRect;
+};
+
+#endif
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index d6dfe6c198..e0bb6bd5d3 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -2929,7 +2929,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
// If the mouse doesn't move, the menu will stay open ala the Mac.
// See also LLContextMenu::show()
S32 mouse_x, mouse_y;
- LLUI::getCursorPositionLocal(menu->getParent(), &mouse_x, &mouse_y);
+ LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y);
const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
@@ -3371,6 +3371,34 @@ BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask )
return handled;
}
+BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ BOOL handled = false;
+ LLMenuGL* const pMenu = dynamic_cast<LLMenuGL*>(getVisibleMenu());
+
+ if (pMenu)
+ {
+ //handle ESCAPE and RETURN key
+ handled = LLPanel::handleKey(key, mask, called_from_parent);
+ if (!handled)
+ {
+ if (pMenu->getHighlightedItem())
+ {
+ handled = pMenu->handleKey(key, mask, TRUE);
+ }
+ else
+ {
+ //highlight first enabled one
+ pMenu->highlightNextItem(NULL);
+ handled = true;
+ }
+ }
+ }
+
+ return handled;
+
+}
+
void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (width != getRect().getWidth() || height != getRect().getHeight())
@@ -3380,17 +3408,17 @@ void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
LLView::reshape(width, height, called_from_parent);
}
-BOOL LLMenuHolderGL::hasVisibleMenu() const
+LLView* const LLMenuHolderGL::getVisibleMenu() const
{
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL)
{
- return TRUE;
+ return viewp;
}
}
- return FALSE;
+ return NULL;
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 0bf6301f93..8309fedf7f 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -772,8 +772,10 @@ public:
// Close context menus on right mouse up not handled by menus.
/*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual const LLRect getMenuRect() const { return getLocalRect(); }
- virtual BOOL hasVisibleMenu() const;
+ LLView*const getVisibleMenu() const;
+ virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;}
static void setActivatedItem(LLMenuItemGL* item);
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index c81be6086a..26136e0a23 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -91,8 +91,8 @@ LLPanel::Params::Params()
LLPanel::LLPanel(const LLPanel::Params& p)
: LLUICtrl(p),
- mBgColorAlpha(p.bg_alpha_color().get()),
- mBgColorOpaque(p.bg_opaque_color().get()),
+ mBgColorAlpha(p.bg_alpha_color()),
+ mBgColorOpaque(p.bg_opaque_color()),
mBgVisible(p.background_visible),
mBgOpaque(p.background_opaque),
mDefaultBtn(NULL),
@@ -100,7 +100,7 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mLabel(p.label),
mCommitCallbackRegistrar(false),
mEnableCallbackRegistrar(false),
- mXMLFilename("")
+ mXMLFilename(p.filename)
{
setIsChrome(FALSE);
@@ -171,6 +171,8 @@ void LLPanel::setCtrlsEnabled( BOOL b )
void LLPanel::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
// draw background
if( mBgVisible )
{
@@ -182,11 +184,11 @@ void LLPanel::draw()
if (mBgOpaque )
{
- gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
+ gl_rect_2d( left, top, right, bottom, mBgColorOpaque.get() % alpha);
}
else
{
- gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
+ gl_rect_2d( left, top, right, bottom, mBgColorAlpha.get() % alpha);
}
}
@@ -195,12 +197,6 @@ void LLPanel::draw()
LLView::draw();
}
-/*virtual*/
-void LLPanel::setAlpha(F32 alpha)
-{
- mBgColorOpaque.setAlpha(alpha);
-}
-
void LLPanel::updateDefaultBtn()
{
if( mDefaultBtn)
@@ -403,6 +399,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
setVisible(p.visible);
setEnabled(p.enabled);
+ setSoundFlags(p.sound_flags);
+
// control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
LLUICtrl::initFromParams(p);
@@ -709,14 +707,6 @@ void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
child->setColor(color);
}
}
-void LLPanel::childSetAlpha(const std::string& id, F32 alpha)
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setAlpha(alpha);
- }
-}
LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
{
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 3f1d1fdc5d..81b5b68f05 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -114,8 +114,6 @@ public:
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
- virtual void setAlpha(F32 alpha);
-
// New virtuals
virtual void refresh(); // called in setFocus()
@@ -190,7 +188,6 @@ public:
void childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb );
void childSetColor(const std::string& id, const LLColor4& color);
- void childSetAlpha(const std::string& id, F32 alpha);
LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const;
LLCtrlListInterface* childGetListInterface(const std::string& id) const;
@@ -236,6 +233,7 @@ public:
virtual void onOpen(const LLSD& key) {}
void setXMLFilename(std::string filename) { mXMLFilename = filename; };
+ std::string getXMLFilename() { return mXMLFilename; };
protected:
// Override to set not found list
@@ -247,13 +245,8 @@ protected:
commit_signal_t mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
private:
- // Unified error reporting for the child* functions
- typedef std::set<std::string> expected_members_list_t;
- mutable expected_members_list_t mExpectedMembers;
- mutable expected_members_list_t mNewExpectedMembers;
-
- LLColor4 mBgColorAlpha;
- LLColor4 mBgColorOpaque;
+ LLUIColor mBgColorAlpha;
+ LLUIColor mBgColorOpaque;
BOOL mBgVisible;
BOOL mBgOpaque;
LLViewBorder* mBorder;
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index b46915b379..172c4a9c65 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -484,7 +484,7 @@ void LLScrollbar::draw()
S32 local_mouse_x;
S32 local_mouse_y;
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this;
BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y));
if (hovered)
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 13f862f3af..30a042cff1 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -37,6 +37,7 @@
#include "llrender.h"
#include "llcontainerview.h"
+#include "lllocalcliprect.h"
// #include "llfolderview.h"
#include "llscrollingpanellist.h"
#include "llscrollbar.h"
@@ -66,9 +67,12 @@ static LLDefaultChildRegistry::Register<LLScrollContainer> r("scroll_container")
#include "llscrollingpanellist.h"
#include "llcontainerview.h"
#include "llpanel.h"
+#include "lllistctrl.h"
+
static ScrollContainerRegistry::Register<LLScrollingPanelList> r1("scrolling_panel_list");
static ScrollContainerRegistry::Register<LLContainerView> r2("container_view");
static ScrollContainerRegistry::Register<LLPanel> r3("panel", &LLPanel::fromXML);
+static ScrollContainerRegistry::Register<LLListCtrl> r4("list");
LLScrollContainer::Params::Params()
: is_opaque("opaque"),
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 637642cdcd..483106e857 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -44,6 +44,8 @@
#include "llcheckboxctrl.h"
#include "llclipboard.h"
#include "llfocusmgr.h"
+#include "llgl.h" // LLGLSUIDefault()
+#include "lllocalcliprect.h"
//#include "llrender.h"
#include "llresmgr.h"
#include "llscrollbar.h"
@@ -57,6 +59,12 @@
#include "llviewborder.h"
#include "lltextbox.h"
#include "llsdparam.h"
+#include "llcachename.h"
+#include "llmenugl.h"
+#include "llurlaction.h"
+#include "lltooltip.h"
+
+#include <boost/bind.hpp>
static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
@@ -118,6 +126,7 @@ LLScrollListCtrl::Params::Params()
sort_ascending("sort_ascending", true),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
heading_height("heading_height"),
+ page_lines("page_lines", 0),
background_visible("background_visible"),
draw_stripes("draw_stripes"),
column_padding("column_padding"),
@@ -140,7 +149,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
: LLUICtrl(p),
mLineHeight(0),
mScrollLines(0),
- mPageLines(0),
+ mPageLines(p.page_lines),
mMaxSelectable(0),
mAllowKeyboardMovement(TRUE),
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
@@ -157,6 +166,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mOnSortChangedCallback( NULL ),
mHighlightedItem(-1),
mBorder(NULL),
+ mPopupMenu(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
mTotalColumnPadding(0),
@@ -179,7 +189,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mHighlightedColor(p.highlighted_color()),
mHoveredColor(p.hovered_color()),
mSearchColumn(p.search_column),
- mColumnPadding(p.column_padding)
+ mColumnPadding(p.column_padding),
+ mContextMenuType(MENU_NONE)
{
mItemListRect.setOriginAndSize(
mBorderThickness,
@@ -189,8 +200,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
updateLineHeight();
- mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0;
-
// Init the scrollbar
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
@@ -207,7 +216,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
sbparams.orientation(LLScrollbar::VERTICAL);
sbparams.doc_size(getItemCount());
sbparams.doc_pos(mScrollLines);
- sbparams.page_size(mPageLines);
+ sbparams.page_size( mPageLines ? mPageLines : getItemCount() );
sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2));
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.visible(false);
@@ -462,8 +471,12 @@ void LLScrollListCtrl::updateLayout()
getChildView("comment_text")->setShape(mItemListRect);
// how many lines of content in a single "page"
- mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0;
- BOOL scrollbar_visible = getItemCount() > mPageLines;
+ S32 page_lines = mLineHeight? mItemListRect.getHeight() / mLineHeight : getItemCount();
+ //if mPageLines is NOT provided display all item
+ if(mPageLines)
+ page_lines = mPageLines;
+
+ BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight();
if (scrollbar_visible)
{
// provide space on the right for scrollbar
@@ -472,7 +485,7 @@ void LLScrollListCtrl::updateLayout()
mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom);
mScrollbar->reshape(scrollbar_size, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
- mScrollbar->setPageSize( mPageLines );
+ mScrollbar->setPageSize(page_lines);
mScrollbar->setDocSize( getItemCount() );
mScrollbar->setVisible(scrollbar_visible);
@@ -484,6 +497,9 @@ void LLScrollListCtrl::updateLayout()
void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
{
S32 height = llmin( getRequiredRect().getHeight(), max_height );
+ if(mPageLines)
+ height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );
+
S32 width = getRect().getWidth();
reshape( width, height );
@@ -714,6 +730,12 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
updateLayout();
}
+void LLScrollListCtrl::setPageLines(S32 new_page_lines)
+{
+ mPageLines = new_page_lines;
+
+ updateLayout();
+}
BOOL LLScrollListCtrl::selectFirstItem()
{
@@ -1360,7 +1382,7 @@ void LLScrollListCtrl::drawItems()
S32 y = mItemListRect.mTop - mLineHeight;
// allow for partial line at bottom
- S32 num_page_lines = mPageLines + 1;
+ S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
LLRect item_rect;
@@ -1503,7 +1525,7 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
-BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
S32 column_index = getColumnIndexFromOffset(x);
LLScrollListColumn* columnp = getColumn(column_index);
@@ -1526,8 +1548,11 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti
LLRect cell_rect;
cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight);
// Convert rect local to screen coordinates
- localRectToScreen(cell_rect, sticky_rect_screen);
- msg = hit_cell->getValue().asString();
+ LLRect sticky_rect;
+ localRectToScreen(cell_rect, &sticky_rect);
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(hit_cell->getValue().asString())
+ .sticky_rect(sticky_rect));
}
handled = TRUE;
}
@@ -1536,8 +1561,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti
LLScrollColumnHeader* headerp = columnp->mHeader;
if (headerp && !handled)
{
- headerp->handleToolTip(x, y, msg, sticky_rect_screen);
- handled = !msg.empty();
+ handled = headerp->handleToolTip(x, y, msg, sticky_rect_screen);
}
return handled;
@@ -1692,6 +1716,72 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
return LLUICtrl::handleMouseUp(x, y, mask);
}
+// virtual
+BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLScrollListItem *item = hitItem(x, y);
+ if (item)
+ {
+ // check to see if we have a UUID for this row
+ std::string id = item->getValue().asString();
+ LLUUID uuid(id);
+ if (! uuid.isNull() && mContextMenuType != MENU_NONE)
+ {
+ // set up the callbacks for all of the avatar/group menu items
+ // (N.B. callbacks don't take const refs as id is local scope)
+ bool is_group = (mContextMenuType == MENU_GROUP);
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
+ registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
+ registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
+
+ // create the context menu from the XUI file and display it
+ std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
+ delete mPopupMenu;
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (mPopupMenu)
+ {
+ mPopupMenu->show(x, y);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
+{
+ // show the resident's profile or the group profile
+ std::string sltype = is_group ? "group" : "agent";
+ std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
+ LLUrlAction::clickAction(slurl);
+}
+
+void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group)
+{
+ // copy the name of the avatar or group to the clipboard
+ std::string name;
+ if (is_group)
+ {
+ gCacheName->getGroupName(LLUUID(id), name);
+ }
+ else
+ {
+ gCacheName->getFullName(LLUUID(id), name);
+ }
+ LLUrlAction::copyURLToClipboard(name);
+}
+
+void LLScrollListCtrl::copySLURLToClipboard(std::string id, bool is_group)
+{
+ // copy a SLURL for the avatar or group to the clipboard
+ std::string sltype = is_group ? "group" : "agent";
+ std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
+ LLUrlAction::copyURLToClipboard(slurl);
+}
+
BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
{
//BOOL handled = FALSE;
@@ -1783,7 +1873,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mLineHeight );
// allow for partial line at bottom
- S32 num_page_lines = mPageLines + 1;
+ S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
S32 line = 0;
item_list::iterator iter;
@@ -2348,7 +2438,8 @@ void LLScrollListCtrl::scrollToShowSelected()
}
S32 lowest = mScrollLines;
- S32 highest = mScrollLines + mPageLines;
+ S32 page_lines = (mPageLines)? mPageLines : getItemCount();
+ S32 highest = mScrollLines + page_lines;
if (index < lowest)
{
@@ -2357,7 +2448,7 @@ void LLScrollListCtrl::scrollToShowSelected()
}
else if (highest <= index)
{
- setScrollPos(index - mPageLines + 1);
+ setScrollPos(index - page_lines + 1);
}
}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 253a58ab73..49a49499ef 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -54,6 +54,7 @@
class LLScrollListCell;
class LLTextBox;
+class LLContextMenu;
class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
public LLCtrlListInterface, public LLCtrlScrollInterface
@@ -86,6 +87,7 @@ public:
// layout
Optional<S32> column_padding,
+ page_lines,
heading_height;
// sort and search behavior
@@ -270,16 +272,21 @@ public:
void clearSearchString() { mSearchString.clear(); }
+ // support right-click context menus for avatar/group lists
+ enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP };
+ void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; }
+
// 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 handleRightMouseDown(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);
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
/*virtual*/ void setEnabled(BOOL enabled);
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void onFocusReceived();
@@ -308,6 +315,11 @@ public:
S32 getMaxContentWidth() { return mMaxContentWidth; }
void setHeadingHeight(S32 heading_height);
+ /**
+ * Sets max visible lines without scroolbar, if this value equals to 0,
+ * then display all items.
+ */
+ void setPageLines(S32 page_lines );
void setCollapseEmptyColumns(BOOL collapse);
LLScrollListItem* hitItem(S32 x,S32 y);
@@ -338,7 +350,7 @@ public:
void sortOnce(S32 column, BOOL ascending);
// manually call this whenever editing list items in place to flag need for resorting
- void setNeedsSort() { mSorted = false; }
+ void setNeedsSort(bool val = true) { mSorted = !val; }
void dirtyColumns(); // some operation has potentially affected column layout or ordering
protected:
@@ -362,11 +374,13 @@ protected:
typedef std::deque<LLScrollListItem *> item_list;
item_list& getItemList() { return mItemList; }
+ void updateLineHeight();
+
private:
void selectPrevItem(BOOL extend_selection);
void selectNextItem(BOOL extend_selection);
void drawItems();
- void updateLineHeight();
+
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;
@@ -375,6 +389,10 @@ private:
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
+ static void showNameDetails(std::string id, bool is_group);
+ static void copyNameToClipboard(std::string id, bool is_group);
+ static void copySLURLToClipboard(std::string id, bool is_group);
+
S32 mLineHeight; // the max height of a single line
S32 mScrollLines; // how many lines we've scrolled down
S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight
@@ -421,6 +439,7 @@ private:
S32 mHighlightedItem;
class LLViewBorder* mBorder;
+ LLContextMenu *mPopupMenu;
LLWString mSearchString;
LLFrameTimer mSearchTimer;
@@ -438,6 +457,8 @@ private:
BOOL mDirty;
S32 mOriginalSelection;
+ ContextMenuType mContextMenuType;
+
typedef std::vector<LLScrollListColumn*> ordered_columns_t;
ordered_columns_t mColumnsIndexed;
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 1b0f3c9885..4bb45a3065 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -90,15 +90,7 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
mNameStack.clear();
setParseSilently(silent);
- // must have named elements at top level to submit for parsing
- if (sd.isMap())
- {
- readSDValues(sd, block);
- }
- else
- {
- parserWarning("Top level map required for LLSD->Block conversion");
- }
+ readSDValues(sd, block);
}
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index fbcbb55b85..b87f645f3f 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -38,30 +38,68 @@
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
: LLUICtrl(p)
+ , mSearchButton(NULL)
+ , mClearButton(NULL)
{
- S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
- S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
- LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
+ S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
+ S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
+ LLRect srch_btn_rect(p.search_button.left_pad, srch_btn_top, srch_btn_right, p.search_button.top_pad);
+ S32 text_pad_left = p.text_pad_left;
+ if (p.search_button_visible)
+ text_pad_left += srch_btn_rect.getWidth();
+
+ // Set up line editor.
LLLineEditor::Params line_editor_params(p);
line_editor_params.name("filter edit box");
line_editor_params.rect(getLocalRect());
line_editor_params.follows.flags(FOLLOWS_ALL);
- line_editor_params.text_pad_left(p.text_pad_left + search_btn_rect.getWidth());
+ line_editor_params.text_pad_left(text_pad_left);
+ line_editor_params.revert_on_esc(false);
line_editor_params.commit_callback.function(boost::bind(&LLUICtrl::onCommit, this));
+ line_editor_params.keystroke_callback(boost::bind(&LLSearchEditor::handleKeystroke, this));
mSearchEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_params);
addChild(mSearchEditor);
- LLButton::Params button_params(p.search_button);
- button_params.name(std::string("clear filter"));
- button_params.rect(search_btn_rect) ;
- button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
- button_params.tab_stop(false);
- button_params.click_callback.function(boost::bind(&LLUICtrl::onCommit, this));
+ if (p.search_button_visible)
+ {
+ // Set up search button.
+ LLButton::Params srch_btn_params(p.search_button);
+ srch_btn_params.name(std::string("search button"));
+ srch_btn_params.rect(srch_btn_rect) ;
+ srch_btn_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
+ srch_btn_params.tab_stop(false);
+ srch_btn_params.click_callback.function(boost::bind(&LLUICtrl::onCommit, this));
+
+ mSearchButton = LLUICtrlFactory::create<LLButton>(srch_btn_params);
+ mSearchEditor->addChild(mSearchButton);
+ }
+
+ if (p.clear_button_visible)
+ {
+ // Set up clear button.
+ S32 clr_btn_width = getRect().getHeight(); // button is square, and as tall as search editor
+ LLRect clear_btn_rect(getRect().getWidth() - clr_btn_width, getRect().getHeight(), getRect().getWidth(), 0);
+ LLButton::Params clr_btn_params(p.clear_button);
+ clr_btn_params.name(std::string("clear button"));
+ clr_btn_params.rect(clear_btn_rect) ;
+ clr_btn_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
+ clr_btn_params.tab_stop(false);
+ clr_btn_params.click_callback.function(boost::bind(&LLSearchEditor::onClearButtonClick, this, _2));
+
+ mClearButton = LLUICtrlFactory::create<LLButton>(clr_btn_params);
+ mSearchEditor->addChild(mClearButton);
+ }
+}
+
+//virtual
+void LLSearchEditor::draw()
+{
+ if (mClearButton)
+ mClearButton->setVisible(!mSearchEditor->getWText().empty());
- mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
- mSearchEditor->addChild(mSearchButton);
+ LLUICtrl::draw();
}
//virtual
@@ -89,6 +127,12 @@ BOOL LLSearchEditor::setLabelArg( const std::string& key, const LLStringExplicit
}
//virtual
+void LLSearchEditor::setLabel( const LLStringExplicit &new_label )
+{
+ mSearchEditor->setLabel(new_label);
+}
+
+//virtual
void LLSearchEditor::clear()
{
if (mSearchEditor)
@@ -96,3 +140,17 @@ void LLSearchEditor::clear()
mSearchEditor->clear();
}
}
+
+void LLSearchEditor::onClearButtonClick(const LLSD& data)
+{
+ setText(LLStringUtil::null);
+ mSearchEditor->doDelete(); // force keystroke callback
+}
+
+void LLSearchEditor::handleKeystroke()
+{
+ if (mKeystrokeCallback)
+ {
+ mKeystrokeCallback(this, getValue());
+ }
+}
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index cd2867b493..f395e7e816 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -50,10 +50,15 @@ class LLSearchEditor : public LLUICtrl
public:
struct Params : public LLInitParam::Block<Params, LLLineEditor::Params>
{
- Optional<LLButton::Params> search_button;
+ Optional<LLButton::Params> search_button, clear_button;
+ Optional<bool> search_button_visible, clear_button_visible;
+ Optional<commit_callback_t> keystroke_callback;
Params()
: search_button("search_button")
+ , search_button_visible("search_button_visible")
+ , clear_button("clear_button")
+ , clear_button_visible("clear_button_visible")
{
name = "search_editor";
}
@@ -66,26 +71,29 @@ protected:
public:
virtual ~LLSearchEditor() {}
+ /*virtual*/ void draw();
+
void setText(const LLStringExplicit &new_text) { mSearchEditor->setText(new_text); }
const std::string& getText() const { return mSearchEditor->getText(); }
-
// LLUICtrl interface
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const;
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
+ virtual void setLabel( const LLStringExplicit &new_label );
virtual void clear();
- void setKeystrokeCallback(LLLineEditor::callback_t callback, void* user_data)
- {
- if(mSearchEditor)
- mSearchEditor->setKeystrokeCallback(callback,user_data);
- }
+ void setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; }
+
+protected:
+ void onClearButtonClick(const LLSD& data);
+ virtual void handleKeystroke();
-private:
+ commit_callback_t mKeystrokeCallback;
LLLineEditor* mSearchEditor;
LLButton* mSearchButton;
+ LLButton* mClearButton;
};
#endif // LL_SEARCHEDITOR_H
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 840dd9b089..f86776384a 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -241,6 +241,8 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
void LLSlider::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
// since thumb image might still be decoding, need thumb to accomodate image size
updateThumbRect();
@@ -255,14 +257,14 @@ void LLSlider::draw()
getRect().getWidth() - mThumbImage->getWidth() / 2,
getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
- mTrackImage->draw(track_rect);
- mTrackHighlightImage->draw(highlight_rect);
+ mTrackImage->draw(track_rect, LLColor4::white % alpha);
+ mTrackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
// Thumb
if (hasFocus())
{
// Draw focus highlighting.
- mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+ mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
}
if( hasMouseCapture() ) // currently clicking on slider
@@ -270,25 +272,25 @@ void LLSlider::draw()
// Show ghost where thumb was before dragging began.
if (mThumbImage.notNull())
{
- mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+ mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % (0.3f * alpha));
}
if (mThumbImagePressed.notNull())
{
- mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor);
+ mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor % alpha);
}
}
else if (!isInEnabledChain())
{
if (mThumbImageDisabled.notNull())
{
- mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor);
+ mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor % alpha);
}
}
else
{
if (mThumbImage.notNull())
{
- mThumbImage->draw(mThumbRect, mThumbCenterColor);
+ mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha);
}
}
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 929a809d88..c16ac08014 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -54,8 +54,6 @@ LLStyle::LLStyle(const LLStyle::Params& p)
mFont(p.font()),
mLink(p.link_href),
mDropShadow(p.drop_shadow),
- mImageHeight(0),
- mImageWidth(0),
mImagep(p.image())
{}
@@ -100,9 +98,7 @@ void LLStyle::setImage(const LLUUID& src)
mImagep = LLUI::getUIImageByID(src);
}
-
-void LLStyle::setImageSize(S32 width, S32 height)
+void LLStyle::setImage(const std::string& name)
{
- mImageWidth = width;
- mImageHeight = height;
+ mImagep = LLUI::getUIImage(name);
}
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index dcf274a651..5e8883afd7 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -69,9 +69,9 @@ public:
LLUIImagePtr getImage() const;
void setImage(const LLUUID& src);
+ void setImage(const std::string& name);
- BOOL isImage() const { return ((mImageWidth != 0) && (mImageHeight != 0)); }
- void setImageSize(S32 width, S32 height);
+ BOOL isImage() const { return mImagep.notNull(); }
// inlined here to make it easier to compare to member data below. -MG
bool operator==(const LLStyle &rhs) const
@@ -82,8 +82,6 @@ public:
&& mFont == rhs.mFont
&& mLink == rhs.mLink
&& mImagep == rhs.mImagep
- && mImageHeight == rhs.mImageHeight
- && mImageWidth == rhs.mImageWidth
&& mItalic == rhs.mItalic
&& mBold == rhs.mBold
&& mUnderline == rhs.mUnderline
@@ -97,8 +95,6 @@ public:
BOOL mBold;
BOOL mUnderline;
BOOL mDropShadow;
- S32 mImageWidth;
- S32 mImageHeight;
protected:
~LLStyle() { }
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index e379954b4f..720ca692f7 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -31,9 +31,12 @@
*/
#include "linden_common.h"
+
#include "lltabcontainer.h"
+
#include "llfocusmgr.h"
#include "llbutton.h"
+#include "lllocalcliprect.h"
#include "llrect.h"
#include "llresizehandle.h"
#include "lltextbox.h"
@@ -303,7 +306,7 @@ void LLTabContainer::draw()
setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
- BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
+ BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0));
if (!mIsVertical)
{
mJumpPrevArrowBtn->setVisible( has_scroll_arrows );
@@ -426,7 +429,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
{
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -495,7 +498,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -537,7 +540,7 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -590,7 +593,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
// virtual
-BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect )
+BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect )
{
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
@@ -731,7 +734,7 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
{
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
- if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+ if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
{
if (has_scroll_arrows)
{
@@ -1837,12 +1840,11 @@ void LLTabContainer::updateMaxScrollPos()
void LLTabContainer::commitHoveredButton(S32 x, S32 y)
{
- if (hasMouseCapture())
+ if (!getTabsHidden() && hasMouseCapture())
{
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
S32 local_x = x - tuple->mButton->getRect().mLeft;
S32 local_y = y - tuple->mButton->getRect().mBottom;
if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index ebe76af966..89a0346896 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -99,7 +99,7 @@ public:
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect );
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect );
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType type, void* cargo_data,
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
new file mode 100644
index 0000000000..cb60b4fe36
--- /dev/null
+++ b/indra/llui/lltextbase.cpp
@@ -0,0 +1,457 @@
+/**
+ * @file lltextbase.cpp
+ * @author Martin Reddy
+ * @brief The base class of text box/editor, providing Url handling support
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltextbase.h"
+#include "llstl.h"
+#include "llview.h"
+#include "llwindow.h"
+#include "llmenugl.h"
+#include "lltooltip.h"
+#include "lluictrl.h"
+#include "llurlaction.h"
+#include "llurlregistry.h"
+
+#include <boost/bind.hpp>
+
+// global state for all text fields
+LLUIColor LLTextBase::mLinkColor = LLColor4::blue;
+
+bool LLTextBase::compare_segment_end::operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const
+{
+ return a->getEnd() < b->getEnd();
+}
+
+//
+// LLTextSegment
+//
+
+LLTextSegment::~LLTextSegment()
+{}
+
+S32 LLTextSegment::getWidth(S32 first_char, S32 num_chars) const { return 0; }
+S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; }
+S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; }
+void LLTextSegment::updateLayout(const LLTextBase& editor) {}
+F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { return draw_rect.mLeft; }
+S32 LLTextSegment::getMaxHeight() const { return 0; }
+bool LLTextSegment::canEdit() const { return false; }
+void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
+void LLTextSegment::linkToDocument(LLTextBase*) {}
+void LLTextSegment::setHasMouseHover(bool hover) {}
+const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
+void LLTextSegment::setColor(const LLColor4 &color) {}
+const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
+void LLTextSegment::setStyle(const LLStyleSP &style) {}
+void LLTextSegment::setToken( LLKeywordToken* token ) {}
+LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
+BOOL LLTextSegment::getToolTip( std::string& msg ) const { return FALSE; }
+void LLTextSegment::setToolTip( const std::string &msg ) {}
+void LLTextSegment::dump() const {}
+
+
+//
+// LLNormalTextSegment
+//
+
+LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor )
+: LLTextSegment(start, end),
+ mStyle( style ),
+ mToken(NULL),
+ mHasMouseHover(false),
+ mEditor(editor)
+{
+ mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
+}
+
+LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
+: LLTextSegment(start, end),
+ mToken(NULL),
+ mHasMouseHover(false),
+ mEditor(editor)
+{
+ mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
+
+ mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
+}
+
+F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+{
+ if( end - start > 0 )
+ {
+ if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
+ {
+ LLUIImagePtr image = mStyle->getImage();
+ S32 style_image_height = image->getHeight();
+ S32 style_image_width = image->getWidth();
+ image->draw(draw_rect.mLeft, draw_rect.mTop-style_image_height,
+ style_image_width, style_image_height);
+ }
+
+ return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect.mLeft, draw_rect.mBottom);
+ }
+ return draw_rect.mLeft;
+}
+
+// Draws a single text segment, reversing the color for selection if needed.
+F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y)
+{
+ const LLWString &text = mEditor.getWText();
+
+ F32 right_x = x;
+ if (!mStyle->isVisible())
+ {
+ return right_x;
+ }
+
+ const LLFontGL* font = mStyle->getFont();
+
+ LLColor4 color = mStyle->getColor();
+
+ font = mStyle->getFont();
+
+ if( selection_start > seg_start )
+ {
+ // Draw normally
+ S32 start = seg_start;
+ S32 end = llmin( selection_start, seg_end );
+ S32 length = end - start;
+ font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ }
+ x = right_x;
+
+ if( (selection_start < seg_end) && (selection_end > seg_start) )
+ {
+ // Draw reversed
+ S32 start = llmax( selection_start, seg_start );
+ S32 end = llmin( selection_end, seg_end );
+ S32 length = end - start;
+
+ font->render(text, start, x, y,
+ LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
+ LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ }
+ x = right_x;
+ if( selection_end < seg_end )
+ {
+ // Draw normally
+ S32 start = llmax( selection_end, seg_start );
+ S32 end = seg_end;
+ S32 length = end - start;
+ font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ }
+ return right_x;
+}
+
+S32 LLNormalTextSegment::getMaxHeight() const
+{
+ return mMaxHeight;
+}
+
+BOOL LLNormalTextSegment::getToolTip(std::string& msg) const
+{
+ // do we have a tooltip for a loaded keyword (for script editor)?
+ if (mToken && !mToken->getToolTip().empty())
+ {
+ const LLWString& wmsg = mToken->getToolTip();
+ msg = wstring_to_utf8str(wmsg);
+ return TRUE;
+ }
+ // or do we have an explicitly set tooltip (e.g., for Urls)
+ if (! mTooltip.empty())
+ {
+ msg = mTooltip;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void LLNormalTextSegment::setToolTip(const std::string& tooltip)
+{
+ // we cannot replace a keyword tooltip that's loaded from a file
+ if (mToken)
+ {
+ llwarns << "LLTextSegment::setToolTip: cannot replace keyword tooltip." << llendl;
+ return;
+ }
+ mTooltip = tooltip;
+}
+
+S32 LLNormalTextSegment::getWidth(S32 first_char, S32 num_chars) const
+{
+ LLWString text = mEditor.getWText();
+ return mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
+}
+
+S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
+{
+ LLWString text = mEditor.getWText();
+ return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
+ (F32)segment_local_x_coord,
+ F32_MAX,
+ num_chars,
+ round);
+}
+
+S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+{
+ LLWString text = mEditor.getWText();
+ S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
+ (F32)num_pixels,
+ max_chars,
+ mEditor.getWordWrap());
+
+ if (num_chars == 0
+ && line_offset == 0
+ && max_chars > 0)
+ {
+ // If at the beginning of a line, and a single character won't fit, draw it anyway
+ num_chars = 1;
+ }
+ if (mStart + segment_offset + num_chars == mEditor.getLength())
+ {
+ // include terminating NULL
+ num_chars++;
+ }
+ return num_chars;
+}
+
+void LLNormalTextSegment::dump() const
+{
+ llinfos << "Segment [" <<
+// mColor.mV[VX] << ", " <<
+// mColor.mV[VY] << ", " <<
+// mColor.mV[VZ] << "]\t[" <<
+ mStart << ", " <<
+ getEnd() << "]" <<
+ llendl;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LLTextBase
+//
+
+LLTextBase::LLTextBase(const LLUICtrl::Params &p) :
+ mHoverSegment(NULL),
+ mDefaultFont(p.font),
+ mParseHTML(TRUE),
+ mPopupMenu(NULL)
+{
+}
+
+LLTextBase::~LLTextBase()
+{
+ clearSegments();
+}
+
+void LLTextBase::clearSegments()
+{
+ setHoverSegment(NULL);
+ mSegments.clear();
+}
+
+void LLTextBase::setHoverSegment(LLTextSegmentPtr segment)
+{
+ if (mHoverSegment)
+ {
+ mHoverSegment->setHasMouseHover(false);
+ }
+ if (segment)
+ {
+ segment->setHasMouseHover(true);
+ }
+ mHoverSegment = segment;
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp )
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
+{
+ segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const
+{
+ LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+// Finds the text segment (if any) at the give local screen position
+LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+{
+ // Find the cursor position at the requested local screen position
+ S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
+ segment_set_t::iterator seg_iter = getSegIterContaining(offset);
+ if (seg_iter != mSegments.end())
+ {
+ return *seg_iter;
+ }
+ else
+ {
+ return LLTextSegmentPtr();
+ }
+}
+
+BOOL LLTextBase::handleHoverOverUrl(S32 x, S32 y)
+{
+ setHoverSegment(NULL);
+
+ // Check to see if we're over an HTML-style link
+ LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
+ if (cur_segment)
+ {
+ setHoverSegment(cur_segment);
+
+ LLStyleSP style = cur_segment->getStyle();
+ if (style && style->isLink())
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL LLTextBase::handleMouseUpOverUrl(S32 x, S32 y)
+{
+ if (mParseHTML && mHoverSegment)
+ {
+ LLStyleSP style = mHoverSegment->getStyle();
+ if (style && style->isLink())
+ {
+ LLUrlAction::clickAction(style->getLinkHREF());
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL LLTextBase::handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y)
+{
+ // pop up a context menu for any Url under the cursor
+ const LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->getStyle() && cur_segment->getStyle()->isLink())
+ {
+ delete mPopupMenu;
+ mPopupMenu = createUrlContextMenu(cur_segment->getStyle()->getLinkHREF());
+ if (mPopupMenu)
+ {
+ mPopupMenu->show(x, y);
+ LLMenuGL::showPopup(view, mPopupMenu, x, y);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+{
+ std::string tooltip_msg;
+ const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
+ if (cur_segment && cur_segment->getToolTip( tooltip_msg ) && view)
+ {
+ // Use a slop area around the cursor
+ const S32 SLOP = 8;
+ // Convert rect local to screen coordinates
+ view->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;
+
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(tooltip_msg)
+ .sticky_rect(sticky_rect_screen));
+ }
+ return TRUE;
+}
+
+LLContextMenu *LLTextBase::createUrlContextMenu(const std::string &in_url)
+{
+ // work out the XUI menu file to use for this url
+ LLUrlMatch match;
+ std::string url = in_url;
+ if (! LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return NULL;
+ }
+
+ std::string xui_file = match.getMenuName();
+ if (xui_file.empty())
+ {
+ return NULL;
+ }
+
+ // set up the callbacks for all of the potential menu items, N.B. we
+ // don't use const ref strings in callbacks in case url goes out of scope
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.Open", boost::bind(&LLUrlAction::openURL, url));
+ registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));
+ registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
+ registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
+ registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
+ registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
+ registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
+
+ // create and return the context menu from the XUI file
+ return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
new file mode 100644
index 0000000000..82b9f6a43f
--- /dev/null
+++ b/indra/llui/lltextbase.h
@@ -0,0 +1,198 @@
+/**
+ * @file lltextbase.h
+ * @author Martin Reddy
+ * @brief The base class of text box/editor, providing Url handling support
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTBASE_H
+#define LL_LLTEXTBASE_H
+
+#include "v4color.h"
+#include "llstyle.h"
+#include "llkeywords.h"
+#include "lluictrl.h"
+
+#include <string>
+#include <set>
+
+class LLContextMenu;
+class LLTextSegment;
+
+typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
+
+///
+/// The LLTextBase class provides a base class for all text fields, such
+/// as LLTextEditor and LLTextBox. It implements shared functionality
+/// such as Url highlighting and opening.
+///
+class LLTextBase
+{
+public:
+ LLTextBase(const LLUICtrl::Params &p);
+ virtual ~LLTextBase();
+
+ /// specify the color to display Url hyperlinks in the text
+ static void setLinkColor(LLColor4 color) { mLinkColor = color; }
+
+ /// enable/disable the automatic hyperlinking of Urls in the text
+ void setParseHTML(BOOL parsing) { mParseHTML=parsing; }
+
+ // public text editing virtual methods
+ virtual LLWString getWText() const = 0;
+ virtual BOOL allowsEmbeddedItems() const { return FALSE; }
+ virtual BOOL getWordWrap() { return mWordWrap; }
+ virtual S32 getLength() const = 0;
+
+protected:
+ struct compare_segment_end
+ {
+ bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const;
+ };
+ typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
+
+ // routines to manage segments
+ void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
+ void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
+ LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
+ segment_set_t::iterator getSegIterContaining(S32 index);
+ segment_set_t::const_iterator getSegIterContaining(S32 index) const;
+ void clearSegments();
+ void setHoverSegment(LLTextSegmentPtr segment);
+
+ // event handling for Urls within the text field
+ BOOL handleHoverOverUrl(S32 x, S32 y);
+ BOOL handleMouseUpOverUrl(S32 x, S32 y);
+ BOOL handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y);
+ BOOL handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+
+ // pure virtuals that have to be implemented by any subclasses
+ virtual S32 getLineCount() const = 0;
+ virtual S32 getLineStart( S32 line ) const = 0;
+ virtual S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const = 0;
+
+ // protected member variables
+ static LLUIColor mLinkColor;
+ const LLFontGL *mDefaultFont;
+ segment_set_t mSegments;
+ LLTextSegmentPtr mHoverSegment;
+ BOOL mParseHTML;
+ BOOL mWordWrap;
+
+private:
+ // create a popup context menu for the given Url
+ static LLContextMenu *createUrlContextMenu(const std::string &url);
+
+ LLContextMenu *mPopupMenu;
+};
+
+///
+/// A text segment is used to specify a subsection of a text string
+/// that should be formatted differently, such as a hyperlink. It
+/// includes a start/end offset from the start of the string, a
+/// style to render with, an optional tooltip, etc.
+///
+class LLTextSegment : public LLRefCount
+{
+public:
+ LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
+ virtual ~LLTextSegment();
+
+ virtual S32 getWidth(S32 first_char, S32 num_chars) const;
+ virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+ virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ virtual void updateLayout(const class LLTextBase& editor);
+ virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ virtual S32 getMaxHeight() const;
+ virtual bool canEdit() const;
+ virtual void unlinkFromDocument(class LLTextBase* editor);
+ virtual void linkToDocument(class LLTextBase* editor);
+
+ virtual void setHasMouseHover(bool hover);
+ virtual const LLColor4& getColor() const;
+ virtual void setColor(const LLColor4 &color);
+ virtual const LLStyleSP getStyle() const;
+ virtual void setStyle(const LLStyleSP &style);
+ virtual void setToken( LLKeywordToken* token );
+ virtual LLKeywordToken* getToken() const;
+ virtual BOOL getToolTip( std::string& msg ) const;
+ virtual void setToolTip(const std::string& tooltip);
+ virtual void dump() const;
+
+ S32 getStart() const { return mStart; }
+ void setStart(S32 start) { mStart = start; }
+ S32 getEnd() const { return mEnd; }
+ void setEnd( S32 end ) { mEnd = end; }
+
+protected:
+ S32 mStart;
+ S32 mEnd;
+};
+
+class LLNormalTextSegment : public LLTextSegment
+{
+public:
+ LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor );
+ LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
+
+ /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
+ /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtual*/ S32 getMaxHeight() const;
+ /*virtual*/ bool canEdit() const { return true; }
+ /*virtual*/ void setHasMouseHover(bool hover) { mHasMouseHover = hover; }
+ /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
+ /*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
+ /*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
+ /*virtual*/ void setStyle(const LLStyleSP &style) { mStyle = style; }
+ /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
+ /*virtual*/ LLKeywordToken* getToken() const { return mToken; }
+ /*virtual*/ BOOL getToolTip( std::string& msg ) const;
+ /*virtual*/ void setToolTip(const std::string& tooltip);
+ /*virtual*/ void dump() const;
+
+protected:
+ F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y);
+
+ class LLTextBase& mEditor;
+ LLStyleSP mStyle;
+ S32 mMaxHeight;
+ LLKeywordToken* mToken;
+ bool mHasMouseHover;
+ std::string mTooltip;
+};
+
+class LLIndexSegment : public LLTextSegment
+{
+public:
+ LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {}
+};
+
+#endif
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 96e72487b8..810626268f 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -32,33 +32,26 @@
#include "linden_common.h"
#include "lltextbox.h"
-#include "lllink.h"
#include "lluictrlfactory.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+#include "llurlregistry.h"
+#include "llstyle.h"
static LLDefaultChildRegistry::Register<LLTextBox> r("text");
-//*NOTE
-// LLLink is not used in code for now, therefor Visual Studio doesn't build it.
-// "link" is registered here to force Visual Studio to build LLLink class.
-static LLDefaultChildRegistry::Register<LLLink> register_link("link");
-
LLTextBox::Params::Params()
: text_color("text_color"),
length("length"),
type("type"),
- highlight_on_hover("hover", false),
border_visible("border_visible", false),
border_drop_shadow_visible("border_drop_shadow_visible", false),
bg_visible("bg_visible", false),
use_ellipses("use_ellipses"),
word_wrap("word_wrap", false),
drop_shadow_visible("drop_shadow_visible"),
- hover_color("hover_color"),
disabled_color("disabled_color"),
background_color("background_color"),
- border_color("border_color"),
v_pad("v_pad", 0),
h_pad("h_pad", 0),
line_spacing("line_spacing", 0),
@@ -68,9 +61,7 @@ LLTextBox::Params::Params()
LLTextBox::LLTextBox(const LLTextBox::Params& p)
: LLUICtrl(p),
- mFontGL(p.font),
- mHoverActive( p.highlight_on_hover ),
- mHasHover( FALSE ),
+ LLTextBase(p),
mBackgroundVisible( p.bg_visible ),
mBorderVisible( p.border_visible ),
mShadowType( p.font_shadow ),
@@ -83,13 +74,11 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
mTextColor(p.text_color()),
mDisabledColor(p.disabled_color()),
mBackgroundColor(p.background_color()),
- mBorderColor(p.border_color()),
- mHoverColor(p.hover_color()),
mHAlign(p.font_halign),
mLineSpacing(p.line_spacing),
- mWordWrap( p.word_wrap ),
mDidWordWrap(FALSE)
{
+ mWordWrap = p.word_wrap;
setText( p.text() );
}
@@ -97,9 +86,9 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // HACK: Only do this if there actually is a click callback, so that
+ // HACK: Only do this if there actually is something to click, so that
// overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback)
+ if (isClickable())
{
handled = TRUE;
@@ -121,10 +110,9 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
// We only handle the click if the click both started and ended within us
- // HACK: Only do this if there actually is a click callback, so that
+ // HACK: Only do this if there actually is something to click, so that
// overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback
- && hasMouseCapture())
+ if (isClickable() && hasMouseCapture())
{
handled = TRUE;
@@ -136,27 +124,44 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
make_ui_sound("UISndClickRelease");
}
- // 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 (mClickedCallback)
+ // handle clicks on Urls in the textbox first
+ if (! handleMouseUpOverUrl(x, y))
{
- mClickedCallback();
+ // 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 (mClickedCallback && ! handled)
+ {
+ mClickedCallback();
+ }
}
}
return handled;
}
+BOOL LLTextBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ // pop up a context menu for any Url under the cursor
+ return handleRightMouseDownOverUrl(this, x, y);
+}
+
BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = LLView::handleHover(x,y,mask);
- if(mHoverActive)
+ // Check to see if we're over an HTML-style link
+ if (handleHoverOverUrl(x, y))
{
- mHasHover = TRUE; // This should be set every frame during a hover.
- getWindow()->setCursor(UI_CURSOR_ARROW);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
+ getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
}
- return (handled || mHasHover);
+ return LLView::handleHover(x,y,mask);
+}
+
+BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+{
+ return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
}
void LLTextBox::setText(const LLStringExplicit& text)
@@ -168,7 +173,7 @@ void LLTextBox::setText(const LLStringExplicit& text)
else
{
mText.assign(text);
- setLineLengths();
+ updateDisplayTextAndSegments();
}
}
@@ -177,11 +182,11 @@ void LLTextBox::setLineLengths()
mLineLengthList.clear();
std::string::size_type cur = 0;
- std::string::size_type len = mText.getWString().size();
+ std::string::size_type len = mDisplayText.size();
while (cur < len)
{
- std::string::size_type end = mText.getWString().find('\n', cur);
+ std::string::size_type end = mDisplayText.find('\n', cur);
std::string::size_type runLen;
if (end == std::string::npos)
@@ -199,20 +204,12 @@ void LLTextBox::setLineLengths()
}
}
-void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
+LLWString LLTextBox::wrapText(const LLWString &wtext, S32 &hoffset, S32 &line_num, F32 max_width)
{
- if (max_width < 0.0f)
- {
- max_width = (F32)getRect().getWidth();
- }
-
- LLWString wtext = utf8str_to_wstring(in_text);
LLWString final_wtext;
- LLWString::size_type cur = 0;;
- LLWString::size_type len = wtext.size();
- F32 line_height = mFontGL->getLineHeight();
- S32 line_num = 1;
+ LLWString::size_type cur = 0;
+ LLWString::size_type len = wtext.size();
while (cur < len)
{
LLWString::size_type end = wtext.find('\n', cur);
@@ -221,41 +218,121 @@ void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
end = len;
}
+ bool charsRemaining = true;
LLWString::size_type runLen = end - cur;
if (runLen > 0)
{
+ // work out how many chars can fit onto the current line
LLWString run(wtext, cur, runLen);
LLWString::size_type useLen =
- mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
+ mDefaultFont->maxDrawableChars(run.c_str(), max_width-hoffset, runLen, TRUE);
+ charsRemaining = (cur + useLen < len);
+ // try to break lines on word boundaries
+ if (useLen < run.size())
+ {
+ LLWString::size_type prev_use_len = useLen;
+ while (useLen > 0 && ! isspace(run[useLen-1]) && ! ispunct(run[useLen-1]))
+ {
+ --useLen;
+ }
+ if (useLen == 0)
+ {
+ useLen = prev_use_len;
+ }
+ }
+
+ // add the chars that could fit onto one line to our result
final_wtext.append(wtext, cur, useLen);
cur += useLen;
- // not enough room to add any more characters
- if (useLen == 0) break;
+ hoffset += mDefaultFont->getWidth(run.substr(0, useLen).c_str());
+
+ // abort if not enough room to add any more characters
+ if (useLen == 0)
+ {
+ break;
+ }
}
- if (cur < len)
+ if (charsRemaining)
{
if (wtext[cur] == '\n')
{
cur += 1;
}
- line_num +=1;
- // Don't wrap the last line if the text is going to spill off
- // the bottom of the rectangle. Assume we prefer to run off
- // the right edge.
- // *TODO: Is this the right behavior?
- if((line_num-1)*line_height <= (F32)getRect().getHeight())
+ final_wtext += '\n';
+ hoffset = 0;
+ line_num += 1;
+ }
+ }
+
+ return final_wtext;
+}
+
+void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
+{
+ mDidWordWrap = TRUE;
+ setText(wstring_to_utf8str(getWrappedText(in_text, max_width)));
+}
+
+LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_width)
+{
+ //
+ // we don't want to wrap Urls otherwise we won't be able to detect their
+ // presence for hyperlinking. So we look for all Urls, and then word wrap
+ // the text before and after, but never break a Url in the middle. We
+ // also need to consider that the Url will be displayed as a label (not
+ // necessary the actual Url string).
+ //
+
+ if (max_width < 0.0f)
+ {
+ max_width = (F32)getRect().getWidth();
+ }
+
+ LLWString wtext = utf8str_to_wstring(in_text);
+ LLWString final_wtext;
+ S32 line_num = 1;
+ S32 hoffset = 0;
+
+ // find the next Url in the text string
+ LLUrlMatch match;
+ while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(wtext), match))
+ {
+ S32 start = match.getStart();
+ S32 end = match.getEnd() + 1;
+
+ // perform word wrap on the text before the Url
+ final_wtext += wrapText(wtext.substr(0, start), hoffset, line_num, max_width);
+
+ // add the Url (but compute width based on its label)
+ S32 label_width = mDefaultFont->getWidth(match.getLabel());
+ if (hoffset > 0 && hoffset + label_width > max_width)
+ {
+ final_wtext += '\n';
+ line_num++;
+ hoffset = 0;
+ }
+ final_wtext += wtext.substr(start, end-start);
+ hoffset += label_width;
+ if (hoffset > max_width)
+ {
+ final_wtext += '\n';
+ line_num++;
+ hoffset = 0;
+ // eat any leading whitespace on the next line
+ while (isspace(wtext[end]) && end < (S32)wtext.size())
{
- final_wtext += '\n';
+ end++;
}
}
+
+ // move on to the rest of the text after the Url
+ wtext = wtext.substr(end, wtext.size() - end + 1);
}
-
- mDidWordWrap = TRUE;
- std::string final_text = wstring_to_utf8str(final_wtext);
- setText(final_text);
+ final_wtext += wrapText(wtext, hoffset, line_num, max_width);
+ return final_wtext;
}
S32 LLTextBox::getTextPixelWidth()
@@ -268,7 +345,7 @@ S32 LLTextBox::getTextPixelWidth()
iter != mLineLengthList.end(); ++iter)
{
S32 line_length = *iter;
- S32 line_width = mFontGL->getWidth( mText.getWString().c_str(), cur_pos, line_length );
+ S32 line_width = mDefaultFont->getWidth( mDisplayText.c_str(), cur_pos, line_length );
if( line_width > max_line_width )
{
max_line_width = line_width;
@@ -278,7 +355,7 @@ S32 LLTextBox::getTextPixelWidth()
}
else
{
- max_line_width = mFontGL->getWidth(mText.getWString().c_str());
+ max_line_width = mDefaultFont->getWidth(mDisplayText.c_str());
}
return max_line_width;
}
@@ -290,7 +367,7 @@ S32 LLTextBox::getTextPixelHeight()
{
num_lines = 1;
}
- return (S32)(num_lines * mFontGL->getLineHeight());
+ return (S32)(num_lines * mDefaultFont->getLineHeight());
}
void LLTextBox::setValue(const LLSD& value )
@@ -302,12 +379,14 @@ void LLTextBox::setValue(const LLSD& value )
BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
{
mText.setArg(key, text);
- setLineLengths();
+ updateDisplayTextAndSegments();
return TRUE;
}
void LLTextBox::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
if (mBorderVisible)
{
gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
@@ -318,13 +397,13 @@ void LLTextBox::draw()
static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- color_drop_shadow, drop_shadow_tooltip);
+ color_drop_shadow % alpha, drop_shadow_tooltip);
}
if (mBackgroundVisible)
{
LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- gl_rect_2d( r, mBackgroundColor.get() );
+ gl_rect_2d( r, mBackgroundColor.get() % alpha );
}
S32 text_x = 0;
@@ -345,18 +424,11 @@ void LLTextBox::draw()
if ( getEnabled() )
{
- if(mHasHover)
- {
- drawText( text_x, text_y, mHoverColor.get() );
- }
- else
- {
- drawText( text_x, text_y, mTextColor.get() );
- }
+ drawText( text_x, text_y, mDisplayText, mTextColor.get() );
}
else
{
- drawText( text_x, text_y, mDisabledColor.get() );
+ drawText( text_x, text_y, mDisplayText, mDisabledColor.get() );
}
if (sDebugRects)
@@ -370,48 +442,314 @@ void LLTextBox::draw()
//{
// drawDebugRect();
//}
-
- mHasHover = FALSE; // This is reset every frame.
}
void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- // reparse line lengths
+ // reparse line lengths (don't need to recalculate the display text)
setLineLengths();
LLView::reshape(width, height, called_from_parent);
}
-void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
+void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color )
{
- if( mLineLengthList.empty() )
+ F32 alpha = getDrawContext().mAlpha;
+ if (mSegments.size() > 1)
{
- mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- 0,
- mShadowType,
- S32_MAX, getRect().getWidth(), NULL, mUseEllipses);
+ // we have Urls (or other multi-styled segments)
+ drawTextSegments(x, y, text);
+ }
+ else if( mLineLengthList.empty() )
+ {
+ // simple case of 1 line of text in one style
+ mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha,
+ mHAlign, mVAlign,
+ 0,
+ mShadowType,
+ S32_MAX, getRect().getWidth(), NULL, mUseEllipses);
}
else
{
+ // simple case of multiple lines of text, all in the same style
S32 cur_pos = 0;
for (std::vector<S32>::iterator iter = mLineLengthList.begin();
iter != mLineLengthList.end(); ++iter)
{
S32 line_length = *iter;
- mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- 0,
- mShadowType,
- line_length, getRect().getWidth(), NULL, mUseEllipses );
+ mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha,
+ mHAlign, mVAlign,
+ 0,
+ mShadowType,
+ line_length, getRect().getWidth(), NULL, mUseEllipses );
cur_pos += line_length + 1;
- y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing;
+ S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing;
+ y -= line_height;
+ if(y < line_height)
+ break;
}
}
}
void LLTextBox::reshapeToFitText()
{
+ // wrap remaining lines that did not fit on call to setWrappedText()
+ setLineLengths();
+
S32 width = getTextPixelWidth();
S32 height = getTextPixelHeight();
reshape( width + 2 * mHPad, height + 2 * mVPad );
}
+
+S32 LLTextBox::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+{
+ // Returns the character offset for the character under the local (x, y) coordinate.
+ // When round is true, if the position is on the right half of a character, the cursor
+ // will be put to its right. If round is false, the cursor will always be put to the
+ // character's left.
+
+ LLRect rect = getLocalRect();
+ rect.mLeft += mHPad;
+ rect.mRight -= mHPad;
+ rect.mTop += mVPad;
+ rect.mBottom -= mVPad;
+
+ // Figure out which line we're nearest to.
+ S32 total_lines = getLineCount();
+ S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing;
+ S32 line = (rect.mTop - 1 - local_y) / line_height;
+ if (line >= total_lines)
+ {
+ return getLength(); // past the end
+ }
+
+ line = llclamp( line, 0, total_lines );
+ S32 line_start = getLineStart(line);
+ S32 next_start = getLineStart(line+1);
+ S32 line_end = (next_start != line_start) ? next_start - 1 : getLength();
+ if (line_start == -1)
+ {
+ return 0;
+ }
+
+ S32 line_len = line_end - line_start;
+ S32 pos = mDefaultFont->charFromPixelOffset(mDisplayText.c_str(), line_start,
+ (F32)(local_x - rect.mLeft),
+ (F32)rect.getWidth(),
+ line_len, round);
+
+ return line_start + pos;
+}
+
+S32 LLTextBox::getLineStart( S32 line ) const
+{
+ line = llclamp(line, 0, getLineCount()-1);
+
+ S32 result = 0;
+ for (int i = 0; i < line; i++)
+ {
+ result += mLineLengthList[i] + 1 /* add newline */;
+ }
+
+ return result;
+}
+
+void LLTextBox::updateDisplayTextAndSegments()
+{
+ // remove any previous segment list
+ clearSegments();
+
+ // if URL parsing is turned off, then not much to bo
+ if (! mParseHTML)
+ {
+ mDisplayText = mText.getWString();
+ setLineLengths();
+ return;
+ }
+
+ // create unique text segments for Urls
+ mDisplayText.clear();
+ S32 end = 0;
+ LLUrlMatch match;
+ LLWString text = mText.getWString();
+
+ // find the next Url in the text string
+ while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(text), match,
+ boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) )
+ {
+ // work out the char offset for the start/end of the url
+ S32 seg_start = mDisplayText.size();
+ S32 start = seg_start + match.getStart();
+ end = start + match.getLabel().size();
+
+ // create a segment for the text before the Url
+ mSegments.insert(new LLNormalTextSegment(new LLStyle(), seg_start, start, *this));
+ mDisplayText += text.substr(0, match.getStart());
+
+ // create a segment for the Url text
+ LLStyleSP html(new LLStyle);
+ html->setVisible(true);
+ html->setColor(mLinkColor);
+ html->mUnderline = TRUE;
+ html->setLinkHREF(match.getUrl());
+
+ LLNormalTextSegment *html_seg = new LLNormalTextSegment(html, start, end, *this);
+ html_seg->setToolTip(match.getTooltip());
+
+ mSegments.insert(html_seg);
+ mDisplayText += utf8str_to_wstring(match.getLabel());
+
+ // move on to the rest of the text after the Url
+ text = text.substr(match.getEnd()+1, text.size() - match.getEnd());
+ }
+
+ // output a segment for the remaining text
+ if (text.size() > 0)
+ {
+ mSegments.insert(new LLNormalTextSegment(new LLStyle(), end, end + text.size(), *this));
+ mDisplayText += text;
+ }
+
+ // strip whitespace from the end of the text
+ while (mDisplayText.size() > 0 && isspace(mDisplayText[mDisplayText.size()-1]))
+ {
+ mDisplayText = mDisplayText.substr(0, mDisplayText.size() - 1);
+
+ segment_set_t::iterator it = getSegIterContaining(mDisplayText.size());
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr seg = *it;
+ seg->setEnd(seg->getEnd()-1);
+ }
+ }
+
+ // we may have changed the line lengths, so recalculate them
+ setLineLengths();
+}
+
+void LLTextBox::onUrlLabelUpdated(const std::string &url, const std::string &label)
+{
+ if (mDidWordWrap)
+ {
+ // re-word wrap as the url label lengths may have changed
+ setWrappedText(mText.getString());
+ }
+ else
+ {
+ // or just update the display text with the latest Url labels
+ updateDisplayTextAndSegments();
+ }
+}
+
+bool LLTextBox::isClickable() const
+{
+ // return true if we have been given a click callback
+ if (mClickedCallback)
+ {
+ return true;
+ }
+
+ // also return true if we have a clickable Url in the text
+ segment_set_t::const_iterator it;
+ for (it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegmentPtr segmentp = *it;
+ if (segmentp)
+ {
+ const LLStyleSP style = segmentp->getStyle();
+ if (style && style->isLink())
+ {
+ return true;
+ }
+ }
+ }
+
+ // otherwise there is nothing clickable here
+ return false;
+}
+
+void LLTextBox::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text)
+{
+ F32 alpha = getDrawContext().mAlpha;
+
+ const S32 text_len = text.length();
+ if (text_len <= 0)
+ {
+ return;
+ }
+
+ S32 cur_line = 0;
+ S32 num_lines = getLineCount();
+ S32 line_start = getLineStart(cur_line);
+ S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing;
+ F32 text_y = (F32) init_y;
+ segment_set_t::iterator cur_seg = mSegments.begin();
+
+ // render a line of text at a time
+ const LLRect textRect = getLocalRect();
+ while((textRect.mBottom <= text_y) && (cur_line < num_lines))
+ {
+ S32 next_start = -1;
+ S32 line_end = text_len;
+
+ if ((cur_line + 1) < num_lines)
+ {
+ next_start = getLineStart(cur_line + 1);
+ line_end = next_start;
+ }
+ if ( text[line_end-1] == '\n' )
+ {
+ --line_end;
+ }
+
+ // render all segments on this line
+ F32 text_x = init_x;
+ S32 seg_start = line_start;
+ while (seg_start < line_end && cur_seg != mSegments.end())
+ {
+ // move to the next segment (or continue the previous one)
+ LLTextSegment *cur_segment = *cur_seg;
+ while (cur_segment->getEnd() <= seg_start)
+ {
+ if (++cur_seg == mSegments.end())
+ {
+ return;
+ }
+ cur_segment = *cur_seg;
+ }
+
+ // Draw a segment within the line
+ S32 clipped_end = llmin( line_end, cur_segment->getEnd() );
+ S32 clipped_len = clipped_end - seg_start;
+ if( clipped_len > 0 )
+ {
+ LLStyleSP style = cur_segment->getStyle();
+ if (style && style->isVisible())
+ {
+ // work out the color for the segment
+ LLColor4 color ;
+ if (getEnabled())
+ {
+ color = style->isLink() ? mLinkColor.get() : mTextColor.get();
+ }
+ else
+ {
+ color = mDisabledColor.get();
+ }
+ color = color % alpha;
+
+ // render a single line worth for this segment
+ mDefaultFont->render(text, seg_start, text_x, text_y, color,
+ mHAlign, mVAlign, 0, mShadowType, clipped_len,
+ textRect.getWidth(), &text_x, mUseEllipses);
+ }
+
+ seg_start += clipped_len;
+ }
+ }
+
+ // move down one line
+ text_y -= (F32)line_height;
+ line_start = next_start;
+ cur_line++;
+ }
+}
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index d807fe7639..291d1dc517 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -37,10 +37,11 @@
#include "v4color.h"
#include "llstring.h"
#include "lluistring.h"
+#include "lltextbase.h"
-
-class LLTextBox
-: public LLUICtrl
+class LLTextBox :
+ public LLTextBase,
+ public LLUICtrl
{
public:
@@ -51,8 +52,7 @@ public:
{
Optional<std::string> text;
- Optional<bool> highlight_on_hover,
- border_visible,
+ Optional<bool> border_visible,
border_drop_shadow_visible,
bg_visible,
use_ellipses,
@@ -65,10 +65,8 @@ public:
length;
Optional<LLUIColor> text_color,
- hover_color,
disabled_color,
- background_color,
- border_color;
+ background_color;
Optional<S32> v_pad,
h_pad,
@@ -90,14 +88,12 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
void setColor( const LLColor4& c ) { mTextColor = c; }
void setDisabledColor( const LLColor4& c) { mDisabledColor = c; }
void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; }
- void setBorderColor( const LLColor4& c) { mBorderColor = c; }
-
- void setHoverColor( const LLColor4& c ) { mHoverColor = c; }
- void setHoverActive( BOOL active ) { mHoverActive = active; }
void setText( const LLStringExplicit& text );
void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.f); // -1 means use existing control width
@@ -112,35 +108,42 @@ public:
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button
- const LLFontGL* getFont() const { return mFontGL; }
+ const LLFontGL* getFont() const { return mDefaultFont; }
void reshapeToFitText();
const std::string& getText() const { return mText.getString(); }
+ LLWString getWText() const { return mDisplayText; }
S32 getTextPixelWidth();
S32 getTextPixelHeight();
+ S32 getLength() const { return mDisplayText.length(); }
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const { return LLSD(getText()); }
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
-private:
+protected:
+ S32 getLineCount() const { return mLineLengthList.size(); }
+ S32 getLineStart( S32 line ) const;
+ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+ LLWString getWrappedText(const LLStringExplicit& in_text, F32 max_width = -1.f);
void setLineLengths();
- void drawText(S32 x, S32 y, const LLColor4& color );
+ void updateDisplayTextAndSegments();
+ virtual void drawText(S32 x, S32 y, const LLWString &text, const LLColor4& color );
+ void onUrlLabelUpdated(const std::string &url, const std::string &label);
+ bool isClickable() const;
+ LLWString wrapText(const LLWString &wtext, S32 &hoffset, S32 &line_num, F32 max_width);
+ void drawTextSegments(S32 x, S32 y, const LLWString &text);
LLUIString mText;
- const LLFontGL* mFontGL;
- LLUIColor mTextColor;
- LLUIColor mDisabledColor;
- LLUIColor mBackgroundColor;
- LLUIColor mBorderColor;
- LLUIColor mHoverColor;
-
- BOOL mHoverActive;
- BOOL mHasHover;
+ LLWString mDisplayText;
+ LLUIColor mTextColor;
+ LLUIColor mDisabledColor;
+ LLUIColor mBackgroundColor;
+ LLUIColor mBorderColor;
+
BOOL mBackgroundVisible;
BOOL mBorderVisible;
- BOOL mWordWrap;
BOOL mDidWordWrap;
LLFontGL::ShadowType mShadowType;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 921041d17f..983777b747 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -38,6 +38,8 @@
#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR
#include "llfontgl.h"
+#include "llgl.h" // LLGLSUIDefault()
+#include "lllocalcliprect.h"
#include "llrender.h"
#include "llui.h"
#include "lluictrlfactory.h"
@@ -59,6 +61,8 @@
#include "lltextparser.h"
#include "llscrollcontainer.h"
#include "llpanel.h"
+#include "llurlregistry.h"
+#include "lltooltip.h"
#include <queue>
#include "llcombobox.h"
@@ -78,10 +82,6 @@ const S32 CURSOR_THICKNESS = 2;
const S32 SPACES_PER_TAB = 4;
-void (* LLTextEditor::sURLcallback)(const std::string&) = NULL;
-bool (* LLTextEditor::sSecondlifeURLcallback)(const std::string&) = NULL;
-bool (* LLTextEditor::sSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
-
// helper functors
struct LLTextEditor::compare_bottom
{
@@ -331,8 +331,9 @@ LLTextEditor::Params::Params()
is_unicode("is_unicode")// ignored
{}
-LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)
- : LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
+LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
+ LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
+ LLTextBase(p),
mMaxTextByteLength( p.max_text_length ),
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
@@ -351,7 +352,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)
mFocusBgColor( p.bg_focus_color() ),
mLinkColor( p.link_color() ),
mReadOnly(p.read_only),
- mWordWrap( p.word_wrap ),
mShowLineNumbers ( p.show_line_numbers ),
mCommitOnFocusLost( p.commit_on_focus_lost),
mTrackBottom( p.track_bottom ),
@@ -363,14 +363,16 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)
mReflowNeeded(FALSE),
mScrollNeeded(FALSE),
mLastSelectionY(-1),
- mParseHTML(FALSE),
mParseHighlights(FALSE),
mTabsToNextField(p.ignore_tab),
- mDefaultFont(p.font),
mScrollIndex(-1)
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+ mWordWrap = p.word_wrap;
+ mDefaultFont = p.font;
+ mParseHTML = FALSE;
+
mSourceID.generate();
// reset desired x cursor position
@@ -413,7 +415,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)
appendText(p.default_text, FALSE, FALSE);
- mHTML.clear();
}
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
@@ -451,7 +452,6 @@ LLTextEditor::~LLTextEditor()
}
// Scrollbar is deleted by LLView
- mHoverSegment = NULL;
std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
}
@@ -666,18 +666,12 @@ BOOL LLTextEditor::truncate()
return did_truncate;
}
-void LLTextEditor::clearSegments()
-{
- mHoverSegment = NULL;
- mSegments.clear();
-}
-
void LLTextEditor::setText(const LLStringExplicit &utf8str)
{
+ // clear out the existing text and segments
clearSegments();
- // LLStringUtil::removeCRLF(utf8str);
- getViewModel()->setValue(utf8str_removeCRLF(utf8str));
+ getViewModel()->setValue("");
truncate();
blockUndo();
@@ -687,6 +681,11 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str)
startOfDoc();
deselect();
+ // append the new text (supports Url linking)
+ std::string text(utf8str);
+ LLStringUtil::removeCRLF(text);
+ appendStyledText(text, false, false, LLStyle::Params());
+
needsReflow();
resetDirty();
@@ -696,9 +695,10 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str)
void LLTextEditor::setWText(const LLWString &wtext)
{
+ // clear out the existing text and segments
clearSegments();
- getViewModel()->setDisplay(wtext);
+ getViewModel()->setDisplay(LLWString());
truncate();
blockUndo();
@@ -708,6 +708,9 @@ void LLTextEditor::setWText(const LLWString &wtext)
startOfDoc();
deselect();
+ // append the new text (supports Url linking)
+ appendStyledText(wstring_to_utf8str(wtext), false, false, LLStyle::Params());
+
needsReflow();
resetDirty();
@@ -913,32 +916,6 @@ void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp, boo
}
}
-void LLTextEditor::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const
-{
- *seg_iter = getSegIterContaining(startpos);
- if (*seg_iter == mSegments.end())
- {
- *offsetp = 0;
- }
- else
- {
- *offsetp = startpos - (**seg_iter)->getStart();
- }
-}
-
-void LLTextEditor::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp )
-{
- *seg_iter = getSegIterContaining(startpos);
- if (*seg_iter == mSegments.end())
- {
- *offsetp = 0;
- }
- else
- {
- *offsetp = startpos - (**seg_iter)->getStart();
- }
-}
-
const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
// find segment index at character to left of cursor (or rightmost edge of selection)
@@ -1154,6 +1131,10 @@ S32 LLTextEditor::getEditableIndex(S32 index, bool increasing_direction)
segment_set_t::iterator segment_iter;
S32 offset;
getSegmentAndOffset(index, &segment_iter, &offset);
+ if (segment_iter == mSegments.end())
+ {
+ return 0;
+ }
LLTextSegmentPtr segmentp = *segment_iter;
@@ -1363,39 +1344,14 @@ void LLTextEditor::selectAll()
}
-BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
- for ( child_list_const_iter_t child_it = getChildList()->begin();
- child_it != getChildList()->end(); ++child_it)
+ if (childrenHandleToolTip(x, y, msg, sticky_rect_screen))
{
- 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;
- }
+ return TRUE;
}
- const LLTextSegmentPtr 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 handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
}
BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -1480,12 +1436,6 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
BOOL handled = FALSE;
- if (mHoverSegment)
- {
- mHoverSegment->setHasMouseHover(false);
- }
- mHoverSegment = NULL;
-
if(hasMouseCapture() )
{
if( mIsSelecting )
@@ -1525,30 +1475,11 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
if( !handled )
{
// Check to see if we're over an HTML-style link
- LLTextSegmentPtr cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
+ handled = handleHoverOverUrl(x, y);
+ if( handled )
{
- if(cur_segment->getStyle()->isLink())
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- handled = TRUE;
- }
- //else
- //if(cur_segment->getStyle()->getIsEmbeddedItem())
- //{
- // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl;
- // getWindow()->setCursor(UI_CURSOR_HAND);
- // //getWindow()->setCursor(UI_CURSOR_ARROW);
- // handled = TRUE;
- //}
- if (mHoverSegment)
- {
- mHoverSegment->setHasMouseHover(false);
- }
- cur_segment->setHasMouseHover(true);
- mHoverSegment = cur_segment;
- mHTML = mHoverSegment->getStyle()->getLinkHREF();
+ lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
+ getWindow()->setCursor(UI_CURSOR_HAND);
}
if( !handled )
@@ -1581,9 +1512,9 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
endSelection();
}
- if( !hasSelection() )
+ if( !hasSelection() && hasMouseCapture() )
{
- handleMouseUpOverSegment( x, y, mask );
+ handleMouseUpOverUrl(x, y);
}
// take selection to 'primary' clipboard
@@ -3258,7 +3189,7 @@ void LLTextEditor::draw()
mDocumentPanel->setBackgroundColor(bg_color);
- drawChildren();
+ LLView::draw();
drawBackground(); //overlays scrolling panel bg
drawLineNumbers();
@@ -3477,11 +3408,8 @@ void LLTextEditor::endOfDoc()
// Sets the scrollbar from the cursor position
void LLTextEditor::updateScrollFromCursor()
{
- if (mReadOnly)
- {
- // no cursor in read only mode
- return;
- }
+ // Update scroll position even in read-only mode (when there's no cursor displayed)
+ // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
if (!mScrollNeeded)
{
@@ -3596,14 +3524,20 @@ void LLTextEditor::appendStyledText(const std::string &new_text,
{
S32 start=0,end=0;
+ LLUrlMatch match;
std::string text = new_text;
- while ( findHTML(text, &start, &end) )
+ while ( LLUrlRegistry::instance().findUrl(text, match,
+ boost::bind(&LLTextEditor::onUrlLabelUpdated, this, _1, _2)) )
{
+ start = match.getStart();
+ end = match.getEnd()+1;
+
LLStyle::Params link_params = style_params;
link_params.color = mLinkColor;
link_params.font.style = "UNDERLINE";
- link_params.link_href = text.substr(start,end-start);
+ link_params.link_href = match.getUrl();
+ // output the text before the Url
if (start > 0)
{
if (part == (S32)LLTextParser::WHOLE ||
@@ -3617,9 +3551,38 @@ void LLTextEditor::appendStyledText(const std::string &new_text,
}
std::string subtext=text.substr(0,start);
appendHighlightedText(subtext,allow_undo, prepend_newline, part, style_params);
+ prepend_newline = false;
}
-
- appendText(text.substr(start, end-start),allow_undo, prepend_newline, link_params);
+
+ // output the styled Url
+ appendText(match.getLabel(),allow_undo, prepend_newline, link_params);
+ prepend_newline = false;
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
+ {
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
+ }
+
+ // output an optional icon after the Url
+ if (! match.getIcon().empty())
+ {
+ LLUIImagePtr image = LLUI::getUIImage(match.getIcon());
+ if (image)
+ {
+ LLStyle::Params icon;
+ icon.image = image;
+ // TODO: fix spacing of images and remove the fixed char spacing
+ appendText(" ", allow_undo, prepend_newline, icon);
+ }
+ }
+
+ // move on to the rest of the text after the Url
if (end < (S32)text.length())
{
text = text.substr(end,text.length() - end);
@@ -3711,7 +3674,7 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
}
append(wide_text, TRUE, segmentp);
-
+
needsReflow();
// Set the cursor and scroll position
@@ -3795,6 +3758,58 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
}
}
+void LLTextEditor::onUrlLabelUpdated(const std::string &url,
+ const std::string &label)
+{
+ // LLUrlRegistry has given us a new label for one of our Urls
+ replaceUrlLabel(url, label);
+}
+
+void LLTextEditor::replaceUrlLabel(const std::string &url,
+ const std::string &label)
+{
+ // get the full (wide) text for the editor so we can change it
+ LLWString text = getWText();
+ LLWString wlabel = utf8str_to_wstring(label);
+ bool modified = false;
+ S32 seg_start = 0;
+
+ // iterate through each segment looking for ones styled as links
+ segment_set_t::iterator it;
+ for (it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *seg = *it;
+ const LLStyleSP style = seg->getStyle();
+
+ // update segment start/end length in case we replaced text earlier
+ S32 seg_length = seg->getEnd() - seg->getStart();
+ seg->setStart(seg_start);
+ seg->setEnd(seg_start + seg_length);
+
+ // if we find a link with our Url, then replace the label
+ if (style->isLink() && style->getLinkHREF() == url)
+ {
+ S32 start = seg->getStart();
+ S32 end = seg->getEnd();
+ text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
+ seg->setEnd(start + wlabel.size());
+ modified = true;
+ }
+
+ // work out the character offset for the next segment
+ seg_start = seg->getEnd();
+ }
+
+ // update the editor with the new (wide) text string
+ if (modified)
+ {
+ getViewModel()->setDisplay(text);
+ deselect();
+ setCursorPos(mCursorPos);
+ needsReflow();
+ }
+}
+
void LLTextEditor::removeTextFromEnd(S32 num_chars)
{
if (num_chars <= 0) return;
@@ -4097,7 +4112,7 @@ void LLTextEditor::updateSegments()
segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
- mSegments.clear();
+ clearSegments();
segment_set_t::iterator insert_it = mSegments.begin();
for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{
@@ -4106,7 +4121,29 @@ void LLTextEditor::updateSegments()
}
createDefaultSegment();
+}
+void LLTextEditor::updateLinkSegments()
+{
+ // update any segments that contain a link
+ for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *segment = *it;
+ if (segment && segment->getStyle() && segment->getStyle()->isLink())
+ {
+ // if the link's label (what the user can edit) is a valid Url,
+ // then update the link's HREF to be the same as the label text.
+ // This lets users edit Urls in-place.
+ LLUrlMatch match;
+ LLStyleSP style = static_cast<LLStyleSP>(segment->getStyle());
+ std::string url_label = getText().substr(segment->getStart(), segment->getEnd()-segment->getStart());
+ if (LLUrlRegistry::instance().findUrl(url_label, match))
+ {
+ LLStringUtil::trim(url_label);
+ style->setLinkHREF(url_label);
+ }
+ }
+ }
}
void LLTextEditor::insertSegment(LLTextSegmentPtr segment_to_insert)
@@ -4170,57 +4207,6 @@ void LLTextEditor::insertSegment(LLTextSegmentPtr segment_to_insert)
}
}
-BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask)
-{
- if ( hasMouseCapture() )
- {
- // This mouse up was part of a click.
- // Regardless of where the cursor is, see if we recently touched a link
- // and launch it if we did.
- if (mParseHTML && mHTML.length() > 0)
- {
- //Special handling for slurls
- if ( (sSecondlifeURLcallback!=NULL) && !(*sSecondlifeURLcallback)(mHTML) )
- {
- if (sURLcallback!=NULL) (*sURLcallback)(mHTML);
- }
- mHTML.clear();
- }
- }
-
- return FALSE;
-}
-
-
-// Finds the text segment (if any) at the give local screen position
-LLTextSegmentPtr LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y )
-{
- // Find the cursor position at the requested local screen position
- S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
- segment_set_t::iterator seg_iter = getSegIterContaining(offset);
- if (seg_iter != mSegments.end())
- {
- return *seg_iter;
- }
- else
- {
- return LLTextSegmentPtr();
- }
-}
-
-LLTextEditor::segment_set_t::iterator LLTextEditor::getSegIterContaining(S32 index)
-{
- segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
- return it;
-}
-
-LLTextEditor::segment_set_t::const_iterator LLTextEditor::getSegIterContaining(S32 index) const
-{
- LLTextEditor::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
- return it;
-}
-
-
void LLTextEditor::onMouseCaptureLost()
{
endSelection();
@@ -4330,169 +4316,6 @@ BOOL LLTextEditor::exportBuffer(std::string &buffer )
return TRUE;
}
-///////////////////////////////////////////////////////////////////
-// Refactoring note: We may eventually want to replace this with boost::regex or
-// boost::tokenizer capabilities since we've already fixed at least two JIRAs
-// concerning logic issues associated with this function.
-S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const
-{
- std::string openers=" \t\n('\"[{<>";
- std::string closers=" \t\n)'\"]}><;";
-
- if (reverse)
- {
- for (int index=pos; index >= 0; index--)
- {
- char c = line[index];
- S32 m2 = openers.find(c);
- if (m2 >= 0)
- {
- return index+1;
- }
- }
- return 0; // index is -1, don't want to return that.
- }
- else
- {
- // adjust the search slightly, to allow matching parenthesis inside the URL
- S32 paren_count = 0;
- for (int index=pos; index<(S32)line.length(); index++)
- {
- char c = line[index];
-
- if (c == '(')
- {
- paren_count++;
- }
- else if (c == ')')
- {
- if (paren_count <= 0)
- {
- return index;
- }
- else
- {
- paren_count--;
- }
- }
- else
- {
- S32 m2 = closers.find(c);
- if (m2 >= 0)
- {
- return index;
- }
- }
- }
- return line.length();
- }
-}
-
-BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
-{
-
- S32 m1,m2,m3;
- BOOL matched = FALSE;
-
- m1=line.find("://",*end);
-
- if (m1 >= 0) //Easy match.
- {
- *begin = findHTMLToken(line, m1, TRUE);
- *end = findHTMLToken(line, m1, FALSE);
-
- //Load_url only handles http and https so don't hilite ftp, smb, etc.
- m2 = line.substr(*begin,(m1 - *begin)).find("http");
- m3 = line.substr(*begin,(m1 - *begin)).find("secondlife");
-
- std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\";
-
- if (m2 >= 0 || m3>=0)
- {
- S32 bn = badneighbors.find(line.substr(m1+3,1));
-
- if (bn < 0)
- {
- matched = TRUE;
- }
- }
- }
-/* matches things like secondlife.com (no http://) needs a whitelist to really be effective.
- else //Harder match.
- {
- m1 = line.find(".",*end);
-
- if (m1 >= 0)
- {
- *end = findHTMLToken(line, m1, FALSE);
- *begin = findHTMLToken(line, m1, TRUE);
-
- m1 = line.rfind(".",*end);
-
- if ( ( *end - m1 ) > 2 && m1 > *begin)
- {
- std::string badneighbors=".,<>/?';\"][}{=-+_)(*&^%$#@!~`";
- m2 = badneighbors.find(line.substr(m1+1,1));
- m3 = badneighbors.find(line.substr(m1-1,1));
- if (m3<0 && m2<0)
- {
- matched = TRUE;
- }
- }
- }
- }
- */
-
- if (matched)
- {
- S32 strpos, strpos2;
-
- std::string url = line.substr(*begin,*end - *begin);
- std::string slurlID = "slurl.com/secondlife/";
- strpos = url.find(slurlID);
-
- if (strpos < 0)
- {
- slurlID="secondlife://";
- strpos = url.find(slurlID);
- }
-
- if (strpos < 0)
- {
- slurlID="sl://";
- strpos = url.find(slurlID);
- }
-
- if (strpos >= 0)
- {
- strpos+=slurlID.length();
-
- while ( ( strpos2=url.find("/",strpos) ) == -1 )
- {
- if ((*end+2) >= (S32)line.length() || line.substr(*end,1) != " " )
- {
- matched=FALSE;
- break;
- }
-
- strpos = (*end + 1) - *begin;
-
- *end = findHTMLToken(line,(*begin + strpos),FALSE);
- url = line.substr(*begin,*end - *begin);
- }
- }
-
- }
-
- if (!matched)
- {
- *begin=*end=0;
- }
- return matched;
-}
-
-
-
void LLTextEditor::updateAllowingLanguageInput()
{
LLWindow* window = getWindow();
@@ -4754,193 +4577,6 @@ void LLTextEditor::onValueChange(S32 start, S32 end)
}
//
-// LLTextSegment
-//
-
-LLTextSegment::~LLTextSegment()
-{}
-
-S32 LLTextSegment::getWidth(S32 first_char, S32 num_chars) const { return 0; }
-S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; }
-S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; }
-void LLTextSegment::updateLayout(const LLTextEditor& editor) {}
-F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { return draw_rect.mLeft; }
-S32 LLTextSegment::getMaxHeight() const { return 0; }
-bool LLTextSegment::canEdit() const { return false; }
-void LLTextSegment::unlinkFromDocument(LLTextEditor*) {}
-void LLTextSegment::linkToDocument(LLTextEditor*) {}
-void LLTextSegment::setHasMouseHover(bool hover) {}
-const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
-void LLTextSegment::setColor(const LLColor4 &color) {}
-const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
-void LLTextSegment::setStyle(const LLStyleSP &style) {}
-void LLTextSegment::setToken( LLKeywordToken* token ) {}
-LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
-BOOL LLTextSegment::getToolTip( std::string& msg ) const { return FALSE; }
-void LLTextSegment::dump() const {}
-
-
-//
-// LLNormalTextSegment
-//
-
-LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextEditor& editor )
-: LLTextSegment(start, end),
- mStyle( style ),
- mToken(NULL),
- mHasMouseHover(false),
- mEditor(editor)
-{
- mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
-}
-
-LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextEditor& editor, BOOL is_visible)
-: LLTextSegment(start, end),
- mToken(NULL),
- mHasMouseHover(false),
- mEditor(editor)
-{
- mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
-
- mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
-}
-
-F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
-{
- if( end - start > 0 )
- {
- if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
- {
- S32 style_image_height = mStyle->mImageHeight;
- S32 style_image_width = mStyle->mImageWidth;
- LLUIImagePtr image = mStyle->getImage();
- image->draw(draw_rect.mLeft, draw_rect.mTop-style_image_height,
- style_image_width, style_image_height);
- }
-
- return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect.mLeft, draw_rect.mBottom);
- }
- return draw_rect.mLeft;
-}
-
-// Draws a single text segment, reversing the color for selection if needed.
-F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y)
-{
- const LLWString &text = mEditor.getWText();
-
- F32 right_x = x;
- if (!mStyle->isVisible())
- {
- return right_x;
- }
-
- const LLFontGL* font = mStyle->getFont();
-
- LLColor4 color = mStyle->getColor();
-
- font = mStyle->getFont();
-
- if( selection_start > seg_start )
- {
- // Draw normally
- S32 start = seg_start;
- S32 end = llmin( selection_start, seg_end );
- S32 length = end - start;
- font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
- }
- x = right_x;
-
- if( (selection_start < seg_end) && (selection_end > seg_start) )
- {
- // Draw reversed
- S32 start = llmax( selection_start, seg_start );
- S32 end = llmin( selection_end, seg_end );
- S32 length = end - start;
-
- font->render(text, start, x, y,
- LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
- LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
- }
- x = right_x;
- if( selection_end < seg_end )
- {
- // Draw normally
- S32 start = llmax( selection_end, seg_start );
- S32 end = seg_end;
- S32 length = end - start;
- font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
- }
- return right_x;
-}
-
-S32 LLNormalTextSegment::getMaxHeight() const
-{
- return mMaxHeight;
-}
-
-BOOL LLNormalTextSegment::getToolTip(std::string& msg) const
-{
- if (mToken && !mToken->getToolTip().empty())
- {
- const LLWString& wmsg = mToken->getToolTip();
- msg = wstring_to_utf8str(wmsg);
- return TRUE;
- }
- return FALSE;
-}
-
-
-S32 LLNormalTextSegment::getWidth(S32 first_char, S32 num_chars) const
-{
- LLWString text = mEditor.getWText();
- return mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
-}
-
-S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
-{
- LLWString text = mEditor.getWText();
- return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
- (F32)segment_local_x_coord,
- F32_MAX,
- num_chars,
- round);
-}
-
-S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
-{
- LLWString text = mEditor.getWText();
- S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
- (F32)num_pixels,
- max_chars,
- mEditor.getWordWrap());
-
- if (num_chars == 0
- && line_offset == 0
- && max_chars > 0)
- {
- // If at the beginning of a line, and a single character won't fit, draw it anyway
- num_chars = 1;
- }
- if (mStart + segment_offset + num_chars == mEditor.getLength())
- {
- // include terminating NULL
- num_chars++;
- }
- return num_chars;
-}
-
-void LLNormalTextSegment::dump() const
-{
- llinfos << "Segment [" <<
-// mColor.mV[VX] << ", " <<
-// mColor.mV[VY] << ", " <<
-// mColor.mV[VZ] << "]\t[" <<
- mStart << ", " <<
- getEnd() << "]" <<
- llendl;
-}
-
-//
// LLInlineViewSegment
//
@@ -4979,11 +4615,15 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
}
}
-void LLInlineViewSegment::updateLayout(const LLTextEditor& editor)
+void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
- LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
- LLRect doc_rect = editor.getDocumentPanel()->getRect();
- mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
+ const LLTextEditor *ed = dynamic_cast<const LLTextEditor *>(&editor);
+ if (ed)
+ {
+ LLRect start_rect = ed->getLocalRectFromDocIndex(mStart);
+ LLRect doc_rect = ed->getDocumentPanel()->getRect();
+ mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
+ }
}
F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
@@ -4996,12 +4636,20 @@ S32 LLInlineViewSegment::getMaxHeight() const
return mView->getRect().getHeight();
}
-void LLInlineViewSegment::unlinkFromDocument(LLTextEditor* editor)
+void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
{
- editor->removeDocumentChild(mView);
+ LLTextEditor *ed = dynamic_cast<LLTextEditor *>(editor);
+ if (ed)
+ {
+ ed->removeDocumentChild(mView);
+ }
}
-void LLInlineViewSegment::linkToDocument(LLTextEditor* editor)
+void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
{
- editor->addDocumentChild(mView);
+ LLTextEditor *ed = dynamic_cast<LLTextEditor *>(editor);
+ if (ed)
+ {
+ ed->addDocumentChild(mView);
+ }
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 67c67d0f67..68b8f2c3b1 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -44,6 +44,7 @@
#include "lleditmenuhandler.h"
#include "lldarray.h"
#include "llviewborder.h" // for params
+#include "lltextbase.h"
#include "llpreeditor.h"
#include "llcontrol.h"
@@ -55,76 +56,6 @@ class LLTextCmd;
class LLUICtrlFactory;
class LLScrollContainer;
-class LLTextSegment : public LLRefCount
-{
-public:
- LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
- virtual ~LLTextSegment();
-
- virtual S32 getWidth(S32 first_char, S32 num_chars) const;
- virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
- virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
- virtual void updateLayout(const class LLTextEditor& editor);
- virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
- virtual S32 getMaxHeight() const;
- virtual bool canEdit() const;
- virtual void unlinkFromDocument(class LLTextEditor* editor);
- virtual void linkToDocument(class LLTextEditor* editor);
-
- virtual void setHasMouseHover(bool hover);
- virtual const LLColor4& getColor() const;
- virtual void setColor(const LLColor4 &color);
- virtual const LLStyleSP getStyle() const;
- virtual void setStyle(const LLStyleSP &style);
- virtual void setToken( LLKeywordToken* token );
- virtual LLKeywordToken* getToken() const;
- virtual BOOL getToolTip( std::string& msg ) const;
- virtual void dump() const;
-
- S32 getStart() const { return mStart; }
- void setStart(S32 start) { mStart = start; }
- S32 getEnd() const { return mEnd; }
- void setEnd( S32 end ) { mEnd = end; }
-
-protected:
- S32 mStart;
- S32 mEnd;
-};
-
-class LLNormalTextSegment : public LLTextSegment
-{
-public:
- LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextEditor& editor );
- LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextEditor& editor, BOOL is_visible = TRUE);
-
- /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
- /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
- /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
- /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
- /*virtual*/ S32 getMaxHeight() const;
- /*virtual*/ bool canEdit() const { return true; }
- /*virtual*/ void setHasMouseHover(bool hover) { mHasMouseHover = hover; }
- /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
- /*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
- /*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
- /*virtual*/ void setStyle(const LLStyleSP &style) { mStyle = style; }
- /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
- /*virtual*/ LLKeywordToken* getToken() const { return mToken; }
- /*virtual*/ BOOL getToolTip( std::string& msg ) const;
- /*virtual*/ void dump() const;
-
-protected:
- F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y);
-
- class LLTextEditor& mEditor;
- LLStyleSP mStyle;
- S32 mMaxHeight;
- LLKeywordToken* mToken;
- bool mHasMouseHover;
-};
-
-typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
-
class LLInlineViewSegment : public LLTextSegment
{
public:
@@ -132,24 +63,22 @@ public:
~LLInlineViewSegment();
/*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
- /*virtual*/ void updateLayout(const class LLTextEditor& editor);
+ /*virtual*/ void updateLayout(const class LLTextBase& editor);
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
/*virtuaL*/ S32 getMaxHeight() const;
/*virtual*/ bool canEdit() const { return false; }
- /*virtual*/ void unlinkFromDocument(class LLTextEditor* editor);
- /*virtual*/ void linkToDocument(class LLTextEditor* editor);
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor);
+ /*virtual*/ void linkToDocument(class LLTextBase* editor);
private:
LLView* mView;
};
-class LLIndexSegment : public LLTextSegment
-{
-public:
- LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {}
-};
-
-class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor
+class LLTextEditor :
+ public LLTextBase,
+ public LLUICtrl,
+ private LLEditMenuHandler,
+ protected LLPreeditor
{
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
@@ -208,11 +137,8 @@ public:
}
};
- typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
-
virtual ~LLTextEditor();
- void setParseHTML(BOOL parsing) {mParseHTML=parsing;}
void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
// mousehandler overrides
@@ -225,7 +151,7 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask );
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type, void *cargo_data,
EAcceptance *accept, std::string& tooltip_msg);
@@ -277,6 +203,7 @@ public:
BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
+ void replaceUrlLabel(const std::string &url, const std::string &label);
// Undo/redo stack
void blockUndo();
@@ -285,7 +212,6 @@ public:
virtual void makePristine();
BOOL isPristine() const;
BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
- BOOL getWordWrap() { return mWordWrap; }
S32 getLength() const { return getWText().length(); }
void setReadOnly(bool read_only) { mReadOnly = read_only; }
bool getReadOnly() { return mReadOnly; }
@@ -352,13 +278,11 @@ public:
const LLUUID& getSourceID() const { return mSourceID; }
// Callbacks
- static void setURLCallbacks(void (*callback1) (const std::string& url),
- bool (*callback2) (const std::string& url),
- bool (*callback3) (const std::string& url) )
- { sURLcallback = callback1; sSecondlifeURLcallback = callback2; sSecondlifeURLcallbackRightClick = callback3;}
-
std::string getText() const;
+ // Callback for when a Url has been resolved by the server
+ void onUrlLabelUpdated(const std::string &url, const std::string &label);
+
// Getters
LLWString getWText() const;
llwchar getWChar(S32 pos) const { return getWText()[pos]; }
@@ -382,8 +306,6 @@ protected:
void startOfDoc();
void endOfDoc();
- void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
- void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ) ;
void drawPreeditMarker();
void needsReflow() { mReflowNeeded = TRUE; }
@@ -399,16 +321,12 @@ protected:
void removeCharOrTab();
void setCursorAtLocalPos(S32 x, S32 y, bool round, bool keep_cursor_offset = false);
- S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+ /*virtual*/ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
void indentSelectedLines( S32 spaces );
S32 indentLine( S32 pos, S32 spaces );
void unindentLineBeforeCloseBrace();
- LLTextSegmentPtr getSegmentAtLocalPos(S32 x, S32 y);
- segment_set_t::iterator getSegIterContaining(S32 index);
- segment_set_t::const_iterator getSegIterContaining(S32 index) const;
-
void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); }
BOOL handleNavigationKey(const KEY key, const MASK mask);
@@ -438,15 +356,9 @@ protected:
void findEmbeddedItemSegments(S32 start, S32 end);
void insertSegment(LLTextSegmentPtr segment_to_insert);
-
- virtual BOOL handleMouseUpOverSegment(S32 x, S32 y, MASK mask);
-
virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
- S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const;
- BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const;
-
// Abstract inner base class representing an undoable editor command.
// Concrete sub-classes can be defined for operations such as insert, remove, etc.
// Used as arguments to the execute() method below.
@@ -538,13 +450,8 @@ protected:
S32 mLastSelectionX;
S32 mLastSelectionY;
- BOOL mParseHTML;
BOOL mParseHighlights;
- std::string mHTML;
- segment_set_t mSegments;
- LLTextSegmentPtr mHoverSegment;
-
// Scrollbar data
class DocumentPanel* mDocumentPanel;
LLScrollContainer* mScroller;
@@ -569,10 +476,10 @@ protected:
LLUIColor mLinkColor;
BOOL mReadOnly;
- BOOL mWordWrap;
BOOL mShowLineNumbers;
void updateSegments();
+ void updateLinkSegments();
private:
@@ -584,7 +491,6 @@ private:
virtual LLTextViewModel* getViewModel() const;
void reflow(S32 startpos = 0);
- void clearSegments();
void createDefaultSegment();
LLStyleSP getDefaultStyle();
S32 getEditableIndex(S32 index, bool increasing_direction);
@@ -601,9 +507,6 @@ private:
// Data
//
LLKeywords mKeywords;
- static void (*sURLcallback) (const std::string& url);
- static bool (*sSecondlifeURLcallback) (const std::string& url);
- static bool (*sSecondlifeURLcallbackRightClick) (const std::string& url);
// Concrete LLTextCmd sub-classes used by the LLTextEditor base class
class LLTextCmdInsert;
@@ -613,8 +516,6 @@ private:
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
- const LLFontGL* mDefaultFont;
-
class LLViewBorder* mBorder;
BOOL mBaseDocIsPristine;
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
new file mode 100644
index 0000000000..5c017dabd7
--- /dev/null
+++ b/indra/llui/lltooltip.cpp
@@ -0,0 +1,445 @@
+/**
+ * @file lltooltip.cpp
+ * @brief LLToolTipMgr class implementation and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// self include
+#include "lltooltip.h"
+
+// Library includes
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lliconctrl.h"
+#include "llui.h" // positionViewNearMouse()
+#include "llwindow.h"
+
+//
+// Constants
+//
+const F32 DELAY_BEFORE_SHOW_TIP = 0.35f;
+
+//
+// Local globals
+//
+
+LLToolTipView *gToolTipView = NULL;
+
+//
+// Member functions
+//
+
+LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
+: LLView(p)
+{
+}
+
+void LLToolTipView::draw()
+{
+ if (LLUI::getWindow()->isCursorHidden() )
+ {
+ LLToolTipMgr::instance().hideToolTips();
+ }
+
+ // do the usual thing
+ LLView::draw();
+}
+
+BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
+{
+ static S32 last_x = x;
+ static S32 last_y = y;
+
+ LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
+
+ // hide existing tooltips when mouse moves out of sticky rect
+ if (tooltip_mgr.toolTipVisible()
+ && !tooltip_mgr.getStickyRect().pointInRect(x, y))
+ {
+ tooltip_mgr.hideToolTips();
+ }
+
+ // allow new tooltips whenever mouse moves
+ if (x != last_x && y != last_y)
+ {
+ tooltip_mgr.enableToolTips();
+ }
+
+ last_x = x;
+ last_y = y;
+ return LLView::handleHover(x, y, mask);
+}
+
+BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().hideToolTips();
+ return LLView::handleMouseDown(x, y, mask);
+}
+
+BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().hideToolTips();
+ return LLView::handleMiddleMouseDown(x, y, mask);
+}
+
+BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().hideToolTips();
+ return LLView::handleRightMouseDown(x, y, mask);
+}
+
+
+BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+ LLToolTipMgr::instance().hideToolTips();
+ return FALSE;
+}
+
+void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().hideToolTips();
+}
+
+
+void LLToolTipView::drawStickyRect()
+{
+ gl_rect_2d(LLToolTipMgr::instance().getStickyRect(), LLColor4::white, false);
+}
+//
+// LLToolTip
+//
+class LLToolTip : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Mandatory<F32> visible_time;
+
+ Optional<LLToolTipParams::click_callback_t> click_callback;
+ Optional<LLUIImage*> image;
+
+ Params()
+ {
+ //use_bounding_rect = true;
+ }
+ };
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ void setVisible(BOOL visible);
+
+ bool isFading() { return mFadeTimer.getStarted(); }
+
+ LLToolTip(const Params& p);
+
+private:
+ LLTextBox* mTextBox;
+ LLFrameTimer mFadeTimer;
+ F32 mVisibleTime;
+ bool mHasClickCallback;
+};
+
+static LLDefaultChildRegistry::Register<LLToolTip> r("tool_tip");
+
+const S32 TOOLTIP_PADDING = 4;
+
+LLToolTip::LLToolTip(const LLToolTip::Params& p)
+: LLPanel(p),
+ mVisibleTime(p.visible_time),
+ mHasClickCallback(p.click_callback.isProvided())
+{
+ LLTextBox::Params params;
+ params.text = "tip_text";
+ params.name = params.text;
+ // bake textbox padding into initial rect
+ params.rect = LLRect (TOOLTIP_PADDING, TOOLTIP_PADDING + 1, TOOLTIP_PADDING + 1, TOOLTIP_PADDING);
+ params.follows.flags = FOLLOWS_ALL;
+ params.h_pad = 4;
+ params.v_pad = 2;
+ params.mouse_opaque = false;
+ params.text_color = LLUIColorTable::instance().getColor( "ToolTipTextColor" );
+ params.bg_visible = false;
+ params.font.style = "NORMAL";
+ //params.border_drop_shadow_visible = true;
+ mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
+ addChild(mTextBox);
+
+ if (p.image.isProvided())
+ {
+ LLIconCtrl::Params icon_params;
+ icon_params.name = "tooltip_icon";
+ LLRect icon_rect;
+ const S32 TOOLTIP_ICON_SIZE = 18;
+ icon_rect.setOriginAndSize(TOOLTIP_PADDING, TOOLTIP_PADDING, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+ icon_params.rect = icon_rect;
+ icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
+ icon_params.image = p.image;
+ icon_params.mouse_opaque = false;
+ addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params));
+
+ // move text over to fit image in
+ mTextBox->translate(TOOLTIP_ICON_SIZE,0);
+ }
+
+ if (p.click_callback.isProvided())
+ {
+ setMouseUpCallback(boost::bind(p.click_callback()));
+ }
+}
+
+void LLToolTip::setValue(const LLSD& value)
+{
+ mTextBox->setWrappedText(value.asString());
+ mTextBox->reshapeToFitText();
+
+ // reshape tooltip panel to fit text box
+ LLRect tooltip_rect = calcBoundingRect();
+ tooltip_rect.mTop += TOOLTIP_PADDING;
+ tooltip_rect.mRight += TOOLTIP_PADDING;
+ tooltip_rect.mBottom = 0;
+ tooltip_rect.mLeft = 0;
+
+ setRect(tooltip_rect);
+}
+
+void LLToolTip::setVisible(BOOL visible)
+{
+ // fade out tooltip over time
+ if (!visible)
+ {
+ // don't actually change mVisible state, start fade out transition instead
+ if (!mFadeTimer.getStarted())
+ {
+ mFadeTimer.start();
+ }
+ }
+ else
+ {
+ mFadeTimer.stop();
+ LLPanel::setVisible(TRUE);
+ }
+}
+
+BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
+{
+ LLPanel::handleHover(x, y, mask);
+ if (mHasClickCallback)
+ {
+ getWindow()->setCursor(UI_CURSOR_HAND);
+ }
+ return TRUE;
+}
+
+void LLToolTip::draw()
+{
+ F32 alpha = 1.f;
+
+ if (LLUI::getMouseIdleTime() > mVisibleTime)
+ {
+ LLToolTipMgr::instance().hideToolTips();
+ }
+
+ if (mFadeTimer.getStarted())
+ {
+ F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime");
+ alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
+ if (alpha == 0.f)
+ {
+ // finished fading out, so hide ourselves
+ mFadeTimer.stop();
+ LLPanel::setVisible(false);
+ }
+ }
+
+ // draw tooltip contents with appropriate alpha
+ {
+ LLViewDrawContext context(alpha);
+ LLPanel::draw();
+ }
+}
+
+
+
+//
+// LLToolTipMgr
+//
+LLToolTipParams::LLToolTipParams()
+: pos("pos"),
+ message("message"),
+ delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
+ visible_time("visible_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTime" )),
+ sticky_rect("sticky_rect"),
+ width("width", 200),
+ image("image")
+{}
+
+LLToolTipMgr::LLToolTipMgr()
+: mToolTip(NULL)
+{
+}
+
+LLToolTip* LLToolTipMgr::createToolTip(const LLToolTipParams& params)
+{
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
+
+
+ LLToolTip::Params tooltip_params;
+ tooltip_params.name = "tooltip";
+ tooltip_params.mouse_opaque = true;
+ tooltip_params.rect = LLRect (0, 1, 1, 0);
+ tooltip_params.bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
+ tooltip_params.background_visible = true;
+ tooltip_params.visible_time = params.visible_time;
+ if (params.image.isProvided())
+ {
+ tooltip_params.image = params.image;
+ }
+ if (params.click_callback.isProvided())
+ {
+ tooltip_params.click_callback = params.click_callback;
+ }
+
+ LLToolTip* tooltip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
+
+ // make tooltip fixed width and tall enough to fit text
+ tooltip->reshape(params.width, 2000);
+ tooltip->setValue(params.message());
+ gToolTipView->addChild(tooltip);
+
+ if (params.pos.isProvided())
+ {
+ // try to spawn at requested position
+ LLUI::positionViewNearMouse(tooltip, params.pos.x, params.pos.y);
+ }
+ else
+ {
+ // just spawn at mouse location
+ LLUI::positionViewNearMouse(tooltip);
+ }
+
+ //...update "sticky" rect and tooltip position
+ if (params.sticky_rect.isProvided())
+ {
+ mToolTipStickyRect = params.sticky_rect;
+ }
+ else
+ {
+ // otherwise just use one pixel rect around mouse cursor
+ mToolTipStickyRect.setOriginAndSize(mouse_x, mouse_y, 1, 1);
+ }
+
+ if (params.click_callback.isProvided())
+ {
+ // keep tooltip up when we mouse over it
+ mToolTipStickyRect.unionWith(tooltip->getRect());
+ }
+
+ return tooltip;
+}
+
+
+void LLToolTipMgr::show(const std::string& msg)
+{
+ show(LLToolTipParams().message(msg));
+}
+
+void LLToolTipMgr::show(const LLToolTipParams& params)
+{
+ if (!params.validateBlock())
+ {
+ llwarns << "Could not display tooltip!" << llendl;
+ return;
+ }
+
+ bool tooltip_shown = mToolTip
+ && mToolTip->getVisible()
+ && !mToolTip->isFading();
+
+ // if tooltip contents change, hide existing tooltip
+ if (tooltip_shown && mLastToolTipMessage != params.message())
+ {
+ hideToolTips();
+ }
+
+ if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc.
+ && LLUI::getMouseIdleTime() > params.delay_time // the mouse has been still long enough
+ && !tooltip_shown) // tooltip not visible
+ {
+ // create new tooltip at mouse cursor position
+ delete mToolTip;
+ mToolTip = createToolTip(params);
+
+ // remember this tooltip so we know when it changes
+ mLastToolTipMessage = params.message();
+ }
+}
+
+// allow new tooltips to be created, e.g. after mouse has moved
+void LLToolTipMgr::enableToolTips()
+{
+ mToolTipsBlocked = false;
+}
+
+void LLToolTipMgr::hideToolTips()
+{
+ mToolTipsBlocked = true;
+ if (mToolTip)
+ {
+ mToolTip->setVisible(FALSE);
+ }
+}
+
+bool LLToolTipMgr::toolTipVisible()
+{
+ return mToolTip ? mToolTip->getVisible() : false;
+}
+
+LLRect LLToolTipMgr::getToolTipRect()
+{
+ if (mToolTip && mToolTip->getVisible())
+ {
+ return mToolTip->getRect();
+ }
+ return LLRect();
+}
+
+
+LLRect LLToolTipMgr::getStickyRect()
+{
+ if (!mToolTip) return LLRect();
+
+ return mToolTip->isInVisibleChain() ? mToolTipStickyRect : LLRect();
+}
+
+// EOF
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
new file mode 100644
index 0000000000..fb7f942099
--- /dev/null
+++ b/indra/llui/lltooltip.h
@@ -0,0 +1,127 @@
+/**
+ * @file lltooltip.h
+ * @brief LLToolTipMgr class definition and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOOLTIP_H
+#define LL_LLTOOLTIP_H
+
+// Library includes
+#include "llsingleton.h"
+#include "llinitparam.h"
+#include "llview.h"
+
+//
+// Classes
+//
+class LLToolTipView : public LLView
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params()
+ {
+ mouse_opaque = false;
+ }
+ };
+ LLToolTipView(const LLToolTipView::Params&);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ void drawStickyRect();
+
+ /*virtual*/ void draw();
+};
+
+struct LLToolTipPosParams : public LLInitParam::Block<LLToolTipPosParams>
+{
+ Mandatory<S32> x,
+ y;
+ LLToolTipPosParams()
+ : x("x"),
+ y("y")
+ {}
+};
+
+struct LLToolTipParams : public LLInitParam::Block<LLToolTipParams>
+{
+ typedef boost::function<void(void)> click_callback_t;
+
+ Mandatory<std::string> message;
+
+ Optional<LLToolTipPosParams> pos;
+ Optional<F32> delay_time,
+ visible_time;
+ Optional<LLRect> sticky_rect;
+ Optional<S32> width;
+ Optional<LLUIImage*> image;
+
+ Optional<click_callback_t> click_callback;
+
+ LLToolTipParams();
+ LLToolTipParams(const std::string& message);
+};
+
+class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
+{
+ LOG_CLASS(LLToolTipMgr);
+public:
+ LLToolTipMgr();
+ void show(const LLToolTipParams& params);
+ void show(const std::string& message);
+
+ void enableToolTips();
+ void hideToolTips();
+ bool toolTipVisible();
+ LLRect getToolTipRect();
+
+ LLRect getStickyRect();
+
+private:
+ class LLToolTip* createToolTip(const LLToolTipParams& params);
+
+ bool mToolTipsBlocked;
+ class LLToolTip* mToolTip;
+ std::string mLastToolTipMessage;
+ LLRect mToolTipStickyRect;
+};
+
+//
+// Globals
+//
+
+extern LLToolTipView *gToolTipView;
+
+#endif
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 1d62ed93f9..950eaf2ea7 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -44,6 +44,7 @@
#include "llrect.h"
#include "lldir.h"
#include "llfontgl.h"
+#include "llgl.h"
// Project includes
#include "llcontrol.h"
@@ -80,10 +81,9 @@ std::list<std::string> gUntranslated;
/*static*/ LLWindow* LLUI::sWindow = NULL;
/*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL;
/*static*/ LLView* LLUI::sRootView = NULL;
-/*static*/ BOOL LLUI::sShowXUINames = FALSE;
-/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
/*static*/ std::vector<std::string> LLUI::sXUIPaths;
+/*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
// register filtereditor here
static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
@@ -1561,12 +1561,6 @@ void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3
gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
}
-bool handleShowXUINamesChanged(const LLSD& newvalue)
-{
- LLUI::sShowXUINames = newvalue.asBoolean();
- return true;
-}
-
void LLUI::initClass(const settings_map_t& settings,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback,
@@ -1588,10 +1582,6 @@ void LLUI::initClass(const settings_map_t& settings,
sWindow = NULL; // set later in startup
LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
- static LLUICachedControl<bool> show_xui_names ("ShowXUINames", false);
- LLUI::sShowXUINames = show_xui_names;
- LLUI::sSettingGroups["config"]->getControl("ShowXUINames")->getSignal()->connect(boost::bind(&handleShowXUINamesChanged, _2));
-
// Callbacks for associating controls with floater visibilty:
LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
@@ -1661,7 +1651,7 @@ void LLUI::setLineWidth(F32 width)
}
//static
-void LLUI::setCursorPositionScreen(S32 x, S32 y)
+void LLUI::setMousePositionScreen(S32 x, S32 y)
{
S32 screen_x, screen_y;
screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
@@ -1674,16 +1664,16 @@ void LLUI::setCursorPositionScreen(S32 x, S32 y)
}
//static
-void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y)
+void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
{
S32 screen_x, screen_y;
viewp->localPointToScreen(x, y, &screen_x, &screen_y);
- setCursorPositionScreen(screen_x, screen_y);
+ setMousePositionScreen(screen_x, screen_y);
}
//static
-void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y)
+void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y)
{
LLCoordWindow cursor_pos_window;
LLView::getWindow()->getCursorPosition(&cursor_pos_window);
@@ -1867,74 +1857,46 @@ LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
return *sSettingGroups["config"]; // default group
}
-LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled)
+//static
+// spawn_x and spawn_y are top left corner of view in screen GL coordinates
+void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
{
- if (mEnabled)
- {
- pushClipRect(rect);
- }
- mScissorState.setEnabled(!sClipRectStack.empty());
- updateScissorRegion();
-}
+ const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
+ const S32 CURSOR_WIDTH = 12;
-LLScreenClipRect::~LLScreenClipRect()
-{
- if (mEnabled)
- {
- popClipRect();
- }
- updateScissorRegion();
-}
+ LLView* parent = view->getParent();
-//static
-void LLScreenClipRect::pushClipRect(const LLRect& rect)
-{
- LLRect combined_clip_rect = rect;
- if (!sClipRectStack.empty())
- {
- LLRect top = sClipRectStack.top();
- combined_clip_rect.intersectWith(top);
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(parent, &mouse_x, &mouse_y);
- if(combined_clip_rect.isEmpty())
- {
- // avoid artifacts where zero area rects show up as lines
- combined_clip_rect = LLRect::null;
- }
+ // If no spawn location provided, use mouse position
+ if (spawn_x == S32_MAX || spawn_y == S32_MAX)
+ {
+ spawn_x = mouse_x + CURSOR_WIDTH;
+ spawn_y = mouse_y - CURSOR_HEIGHT;
}
- sClipRectStack.push(combined_clip_rect);
-}
-//static
-void LLScreenClipRect::popClipRect()
-{
- sClipRectStack.pop();
-}
+ LLRect virtual_window_rect = parent->getLocalRect();
-//static
-void LLScreenClipRect::updateScissorRegion()
-{
- if (sClipRectStack.empty()) return;
+ LLRect mouse_rect;
+ const S32 MOUSE_CURSOR_PADDING = 5;
+ mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING,
+ mouse_y + MOUSE_CURSOR_PADDING,
+ CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
+ CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
- 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();
+ S32 local_x, local_y;
+ view->getParent()->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y);
+
+ // Start at spawn position (using left/top)
+ view->setOrigin( local_x, local_y - view->getRect().getHeight());
+ // Make sure we're onscreen and not overlapping the mouse
+ view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
}
-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)
-{
-}
+// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
namespace LLInitParam
{
@@ -2084,6 +2046,19 @@ namespace LLInitParam
return rect;
}
+ TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count),
+ x("x"),
+ y("y")
+ {
+ }
+
+ LLCoordGL TypedParam<LLCoordGL>::getValueFromBlock() const
+ {
+ return LLCoordGL(x, y);
+ }
+
+
void TypeValues<LLFontGL::HAlign>::declareValues()
{
declare("left", LLFontGL::LEFT);
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 1f9b0b2dbc..33338f30f9 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -39,8 +39,6 @@
#include "llrect.h"
#include "llcontrol.h"
#include "llcoord.h"
-#include "llgl.h" // *TODO: break this dependency
-#include <stack>
#include "lluiimage.h" // *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional<LLUIImage*> in their paramblocks
#include "llinitparam.h"
#include "llregistry.h"
@@ -50,6 +48,7 @@
#include "lllazyvalue.h"
#include "llhandle.h" // *TODO: remove this dependency, added as a
// convenience when LLHandle moved to llhandle.h
+#include "llframetimer.h"
// LLUIFactory
#include "llsd.h"
@@ -188,9 +187,9 @@ public:
static LLView* getRootView() { return sRootView; }
static void setRootView(LLView* view) { sRootView = view; }
static std::string locateSkin(const std::string& filename);
- static void setCursorPositionScreen(S32 x, S32 y);
- static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y);
- static void getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y);
+ static void setMousePositionScreen(S32 x, S32 y);
+ static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y);
+ static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
static void setScaleFactor(const LLVector2& scale_factor);
static void setLineWidth(F32 width);
static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id);
@@ -203,7 +202,16 @@ public:
static void setHtmlHelp(LLHtmlHelp* html_help);
// Returns the control group containing the control name, or the default group
static LLControlGroup& getControlControlGroup (const std::string& controlname);
-
+ static F32 getMouseIdleTime() { return sMouseIdleTimer.getElapsedTimeF32(); }
+ static void resetMouseIdleTimer() { sMouseIdleTimer.reset(); }
+ static LLWindow* getWindow() { return sWindow; }
+
+ // Ensures view does not overlap mouse cursor, but is inside
+ // the view's parent rectangle. Used for tooltips, inspectors.
+ // Optionally override the view's default X/Y, which are relative to the
+ // view's parent.
+ static void positionViewNearMouse(LLView* view, S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX);
+
//
// Data
//
@@ -211,38 +219,16 @@ public:
static LLUIAudioCallback sAudioCallback;
static LLVector2 sGLScaleFactor;
static LLWindow* sWindow;
- static BOOL sShowXUINames;
static LLHtmlHelp* sHtmlHelp;
static LLView* sRootView;
private:
static LLImageProviderInterface* sImageProvider;
static std::vector<std::string> sXUIPaths;
+ static LLFrameTimer sMouseIdleTimer;
};
-class LLScreenClipRect
-{
-public:
- 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 : public LLScreenClipRect
-{
-public:
- LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
-};
+// Moved LLLocalClipRect to lllocalcliprect.h
// Moved all LLHandle-related code to llhandle.h
@@ -406,10 +392,10 @@ namespace LLInitParam
{
typedef BlockValue<LLUIColor> super_t;
public:
- Optional<F32> red;
- Optional<F32> green;
- Optional<F32> blue;
- Optional<F32> alpha;
+ Optional<F32> red,
+ green,
+ blue,
+ alpha;
Optional<std::string> control;
TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
@@ -422,9 +408,9 @@ namespace LLInitParam
{
typedef BlockValue<const LLFontGL*> super_t;
public:
- Optional<std::string> name;
- Optional<std::string> size;
- Optional<std::string> style;
+ Optional<std::string> name,
+ size,
+ style;
TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
const LLFontGL* getValueFromBlock() const;
@@ -447,6 +433,19 @@ namespace LLInitParam
{
static void declareValues();
};
+
+ template<>
+ class TypedParam<LLCoordGL>
+ : public BlockValue<LLCoordGL>
+ {
+ typedef BlockValue<LLCoordGL> super_t;
+ public:
+ Optional<S32> x,
+ y;
+
+ TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
+ LLCoordGL getValueFromBlock() const;
+ };
}
#endif
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 7ff942268d..28cdb1ac27 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -257,6 +257,13 @@ BOOL LLUICtrl::handleRightMouseUp(S32 x, S32 y, MASK mask)
return handled;
}
+BOOL LLUICtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleDoubleClick(x, y, mask);
+ mDoubleClickSignal(this, x, y, mask);
+ return handled;
+}
+
// can't tab to children of a non-tab-stop widget
BOOL LLUICtrl::canFocusChildren() const
{
@@ -832,10 +839,6 @@ BOOL LLUICtrl::getTentative() const
void LLUICtrl::setColor(const LLColor4& color)
{ }
-// virtual
-void LLUICtrl::setAlpha(F32 alpha)
-{ }
-
namespace LLInitParam
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 3e2e1f41a1..4030230684 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -166,6 +166,7 @@ public:
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
@@ -212,7 +213,6 @@ public:
virtual void onTabInto();
virtual void clear();
virtual void setColor(const LLColor4& color);
- virtual void setAlpha(F32 alpha);
BOOL focusNextItem(BOOL text_entry_only);
BOOL focusPrevItem(BOOL text_entry_only);
@@ -239,6 +239,8 @@ public:
boost::signals2::connection setRightMouseDownCallback( const mouse_signal_t::slot_type& cb ) { return mRightMouseDownSignal.connect(cb); }
boost::signals2::connection setRightMouseUpCallback( const mouse_signal_t::slot_type& cb ) { return mRightMouseUpSignal.connect(cb); }
+ boost::signals2::connection setDoubleClickCallback( const mouse_signal_t::slot_type& cb ) { return mDoubleClickSignal.connect(cb); }
+
// *TODO: Deprecate; for backwards compatability only:
boost::signals2::connection setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data);
boost::signals2::connection setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb );
@@ -273,6 +275,8 @@ protected:
mouse_signal_t mMouseUpSignal;
mouse_signal_t mRightMouseDownSignal;
mouse_signal_t mRightMouseUpSignal;
+
+ mouse_signal_t mDoubleClickSignal;
LLViewModelPtr mViewModel;
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 1161101f90..538e1ec492 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -200,10 +200,7 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
floaterp->initFloaterXML(root, floaterp->getParent(), output_node);
- if (LLUI::sShowXUINames)
- {
- floaterp->setToolTip(filename);
- }
+ floaterp->setXMLFilename(filename);
floaterp->getCommitCallbackRegistrar().popScope();
floaterp->getEnableCallbackRegistrar().popScope();
@@ -276,10 +273,7 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L
panelp->getCommitCallbackRegistrar().popScope();
panelp->getEnableCallbackRegistrar().popScope();
- if (LLUI::sShowXUINames)
- {
- panelp->setToolTip(filename);
- }
+ panelp->setXMLFilename(filename);
if (!panelp->getFactoryMap().empty())
{
@@ -317,10 +311,6 @@ LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const
parent = mDummyPanel;
}
LLView *view = (*funcp)(node, parent, output_node);
- if (LLUI::sShowXUINames && view && !filename.empty())
- {
- view->setToolTip(filename);
- }
return view;
}
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
new file mode 100644
index 0000000000..3b689b93c0
--- /dev/null
+++ b/indra/llui/llurlaction.cpp
@@ -0,0 +1,137 @@
+/**
+ * @file llurlaction.cpp
+ * @author Martin Reddy
+ * @brief A set of actions that can performed on Urls
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llurlaction.h"
+#include "llview.h"
+#include "llwindow.h"
+#include "llurlregistry.h"
+
+// global state for the callback functions
+void (*LLUrlAction::sOpenURLCallback) (const std::string& url) = NULL;
+void (*LLUrlAction::sOpenURLInternalCallback) (const std::string& url) = NULL;
+void (*LLUrlAction::sOpenURLExternalCallback) (const std::string& url) = NULL;
+bool (*LLUrlAction::sExecuteSLURLCallback) (const std::string& url) = NULL;
+
+
+void LLUrlAction::setOpenURLCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLCallback = cb;
+}
+
+void LLUrlAction::setOpenURLInternalCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLInternalCallback = cb;
+}
+
+void LLUrlAction::setOpenURLExternalCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLExternalCallback = cb;
+}
+
+void LLUrlAction::setExecuteSLURLCallback(bool (*cb) (const std::string& url))
+{
+ sExecuteSLURLCallback = cb;
+}
+
+void LLUrlAction::openURL(std::string url)
+{
+ if (sOpenURLCallback)
+ {
+ (*sOpenURLCallback)(url);
+ }
+}
+
+void LLUrlAction::openURLInternal(std::string url)
+{
+ if (sOpenURLInternalCallback)
+ {
+ (*sOpenURLInternalCallback)(url);
+ }
+}
+
+void LLUrlAction::openURLExternal(std::string url)
+{
+ if (sOpenURLExternalCallback)
+ {
+ (*sOpenURLExternalCallback)(url);
+ }
+}
+
+void LLUrlAction::executeSLURL(std::string url)
+{
+ if (sExecuteSLURLCallback)
+ {
+ (*sExecuteSLURLCallback)(url);
+ }
+}
+
+void LLUrlAction::clickAction(std::string url)
+{
+ // Try to handle as SLURL first, then http Url
+ if ( (sExecuteSLURLCallback) && !(*sExecuteSLURLCallback)(url) )
+ {
+ if (sOpenURLCallback)
+ {
+ (*sOpenURLCallback)(url);
+ }
+ }
+}
+
+void LLUrlAction::teleportToLocation(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ if (! match.getLocation().empty())
+ {
+ executeSLURL("secondlife:///app/teleport/" + match.getLocation());
+ }
+ }
+}
+
+void LLUrlAction::copyURLToClipboard(std::string url)
+{
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
+}
+
+void LLUrlAction::copyLabelToClipboard(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));
+ }
+}
+
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
new file mode 100644
index 0000000000..6b9d565b44
--- /dev/null
+++ b/indra/llui/llurlaction.h
@@ -0,0 +1,93 @@
+/**
+ * @file llurlaction.h
+ * @author Martin Reddy
+ * @brief A set of actions that can performed on Urls
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLACTION_H
+#define LL_LLURLACTION_H
+
+#include <string>
+
+///
+/// The LLUrlAction class provides a number of static functions that
+/// let you open Urls in web browsers, execute SLURLs, and copy Urls
+/// to the clipboard. Many of these functions are not available at
+/// the llui level, and must be supplied via a set of callbacks.
+///
+/// N.B. The action functions specifically do not use const ref
+/// strings so that a url parameter can be used into a boost::bind()
+/// call under situations when that input string is deallocated before
+/// the callback is executed.
+///
+class LLUrlAction
+{
+public:
+ LLUrlAction();
+
+ /// load a Url in the user's preferred web browser
+ static void openURL(std::string url);
+
+ /// load a Url in the internal Second Life web browser
+ static void openURLInternal(std::string url);
+
+ /// load a Url in the operating system's default web browser
+ static void openURLExternal(std::string url);
+
+ /// execute the given secondlife: SLURL
+ static void executeSLURL(std::string url);
+
+ /// if the Url specifies an SL location, teleport there
+ static void teleportToLocation(std::string url);
+
+ /// perform the appropriate action for left-clicking on a Url
+ static void clickAction(std::string url);
+
+ /// copy the label for a Url to the clipboard
+ static void copyLabelToClipboard(std::string url);
+
+ /// copy a Url to the clipboard
+ static void copyURLToClipboard(std::string url);
+
+ /// specify the callbacks to enable this class's functionality
+ static void setOpenURLCallback(void (*cb) (const std::string& url));
+ static void setOpenURLInternalCallback(void (*cb) (const std::string& url));
+ static void setOpenURLExternalCallback(void (*cb) (const std::string& url));
+ static void setExecuteSLURLCallback(bool (*cb) (const std::string& url));
+
+private:
+ // callbacks for operations we can perform on Urls
+ static void (*sOpenURLCallback) (const std::string& url);
+ static void (*sOpenURLInternalCallback) (const std::string& url);
+ static void (*sOpenURLExternalCallback) (const std::string& url);
+ static bool (*sExecuteSLURLCallback) (const std::string& url);
+};
+
+#endif
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
new file mode 100644
index 0000000000..c20212c375
--- /dev/null
+++ b/indra/llui/llurlentry.cpp
@@ -0,0 +1,567 @@
+/**
+ * @file llurlentry.cpp
+ * @author Martin Reddy
+ * @brief Describes the Url types that can be registered in LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlentry.h"
+#include "lluri.h"
+#include "llcachename.h"
+#include "lltrans.h"
+
+LLUrlEntryBase::LLUrlEntryBase()
+{
+}
+
+LLUrlEntryBase::~LLUrlEntryBase()
+{
+}
+
+std::string LLUrlEntryBase::getUrl(const std::string &string)
+{
+ return escapeUrl(string);
+}
+
+std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
+{
+ // return the id from a SLURL in the format /app/{cmd}/{id}/about
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ if (path_array.size() == 4)
+ {
+ return path_array.get(2).asString();
+ }
+ return "";
+}
+
+std::string LLUrlEntryBase::unescapeUrl(const std::string &url) const
+{
+ return LLURI::unescape(url);
+}
+
+std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
+{
+ static std::string no_escape_chars;
+ static bool initialized = false;
+ if (!initialized)
+ {
+ no_escape_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~!$?&()*+,@:;=/%";
+
+ std::sort(no_escape_chars.begin(), no_escape_chars.end());
+ initialized = true;
+ }
+ return LLURI::escape(url, no_escape_chars, true);
+}
+
+std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
+{
+ // return the label part from [http://www.example.org Label]
+ const char *text = url.c_str();
+ S32 start = 0;
+ while (! isspace(text[start]))
+ {
+ start++;
+ }
+ while (text[start] == ' ' || text[start] == '\t')
+ {
+ start++;
+ }
+ return url.substr(start, url.size()-start-1);
+}
+
+std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string)
+{
+ // return the url part from [http://www.example.org Label]
+ const char *text = string.c_str();
+ S32 end = 0;
+ while (! isspace(text[end]))
+ {
+ end++;
+ }
+ return escapeUrl(string.substr(1, end-1));
+}
+
+void LLUrlEntryBase::addObserver(const std::string &id,
+ const std::string &url,
+ const LLUrlLabelCallback &cb)
+{
+ // add a callback to be notified when we have a label for the uuid
+ LLUrlEntryObserver observer;
+ observer.url = url;
+ observer.signal = new LLUrlLabelSignal();
+ if (observer.signal)
+ {
+ observer.signal->connect(cb);
+ mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
+ }
+}
+
+void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
+{
+ // notify all callbacks waiting on the given uuid
+ std::multimap<std::string, LLUrlEntryObserver>::iterator it;
+ for (it = mObservers.find(id); it != mObservers.end();)
+ {
+ // call the callback - give it the new label
+ LLUrlEntryObserver &observer = it->second;
+ (*observer.signal)(it->second.url, label);
+ // then remove the signal - we only need to call it once
+ delete observer.signal;
+ mObservers.erase(it++);
+ }
+}
+
+//
+// LLUrlEntryHTTP Describes generic http: and https: Urls
+//
+LLUrlEntryHTTP::LLUrlEntryHTTP()
+{
+ mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+ //mIcon = "gear.tga";
+}
+
+std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntryHTTP Describes generic http: and https: Urls with custom label
+// We use the wikipedia syntax of [http://www.example.org Text]
+//
+LLUrlEntryHTTPLabel::LLUrlEntryHTTPLabel()
+{
+ mPattern = boost::regex("\\[https?://\\S+[ \t]+[^\\]]+\\]",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTPLabel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getLabelFromWikiLink(url);
+}
+
+std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
+{
+ return getUrlFromWikiLink(string);
+}
+
+//
+// LLUrlEntrySLURL Describes generic http: and https: Urls
+//
+LLUrlEntrySLURL::LLUrlEntrySLURL()
+{
+ // see http://slurl.com/about.php for details on the SLURL format
+ mPattern = boost::regex("http://slurl.com/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slurl.xml";
+ mTooltip = LLTrans::getString("TooltipSLURL");
+}
+
+std::string LLUrlEntrySLURL::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - http://slurl.com/secondlife/Place/X/Y/Z
+ // - http://slurl.com/secondlife/Place/X/Y
+ // - http://slurl.com/secondlife/Place/X
+ // - http://slurl.com/secondlife/Place
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts == 5)
+ {
+ // handle slurl with (X,Y,Z) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-4]);
+ std::string x = path_array[path_parts-3];
+ std::string y = path_array[path_parts-2];
+ std::string z = path_array[path_parts-1];
+ return location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 4)
+ {
+ // handle slurl with (X,Y) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-3]);
+ std::string x = path_array[path_parts-2];
+ std::string y = path_array[path_parts-1];
+ return location + " (" + x + "," + y + ")";
+ }
+ else if (path_parts == 3)
+ {
+ // handle slurl with (X) coordinate
+ std::string location = unescapeUrl(path_array[path_parts-2]);
+ std::string x = path_array[path_parts-1];
+ return location + " (" + x + ")";
+ }
+ else if (path_parts == 2)
+ {
+ // handle slurl with no coordinates
+ std::string location = unescapeUrl(path_array[path_parts-1]);
+ return location;
+ }
+
+ return url;
+}
+
+std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
+{
+ // return the part of the Url after slurl.com/secondlife/
+ const std::string search_string = "secondlife";
+ size_t pos = url.find(search_string);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += search_string.size() + 1;
+ return url.substr(pos, url.size() - pos);
+}
+
+//
+// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+//
+LLUrlEntryAgent::LLUrlEntryAgent()
+{
+ mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/about",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_agent.xml";
+ mTooltip = LLTrans::getString("TooltipAgentUrl");
+}
+
+void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ // received the agent name from the server - tell our observers
+ callObservers(id.asString(), first + " " + last);
+}
+
+std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ std::string id = getIDStringFromUrl(url);
+ if (gCacheName && ! id.empty())
+ {
+ LLUUID uuid(id);
+ std::string full_name;
+ if (gCacheName->getFullName(uuid, full_name))
+ {
+ return full_name;
+ }
+ else
+ {
+ gCacheName->get(uuid, FALSE, boost::bind(&LLUrlEntryAgent::onAgentNameReceived, this, _1, _2, _3, _4));
+ addObserver(id, url, cb);
+ }
+ }
+
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
+// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
+//
+LLUrlEntryGroup::LLUrlEntryGroup()
+{
+ mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/about",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_group.xml";
+ mTooltip = LLTrans::getString("TooltipGroupUrl");
+}
+
+void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ // received the group name from the server - tell our observers
+ callObservers(id.asString(), first);
+}
+
+std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ std::string id = getIDStringFromUrl(url);
+ if (gCacheName && ! id.empty())
+ {
+ LLUUID uuid(id);
+ std::string group_name;
+ if (gCacheName->getGroupName(uuid, group_name))
+ {
+ return group_name;
+ }
+ else
+ {
+ gCacheName->get(uuid, TRUE, boost::bind(&LLUrlEntryGroup::onGroupNameReceived, this, _1, _2, _3, _4));
+ addObserver(id, url, cb);
+ }
+ }
+
+ return unescapeUrl(url);
+}
+
+///
+/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
+/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
+///
+LLUrlEntryParcel::LLUrlEntryParcel()
+{
+ mPattern = boost::regex("secondlife:///app/parcel/[\\da-f-]+/about",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_parcel.xml";
+ mTooltip = LLTrans::getString("TooltipParcelUrl");
+}
+
+std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntryPlace Describes secondlife:///<location> URLs
+//
+LLUrlEntryPlace::LLUrlEntryPlace()
+{
+ mPattern = boost::regex("secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slurl.xml";
+ mTooltip = LLTrans::getString("TooltipSLURL");
+}
+
+std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - secondlife://Place/X/Y/Z
+ // - secondlife://Place/X/Y
+ //
+ LLURI uri(url);
+ std::string location = unescapeUrl(uri.hostName());
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts == 3)
+ {
+ // handle slurl with (X,Y,Z) coordinates
+ std::string x = path_array[0];
+ std::string y = path_array[1];
+ std::string z = path_array[2];
+ return location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 2)
+ {
+ // handle slurl with (X,Y) coordinates
+ std::string x = path_array[0];
+ std::string y = path_array[1];
+ return location + " (" + x + "," + y + ")";
+ }
+
+ return url;
+}
+
+std::string LLUrlEntryPlace::getLocation(const std::string &url) const
+{
+ // return the part of the Url after secondlife:// part
+ const std::string search_string = "://";
+ size_t pos = url.find(search_string);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += search_string.size();
+ return url.substr(pos, url.size() - pos);
+}
+
+//
+// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
+// secondlife:///app/teleport/Ahern/50/50/50/
+//
+LLUrlEntryTeleport::LLUrlEntryTeleport()
+{
+ mPattern = boost::regex("secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_teleport.xml";
+ mTooltip = LLTrans::getString("TooltipTeleportUrl");
+}
+
+std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle teleport SLURLs in the following formats:
+ // - secondlife:///app/teleport/Place/X/Y/Z
+ // - secondlife:///app/teleport/Place/X/Y
+ // - secondlife:///app/teleport/Place/X
+ // - secondlife:///app/teleport/Place
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts == 6)
+ {
+ // handle teleport url with (X,Y,Z) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-4]);
+ std::string x = path_array[path_parts-3];
+ std::string y = path_array[path_parts-2];
+ std::string z = path_array[path_parts-1];
+ return "Teleport to " + location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 5)
+ {
+ // handle teleport url with (X,Y) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-3]);
+ std::string x = path_array[path_parts-2];
+ std::string y = path_array[path_parts-1];
+ return "Teleport to " + location + " (" + x + "," + y + ")";
+ }
+ else if (path_parts == 4)
+ {
+ // handle teleport url with (X) coordinate only
+ std::string location = unescapeUrl(path_array[path_parts-2]);
+ std::string x = path_array[path_parts-1];
+ return "Teleport to " + location + " (" + x + ")";
+ }
+ else if (path_parts == 3)
+ {
+ // handle teleport url with no coordinates
+ std::string location = unescapeUrl(path_array[path_parts-1]);
+ return "Teleport to " + location;
+ }
+
+ return url;
+}
+
+std::string LLUrlEntryTeleport::getLocation(const std::string &url) const
+{
+ // return the part of the Url after ///app/teleport
+ const std::string search_string = "teleport";
+ size_t pos = url.find(search_string);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += search_string.size() + 1;
+ return url.substr(pos, url.size() - pos);
+}
+
+///
+/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g.,
+/// secondlife:///app/objectim/<sessionid>
+///
+LLUrlEntryObjectIM::LLUrlEntryObjectIM()
+{
+ mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\\??\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_objectim.xml";
+ mTooltip = LLTrans::getString("TooltipObjectIMUrl");
+}
+
+std::string LLUrlEntryObjectIM::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ LLURI uri(url);
+ LLSD params = uri.queryMap();
+ if (params.has("name"))
+ {
+ // look for a ?name=<obj-name> param in the url
+ // and use that as the label if present.
+ std::string name = params.get("name");
+ LLStringUtil::trim(name);
+ if (name.empty())
+ {
+ name = LLTrans::getString("Unnamed");
+ }
+ return name;
+ }
+
+ return unescapeUrl(url);
+}
+
+std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
+{
+ LLURI uri(url);
+ LLSD params = uri.queryMap();
+ if (params.has("slurl"))
+ {
+ return params.get("slurl");
+ }
+
+ return "";
+}
+
+//
+// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
+// with secondlife:// (used as a catch-all for cases not matched above)
+//
+LLUrlEntrySL::LLUrlEntrySL()
+{
+ mPattern = boost::regex("secondlife://(\\w+)?(:\\d+)?/\\S+",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slapp.xml";
+ mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntrySL::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// with the ability to specify a custom label.
+//
+LLUrlEntrySLLabel::LLUrlEntrySLLabel()
+{
+ mPattern = boost::regex("\\[secondlife://\\S+[ \t]+[^\\]]+\\]",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slapp.xml";
+ mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntrySLLabel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getLabelFromWikiLink(url);
+}
+
+std::string LLUrlEntrySLLabel::getUrl(const std::string &string)
+{
+ return getUrlFromWikiLink(string);
+}
+
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
new file mode 100644
index 0000000000..54053872df
--- /dev/null
+++ b/indra/llui/llurlentry.h
@@ -0,0 +1,242 @@
+/**
+ * @file llurlentry.h
+ * @author Martin Reddy
+ * @brief Describes the Url types that can be registered in LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLENTRY_H
+#define LL_LLURLENTRY_H
+
+#include "lluuid.h"
+
+#include <boost/signals2.hpp>
+#include <boost/regex.hpp>
+#include <string>
+#include <map>
+
+typedef boost::signals2::signal<void (const std::string& url,
+ const std::string& label)> LLUrlLabelSignal;
+typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
+
+///
+/// LLUrlEntryBase is the base class of all Url types registered in the
+/// LLUrlRegistry. Each derived classes provides a regular expression
+/// to match the Url type (e.g., http://... or secondlife://...) along
+/// with an optional icon to display next to instances of the Url in
+/// a text display and a XUI file to use for any context menu popup.
+/// Functions are also provided to compute an appropriate label and
+/// tooltip/status bar text for the Url.
+///
+/// Some derived classes of LLUrlEntryBase may wish to compute an
+/// appropriate label for a Url by asking the server for information.
+/// You must therefore provide a callback method, so that you can be
+/// notified when an updated label has been received from the server.
+/// This label should then be used to replace any previous label
+/// that you received from getLabel() for the Url in question.
+///
+class LLUrlEntryBase
+{
+public:
+ LLUrlEntryBase();
+ virtual ~LLUrlEntryBase();
+
+ /// Return the regex pattern that matches this Url
+ boost::regex getPattern() const { return mPattern; }
+
+ /// Return the url from a string that matched the regex
+ virtual std::string getUrl(const std::string &string);
+
+ /// Given a matched Url, return a label for the Url
+ virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
+
+ /// Return an icon that can be displayed next to Urls of this type
+ const std::string &getIcon() const { return mIcon; }
+
+ /// Given a matched Url, return a tooltip string for the hyperlink
+ std::string getTooltip() const { return mTooltip; }
+
+ /// Return the name of a XUI file containing the context menu items
+ const std::string getMenuName() const { return mMenuName; }
+
+ /// Return the name of a SL location described by this Url, if any
+ virtual std::string getLocation(const std::string &url) const { return ""; }
+
+protected:
+ std::string getIDStringFromUrl(const std::string &url) const;
+ std::string escapeUrl(const std::string &url) const;
+ std::string unescapeUrl(const std::string &url) const;
+ std::string getLabelFromWikiLink(const std::string &url);
+ std::string getUrlFromWikiLink(const std::string &string);
+ void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
+ void callObservers(const std::string &id, const std::string &label);
+
+ typedef struct {
+ std::string url;
+ LLUrlLabelSignal *signal;
+ } LLUrlEntryObserver;
+
+ boost::regex mPattern;
+ std::string mIcon;
+ std::string mMenuName;
+ std::string mTooltip;
+ std::multimap<std::string, LLUrlEntryObserver> mObservers;
+};
+
+///
+/// LLUrlEntryHTTP Describes generic http: and https: Urls
+///
+class LLUrlEntryHTTP : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTP();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels
+///
+class LLUrlEntryHTTPLabel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTPLabel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+///
+/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
+///
+class LLUrlEntrySLURL : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySLURL();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+///
+class LLUrlEntryAgent : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryAgent();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+private:
+ void onAgentNameReceived(const LLUUID& id, const std::string& first,
+ const std::string& last, BOOL is_group);
+};
+
+///
+/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
+/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
+///
+class LLUrlEntryGroup : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryGroup();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+private:
+ void onGroupNameReceived(const LLUUID& id, const std::string& first,
+ const std::string& last, BOOL is_group);
+};
+
+///
+/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
+/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
+///
+class LLUrlEntryParcel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryParcel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
+/// secondlife:///Ahern/50/50/50
+///
+class LLUrlEntryPlace : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryPlace();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
+/// secondlife:///app/teleport/Ahern/50/50/50/
+///
+class LLUrlEntryTeleport : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryTeleport();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g.,
+/// secondlife:///app/objectim/<sessionid>?name=Foo
+///
+class LLUrlEntryObjectIM : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryObjectIM();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// (used as a catch-all for cases not matched above)
+///
+class LLUrlEntrySL : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySL();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// with the ability to specify a custom label.
+///
+class LLUrlEntrySLLabel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySLLabel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+#endif
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
new file mode 100644
index 0000000000..7eec4c4a65
--- /dev/null
+++ b/indra/llui/llurlmatch.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file llurlmatch.cpp
+ * @author Martin Reddy
+ * @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlmatch.h"
+
+LLUrlMatch::LLUrlMatch() :
+ mStart(0),
+ mEnd(0),
+ mUrl(""),
+ mLabel(""),
+ mTooltip(""),
+ mIcon(""),
+ mMenuName("")
+{
+}
+
+void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
+ const std::string &label, const std::string &tooltip,
+ const std::string &icon, const std::string &menu,
+ const std::string &location)
+{
+ mStart = start;
+ mEnd = end;
+ mUrl = url;
+ mLabel = label;
+ mTooltip = tooltip;
+ mIcon = icon;
+ mMenuName = menu;
+ mLocation = location;
+}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
new file mode 100644
index 0000000000..0711e41443
--- /dev/null
+++ b/indra/llui/llurlmatch.h
@@ -0,0 +1,98 @@
+/**
+ * @file llurlmatch.h
+ * @author Martin Reddy
+ * @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLMATCH_H
+#define LL_LLURLMATCH_H
+
+#include "linden_common.h"
+
+#include <string>
+#include <vector>
+
+///
+/// LLUrlMatch describes a single Url that was matched within a string by
+/// the LLUrlRegistry::findUrl() method. It includes the actual Url that
+/// was matched along with its first/last character offset in the string.
+/// An alternate label is also provided for creating a hyperlink, as well
+/// as tooltip/status text, an icon, and a XUI file for a context menu
+/// that can be used in a popup for a Url (e.g., Open, Copy URL, etc.)
+///
+class LLUrlMatch
+{
+public:
+ LLUrlMatch();
+
+ /// return true if this object does not contain a valid Url match yet
+ bool empty() const { return mUrl.empty(); }
+
+ /// return the offset in the string for the first character of the Url
+ U32 getStart() const { return mStart; }
+
+ /// return the offset in the string for the last character of the Url
+ U32 getEnd() const { return mEnd; }
+
+ /// return the Url that has been matched in the input string
+ const std::string &getUrl() const { return mUrl; }
+
+ /// return a label that can be used for the display of this Url
+ const std::string &getLabel() const { return mLabel; }
+
+ /// return a message that could be displayed in a tooltip or status bar
+ const std::string &getTooltip() const { return mTooltip; }
+
+ /// return the filename for an icon that can be displayed next to this Url
+ const std::string &getIcon() const { return mIcon; }
+
+ /// Return the name of a XUI file containing the context menu items
+ const std::string getMenuName() const { return mMenuName; }
+
+ /// return the SL location that this Url describes, or "" if none.
+ const std::string &getLocation() const { return mLocation; }
+
+ /// Change the contents of this match object (used by LLUrlRegistry)
+ void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
+ const std::string &tooltip, const std::string &icon,
+ const std::string &menu, const std::string &location);
+
+private:
+ U32 mStart;
+ U32 mEnd;
+ std::string mUrl;
+ std::string mLabel;
+ std::string mTooltip;
+ std::string mIcon;
+ std::string mMenuName;
+ std::string mLocation;
+};
+
+#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
new file mode 100644
index 0000000000..f2d340deb7
--- /dev/null
+++ b/indra/llui/llurlregistry.cpp
@@ -0,0 +1,164 @@
+/**
+ * @file llurlregistry.cpp
+ * @author Martin Reddy
+ * @brief Contains a set of Url types that can be matched in a string
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlregistry.h"
+
+#include <boost/regex.hpp>
+
+// default dummy callback that ignores any label updates from the server
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
+{
+}
+
+LLUrlRegistry::LLUrlRegistry()
+{
+ // Urls are matched in the order that they were registered
+ registerUrl(new LLUrlEntrySLURL());
+ registerUrl(new LLUrlEntryHTTP());
+ registerUrl(new LLUrlEntryHTTPLabel());
+ registerUrl(new LLUrlEntryAgent());
+ registerUrl(new LLUrlEntryGroup());
+ registerUrl(new LLUrlEntryParcel());
+ registerUrl(new LLUrlEntryTeleport());
+ registerUrl(new LLUrlEntryObjectIM());
+ registerUrl(new LLUrlEntryPlace());
+ registerUrl(new LLUrlEntrySL());
+ registerUrl(new LLUrlEntrySLLabel());
+}
+
+LLUrlRegistry::~LLUrlRegistry()
+{
+ // free all of the LLUrlEntryBase objects we are holding
+ std::vector<LLUrlEntryBase *>::iterator it;
+ for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
+ {
+ delete *it;
+ }
+}
+
+void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
+{
+ if (url)
+ {
+ mUrlEntry.push_back(url);
+ }
+}
+
+static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end)
+{
+ boost::cmatch result;
+ bool found;
+
+ // regex_search can potentially throw an exception, so check for it
+ try
+ {
+ found = boost::regex_search(text, result, regex);
+ }
+ catch (std::runtime_error &)
+ {
+ return false;
+ }
+
+ if (! found)
+ {
+ return false;
+ }
+
+ // return the first/last character offset for the matched substring
+ start = static_cast<U32>(result[0].first - text);
+ end = static_cast<U32>(result[0].second - text) - 1;
+
+ // we allow certain punctuation to terminate a Url but not match it,
+ // e.g., "http://foo.com/." should just match "http://foo.com/"
+ if (text[end] == '.' || text[end] == ',')
+ {
+ end--;
+ }
+ // ignore a terminating ')' when Url contains no matching '('
+ // see DEV-19842 for details
+ else if (text[end] == ')' && std::string(text+start, end-start).find('(') == std::string::npos)
+ {
+ end--;
+ }
+
+ return true;
+}
+
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+{
+ // avoid costly regexes if there is clearly no URL in the text
+ if (text.find("://") == std::string::npos)
+ {
+ return false;
+ }
+
+ // find the first matching regex from all url entries in the registry
+ U32 match_start = 0, match_end = 0;
+ LLUrlEntryBase *match_entry = NULL;
+
+ std::vector<LLUrlEntryBase *>::iterator it;
+ for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
+ {
+ LLUrlEntryBase *url_entry = *it;
+
+ U32 start = 0, end = 0;
+ if (matchRegex(text.c_str(), url_entry->getPattern(), start, end))
+ {
+ // does this match occur in the string before any other match
+ if (start < match_start || match_entry == NULL)
+ {
+ match_start = start;
+ match_end = end;
+ match_entry = url_entry;
+ }
+ }
+ }
+
+ // did we find a match? if so, return its details in the match object
+ if (match_entry)
+ {
+ // fill in the LLUrlMatch object and return it
+ std::string url = text.substr(match_start, match_end - match_start + 1);
+ match.setValues(match_start, match_end,
+ match_entry->getUrl(url),
+ match_entry->getLabel(url, cb),
+ match_entry->getTooltip(),
+ match_entry->getIcon(),
+ match_entry->getMenuName(),
+ match_entry->getLocation(url));
+ return true;
+ }
+
+ return false;
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
new file mode 100644
index 0000000000..84b033036c
--- /dev/null
+++ b/indra/llui/llurlregistry.h
@@ -0,0 +1,87 @@
+/**
+ * @file llurlregistry.h
+ * @author Martin Reddy
+ * @brief Contains a set of Url types that can be matched in a string
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLREGISTRY_H
+#define LL_LLURLREGISTRY_H
+
+#include "llurlentry.h"
+#include "llurlmatch.h"
+#include "llsingleton.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+/// This default callback for findUrl() simply ignores any label updates
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
+
+///
+/// LLUrlRegistry is a singleton that contains a set of Url types that
+/// can be matched in string. E.g., http:// or secondlife:// Urls.
+///
+/// Clients call the findUrl() method on a string to locate the first
+/// occurence of a supported Urls in that string. If findUrl() returns
+/// true, the LLUrlMatch object will be updated to describe the Url
+/// that was matched, including a label that can be used to hyperlink
+/// the Url, an icon to display next to the Url, and a XUI menu that
+/// can be used as a popup context menu for that Url.
+///
+/// New Url types can be added to the registry with the registerUrl
+/// method. E.g., to add support for a new secondlife:///app/ Url.
+///
+/// Computing the label for a Url could involve a roundtrip request
+/// to the server (e.g., to find the actual agent or group name).
+/// As such, you can provide a callback method that will get invoked
+/// when a new label is available for one of your matched Urls.
+///
+class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
+{
+public:
+ ~LLUrlRegistry();
+
+ /// add a new Url handler to the registry (will be freed on destruction)
+ void registerUrl(LLUrlEntryBase *url);
+
+ /// get the next Url in an input string, starting at a given character offset
+ /// your callback is invoked if the matched Url's label changes in the future
+ bool findUrl(const std::string &text, LLUrlMatch &match,
+ const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+
+private:
+ LLUrlRegistry();
+ friend class LLSingleton<LLUrlRegistry>;
+
+ std::vector<LLUrlEntryBase *> mUrlEntry;
+};
+
+#endif
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 4770807ac7..46510804f8 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -49,6 +49,7 @@
#include "llwindow.h"
#include "v3color.h"
#include "lluictrlfactory.h"
+#include "lltooltip.h"
// for ui edit hack
#include "llbutton.h"
@@ -70,6 +71,8 @@ LLView* LLView::sPreviewClickedElement = NULL;
BOOL LLView::sDrawPreviewHighlights = FALSE;
S32 LLView::sLastLeftXML = S32_MIN;
S32 LLView::sLastBottomXML = S32_MIN;
+std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
+
#if LL_DEBUG
BOOL LLView::sIsDrawing = FALSE;
@@ -662,86 +665,52 @@ void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
}
-std::string LLView::getShowNamesToolTip()
+LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
- LLView* view = getParent();
- std::string name;
- std::string tool_tip = mName;
-
- while (view)
+ LLView* handled_view = NULL;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- name = view->getName();
-
- if (name == "root") break;
-
- if (view->getToolTip().find(".xml") != std::string::npos)
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if(viewp->pointInView(local_x, local_y) &&
+ viewp->getVisible() &&
+ viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) )
{
- tool_tip = view->getToolTip() + "/" + tool_tip;
+ if (sDebugMouseHandling)
+ {
+ sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ }
+
+ handled_view = viewp;
break;
}
- else
- {
- tool_tip = view->getName() + "/" + tool_tip;
- }
-
- view = view->getParent();
}
-
- return "/" + tool_tip;
+ return handled_view;
}
-
-BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
- BOOL handled = FALSE;
-
- std::string tool_tip;
+ LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen);
+ BOOL handled = child_handler != NULL;
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ // child widgets get priority on tooltips
+ if (!handled && !mToolTipMsg.empty())
{
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->mRect.mLeft;
- S32 local_y = y - viewp->mRect.mBottom;
- // Allow tooltips for disabled views so we can explain to the user why
- // the view is disabled. JC
- if( viewp->pointInView(local_x, local_y)
- && viewp->getVisible()
- // && viewp->getEnabled()
- && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ))
- {
- // child provided a tooltip, just return
- if (!msg.empty()) return TRUE;
-
- // otherwise, one of our children ate the event so don't traverse
- // siblings however, our child did not actually provide a tooltip
- // so we might want to
- handled = TRUE;
- break;
- }
- }
+ // allow "scrubbing" over ui by showing next tooltip immediately
+ // if previous one was still visible
+ F32 timeout = LLToolTipMgr::instance().toolTipVisible()
+ ? 0.f
+ : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" );
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(mToolTipMsg)
+ .sticky_rect(calcScreenRect())
+ .delay_time(timeout));
- // get our own tooltip
- tool_tip = mToolTipMsg.getString();
-
- if (LLUI::sShowXUINames
- && (tool_tip.find(".xml", 0) == std::string::npos)
- && (mName.find("Drag", 0) == std::string::npos))
- {
- tool_tip = getShowNamesToolTip();
+ handled = TRUE;
}
- if(!tool_tip.empty())
- {
- msg = tool_tip;
-
- // Convert rect local to screen coordinates
- *sticky_rect_screen = calcScreenRect();
- }
- // don't allow any siblings to handle this event
- // even if we don't have a tooltip
- if (getMouseOpaque() ||
- (!tool_tip.empty() &&
- (!LLUI::sShowXUINames || dynamic_cast<LLTextBox*>(this))))
+ if( blockMouseEvent(x, y) )
{
handled = TRUE;
}
@@ -1518,45 +1487,51 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
updateBoundingRect();
}
-void LLView::updateBoundingRect()
+LLRect LLView::calcBoundingRect()
{
- if (isDead()) return;
+ LLRect local_bounding_rect = LLRect::null;
- if (mUseBoundingRect)
+ child_list_const_iter_t child_it;
+ for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- 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;
+ // ignore invisible and "top" children when calculating bounding rect
+ // such as combobox popups
+ if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
{
- LLView* childp = *child_it;
- // ignore invisible and "top" children when calculating bounding rect
- // such as combobox popups
- if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
- {
- continue;
- }
+ continue;
+ }
- LLRect child_bounding_rect = childp->getBoundingRect();
+ LLRect child_bounding_rect = childp->getBoundingRect();
- if (local_bounding_rect.isEmpty())
- {
- // start out with bounding rect equal to first visible child's bounding rect
- local_bounding_rect = child_bounding_rect;
- }
- else
+ if (local_bounding_rect.isEmpty())
+ {
+ // 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.isEmpty())
{
- // accumulate non-null children rectangles
- if (!child_bounding_rect.isEmpty())
- {
- local_bounding_rect.unionWith(child_bounding_rect);
- }
+ local_bounding_rect.unionWith(child_bounding_rect);
}
}
+ }
- mBoundingRect = local_bounding_rect;
- // translate into parent-relative coordinates
- mBoundingRect.translate(mRect.mLeft, mRect.mBottom);
+ // convert to parent-relative coordinates
+ local_bounding_rect.translate(mRect.mLeft, mRect.mBottom);
+ return local_bounding_rect;
+}
+
+
+void LLView::updateBoundingRect()
+{
+ if (isDead()) return;
+
+ if (mUseBoundingRect)
+ {
+ mBoundingRect = calcBoundingRect();
}
else
{
@@ -1817,73 +1792,123 @@ void LLView::deleteViewByHandle(LLHandle<LLView> handle)
}
-// Moves the view so that it is entirely inside of constraint.
-// If the view will not fit because it's too big, aligns with the top and left.
-// (Why top and left? That's where the drag bars are for floaters.)
-BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)
{
- S32 delta_x = 0;
- S32 delta_y = 0;
+ LLCoordGL delta;
if (allow_partial_outside)
{
const S32 KEEP_ONSCREEN_PIXELS = 16;
- if( getRect().mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
+ if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
{
- delta_x = constraint.mLeft - (getRect().mRight - KEEP_ONSCREEN_PIXELS);
+ delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS);
}
else
- if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
+ if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
{
- delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS);
+ delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS);
}
- if( getRect().mTop > constraint.mTop )
+ if( input.mTop > constraint.mTop )
{
- delta_y = constraint.mTop - getRect().mTop;
+ delta.mY = constraint.mTop - input.mTop;
}
else
- if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
+ if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
{
- delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS);
+ delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS);
}
}
else
{
- if( getRect().mLeft < constraint.mLeft )
+ if( input.mLeft < constraint.mLeft )
{
- delta_x = constraint.mLeft - getRect().mLeft;
+ delta.mX = constraint.mLeft - input.mLeft;
}
else
- if( getRect().mRight > constraint.mRight )
+ if( input.mRight > constraint.mRight )
{
- delta_x = constraint.mRight - getRect().mRight;
+ delta.mX = constraint.mRight - input.mRight;
// compensate for left edge possible going off screen
- delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() );
+ delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() );
}
- if( getRect().mTop > constraint.mTop )
+ if( input.mTop > constraint.mTop )
{
- delta_y = constraint.mTop - getRect().mTop;
+ delta.mY = constraint.mTop - input.mTop;
}
else
- if( getRect().mBottom < constraint.mBottom )
+ if( input.mBottom < constraint.mBottom )
{
- delta_y = constraint.mBottom - getRect().mBottom;
+ delta.mY = constraint.mBottom - input.mBottom;
// compensate for top edge possible going off screen
- delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() );
+ delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() );
}
}
- if (delta_x != 0 || delta_y != 0)
+ return delta;
+}
+
+// Moves the view so that it is entirely inside of constraint.
+// If the view will not fit because it's too big, aligns with the top and left.
+// (Why top and left? That's where the drag bars are for floaters.)
+BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+{
+ LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside);
+
+ if (translation.mX != 0 || translation.mY != 0)
+ {
+ translate(translation.mX, translation.mY);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// move this view into "inside" but not onto "exclude"
+// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect
+BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside )
+{
+ LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside);
+
+ if (translation.mX != 0 || translation.mY != 0)
{
- translate(delta_x, delta_y);
+ // translate ourselves into constraint rect
+ translate(translation.mX, translation.mY);
+
+ // do we overlap with exclusion area?
+ // keep moving in the same direction to the other side of the exclusion rect
+ if (exclude.overlaps(getRect()))
+ {
+ // moving right
+ if (translation.mX > 0)
+ {
+ translate(exclude.mRight - getRect().mLeft, 0);
+ }
+ // moving left
+ else if (translation.mX < 0)
+ {
+ translate(exclude.mLeft - getRect().mRight, 0);
+ }
+
+ // moving up
+ if (translation.mY > 0)
+ {
+ translate(0, exclude.mTop - getRect().mBottom);
+ }
+ // moving down
+ else if (translation.mY < 0)
+ {
+ translate(0, exclude.mBottom - getRect().mTop);
+ }
+ }
+
return TRUE;
}
return FALSE;
}
+
void LLView::centerWithin(const LLRect& bounds)
{
S32 left = bounds.mLeft + (bounds.getWidth() - getRect().getWidth()) / 2;
@@ -2712,19 +2737,44 @@ void LLView::setupParamsForExport(Params& p, LLView* parent)
convert_coords_to_top_left(p, parent);
}
-LLView::tree_iterator_t LLView::beginTree()
+LLView::tree_iterator_t LLView::beginTreeDFS()
{
return tree_iterator_t(this,
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
-LLView::tree_iterator_t LLView::endTree()
+LLView::tree_iterator_t LLView::endTreeDFS()
{
// an empty iterator is an "end" iterator
return tree_iterator_t();
}
+LLView::tree_post_iterator_t LLView::beginTreeDFSPost()
+{
+ return tree_post_iterator_t(this,
+ boost::bind(boost::mem_fn(&LLView::beginChild), _1),
+ boost::bind(boost::mem_fn(&LLView::endChild), _1));
+}
+
+LLView::tree_post_iterator_t LLView::endTreeDFSPost()
+{
+ // an empty iterator is an "end" iterator
+ return tree_post_iterator_t();
+}
+
+
+LLView::root_to_view_iterator_t LLView::beginRootToView()
+{
+ return root_to_view_iterator_t(this, boost::bind(&LLView::getParent, _1));
+}
+
+LLView::root_to_view_iterator_t LLView::endRootToView()
+{
+ return root_to_view_iterator_t();
+}
+
+
// only create maps on demand, as they incur heap allocation/deallocation cost
// when a view is constructed/deconstructed
LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const
@@ -2735,3 +2785,33 @@ LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const
}
return *mDefaultWidgets;
}
+
+void LLView::notifyParent(const LLSD& info)
+{
+ LLView* parent = getParent();
+ if(parent)
+ parent->notifyParent(info);
+}
+void LLView::notifyChildren(const LLSD& info)
+{
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ {
+ (*child_it)->notifyChildren(info);
+ }
+}
+
+// convenient accessor for draw context
+const LLViewDrawContext& LLView::getDrawContext()
+{
+ return LLViewDrawContext::getCurrentContext();
+}
+
+const LLViewDrawContext& LLViewDrawContext::getCurrentContext()
+{
+ static LLViewDrawContext default_context;
+
+ if (sDrawContextStack.empty())
+ return default_context;
+
+ return *sDrawContextStack.back();
+}
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index ecc6bf47da..1f7e5afaae 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -70,74 +70,35 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE;
const U32 GL_NAME_UI_RESERVED = 2;
-/*
-// virtual functions defined in LLView:
-
-virtual BOOL isCtrl() const;
- LLUICtrl
-virtual BOOL isPanel();
- LLPanel
-virtual void setRect(const LLRect &rect);
- LLLineEditor
- LLPanel
-virtual BOOL canFocusChildren() const { return TRUE; }
- LLFolderView
-virtual void deleteAllChildren();
- LLFolderView, LLPanelInventory
-virtual void setTentative(BOOL b) {}
- LLUICtrl, LLSliderCtrl, LLSpinCtrl
-virtual BOOL getTentative() const { return FALSE; }
- LLUICtrl, LLCheckBoxCtrl
-virtual void setVisible(BOOL visible);
- LLFloater, LLAlertDialog, LLMenuItemGL, LLModalDialog
-virtual void setEnabled(BOOL enabled) { mEnabled = enabled; }
- LLCheckBoxCtrl, LLComboBox, LLLineEditor, LLMenuGL, LLRadioGroup, etc
-virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) { return FALSE; }
- LLUICtrl, LLButton, LLCheckBoxCtrl, LLLineEditor, LLMenuGL, LLSliderCtrl
-virtual void handleVisibilityChange ( BOOL curVisibilityIn );
- LLMenuGL
-virtual LLRect getSnapRect() const { return mRect; } *TODO: Make non virtual
- LLFloater
-virtual LLRect getRequiredRect() { return mRect; }
- LLScrolllistCtrl
-virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- LLUICtrl, et. al.
-virtual void translate( S32 x, S32 y );
- LLMenuGL
-virtual void setShape(const LLRect& new_rect, bool by_user);
- LLFloater, LLScrollLIstVtrl
-virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
-virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
- LLScrollListCtrl
-virtual BOOL canSnapTo(const LLView* other_view) { return other_view != this && other_view->getVisible(); }
- LLFloater
-virtual void snappedTo(const LLView* snap_view) {}
- LLFloater
-virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- *
-virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
- *
-virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropType cargo_type,void* cargo_data,EAcceptance* accept,std::string& tooltip_msg);
- *
-virtual void draw();
- *
-
- *
-virtual void onFocusLost() {}
- LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox
-virtual void onFocusReceived() {}
- LLUICtrl, LLTextEditor, LLScrollListVtrl, LLMenuGL, LLLineEditor
-virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
- LLTabContainer, LLPanel, LLMenuGL
-virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- LLMenuItem
-protected:
-virtual BOOL handleKeyHere(KEY key, MASK mask);
- *
-virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- *
-*/
+// maintains render state during traversal of UI tree
+class LLViewDrawContext
+{
+public:
+ F32 mAlpha;
+
+ LLViewDrawContext(F32 alpha = 1.f)
+ : mAlpha(alpha)
+ {
+ if (!sDrawContextStack.empty())
+ {
+ LLViewDrawContext* context_top = sDrawContextStack.back();
+ // merge with top of stack
+ mAlpha *= context_top->mAlpha;
+ }
+ sDrawContextStack.push_back(this);
+ }
+
+ ~LLViewDrawContext()
+ {
+ sDrawContextStack.pop_back();
+ }
+
+ static const LLViewDrawContext& getCurrentContext();
+
+private:
+ static std::vector<LLViewDrawContext*> sDrawContextStack;
+};
class LLViewWidgetRegistry : public LLChildRegistry<LLViewWidgetRegistry>
{};
@@ -380,6 +341,7 @@ public:
// Override and return required size for this object. 0 for width/height means don't care.
virtual LLRect getRequiredRect();
+ LLRect calcBoundingRect();
void updateBoundingRect();
LLView* getRootView();
@@ -393,9 +355,19 @@ public:
BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const;
BOOL childHasKeyboardFocus( const std::string& childname ) const;
+ // these iterators are used for collapsing various tree traversals into for loops
typedef LLTreeDFSIter<LLView, child_list_const_iter_t> tree_iterator_t;
- tree_iterator_t beginTree();
- tree_iterator_t endTree();
+ tree_iterator_t beginTreeDFS();
+ tree_iterator_t endTreeDFS();
+
+ typedef LLTreeDFSPostIter<LLView, child_list_const_iter_t> tree_post_iterator_t;
+ tree_post_iterator_t beginTreeDFSPost();
+ tree_post_iterator_t endTreeDFSPost();
+
+
+ typedef LLTreeDownIter<LLView> root_to_view_iterator_t;
+ root_to_view_iterator_t beginRootToView();
+ root_to_view_iterator_t endRootToView();
//
// UTILITIES
@@ -406,6 +378,7 @@ public:
virtual void translate( S32 x, S32 y );
void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
+ BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside );
void centerWithin(const LLRect& bounds);
void setShape(const LLRect& new_rect, bool by_user = false);
@@ -424,10 +397,7 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
- virtual std::string getShowNamesToolTip();
-
virtual void draw();
- void drawChildren();
void parseFollowsFlags(const LLView::Params& params);
@@ -477,7 +447,8 @@ public:
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it.
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); // Display mToolTipMsg if no child handles it.
+
/*virtual*/ const std::string& getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ BOOL hasMouseCapture();
@@ -549,9 +520,15 @@ public:
virtual void handleReshape(const LLRect& rect, bool by_user);
+ virtual void notifyParent(const LLSD& info);
+ virtual void notifyChildren(const LLSD& info);
+
+ static const LLViewDrawContext& getDrawContext();
+
protected:
void drawDebugRect();
void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
+ void drawChildren();
LLView* childrenHandleKey(KEY key, MASK mask);
LLView* childrenHandleUnicodeChar(llwchar uni_char);
@@ -571,10 +548,12 @@ protected:
LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
+ LLView* childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
ECursorType mHoverCursor;
private:
+
LLView* mParentView;
child_list_t mChildList;
@@ -654,7 +633,7 @@ template <class T> T* LLView::getChild(const std::string& name, BOOL recurse) co
// did we find *something* with that name?
if (child)
{
- llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T*).name() << llendl;
+ llwarns << "Found child named " << name << " but of wrong type " << typeid(*child).name() << ", expecting " << typeid(T*).name() << llendl;
}
result = getDefaultWidget<T>(name);
if (!result)
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index f41c98f7b3..30717f87de 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -134,7 +134,7 @@ void LLViewBorder::draw()
}
}
- drawChildren();
+ LLView::draw();
}
void LLViewBorder::drawOnePixelLines()
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
new file mode 100644
index 0000000000..26d1f2e067
--- /dev/null
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -0,0 +1,64 @@
+/**
+ * @file llurlentry_stub.cpp
+ * @author Martin Reddy
+ * @brief Stub implementations for LLUrlEntry unit test dependencies
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llstring.h"
+#include "llfile.h"
+#include "llcachename.h"
+#include "lluuid.h"
+
+#include <string>
+
+//
+// Stub implementation for LLCacheName
+//
+BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
+{
+ fullname = "Lynx Linden";
+ return TRUE;
+}
+
+BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
+{
+ group = "My Group";
+ return TRUE;
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+{
+ return boost::signals2::connection();
+}
+
+LLCacheName* gCacheName = NULL;
+
+//
+// Stub implementation for LLTrans
+//
+class LLTrans
+{
+public:
+ static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+};
+
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args)
+{
+ return std::string();
+}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
new file mode 100644
index 0000000000..1e7a0f7f2c
--- /dev/null
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -0,0 +1,531 @@
+/**
+ * @file llurlentry_test.cpp
+ * @author Martin Reddy
+ * @brief Unit tests for LLUrlEntry objects
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../llurlentry.h"
+#include "llurlentry_stub.cpp"
+#include "lltut.h"
+
+#include <boost/regex.hpp>
+
+namespace tut
+{
+ struct LLUrlEntryData
+ {
+ };
+
+ typedef test_group<LLUrlEntryData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLUrlEntry");
+}
+
+namespace tut
+{
+ void testRegex(const std::string &testname, boost::regex regex,
+ const char *text, const std::string &expected)
+ {
+ std::string url = "";
+ boost::cmatch result;
+ bool found = boost::regex_search(text, result, regex);
+ if (found)
+ {
+ S32 start = static_cast<U32>(result[0].first - text);
+ S32 end = static_cast<U32>(result[0].second - text);
+ url = std::string(text+start, end-start);
+ }
+ ensure_equals(testname, url, expected);
+ }
+
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test LLUrlEntryHTTP - standard http Urls
+ //
+ LLUrlEntryHTTP url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid url", r,
+ "htp://slurl.com/",
+ "");
+
+ testRegex("simple http (1)", r,
+ "http://slurl.com/",
+ "http://slurl.com/");
+
+ testRegex("simple http (2)", r,
+ "http://slurl.com",
+ "http://slurl.com");
+
+ testRegex("simple http (3)", r,
+ "http://slurl.com/about.php",
+ "http://slurl.com/about.php");
+
+ testRegex("simple https", r,
+ "https://slurl.com/about.php",
+ "https://slurl.com/about.php");
+
+ testRegex("http in text (1)", r,
+ "XX http://slurl.com/ XX",
+ "http://slurl.com/");
+
+ testRegex("http in text (2)", r,
+ "XX http://slurl.com/about.php XX",
+ "http://slurl.com/about.php");
+
+ testRegex("https in text", r,
+ "XX https://slurl.com/about.php XX",
+ "https://slurl.com/about.php");
+
+ testRegex("two http urls", r,
+ "XX http://slurl.com/about.php http://secondlife.com/ XX",
+ "http://slurl.com/about.php");
+
+ testRegex("http url with port and username", r,
+ "XX http://nobody@slurl.com:80/about.php http://secondlife.com/ XX",
+ "http://nobody@slurl.com:80/about.php");
+
+ testRegex("http url with port, username, and query string", r,
+ "XX http://nobody@slurl.com:80/about.php?title=hi%20there http://secondlife.com/ XX",
+ "http://nobody@slurl.com:80/about.php?title=hi%20there");
+
+ // note: terminating commas will be removed by LLUrlRegistry:findUrl()
+ testRegex("http url with commas in middle and terminating", r,
+ "XX http://slurl.com/?title=Hi,There, XX",
+ "http://slurl.com/?title=Hi,There,");
+
+ // note: terminating periods will be removed by LLUrlRegistry:findUrl()
+ testRegex("http url with periods in middle and terminating", r,
+ "XX http://slurl.com/index.php. XX",
+ "http://slurl.com/index.php.");
+
+ // DEV-19842: Closing parenthesis ")" breaks urls
+ testRegex("http url with brackets (1)", r,
+ "XX http://en.wikipedia.org/wiki/JIRA_(software) XX",
+ "http://en.wikipedia.org/wiki/JIRA_(software)");
+
+ // DEV-19842: Closing parenthesis ")" breaks urls
+ testRegex("http url with brackets (2)", r,
+ "XX http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg XX",
+ "http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg");
+
+ // DEV-10353: URLs in chat log terminated incorrectly when newline in chat
+ testRegex("http url with newlines", r,
+ "XX\nhttp://www.secondlife.com/\nXX",
+ "http://www.secondlife.com/");
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test LLUrlEntryHTTPLabel - wiki-style http Urls with labels
+ //
+ LLUrlEntryHTTPLabel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("invalid wiki url [1]", r,
+ "[http://www.example.org]",
+ "");
+
+ testRegex("invalid wiki url [2]", r,
+ "[http://www.example.org",
+ "");
+
+ testRegex("invalid wiki url [3]", r,
+ "[http://www.example.org Label",
+ "");
+
+ testRegex("example.org with label (spaces)", r,
+ "[http://www.example.org Text]",
+ "[http://www.example.org Text]");
+
+ testRegex("example.org with label (tabs)", r,
+ "[http://www.example.org\t Text]",
+ "[http://www.example.org\t Text]");
+
+ testRegex("SL http URL with label", r,
+ "[http://www.secondlife.com/ Second Life]",
+ "[http://www.secondlife.com/ Second Life]");
+
+ testRegex("SL https URL with label", r,
+ "XXX [https://www.secondlife.com/ Second Life] YYY",
+ "[https://www.secondlife.com/ Second Life]");
+
+ testRegex("SL http URL with label", r,
+ "[http://www.secondlife.com/?test=Hi%20There Second Life]",
+ "[http://www.secondlife.com/?test=Hi%20There Second Life]");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test LLUrlEntrySLURL - second life URLs
+ //
+ LLUrlEntrySLURL url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slurl [1]", r,
+ "htp://slurl.com/secondlife/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid slurl [2]", r,
+ "http://slurl.com/secondlife/",
+ "");
+
+ testRegex("no valid slurl [3]", r,
+ "hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "http://slurl.com/secondlife/Ahern/50/50/50/",
+ "http://slurl.com/secondlife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/ XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX http://SLUrl.com/SecondLife/Ahern/50/50/50/ XXX",
+ "http://SLUrl.com/SecondLife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/ XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50/50");
+
+ testRegex("Ahern (50)", r,
+ "XXX http://slurl.com/secondlife/Ahern/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50");
+
+ testRegex("Ahern", r,
+ "XXX http://slurl.com/secondlife/Ahern/ XXX",
+ "http://slurl.com/secondlife/Ahern/");
+
+ testRegex("Ahern SLURL with title", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
+
+ testRegex("Ahern SLURL with msg", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here.");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("SLURL with brackets", r,
+ "XXX http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("SLURL with quote", r,
+ "XXX http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701 XXX",
+ "http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test LLUrlEntryAgent - secondlife://app/agent Urls
+ //
+ LLUrlEntryAgent url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Agent Url", r,
+ "secondlife:///app/agent/0e346d8b-4433-4d66-XXXX-fd37083abc4c/about",
+ "");
+
+ testRegex("Agent Url ", r,
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about",
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
+
+ testRegex("Agent Url in text", r,
+ "XXX secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about XXX",
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
+
+ testRegex("Agent Url multicase", r,
+ "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About XXX",
+ "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test LLUrlEntryGroup - secondlife://app/group Urls
+ //
+ LLUrlEntryGroup url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Group Url", r,
+ "secondlife:///app/group/00005ff3-4044-c79f-XXXX-fb28ae0df991/about",
+ "");
+
+ testRegex("Group Url ", r,
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about",
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
+
+ testRegex("Group Url in text", r,
+ "XXX secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about XXX",
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
+
+ testRegex("Group Url multicase", r,
+ "XXX secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About XXX",
+ "secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About");
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test LLUrlEntryPlace - secondlife://<location> URLs
+ //
+ LLUrlEntryPlace url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slurl [1]", r,
+ "secondlife://Ahern/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "secondlife://Ahern/50/50/50/",
+ "secondlife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX secondlife://Ahern/50/50/50/ XXX",
+ "secondlife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX secondlife://Ahern/50/50/50 XXX",
+ "secondlife://Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX SecondLife://Ahern/50/50/50/ XXX",
+ "SecondLife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX secondlife://Ahern/50/50/ XXX",
+ "secondlife://Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX secondlife://Ahern/50/50 XXX",
+ "secondlife://Ahern/50/50");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("SLURL with brackets", r,
+ "XXX secondlife://Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "secondlife://Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("SLURL with quote", r,
+ "XXX secondlife://A'ksha%20Oasis/41/166/701 XXX",
+ "secondlife://A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test LLUrlEntryParcel - secondlife://app/parcel Urls
+ //
+ LLUrlEntryParcel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Classified Url", r,
+ "secondlife:///app/parcel/0000060e-4b39-e00b-XXXX-d98b1934e3a8/about",
+ "");
+
+ testRegex("Classified Url ", r,
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about",
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
+
+ testRegex("Classified Url in text", r,
+ "XXX secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about XXX",
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
+
+ testRegex("Classified Url multicase", r,
+ "XXX secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About XXX",
+ "secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About");
+ }
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test LLUrlEntryTeleport - secondlife://app/teleport URLs
+ //
+ LLUrlEntryTeleport url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid teleport [1]", r,
+ "http://slurl.com/secondlife/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid teleport [2]", r,
+ "secondlife:///app/teleport/",
+ "");
+
+ testRegex("no valid teleport [3]", r,
+ "second-life:///app/teleport/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid teleport [3]", r,
+ "hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "secondlife:///app/teleport/Ahern/50/50/50/",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50 XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50 XXX",
+ "secondlife:///app/teleport/Ahern/50/50");
+
+ testRegex("Ahern (50)", r,
+ "XXX secondlife:///app/teleport/Ahern/50 XXX",
+ "secondlife:///app/teleport/Ahern/50");
+
+ testRegex("Ahern", r,
+ "XXX secondlife:///app/teleport/Ahern/ XXX",
+ "secondlife:///app/teleport/Ahern/");
+
+ testRegex("Ahern teleport with title", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
+
+ testRegex("Ahern teleport with msg", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here.");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("Teleport with brackets", r,
+ "XXX secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("Teleport url with quote", r,
+ "XXX secondlife:///app/teleport/A'ksha%20Oasis/41/166/701 XXX",
+ "secondlife:///app/teleport/A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test LLUrlEntrySL - general secondlife:// URLs
+ //
+ LLUrlEntrySL url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slapp [1]", r,
+ "http:///app/",
+ "");
+
+ testRegex("valid slapp [1]", r,
+ "secondlife:///app/",
+ "secondlife:///app/");
+
+ testRegex("valid slapp [2]", r,
+ "secondlife:///app/teleport/Ahern/50/50/50/",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("valid slapp [3]", r,
+ "secondlife:///app/foo",
+ "secondlife:///app/foo");
+
+ testRegex("valid slapp [4]", r,
+ "secondlife:///APP/foo?title=Hi%20There",
+ "secondlife:///APP/foo?title=Hi%20There");
+
+ testRegex("valid slapp [5]", r,
+ "secondlife://host/app/",
+ "secondlife://host/app/");
+
+ testRegex("valid slapp [6]", r,
+ "secondlife://host:8080/foo/bar",
+ "secondlife://host:8080/foo/bar");
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test LLUrlEntrySLLabel - general secondlife:// URLs with labels
+ //
+ LLUrlEntrySLLabel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("invalid wiki url [1]", r,
+ "[secondlife:///app/]",
+ "");
+
+ testRegex("invalid wiki url [2]", r,
+ "[secondlife:///app/",
+ "");
+
+ testRegex("invalid wiki url [3]", r,
+ "[secondlife:///app/ Label",
+ "");
+
+ testRegex("agent slurl with label (spaces)", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]");
+
+ testRegex("agent slurl with label (tabs)", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]");
+
+ testRegex("agent slurl with label", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]");
+
+ testRegex("teleport slurl with label", r,
+ "XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY",
+ "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]");
+ }
+}
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
new file mode 100644
index 0000000000..4dae49db90
--- /dev/null
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -0,0 +1,177 @@
+/**
+ * @file llurlmatch_test.cpp
+ * @author Martin Reddy
+ * @brief Unit tests for LLUrlMatch
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../llurlmatch.h"
+#include "lltut.h"
+
+namespace tut
+{
+ struct LLUrlMatchData
+ {
+ };
+
+ typedef test_group<LLUrlMatchData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLUrlMatch");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the empty() method
+ //
+ LLUrlMatch match;
+ ensure("empty()", match.empty());
+
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", "", "");
+ ensure("! empty()", ! match.empty());
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the getStart() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getStart() == 0", match.getStart(), 0);
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getStart() == 10", match.getStart(), 10);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the getEnd() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getEnd() == 0", match.getEnd(), 0);
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getEnd() == 20", match.getEnd(), 20);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the getUrl() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getUrl() == ''", match.getUrl(), "");
+
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", "", "");
+ ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getLabel() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getLabel() == ''", match.getLabel(), "");
+
+ match.setValues(10, 20, "", "Label", "", "", "", "");
+ ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getTooltip() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getTooltip() == ''", match.getTooltip(), "");
+
+ match.setValues(10, 20, "", "", "Info", "", "", "");
+ ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the getIcon() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getIcon() == ''", match.getIcon(), "");
+
+ match.setValues(10, 20, "", "", "", "Icon", "", "");
+ ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the getMenuName() method
+ //
+ LLUrlMatch match;
+ ensure("getMenuName() empty", match.getMenuName().empty());
+
+ match.setValues(10, 20, "", "", "", "Icon", "xui_file.xml", "");
+ ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure("getMenuName() empty (2)", match.getMenuName().empty());
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the getLocation() method
+ //
+ LLUrlMatch match;
+ ensure("getLocation() empty", match.getLocation().empty());
+
+ match.setValues(10, 20, "", "", "", "Icon", "xui_file.xml", "Paris");
+ ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
+
+ match.setValues(10, 20, "", "", "", "", "", "");
+ ensure("getLocation() empty (2)", match.getLocation().empty());
+ }
+}
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 93ac120302..315baa001d 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -62,7 +62,7 @@ class LLPidLockFile
mSaving(FALSE), mWaiting(FALSE),
mClean(TRUE), mPID(getpid())
{
- mLockName = gDirUtilp->getTempDir() + "/savelock";
+ mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h
index 7bd0f2eebf..b5dbbc53fb 100644
--- a/indra/llwindow/llmousehandler.h
+++ b/indra/llwindow/llmousehandler.h
@@ -45,17 +45,20 @@ class LLMouseHandler
public:
LLMouseHandler() {}
virtual ~LLMouseHandler() {}
+
typedef enum {
SHOW_NEVER,
SHOW_IF_NOT_BLOCKED,
SHOW_ALWAYS,
} EShowToolTip;
+
typedef enum {
CLICK_LEFT,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_DOUBLELEFT
} EClickType;
+
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
@@ -67,8 +70,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) = 0;
- virtual EShowToolTip getShowToolTip() { return SHOW_IF_NOT_BLOCKED; };
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) = 0;
virtual const std::string& getName() const = 0;
virtual void onMouseCaptureLost() = 0;
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index d35e7b40f8..1b867b79c9 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -517,6 +517,14 @@ namespace LLInitParam
}
template<>
+ bool ParamCompare<boost::function<void (void)> >::equals(
+ const boost::function<void (void)> &a,
+ const boost::function<void (void)> &b)
+ {
+ return false;
+ }
+
+ template<>
bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b)
{
return false;
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index a1d0831939..baa782916e 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -1815,7 +1815,13 @@ namespace LLInitParam
bool ParamCompare<boost::function<void (const LLSD &,const LLSD &)> >::equals(
const boost::function<void (const LLSD &,const LLSD &)> &a,
const boost::function<void (const LLSD &,const LLSD &)> &b);
-
+
+ template<>
+ bool ParamCompare<boost::function<void (void)> >::equals(
+ const boost::function<void (void)> &a,
+ const boost::function<void (void)> &b);
+
+
template<>
bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b);
}
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef2..a54ebd5831 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
// http_request string constants
extern const char* URL_REQUEST_GRANTED;
extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
#endif
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 98146d6f2b..3b8bbbe805 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
switch(targetType)
{
case LST_INTEGER:
- //fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
- fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
- // we the entire grid is > 1.25.1
+ fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
break;
case LST_STRING:
fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
chunk->addInteger(mIdentifier->mScopeEntry->mCount);
}
break;
+ case LSCP_TYPE:
+ mReturnType = basetype;
+ break;
case LSCP_EMIT_CIL_ASSEMBLY:
fprintf(fp, "ldarg.0\n");
fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+ // We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+ // here using a call to the ChangeState followed by a short cut return of the current method. To
+ // maintain type safety we need to push an arbitrary variable of the current method's return type
+ // onto the stack before returning. This will be ignored and discarded.
+ print_cil_init_variable(fp, mReturnType);
fprintf(fp, "ret\n");
break;
default:
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af..a667e1eb5b 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ public:
S32 getSize();
LLScriptIdentifier *mIdentifier;
+ LSCRIPTType mReturnType;
};
class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 245fc320d1..96855abea0 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -371,8 +371,7 @@ class LLScriptExecute
{
public:
LLScriptExecute();
- virtual ~LLScriptExecute() {;}
-
+ virtual ~LLScriptExecute() = 0;
virtual S32 getVersion() const = 0;
virtual void deleteAllEvents() = 0;
virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 2fd81210c0..e849fa9a6e 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
#include "lscript_library.h"
#include "lscript_heapruntime.h"
#include "lscript_alloc.h"
+#include "llstat.h"
+
// Static
const S32 DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
// HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC;
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC;
LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
{
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
init();
}
+LLScriptExecute::~LLScriptExecute() {}
LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
{
delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
return 4;
}
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
- offset++;
- U8 arg = safe_instruction_bytestream2byte(buffer, offset);
- if (arg >= (U8)gScriptLibrary.mFunctions.size())
+ if (arg >= gScriptLibrary.mFunctions.size())
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
return FALSE;
}
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
// pull out the arguments and the return values
LLScriptLibData *arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
S32 i, number;
- if (gScriptLibrary.mFunctions[arg].mReturnType)
+ if (function.mReturnType)
{
returnvalue = new LLScriptLibData;
}
- if (gScriptLibrary.mFunctions[arg].mArgs)
+ if (function.mArgs)
{
- number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
+ number = (S32)strlen(function.mArgs); //Flawfinder: ignore
arguments = new LLScriptLibData[number];
}
else
@@ -4271,23 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
for (i = number - 1; i >= 0; i--)
{
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
+ lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]);
}
- if (b_print)
- {
- printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
+ // Actually execute the function call
+ function.mExecFunc(returnvalue, arguments, id);
- {
- gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
- }
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+ add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse));
+ add_register_fp(buffer, LREG_SLR, function.mSleepTime);
if (returnvalue)
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
+ returnvalue->mType = char2type(*function.mReturnType);
lscript_push_return_variable(returnvalue, buffer);
}
@@ -4304,71 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
}
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
offset++;
- U16 arg = safe_instruction_bytestream2u16(buffer, offset);
- if (arg >= (U16)gScriptLibrary.mFunctions.size())
+ U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
- return FALSE;
- }
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
-
- // pull out the arguments and the return values
- LLScriptLibData *arguments = NULL;
- LLScriptLibData *returnvalue = NULL;
-
- S32 i, number;
-
- if (gScriptLibrary.mFunctions[arg].mReturnType)
- {
- returnvalue = new LLScriptLibData;
- }
-
- if (gScriptLibrary.mFunctions[arg].mArgs)
- {
- number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
- arguments = new LLScriptLibData[number];
- }
- else
- {
- number = 0;
- }
-
- for (i = number - 1; i >= 0; i--)
- {
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
- }
-
- if (b_print)
- {
- printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
-
- {
- gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
+ printf("[0x%X]\tCALLLIB ", offset);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+ return run_calllib_common(buffer, offset, id, arg);
+}
- if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+ offset++;
+ U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
- lscript_push_return_variable(returnvalue, buffer);
+ printf("[0x%X]\tCALLLIB ", (offset-1));
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
-
- delete [] arguments;
- delete returnvalue;
-
- // reset the BP after calling the library files
- S32 bp = lscript_pop_int(buffer);
- set_bp(buffer, bp);
-
- // pop off the spot for the instruction pointer
- lscript_poparg(buffer, 4);
- return FALSE;
+ return run_calllib_common(buffer, offset, id, arg);
}
diff --git a/indra/media_plugins/base/media_plugin_base.exp b/indra/media_plugins/base/media_plugin_base.exp
index d7a945a1c5..d8c7bb712a 100644
--- a/indra/media_plugins/base/media_plugin_base.exp
+++ b/indra/media_plugins/base/media_plugin_base.exp
@@ -1 +1,2 @@
-_LLPluginInitEntryPoint \ No newline at end of file
+_LLPluginInitEntryPoint
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3f8b8688d2..2faa9b1df1 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -64,7 +64,6 @@ include_directories(
set(viewer_SOURCE_FILES
llaccordionctrltab.cpp
llaccordionctrl.cpp
- llactiveimwindow.cpp
llagent.cpp
llagentlistener.cpp
llagentaccess.cpp
@@ -74,6 +73,7 @@ set(viewer_SOURCE_FILES
llagentui.cpp
llagentwearables.cpp
llanimstatelabels.cpp
+ llappearancemgr.cpp
llappviewer.cpp
llappviewerlistener.cpp
llassetuploadresponders.cpp
@@ -181,7 +181,6 @@ set(viewer_SOURCE_FILES
llfloaterlandholdings.cpp
llfloatermap.cpp
llfloatermemleak.cpp
- llfloatermute.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
@@ -198,6 +197,7 @@ set(viewer_SOURCE_FILES
llfloatersettingsdebug.cpp
llfloatersnapshot.cpp
llfloatertelehub.cpp
+ llfloatertestinspectors.cpp
llfloatertestlistview.cpp
llfloatertools.cpp
llfloatertopobjects.cpp
@@ -222,7 +222,6 @@ set(viewer_SOURCE_FILES
llgroupmgr.cpp
llgroupnotify.cpp
llhomelocationresponder.cpp
- llhoverview.cpp
llhudeffectbeam.cpp
llhudeffect.cpp
llhudeffectlookat.cpp
@@ -288,6 +287,7 @@ set(viewer_SOURCE_FILES
llpanelavatar.cpp
llpanelavatarrow.cpp
llpanelavatartag.cpp
+ llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp
llpaneldirbrowser.cpp
@@ -351,6 +351,8 @@ set(viewer_SOURCE_FILES
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llscreenchannel.cpp
+ llsearchcombobox.cpp
+ llsearchhistory.cpp
llselectmgr.cpp
llsidetray.cpp
llsidetraypanelcontainer.cpp
@@ -522,7 +524,6 @@ set(viewer_HEADER_FILES
ViewerInstall.cmake
llaccordionctrltab.h
llaccordionctrl.h
- llactiveimwindow.h
llagent.h
llagentlistener.h
llagentaccess.h
@@ -538,6 +539,7 @@ set(viewer_HEADER_FILES
llassetuploadresponders.h
llassetuploadqueue.h
llaudiosourcevo.h
+ llappearancemgr.h
llavataractions.h
llavatariconctrl.h
llavatarlist.h
@@ -642,7 +644,6 @@ set(viewer_HEADER_FILES
llfloaterlandholdings.h
llfloatermap.h
llfloatermemleak.h
- llfloatermute.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloateropenobject.h
@@ -659,6 +660,7 @@ set(viewer_HEADER_FILES
llfloatersettingsdebug.h
llfloatersnapshot.h
llfloatertelehub.h
+ llfloatertestinspectors.h
llfloatertestlistview.h
llfloatertools.h
llfloatertopobjects.h
@@ -683,7 +685,6 @@ set(viewer_HEADER_FILES
llgroupmgr.h
llgroupnotify.h
llhomelocationresponder.h
- llhoverview.h
llhudeffect.h
llhudeffectbeam.h
llhudeffectlookat.h
@@ -747,6 +748,7 @@ set(viewer_HEADER_FILES
llpanelavatar.h
llpanelavatarrow.h
llpanelavatartag.h
+ llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h
llpaneldirbrowser.h
@@ -812,6 +814,8 @@ set(viewer_HEADER_FILES
llrootview.h
llscreenchannel.h
llsavedsettingsglue.h
+ llsearchcombobox.h
+ llsearchhistory.h
llselectmgr.h
llsidetray.h
llsidetraypanelcontainer.h
@@ -1607,6 +1611,7 @@ set(test_libs
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(llcapabilitylistener
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 28853ba032..0e685c818a 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -2,6 +2,6 @@
CFBundleName = "Second Life";
-CFBundleShortVersionString = "Second Life version 2.0.0.2425";
-CFBundleGetInfoString = "Second Life version 2.0.0.2425, Copyright 2004-2009 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.2639";
+CFBundleGetInfoString = "Second Life version 2.0.0.2639, Copyright 2004-2009 Linden Research, Inc.";
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index c0a33feaec..0c1d6ea105 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
- <string>2.0.0.2425</string>
+ <string>2.0.0.2639</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 09ebb47fd0..498d8b2e3b 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -804,28 +804,6 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>BuildBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>BuildBtnEnabled</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>BuildFeathering</key>
<map>
<key>Comment</key>
@@ -1728,7 +1706,18 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>DebugStatModeFPS</key>
+ <key>DebugShowXUINames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show tooltips with XUI path to widget</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DebugStatModeFPS</key>
<map>
<key>Comment</key>
<string>Mode of stat in Statistics floater</string>
@@ -2784,17 +2773,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>FirstPersonBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>FirstRunThisInstall</key>
<map>
<key>Comment</key>
@@ -2966,28 +2944,6 @@
<integer>0</integer>
</array>
</map>
- <key>FlyBtnEnabled</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FlyBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>FlycamAbsolute</key>
<map>
<key>Comment</key>
@@ -3697,6 +3653,17 @@
<key>Value</key>
<real>0.0</real>
</map>
+ <key>InspectorFadeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade out timing for inspectors</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <string>0.1</string>
+ </map>
<key>InstallLanguage</key>
<map>
<key>Comment</key>
@@ -4600,17 +4567,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>MouselookBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>MuteAmbient</key>
<map>
<key>Comment</key>
@@ -6563,17 +6519,6 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>RunBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>RunMultipleThreads</key>
<map>
<key>Comment</key>
@@ -6952,12 +6897,12 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>ShowPGSearchAll</key>
+ <key>ShowCameraAndMoveControls</key>
<map>
<key>Comment</key>
- <string>Show/Hide Navigation Bar Favorites Panel</string>
+ <string>Show/Hide Camera and Move controls in the bottom tray</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6968,7 +6913,7 @@
<key>ShowNavbarFavoritesPanel</key>
<map>
<key>Comment</key>
- <string>Show/Hide Navigation Bar Navigation Panel</string>
+ <string>Show/Hide Navigation Bar Favorites Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6979,6 +6924,17 @@
<key>ShowNavbarNavigationPanel</key>
<map>
<key>Comment</key>
+ <string>Show/Hide Navigation Bar Navigation Panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowPGSearchAll</key>
+ <map>
+ <key>Comment</key>
<string>Display results of search All that are flagged as PG</string>
<key>Persist</key>
<integer>1</integer>
@@ -7386,28 +7342,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowXUINames</key>
- <map>
- <key>Comment</key>
- <string>Display XUI Names as Tooltips</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>SitBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>SkinCurrent</key>
<map>
<key>Comment</key>
@@ -7768,17 +7702,6 @@
<key>Value</key>
<integer>2</integer>
</map>
- <key>ThirdPersonBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>ThrottleBandwidthKBPS</key>
<map>
<key>Comment</key>
@@ -7812,7 +7735,18 @@
<key>Value</key>
<real>0.2</real>
</map>
- <key>ToolboxAutoMove</key>
+ <key>ToolTipVisibleTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade tooltip after mouse is idle for this long</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+ <key>ToolboxAutoMove</key>
<map>
<key>Comment</key>
<string>[NOT USED]</string>
diff --git a/indra/newview/fonts/DejaVuSans-Bold.ttf b/indra/newview/fonts/DejaVuSans-Bold.ttf
new file mode 100644
index 0000000000..ec1a2ebaf2
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-Bold.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
new file mode 100644
index 0000000000..1a5576460d
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf
new file mode 100644
index 0000000000..becc549927
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-Oblique.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf
new file mode 100644
index 0000000000..c1b19d8705
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf
index 19d188832b..6bc854ddae 100644
--- a/indra/newview/fonts/DejaVuSansMono.ttf
+++ b/indra/newview/fonts/DejaVuSansMono.ttf
Binary files differ
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index a4692dd38b..ab9db303b5 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -48,7 +48,6 @@
#include "llfloaterdirectory.h"
#include "llfloaterland.h"
-#include "llfloatermute.h"
#include "llfloatersnapshot.h"
#include "llfloatertools.h"
#include "llfloaterworldmap.h"
@@ -799,12 +798,10 @@ void LLAgent::setFlying(BOOL fly)
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT);
}
setControlFlags(AGENT_CONTROL_FLY);
- gSavedSettings.setBOOL("FlyBtnState", TRUE);
}
else
{
clearControlFlags(AGENT_CONTROL_FLY);
- gSavedSettings.setBOOL("FlyBtnState", FALSE);
}
@@ -4002,11 +3999,6 @@ void LLAgent::changeCameraToMouselook(BOOL animate)
LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", TRUE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
if (mAvatarObject.notNull())
{
mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE );
@@ -4102,11 +4094,6 @@ void LLAgent::changeCameraToFollow(BOOL animate)
mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
// unpause avatar animation
mPauseRequest = NULL;
@@ -4153,11 +4140,6 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
LLVector3 at_axis;
// unpause avatar animation
@@ -4235,11 +4217,6 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
if (camera_animate)
{
startCameraAnimation();
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 0f735282cb..c4e01808f7 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -45,6 +45,7 @@
#include "llwearable.h"
#include "llwearablelist.h"
#include "llgesturemgr.h"
+#include "llappearancemgr.h"
#include <boost/scoped_ptr.hpp>
@@ -76,11 +77,9 @@ public:
initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
protected:
- void processInitialWearables();
+ void processWearablesMessage();
};
-
-
LLAgentWearables gAgentWearables;
BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE;
@@ -312,7 +311,15 @@ void LLAgentWearables::sendAgentWearablesUpdate()
if (wearable)
{
//llinfos << "Sending wearable " << wearable->getName() << llendl;
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, wearable->getItemID());
+ LLUUID item_id = wearable->getItemID();
+ const LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item && item->getIsLinkType())
+ {
+ // Get the itemID that this item points to. i.e. make sure
+ // we are storing baseitems, not their links, in the database.
+ item_id = item->getLinkedUUID();
+ }
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
}
else
{
@@ -737,7 +744,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
gAgentWearables.mItemsAwaitingWearableUpdate.clear();
for (S32 i=0; i < num_wearables; i++)
{
- // Parse initial werables data from message system
+ // Parse initial wearables data from message system
U8 type_u8 = 0;
gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i);
if (type_u8 >= WT_COUNT)
@@ -1195,7 +1202,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
if (!item) continue;
LLPointer<LLInventoryCallback> cb = NULL;
link_inventory_item(gAgent.getID(),
- item->getUUID(),
+ item->getLinkedUUID(),
folder_id,
item->getName(),
LLAssetType::AT_LINK,
@@ -1226,7 +1233,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
LLPointer<LLInventoryCallback> cb = NULL;
link_inventory_item(gAgent.getID(),
- item->getUUID(),
+ item->getLinkedUUID(),
folder_id,
item->getName(),
LLAssetType::AT_LINK,
@@ -1781,6 +1788,57 @@ void LLAgentWearables::userRemoveAllAttachments(void* userdata)
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
+void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array)
+{
+ // Build a compound message to send all the objects that need to be rezzed.
+ S32 obj_count = obj_item_array.count();
+
+ // Limit number of packets to send
+ const S32 MAX_PACKETS_TO_SEND = 10;
+ const S32 OBJECTS_PER_PACKET = 4;
+ const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
+ if( obj_count > MAX_OBJECTS_TO_SEND )
+ {
+ obj_count = MAX_OBJECTS_TO_SEND;
+ }
+
+ // Create an id to keep the parts of the compound message together
+ LLUUID compound_msg_id;
+ compound_msg_id.generate();
+ LLMessageSystem* msg = gMessageSystem;
+
+ for(S32 i = 0; i < obj_count; ++i)
+ {
+ if( 0 == (i % OBJECTS_PER_PACKET) )
+ {
+ // Start a new message chunk
+ msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_HeaderData);
+ msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
+ msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
+ msg->addBOOLFast(_PREHASH_FirstDetachAll, true );
+ }
+
+ const LLInventoryItem* item = obj_item_array.get(i).get();
+ msg->nextBlockFast(_PREHASH_ObjectData );
+ msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
+ msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
+ pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
+ msg->addStringFast(_PREHASH_Name, item->getName());
+ msg->addStringFast(_PREHASH_Description, item->getDescription());
+
+ if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
+ {
+ // End of message chunk
+ msg->sendReliable( gAgent.getRegion()->getHost() );
+ }
+ }
+}
+
void LLAgentWearables::checkWearablesLoaded() const
{
#ifdef SHOW_ASSERT
@@ -1812,69 +1870,29 @@ void LLAgentWearables::updateServer()
void LLInitialWearablesFetch::done()
{
- // Get the complete information on the items in the library,
- // and set up an observer that will wait for that to happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
+ // No longer need this observer hanging around.
+ gInventory.removeObserver(this);
+ // Fetch the wearable items from the Current Outfit Folder
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable);
- S32 count = item_array.count();
- mCOFInitialWearables.reserve(count);
+ gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH, is_wearable);
- for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- const LLViewerInventoryItem *item = (*iter).get();
- // We're only concerned with linked items in the COF. Ignore
- // any non-link items or links to folders.
- if (item->getActualType() != LLAssetType::AT_LINK)
- {
- continue;
- }
- EWearableType type = (EWearableType) (item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
- // MULTI-WEARABLE: update
- InitialWearableData wearable_data(type, 0, item->getUUID(), item->getAssetUUID());
- mCOFInitialWearables.push_back(wearable_data);
+ if (wearable_array.count() > 0)
+ {
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+ }
+ else
+ {
+ processWearablesMessage();
}
-
- gInventory.removeObserver(this);
- processInitialWearables();
delete this;
}
-// This will either grab the contents of the Current Outfit Folder if they exist,
-// or use the old-style initial agent wearables message.
-void LLInitialWearablesFetch::processInitialWearables()
+void LLInitialWearablesFetch::processWearablesMessage()
{
-#ifdef USE_CURRENT_OUTFIT_FOLDER
- if (!mCOFInitialWearables.empty())
- {
- for (U8 i = 0; i < mCOFInitialWearables.size(); ++i)
- {
- // Fetch the wearables in the current outfit folder
- InitialWearableData *wearable_data = new InitialWearableData(mCOFInitialWearables[i]); // This will be deleted in the callback.
- if (wearable_data->mAssetID.notNull())
- {
- LLWearableList::instance().getAsset(wearable_data->mAssetID,
- LLStringUtil::null,
- LLWearableDictionary::getAssetType(wearable_data->mType),
- LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data));
- }
- else
- {
- llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
- << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
- }
- }
- }
- else
-#endif
if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
{
LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
@@ -1882,7 +1900,7 @@ void LLInitialWearablesFetch::processInitialWearables()
{
// Populate the current outfit folder with links to the wearables passed in the message
InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback.
-
+
if (wearable_data->mAssetID.notNull())
{
#ifdef USE_CURRENT_OUTFIT_FOLDER
@@ -1899,7 +1917,7 @@ void LLInitialWearablesFetch::processInitialWearables()
else
{
llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
- << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
+ << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
}
}
}
@@ -1908,3 +1926,5 @@ void LLInitialWearablesFetch::processInitialWearables()
LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
}
}
+
+
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index b415ef9eb3..cb4de555d5 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -182,6 +182,7 @@ public:
static void userRemoveWearable(void* userdata); // userdata is EWearableType
static void userRemoveAllClothes(void* userdata); // userdata is NULL
static void userRemoveAllAttachments(void* userdata); // userdata is NULL
+ static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
BOOL itemUpdatePending(const LLUUID& item_id) const;
U32 itemUpdatePendingCount() const;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
new file mode 100644
index 0000000000..6c234f23fe
--- /dev/null
+++ b/indra/newview/llappearancemgr.cpp
@@ -0,0 +1,793 @@
+/**
+ * @file llappearancemgr.cpp
+ * @brief Manager for initiating appearance changes on the viewer
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llappearancemgr.h"
+#include "llinventorymodel.h"
+#include "llnotifications.h"
+#include "llgesturemgr.h"
+#include "llinventorybridge.h"
+#include "llwearablelist.h"
+#include "llagentwearables.h"
+#include "llagent.h"
+#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llviewerregion.h"
+#include "llfloatercustomize.h"
+
+class LLWearInventoryCategoryCallback : public LLInventoryCallback
+{
+public:
+ LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
+ {
+ mCatID = cat_id;
+ mAppend = append;
+ }
+ void fire(const LLUUID& item_id)
+ {
+ /*
+ * Do nothing. We only care about the destructor
+ *
+ * The reason for this is that this callback is used in a hack where the
+ * same callback is given to dozens of items, and the destructor is called
+ * after the last item has fired the event and dereferenced it -- if all
+ * the events actually fire!
+ */
+ }
+
+protected:
+ ~LLWearInventoryCategoryCallback()
+ {
+ // Is the destructor called by ordinary dereference, or because the app's shutting down?
+ // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
+ if( LLInventoryCallbackManager::is_instantiated() )
+ {
+ LLAppearanceManager::wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
+ }
+ else
+ {
+ llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
+ }
+ }
+
+private:
+ LLUUID mCatID;
+ bool mAppend;
+};
+
+class LLOutfitObserver : public LLInventoryFetchObserver
+{
+public:
+ LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
+ mCatID(cat_id),
+ mCopyItems(copy_items),
+ mAppend(append)
+ {}
+ ~LLOutfitObserver() {}
+ virtual void done(); //public
+
+protected:
+ LLUUID mCatID;
+ bool mCopyItems;
+ bool mAppend;
+};
+
+void LLOutfitObserver::done()
+{
+ // We now have an outfit ready to be copied to agent inventory. Do
+ // it, and wear that outfit normally.
+ if(mCopyItems)
+ {
+ LLInventoryCategory* cat = gInventory.getCategory(mCatID);
+ std::string name;
+ if(!cat)
+ {
+ // should never happen.
+ name = "New Outfit";
+ }
+ else
+ {
+ name = cat->getName();
+ }
+ LLViewerInventoryItem* item = NULL;
+ item_ref_t::iterator it = mComplete.begin();
+ item_ref_t::iterator end = mComplete.end();
+ LLUUID pid;
+ for(; it < end; ++it)
+ {
+ item = (LLViewerInventoryItem*)gInventory.getItem(*it);
+ if(item)
+ {
+ if(LLInventoryType::IT_GESTURE == item->getInventoryType())
+ {
+ pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
+ }
+ else
+ {
+ pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ }
+ break;
+ }
+ }
+ if(pid.isNull())
+ {
+ pid = gInventory.getRootFolderID();
+ }
+
+ LLUUID cat_id = gInventory.createNewCategory(
+ pid,
+ LLAssetType::AT_NONE,
+ name);
+ mCatID = cat_id;
+ LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
+ it = mComplete.begin();
+ for(; it < end; ++it)
+ {
+ item = (LLViewerInventoryItem*)gInventory.getItem(*it);
+ if(item)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ cat_id,
+ std::string(),
+ cb);
+ }
+ }
+ }
+ else
+ {
+ // Wear the inventory category.
+ LLAppearanceManager::wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
+ }
+}
+
+class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
+ ~LLOutfitFetch() {}
+ virtual void done();
+protected:
+ bool mCopyItems;
+ bool mAppend;
+};
+
+void LLOutfitFetch::done()
+{
+ // What we do here is get the complete information on the items in
+ // the library, and set up an observer that will wait for that to
+ // happen.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(mCompleteFolders.front(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ S32 count = item_array.count();
+ if(!count)
+ {
+ llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+ << llendl;
+ //dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+
+ LLOutfitObserver* outfit_observer = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
+ LLInventoryFetchObserver::item_ref_t ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(item_array.get(i)->getUUID());
+ }
+
+ // clean up, and remove this as an observer since the call to the
+ // outfit could notify observers and throw us into an infinite
+ // loop.
+ //dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+
+ // increment busy count and either tell the inventory to check &
+ // call done, or add this object to the inventory for observation.
+ //inc_busy_count();
+
+ // do the fetch
+ outfit_observer->fetchItems(ids);
+ if(outfit_observer->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit_observer->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit_observer);
+ }
+}
+
+class LLUpdateAppearanceOnCount: public LLInventoryCallback
+{
+public:
+ LLUpdateAppearanceOnCount(S32 count):
+ mCount(count)
+ {
+ }
+
+ virtual ~LLUpdateAppearanceOnCount()
+ {
+ }
+
+ /* virtual */ void fire(const LLUUID& inv_item)
+ {
+ mCount--;
+ if (mCount==0)
+ {
+ done();
+ }
+ }
+
+ void done()
+ {
+ LLAppearanceManager::updateAppearanceFromCOF();
+ }
+private:
+ S32 mCount;
+};
+
+struct LLFoundData
+{
+ LLFoundData(const LLUUID& item_id,
+ const LLUUID& asset_id,
+ const std::string& name,
+ LLAssetType::EType asset_type) :
+ mItemID(item_id),
+ mAssetID(asset_id),
+ mName(name),
+ mAssetType(asset_type),
+ mWearable( NULL ) {}
+
+ LLUUID mItemID;
+ LLUUID mAssetID;
+ std::string mName;
+ LLAssetType::EType mAssetType;
+ LLWearable* mWearable;
+};
+
+
+struct LLWearableHoldingPattern
+{
+ LLWearableHoldingPattern() : mResolved(0) {}
+ ~LLWearableHoldingPattern()
+ {
+ for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
+ mFoundList.clear();
+ }
+ typedef std::list<LLFoundData*> found_list_t;
+ found_list_t mFoundList;
+ S32 mResolved;
+ bool append;
+};
+
+
+void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src)
+{
+ LLInventoryModel::item_array_t new_dst;
+ std::set<LLUUID> mark_inventory;
+ std::set<LLUUID> mark_asset;
+
+ S32 inventory_dups = 0;
+ S32 asset_dups = 0;
+
+ for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin();
+ src_pos != src.end();
+ ++src_pos)
+ {
+ LLUUID src_item_id = (*src_pos)->getLinkedUUID();
+ mark_inventory.insert(src_item_id);
+ LLUUID src_asset_id = (*src_pos)->getAssetUUID();
+ mark_asset.insert(src_asset_id);
+ }
+
+ for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin();
+ dst_pos != dst.end();
+ ++dst_pos)
+ {
+ LLUUID dst_item_id = (*dst_pos)->getLinkedUUID();
+
+ if (mark_inventory.find(dst_item_id) == mark_inventory.end())
+ {
+ }
+ else
+ {
+ inventory_dups++;
+ }
+
+ LLUUID dst_asset_id = (*dst_pos)->getAssetUUID();
+
+ if (mark_asset.find(dst_asset_id) == mark_asset.end())
+ {
+ // Item is not already present in COF.
+ new_dst.put(*dst_pos);
+ mark_asset.insert(dst_item_id);
+ }
+ else
+ {
+ asset_dups++;
+ }
+ }
+ llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count()
+ << " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl;
+
+ dst = new_dst;
+}
+
+
+/* static */ LLUUID LLAppearanceManager::getCOF()
+{
+ return gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+}
+
+// Update appearance from outfit folder.
+/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links)
+{
+ if (!proceed)
+ return;
+
+ updateCOFFromOutfit(category, append, follow_folder_links);
+}
+
+// Update COF contents from outfit folder.
+/* static */ void LLAppearanceManager::updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links)
+{
+ // BAP consolidate into one "get all 3 types of descendents" function, use both places.
+ LLInventoryModel::item_array_t wear_items;
+ LLInventoryModel::item_array_t obj_items;
+ LLInventoryModel::item_array_t gest_items;
+ getUserDescendents(category, wear_items, obj_items, gest_items, follow_folder_links);
+
+ // Find all the wearables that are in the category's subtree.
+ lldebugs << "updateCOFFromOutfit()" << llendl;
+ if( !wear_items.count() && !obj_items.count() && !gest_items.count())
+ {
+ LLNotifications::instance().add("CouldNotPutOnOutfit");
+ return;
+ }
+
+ const LLUUID &current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ // Processes that take time should show the busy cursor
+ //inc_busy_count();
+
+ LLInventoryModel::cat_array_t cof_cats;
+ LLInventoryModel::item_array_t cof_items;
+ gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ if (append)
+ {
+ // Remove duplicates
+ removeDuplicateItems(wear_items, cof_items);
+ removeDuplicateItems(obj_items, cof_items);
+ removeDuplicateItems(gest_items, cof_items);
+ }
+
+
+ if (wear_items.count() > 0 || obj_items.count() > 0)
+ {
+ if (!append)
+ {
+ // Remove all current outfit folder links if we're now replacing the contents.
+ for (S32 i = 0; i < cof_items.count(); ++i)
+ {
+ gInventory.purgeObject(cof_items.get(i)->getUUID());
+ }
+ }
+ }
+
+ // BAP should we just link all contents, rather than restricting to these 3 types?
+
+ S32 total_links = gest_items.count() + wear_items.count() + obj_items.count();
+ LLPointer<LLUpdateAppearanceOnCount> link_waiter = new LLUpdateAppearanceOnCount(total_links);
+
+ // Link all gestures in this folder
+ if (gest_items.count() > 0)
+ {
+ llinfos << "Linking " << gest_items.count() << " gestures" << llendl;
+ for (S32 i = 0; i < gest_items.count(); ++i)
+ {
+ const LLInventoryItem* gest_item = gest_items.get(i).get();
+ link_inventory_item(gAgent.getID(), gest_item->getLinkedUUID(), current_outfit_id,
+ gest_item->getName(),
+ LLAssetType::AT_LINK, link_waiter);
+ }
+ }
+
+ // Link all wearables
+ if(wear_items.count() > 0)
+ {
+ llinfos << "Linking " << wear_items.count() << " wearables" << llendl;
+ for(S32 i = 0; i < wear_items.count(); ++i)
+ {
+ // Populate the current outfit folder with links to the newly added wearables
+ const LLInventoryItem* wear_item = wear_items.get(i).get();
+ link_inventory_item(gAgent.getID(),
+ wear_item->getLinkedUUID(), // If this item is a link, then we'll use the linked item's UUID.
+ current_outfit_id,
+ wear_item->getName(),
+ LLAssetType::AT_LINK,
+ link_waiter);
+ }
+ }
+
+ // Link all attachments.
+ if( obj_items.count() > 0 )
+ {
+ llinfos << "Linking " << obj_items.count() << " attachments" << llendl;
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ for(S32 i = 0; i < obj_items.count(); ++i)
+ {
+ const LLInventoryItem* obj_item = obj_items.get(i).get();
+ link_inventory_item(gAgent.getID(),
+ obj_item->getLinkedUUID(), // If this item is a link, then we'll use the linked item's UUID.
+ current_outfit_id,
+ obj_item->getName(),
+ LLAssetType::AT_LINK, link_waiter);
+ }
+ }
+ }
+
+ // In the particular case that we're switching to a different outfit,
+ // create a link to the folder that we wore.
+ LLViewerInventoryCategory* catp = gInventory.getCategory(category);
+ if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
+ {
+ link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(),
+ LLAssetType::AT_LINK_FOLDER, LLPointer<LLInventoryCallback>(NULL));
+ }
+}
+
+/* static */
+void LLAppearanceManager::onWearableAssetFetch(LLWearable* wearable, void* data)
+{
+ LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
+ bool append = holder->append;
+
+ if(wearable)
+ {
+ for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
+ iter != holder->mFoundList.end(); ++iter)
+ {
+ LLFoundData* data = *iter;
+ if(wearable->getAssetID() == data->mAssetID)
+ {
+ data->mWearable = wearable;
+ break;
+ }
+ }
+ }
+ holder->mResolved += 1;
+ if(holder->mResolved >= (S32)holder->mFoundList.size())
+ {
+ LLAppearanceManager::updateAgentWearables(holder, append);
+ }
+}
+
+/* static */
+void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
+{
+ lldebugs << "updateAgentWearables()" << llendl;
+ LLInventoryItem::item_array_t items;
+ LLDynamicArray< LLWearable* > wearables;
+
+ // For each wearable type, find the first instance in the category
+ // that we recursed through.
+ for( S32 i = 0; i < WT_COUNT; i++ )
+ {
+ for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
+ iter != holder->mFoundList.end(); ++iter)
+ {
+ LLFoundData* data = *iter;
+ LLWearable* wearable = data->mWearable;
+ if( wearable && ((S32)wearable->getType() == i) )
+ {
+ LLViewerInventoryItem* item;
+ item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
+ if( item && (item->getAssetUUID() == wearable->getAssetID()) )
+ {
+ items.put(item);
+ wearables.put(wearable);
+ }
+ break;
+ }
+ }
+ }
+
+ if(wearables.count() > 0)
+ {
+ gAgentWearables.setWearableOutfit(items, wearables, !append);
+ gInventory.notifyObservers();
+ }
+
+ delete holder;
+
+// dec_busy_count();
+}
+
+/* static */ void LLAppearanceManager::updateAppearanceFromCOF()
+{
+ bool follow_folder_links = true;
+ LLUUID current_outfit_id = getCOF();
+
+ // Find all the wearables that are in the COF's subtree.
+ lldebugs << "LLAppearanceManager::updateFromCOF()" << llendl;
+ LLInventoryModel::item_array_t wear_items;
+ LLInventoryModel::item_array_t obj_items;
+ LLInventoryModel::item_array_t gest_items;
+ getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
+
+ if( !wear_items.count() && !obj_items.count() && !gest_items.count())
+ {
+ LLNotifications::instance().add("CouldNotPutOnOutfit");
+ return;
+ }
+
+ // Processes that take time should show the busy cursor
+ //inc_busy_count(); // BAP this is currently a no-op in llinventorybridge.cpp - do we need it?
+
+ // Activate all gestures in this folder
+ if (gest_items.count() > 0)
+ {
+ llinfos << "Activating " << gest_items.count() << " gestures" << llendl;
+
+ LLGestureManager::instance().activateGestures(gest_items);
+
+ // Update the inventory item labels to reflect the fact
+ // they are active.
+ LLViewerInventoryCategory* catp = gInventory.getCategory(current_outfit_id);
+ if (catp)
+ {
+ gInventory.updateCategory(catp);
+ gInventory.notifyObservers();
+ }
+ }
+
+ if(wear_items.count() > 0)
+ {
+ // Note: can't do normal iteration, because if all the
+ // wearables can be resolved immediately, then the
+ // callback will be called (and this object deleted)
+ // before the final getNextData().
+ LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
+ LLFoundData* found;
+ LLDynamicArray<LLFoundData*> found_container;
+ for(S32 i = 0; i < wear_items.count(); ++i)
+ {
+ found = new LLFoundData(wear_items.get(i)->getUUID(),
+ wear_items.get(i)->getAssetUUID(),
+ wear_items.get(i)->getName(),
+ wear_items.get(i)->getType());
+ holder->mFoundList.push_front(found);
+ found_container.put(found);
+ }
+ for(S32 i = 0; i < wear_items.count(); ++i)
+ {
+ holder->append = false;
+ found = found_container.get(i);
+
+ // Fetch the wearables about to be worn.
+ LLWearableList::instance().getAsset(found->mAssetID,
+ found->mName,
+ found->mAssetType,
+ LLAppearanceManager::onWearableAssetFetch,
+ (void*)holder);
+ }
+ }
+
+
+ //If the folder doesn't contain only gestures, take off all attachments.
+ if (!(wear_items.count() == 0 && obj_items.count() == 0 && gest_items.count() > 0) )
+ {
+ LLAgentWearables::userRemoveAllAttachments(NULL);
+ }
+
+ if( obj_items.count() > 0 )
+ {
+ // We've found some attachments. Add these.
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ LLAgentWearables::userAttachMultipleAttachments(obj_items);
+ }
+ }
+}
+
+/* static */ void LLAppearanceManager::getUserDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& wear_items,
+ LLInventoryModel::item_array_t& obj_items,
+ LLInventoryModel::item_array_t& gest_items,
+ bool follow_folder_links)
+{
+ LLInventoryModel::cat_array_t wear_cats;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(category,
+ wear_cats,
+ wear_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_wearable,
+ follow_folder_links);
+
+ LLInventoryModel::cat_array_t obj_cats;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ gInventory.collectDescendentsIf(category,
+ obj_cats,
+ obj_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_object,
+ follow_folder_links);
+
+ // Find all gestures in this folder
+ LLInventoryModel::cat_array_t gest_cats;
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+ gInventory.collectDescendentsIf(category,
+ gest_cats,
+ gest_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_gesture,
+ follow_folder_links);
+}
+
+void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
+{
+ if(!category) return;
+
+ lldebugs << "wearInventoryCategory( " << category->getName()
+ << " )" << llendl;
+ // What we do here is get the complete information on the items in
+ // the inventory, and set up an observer that will wait for that to
+ // happen.
+ LLOutfitFetch* outfit_fetcher = new LLOutfitFetch(copy, append);
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(category->getUUID());
+ outfit_fetcher->fetchDescendents(folders);
+ //inc_busy_count();
+ if(outfit_fetcher->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit_fetcher->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit_fetcher);
+ }
+}
+
+// *NOTE: hack to get from avatar inventory to avatar
+/* static */
+void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* category, bool append )
+{
+ // Avoid unintentionally overwriting old wearables. We have to do
+ // this up front to avoid having to deal with the case of multiple
+ // wearables being dirty.
+ if(!category) return;
+ lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName()
+ << " )" << llendl;
+
+ bool follow_folder_links = (category->getPreferredType() == LLAssetType::AT_CURRENT_OUTFIT || category->getPreferredType() == LLAssetType::AT_OUTFIT );
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->askToSaveIfDirty(boost::bind(LLAppearanceManager::changeOutfit, _1, category->getUUID(), append, follow_folder_links));
+ }
+ else
+ {
+ LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append, follow_folder_links );
+ }
+}
+
+/* static */
+void LLAppearanceManager::wearOutfitByName(const std::string& name)
+{
+ llinfos << "Wearing category " << name << llendl;
+ //inc_busy_count();
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLNameCategoryCollector has_name(name);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ has_name);
+ bool copy_items = false;
+ LLInventoryCategory* cat = NULL;
+ if (cat_array.count() > 0)
+ {
+ // Just wear the first one that matches
+ cat = cat_array.get(0);
+ }
+ else
+ {
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ has_name);
+ if(cat_array.count() > 0)
+ {
+ cat = cat_array.get(0);
+ copy_items = true;
+ }
+ }
+
+ if(cat)
+ {
+ LLAppearanceManager::wearInventoryCategory(cat, copy_items, false);
+ }
+ else
+ {
+ llwarns << "Couldn't find outfit " <<name<< " in wearOutfitByName()"
+ << llendl;
+ }
+
+ //dec_busy_count();
+}
+
+void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
+{
+ // BAP add check for already in COF.
+ LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
+ link_inventory_item( gAgent.getID(),
+ item->getLinkedUUID(),
+ getCOF(),
+ item->getName(),
+ LLAssetType::AT_LINK,
+ cb);
+}
+
+void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update )
+{
+ // BAP add check for already in COF.
+ LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
+ link_inventory_item( gAgent.getID(),
+ cat->getLinkedUUID(),
+ getCOF(),
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+}
+
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
new file mode 100644
index 0000000000..89b95833d7
--- /dev/null
+++ b/indra/newview/llappearancemgr.h
@@ -0,0 +1,70 @@
+/**
+ * @file llappearancemgr.h
+ * @brief Manager for initiating appearance changes on the viewer
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAPPEARANCEMGR_H
+#define LL_LLAPPEARANCEMGR_H
+
+#include "llsingleton.h"
+#include "llinventorymodel.h"
+
+class LLWearable;
+struct LLWearableHoldingPattern;
+
+class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
+{
+public:
+ static void updateAppearanceFromCOF();
+ static bool needToSaveCOF();
+ static void changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links);
+ static void updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links);
+ static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
+ static void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
+ static void wearOutfitByName(const std::string& name);
+
+ // Add COF link to individual item.
+ static void wearItem(LLInventoryItem* item, bool do_update = true);
+
+ // Add COF link to ensemble folder.
+ static void wearEnsemble(LLInventoryCategory* item, bool do_update = true);
+
+private:
+ static LLUUID getCOF();
+ static void getUserDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& wear_items,
+ LLInventoryModel::item_array_t& obj_items,
+ LLInventoryModel::item_array_t& gest_items,
+ bool follow_folder_links);
+ static void onWearableAssetFetch(LLWearable* wearable, void* data);
+ static void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
+};
+
+#endif
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 93c203cecd..ef1fa98b1f 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -34,8 +34,7 @@
#include "llappviewer.h"
-#include "llprimitive.h"
-
+// Viewer includes
#include "llversionviewer.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
@@ -81,6 +80,10 @@
// Linden library includes
#include "llmemory.h"
+#include "llprimitive.h"
+#include "llurlaction.h"
+#include "llvfsthread.h"
+#include "llvolumemgr.h"
// Third party library includes
#include <boost/bind.hpp>
@@ -132,7 +135,7 @@
#include "lldebugview.h"
#include "llconsole.h"
#include "llcontainerview.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llsdserialize.h"
@@ -412,7 +415,6 @@ static void settings_to_globals()
gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
gMapScale = gSavedSettings.getF32("MapScale");
- LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
}
@@ -689,9 +691,14 @@ bool LLAppViewer::init()
LLTransUtil::parseLanguageStrings("language_settings.xml");
LLWeb::initClass(); // do this after LLUI
- LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
- &LLURLDispatcher::dispatchFromTextEditor,
- &LLURLDispatcher::dispatchFromTextEditor);
+ // Provide the text fields with callbacks for opening Urls
+ LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
+ LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
+ LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal);
+ LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
+
+ // Set the link color for any Urls in text fields
+ LLTextBase::setLinkColor( LLUIColorTable::instance().getColor("HTMLLinkColor") );
// Load translations for tooltips
LLFloater::initClass();
@@ -2339,12 +2346,6 @@ void LLAppViewer::cleanupSavedSettings()
{
gSavedSettings.setBOOL("MouseSun", FALSE);
- gSavedSettings.setBOOL("FlyBtnState", FALSE);
-
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator
gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
@@ -2376,7 +2377,7 @@ void LLAppViewer::cleanupSavedSettings()
}
gSavedSettings.setF32("MapScale", gMapScale );
- gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips);
+ gSavedSettings.setBOOL("ShowHoverTips", gToolTipView->getVisible());
// Some things are cached in LLAgent.
if (gAgent.mInitialized)
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 5f71b6e3f6..4819703e72 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -41,6 +41,7 @@
#include "llagent.h"
#include "llappviewer.h" // for gLastVersionChannel
+#include "llcachename.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
#include "llimview.h" // for gIMMgr
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 05addf3f3a..a8b1ff6c92 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -147,7 +147,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
if (mAvatarId != value.asUUID())
{
LLAvatarPropertiesProcessor::getInstance()->addObserver(value.asUUID(), this);
- LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(value.asUUID(),APT_PROPERTIES);
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(value.asUUID());
mAvatarId = value.asUUID();
// Check if cache already contains image_id for that avatar
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index f557adf6a6..2e64c10bb2 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -41,6 +41,9 @@
#include "llvoiceclient.h"
static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
+static LLDefaultChildRegistry::Register<LLAvatarListTmp> r_tmp("avatar_list_tmp");
+
+static const std::string COMMENT_TEXTBOX = "comment_text";
LLAvatarList::Params::Params()
:
@@ -62,6 +65,9 @@ LLAvatarList::LLAvatarList(const Params& p)
{
setCommitOnSelectionChange(TRUE); // there's no such param in LLScrollListCtrl::Params
+ // display a context menu appropriate for a list of avatar names
+ setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+
// "volume" column
{
LLScrollListColumn::Params col_params;
@@ -220,6 +226,16 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str
#endif
setScrollPos(pos);
+ updateLineHeight();
+ LLRect rect = getRequiredRect();
+
+ LLSD params;
+ params["action"] = "size_changes";
+ params["width"] = rect.getWidth();
+ params["height"] = llmax(rect.getHeight(),20) + 5;
+
+ getParent()->notifyParent(params);
+
return have_names;
}
@@ -289,3 +305,213 @@ void LLAvatarList::updateVolume()
icon_cell->setValue(getVolumeIcon(speaker_id));
}
}
+
+
+
+
+#include "llavatarlistitem.h"
+
+LLAvatarListTmp::Params::Params()
+:
+volume_column_width("volume_column_width", 0)
+, online_go_first("online_go_first", true)
+{
+}
+
+
+
+LLAvatarListTmp::LLAvatarListTmp(const Params& p)
+: LLFlatListView(p)
+, mHaveVolumeColumn(p.volume_column_width > 0)
+, mOnlineGoFirst(p.online_go_first)
+{
+ LLRect item_list_rect = getLocalRect();
+ item_list_rect.stretch( -getBorderWidth());
+
+ LLTextBox::Params text_p;
+ text_p.name(COMMENT_TEXTBOX);
+ text_p.border_visible(false);
+ text_p.rect(item_list_rect);
+ text_p.follows.flags(FOLLOWS_ALL);
+ addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
+}
+
+// virtual
+void LLAvatarListTmp::draw()
+{
+ LLFlatListView::draw();
+ if (mHaveVolumeColumn)
+ {
+ updateVolume();
+ }
+}
+
+std::vector<LLUUID> LLAvatarListTmp::getSelectedIDs()
+{
+ LLUUID selected_id;
+ std::vector<LLUUID> avatar_ids;
+
+ getSelectedUUIDs(avatar_ids);
+
+ return avatar_ids;
+}
+
+void LLAvatarListTmp::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
+{
+ LLAvatarListItem* item = new LLAvatarListItem();
+ item->showStatus(true);
+ item->showInfoBtn(true);
+ item->showSpeakingIndicator(true);
+ item->setName(name);
+ item->setAvatarId(id);
+
+ item->childSetVisible("info_btn", false);
+
+ addItem(item, id, pos);
+
+ setCommentVisible(false);
+}
+
+BOOL LLAvatarListTmp::update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter)
+{
+ BOOL have_names = TRUE;
+
+ // Save selection.
+ std::vector<LLUUID> selected_ids = getSelectedIDs();
+ LLUUID current_id = getSelectedUUID();
+ LLRect pos = getScrolledViewRect();
+
+ std::vector<LLUUID>::const_iterator buddy_it = all_buddies.begin();
+ clear();
+ for(; buddy_it != all_buddies.end(); ++buddy_it)
+ {
+ std::string name;
+ const LLUUID& buddy_id = *buddy_it;
+ have_names &= gCacheName->getFullName(buddy_id, name);
+ if (name_filter != LLStringUtil::null && !findInsensitive(name, name_filter))
+ continue;
+ addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ }
+
+ // Changed item in place, need to request sort and update columns
+ // because we might have changed data in a column on which the user
+ // has already sorted. JC
+ // updateSort(); // TODO: implement sorting
+
+ // re-select items
+ // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
+ selectItemByUUID(current_id);
+
+ scrollToShowRect(pos);
+
+
+ setCommentVisible(false);
+
+ return have_names;
+}
+
+
+const LLUUID LLAvatarListTmp::getCurrentID() const
+{
+ return getSelectedUUID();
+}
+
+void LLAvatarListTmp::setCommentText(const std::string& comment_text)
+{
+ getChild<LLTextBox>(COMMENT_TEXTBOX)->setValue(comment_text);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED SECTION
+//////////////////////////////////////////////////////////////////////////
+
+// virtual overridden
+bool LLAvatarListTmp::removeItemPair(item_pair_t* item_pair)
+{
+ bool removed = LLFlatListView::removeItemPair(item_pair);
+ setCommentVisible(size() == 0);
+ return removed;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+
+// static
+std::string LLAvatarListTmp::getVolumeIcon(const LLUUID& id)
+{
+ //
+ // Determine icon appropriate for the current avatar volume.
+ //
+ // *TODO: remove this in favor of LLOutputMonitorCtrl
+ // when ListView widget is implemented
+ // which is capable of containing arbitrary widgets.
+ //
+ static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams<LLOutputMonitorCtrl>());
+ bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id);
+ F32 power = gVoiceClient->getCurrentPower(id);
+ std::string icon;
+
+ if (muted)
+ {
+ icon = default_monitor_params.image_mute.name;
+ }
+ else if (power == 0.f)
+ {
+ icon = default_monitor_params.image_off.name;
+ }
+ else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+ {
+ S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f));
+ switch(icon_image_idx)
+ {
+ default:
+ case 0:
+ icon = default_monitor_params.image_on.name;
+ break;
+ case 1:
+ icon = default_monitor_params.image_level_1.name;
+ break;
+ case 2:
+ icon = default_monitor_params.image_level_2.name;
+ break;
+ }
+ }
+ else
+ {
+ // overdriven
+ icon = default_monitor_params.image_level_3.name;
+ }
+
+ return icon;
+}
+
+// Update volume column for all list rows.
+void LLAvatarListTmp::updateVolume()
+{
+ // TODO: implement via Listener
+ /*
+ item_list& items = getItemList();
+
+ for (item_list::iterator item_it = items.begin();
+ item_it != items.end();
+ ++item_it)
+ {
+ LLScrollListItem* itemp = (*item_it);
+ LLUUID speaker_id = itemp->getUUID();
+
+ LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME);
+ if (icon_cell)
+ icon_cell->setValue(getVolumeIcon(speaker_id));
+ }
+ */
+}
+
+void LLAvatarListTmp::setCommentVisible(bool visible) const
+{
+ getChildView(COMMENT_TEXTBOX)->setVisible(visible);
+}
+
+// EOF
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 8b419dbb57..639ed83ada 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -75,4 +75,46 @@ private:
bool mOnlineGoFirst;
};
+
+#include "llflatlistview.h"
+
+class LLAvatarListTmp : public LLFlatListView
+{
+ LOG_CLASS(LLAvatarListTmp);
+public:
+ struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
+ {
+ Optional<S32> volume_column_width;
+ Optional<bool> online_go_first;
+ Params();
+ };
+
+ LLAvatarListTmp(const Params&);
+ virtual ~LLAvatarListTmp() {}
+
+ /*virtual*/ void draw();
+
+ BOOL update(const std::vector<LLUUID>& all_buddies,
+ const std::string& name_filter = LLStringUtil::null);
+
+ const LLUUID getCurrentID() const;
+ void setCommentText( const std::string& comment_text);
+
+protected:
+ std::vector<LLUUID> getSelectedIDs();
+ void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM);
+ /*virtual*/ bool removeItemPair(item_pair_t* item_pair);
+
+private:
+ static std::string getVolumeIcon(const LLUUID& id); /// determine volume icon from current avatar volume
+ void updateVolume(); // update volume for all avatars
+ void setCommentVisible(bool visible) const;
+
+ bool mHaveVolumeColumn;
+ bool mOnlineGoFirst;
+
+};
+
+
+
#endif // LL_LLAVATARLIST_H
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 253c2ee9a6..feae8202bc 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -2,9 +2,9 @@
* @file llavatarlistitem.cpp
* @avatar list item source file
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -33,70 +33,39 @@
#include "llviewerprecompiledheaders.h"
-#include "llfloaterreg.h"
#include "llavatarlistitem.h"
-#include "llagent.h"
-
-
-//---------------------------------------------------------------------------------
-LLAvatarListItem::LLAvatarListItem(const Params& p) : LLPanel()
+#include "llfloaterreg.h"
+#include "llagent.h"
+#include "lloutputmonitorctrl.h"
+#include "llavatariconctrl.h"
+#include "llbutton.h"
+
+
+LLAvatarListItem::LLAvatarListItem()
+: LLPanel(),
+ mAvatarIcon(NULL),
+ mAvatarName(NULL),
+ mStatus(NULL),
+ mSpeakingIndicator(NULL),
+ mInfoBtn(NULL)
{
- mNeedsArrange = false;
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
-
- mStatus = NULL;
- mInfo = NULL;
- mProfile = NULL;
- mInspector = NULL;
-
- mAvatar = getChild<LLAvatarIconCtrl>("avatar_icon");
- //mAvatar->setValue(p.avatar_icon);
- mName = getChild<LLTextBox>("name");
- //mName->setText(p.user_name);
-
- init(p);
-
-
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::init(const Params& p)
+BOOL LLAvatarListItem::postBuild()
{
- mLocator = getChild<LLIconCtrl>("locator");
-
- mStatus = getChild<LLTextBox>("user_status");
-
- mInfo = getChild<LLButton>("info_btn");
- mInfo->setVisible(false);
-
- mProfile = getChild<LLButton>("profile_btn");
- mProfile->setVisible(false);
-
- if(!p.buttons.locator)
- {
- mLocator->setVisible(false);
- delete mLocator;
- mLocator = NULL;
- }
+ mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ mAvatarName = getChild<LLTextBox>("avatar_name");
+ mStatus = getChild<LLTextBox>("avatar_status");
- if(!p.buttons.status)
- {
- mStatus->setVisible(false);
- delete mStatus;
- mStatus = NULL;
- }
+ mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
+ mInfoBtn = getChild<LLButton>("info_btn");
- if(!p.buttons.info)
- {
- delete mInfo;
- mInfo = NULL;
- }
- else
- {
- mInfo->setClickedCallback(boost::bind(&LLAvatarListItem::onInfoBtnClick, this));
- }
+ mInfoBtn->setVisible(false);
+ mInfoBtn->setClickedCallback(boost::bind(&LLAvatarListItem::onInfoBtnClick, this));
+/*
if(!p.buttons.profile)
{
delete mProfile;
@@ -125,150 +94,72 @@ void LLAvatarListItem::init(const Params& p)
mInfo->setRect(rect);
}
}
-
+*/
+ return TRUE;
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- if(!mNeedsArrange)
- {
- LLView::reshape(width, height, called_from_parent);
- return;
- }
-
- LLRect rect;
- S32 profile_delta = 0;
- S32 width_delta = getRect().getWidth() - width;
-
- if(!mProfile)
- {
- profile_delta = 30;
- }
- else
- {
- rect.setLeftTopAndSize(mProfile->getRect().mLeft - width_delta, mProfile->getRect().mTop, mProfile->getRect().getWidth(), mProfile->getRect().getHeight());
- mProfile->setRect(rect);
- }
-
- width_delta += profile_delta;
-
- if(mInfo)
- {
- rect.setLeftTopAndSize(mInfo->getRect().mLeft - width_delta, mInfo->getRect().mTop, mInfo->getRect().getWidth(), mInfo->getRect().getHeight());
- mInfo->setRect(rect);
- }
-
- if(mLocator)
- {
- rect.setLeftTopAndSize(mLocator->getRect().mLeft - width_delta, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight());
- mLocator->setRect(rect);
- }
-
- if(mStatus)
- {
- rect.setLeftTopAndSize(mStatus->getRect().mLeft - width_delta, mStatus->getRect().mTop, mStatus->getRect().getWidth(), mStatus->getRect().getHeight());
- mStatus->setRect(rect);
- }
-
- mNeedsArrange = false;
- LLView::reshape(width, height, called_from_parent);
-}
-
-//---------------------------------------------------------------------------------
-LLAvatarListItem::~LLAvatarListItem()
-{
-}
-//---------------------------------------------------------------------------------
-
-//---------------------------------------------------------------------------------
-BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask)
-{
- mYPos = y;
- mXPos = x;
-
- return true;
-}
-
-//---------------------------------------------------------------------------------
void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
- setTransparentColor( *(new LLColor4((F32)0.4, (F32)0.4, (F32)0.4)) );
+ childSetVisible("hovered_icon", true);
+ mInfoBtn->setVisible(true);
- if(mInfo)
- mInfo->setVisible(true);
-
- if(mProfile)
- mProfile->setVisible(true);
+ LLPanel::onMouseEnter(x, y, mask);
}
-//---------------------------------------------------------------------------------
void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
- if(mInfo)
- {
- if( mInfo->getRect().pointInRect(x, y) )
- return;
-
- mInfo->setVisible(false);
- }
-
- if(mProfile)
- {
- if( mProfile->getRect().pointInRect(x, y) )
- return;
-
- mProfile->setVisible(false);
- }
+ childSetVisible("hovered_icon", false);
+ mInfoBtn->setVisible(false);
- setTransparentColor( *(new LLColor4((F32)0.3, (F32)0.3, (F32)0.3)) );
+ LLPanel::onMouseLeave(x, y, mask);
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::setStatus(int status)
+void LLAvatarListItem::setStatus(const std::string& status)
{
+ mStatus->setValue(status);
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::setName(std::string name)
+void LLAvatarListItem::setName(const std::string& name)
{
+ mAvatarName->setValue(name);
+ mAvatarName->setToolTip(name);
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::setAvatar(LLSD& data)
+void LLAvatarListItem::setAvatarId(const LLUUID& id)
{
+ mAvatarIcon->setValue(id);
+ mSpeakingIndicator->setSpeakerId(id);
}
-//---------------------------------------------------------------------------------
void LLAvatarListItem::onInfoBtnClick()
{
- mInspector = LLFloaterReg::showInstance("inspect_avatar", gAgent.getID());
-
- if (!mInspector)
- return;
+ LLFloaterReg::showInstance("inspect_avatar", mAvatarIcon->getValue());
- LLRect rect;
+ /* TODO fix positioning of inspector
localPointToScreen(mXPos, mYPos, &mXPos, &mYPos);
+
+ LLRect rect;
// *TODO Vadim: rewrite this. "+= -" looks weird.
- S32 delta = mYPos - mInspector->getRect().getHeight();
+ S32 delta = mYPos - inspector->getRect().getHeight();
if(delta < 0)
{
mYPos += -delta;
}
-
+
rect.setLeftTopAndSize(mXPos, mYPos,
- mInspector->getRect().getWidth(), mInspector->getRect().getHeight());
- mInspector->setRect(rect);
- mInspector->setFrontmost(true);
- mInspector->setVisible(true);
-
+ inspector->getRect().getWidth(), inspector->getRect().getHeight());
+ inspector->setRect(rect);
+ inspector->setFrontmost(true);
+ inspector->setVisible(true);
+ */
}
-//---------------------------------------------------------------------------------
-void LLAvatarListItem::onProfileBtnClick()
+void LLAvatarListItem::setValue( const LLSD& value )
{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
}
-//---------------------------------------------------------------------------------
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index b41e0ff209..dc5606e4c2 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -2,9 +2,9 @@
* @file llavatarlistitem.h
* @avatar list item header file
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -30,75 +30,45 @@
* $/LicenseInfo$
*/
-#include "llavatariconctrl.h"
-#include <llview.h>
-#include <llpanel.h>
-#include <llfloater.h>
-#include <lltextbox.h>
-#include <llbutton.h>
-#include <lluuid.h>
+#ifndef LL_LLAVATARLISTITEM_H
+#define LL_LLAVATARLISTITEM_H
-//#include "llfloaterminiinspector.h"
+#include "llpanel.h"
+#include "lloutputmonitorctrl.h"
+#include "llbutton.h"
+#include "lltextbox.h"
-class LLAvatarListItem : public LLPanel
+class LLAvatarIconCtrl;
+
+class LLAvatarListItem : public LLPanel
{
public:
- struct Params : public LLInitParam::Block<Params, LLPanel::Params>
- {
- Optional<LLUUID> avatar_icon;
- Optional<std::string> user_name;
- struct avatar_list_item_buttons
- {
- bool status;
- bool info;
- bool profile;
- bool locator;
- avatar_list_item_buttons() : status(true), info(true), profile(true), locator(true)
- {};
- } buttons;
-
- Params()
- : avatar_icon("avatar_icon"),
- user_name("user_name")
- {};
- };
-
-
- LLAvatarListItem(const Params& p);
- virtual ~LLAvatarListItem();
-
- void reshape(S32 width, S32 height, BOOL called_from_parent);
-
- //interface
- void setStatus(int status);
- void setName(std::string name);
- void setAvatar(LLSD& data);
- void needsArrange( void ) {mNeedsArrange = true;}
-
+ LLAvatarListItem();
+ virtual ~LLAvatarListItem() {};
- //event handlers
- //mouse
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL postBuild();
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
- //buttons
- void onInfoBtnClick();
- void onProfileBtnClick();
+ virtual void setValue(const LLSD& value);
-private:
- LLAvatarIconCtrl* mAvatar;
- LLIconCtrl* mLocator;
- LLTextBox* mName;
- LLTextBox* mStatus;
- LLButton* mInfo;
- LLButton* mProfile;
+ void setStatus(const std::string& status);
+ void setName(const std::string& name);
+ void setAvatarId(const LLUUID& id);
+
+ void onInfoBtnClick();
- S32 mYPos;
- S32 mXPos;
+ void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); }
+ void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }
+ void showStatus(bool show_status) {mStatus->setVisible(show_status); }
- LLFloater* mInspector;
- bool mNeedsArrange;
- //
- void init(const Params& p);
+private:
+ LLAvatarIconCtrl*mAvatarIcon;
+ LLTextBox* mAvatarName;
+ LLTextBox* mStatus;
+
+ LLOutputMonitorCtrl* mSpeakingIndicator;
+ LLButton* mInfoBtn;
};
+
+#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index ecd67e44ae..edf6e84b68 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -34,10 +34,16 @@
#include "llavatarpropertiesprocessor.h"
-#include "message.h"
+// Viewer includes
#include "llagent.h"
#include "llviewergenericmessage.h"
+// Linden library includes
+#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
+#include "lldate.h"
+#include "lltrans.h"
+#include "message.h"
+
LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor()
{
}
@@ -87,35 +93,18 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat
}
}
-void LLAvatarPropertiesProcessor::sendDataRequest(const LLUUID& avatar_id, EAvatarProcessorType type,
- const void * data)
+
+void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method)
{
- switch(type)
+ // Suppress duplicate requests while waiting for a response from the network
+ if (isPendingRequest(avatar_id, type))
{
- case APT_PROPERTIES:
- sendAvatarPropertiesRequest(avatar_id);
- break;
- case APT_PICKS:
- sendGenericRequest(avatar_id, "avatarpicksrequest");
- break;
- case APT_PICK_INFO:
- if (data) {
- sendPickInfoRequest(avatar_id, *static_cast<const LLUUID*>(data));
- }
- break;
- case APT_NOTES:
- sendGenericRequest(avatar_id, "avatarnotesrequest");
- break;
- case APT_GROUPS:
- sendGenericRequest(avatar_id, "avatargroupsrequest");
- break;
- default:
- break;
+ // waiting for a response, don't re-request
+ return;
}
-}
+ // indicate we're going to make a request
+ addPendingRequest(avatar_id, type);
-void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, const std::string method)
-{
std::vector<std::string> strings;
strings.push_back( avatar_id.asString() );
send_generic_message(method, strings);
@@ -123,6 +112,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, co
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
{
+ if (isPendingRequest(avatar_id, APT_PROPERTIES))
+ {
+ // waiting for a response, don't re-request
+ return;
+ }
+ // indicate we're going to make a request
+ addPendingRequest(avatar_id, APT_PROPERTIES);
+
LLMessageSystem *msg = gMessageSystem;
msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
@@ -133,40 +130,29 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avat
gAgent.sendReliableMessage();
}
-void LLAvatarPropertiesProcessor::sendDataUpdate(const void* data, EAvatarProcessorType type)
+void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id)
{
- switch(type)
- {
- case APT_PROPERTIES:
- sendAvatarPropertiesUpdate(data);
- break;
- case APT_PICK_INFO:
- sendPicInfoUpdate(data);
- case APT_PICKS:
-// sendGenericRequest(avatar_id, "avatarpicksrequest");
- break;
- case APT_NOTES:
-// sendGenericRequest(avatar_id, "avatarnotesrequest");
- break;
- case APT_GROUPS:
-// sendGenericRequest(avatar_id, "avatargroupsrequest");
- break;
- default:
- break;
- }
+ sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest");
+}
+void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest");
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest");
}
-void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const void* data)
+
+void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
{
llinfos << "Sending avatarinfo update" << llendl;
- const LLAvatarData* avatar_props = static_cast<const LLAvatarData*>(data);
// This value is required by sendAvatarPropertiesUpdate method.
//A profile should never be mature. (From the original code)
BOOL mature = FALSE;
-
-
LLMessageSystem *msg = gMessageSystem;
msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate);
@@ -186,6 +172,156 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const void* data)
gAgent.sendReliableMessage();
}
+//static
+std::string LLAvatarPropertiesProcessor::ageFromDate(const std::string& date_string)
+{
+ // Convert string date to malleable representation
+ S32 month, day, year;
+ S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &month, &day, &year);
+ if (matched != 3) return "???";
+
+ // Create ISO-8601 date string
+ std::string iso8601_date_string =
+ llformat("%04d-%02d-%02dT00:00:00Z", year, month, day);
+ LLDate date(iso8601_date_string);
+
+ // Correct for the fact that account creation dates are in Pacific time,
+ // == UTC - 8
+ F64 date_secs_since_epoch = date.secondsSinceEpoch();
+ date_secs_since_epoch += 8.0 * 60.0 * 60.0;
+
+ // Convert seconds from epoch to seconds from now
+ F64 now_secs_since_epoch = LLDate::now().secondsSinceEpoch();
+ F64 age_secs = now_secs_since_epoch - date_secs_since_epoch;
+
+ // We don't care about sub-day times
+ const F64 SEC_PER_DAY = 24.0 * 60.0 * 60.0;
+ S32 age_days = lltrunc(age_secs / SEC_PER_DAY);
+
+ // Assume most values won't be used to fill in the format string:
+ // "[AGEYEARS][AGEMONTHS][AGEWEEKS][AGEDAYS]old"
+ LLStringUtil::format_map_t final_args;
+ final_args["[AGEYEARS]"] = "";
+ final_args["[AGEMONTHS]"] = "";
+ final_args["[AGEWEEKS]"] = "";
+ final_args["[AGEDAYS]"] = "";
+
+ // Try for age in round number of years
+ LLStringUtil::format_map_t args;
+ S32 age_years = age_days / 365;
+ age_days = age_days % 365;
+ if (age_years > 1)
+ {
+ args["[YEARS]"] = llformat("%d", age_years);
+ final_args["[AGEYEARS]"] = LLTrans::getString("AgeYears", args);
+ }
+ else if (age_years == 1)
+ {
+ final_args["[AGEYEARS]"] = LLTrans::getString("Age1Year");
+ }
+ // fall through because we show years + months for ages > 1 year
+
+ S32 age_months = age_days / 30;
+ age_days = age_days % 30;
+ if (age_months > 1)
+ {
+ args["[MONTHS]"] = llformat("%d", age_months);
+ final_args["[AGEMONTHS]"] = LLTrans::getString("AgeMonths", args);
+ // Either N years M months, or just M months,
+ // so we can exit.
+ return LLTrans::getString("YearsMonthsOld", final_args);
+ }
+ else if (age_months == 1)
+ {
+ final_args["[AGEMONTHS]"] = LLTrans::getString("Age1Month");
+ return LLTrans::getString("YearsMonthsOld", final_args);
+ }
+
+ // Now for age in weeks
+ S32 age_weeks = age_days / 7;
+ age_days = age_days % 7;
+ if (age_weeks > 1)
+ {
+ args["[WEEKS]"] = llformat("%d", age_weeks);
+ final_args["[AGEWEEKS]"] = LLTrans::getString("AgeWeeks", args);
+ return LLTrans::getString("WeeksOld", final_args);
+ }
+ else if (age_weeks == 1)
+ {
+ final_args["[AGEWEEKS]"] = LLTrans::getString("Age1Week");
+ return LLTrans::getString("WeeksOld", final_args);
+ }
+
+ // Down to days now
+ if (age_days > 1)
+ {
+ args["[DAYS]"] = llformat("%d", age_days);
+ final_args["[AGEDAYS]"] = LLTrans::getString("AgeDays", args);
+ return LLTrans::getString("DaysOld", final_args);
+ }
+ else if (age_days == 1)
+ {
+ final_args["[AGEDAYS]"] = LLTrans::getString("Age1Day");
+ return LLTrans::getString("DaysOld", final_args);
+ }
+ else
+ {
+ return LLTrans::getString("TodayOld");
+ }
+}
+
+
+//static
+std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data)
+{
+ // If you have a special account, like M Linden ("El Jefe!")
+ // return an untranslated "special" string
+ if (!avatar_data->caption_text.empty())
+ {
+ return avatar_data->caption_text;
+ }
+ const char* const ACCT_TYPE[] = {
+ "AcctTypeResident",
+ "AcctTypeTrial",
+ "AcctTypeCharterMember",
+ "AcctTypeEmployee"
+ };
+ U8 caption_max = (U8)LL_ARRAY_SIZE(ACCT_TYPE)-1;
+ U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, caption_max);
+ return LLTrans::getString(ACCT_TYPE[caption_index]);
+}
+
+//static
+std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data)
+{
+ // Special accounts like M Linden don't have payment info revealed.
+ if (!avatar_data->caption_text.empty()) return "";
+
+ // Linden employees don't have payment info revealed
+ const S32 LINDEN_EMPLOYEE_INDEX = 3;
+ if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return "";
+
+ BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED);
+ BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED);
+ // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
+ //BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED);
+
+ const char* payment_text;
+ if(transacted)
+ {
+ payment_text = "PaymentInfoUsed";
+ }
+ else if (identified)
+ {
+ payment_text = "PaymentInfoOnFile";
+ }
+ else
+ {
+ payment_text = "NoPaymentInfoOnFile";
+ }
+ return LLTrans::getString(payment_text);
+}
+
void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)
{
LLAvatarData avatar_data;
@@ -214,7 +350,10 @@ void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem*
{
msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text);
}
- notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES);
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES);
+ self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES);
}
void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**)
@@ -228,11 +367,13 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m
WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply
*/
}
+
void LLAvatarPropertiesProcessor::processAvatarClassifiedReply(LLMessageSystem* msg, void**)
{
// avatarclassifiedsrequest is not sent according to new UI design but
// keep this method according to resolved issues.
}
+
void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**)
{
LLAvatarNotes avatar_notes;
@@ -241,7 +382,10 @@ void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg,
msg->getUUID(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id);
msg->getString(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes);
- notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES);
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_notes.target_id, APT_NOTES);
+ self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES);
}
void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**)
@@ -261,7 +405,10 @@ void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg,
avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name));
}
- notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS);
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_picks.target_id, APT_PICKS);
+ self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS);
}
void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**)
@@ -306,7 +453,9 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi
msg->getS32(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order);
msg->getBOOL(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled);
- notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO);
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // don't need to remove pending request as we don't track pick info
+ self->notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO);
}
void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**)
@@ -329,12 +478,15 @@ void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg,
avatar_groups.group_list.push_back(group_data);
}
- notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS);
+ LLAvatarPropertiesProcessor* self = getInstance();
+ self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS);
+ self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS);
}
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type)
{
- LLAvatarPropertiesProcessor::observer_multimap_t observers = LLAvatarPropertiesProcessor::getInstance()->mObservers;
+ // Copy the map (because observers may delete themselves when updated?)
+ LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers;
observer_multimap_t::iterator oi = observers.lower_bound(id);
observer_multimap_t::iterator end = observers.upper_bound(id);
@@ -397,10 +549,8 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
gAgent.sendReliableMessage();
}
-void LLAvatarPropertiesProcessor::sendPicInfoUpdate(const void* pick_data)
+void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
{
- if (!pick_data) return;
- const LLPickData *new_pick = static_cast<const LLPickData*>(pick_data);
if (!new_pick) return;
LLMessageSystem* msg = gMessageSystem;
@@ -440,3 +590,38 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id,
request_params.push_back(pick_id.asString() );
send_generic_message("pickinforequest", request_params);
}
+
+
+bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ timestamp_map_t::iterator it = mRequestTimestamps.find(key);
+
+ // Is this a new request?
+ if (it == mRequestTimestamps.end()) return false;
+
+ // We found a request, check if it has timed out
+ U32 now = time(NULL);
+ const U32 REQUEST_EXPIRE_SECS = 5;
+ U32 expires = it->second + REQUEST_EXPIRE_SECS;
+
+ // Request is still pending if it hasn't expired yet
+ // *NOTE: Expired requests will accumulate in this map, but they are rare,
+ // the data is small, and they will be updated if the same data is
+ // re-requested
+ return (now < expires);
+}
+
+void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ U32 now = time(NULL);
+ // Add or update existing (expired) request
+ mRequestTimestamps[ key ] = now;
+}
+
+void LLAvatarPropertiesProcessor::removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ mRequestTimestamps.erase(key);
+}
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 2e10dea834..24675c44c0 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -43,10 +43,6 @@
- Remove EAvatarProcessorType in favor of separate observers, derived from a common parent (to get rid of void*).
*/
-/*
-*TODO: mantipov: get rid of sendDataRequest and sendDataUpdate methods. Use exact methods instead of.
-*/
-
class LLMessageSystem;
enum EAvatarProcessorType
@@ -157,10 +153,20 @@ public:
void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
-
- void sendDataRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const void * data = NULL);
- void sendDataUpdate(const void* data, EAvatarProcessorType type);
+ // Request various types of avatar data. Duplicate requests will be
+ // suppressed while waiting for a response from the network.
+ void sendAvatarPropertiesRequest(const LLUUID& avatar_id);
+ void sendAvatarPicksRequest(const LLUUID& avatar_id);
+ void sendAvatarNotesRequest(const LLUUID& avatar_id);
+ void sendAvatarGroupsRequest(const LLUUID& avatar_id);
+
+ // Duplicate pick info requests are not suppressed.
+ void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id);
+
+ void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props);
+
+ void sendPickInfoUpdate(const LLPickData* new_pick);
void sendFriendRights(const LLUUID& avatar_id, S32 rights);
@@ -168,6 +174,20 @@ public:
void sendPickDelete(const LLUUID& pick_id);
+ // Convert a date provided by the server (MM/DD/YYYY) into a localized,
+ // human-readable age (1 year, 2 months) using translation strings from
+ // the XML file.
+ static std::string ageFromDate(const std::string& date_string);
+
+ // Returns translated, human readable string for account type, such
+ // as "Resident" or "Linden Employee". Used for profiles, inspectors.
+ static std::string accountType(const LLAvatarData* avatar_data);
+
+ // Returns translated, human readable string for payment info, such
+ // as "Payment Info on File" or "Payment Info Used".
+ // Used for profiles, inspectors.
+ static std::string paymentInfo(const LLAvatarData* avatar_data);
+
static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);
static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
@@ -181,19 +201,23 @@ public:
static void processAvatarPicksReply(LLMessageSystem* msg, void**);
static void processPickInfoReply(LLMessageSystem* msg, void**);
+
protected:
- void sendAvatarPropertiesRequest(const LLUUID& avatar_id);
+ void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method);
- void sendGenericRequest(const LLUUID& avatar_id, const std::string method);
-
- void sendAvatarPropertiesUpdate(const void* data);
+ void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type);
- void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id);
-
- void sendPicInfoUpdate(const void * pick_data);
+ // Is there a pending, not timed out, request for this avatar's data?
+ // Use this to suppress duplicate requests for data when a request is
+ // pending.
+ bool isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
- static void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type);
+ // Call this when a request has been sent
+ void addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
+
+ // Call this when the reply to the request is received
+ void removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
typedef void* (*processor_method_t)(LLMessageSystem*);
static processor_method_t getProcessor(EAvatarProcessorType type);
@@ -203,6 +227,13 @@ protected:
typedef std::multimap<LLUUID, LLAvatarPropertiesObserver*> observer_multimap_t;
observer_multimap_t mObservers;
+
+ // Keep track of pending requests for data by avatar id and type.
+ // Maintain a timestamp for each request so a request that receives no reply
+ // does not block future requests forever.
+ // Map avatar_id+request_type -> U32 timestamp in seconds
+ typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t;
+ timestamp_map_t mRequestTimestamps;
};
#endif // LL_LLAVATARPROPERTIESPROCESSOR_H
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 2403e891f6..06f9a86d8d 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -37,16 +37,15 @@
#include "llchiclet.h"
#include "llfloaterreg.h"
#include "llflyoutbutton.h"
+#include "llimpanel.h" // for LLIMFloater
#include "lllayoutstack.h"
#include "llnearbychatbar.h"
#include "llsplitbutton.h"
+#include "llsyswellwindow.h"
#include "llfloatercamera.h"
-#include "llimpanel.h"
-#include "llactiveimwindow.h"
LLBottomTray::LLBottomTray(const LLSD&)
: mChicletPanel(NULL),
- mIMWell(NULL),
mSysWell(NULL),
mTalkBtn(NULL),
mNearbyChatBar(NULL),
@@ -58,10 +57,10 @@ LLBottomTray::LLBottomTray(const LLSD&)
LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");
mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
- mIMWell = getChild<LLNotificationChiclet>("im_well");
mSysWell = getChild<LLNotificationChiclet>("sys_well");
mSysWell->setNotificationChicletWindow(LLFloaterReg::getInstance("syswell_window"));
+
mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
LLSplitButton* presets = getChild<LLSplitButton>("presets");
@@ -76,14 +75,20 @@ LLBottomTray::LLBottomTray(const LLSD&)
// Necessary for focus movement among child controls
setFocusRoot(TRUE);
-
- LLActiveIMWindow::init(mIMWell);
}
BOOL LLBottomTray::postBuild()
{
+ mCommitCallbackRegistrar.add("ShowCamMoveCtrls.Action", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked, this, _2));
+ mEnableCallbackRegistrar.add("ShowCamMoveCtrls.EnableMenuItem", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled, this, _2));
+
+ mShowCamMoveCtrlsContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_camera_move_controls.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ gMenuHolder->addChild(mShowCamMoveCtrlsContextMenu);
+
mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
+ mMovementPanel = getChild<LLPanel>("movement_panel");
+ mCamPanel = getChild<LLPanel>("cam_panel");
return TRUE;
}
@@ -114,11 +119,29 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl)
}
}
+// *TODO Vadim: why void* ?
void* LLBottomTray::createNearbyChatBar(void* userdata)
{
return new LLNearbyChatBar();
}
+LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
+{
+ LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
+
+ switch (im_chiclet_type)
+ {
+ case LLIMChiclet::TYPE_IM:
+ return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
+ case LLIMChiclet::TYPE_GROUP:
+ return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
+ case LLIMChiclet::TYPE_UNKNOWN:
+ break;
+ }
+
+ return NULL;
+}
+
//virtual
void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
@@ -130,12 +153,18 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam
}
else
{
- LLIMChiclet* chiclet = getChicletPanel()->createChiclet<LLIMChiclet>(session_id);
- chiclet->setIMSessionName(name);
- chiclet->setOtherParticipantId(other_participant_id);
+ LLIMChiclet* chiclet = createIMChiclet(session_id);
+ if(chiclet)
+ {
+ chiclet->setIMSessionName(name);
+ chiclet->setOtherParticipantId(other_participant_id);
+ }
+ else
+ {
+ llerrs << "Could not create chiclet" << llendl;
+ }
}
}
- updateImChicletCount();
}
//virtual
@@ -143,9 +172,16 @@ void LLBottomTray::sessionRemoved(const LLUUID& session_id)
{
if(getChicletPanel())
{
+ // IM floater should be closed when session removed and associated chiclet closed
+ LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+ "impanel", session_id);
+ if (iMfloater != NULL)
+ {
+ iMfloater->closeFloater();
+ }
+
getChicletPanel()->removeChiclet(session_id);
}
- updateImChicletCount();
}
//virtual
@@ -174,8 +210,9 @@ void LLBottomTray::setVisible(BOOL visible)
child_it != mToolbarStack->getChildList()->end(); child_it++)
{
LLView* viewp = *child_it;
+ std::string name = viewp->getName();
- if ("chat_bar" == viewp->getName())
+ if ("chat_bar" == name || "movement_panel" == name || "cam_panel" == name)
continue;
else
{
@@ -185,7 +222,54 @@ void LLBottomTray::setVisible(BOOL visible)
}
}
-void LLBottomTray::updateImChicletCount() {
- U32 chicletCount = mChicletPanel->getChicletCount();
- mIMWell->setCounter(chicletCount);
+BOOL LLBottomTray::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (!LLPanel::handleRightMouseDown(x, y, mask))
+ {
+ if (mShowCamMoveCtrlsContextMenu)
+ {
+ mShowCamMoveCtrlsContextMenu->buildDrawLabels();
+ mShowCamMoveCtrlsContextMenu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, mShowCamMoveCtrlsContextMenu, x, y);
+ }
+ }
+
+ return TRUE;
+}
+
+bool LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ if (item == "show_camera_move_controls")
+ {
+ return gSavedSettings.getBOOL("ShowCameraAndMoveControls");
+ }
+
+ return FALSE;
+}
+
+void LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ if (item == "show_camera_move_controls")
+ {
+ BOOL state = !gSavedSettings.getBOOL("ShowCameraAndMoveControls");
+
+ showCameraAndMoveControls(state);
+ gSavedSettings.setBOOL("ShowCameraAndMoveControls", state);
+ }
+}
+
+void LLBottomTray::showCameraAndMoveControls(BOOL visible)
+{
+ mCamPanel->setVisible(visible);
+ mMovementPanel->setVisible(visible);
+
+ if (!visible)
+ {
+ LLFloaterReg::hideFloaterInstance("moveview");
+ LLFloaterReg::hideFloaterInstance("camera");
+ }
}
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 7f606339bc..c3c840ede0 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -33,6 +33,8 @@
#ifndef LL_LLBOTTOMPANEL_H
#define LL_LLBOTTOMPANEL_H
+#include <llmenugl.h>
+
#include "llpanel.h"
#include "llimview.h"
@@ -42,6 +44,7 @@ class LLLayoutStack;
class LLNotificationChiclet;
class LLTalkButton;
class LLNearbyChatBar;
+class LLIMChiclet;
class LLBottomTray
: public LLSingleton<LLBottomTray>
@@ -55,7 +58,6 @@ public:
BOOL postBuild();
LLChicletPanel* getChicletPanel() {return mChicletPanel;}
- LLNotificationChiclet* getIMWell() {return mIMWell;}
LLNotificationChiclet* getSysWell() {return mSysWell;}
LLNearbyChatBar* getNearbyChatBar() {return mNearbyChatBar;}
@@ -68,8 +70,11 @@ public:
virtual void onFocusLost();
virtual void setVisible(BOOL visible);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ void showCameraAndMoveControls(BOOL visible);
+
private:
- void updateImChicletCount();
protected:
@@ -77,15 +82,24 @@ protected:
void onChicletClick(LLUICtrl* ctrl);
+ bool onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata);
+ void onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata);
+
static void* createNearbyChatBar(void* userdata);
+ /**
+ * Creates IM Chiclet based on session type (IM chat or Group chat)
+ */
+ LLIMChiclet* createIMChiclet(const LLUUID& session_id);
+
LLChicletPanel* mChicletPanel;
- LLNotificationChiclet* mIMWell;
LLNotificationChiclet* mSysWell;
LLTalkButton* mTalkBtn;
LLNearbyChatBar* mNearbyChatBar;
LLLayoutStack* mToolbarStack;
-
+ LLMenuGL* mShowCamMoveCtrlsContextMenu;
+ LLPanel* mMovementPanel;
+ LLPanel* mCamPanel;
};
#endif // LL_LLBOTTOMPANEL_H
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 3ee2c93961..96c707b08f 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -674,7 +674,7 @@ class LLChatHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
- LLChatHandler() : LLCommandHandler("chat", true) { }
+ LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index f5dfbb2851..6fb6552f2d 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -38,6 +38,7 @@
#include "llchatmsgbox.h"
#include "llavatariconctrl.h"
#include "llfloaterreg.h"
+#include "lllocalcliprect.h"
#include "lltrans.h"
#include "llviewercontrol.h"
diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp
index 9399e1f68d..e6398dd47a 100644
--- a/indra/newview/llchatmsgbox.cpp
+++ b/indra/newview/llchatmsgbox.cpp
@@ -1,10 +1,11 @@
/**
* @file llchatmsgbox.cpp
+ * @author Martin Reddy
* @brief chat history text box, able to show array of strings with separator
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -30,360 +31,96 @@
* $/LicenseInfo$
*/
-
#include "llviewerprecompiledheaders.h"
#include "llchatmsgbox.h"
#include "llwindow.h"
-#include "llfocusmgr.h"
-
-static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
-LLChatMsgBox::Params::Params()
-: text_color("text_color"),
- highlight_on_hover("hover", false),
- border_visible("border_visible", false),
- border_drop_shadow_visible("border_drop_shadow_visible", false),
- bg_visible("bg_visible", false),
- use_ellipses("use_ellipses"),
- word_wrap("word_wrap", false),
- hover_color("hover_color"),
- disabled_color("disabled_color"),
- background_color("background_color"),
- border_color("border_color"),
- line_spacing("line_spacing", 4),
- block_spacing("block_spacing",10),
- text("text"),
- font_shadow("font_shadow", LLFontGL::NO_SHADOW)
-{}
-LLChatMsgBox::LLChatMsgBox(const LLChatMsgBox::Params& p)
-: LLUICtrl(p),
- mFontGL(p.font),
- mHoverActive( p.highlight_on_hover ),
- mHasHover( FALSE ),
- mBackgroundVisible( p.bg_visible ),
- mBorderVisible( p.border_visible ),
- mShadowType( p.font_shadow ),
- mBorderDropShadowVisible( p.border_drop_shadow_visible ),
- mUseEllipses( p.use_ellipses ),
- mVAlign( LLFontGL::TOP ),
- mClickedCallback(NULL),
- mTextColor(p.text_color()),
- mDisabledColor(p.disabled_color()),
- mBackgroundColor(p.background_color()),
- mBorderColor(p.border_color()),
- mHoverColor(p.hover_color()),
- mHAlign(p.font_halign),
- mLineSpacing(p.line_spacing),
- mBlockSpasing(p.block_spacing),
- mWordWrap( p.word_wrap ),
- mFontStyle(LLFontGL::getStyleFromString(p.font.style))
-{
- setText( p.text() );
-}
+static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
-BOOL LLChatMsgBox::handleMouseDown(S32 x, S32 y, MASK mask)
+LLChatMsgBox::Params::Params() :
+ block_spacing("block_spacing", 10)
{
- BOOL handled = FALSE;
-
- // HACK: Only do this if there actually is a click callback, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback)
- {
- handled = TRUE;
-
- // Route future Mouse messages here preemptively. (Release on mouse up.)
- gFocusMgr.setMouseCapture( this );
-
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
- }
-
- return handled;
+ line_spacing = 4;
}
-BOOL LLChatMsgBox::handleMouseUp(S32 x, S32 y, MASK mask)
-{
- BOOL handled = FALSE;
-
- // We only handle the click if the click both started and ended within us
-
- // HACK: Only do this if there actually is a click callback, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback
- && hasMouseCapture())
- {
- handled = TRUE;
-
- // Release the mouse
- gFocusMgr.setMouseCapture( NULL );
-
- if (getSoundFlags() & MOUSE_UP)
- {
- make_ui_sound("UISndClickRelease");
- }
-
- // 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 (mClickedCallback)
- {
- mClickedCallback();
- }
- }
-
- return handled;
-}
+LLChatMsgBox::LLChatMsgBox(const Params& p) :
+ LLTextBox(p),
+ mBlockSpacing(p.block_spacing)
+{}
-BOOL LLChatMsgBox::handleHover(S32 x, S32 y, MASK mask)
+void LLChatMsgBox::addText( const LLStringExplicit& text )
{
- BOOL handled = LLView::handleHover(x,y,mask);
- if(mHoverActive)
+ LLWString t = mText.getWString();
+ if (! t.empty())
{
- mHasHover = TRUE; // This should be set every frame during a hover.
- getWindow()->setCursor(UI_CURSOR_ARROW);
+ t += '\n';
}
-
- return (handled || mHasHover);
-}
-
-void LLChatMsgBox::addText( const LLStringExplicit& text )
-{
- boost::shared_ptr<text_block> t(new text_block());
- t->text = wrapText(text);
- setLineLengths(*t);
- mTextStrings.push_back(t);
+ t += getWrappedText(text);
+ LLTextBox::setText(wstring_to_utf8str(t));
+ mSeparatorOffset.push_back(getLength());
}
void LLChatMsgBox::setText(const LLStringExplicit& text)
{
- mTextStrings.clear();
-
+ mSeparatorOffset.clear();
+ mText.clear();
addText(text);
-
-}
-
-void LLChatMsgBox::resetLineLengths()
-{
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
- {
- boost::shared_ptr<text_block> tblock = *it;
- setLineLengths(*tblock);
- }
-}
-
-void LLChatMsgBox::setLineLengths(text_block& t)
-{
- t.lines.clear();
-
- std::string::size_type cur = 0;
- std::string::size_type len = t.text.length();
-
- while (cur < len)
- {
- std::string::size_type end = t.text.getWString().find('\n', cur);
- std::string::size_type runLen;
-
- if (end == std::string::npos)
- {
- runLen = len - cur;
- cur = len;
- }
- else
- {
- runLen = end - cur;
- cur = end + 1; // skip the new line character
- }
-
- t.lines.push_back( (S32)runLen );
- }
}
-std::string LLChatMsgBox::wrapText(const LLStringExplicit& in_text, F32 max_width)
-{
- if (max_width < 0.0f)
- {
- max_width = (F32)getRect().getWidth();
- }
-
- LLWString wtext = utf8str_to_wstring(in_text);
- LLWString final_wtext;
-
- LLWString::size_type cur = 0;;
- LLWString::size_type len = wtext.size();
- while (cur < len)
- {
- LLWString::size_type end = wtext.find('\n', cur);
- if (end == LLWString::npos)
- {
- end = len;
- }
-
- LLWString::size_type runLen = end - cur;
- if (runLen > 0)
- {
- LLWString run(wtext, cur, runLen);
- LLWString::size_type useLen =
- mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
-
- final_wtext.append(wtext, cur, useLen);
- cur += useLen;
- // not enough room to add any more characters
- if (useLen == 0) break;
- }
-
- if (cur < len)
- {
- if (wtext[cur] == '\n')
- cur += 1;
- else
- final_wtext += '\n';
- }
- }
-
- std::string final_text = wstring_to_utf8str(final_wtext);
- return final_text;
-}
-
-S32 LLChatMsgBox::getTextLinesNum()
-{
- S32 num_lines = 0;
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
- {
- boost::shared_ptr<text_block> tblock = *it;
- num_lines+=tblock->lines.size();
- }
-
- if( num_lines < 1 )
- {
- num_lines = 1;
- }
-
- return num_lines;
+void LLChatMsgBox::setValue(const LLSD& value )
+{
+ setText(value.asString());
}
S32 LLChatMsgBox::getTextPixelHeight()
{
+ S32 num_blocks = mSeparatorOffset.size();
S32 num_lines = getTextLinesNum();
- return (S32)(num_lines * mFontGL->getLineHeight() + (num_lines-1)*mLineSpacing + mBlockSpasing*(mTextStrings.size()-1) + 2*mLineSpacing);//some extra space
-}
-
-void LLChatMsgBox::setValue(const LLSD& value )
-{
- setText(value.asString());
+ return (S32)(num_lines * mDefaultFont->getLineHeight() + \
+ (num_lines-1) * mLineSpacing + \
+ (num_blocks-1) * mBlockSpacing + \
+ 2 * mLineSpacing);
}
-
-void LLChatMsgBox::draw()
+S32 LLChatMsgBox::getTextLinesNum()
{
- if (mBorderVisible)
- {
- gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
- }
-
- if( mBorderDropShadowVisible )
+ S32 num_lines = getLineCount();
+ if (num_lines < 1)
{
- static LLUICachedControl<LLColor4> color_drop_shadow ("ColorDropShadow", *(new LLColor4));
- static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
- gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- color_drop_shadow, drop_shadow_tooltip);
- }
-
- if (mBackgroundVisible)
- {
- LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- gl_rect_2d( r, mBackgroundColor.get() );
- }
-
- S32 text_x = 0;
- switch( mHAlign )
- {
- case LLFontGL::LEFT:
- break;
- case LLFontGL::HCENTER:
- text_x = getRect().getWidth() / 2;
- break;
- case LLFontGL::RIGHT:
- text_x = getRect().getWidth() ;
- break;
- }
-
- S32 text_y = getRect().getHeight() ;
-
- if ( getEnabled() )
- {
- if(mHasHover)
- {
- drawText( text_x, text_y, mHoverColor.get() );
- }
- else
- {
- drawText( text_x, text_y, mTextColor.get() );
- }
- }
- else
- {
- drawText( text_x, text_y, mDisabledColor.get() );
- }
-
- if (sDebugRects)
- {
- drawDebugRect();
+ num_lines = 1;
}
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
-
- mHasHover = FALSE; // This is reset every frame.
-}
-
-void LLChatMsgBox::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- // reparse line lengths
- LLView::reshape(width, height, called_from_parent);
- resetLineLengths();
+
+ return num_lines;
}
-void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color )
+void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4 &color)
{
+ S32 start = 0;
S32 width = getRect().getWidth()-10;
-
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
+ // iterate through each block of text that has been added
+ y -= mLineSpacing;
+ for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); true ;)
{
- boost::shared_ptr<text_block> tblock = *it;
+ // display the text for this block
+ S32 num_chars = *it - start;
+ LLWString text = mDisplayText.substr(start, num_chars);
+ LLTextBox::drawText(x, y, text, color);
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = tblock->lines.begin();
- iter != tblock->lines.end(); ++iter)
+ // exit the loop if this is the last text block
+ start += num_chars + 1; // skip the newline
+ if (++it == mSeparatorOffset.end())
{
- S32 line_length = *iter;
- mFontGL->render(tblock->text, cur_pos, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- mFontStyle,
- mShadowType,
- line_length, getRect().getWidth(), NULL, mUseEllipses );
- cur_pos += line_length + 1;
- y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing;
-
- }
- std::vector< boost::shared_ptr<text_block> >::iterator next = it;
- ++next;
- if(next == mTextStrings.end())
break;
- //separator
- gl_line_2d(5,y-mBlockSpasing/2,width,y-mBlockSpasing/2,LLColor4::grey);
- y-=mBlockSpasing;
- }
+ }
+ // output a separator line between blocks
+ S32 num_lines = std::count(text.begin(), text.end(), '\n') + 1;
+ y -= num_lines * (llfloor(mDefaultFont->getLineHeight()) + mLineSpacing);
+ S32 sep_y = y - mBlockSpacing/2 + mLineSpacing/2;
+ gl_line_2d(5, sep_y, width, sep_y, LLColor4::grey);
+ y -= mBlockSpacing;
+ }
}
-
diff --git a/indra/newview/llchatmsgbox.h b/indra/newview/llchatmsgbox.h
index 61035499c7..b81b740bdc 100644
--- a/indra/newview/llchatmsgbox.h
+++ b/indra/newview/llchatmsgbox.h
@@ -1,10 +1,11 @@
/**
* @file llchatmsgbox.h
+ * @author Martin Reddy
* @brief chat history text box, able to show array of strings with separator
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -33,127 +34,45 @@
#ifndef LL_LLCHATMSGBOX_H
#define LL_LLCHATMSGBOX_H
-
+#include "lltextbox.h"
#include "lluictrl.h"
#include "v4color.h"
#include "llstring.h"
-#include "lluistring.h"
-
-class LLChatMsgBox
-: public LLUICtrl
+///
+/// LLChatMsgBox provides a text box with support for multiple blocks
+/// of text that can be added incrementally. Each block of text is
+/// visual separated from the previous block (e.g., with a horizontal
+/// line).
+///
+class LLChatMsgBox :
+ public LLTextBox
{
-protected:
- struct text_block
- {
- LLUIString text;
- std::vector<S32> lines;
- };
public:
- typedef boost::function<void (void)> callback_t;
-
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
{
- Optional<std::string> text;
-
- Optional<bool> highlight_on_hover,
- border_visible,
- border_drop_shadow_visible,
- bg_visible,
- use_ellipses,
- word_wrap;
-
- Optional<LLFontGL::ShadowType> font_shadow;
-
- Optional<LLUIColor> text_color,
- hover_color,
- disabled_color,
- background_color,
- border_color;
-
- Optional<S32> line_spacing;
-
- Optional<S32> block_spacing;
+ Optional<S32> block_spacing;
Params();
};
+
protected:
LLChatMsgBox(const Params&);
friend class LLUICtrlFactory;
-public:
- virtual void draw();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
-
- void setColor( const LLColor4& c ) { mTextColor = c; }
- void setDisabledColor( const LLColor4& c) { mDisabledColor = c; }
- void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; }
- void setBorderColor( const LLColor4& c) { mBorderColor = c; }
-
- void setHoverColor( const LLColor4& c ) { mHoverColor = c; }
- void setHoverActive( BOOL active ) { mHoverActive = active; }
-
- void setText( const LLStringExplicit& text );
- void addText( const LLStringExplicit& text );
-
- void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
+public:
+ void setText(const LLStringExplicit &text);
+ void addText(const LLStringExplicit &text);
- void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
- void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
- void setBorderDropshadowVisible(BOOL visible){ mBorderDropShadowVisible = visible; }
- void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
- void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
- void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button
-
- const LLFontGL* getFont() const { return mFontGL; }
-
- S32 getTextPixelHeight();
- S32 getTextLinesNum();
-
- virtual void setValue(const LLSD& value );
-
+ S32 getTextPixelHeight();
+ S32 getTextLinesNum();
+ /*virtual*/ void setValue(const LLSD &value);
+ /*virtual*/ void drawText(S32 x, S32 y, const LLWString &text, const LLColor4 &color);
private:
- std::string wrapText (const LLStringExplicit& in_text, F32 max_width = -1.0);
-
- void setLineLengths (text_block& t);
- void resetLineLengths ();
- void drawText (S32 x, S32 y, const LLColor4& color );
-
- const LLFontGL* mFontGL;
- LLUIColor mTextColor;
- LLUIColor mDisabledColor;
- LLUIColor mBackgroundColor;
- LLUIColor mBorderColor;
- LLUIColor mHoverColor;
-
- BOOL mHoverActive;
- BOOL mHasHover;
- BOOL mBackgroundVisible;
- BOOL mBorderVisible;
- BOOL mWordWrap;
-
- U8 mFontStyle; // style bit flags for font
- LLFontGL::ShadowType mShadowType;
- BOOL mBorderDropShadowVisible;
- BOOL mUseEllipses;
-
- S32 mLineSpacing;
- S32 mBlockSpasing;
-
- LLFontGL::HAlign mHAlign;
- LLFontGL::VAlign mVAlign;
-
- callback_t mClickedCallback;
-
-
- //same as mLineLengthList and mText in LLTextBox
- std::vector< boost::shared_ptr<text_block> > mTextStrings;
-
+ S32 mBlockSpacing;
+ std::vector<S32> mSeparatorOffset;
};
#endif
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 6b4dfa73a4..42ed783f94 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -40,6 +40,7 @@
#include "llimpanel.h" // LLFloaterIMPanel
#include "llimview.h"
#include "llfloaterreg.h"
+#include "lllocalcliprect.h"
#include "llmenugl.h"
#include "lloutputmonitorctrl.h"
#include "lltextbox.h"
@@ -47,13 +48,11 @@
#include "llvoicecontrolpanel.h"
#include "llgroupmgr.h"
-static const std::string P2P_MENU_NAME = "IMChiclet P2P Menu";
-static const std::string GROUP_MENU_NAME = "IMChiclet Group Menu";
-
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk");
static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification");
-static LLDefaultChildRegistry::Register<LLIMChiclet> t4("chiclet_im");
+static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p");
+static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group");
S32 LLNotificationChiclet::mUreadSystemNotifications = 0;
S32 LLNotificationChiclet::mUreadIMNotifications = 0;
@@ -119,6 +118,10 @@ boost::signals2::connection LLNotificationChiclet::setClickCallback(
return mButton->setClickedCallback(cb);
}
+void LLNotificationChiclet::setToggleState(BOOL toggled) {
+ mButton->setToggleState(toggled);
+}
+
void LLNotificationChiclet::updateUreadIMNotifications()
{
mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM();
@@ -187,23 +190,77 @@ void LLChiclet::setValue(const LLSD& value)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-LLIMChiclet::Params::Params()
+LLIMChiclet::LLIMChiclet(const LLChiclet::Params& p)
+: LLChiclet(p)
+{
+}
+
+void LLIMChiclet::onMouseDown()
+{
+ LLIMFloater::toggle(getSessionId());
+ setCounter(0);
+}
+
+BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onMouseDown();
+ return LLChiclet::handleMouseDown(x, y, mask);
+}
+
+void LLIMChiclet::draw()
+{
+ LLUICtrl::draw();
+
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
+}
+
+// static
+LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
+{
+ EType type = TYPE_UNKNOWN;
+ LLFloaterIMPanel* im = NULL;
+
+ if(session_id.isNull())
+ return type;
+
+ if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id)))
+ {
+ llassert_always(0 && "IM session not found"); // should never happen
+ return type;
+ }
+
+ switch(im->getDialogType())
+ {
+ case IM_NOTHING_SPECIAL:
+ type = TYPE_IM;
+ break;
+ case IM_SESSION_GROUP_START:
+ case IM_SESSION_INVITE:
+ type = TYPE_GROUP;
+ break;
+ default:
+ break;
+ }
+
+ return type;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMP2PChiclet::Params::Params()
: avatar_icon("avatar_icon")
-, group_insignia("group_insignia")
, unread_notifications("unread_notifications")
, speaker("speaker")
, show_speaker("show_speaker")
{
+ // *TODO Vadim: Get rid of hardcoded values.
rect(LLRect(0, 25, 45, 0));
avatar_icon.name("avatar_icon");
- avatar_icon.visible(false);
avatar_icon.rect(LLRect(0, 25, 25, 0));
-
- //it's an icon for a group in case there is a group chat created
- group_insignia.name("group_icon");
- group_insignia.visible(false);
- group_insignia.rect(LLRect(0, 25, 25, 0));
+ avatar_icon.mouse_opaque(false);
unread_notifications.name("unread");
unread_notifications.rect(LLRect(25, 25, 45, 0));
@@ -211,6 +268,7 @@ LLIMChiclet::Params::Params()
unread_notifications.font_halign(LLFontGL::HCENTER);
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
+ unread_notifications.mouse_opaque(false);
speaker.name("speaker");
speaker.rect(LLRect(45, 25, 65, 0));
@@ -218,25 +276,16 @@ LLIMChiclet::Params::Params()
show_speaker = false;
}
-LLIMChiclet::LLIMChiclet(const Params& p)
-: LLChiclet(p)
-, LLGroupMgrObserver(LLUUID())
-, mAvatarCtrl(NULL)
-, mGroupInsignia(NULL)
+LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
+: LLIMChiclet(p)
+, mChicletIconCtrl(NULL)
, mCounterCtrl(NULL)
, mSpeakerCtrl(NULL)
-, mShowSpeaker(p.show_speaker)
, mPopupMenu(NULL)
{
LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
- mAvatarCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
- addChild(mAvatarCtrl);
-
- //Before setOtherParticipantId() we are UNAWARE which dialog type will it be
- //so keeping both icons for all both p2p and group chat cases
- LLIconCtrl::Params grop_icon_params = p.group_insignia;
- mGroupInsignia = LLUICtrlFactory::create<LLIconCtrl>(grop_icon_params);
- addChild(mGroupInsignia);
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
+ addChild(mChicletIconCtrl);
LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
@@ -249,16 +298,10 @@ LLIMChiclet::LLIMChiclet(const Params& p)
mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
addChild(mSpeakerCtrl);
- setShowSpeaker(getShowSpeaker());
-}
-
-LLIMChiclet::~LLIMChiclet()
-{
- LLGroupMgr::getInstance()->removeObserver(this);
+ setShowSpeaker(p.show_speaker);
}
-
-void LLIMChiclet::setCounter(S32 counter)
+void LLIMP2PChiclet::setCounter(S32 counter)
{
mCounterCtrl->setCounter(counter);
@@ -279,15 +322,9 @@ void LLIMChiclet::setCounter(S32 counter)
}
}
-void LLIMChiclet::onMouseDown()
-{
- LLIMFloater::toggle(getSessionId());
- setCounter(0);
-}
-
-LLRect LLIMChiclet::getRequiredRect()
+LLRect LLIMP2PChiclet::getRequiredRect()
{
- LLRect rect(0, 0, mAvatarCtrl->getRect().getWidth(), 0);
+ LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0);
if(getShowCounter())
{
rect.mRight += mCounterCtrl->getRequiredRect().getWidth();
@@ -299,169 +336,234 @@ LLRect LLIMChiclet::getRequiredRect()
return rect;
}
-void LLIMChiclet::setShowCounter(bool show)
+void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
{
- bool needs_resize = getShowCounter() != show;
-
- LLChiclet::setShowCounter(show);
- mCounterCtrl->setVisible(getShowCounter());
-
- if(needs_resize)
- {
- onChicletSizeChanged();
- }
+ LLIMChiclet::setOtherParticipantId(other_participant_id);
+ mChicletIconCtrl->setValue(getOtherParticipantId());
}
-
-void LLIMChiclet::setSessionId(const LLUUID& session_id)
+void LLIMP2PChiclet::updateMenuItems()
{
- LLChiclet::setSessionId(session_id);
+ if(!mPopupMenu)
+ return;
+ if(getSessionId().isNull())
+ return;
- //for a group chat session_id = group_id
- LLFloaterIMPanel* im = LLIMMgr::getInstance()->findFloaterBySession(session_id);
- if (!im) return; //should never happen
-
- EInstantMessage type = im->getDialogType();
- if (type == IM_SESSION_INVITE || type == IM_SESSION_GROUP_START)
- {
- if (!gAgent.isInGroup(session_id)) return;
+ bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
- if (mGroupInsignia) {
- LLGroupMgr* grp_mgr = LLGroupMgr::getInstance();
- LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id);
- if (group_data && group_data->mInsigniaID.notNull())
- {
- mGroupInsignia->setVisible(TRUE);
- mGroupInsignia->setValue(group_data->mInsigniaID);
- }
- else
- {
- mID = session_id; //needed for LLGroupMgrObserver
- grp_mgr->addObserver(this);
- grp_mgr->sendGroupPropertiesRequest(session_id);
- }
- }
- }
+ mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
+ mPopupMenu->getChild<LLUICtrl>("Remove Friend")->setEnabled(is_friend);
}
-void LLIMChiclet::setIMSessionName(const std::string& name)
+BOOL LLIMP2PChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- setToolTip(name);
+ if(!mPopupMenu)
+ {
+ createPopupMenu();
+ }
+
+ if (mPopupMenu)
+ {
+ updateMenuItems();
+ mPopupMenu->arrangeAndClear();
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+
+ return TRUE;
}
-//session id should be set before calling this
-void LLIMChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
+void LLIMP2PChiclet::createPopupMenu()
{
- llassert(getSessionId().notNull());
+ if(mPopupMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+ if(getSessionId().isNull())
+ {
+ return;
+ }
- LLFloaterIMPanel*floater = gIMMgr->findFloaterBySession(getSessionId());
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2));
- //all alive sessions have alive floater, haven't they?
- llassert(floater);
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
- mOtherParticipantId = other_participant_id;
+void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string level = user_data.asString();
+ LLUUID other_participant_id = getOtherParticipantId();
- if (mAvatarCtrl && floater->getDialogType() == IM_NOTHING_SPECIAL)
+ if("profile" == level)
{
- mAvatarCtrl->setVisible(TRUE);
- mAvatarCtrl->setValue(other_participant_id);
+ LLAvatarActions::showProfile(other_participant_id);
+ }
+ else if("im" == level)
+ {
+ LLAvatarActions::startIM(other_participant_id);
+ }
+ else if("add" == level)
+ {
+ LLAvatarActions::requestFriendshipDialog(other_participant_id);
}
}
-
-void LLIMChiclet::changed(LLGroupChange gc)
+void LLIMP2PChiclet::setShowSpeaker(bool show)
{
- LLSD group_insignia = mGroupInsignia->getValue();
- if (group_insignia.isUUID() && group_insignia.asUUID().notNull()) return;
+ LLIMChiclet::setShowSpeaker(show);
- if (GC_PROPERTIES == gc)
+ bool needs_resize = getShowSpeaker() != show;
+ mSpeakerCtrl->setVisible(getShowSpeaker());
+ if(needs_resize)
{
- LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId());
- if (group_data && group_data->mInsigniaID.notNull())
- {
- mGroupInsignia->setVisible(TRUE);
- mGroupInsignia->setValue(group_data->mInsigniaID);
- }
+ onChicletSizeChanged();
}
}
-LLUUID LLIMChiclet::getOtherParticipantId()
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMGroupChiclet::Params::Params()
+: group_icon("group_icon")
{
- return mOtherParticipantId;
+ rect(LLRect(0, 25, 45, 0));
+
+ group_icon.name("group_icon");
+ group_icon.rect(LLRect(0, 25, 25, 0));
+
+ unread_notifications.name("unread");
+ unread_notifications.rect(LLRect(25, 25, 45, 0));
+ unread_notifications.font(LLFontGL::getFontSansSerif());
+ unread_notifications.font_halign(LLFontGL::HCENTER);
+ unread_notifications.v_pad(5);
+ unread_notifications.text_color(LLColor4::white);
+
+ speaker.name("speaker");
+ speaker.rect(LLRect(45, 25, 65, 0));
+
+ show_speaker = false;
}
-void LLIMChiclet::updateMenuItems()
+LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
+: LLIMChiclet(p)
+, LLGroupMgrObserver(LLUUID::null)
+, mChicletIconCtrl(NULL)
+, mCounterCtrl(NULL)
+, mSpeakerCtrl(NULL)
+, mPopupMenu(NULL)
{
- if(!mPopupMenu)
- return;
- if(getSessionId().isNull())
- return;
+ LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);
+ addChild(mChicletIconCtrl);
- if(P2P_MENU_NAME == mPopupMenu->getName())
- {
- bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
- mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
- mPopupMenu->getChild<LLUICtrl>("Remove Friend")->setEnabled(is_friend);
- }
+ setCounter(getCounter());
+ setShowCounter(getShowCounter());
+
+ LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
+ mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
+ addChild(mSpeakerCtrl);
+
+ setShowSpeaker(p.show_speaker);
}
-BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+LLIMGroupChiclet::~LLIMGroupChiclet()
{
- onMouseDown();
- return LLChiclet::handleMouseDown(x, y, mask);
+ LLGroupMgr::getInstance()->removeObserver(this);
}
-void LLIMChiclet::setShowSpeaker(bool show)
+void LLIMGroupChiclet::setCounter(S32 counter)
{
- bool needs_resize = getShowSpeaker() != show;
-
- mShowSpeaker = show;
- mSpeakerCtrl->setVisible(getShowSpeaker());
+ mCounterCtrl->setCounter(counter);
- if(needs_resize)
+ if(getShowCounter())
{
- onChicletSizeChanged();
+ LLRect counter_rect = mCounterCtrl->getRect();
+ LLRect required_rect = mCounterCtrl->getRequiredRect();
+ bool needs_resize = required_rect.getWidth() != counter_rect.getWidth();
+
+ if(needs_resize)
+ {
+ counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth();
+ mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight());
+ mCounterCtrl->setRect(counter_rect);
+
+ onChicletSizeChanged();
+ }
}
}
-void LLIMChiclet::draw()
+LLRect LLIMGroupChiclet::getRequiredRect()
{
- LLUICtrl::draw();
+ LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0);
+ if(getShowCounter())
+ {
+ rect.mRight += mCounterCtrl->getRequiredRect().getWidth();
+ }
+ if(getShowSpeaker())
+ {
+ rect.mRight += mSpeakerCtrl->getRect().getWidth();
+ }
+ return rect;
+}
- //if we have a docked floater, we want to position it relative to us
- LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", getSessionId());
+void LLIMGroupChiclet::setSessionId(const LLUUID& session_id)
+{
+ LLChiclet::setSessionId(session_id);
- if (im_floater && im_floater->isDocked())
+ LLGroupMgr* grp_mgr = LLGroupMgr::getInstance();
+ LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id);
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mChicletIconCtrl->setValue(group_data->mInsigniaID);
+ }
+ else
{
- S32 x, y;
- getParent()->localPointToScreen(getRect().getCenterX(), 0, &x, &y);
- im_floater->translate(x - im_floater->getRect().getCenterX(), 10 - im_floater->getRect().mBottom);
- //set this so the docked floater knows it's been positioned and can now draw
- im_floater->setPositioned(true);
+ if(getSessionId() != mID)
+ {
+ grp_mgr->removeObserver(this);
+ mID = getSessionId();
+ grp_mgr->addObserver(this);
+ }
+ grp_mgr->sendGroupPropertiesRequest(session_id);
}
+}
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
+void LLIMGroupChiclet::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
+ {
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId());
+ if (group_data)
+ {
+ mChicletIconCtrl->setValue(group_data->mInsigniaID);
+ }
+ }
}
-BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if(!mPopupMenu)
+ {
createPopupMenu();
-
- updateMenuItems();
+ }
if (mPopupMenu)
{
mPopupMenu->arrangeAndClear();
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
}
-
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
return TRUE;
}
-void LLIMChiclet::createPopupMenu()
+void LLIMGroupChiclet::createPopupMenu()
{
if(mPopupMenu)
{
@@ -469,55 +571,41 @@ void LLIMChiclet::createPopupMenu()
return;
}
if(getSessionId().isNull())
+ {
return;
-
- LLFloaterIMPanel*floater = gIMMgr->findFloaterBySession(getSessionId());
- if(!floater)
- return;
+ }
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- registrar.add("IMChicletMenu.Action", boost::bind(&LLIMChiclet::onMenuItemClicked, this, _2));
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2));
- switch(floater->getDialogType())
- {
- case IM_SESSION_GROUP_START:
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
- ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- break;
- case IM_NOTHING_SPECIAL:
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
- ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- break;
- default:
- llwarns << "Unexpected dialog type" << llendl;
- break;
- }
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
}
-void LLIMChiclet::onMenuItemClicked(const LLSD& user_data)
+void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)
{
std::string level = user_data.asString();
- LLUUID other_participant_id = getOtherParticipantId();
+ LLUUID group_id = getSessionId();
- if("profile" == level)
+ if("group chat" == level)
{
- LLAvatarActions::showProfile(other_participant_id);
- }
- else if("im" == level)
- {
- LLAvatarActions::startIM(other_participant_id);
- }
- else if("add" == level)
- {
- LLAvatarActions::requestFriendshipDialog(other_participant_id);
+ LLGroupActions::startChat(group_id);
}
- else if("group chat" == level)
+ else if("info" == level)
{
- LLGroupActions::startChat(other_participant_id);
+ LLGroupActions::show(group_id);
}
- else if("info" == level)
+}
+
+void LLIMGroupChiclet::setShowSpeaker(bool show)
+{
+ LLIMChiclet::setShowSpeaker(show);
+
+ bool needs_resize = getShowSpeaker() != show;
+ mSpeakerCtrl->setVisible(getShowSpeaker());
+ if(needs_resize)
{
- LLGroupActions::show(other_participant_id);
+ onChicletSizeChanged();
}
}
@@ -582,6 +670,10 @@ LLChicletPanel::LLChicletPanel(const Params&p)
LLPanel::Params panel_params;
mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this);
+
+ // important for Show/Hide Camera and Move controls menu in bottom tray to work properly
+ mScrollArea->setMouseOpaque(false);
+
addChild(mScrollArea);
}
@@ -972,11 +1064,14 @@ BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+// *TODO Vadim: Move this out of llchiclet.cpp.
+
LLTalkButton::Params::Params()
: speak_button("speak_button")
, show_button("show_button")
, monitor("monitor")
{
+ // *TODO Vadim: move hardcoded labels (!) and other params to XUI.
speak_button.name("left");
speak_button.label("Speak");
speak_button.label_selected("Speak");
@@ -1045,6 +1140,8 @@ LLTalkButton::LLTalkButton(const Params& p)
LLOutputMonitorCtrl::Params monitor_params = p.monitor;
monitor_params.draw_border(false);
monitor_params.rect(monitor_rect);
+ monitor_params.auto_update(true);
+ monitor_params.speaker_id(gAgentID);
mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params);
mSpeakBtn->addChild(mOutputMonitor);
@@ -1056,17 +1153,6 @@ LLTalkButton::~LLTalkButton()
{
}
-void LLTalkButton::draw()
-{
- // Always provide speaking feedback. User can trigger speaking
- // with keyboard or middle-mouse shortcut.
- mOutputMonitor->setPower(gVoiceClient->getCurrentPower(gAgent.getID()));
- mOutputMonitor->setIsTalking( gVoiceClient->getUserPTTState() );
- mSpeakBtn->setToggleState( gVoiceClient->getUserPTTState() );
-
- LLUICtrl::draw();
-}
-
void LLTalkButton::setSpeakBtnToggleState(bool state)
{
mSpeakBtn->setToggleState(state);
@@ -1103,13 +1189,14 @@ void LLTalkButton::onClick_ShowBtn()
rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight());
mPrivateCallPanel->setRect(rect);
- LLAvatarListItem::Params p;
- p.buttons.status = true;
- p.buttons.info = true;
- p.buttons.profile = false;
- p.buttons.locator = true;
- mPrivateCallPanel->addItem(new LLAvatarListItem(p));
+ LLAvatarListItem* item = new LLAvatarListItem();
+ item->showStatus(true);
+ item->showInfoBtn(true);
+ item->showSpeakingIndicator(true);
+ item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE);
+
+ mPrivateCallPanel->addItem(item);
mPrivateCallPanel->setVisible(TRUE);
mPrivateCallPanel->setFrontmost(TRUE);
@@ -1178,6 +1265,28 @@ LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)
+: LLIconCtrl(p)
+, mDefaultIcon(p.default_icon)
+{
+}
+
+void LLChicletGroupIconCtrl::setValue(const LLSD& value )
+{
+ if(value.asUUID().isNull())
+ {
+ LLIconCtrl::setValue(mDefaultIcon);
+ }
+ else
+ {
+ LLIconCtrl::setValue(value);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
: LLIconCtrl(p)
{
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index b1e73c9d8d..52bd7dbc31 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -95,7 +95,7 @@ private:
};
/*
- * Class for displaying avatar's icon.
+ * Class for displaying avatar's icon in P2P chiclet.
*/
class LLChicletAvatarIconCtrl : public LLAvatarIconCtrl
{
@@ -116,6 +116,36 @@ protected:
friend class LLUICtrlFactory;
};
+/**
+ * Class for displaying group's icon in Group chiclet.
+ */
+class LLChicletGroupIconCtrl : public LLIconCtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params>
+ {
+ Optional<std::string> default_icon;
+
+ Params()
+ : default_icon("default_icon", "default_land_picture.j2c")
+ {
+ };
+ };
+
+ /**
+ * Sets icon, if value is LLUUID::null - default icon will be set.
+ */
+ virtual void setValue(const LLSD& value );
+
+protected:
+
+ LLChicletGroupIconCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+
+ std::string mDefaultIcon;
+};
+
/*
* Class for displaying status of Voice Chat
*/
@@ -231,53 +261,45 @@ private:
chiclet_size_changed_signal_t mChicletSizeChangedSignal;
};
+
/*
-* Implements Instant Message chiclet.
-* IMChiclet displays avatar's icon, number of unread messages(optional)
+* Base class for Instant Message chiclets.
+* IMChiclet displays icon, number of unread messages(optional)
* and voice chat status(optional).
+* Every chiclet should override LLUICtrl::getRequiredRect and return
+* desired width.
*/
-class LLIMChiclet : public LLChiclet, LLGroupMgrObserver
+class LLIMChiclet : public LLChiclet
{
public:
- struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
- {
- Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
-
- Optional<LLIconCtrl::Params> group_insignia;
-
- Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
-
- Optional<LLChicletSpeakerCtrl::Params> speaker;
-
- Optional<bool> show_speaker;
-
- Params();
+ enum EType {
+ TYPE_UNKNOWN,
+ TYPE_IM,
+ TYPE_GROUP
};
-
- /*virtual*/ ~LLIMChiclet();
-
- virtual void setSessionId(const LLUUID& session_id);
+
+ /*virtual*/ ~LLIMChiclet() {};
/*
* Sets IM session name. This name will be displayed in chiclet tooltip.
*/
- virtual void setIMSessionName(const std::string& name);
+ virtual void setIMSessionName(const std::string& name) { setToolTip(name); }
/*
* Sets id of person/group user is chatting with.
* Session id should be set before calling this
*/
- virtual void setOtherParticipantId(const LLUUID& other_participant_id);
+ virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; }
/*
* Gets id of person/group user is chatting with.
*/
- virtual LLUUID getOtherParticipantId();
+ virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; }
/*
* Shows/hides voice chat status control.
*/
- virtual void setShowSpeaker(bool show);
+ virtual void setShowSpeaker(bool show) { mShowSpeaker = show; }
/*
* Returns voice chat status control visibility.
@@ -285,27 +307,24 @@ public:
virtual bool getShowSpeaker() {return mShowSpeaker;};
/*
- * Sets number of unread messages. Will update chiclet's width if number text
- * exceeds size of counter and notify it's parent about size change.
- */
- /*virtual*/ void setCounter(S32);
-
- /*
- * Returns number of unread messages.
- */
- /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
-
- /*
- * Shows/hides number of unread messages.
- */
- /*virtual*/ void setShowCounter(bool show);
-
- /*
* Draws border around chiclet.
*/
/*virtual*/ void draw();
/**
+ * Determine whether given ID refers to a group or an IM chat session.
+ *
+ * This is used when we need to chose what IM chiclet (P2P/group)
+ * class to instantiate.
+ *
+ * @param session_id session ID.
+ * @return TYPE_GROUP in case of group chat session,
+ * TYPE_IM in case of P2P session,
+ * TYPE_UNKNOWN otherwise.
+ */
+ static EType getIMSessionType(const LLUUID& session_id);
+
+ /**
* The action taken on mouse down event.
*
* Made public so that it can be triggered from outside
@@ -313,52 +332,13 @@ public:
*/
void onMouseDown();
- /*
- * Returns rect, required to display chiclet.
- * Width is the only valid value.
- */
- /*virtual*/ LLRect getRequiredRect();
-
- /** comes from LLGroupMgrObserver */
- virtual void changed(LLGroupChange gc);
-
protected:
- LLIMChiclet(const Params& p);
- friend class LLUICtrlFactory;
-
- /*
- * Creates chiclet popup menu. Will create P2P or Group IM Chat menu
- * based on other participant's id.
- */
- virtual void createPopupMenu();
-
- /*
- * Processes clicks on chiclet popup menu.
- */
- virtual void onMenuItemClicked(const LLSD& user_data);
-
- /*
- * Enables/disables menus based on relationship with other participant.
- */
- virtual void updateMenuItems();
-
- /*
- * Displays popup menu.
- */
- /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ LLIMChiclet(const LLChiclet::Params& p);
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
protected:
- LLChicletAvatarIconCtrl* mAvatarCtrl;
-
- /** the icon of a group in case of group chat */
- LLIconCtrl* mGroupInsignia;
- LLChicletNotificationCounterCtrl* mCounterCtrl;
- LLChicletSpeakerCtrl* mSpeakerCtrl;
-
- LLMenuGL* mPopupMenu;
bool mShowSpeaker;
@@ -387,6 +367,160 @@ public:
sFindChicletsSignal;
};
+/**
+ * Implements P2P chiclet.
+ */
+class LLIMP2PChiclet : public LLIMChiclet
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ {
+ Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ Optional<bool> show_speaker;
+
+ Params();
+ };
+
+ /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id);
+
+ /*virtual*/ void setShowSpeaker(bool show);
+
+ /*
+ * Sets number of unread messages. Will update chiclet's width if number text
+ * exceeds size of counter and notify it's parent about size change.
+ */
+ /*virtual*/ void setCounter(S32);
+
+ /*
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+ /*
+ * Returns rect, required to display chiclet.
+ * Width is the only valid value.
+ */
+ /*virtual*/ LLRect getRequiredRect();
+
+protected:
+ LLIMP2PChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /*
+ * Creates chiclet popup menu. Will create P2P or Group IM Chat menu
+ * based on other participant's id.
+ */
+ virtual void createPopupMenu();
+
+ /*
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /*
+ * Displays popup menu.
+ */
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ /*
+ * Enables/disables menus based on relationship with other participant.
+ */
+ virtual void updateMenuItems();
+
+private:
+
+ LLChicletAvatarIconCtrl* mChicletIconCtrl;
+ LLChicletNotificationCounterCtrl* mCounterCtrl;
+ LLChicletSpeakerCtrl* mSpeakerCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
+/**
+ * Implements Group chat chiclet.
+ */
+class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ {
+ Optional<LLChicletGroupIconCtrl::Params> group_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ Optional<bool> show_speaker;
+
+ Params();
+ };
+
+ /**
+ * Sets session id.
+ * Session ID for group chat is actually Group ID.
+ */
+ /*virtual*/ void setSessionId(const LLUUID& session_id);
+
+ /**
+ * Callback for LLGroupMgrObserver, we get this when group data is available or changed.
+ * Sets group icon.
+ */
+ /*virtual*/ void changed(LLGroupChange gc);
+
+ /*virtual*/ void setShowSpeaker(bool show);
+
+ /*
+ * Sets number of unread messages. Will update chiclet's width if number text
+ * exceeds size of counter and notify it's parent about size change.
+ */
+ /*virtual*/ void setCounter(S32);
+
+ /*
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+ /*
+ * Returns rect, required to display chiclet.
+ * Width is the only valid value.
+ */
+ /*virtual*/ LLRect getRequiredRect();
+
+ ~LLIMGroupChiclet();
+
+protected:
+ LLIMGroupChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /*
+ * Creates chiclet popup menu. Will create P2P or Group IM Chat menu
+ * based on other participant's id.
+ */
+ virtual void createPopupMenu();
+
+ /*
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /*
+ * Displays popup menu.
+ */
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+private:
+
+ LLChicletGroupIconCtrl* mChicletIconCtrl;
+ LLChicletNotificationCounterCtrl* mCounterCtrl;
+ LLChicletSpeakerCtrl* mSpeakerCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
/*
* Implements notification chiclet. Used to display total amount of unread messages
* across all IM sessions, total amount of system notifications.
@@ -421,6 +555,7 @@ public:
void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); }
void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); }
void updateUreadIMNotifications();
+ void setToggleState(BOOL toggled);
protected:
LLNotificationChiclet(const Params& p);
@@ -645,7 +780,6 @@ public:
/*virtual*/ ~LLTalkButton();
- /*virtual*/ void draw();
void setSpeakBtnToggleState(bool state);
protected:
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 31c2d93c05..113f4c2c54 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -197,6 +197,7 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
// assumes GL state is set for 2D
void LLColorSwatchCtrl::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
mBorder->setKeyboardFocusHighlight(hasFocus());
// Draw border
LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
@@ -232,15 +233,15 @@ void LLColorSwatchCtrl::draw()
{
gl_rect_2d_checkerboard( interior );
}
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image);
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image, LLColor4::white % alpha);
fallback_image->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
else
{
// Draw grey and an X
- gl_rect_2d(interior, LLColor4::grey, TRUE);
+ gl_rect_2d(interior, LLColor4::grey % alpha, TRUE);
- gl_draw_x(interior, LLColor4::black);
+ gl_draw_x(interior, LLColor4::black % alpha);
}
}
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index a04182a910..af6488388a 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -38,12 +38,14 @@
// system includes
#include <boost/tokenizer.hpp>
+#define THROTTLE_PERIOD 15 // required secs between throttled commands
+
//---------------------------------------------------------------------------
// Underlying registry for command handlers, not directly accessible.
//---------------------------------------------------------------------------
struct LLCommandHandlerInfo
{
- bool mRequireTrustedBrowser;
+ LLCommandHandler::EUntrustedAccess mUntrustedBrowserAccess;
LLCommandHandler* mHandler; // safe, all of these are static objects
};
@@ -51,7 +53,9 @@ class LLCommandHandlerRegistry
{
public:
static LLCommandHandlerRegistry& instance();
- void add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler);
+ void add(const char* cmd,
+ LLCommandHandler::EUntrustedAccess untrusted_access,
+ LLCommandHandler* handler);
bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
@@ -72,10 +76,12 @@ LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance()
return instance;
}
-void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler)
+void LLCommandHandlerRegistry::add(const char* cmd,
+ LLCommandHandler::EUntrustedAccess untrusted_access,
+ LLCommandHandler* handler)
{
LLCommandHandlerInfo info;
- info.mRequireTrustedBrowser = require_trusted_browser;
+ info.mUntrustedBrowserAccess = untrusted_access;
info.mHandler = handler;
mMap[cmd] = info;
@@ -87,15 +93,37 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
LLMediaCtrl* web,
bool trusted_browser)
{
+ static F64 last_throttle_time = 0.0;
+ F64 cur_time = 0.0;
std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd);
if (it == mMap.end()) return false;
const LLCommandHandlerInfo& info = it->second;
- if (!trusted_browser && info.mRequireTrustedBrowser)
+ if (!trusted_browser)
{
- // block request from external browser, but report as
- // "handled" because it was well formatted.
- LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
- return true;
+ switch (info.mUntrustedBrowserAccess)
+ {
+ case LLCommandHandler::UNTRUSTED_ALLOW:
+ // fall through and let the command be handled
+ break;
+
+ case LLCommandHandler::UNTRUSTED_BLOCK:
+ // block request from external browser, but report as
+ // "handled" because it was well formatted.
+ LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
+ return true;
+
+ case LLCommandHandler::UNTRUSTED_THROTTLE:
+ cur_time = LLTimer::getElapsedSeconds();
+ if (cur_time < last_throttle_time + THROTTLE_PERIOD)
+ {
+ // block request from external browser if it happened
+ // within THROTTLE_PERIOD secs of the last command
+ LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
+ return true;
+ }
+ last_throttle_time = cur_time;
+ break;
+ }
}
if (!info.mHandler) return false;
return info.mHandler->handle(params, query_map, web);
@@ -106,10 +134,9 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
//---------------------------------------------------------------------------
LLCommandHandler::LLCommandHandler(const char* cmd,
- bool require_trusted_browser)
+ EUntrustedAccess untrusted_access)
{
- LLCommandHandlerRegistry::instance().add(
- cmd, require_trusted_browser, this);
+ LLCommandHandlerRegistry::instance().add(cmd, untrusted_access, this);
}
LLCommandHandler::~LLCommandHandler()
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index 5cb3ee73d4..1bae6d9414 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -43,7 +43,7 @@ public:
// Inform the system you handle commands starting
// with "foo" and they are only allowed from
// "trusted" (pointed at Linden content) browsers
- LLFooHandler() : LLCommandHandler("foo", true) { }
+ LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
@@ -65,7 +65,14 @@ class LLMediaCtrl;
class LLCommandHandler
{
public:
- LLCommandHandler(const char* command, bool allow_from_untrusted_browser);
+ enum EUntrustedAccess
+ {
+ UNTRUSTED_ALLOW, // allow commands from untrusted browsers
+ UNTRUSTED_BLOCK, // ignore commands from untrusted browsers
+ UNTRUSTED_THROTTLE // allow untrusted, but only a few per min.
+ };
+
+ LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
// Automatically registers object to get called when
// command is executed. All commands can be processed
// in links from LLMediaCtrl, but some (like teleport)
diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp
index 00ffff79a8..225f177546 100644
--- a/indra/newview/llconfirmationmanager.cpp
+++ b/indra/newview/llconfirmationmanager.cpp
@@ -37,8 +37,7 @@
#include "lluictrlfactory.h"
// viewer includes
-#include "llviewerwindow.h"
-#include "lllineeditor.h"
+#include "llnotifications.h"
#include "llstring.h"
LLConfirmationManager::ListenerBase::~ListenerBase()
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index b406300a38..8b06947c4e 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -32,16 +32,18 @@
#include "llviewerprecompiledheaders.h"
-#include "indra_constants.h"
#include "llfasttimerview.h"
+
#include "llviewerwindow.h"
#include "llrect.h"
#include "llerror.h"
#include "llgl.h"
#include "llrender.h"
+#include "lllocalcliprect.h"
#include "llmath.h"
#include "llfontgl.h"
#include "llsdserialize.h"
+#include "lltooltip.h"
#include "llappviewer.h"
#include "llviewertexturelist.h"
@@ -242,15 +244,20 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
}
-BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
{
// tooltips for timer bars
if (mHoverTimer)
{
- localRectToScreen(mToolTipRect, sticky_rect_screen);
- msg = mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex);
+ LLRect screen_rect;
+ localRectToScreen(mToolTipRect, &screen_rect);
+
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex))
+ .sticky_rect(screen_rect));
+
return TRUE;
}
}
@@ -262,11 +269,11 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* stic
LLFastTimer::NamedTimer* idp = getLegendID(y);
if (idp)
{
- msg = idp->getToolTip();
+ LLToolTipMgr::instance().show(idp->getToolTip());
+
return TRUE;
}
}
-
}
return FALSE;
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index f301888984..97e4e94460 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -57,7 +57,7 @@ public:
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual void draw();
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 7ad60232c7..ef71e35254 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -42,6 +42,7 @@
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llmenugl.h"
+#include "lltooltip.h"
#include "llagent.h"
#include "llclipboard.h"
@@ -55,6 +56,7 @@
#include "llviewerinventory.h"
#include "llviewermenu.h"
#include "llviewermenu.h"
+#include "lltooldraganddrop.h"
static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar");
@@ -73,6 +75,7 @@ public:
, mLoaded(false) {}
void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
+ const LLUUID& getLandmarkId() const { return mLandmarkID; }
const std::string& getSLURL()
{
@@ -120,18 +123,26 @@ class LLFavoriteLandmarkButton : public LLButton
{
public:
- BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)
+ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect)
{
- if(LLUI::sShowXUINames)
+ LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
+ return TRUE;
+ }
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ LLFavoritesBarCtrl* fb = dynamic_cast<LLFavoritesBarCtrl*>(getParent());
+
+ if (fb)
{
- return LLButton::handleToolTip(x, y, msg, sticky_rect);
+ fb->handleHover(x, y, mask);
}
- msg = mUrlGetter.getSLURL();
- return TRUE;
+ return LLButton::handleHover(x, y, mask);
}
void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
+ const LLUUID& getLandmarkId() const { return mUrlGetter.getLandmarkId(); }
protected:
LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {}
@@ -141,6 +152,33 @@ private:
LLSLURLGetter mUrlGetter;
};
+class LLFavoritesToggleableMenu : public LLToggleableMenu
+{
+public:
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ if (fb)
+ {
+ fb->handleHover(x, y, mask);
+ }
+
+ return LLToggleableMenu::handleHover(x, y, mask);
+ }
+
+ void initFavoritesBarPointer(LLFavoritesBarCtrl* fb) { this->fb = fb; }
+
+protected:
+ LLFavoritesToggleableMenu(const LLToggleableMenu::Params& p):
+ LLToggleableMenu(p)
+ {
+ }
+
+ friend class LLUICtrlFactory;
+
+private:
+ LLFavoritesBarCtrl* fb;
+};
+
/**
* This class is needed to override LLMenuItemCallGL default handleToolTip function and
* show SLURL as button tooltip.
@@ -151,19 +189,26 @@ private:
class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL
{
public:
- BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)
+ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect)
{
- if(LLUI::sShowXUINames)
- {
- return LLMenuItemCallGL::handleToolTip(x, y, msg, sticky_rect);
- }
-
- msg = mUrlGetter.getSLURL();
+ LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
return TRUE;
}
void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
+ {
+ mMouseDownSignal(this, x, y, mask);
+ return LLMenuItemCallGL::handleMouseDown(x, y, mask);
+ }
+
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+ {
+ mMouseUpSignal(this, x, y, mask);
+ return LLMenuItemCallGL::handleMouseUp(x, y, mask);
+ }
+
protected:
LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {}
@@ -173,6 +218,36 @@ private:
LLSLURLGetter mUrlGetter;
};
+/**
+ * This class is needed to update an item being copied to the favorites folder
+ * with a sort field value (required to save favorites bar's tabs order).
+ * See method handleNewFavoriteDragAndDrop for more details on how this class is used.
+ */
+class LLItemCopiedCallback : public LLInventoryCallback
+{
+public:
+ LLItemCopiedCallback(S32 sortField): mSortField(sortField) {}
+
+ virtual void fire(const LLUUID& inv_item)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item);
+
+ if (item)
+ {
+ item->setSortField(mSortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+
+ LLView::getWindow()->setCursor(UI_CURSOR_ARROW);
+ }
+
+private:
+ S32 mSortField;
+};
// updateButtons's helper
struct LLFavoritesSort
@@ -181,6 +256,14 @@ struct LLFavoritesSort
// TODO - made it customizible using gSavedSettings
bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)
{
+ S32 sortField1 = a->getSortField();
+ S32 sortField2 = b->getSortField();
+
+ if (!(sortField1 < 0 && sortField2 < 0))
+ {
+ return sortField2 > sortField1;
+ }
+
time_t first_create = a->getCreationDate();
time_t second_create = b->getCreationDate();
if (first_create == second_create)
@@ -239,29 +322,34 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_LANDMARK:
{
// Copy the item into the favorites folder (if it's not already there).
- LLInventoryItem *item = (LLInventoryItem *)cargo_data;
- LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
- if (item->getParentUUID() == favorites_id)
+ LLInventoryItem *item = (LLInventoryItem *)cargo_data;
+
+ // check if we are dragging an existing item from the favorites bar
+ if (item && mDragItemId == item->getUUID())
{
- llwarns << "Attemt to copy a favorite item into the same folder." << llendl;
- break;
+ *accept = ACCEPT_YES_SINGLE;
+
+ if (drop)
+ {
+ handleExistingFavoriteDragAndDrop(x, y);
+ }
}
+ else
+ {
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ if (item->getParentUUID() == favorites_id)
+ {
+ llwarns << "Attemt to copy a favorite item into the same folder." << llendl;
+ break;
+ }
- *accept = ACCEPT_YES_COPY_SINGLE;
+ *accept = ACCEPT_YES_COPY_SINGLE;
- if (drop)
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- favorites_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
-
- llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
+ if (drop)
+ {
+ handleNewFavoriteDragAndDrop(item, favorites_id, x, y);
+ }
}
-
}
break;
default:
@@ -271,6 +359,79 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return TRUE;
}
+void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
+{
+ LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y));
+
+ if (dest)
+ {
+ updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId());
+ }
+ else
+ {
+ mItems.push_back(gInventory.getItem(mDragItemId));
+ }
+
+ saveItemsOrder(mItems);
+
+ LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*) mPopupMenuHandle.get();
+
+ if (menu && menu->getVisible())
+ {
+ menu->setVisible(FALSE);
+ showDropDownMenu();
+ }
+
+ mDragItemId = LLUUID::null;
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+}
+
+void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y)
+{
+ LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y));
+
+ if (dest)
+ {
+ insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
+ }
+ else
+ {
+ mItems.push_back(gInventory.getItem(item->getUUID()));
+ }
+
+ int sortField = 0;
+ LLPointer<LLItemCopiedCallback> cb;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i)
+ {
+ LLViewerInventoryItem* currItem = *i;
+
+ if (currItem->getUUID() == item->getUUID())
+ {
+ cb = new LLItemCopiedCallback(++sortField);
+ }
+ else
+ {
+ currItem->setSortField(++sortField);
+ currItem->setComplete(TRUE);
+ currItem->updateServer(FALSE);
+
+ gInventory.updateItem(currItem);
+ }
+ }
+
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ favorites_id,
+ std::string(),
+ cb);
+
+ llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
+}
+
//virtual
void LLFavoritesBarCtrl::changed(U32 mask)
{
@@ -311,9 +472,9 @@ LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode()
void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
{
- LLInventoryModel::item_array_t items;
+ mItems.clear();
- if (!collectFavoriteItems(items))
+ if (!collectFavoriteItems(mItems))
{
return;
}
@@ -331,7 +492,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
const S32 buttonVGap = 2;
- S32 count = items.count();
+ S32 count = mItems.count();
const S32 buttonHPad = LLUI::sSettingGroups["config"]->getS32("ButtonHPad");
const S32 chevron_button_width = mFont->getWidth(">>") + buttonHPad * 2;
@@ -369,7 +530,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
S32 i;
for (i = 0; i < mFirstDropDownItem; ++i)
{
- if (mItemNamesCache.get(i) != items.get(i)->getName())
+ if (mItemNamesCache.get(i) != mItems.get(i)->getName())
{
break;
}
@@ -387,7 +548,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
mItemNamesCache.clear();
for (S32 i = 0; i < mFirstDropDownItem; i++)
{
- mItemNamesCache.put(items.get(i)->getName());
+ mItemNamesCache.put(mItems.get(i)->getName());
}
// Rebuild the buttons only
@@ -404,7 +565,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
}
}
- createButtons(items, buttonXMLNode, buttonWidth, buttonHGap);
+ createButtons(mItems, buttonXMLNode, buttonWidth, buttonHGap);
}
// Chevron button
@@ -467,9 +628,9 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite
{
S32 curr_x = buttonHGap;
// Adding buttons
- for(S32 i = mFirstDropDownItem -1; i >= 0; i--)
+ for(S32 i = mFirstDropDownItem -1, j = 0; i >= 0; i--)
{
- LLInventoryItem* item = items.get(i);
+ LLViewerInventoryItem* item = items.get(j++);
LLFavoriteLandmarkButton* fav_btn = LLUICtrlFactory::defaultBuilder<LLFavoriteLandmarkButton>(buttonXMLNode, this, NULL);
if (NULL == fav_btn)
@@ -488,6 +649,10 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite
fav_btn->setToolTip(item->getName());
fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 ));
+
+ fav_btn->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
+ fav_btn->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
+
sendChildToBack(fav_btn);
curr_x += buttonWidth + buttonHGap;
@@ -521,6 +686,15 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it
std::sort(items.begin(), items.end(), LLFavoritesSort());
+ if (needToSaveItemsOrder(items))
+ {
+ S32 sortField = 0;
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ (*i)->setSortField(++sortField);
+ }
+ }
+
return TRUE;
}
@@ -528,7 +702,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
if (mPopupMenuHandle.isDead())
{
- LLToggleableMenu::Params menu_p;
+ LLFavoritesToggleableMenu::Params menu_p;
menu_p.name("favorites menu");
menu_p.can_tear_off(false);
menu_p.visible(false);
@@ -536,26 +710,26 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu_p.max_scrollable_items = 10;
menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
- LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p);
-
+ LLFavoritesToggleableMenu* menu = LLUICtrlFactory::create<LLFavoritesToggleableMenu>(menu_p);
+ menu->initFavoritesBarPointer(this);
mPopupMenuHandle = menu->getHandle();
}
- LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get();
+ LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*)mPopupMenuHandle.get();
if(menu)
{
if (!menu->toggleVisibility())
return;
- LLInventoryModel::item_array_t items;
+ mItems.clear();
- if (!collectFavoriteItems(items))
+ if (!collectFavoriteItems(mItems))
{
return;
}
- S32 count = items.count();
+ S32 count = mItems.count();
// Check it there are changed items, since last call
if (mItemNamesCache.size() == count)
@@ -563,7 +737,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
S32 i;
for (i = mFirstDropDownItem; i < count; i++)
{
- if (mItemNamesCache.get(i) != items.get(i)->getName())
+ if (mItemNamesCache.get(i) != mItems.get(i)->getName())
{
break;
}
@@ -587,7 +761,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
for (S32 i = mFirstDropDownItem; i < count; i++)
{
- mItemNamesCache.put(items.get(i)->getName());
+ mItemNamesCache.put(mItems.get(i)->getName());
}
}
@@ -598,17 +772,18 @@ void LLFavoritesBarCtrl::showDropDownMenu()
for(S32 i = mFirstDropDownItem; i < count; i++)
{
- LLInventoryItem* item = items.get(i);
+ LLViewerInventoryItem* item = mItems.get(i);
const std::string& item_name = item->getName();
- LLMenuItemCallGL::Params item_params;
+ LLFavoriteLandmarkMenuItem::Params item_params;
item_params.name(item_name);
item_params.label(item_name);
item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params);
menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4));
- menu_item->setLandmarkID(item->getUUID());
+ menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
+ menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
// Check whether item name wider than menu
if (menu_item->getNominalWidth() > max_width)
@@ -644,13 +819,6 @@ void LLFavoritesBarCtrl::showDropDownMenu()
void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id)
{
- LLInventoryModel::item_array_t items;
-
- if (!collectFavoriteItems(items))
- {
- return;
- }
-
// We only have one Inventory, gInventory. Some day this should be better abstracted.
LLInvFVBridgeAction::doAction(item_id,&gInventory);
}
@@ -797,5 +965,135 @@ void LLFavoritesBarCtrl::pastFromClipboard() const
}
}
+void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mDragItemId = id;
+ mStartDrag = TRUE;
+
+ S32 screenX, screenY;
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ LLToolDragAndDrop::getInstance()->setDragStart(screenX, screenY);
+}
+
+void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mDragItemId = LLUUID::null;
+}
+
+BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (mDragItemId != LLUUID::null && mStartDrag)
+ {
+ S32 screenX, screenY;
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ if(LLToolDragAndDrop::getInstance()->isOverThreshold(screenX, screenY))
+ {
+ LLToolDragAndDrop::getInstance()->beginDrag(
+ DAD_LANDMARK, mDragItemId,
+ LLToolDragAndDrop::SOURCE_LIBRARY);
+
+ mStartDrag = FALSE;
+
+ return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask);
+ }
+ }
+
+ return TRUE;
+}
+
+LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y)
+{
+ LLUICtrl* ctrl = 0;
+ S32 screenX, screenY;
+ const child_list_t* list = getChildList();
+
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ // look for a child which contains the point (screenX, screenY) in it's rectangle
+ for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
+ {
+ LLRect rect;
+ localRectToScreen((*i)->getRect(), &rect);
+
+ if (rect.pointInRect(screenX, screenY))
+ {
+ ctrl = dynamic_cast<LLUICtrl*>(*i);
+ break;
+ }
+ }
+
+ return ctrl;
+}
+
+BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array_t& items)
+{
+ BOOL result = FALSE;
+
+ // if there is an item without sort order field set, we need to save items order
+ for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getSortField() < 0)
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void LLFavoritesBarCtrl::saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
+{
+ LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
+ LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
+
+ items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
+}
// EOF
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 824b396add..4cd92d1a58 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -60,6 +60,8 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+
// LLInventoryObserver observer trigger
virtual void changed(U32 mask);
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -73,10 +75,12 @@ protected:
void onButtonClick(LLUUID id);
void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask);
+ void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
+ void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
+
void doToSelected(const LLSD& userdata);
BOOL isClipboardPasteable() const;
void pastFromClipboard() const;
-
void showDropDownMenu();
@@ -94,8 +98,49 @@ protected:
LLRect mChevronRect;
std::string mChevronButtonToolTip;
+
+private:
+ /*
+ * Helper function to make code more readable. It handles all drag and drop
+ * operations of the existing favorites items on the favorites bar.
+ */
+ void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
+
+ /*
+ * Helper function to make code more readable. It handles all drag and drop
+ * operations of the new landmark to the favorites bar.
+ */
+ void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
+
+ // finds a control under the specified LOCAL point
+ LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
+
+ // checks if the current order of the favorites items must be saved
+ BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
+
+ // saves current order of the favorites items
+ void saveItemsOrder(LLInventoryModel::item_array_t& items);
+
+ /*
+ * changes favorites items order by insertion of the item identified by srcItemId
+ * BEFORE the item identified by destItemId. both items must exist in items array.
+ */
+ void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId);
+
+ /*
+ * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
+ * this function assumes that an item identified by insertedItemId doesn't exist in items array.
+ */
+ void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId);
+
+ // finds an item by it's UUID in the items array
+ LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
+
+ BOOL mSkipUpdate;
+ BOOL mStartDrag;
+ LLUUID mDragItemId;
+ LLInventoryModel::item_array_t mItems;
};
#endif // LL_LLFAVORITESBARCTRL_H
-
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 30a5f9f36a..da602d5f27 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -98,24 +98,20 @@ BOOL LLFloaterAbout::postBuild()
LLViewerTextEditor *credits_widget =
getChild<LLViewerTextEditor>("credits_editor", true);
- // For some reason, adding style doesn't work unless this is true.
+ // make sure that we handle hyperlinks in the About text
support_widget->setParseHTML(TRUE);
- // Text styles for release notes hyperlinks
- LLStyle::Params link_style_params;
- link_style_params.color.control = "HTMLLinkColor";
- link_style_params.link_href = get_viewer_release_notes_url();
-
// Version string
std::string version = LLTrans::getString("APP_NAME")
+ llformat(" %d.%d.%d (%d) %s %s (%s)\n",
LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
__DATE__, __TIME__,
gSavedSettings.getString("VersionChannelName").c_str());
- support_widget->appendColoredText(version, FALSE, FALSE, LLUIColorTable::instance().getColor("TextFgReadOnlyColor"));
- support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, link_style_params);
std::string support;
+ support.append(version);
+ support.append("[" + get_viewer_release_notes_url() + " " +
+ LLTrans::getString("ReleaseNotes") + "]");
support.append("\n\n");
#if LL_MSVC
@@ -130,10 +126,6 @@ BOOL LLFloaterAbout::postBuild()
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- LLStyle::Params server_link_style_params;
- server_link_style_params.color.control = "HTMLLinkColor";
- server_link_style_params.link_href = region->getCapability("ServerReleaseNotes");
-
const LLVector3d &pos = gAgent.getPositionGlobal();
LLUIString pos_text = getString("you_are_at");
pos_text.setArg("[POSITION]",
@@ -153,11 +145,9 @@ BOOL LLFloaterAbout::postBuild()
support.append(")\n");
support.append(gLastVersionChannel);
support.append("\n");
-
- support_widget->appendColoredText(support, FALSE, FALSE, LLUIColorTable::instance().getColor("TextFgReadOnlyColor"));
- support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style_params);
-
- support = "\n\n";
+ support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
+ " " + LLTrans::getString("ReleaseNotes") + "]");
+ support.append("\n\n");
}
// *NOTE: Do not translate text like GPU, Graphics Card, etc -
@@ -247,20 +237,20 @@ BOOL LLFloaterAbout::postBuild()
}
- static std::string get_viewer_release_notes_url()
- {
- std::ostringstream version;
- version << LL_VERSION_MAJOR << "."
- << LL_VERSION_MINOR << "."
- << LL_VERSION_PATCH << "."
- << LL_VERSION_BUILD;
+static std::string get_viewer_release_notes_url()
+{
+ std::ostringstream version;
+ version << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH << "."
+ << LL_VERSION_BUILD;
- LLSD query;
- query["channel"] = gSavedSettings.getString("VersionChannelName");
- query["version"] = version.str();
+ LLSD query;
+ query["channel"] = gSavedSettings.getString("VersionChannelName");
+ query["version"] = version.str();
- std::ostringstream url;
- url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
+ std::ostringstream url;
+ url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
- return url.str();
- }
+ return LLWeb::escapeURL(url.str());
+}
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index dec27db74b..c062e6ccf2 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -505,7 +505,7 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
mAnimPreview->requestUpdate();
- LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
+ LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
}
if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview)
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index 94ea20893a..f4c4f38008 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -77,21 +77,11 @@ bool LLFloaterCamera::inAvatarViewMode()
return mCurrMode == CAMERA_CTRL_MODE_AVATAR_VIEW;
}
-void LLFloaterCamera::resetFreeCameraMode()
+void LLFloaterCamera::resetCameraMode()
{
- if (mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA)
- {
- /* Camera Tool can be deselected when we are mouse wheel scrolling into Mouse Look
- In such case we are unable to determine that we will be into Mouse Look view */
- if (mPrevMode == CAMERA_CTRL_MODE_AVATAR_VIEW)
- {
- setMode(CAMERA_CTRL_MODE_ORBIT);
- }
- else
- {
- setMode(mPrevMode);
- }
- }
+ LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
+ if (!floater_camera) return;
+ floater_camera->switchMode(CAMERA_CTRL_MODE_ORBIT);
}
void LLFloaterCamera::update()
diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h
index 04554c6493..1181c443bf 100644
--- a/indra/newview/llfloatercamera.h
+++ b/indra/newview/llfloatercamera.h
@@ -62,9 +62,8 @@ public:
static void toPrevModeIfInAvatarViewMode();
- /* resets free camera mode to the previous mode */
- //*TODO remove, if it won't be used by LLToolCamera::handleDeselect()
- void resetFreeCameraMode();
+ /** resets current camera mode to orbit mode */
+ static void resetCameraMode();
/* determines actual mode and updates ui */
void update();
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 0dee3a1e83..14fb93df61 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -47,7 +47,6 @@
#include "llconsole.h"
#include "llfloateractivespeakers.h"
#include "llfloaterchatterbox.h"
-#include "llfloatermute.h"
#include "llfloaterreg.h"
#include "llfloaterscriptdebug.h"
#include "llkeyboard.h"
@@ -56,6 +55,7 @@
//#include "llresizehandle.h"
#include "llchatbar.h"
#include "llrecentpeople.h"
+#include "llpanelblockedlist.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
@@ -280,7 +280,7 @@ void LLFloaterChat::onClickMute(void *data)
LLMute mute(id);
mute.setFromDisplayName(name);
LLMuteList::getInstance()->add(mute);
- LLFloaterReg::showInstance("mute");
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
//static
diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp
index eb73bd6d8f..0c77d88efb 100644
--- a/indra/newview/llfloaterfriends.cpp
+++ b/indra/newview/llfloaterfriends.cpp
@@ -194,6 +194,7 @@ BOOL LLPanelFriends::postBuild()
mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT);
mFriendsList->setMaximumSelectCallback(boost::bind(&LLPanelFriends::onMaximumSelect));
mFriendsList->setCommitOnSelectionChange(TRUE);
+ mFriendsList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
childSetCommitCallback("friend_list", onSelectName, this);
getChild<LLScrollListCtrl>("friend_list")->setDoubleClickCallback(onClickIM, this);
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 7a88612f1a..b1f40d9d1d 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -82,7 +82,12 @@ void LLFloaterGroupPicker::setPowersMask(U64 powers_mask)
BOOL LLFloaterGroupPicker::postBuild()
{
LLScrollListCtrl* list_ctrl = getChild<LLScrollListCtrl>("group list");
- init_group_list(list_ctrl, gAgent.getGroupID(), mPowersMask);
+ if (list_ctrl)
+ {
+ init_group_list(list_ctrl, gAgent.getGroupID(), mPowersMask);
+ list_ctrl->setDoubleClickCallback(onBtnOK, this);
+ list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP);
+ }
// Remove group "none" from list. Group "none" is added in init_group_list().
// Some UI elements use group "none", we need to manually delete it here.
@@ -100,8 +105,6 @@ BOOL LLFloaterGroupPicker::postBuild()
setDefaultBtn("OK");
- getChild<LLScrollListCtrl>("group list")->setDoubleClickCallback(onBtnOK, this);
-
childEnable("OK");
return TRUE;
@@ -183,7 +186,13 @@ BOOL LLPanelGroups::postBuild()
childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count()));
childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS));
- init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");
+ if (list)
+ {
+ init_group_list(list, gAgent.getGroupID());
+ list->setDoubleClickCallback(onBtnIM, this);
+ list->setContextMenu(LLScrollListCtrl::MENU_GROUP);
+ }
childSetAction("Activate", onBtnActivate, this);
@@ -199,8 +208,6 @@ BOOL LLPanelGroups::postBuild()
setDefaultBtn("IM");
- getChild<LLScrollListCtrl>("group list")->setDoubleClickCallback(onBtnIM, this);
-
reset();
return TRUE;
diff --git a/indra/newview/llfloaterhandler.h b/indra/newview/llfloaterhandler.h
index 31ea80c12c..cd9d8b5377 100644
--- a/indra/newview/llfloaterhandler.h
+++ b/indra/newview/llfloaterhandler.h
@@ -38,7 +38,7 @@ class LLFloaterHandler
: public LLCommandHandler
{
public:
- LLFloaterHandler() : LLCommandHandler("floater", true) { }
+ LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web);
};
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 07dbf98a1e..61568df12e 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -547,7 +547,7 @@ BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask)
mSculptedPreview->refresh();
}
- LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
+ LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
}
if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview)
diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h
index f007697e88..4a12543650 100644
--- a/indra/newview/llfloaterimagepreview.h
+++ b/indra/newview/llfloaterimagepreview.h
@@ -35,6 +35,7 @@
#include "llfloaternamedesc.h"
#include "lldynamictexture.h"
+#include "llpointer.h"
#include "llquaternion.h"
class LLComboBox;
@@ -43,6 +44,7 @@ class LLViewerJointMesh;
class LLVOAvatar;
class LLTextBox;
class LLVertexBuffer;
+class LLVolume;
class LLImagePreviewSculpted : public LLViewerDynamicTexture
{
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 4cd09faaaf..e5f5e8eedb 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1061,6 +1061,7 @@ BOOL LLPanelLandObjects::postBuild()
mOwnerList->sortByColumnIndex(3, FALSE);
childSetCommitCallback("owner list", onCommitList, this);
mOwnerList->setDoubleClickCallback(onDoubleClickOwner, this);
+ mOwnerList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
return TRUE;
}
@@ -2297,11 +2298,17 @@ BOOL LLPanelLandAccess::postBuild()
mListAccess = getChild<LLNameListCtrl>("AccessList");
if (mListAccess)
+ {
mListAccess->sortByColumnIndex(0, TRUE); // ascending
+ mListAccess->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ }
mListBanned = getChild<LLNameListCtrl>("BannedList");
if (mListBanned)
+ {
mListBanned->sortByColumnIndex(0, TRUE); // ascending
+ mListBanned->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ }
return TRUE;
}
diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp
index 44270683a0..88a39a495f 100644
--- a/indra/newview/llfloaterparcel.cpp
+++ b/indra/newview/llfloaterparcel.cpp
@@ -53,7 +53,7 @@ class LLParcelHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLParcelHandler() : LLCommandHandler("parcel", true) { }
+ LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index c47c7b073c..2dc96d1fb3 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -61,6 +61,7 @@
#include "llnavigationbar.h"
#include "llpanellogin.h"
#include "llradiogroup.h"
+#include "llsearchcombobox.h"
#include "llsky.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
@@ -102,6 +103,7 @@
#include "llviewermedia.h"
#include "llpluginclassmedia.h"
+#include <boost/regex.hpp>
//RN temporary includes for resolution switching
#include "llglheaders.h"
@@ -214,6 +216,11 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response
// flag client texture cache for clearing next time the client runs
gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
LLNotifications::instance().add("CacheWillClear");
+
+ LLSearchHistory::getInstance()->clearHistory();
+ LLSearchHistory::getInstance()->save();
+ LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild<LLSearchComboBox>("search_combo_box");
+ search_ctrl->clearHistory();
}
return false;
@@ -515,6 +522,34 @@ void LLFloaterPreference::cancel()
void LLFloaterPreference::onOpen(const LLSD& key)
{
gAgent.sendAgentUserInfoRequest();
+ /////////////////////////// From LLPanelGeneral //////////////////////////
+ // if we have no agent, we can't let them choose anything
+ // if we have an agent, then we only let them choose if they have a choice
+ bool canChoose = gAgent.getID().notNull() &&
+ (gAgent.isMature() || gAgent.isGodlike());
+
+ if (canChoose)
+ {
+
+ // if they're not adult or a god, they shouldn't see the adult selection, so delete it
+ if (!gAgent.isAdult() && !gAgent.isGodlike())
+ {
+ LLComboBox* pMaturityCombo = getChild<LLComboBox>("maturity_desired_combobox");
+ // we're going to remove the adult entry from the combo. This obviously depends
+ // on the order of items in the XML file, but there doesn't seem to be a reasonable
+ // way to depend on the field in XML called 'name'.
+ pMaturityCombo->remove(0);
+ }
+ childSetVisible("maturity_desired_combobox", true);
+ childSetVisible("maturity_desired_prompt", true);
+
+ }
+ else
+ {
+ childSetVisible("maturity_desired_prompt", false);
+ childSetVisible("maturity_desired_combobox", false);
+ }
+
LLPanelLogin::setAlwaysRefresh(true);
refresh();
}
@@ -1344,37 +1379,7 @@ static void applyUIColor(const std::string& color_name, LLUICtrl* ctrl, const LL
//virtual
BOOL LLPanelPreference::postBuild()
{
- if (hasChild("maturity_desired_combobox"))
- {
- /////////////////////////// From LLPanelGeneral //////////////////////////
- // if we have no agent, we can't let them choose anything
- // if we have an agent, then we only let them choose if they have a choice
- bool canChoose = gAgent.getID().notNull() &&
- (gAgent.isMature() || gAgent.isGodlike());
-
- if (canChoose)
- {
- // if they're not adult or a god, they shouldn't see the adult selection, so delete it
- if (!gAgent.isAdult() && !gAgent.isGodlike())
- {
- LLComboBox* pMaturityCombo = getChild<LLComboBox>("maturity_desired_combobox");
- // we're going to remove the adult entry from the combo. This obviously depends
- // on the order of items in the XML file, but there doesn't seem to be a reasonable
- // way to depend on the field in XML called 'name'.
- pMaturityCombo->remove(0);
- }
- childSetVisible("maturity_desired_combobox", true);
- childSetVisible("maturity_desired_textbox", false);
- }
- else
- {
- childSetVisible("maturity_desired_combobox", false);
- std::string selectedItemLabel = getChild<LLComboBox>("maturity_desired_combobox")->getSelectedItemLabel();
- childSetValue("maturity_desired_textbox", selectedItemLabel);
- childSetVisible("maturity_desired_textbox", true);
- }
- }
////////////////////// PanelVoice ///////////////////
if(hasChild("voice_unavailable"))
{
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index b5c36b1083..13a2594c45 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -75,6 +75,7 @@
#include "llimagepng.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
+#include "lllocalcliprect.h"
#include "llresmgr.h" // LLLocale
#include "llvfile.h"
#include "llvfs.h"
diff --git a/indra/newview/llfloatertestinspectors.cpp b/indra/newview/llfloatertestinspectors.cpp
new file mode 100644
index 0000000000..c56586cb95
--- /dev/null
+++ b/indra/newview/llfloatertestinspectors.cpp
@@ -0,0 +1,109 @@
+/**
+* @file llfloatertestinspectors.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatertestinspectors.h"
+
+// Viewer includes
+#include "llstartup.h"
+
+// Linden library includes
+#include "llfloaterreg.h"
+//#include "lluictrlfactory.h"
+
+LLFloaterTestInspectors::LLFloaterTestInspectors(const LLSD& seed)
+: LLFloater(seed)
+{
+ mCommitCallbackRegistrar.add("ShowAvatarInspector",
+ boost::bind(&LLFloaterTestInspectors::showAvatarInspector, this, _1, _2));
+}
+
+LLFloaterTestInspectors::~LLFloaterTestInspectors()
+{}
+
+BOOL LLFloaterTestInspectors::postBuild()
+{
+// getChild<LLUICtrl>("avatar_2d_btn")->setCommitCallback(
+// boost::bind(&LLFloaterTestInspectors::onClickAvatar2D, this));
+ getChild<LLUICtrl>("avatar_3d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickAvatar3D, this));
+ getChild<LLUICtrl>("object_2d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickObject2D, this));
+ getChild<LLUICtrl>("object_3d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickObject3D, this));
+ getChild<LLUICtrl>("group_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickGroup, this));
+ getChild<LLUICtrl>("place_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickPlace, this));
+ getChild<LLUICtrl>("event_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickEvent, this));
+
+ return LLFloater::postBuild();
+}
+
+void LLFloaterTestInspectors::showAvatarInspector(LLUICtrl*, const LLSD& avatar_id)
+{
+ LLUUID id; // defaults to null
+ if (LLStartUp::getStartupState() >= STATE_STARTED)
+ {
+ id = avatar_id.asUUID();
+ }
+ // spawns off mouse position automatically
+ LLFloaterReg::showInstance("inspect_avatar", id);
+}
+
+void LLFloaterTestInspectors::onClickAvatar2D()
+{
+}
+
+void LLFloaterTestInspectors::onClickAvatar3D()
+{
+}
+
+void LLFloaterTestInspectors::onClickObject2D()
+{
+}
+
+void LLFloaterTestInspectors::onClickObject3D()
+{
+}
+
+void LLFloaterTestInspectors::onClickGroup()
+{
+}
+
+void LLFloaterTestInspectors::onClickPlace()
+{
+}
+
+void LLFloaterTestInspectors::onClickEvent()
+{
+}
diff --git a/indra/newview/llfloatertestinspectors.h b/indra/newview/llfloatertestinspectors.h
new file mode 100644
index 0000000000..d2dc2248bb
--- /dev/null
+++ b/indra/newview/llfloatertestinspectors.h
@@ -0,0 +1,64 @@
+/**
+* @file llfloatertestinspectors.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLFLOATERTESTINSPECTORS_H
+#define LLFLOATERTESTINSPECTORS_H
+
+#include "llfloater.h"
+
+class LLSD;
+
+class LLFloaterTestInspectors : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+ // nothing yet
+
+private:
+ // Construction handled by LLFloaterReg
+ LLFloaterTestInspectors(const LLSD& seed);
+ ~LLFloaterTestInspectors();
+
+ /*virtual*/ BOOL postBuild();
+
+ // Button callback to show
+ void showAvatarInspector(LLUICtrl*, const LLSD& avatar_id);
+
+ // Debug function hookups for buttons
+ void onClickAvatar2D();
+ void onClickAvatar3D();
+ void onClickObject2D();
+ void onClickObject3D();
+ void onClickGroup();
+ void onClickPlace();
+ void onClickEvent();
+};
+
+#endif
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index d05c9cb9a7..f334344279 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -725,7 +725,7 @@ void LLFloaterTools::onOpen(const LLSD& key)
mTab->selectTabByName(panel);
}
- gMenuBarView->setItemVisible("BuildTools", TRUE);
+ //gMenuBarView->setItemVisible("BuildTools", TRUE);
}
void LLFloaterTools::onClose()
@@ -755,7 +755,7 @@ void LLFloaterTools::onClose()
// so manually reset tool to default (pie menu tool)
LLToolMgr::getInstance()->getCurrentToolset()->selectFirstTool();
- gMenuBarView->setItemVisible("BuildTools", FALSE);
+ //gMenuBarView->setItemVisible("BuildTools", FALSE);
}
void click_popup_info(void*)
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index f1e499e14b..490929e5a6 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -1183,6 +1183,8 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
// you will automatically fail this time, so we only
// check against items that have passed the filter
S32 must_pass_generation = filter.getMustPassGeneration();
+
+ bool autoopen_folders = (filter.hasFilterString());
// if we have already been filtered against this generation, skip out
if (getCompletedFilterGeneration() >= filter_generation)
@@ -1255,7 +1257,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration()))
{
mMostFilteredDescendantGeneration = filter_generation;
- if (getRoot()->needsAutoSelect())
+ if (getRoot()->needsAutoSelect() && autoopen_folders)
{
(*fit)->setOpenArrangeRecursively(TRUE);
}
@@ -1271,7 +1273,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation))
{
mMostFilteredDescendantGeneration = filter_generation;
- if (getRoot()->needsAutoSelect())
+ if (getRoot()->needsAutoSelect() && autoopen_folders)
{
(*fit)->setOpenArrangeRecursively(TRUE);
}
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 31866c83c8..eec885fd29 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -33,6 +33,7 @@
#define LLFOLDERVIEWITEM_H
#include "llview.h"
+#include "lldarray.h" // *TODO: Eliminate, forward declare
class LLFontGL;
class LLFolderView;
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index bef5f094e3..97b7f3e9ad 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -173,6 +173,15 @@ bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCateg
return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl());
}
+bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const
+{
+ const LLUUID& friendFolderID = findFriendFolderUUIDImpl();
+ if (catID == friendFolderID)
+ return true;
+
+ return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);
+}
+
void LLFriendCardsManager::syncFriendsFolder()
{
//lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent
@@ -305,10 +314,12 @@ void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInve
LLInventoryModel::cat_array_t cats;
LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
- LLParticularBuddyCollector matchFunctor(avatarID);
LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID);
+ if (NULL == friendFolder)
+ return;
+ LLParticularBuddyCollector matchFunctor(avatarID);
LLInventoryModel::cat_array_t subFolders;
subFolders.push_back(friendFolder);
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index 18a6d0ab69..aa391ce2c1 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -77,6 +77,11 @@ public:
bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const;
/**
+ * Checks is the specified category is a Friend folder or any its subfolder
+ */
+ bool isAnyFriendCategory(const LLUUID& catID) const;
+
+ /**
* Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
*/
void syncFriendsFolder();
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 3b3ada46a8..43fbe362d5 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -161,8 +161,6 @@ void LLAgent::renderAutoPilotTarget()
}
}
-extern BOOL gDebugSelect;
-
// Returns true if you got at least one object
void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
{
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 10a17476d9..d1cbe96906 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -51,7 +51,7 @@ class LLGroupHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLGroupHandler() : LLCommandHandler("group", true) { }
+ LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 278fd5b9f6..cddc67cb0a 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -51,6 +51,8 @@ LLGroupList::Params::Params()
LLGroupList::LLGroupList(const Params& p)
: LLAvatarList(p)
{
+ // display a context menu appropriate for a list of group names
+ setContextMenu(LLScrollListCtrl::MENU_GROUP);
}
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
@@ -75,14 +77,20 @@ BOOL LLGroupList::update(const std::string& name_filter)
const LLGroupData& group_data = gAgent.mGroups.get(i);
if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter))
continue;
- addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM);
+ addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM); // ADD_SORTED can only sort by first column anyway
}
+ // Force sorting the list.
+ updateSort();
+
// add "none" to list at top
{
std::string loc_none = LLTrans::getString("GroupsNone");
if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter))
addItem(LLUUID::null, loc_none, highlight_id.isNull(), ADD_TOP);
+
+ // Prevent the "none" item from being sorted.
+ setNeedsSort(false);
}
group_list->selectByValue(highlight_id);
diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp
index 0262e40803..a47477c446 100644
--- a/indra/newview/llimhandler.cpp
+++ b/indra/newview/llimhandler.cpp
@@ -35,6 +35,7 @@
#include "llnotificationhandler.h"
+#include "llagentdata.h"
#include "llbottomtray.h"
#include "llviewercontrol.h"
#include "lltoastimpanel.h"
@@ -77,9 +78,15 @@ void LLIMHandler::processNotification(const LLSD& notify)
{
LLSD substitutions = notification->getSubstitutions();
+ // According to comments in LLIMMgr::addMessage(), if we get message
+ // from ourselves, the sender id is set to null. This fixes EXT-875.
+ LLUUID avatar_id = substitutions["FROM_ID"].asUUID();
+ if (avatar_id.isNull())
+ avatar_id = gAgentID;
+
LLToastIMPanel::Params im_p;
im_p.notification = notification;
- im_p.avatar_id = substitutions["FROM_ID"].asUUID();
+ im_p.avatar_id = avatar_id;
im_p.from = substitutions["FROM"].asString();
im_p.time = substitutions["TIME"].asString();
im_p.message = substitutions["MESSAGE"].asString();
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 9cf3e57e22..0efe9b9849 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -1917,19 +1917,8 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
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.
LLSD args;
- args["REASON"] =
- LLFloaterIM::sErrorStringsMap[error_string];
+ args["REASON"] = LLTrans::getString(error_string);
args["RECIPIENT"] = getTitle();
LLSD payload;
@@ -1948,9 +1937,9 @@ void LLFloaterIMPanel::showSessionEventError(
{
LLSD args;
args["REASON"] =
- LLFloaterIM::sErrorStringsMap[error_string];
+ LLTrans::getString(error_string);
args["EVENT"] =
- LLFloaterIM::sEventStringsMap[event_string];
+ LLTrans::getString(event_string);
args["RECIPIENT"] = getTitle();
LLNotifications::instance().add(
@@ -1964,7 +1953,7 @@ void LLFloaterIMPanel::showSessionForceClose(
LLSD args;
args["NAME"] = getTitle();
- args["REASON"] = LLFloaterIM::sForceCloseSessionMap[reason_string];
+ args["REASON"] = LLTrans::getString(reason_string);
LLSD payload;
payload["session_id"] = mSessionUUID;
@@ -2000,7 +1989,7 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const
LLIMFloater::LLIMFloater(const LLUUID& session_id)
- : LLFloater(session_id),
+ : LLDockableFloater(NULL, session_id),
mControlPanel(NULL),
mSessionID(session_id),
mLastMessageIndex(-1),
@@ -2125,13 +2114,12 @@ BOOL LLIMFloater::postBuild()
childSetCommitCallback("chat_editor", onSendMsg, this);
mHistoryEditor = getChild<LLViewerTextEditor>("im_text");
+ mHistoryEditor->setParseHTML(TRUE);
setTitle(LLIMModel::instance().getName(mSessionID));
setDocked(true);
- mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
-
- return TRUE;
+ return LLDockableFloater::postBuild();
}
@@ -2155,8 +2143,6 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
return self->mControlPanel;
}
-
-const U32 UNDOCK_LEAP_HEIGHT = 12;
const U32 DOCK_ICON_HEIGHT = 6;
//virtual
@@ -2174,20 +2160,6 @@ void LLIMFloater::onFocusLost()
}
}
-
-
-//virtual
-void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
-{
- LLFloater::setDocked(docked);
-
- if (!docked && pop_on_undock)
- {
- // visually pop up a little bit to emphasize the undocking
- translate(0, UNDOCK_LEAP_HEIGHT);
- }
-}
-
void LLIMFloater::onSlide()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
@@ -2216,6 +2188,20 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
floater->updateMessages();
floater->mInputEditor->setFocus(TRUE);
+
+ if (floater->getDockControl() == NULL)
+ {
+ LLView* chiclet =
+ LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLView>(
+ session_id);
+ if (chiclet == NULL)
+ {
+ llerror("Dock chiclet for LLIMFloater doesn't exists", 0);
+ }
+ floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
+ LLDockControl::TOP, floater->isDocked()));
+ }
+
return floater;
}
@@ -2315,18 +2301,3 @@ void LLIMFloater::setTyping(BOOL typing)
{
}
-
-void LLIMFloater::draw()
-{
- //if we are docked, make sure we've been positioned by the chiclet
- if (!isDocked() || mPositioned)
- {
- LLFloater::draw();
-
- if (isDocked())
- {
- mDockTongue->draw( (getRect().getWidth()/2) - mDockTongue->getWidth()/2, -mDockTongue->getHeight());
- }
- }
-}
-
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 284a486b0f..1d69f1567c 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -33,7 +33,7 @@
#ifndef LL_IMPANEL_H
#define LL_IMPANEL_H
-#include "llfloater.h"
+#include "lldockablefloater.h"
#include "lllogchat.h"
#include "lluuid.h"
#include "lldarray.h"
@@ -363,7 +363,7 @@ private:
// Individual IM window that appears at the bottom of the screen,
// optionally "docked" to the bottom tray.
-class LLIMFloater : public LLFloater
+class LLIMFloater : public LLDockableFloater
{
public:
LLIMFloater(const LLUUID& session_id);
@@ -372,18 +372,11 @@ public:
// LLView overrides
/*virtual*/ BOOL postBuild();
-
- // LLView overrides for drawing dock tongue
- /*virtual*/
- void draw();
// Floater should close when user clicks away to other UI area,
// hence causing focus loss.
/*virtual*/ void onFocusLost();
- // LLFloater overrides
- /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
-
// Make IM conversion visible and update the message history
static LLIMFloater* show(const LLUUID& session_id);
@@ -426,7 +419,6 @@ private:
LLViewerTextEditor* mHistoryEditor;
LLLineEditor* mInputEditor;
bool mPositioned;
- LLUIImagePtr mDockTongue;
};
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 1b07c7630f..a58cca1ba4 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -83,14 +83,7 @@ LLIMMgr* gIMMgr = NULL;
// Statics
//
// *FIXME: make these all either UIStrings or Strings
-static std::string sOnlyUserMessage;
-static LLUIString sOfflineMessage;
-static std::string sMutedMessage;
-static LLUIString sInviteMessage;
-std::map<std::string,std::string> LLFloaterIM::sEventStringsMap;
-std::map<std::string,std::string> LLFloaterIM::sErrorStringsMap;
-std::map<std::string,std::string> LLFloaterIM::sForceCloseSessionMap;
std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap;
@@ -108,7 +101,8 @@ void toast_callback(const LLSD& msg){
args["FROM_ID"] = msg["from_id"];
args["SESSION_ID"] = msg["session_id"];
- LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLFloaterChatterBox::onOpen, LLFloaterChatterBox::getInstance(), msg["session_id"].asUUID()));
+ //LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLFloaterChatterBox::onOpen, LLFloaterChatterBox::getInstance(), msg["session_id"].asUUID()));
+ LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::toggle, msg["session_id"].asUUID()));
}
}
@@ -750,101 +744,6 @@ LLUUID LLIMMgr::computeSessionID(
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LLFloaterIM
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-LLFloaterIM::LLFloaterIM()
- : LLMultiFloater(LLSD())
-{
- // autoresize=false is necessary to avoid resizing of the IM window whenever
- // a session is opened or closed (it would otherwise resize the window to match
- // the size of the im-sesssion when they were created. This happens in
- // LLMultiFloater::resizeToContents() when called through LLMultiFloater::addFloater())
- mAutoResize = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im.xml", NULL);
-}
-
-BOOL LLFloaterIM::postBuild()
-{
- // IM session initiation warnings
- sOnlyUserMessage = getString("only_user_message");
- sOfflineMessage = getString("offline_message");
- sMutedMessage = getString("muted_message");
-
- sInviteMessage = getString("invite_message");
-
- if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() )
- {
- sErrorStringsMap["generic"] =
- getString("generic_request_error");
- }
-
- if ( sErrorStringsMap.find("unverified") ==
- sErrorStringsMap.end() )
- {
- sErrorStringsMap["unverified"] =
- getString("insufficient_perms_error");
- }
-
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("no_ability") )
- {
- sErrorStringsMap["no_ability"] =
- getString("no_ability_error");
- }
-
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("muted") )
- {
- sErrorStringsMap["muted"] =
- getString("muted_error");
- }
-
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("not_a_moderator") )
- {
- sErrorStringsMap["not_a_moderator"] =
- getString("not_a_mod_error");
- }
-
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("does not exist") )
- {
- sErrorStringsMap["does not exist"] =
- getString("session_does_not_exist_error");
- }
-
- if ( sEventStringsMap.end() == sEventStringsMap.find("add") )
- {
- sEventStringsMap["add"] =
- getString("add_session_event");
- }
-
- if ( sEventStringsMap.end() == sEventStringsMap.find("message") )
- {
- sEventStringsMap["message"] =
- getString("message_session_event");
- }
-
-
- if ( sForceCloseSessionMap.end() ==
- sForceCloseSessionMap.find("removed") )
- {
- sForceCloseSessionMap["removed"] =
- getString("removed_from_group");
- }
-
- if ( sForceCloseSessionMap.end() ==
- sForceCloseSessionMap.find("no ability") )
- {
- sForceCloseSessionMap["no ability"] =
- getString("close_on_no_ability");
- }
-
- return TRUE;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
@@ -1151,11 +1050,6 @@ LLIMMgr::LLIMMgr() :
mFriendObserver = new LLIMViewFriendObserver(this);
LLAvatarTracker::instance().addObserver(mFriendObserver);
- // *HACK: use floater to initialize string constants from xml file
- // then delete it right away
- LLFloaterIM* dummy_floater = new LLFloaterIM();
- delete dummy_floater;
-
mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
}
@@ -1338,7 +1232,10 @@ S32 LLIMMgr::getNumberOfUnreadIM()
S32 num = 0;
for(it = LLIMModel::sSessionsMap.begin(); it != LLIMModel::sSessionsMap.end(); ++it)
{
- num += (*it).second->mNumUnread;
+ if((*it).first != mBeingRemovedSessionID)
+ {
+ num += (*it).second->mNumUnread;
+ }
}
return num;
@@ -1460,6 +1357,9 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
clearPendingInvitation(session_id);
clearPendingAgentListUpdates(session_id);
}
+
+ // for some purposes storing ID of a sessios that is being removed
+ mBeingRemovedSessionID = session_id;
notifyObserverSessionRemoved(session_id);
//if we don't clear session data on removing the session
@@ -1467,6 +1367,9 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
//creating chiclets only on session created even, we need to handle chiclets creation
//the same way as LLFloaterIMPanels were managed.
LLIMModel::getInstance()->clearSession(session_id);
+
+ // now this session is completely removed
+ mBeingRemovedSessionID.setNull();
}
void LLIMMgr::inviteToSession(
@@ -1800,7 +1703,7 @@ void LLIMMgr::noteOfflineUsers(
S32 count = ids.count();
if(count == 0)
{
- floater->addHistoryLine(sOnlyUserMessage, LLUIColorTable::instance().getColor("SystemChatColor"));
+ floater->addHistoryLine(LLTrans::getString("only_user_message"), LLUIColorTable::instance().getColor("SystemChatColor"));
}
else
{
@@ -1813,7 +1716,7 @@ void LLIMMgr::noteOfflineUsers(
if(info && !info->isOnline()
&& gCacheName->getName(ids.get(i), first, last))
{
- LLUIString offline = sOfflineMessage;
+ LLUIString offline = LLTrans::getString("offline_message");
offline.setArg("[FIRST]", first);
offline.setArg("[LAST]", last);
floater->addHistoryLine(offline, LLUIColorTable::instance().getColor("SystemChatColor"));
@@ -1839,7 +1742,7 @@ void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater,
{
if( ml->isMuted(ids.get(i)) )
{
- LLUIString muted = sMutedMessage;
+ LLUIString muted = LLTrans::getString("muted_message");
floater->addHistoryLine(muted);
break;
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index ce6f0394dd..4eb743b1ac 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -44,7 +44,6 @@ class LLFloaterChatterBox;
class LLUUID;
class LLFloaterIMPanel;
class LLFriendObserver;
-class LLFloaterIM;
class LLIMModel : public LLSingleton<LLIMModel>
{
@@ -264,18 +263,9 @@ private:
LLSD mPendingInvitations;
LLSD mPendingAgentListUpdates;
-};
-
-
-class LLFloaterIM : public LLMultiFloater
-{
-public:
- LLFloaterIM();
- /*virtual*/ BOOL postBuild();
-
- static std::map<std::string,std::string> sEventStringsMap;
- static std::map<std::string,std::string> sErrorStringsMap;
- static std::map<std::string,std::string> sForceCloseSessionMap;
+ // ID of a session that is being removed: observers are already told
+ // that this session is being removed, but it is still present in the sessions' map
+ LLUUID mBeingRemovedSessionID;
};
class LLIncomingCallDialog : public LLModalDialog
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 5bb96f0469..72f89d2e72 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -36,22 +36,72 @@
// viewer files
#include "llagentdata.h"
#include "llavataractions.h"
+#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
// linden libraries
+#include "lltooltip.h" // positionViewNearMouse()
#include "lluictrl.h"
+// This object represents a pending request for avatar properties information
+class LLFetchAvatarData : public LLAvatarPropertiesObserver
+{
+public:
+ // If the inspector closes it will delete the pending request object, so the
+ // inspector pointer will be valid for the lifetime of this object
+ LLFetchAvatarData(const LLUUID& avatar_id, LLInspectAvatar* inspector)
+ : mAvatarID(avatar_id),
+ mInspector(inspector)
+ {
+ LLAvatarPropertiesProcessor* processor =
+ LLAvatarPropertiesProcessor::getInstance();
+ // register ourselves as an observer
+ processor->addObserver(mAvatarID, this);
+ // send a request (duplicates will be suppressed inside the avatar
+ // properties processor)
+ processor->sendAvatarPropertiesRequest(mAvatarID);
+ }
+
+ ~LLFetchAvatarData()
+ {
+ // remove ourselves as an observer
+ LLAvatarPropertiesProcessor::getInstance()->
+ removeObserver(mAvatarID, this);
+ }
+
+ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ // route the data to the inspector
+ if (data
+ && type == APT_PROPERTIES)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ mInspector->processAvatarData(avatar_data);
+ }
+ }
-LLInspectAvatar::LLInspectAvatar(const LLSD& avatar_id)
-: LLFloater(avatar_id),
- mAvatarID( avatar_id.asUUID() ),
+ // Store avatar ID so we can un-register the observer on destruction
+ LLUUID mAvatarID;
+ LLInspectAvatar* mInspector;
+};
+
+LLInspectAvatar::LLInspectAvatar(const LLSD& sd)
+: LLFloater( LLSD() ), // single_instance, doesn't really need key
+ mAvatarID(), // set in onOpen()
mFirstName(),
- mLastName()
+ mLastName(),
+ mPropertiesRequest(NULL)
{
+ // can't make the properties request until the widgets are constructed
+ // as it might return immediately, so do it in postBuild.
}
LLInspectAvatar::~LLInspectAvatar()
{
+ // clean up any pending requests so they don't call back into a deleted
+ // view
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
}
/*virtual*/
@@ -63,31 +113,94 @@ BOOL LLInspectAvatar::postBuild(void)
getChild<LLUICtrl>("view_profile_btn")->setCommitCallback(
boost::bind(&LLInspectAvatar::onClickViewProfile, this) );
- // can't call from constructor as widgets are not built yet
- refresh();
-
return TRUE;
}
-void LLInspectAvatar::setAvatarID(const LLUUID &avatar_id)
+void LLInspectAvatar::draw()
{
- mAvatarID = avatar_id;
- refresh();
+ static LLCachedControl<F32> FADE_OUT_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
+ if (mCloseTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ if (mCloseTimer.getElapsedTimeF32() > FADE_OUT_TIME)
+ {
+ closeFloater(false);
+ }
+ }
+ else
+ {
+ LLFloater::draw();
+ }
}
-void LLInspectAvatar::refresh()
+
+// Multiple calls to showInstance("inspect_avatar", foo) will provide different
+// LLSD for foo, which we will catch here.
+//virtual
+void LLInspectAvatar::onOpen(const LLSD& data)
{
- // *HACK: Don't stomp data when spawning from login screen
- if (mAvatarID.isNull()) return;
+ mCloseTimer.stop();
+
+ // Extract appropriate avatar id
+ mAvatarID = data.isUUID() ? data : data["avatar_id"];
+
+ // Position the inspector relative to the mouse cursor
+ // Similar to how tooltips are positioned
+ // See LLToolTipMgr::createToolTip
+ if (data.has("pos"))
+ {
+ LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
+ }
+ else
+ {
+ LLUI::positionViewNearMouse(this);
+ }
+
+ // can't call from constructor as widgets are not built yet
+ requestUpdate();
+}
+
+//virtual
+void LLInspectAvatar::onFocusLost()
+{
+ // Start closing when we lose focus
+ mCloseTimer.start();
+}
+
+void LLInspectAvatar::requestUpdate()
+{
+ // Don't make network requests when spawning from the debug menu at the
+ // login screen (which is useful to work on the layout).
+ if (mAvatarID.isNull())
+ {
+ getChild<LLUICtrl>("user_subtitle")->
+ setValue("Test subtitle");
+ getChild<LLUICtrl>("user_details")->
+ setValue("Test details\nTest line 2");
+ return;
+ }
+
+ // Clear out old data so it doesn't flash between old and new
+ getChild<LLUICtrl>("user_name")->setValue("");
+ getChild<LLUICtrl>("user_subtitle")->setValue("");
+ getChild<LLUICtrl>("user_details")->setValue("");
+
+ // Make a new request for properties
+ delete mPropertiesRequest;
+ mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this);
// You can't re-add someone as a friend if they are already your friend
bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
bool is_self = (mAvatarID == gAgentID);
childSetEnabled("add_friend_btn", !is_friend && !is_self);
- // *TODO: replace with generic
- // LLAvatarPropertiesProcessor::getInstance()->addObserver()
- // ->sendDataRequest()
+ // Use an avatar_icon even though the image id will come down with the
+ // avatar properties because the avatar_icon code maintains a cache of icons
+ // and this may result in the image being visible sooner.
+ // *NOTE: This may generate a duplicate avatar properties request, but that
+ // will be suppressed internally in the avatar properties processor.
childSetValue("avatar_icon", LLSD(mAvatarID) );
gCacheName->get(mAvatarID, FALSE,
@@ -95,6 +208,26 @@ void LLInspectAvatar::refresh()
this, _1, _2, _3, _4));
}
+void LLInspectAvatar::processAvatarData(LLAvatarData* data)
+{
+ LLStringUtil::format_map_t args;
+ args["[BORN_ON]"] = data->born_on;
+ args["[AGE]"] = LLAvatarPropertiesProcessor::ageFromDate(data->born_on);
+ args["[SL_PROFILE]"] = data->about_text;
+ args["[RW_PROFILE"] = data->fl_about_text;
+ args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);
+ args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(data);
+
+ std::string subtitle = getString("Subtitle", args);
+ getChild<LLUICtrl>("user_subtitle")->setValue( LLSD(subtitle) );
+ std::string details = getString("Details", args);
+ getChild<LLUICtrl>("user_details")->setValue( LLSD(details) );
+
+ // Delete the request object as it has been satisfied
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
+}
+
void LLInspectAvatar::nameUpdatedCallback(
const LLUUID& id,
const std::string& first,
@@ -114,14 +247,14 @@ void LLInspectAvatar::nameUpdatedCallback(
void LLInspectAvatar::onClickAddFriend()
{
std::string name;
- name.assign(getFirstName());
+ name.assign(mFirstName);
name.append(" ");
- name.append(getLastName());
+ name.append(mLastName);
- LLAvatarActions::requestFriendshipDialog(getAvatarID(), name);
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, name);
}
void LLInspectAvatar::onClickViewProfile()
{
- LLAvatarActions::showProfile(getAvatarID());
+ LLAvatarActions::showProfile(mAvatarID);
}
diff --git a/indra/newview/llinspectavatar.h b/indra/newview/llinspectavatar.h
index 05b0d6fe20..8d490382d2 100644
--- a/indra/newview/llinspectavatar.h
+++ b/indra/newview/llinspectavatar.h
@@ -1,8 +1,5 @@
/**
* @file llinspectavatar.h
- * @brief Avatar Inspector, a small information window used when clicking
- * on avatar names in the 2D UI and in the ambient inspector widget for
- * the 3D world.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
@@ -37,32 +34,45 @@
#include "llfloater.h"
+struct LLAvatarData;
+class LLFetchAvatarData;
+
+// Avatar Inspector, a small information window used when clicking
+// on avatar names in the 2D UI and in the ambient inspector widget for
+// the 3D world.
class LLInspectAvatar : public LLFloater
{
friend class LLFloaterReg;
public:
- // key is the UUID of avatar for whom to show information
- // *TODO: Needs to take a spawn location
+ // avatar_id - Avatar ID for which to show information
+ // Inspector will be positioned relative to current mouse position
LLInspectAvatar(const LLSD& avatar_id);
virtual ~LLInspectAvatar();
/*virtual*/ BOOL postBuild(void);
+ /*virtual*/ void draw();
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same avatar but in different position)
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
- void setAvatarID(const LLUUID &avatar_id);
+ // Inspectors close themselves when they lose focus
+ /*virtual*/ void onFocusLost();
- const LLUUID& getAvatarID() const { return mAvatarID; }
- const std::string& getFirstName() const { return mFirstName; }
- const std::string& getLastName() const { return mLastName; }
+ // Update view based on information from avatar properties processor
+ void processAvatarData(LLAvatarData* data);
private:
- // Update widgets, including avatar name, buttons enabled, etc.
- // Used after avatar id changes.
- void refresh();
+ // Make network requests for all the data to display in this view.
+ // Used on construction and if avatar id changes.
+ void requestUpdate();
+ // Button callbacks
void onClickAddFriend();
void onClickViewProfile();
+ // Callback for gCacheName to look up avatar name
void nameUpdatedCallback(
const LLUUID& id,
const std::string& first,
@@ -74,6 +84,10 @@ private:
// Need avatar name information to spawn friend add request
std::string mFirstName;
std::string mLastName;
+ // an in-flight request for avatar properties from LLAvatarPropertiesProcessor
+ // is represented by this object
+ LLFetchAvatarData* mPropertiesRequest;
+ LLFrameTimer mCloseTimer;
};
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 789e628b67..eb07078402 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -92,6 +92,7 @@
#include "llsidetray.h"
#include "llfloateropenobject.h"
#include "lltrans.h"
+#include "llappearancemgr.h"
using namespace LLOldEvents;
@@ -111,12 +112,7 @@ void dec_busy_count()
}
// Function declarations
-struct LLWearableHoldingPattern;
void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
-void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append);
-void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOOL append, BOOL follow_folder_links);
-void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
-void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append);
void remove_inventory_category_from_avatar(LLInventoryCategory* category);
void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
@@ -161,8 +157,6 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
"inv_item_linkfolder.tga"
};
-BOOL gAddToOutfit = FALSE;
-
// +=================================================+
// | LLInventoryPanelObserver |
@@ -474,7 +468,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
{
return FALSE;
}
- LLInventoryModel* model = getInventoryModel();
+ const LLInventoryModel* model = getInventoryModel();
if (!model)
{
return FALSE;
@@ -485,7 +479,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
S32 count = objects.count();
for(S32 i = 0; i < count; i++)
{
- LLInventoryItem *item = model->getItem(objects.get(i));
+ const LLInventoryItem *item = model->getItem(objects.get(i));
if (item)
{
if (!LLAssetType::lookupCanLink(item->getActualType()))
@@ -665,7 +659,7 @@ BOOL LLInvFVBridge::isInTrash() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
return model->isObjectDescendentOf(mUUID, trash_id);
}
@@ -673,12 +667,12 @@ BOOL LLInvFVBridge::isLinkedObjectInTrash() const
{
if (isInTrash()) return TRUE;
- LLInventoryObject *obj = getInventoryObject();
+ const LLInventoryObject *obj = getInventoryObject();
if (obj && obj->getIsLinkType())
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
}
return FALSE;
@@ -686,12 +680,24 @@ BOOL LLInvFVBridge::isLinkedObjectInTrash() const
BOOL LLInvFVBridge::isAgentInventory() const
{
- LLInventoryModel* model = getInventoryModel();
+ const LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
if(gInventory.getRootFolderID() == mUUID) return TRUE;
return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
}
+BOOL LLInvFVBridge::isCOFFolder() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return TRUE;
+ const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
BOOL LLInvFVBridge::isItemPermissive() const
{
return FALSE;
@@ -993,7 +999,7 @@ void LLItemBridge::restoreItem()
if(item)
{
LLInventoryModel* model = getInventoryModel();
- LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
+ const LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@@ -1026,8 +1032,7 @@ void LLItemBridge::restoreToWorld()
}
// Check if it's in the trash. (again similar to the normal rez logic)
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
{
remove_from_inventory = TRUE;
@@ -1423,6 +1428,46 @@ BOOL LLFolderBridge::copyToClipboard() const
return FALSE;
}
+BOOL LLFolderBridge::isClipboardPasteableAsLink() const
+{
+ // Check normal paste-as-link permissions
+ if (!LLInvFVBridge::isClipboardPasteableAsLink())
+ {
+ return FALSE;
+ }
+
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLViewerInventoryCategory *current_cat = getCategory();
+ if (current_cat)
+ {
+ const LLUUID &current_cat_id = current_cat->getUUID();
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat)
+ {
+ const LLUUID &cat_id = cat->getUUID();
+ // Don't allow recursive pasting
+ if ((cat_id == current_cat_id) ||
+ model->isObjectDescendentOf(current_cat_id, cat_id))
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+
+}
+
BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
BOOL drop)
{
@@ -1436,8 +1481,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(!avatar) return FALSE;
- // cannot drag into library
- if(!isAgentInventory())
+ // cannot drag categories into library or COF
+ if(!isAgentInventory() || isCOFFolder())
{
return FALSE;
}
@@ -1456,14 +1501,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID& cat_id = inv_cat->getUUID();
// Is the destination the trash?
- LLUUID trash_id;
- trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id)
|| model->isObjectDescendentOf(mUUID, trash_id);
BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- if (move_is_into_current_outfit)
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
// BAP - restrictions?
is_movable = true;
@@ -1533,16 +1578,25 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
-
- if (current_outfit_id == mUUID) // if target is current outfit folder we use link
+ // if target is an outfit or current outfit folder we use link
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
- link_inventory_item(
- gAgent.getID(),
- inv_cat->getUUID(),
- mUUID,
- inv_cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- LLPointer<LLInventoryCallback>(NULL));
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearEnsemble(inv_cat);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_cat->getUUID(),
+ mUUID,
+ inv_cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+ }
}
else
{
@@ -1856,7 +1910,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
mContentsCount)
{
gInventory.removeObserver(this);
- wear_inventory_category(category, FALSE, TRUE);
+ LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
delete this;
}
}
@@ -2117,8 +2171,7 @@ BOOL LLFolderBridge::removeItem()
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLUUID trash_id;
- trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
// Look for any gestures and deactivate them
LLInventoryModel::cat_array_t descendent_categories;
@@ -2176,7 +2229,7 @@ void LLFolderBridge::pasteFromClipboard()
void LLFolderBridge::pasteLinkFromClipboard()
{
- LLInventoryModel* model = getInventoryModel();
+ const LLInventoryModel* model = getInventoryModel();
if(model)
{
LLDynamicArray<LLUUID> objects;
@@ -2224,7 +2277,7 @@ void LLFolderBridge::folderOptionsMenu()
if(!model) return;
const LLInventoryCategory* category = model->getCategory(mUUID);
- bool is_default_folder = category &&
+ const bool is_default_folder = category &&
(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()));
// calling card related functionality for folders.
@@ -2262,10 +2315,6 @@ void LLFolderBridge::folderOptionsMenu()
}
mItems.push_back(std::string("Take Off Items"));
}
- if (LLAssetType::AT_CURRENT_OUTFIT == category->getPreferredType())
- {
- mItems.push_back(std::string("Replace Outfit"));
- }
hideContextEntries(*mMenu, mItems, disabled_items);
}
@@ -2321,26 +2370,40 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
LLViewerInventoryCategory *cat = getCategory();
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
- mItems.push_back(std::string("Change Type"));
-
- if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ if (!isCOFFolder() && cat &&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ {
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
+
+ getClipboardEntries(false, mItems, mDisabledItems, flags);
+ }
+ else
{
- mDisabledItems.push_back(std::string("Change Type"));
+ // Want some but not all of the items from getClipboardEntries for outfits.
+ if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT)
+ {
+ mItems.push_back(std::string("Rename"));
+ mItems.push_back(std::string("Delete"));
+ }
}
-
- getClipboardEntries(false, mItems, mDisabledItems, flags);
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
mCallingCards = mWearables = FALSE;
-
+
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (checkFolderForContentsOfType(model, is_callingcard))
{
@@ -2350,7 +2413,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
LLFindWearables is_wearable;
LLIsType is_object( LLAssetType::AT_OBJECT );
LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
+
if (checkFolderForContentsOfType(model, is_wearable) ||
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
@@ -2364,7 +2427,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- folders.push_back(category->getUUID());
+ if (category)
+ {
+ folders.push_back(category->getUUID());
+ }
fetch->fetchDescendents(folders);
inc_busy_count();
if(fetch->isEverythingComplete())
@@ -2420,8 +2486,14 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
drop);
break;
case DAD_CATEGORY:
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
- drop);
+ if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
+ {
+ accept = FALSE;
+ }
+ else
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ }
break;
default:
break;
@@ -2564,7 +2636,7 @@ void LLFolderBridge::modifyOutfit(BOOL append)
// BAP - was:
// wear_inventory_category_on_avatar( cat, append );
- wear_inventory_category( cat, FALSE, append );
+ LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
}
// helper stuff
@@ -2644,6 +2716,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
+
if(is_movable && move_is_into_trash)
{
switch(inv_item->getType())
@@ -2694,6 +2770,25 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
}
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearItem(inv_item);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
else
{
// restamp if the move is into the trash.
@@ -3850,12 +3945,8 @@ void wear_inventory_item_on_avatar( LLInventoryItem* item )
{
lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
-
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onWearOnAvatarArrived,
- new LLUUID(item->getUUID()));
+
+ LLAppearanceManager::wearItem(item);
}
}
@@ -3874,667 +3965,6 @@ void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
}
}
-
-struct LLFoundData
-{
- LLFoundData(const LLUUID& item_id,
- const LLUUID& asset_id,
- const std::string& name,
- LLAssetType::EType asset_type) :
- mItemID(item_id),
- mAssetID(asset_id),
- mName(name),
- mAssetType(asset_type),
- mWearable( NULL ) {}
-
- LLUUID mItemID;
- LLUUID mAssetID;
- std::string mName;
- LLAssetType::EType mAssetType;
- LLWearable* mWearable;
-};
-
-struct LLWearableHoldingPattern
-{
- LLWearableHoldingPattern() : mResolved(0) {}
- ~LLWearableHoldingPattern()
- {
- for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
- mFoundList.clear();
- }
- typedef std::list<LLFoundData*> found_list_t;
- found_list_t mFoundList;
- S32 mResolved;
-};
-
-
-class LLOutfitObserver : public LLInventoryFetchObserver
-{
-public:
- LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
- mCatID(cat_id),
- mCopyItems(copy_items),
- mAppend(append)
- {}
- ~LLOutfitObserver() {}
- virtual void done(); //public
-
-protected:
- LLUUID mCatID;
- bool mCopyItems;
- bool mAppend;
-};
-
-class LLWearInventoryCategoryCallback : public LLInventoryCallback
-{
-public:
- LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
- {
- mCatID = cat_id;
- mAppend = append;
- }
- void fire(const LLUUID& item_id)
- {
- /*
- * Do nothing. We only care about the destructor
- *
- * The reason for this is that this callback is used in a hack where the
- * same callback is given to dozens of items, and the destructor is called
- * after the last item has fired the event and dereferenced it -- if all
- * the events actually fire!
- */
- }
-
-protected:
- ~LLWearInventoryCategoryCallback()
- {
- // Is the destructor called by ordinary dereference, or because the app's shutting down?
- // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
- if( LLInventoryCallbackManager::is_instantiated() )
- {
- wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
- }
- else
- {
- llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
- }
- }
-
-private:
- LLUUID mCatID;
- bool mAppend;
-};
-
-void LLOutfitObserver::done()
-{
- // We now have an outfit ready to be copied to agent inventory. Do
- // it, and wear that outfit normally.
- if(mCopyItems)
- {
- LLInventoryCategory* cat = gInventory.getCategory(mCatID);
- std::string name;
- if(!cat)
- {
- // should never happen.
- name = "New Outfit";
- }
- else
- {
- name = cat->getName();
- }
- LLViewerInventoryItem* item = NULL;
- item_ref_t::iterator it = mComplete.begin();
- item_ref_t::iterator end = mComplete.end();
- LLUUID pid;
- for(; it < end; ++it)
- {
- item = (LLViewerInventoryItem*)gInventory.getItem(*it);
- if(item)
- {
- if(LLInventoryType::IT_GESTURE == item->getInventoryType())
- {
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
- }
- else
- {
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
- }
- break;
- }
- }
- if(pid.isNull())
- {
- pid = gInventory.getRootFolderID();
- }
-
- LLUUID cat_id = gInventory.createNewCategory(
- pid,
- LLAssetType::AT_NONE,
- name);
- mCatID = cat_id;
- LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
- it = mComplete.begin();
- for(; it < end; ++it)
- {
- item = (LLViewerInventoryItem*)gInventory.getItem(*it);
- if(item)
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- cat_id,
- std::string(),
- cb);
- }
- }
- }
- else
- {
- // Wear the inventory category.
- wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
- }
-}
-
-class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
- ~LLOutfitFetch() {}
- virtual void done();
-protected:
- bool mCopyItems;
- bool mAppend;
-};
-
-void LLOutfitFetch::done()
-{
- // What we do here is get the complete information on the items in
- // the library, and set up an observer that will wait for that to
- // happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- S32 count = item_array.count();
- if(!count)
- {
- llwarns << "Nothing fetched in category " << mCompleteFolders.front()
- << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-
- LLOutfitObserver* outfit;
- outfit = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
- LLInventoryFetchObserver::item_ref_t ids;
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(item_array.get(i)->getUUID());
- }
-
- // clean up, and remove this as an observer since the call to the
- // outfit could notify observers and throw us into an infinite
- // loop.
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
-
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
-
- // do the fetch
- outfit->fetchItems(ids);
- if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
- }
-}
-
-void wear_outfit_by_name(const std::string& name)
-{
- llinfos << "Wearing category " << name << llendl;
- inc_busy_count();
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLNameCategoryCollector has_name(name);
- gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- has_name);
- bool copy_items = false;
- LLInventoryCategory* cat = NULL;
- if (cat_array.count() > 0)
- {
- // Just wear the first one that matches
- cat = cat_array.get(0);
- }
- else
- {
- gInventory.collectDescendentsIf(LLUUID::null,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- has_name);
- if(cat_array.count() > 0)
- {
- cat = cat_array.get(0);
- copy_items = true;
- }
- }
-
- if(cat)
- {
- wear_inventory_category(cat, copy_items, false);
- }
- else
- {
- llwarns << "Couldn't find outfit " <<name<< " in wear_outfit_by_name()"
- << llendl;
- }
-
- dec_busy_count();
-}
-
-void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append)
-{
- if(!category) return;
-
- lldebugs << "wear_inventory_category( " << category->getName()
- << " )" << llendl;
- // What we do here is get the complete information on the items in
- // the inventory, and set up an observer that will wait for that to
- // happen.
- LLOutfitFetch* outfit;
- outfit = new LLOutfitFetch(copy, append);
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- folders.push_back(category->getUUID());
- outfit->fetchDescendents(folders);
- inc_busy_count();
- if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
- }
-}
-
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL append )
-{
- // Avoid unintentionally overwriting old wearables. We have to do
- // this up front to avoid having to deal with the case of multiple
- // wearables being dirty.
- if(!category) return;
- lldebugs << "wear_inventory_category_on_avatar( " << category->getName()
- << " )" << llendl;
-
- BOOL follow_folder_links = (category->getPreferredType() == LLAssetType::AT_CURRENT_OUTFIT || category->getPreferredType() == LLAssetType::AT_OUTFIT );
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty(boost::bind(wear_inventory_category_on_avatar_step2, _1, category->getUUID(), append, follow_folder_links));
- }
- else
- {
- wear_inventory_category_on_avatar_step2(TRUE, category->getUUID(), append, follow_folder_links );
- }
-}
-
-void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src)
-{
- LLInventoryModel::item_array_t new_dst;
- std::set<LLUUID> mark_inventory;
- std::set<LLUUID> mark_asset;
-
- S32 inventory_dups = 0;
- S32 asset_dups = 0;
-
- for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin();
- src_pos != src.end();
- ++src_pos)
- {
- LLUUID src_item_id = (*src_pos)->getLinkedUUID();
- mark_inventory.insert(src_item_id);
- LLUUID src_asset_id = (*src_pos)->getAssetUUID();
- mark_asset.insert(src_asset_id);
- }
-
- for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin();
- dst_pos != dst.end();
- ++dst_pos)
- {
- LLUUID dst_item_id = (*dst_pos)->getLinkedUUID();
-
- if (mark_inventory.find(dst_item_id) == mark_inventory.end())
- {
- }
- else
- {
- inventory_dups++;
- }
-
- LLUUID dst_asset_id = (*dst_pos)->getAssetUUID();
-
- if (mark_asset.find(dst_asset_id) == mark_asset.end())
- {
- // Item is not already present in COF.
- new_dst.put(*dst_pos);
- mark_asset.insert(dst_item_id);
- }
- else
- {
- asset_dups++;
- }
- }
- llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count()
- << " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl;
-
- dst = new_dst;
-}
-
-void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOOL append, BOOL follow_folder_links )
-{
- // Find all the wearables that are in the category's subtree.
- lldebugs << "wear_inventory_category_on_avatar_step2()" << llendl;
- if(proceed)
- {
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(category,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable,
- follow_folder_links);
- S32 i;
- S32 wearable_count = item_array.count();
-
- LLInventoryModel::cat_array_t obj_cat_array;
- LLInventoryModel::item_array_t obj_item_array;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(category,
- obj_cat_array,
- obj_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_object,
- follow_folder_links);
- S32 obj_count = obj_item_array.count();
-
- // Find all gestures in this folder
- LLInventoryModel::cat_array_t gest_cat_array;
- LLInventoryModel::item_array_t gest_item_array;
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(category,
- gest_cat_array,
- gest_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_gesture,
- follow_folder_links);
- S32 gest_count = gest_item_array.count();
-
- if( !wearable_count && !obj_count && !gest_count)
- {
- LLNotifications::instance().add("CouldNotPutOnOutfit");
- return;
- }
-
- const LLUUID &current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- // Processes that take time should show the busy cursor
- inc_busy_count();
-
- LLInventoryModel::cat_array_t co_cat_array;
- LLInventoryModel::item_array_t co_item_array;
- gInventory.collectDescendents(current_outfit_id, co_cat_array, co_item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- if (append)
- {
- // Remove duplicates and update counts.
- removeDuplicateItems(item_array,co_item_array);
- wearable_count = item_array.count();
-
- removeDuplicateItems(obj_item_array,co_item_array);
- obj_count = obj_item_array.count();
-
- removeDuplicateItems(gest_item_array,co_item_array);
- gest_count = gest_item_array.count();
- }
-
-
- if (wearable_count > 0 || obj_count > 0)
- {
- if (!append)
- {
- // Remove all current outfit folder links if we're now replacing the contents.
- for (i = 0; i < co_item_array.count(); ++i)
- {
- gInventory.purgeObject(co_item_array.get(i)->getUUID());
- }
- }
- }
-
- // Activate all gestures in this folder
- if (gest_count > 0)
- {
- llinfos << "Activating " << gest_count << " gestures" << llendl;
-
- LLGestureManager::instance().activateGestures(gest_item_array);
-
- // Update the inventory item labels to reflect the fact
- // they are active.
- LLViewerInventoryCategory* catp = gInventory.getCategory(category);
- if (catp)
- {
- gInventory.updateCategory(catp);
- gInventory.notifyObservers();
- }
- }
-
- if(wearable_count > 0)
- {
- // Note: can't do normal iteration, because if all the
- // wearables can be resolved immediately, then the
- // callback will be called (and this object deleted)
- // before the final getNextData().
- LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
- LLFoundData* found;
- LLDynamicArray<LLFoundData*> found_container;
- for(i = 0; i < wearable_count; ++i)
- {
- found = new LLFoundData(item_array.get(i)->getUUID(),
- item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType());
- holder->mFoundList.push_front(found);
- found_container.put(found);
- }
- for(i = 0; i < wearable_count; ++i)
- {
- gAddToOutfit = append;
- found = found_container.get(i);
-
- // Populate the current outfit folder with links to the newly added wearables
- std::string link_name = "WearableLink";
- link_inventory_item(gAgent.getID(), found->mItemID, current_outfit_id, link_name,
- LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
-
- // Fetch the wearables about to be worn.
- LLWearableList::instance().getAsset(found->mAssetID,
- found->mName,
- found->mAssetType,
- wear_inventory_category_on_avatar_loop,
- (void*)holder);
- }
- }
-
-
- //If not appending and the folder doesn't contain only gestures, take off all attachments.
- if (!append
- && !(wearable_count == 0 && obj_count == 0 && gest_count > 0) )
- {
- LLAgentWearables::userRemoveAllAttachments(NULL);
- }
-
- if( obj_count > 0 )
- {
- // We've found some attachements. Add these.
-
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar )
- {
- // Build a compound message to send all the objects that need to be rezzed.
-
- // Limit number of packets to send
- const S32 MAX_PACKETS_TO_SEND = 10;
- const S32 OBJECTS_PER_PACKET = 4;
- const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
- if( obj_count > MAX_OBJECTS_TO_SEND )
- {
- obj_count = MAX_OBJECTS_TO_SEND;
- }
-
- // Create an id to keep the parts of the compound message together
- LLUUID compound_msg_id;
- compound_msg_id.generate();
- LLMessageSystem* msg = gMessageSystem;
-
- for(i = 0; i < obj_count; ++i)
- {
- if( 0 == (i % OBJECTS_PER_PACKET) )
- {
- // Start a new message chunk
- msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_HeaderData);
- msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
- msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
- msg->addBOOLFast(_PREHASH_FirstDetachAll, !append );
- }
-
- const LLInventoryItem* item = obj_item_array.get(i).get();
- msg->nextBlockFast(_PREHASH_ObjectData );
- msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
- msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
- msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
- pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
- msg->addStringFast(_PREHASH_Name, item->getName());
- msg->addStringFast(_PREHASH_Description, item->getDescription());
-
- if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
- {
- // End of message chunk
- msg->sendReliable( gAgent.getRegion()->getHost() );
- }
-
- }
-
- for(i = 0; i < obj_count; ++i)
- {
- const std::string link_name = "AttachmentLink";
- const LLInventoryItem* item = obj_item_array.get(i).get();
- link_inventory_item(gAgent.getID(), item->getLinkedUUID(), current_outfit_id, link_name,
- LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
-
- // In the particular case that we're switching to a different outfit,
- // create a link to the folder that we wore.
- LLViewerInventoryCategory* catp = gInventory.getCategory(category);
- if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
- {
- link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(),
- LLAssetType::AT_LINK_FOLDER, LLPointer<LLInventoryCallback>(NULL));
- }
- }
-}
-
-void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data)
-{
- LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
- BOOL append= gAddToOutfit;
-
- if(wearable)
- {
- for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
- iter != holder->mFoundList.end(); ++iter)
- {
- LLFoundData* data = *iter;
- if(wearable->getAssetID() == data->mAssetID)
- {
- data->mWearable = wearable;
- break;
- }
- }
- }
- holder->mResolved += 1;
- if(holder->mResolved >= (S32)holder->mFoundList.size())
- {
- wear_inventory_category_on_avatar_step3(holder, append);
- }
-}
-
-void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append)
-{
- lldebugs << "wear_inventory_category_on_avatar_step3()" << llendl;
- LLInventoryItem::item_array_t items;
- LLDynamicArray< LLWearable* > wearables;
-
- // For each wearable type, find the first instance in the category
- // that we recursed through.
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
- iter != holder->mFoundList.end(); ++iter)
- {
- LLFoundData* data = *iter;
- LLWearable* wearable = data->mWearable;
- if( wearable && ((S32)wearable->getType() == i) )
- {
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
- if( item && (item->getAssetUUID() == wearable->getAssetID()) )
- {
- items.put(item);
- wearables.put(wearable);
- }
- break;
- }
- }
- }
-
- if(wearables.count() > 0)
- {
- gAgentWearables.setWearableOutfit(items, wearables, !append);
- gInventory.notifyObservers();
- }
-
- delete holder;
-
- dec_busy_count();
-}
-
void remove_inventory_category_from_avatar( LLInventoryCategory* category )
{
if(!category) return;
@@ -4939,6 +4369,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda
}
// static
+// BAP remove the "add" code path once everything is fully COF-ified.
void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
{
LLUUID* item_id = (LLUUID*) userdata;
@@ -5298,15 +4729,15 @@ void LLWearableBridgeAction::wearOnAvatar()
}
//virtual
-void LLWearableBridgeAction::doIt()
+void LLWearableBridgeAction::doIt()
{
- if( isInTrash() )
+ if(isInTrash())
{
LLNotifications::instance().add("CannotWearTrash");
}
else if(isAgentInventory())
{
- if( !gAgentWearables.isWearingItem( mUUID ) )
+ if(!gAgentWearables.isWearingItem(mUUID))
{
wearOnAvatar();
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 25859b7f73..bc950520aa 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -200,9 +200,8 @@ protected:
BOOL isInTrash() const;
BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
- // return true if the item is in agent inventory. if false, it
- // must be lost or in the inventory library.
- BOOL isAgentInventory() const;
+ BOOL isAgentInventory() const; // false if lost or in the inventory library
+ BOOL isCOFFolder() const; // true if COF or descendent of.
virtual BOOL isItemPermissive() const;
static void changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
@@ -295,6 +294,7 @@ public:
virtual BOOL isItemMovable();
virtual BOOL isUpToDate() const;
virtual BOOL isItemCopyable() const;
+ virtual BOOL isClipboardPasteableAsLink() const;
virtual BOOL copyToClipboard() const;
static void createWearable(LLFolderBridge* bridge, EWearableType type);
@@ -769,8 +769,6 @@ protected:
};
void wear_inventory_item_on_avatar(LLInventoryItem* item);
-void wear_outfit_by_name(const std::string& name);
-void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append);
class LLViewerJointAttachment;
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
@@ -787,4 +785,5 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
void teleport_via_landmark(const LLUUID& asset_id);
+
#endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 670b1f000b..b803df110b 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -94,6 +94,7 @@ public:
BOOL isModified();
BOOL isModifiedAndClear();
BOOL isSinceLogoff();
+ bool hasFilterString() { return mFilterSubString.size() > 0; }
void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; }
const std::string getName() const { return mName; }
std::string getFilterText();
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index ef2ba5c11b..7f91f8f8b2 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -187,9 +187,9 @@ LLInventoryModel::~LLInventoryModel()
// This is a convenience function to check if one object has a parent
// chain up to the category specified by UUID.
BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
- const LLUUID& cat_id)
+ const LLUUID& cat_id) const
{
- LLInventoryObject* obj = getObject(obj_id);
+ const LLInventoryObject* obj = getObject(obj_id);
while(obj)
{
const LLUUID& parent_id = obj->getParentUUID();
@@ -307,13 +307,13 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
// inventory category on the fly if one does not exist.
LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool create_folder)
{
- LLUUID rv = findCatUUID(t);
+ const LLUUID &rv = findCatUUID(t);
if(rv.isNull() && isInventoryUsable() && create_folder)
{
- LLUUID root_id = gInventory.getRootFolderID();
+ const LLUUID &root_id = gInventory.getRootFolderID();
if(root_id.notNull())
{
- rv = createNewCategory(root_id, t, LLStringUtil::null);
+ return createNewCategory(root_id, t, LLStringUtil::null);
}
}
return rv;
@@ -321,9 +321,9 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found.
-LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type)
+const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) const
{
- LLUUID root_id = gInventory.getRootFolderID();
+ const LLUUID &root_id = gInventory.getRootFolderID();
if(LLAssetType::AT_CATEGORY == preferred_type)
{
return root_id;
@@ -440,7 +440,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
// Start with categories
if(!include_trash)
{
- LLUUID trash_id(findCatUUID(LLAssetType::AT_TRASH));
+ const LLUUID trash_id = findCategoryUUIDForType(LLAssetType::AT_TRASH);
if(trash_id.notNull() && (trash_id == id))
return;
}
@@ -473,8 +473,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
item = item_array->get(i);
if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
{
- // BAP either getLinkedCategory() should return non-const, or the functor should take const.
- LLViewerInventoryCategory *linked_cat = const_cast<LLViewerInventoryCategory*>(item->getLinkedCategory());
+ LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
if (linked_cat)
{
if(add(linked_cat,NULL))
@@ -548,10 +547,10 @@ void LLInventoryModel::collectLinkedItems(const LLUUID& id,
// Generates a string containing the path to the item specified by
// item_id.
-void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
+void LLInventoryModel::appendPath(const LLUUID& id, std::string& path) const
{
std::string temp;
- LLInventoryObject* obj = getObject(id);
+ const LLInventoryObject* obj = getObject(id);
LLUUID parent_id;
if(obj) parent_id = obj->getParentUUID();
std::string forward_slash("/");
@@ -567,7 +566,7 @@ void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
path.append(temp);
}
-bool LLInventoryModel::isInventoryUsable()
+bool LLInventoryModel::isInventoryUsable() const
{
bool result = false;
if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable)
@@ -1086,7 +1085,7 @@ void LLInventoryModel::removeObserver(LLInventoryObserver* observer)
mObservers.erase(observer);
}
-BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer)
+BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
{
return mObservers.find(observer) != mObservers.end();
}
@@ -1112,7 +1111,7 @@ void LLInventoryModel::notifyObservers(const std::string service_name)
observer->changed(mModifyMask);
}
- // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
+ // safe way to increment since changed may delete entries! (@!##%@!@&*!)
iter = mObservers.upper_bound(observer);
}
@@ -1791,6 +1790,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
if (item->getIsBrokenLink())
{
llwarns << "Add link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
+// llassert_always(FALSE); // DO NOT MERGE THIS IN. This is an AVP debugging line. If this line triggers, it means that you just loaded in a broken link. Unless that happens because you actually deleted a baseobj without deleting the link, it's indicative of a serious problem (likely with your inventory) and should be diagnosed.
}
mItemMap[item->getUUID()] = item;
//mInventory[item->getUUID()] = item;
@@ -1817,7 +1817,7 @@ void LLInventoryModel::empty()
//mInventory.clear();
}
-void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update)
+void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
{
LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
if(cat)
@@ -2170,7 +2170,8 @@ bool LLInventoryModel::loadSkeleton(
update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
if(the_count != no_child_counts)
{
- cat->setDescendentCount((*the_count).second.mValue);
+ const S32 num_descendents = (*the_count).second.mValue;
+ cat->setDescendentCount(num_descendents);
}
else
{
@@ -2473,7 +2474,7 @@ void LLInventoryModel::buildParentChildMap()
}
}
- LLUUID agent_inv_root_id = gInventory.getRootFolderID();
+ const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
if (agent_inv_root_id.notNull())
{
cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
@@ -3316,7 +3317,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetTy
void LLInventoryModel::removeItem(const LLUUID& item_id)
{
LLViewerInventoryItem* item = getItem(item_id);
- const LLUUID& new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH);
if (item && item->getParentUUID() != new_parent)
{
LLInventoryModel::update_list_t update;
@@ -3334,7 +3335,7 @@ void LLInventoryModel::removeItem(const LLUUID& item_id)
}
}
-LLUUID LLInventoryModel::getRootFolderID() const
+const LLUUID &LLInventoryModel::getRootFolderID() const
{
return mRootFolderID;
}
@@ -3344,7 +3345,7 @@ void LLInventoryModel::setRootFolderID(const LLUUID& val)
mRootFolderID = val;
}
-LLUUID LLInventoryModel::getLibraryRootFolderID() const
+const LLUUID &LLInventoryModel::getLibraryRootFolderID() const
{
return mLibraryRootFolderID;
}
@@ -3354,7 +3355,7 @@ void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val)
mLibraryRootFolderID = val;
}
-LLUUID LLInventoryModel::getLibraryOwnerID() const
+const LLUUID &LLInventoryModel::getLibraryOwnerID() const
{
return mLibraryOwnerID;
}
@@ -3367,13 +3368,13 @@ void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
//----------------------------------------------------------------------------
// *NOTE: DEBUG functionality
-void LLInventoryModel::dumpInventory()
+void LLInventoryModel::dumpInventory() const
{
llinfos << "\nBegin Inventory Dump\n**********************:" << llendl;
- llinfos << "mCategroy[] contains " << mCategoryMap.size() << " items." << llendl;
- for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+ llinfos << "mCategory[] contains " << mCategoryMap.size() << " items." << llendl;
+ for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
{
- LLViewerInventoryCategory* cat = cit->second;
+ const LLViewerInventoryCategory* cat = cit->second;
if(cat)
{
llinfos << " " << cat->getUUID() << " '" << cat->getName() << "' "
@@ -3386,9 +3387,9 @@ void LLInventoryModel::dumpInventory()
}
}
llinfos << "mItemMap[] contains " << mItemMap.size() << " items." << llendl;
- for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+ for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
{
- LLViewerInventoryItem* item = iit->second;
+ const LLViewerInventoryItem* item = iit->second;
if(item)
{
llinfos << " " << item->getUUID() << " "
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 649a7e5b16..3f2e6b624e 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -99,12 +99,12 @@ class LLInventoryCollectFunctor;
class LLInventoryModel
{
public:
- typedef enum e_has_children
+ enum EHasChildren
{
CHILDREN_NO,
CHILDREN_YES,
CHILDREN_MAYBE
- }EHasChildren;
+ };
// These are used a lot...
typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
@@ -133,7 +133,7 @@ public:
// This is a convenience function to check if one object has a
// parent chain up to the category specified by UUID.
- BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id);
+ BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
// Get the object by id. Returns NULL if not found.
// * WARNING: use the pointer returned for read operations - do
@@ -197,7 +197,7 @@ public:
// The inventory model usage is sensitive to the initial construction of the
// model.
- bool isInventoryUsable();
+ bool isInventoryUsable() const;
//
// Mutators
@@ -261,7 +261,7 @@ public:
// to remove it.
void addObserver(LLInventoryObserver* observer);
void removeObserver(LLInventoryObserver* observer);
- BOOL containsObserver(LLInventoryObserver* observer);
+ BOOL containsObserver(LLInventoryObserver* observer) const;
//
// Misc Methods
@@ -312,7 +312,7 @@ public:
// Generates a string containing the path to the item specified by
// item_id.
- void appendPath(const LLUUID& id, std::string& path);
+ void appendPath(const LLUUID& id, std::string& path) const;
// message handling functionality
static void registerCallbacks(LLMessageSystem* msg);
@@ -368,7 +368,7 @@ public:
// Call these methods when there are category updates, but call
// them *before* the actual update so the method can do descendent
// accounting correctly.
- void accountForUpdate(const LLCategoryUpdate& update);
+ void accountForUpdate(const LLCategoryUpdate& update) const;
void accountForUpdate(const update_list_t& updates);
void accountForUpdate(const update_map_t& updates);
@@ -402,9 +402,9 @@ public:
// gInventory is a singleton and represents the agent's inventory.
// The "library" is actually the inventory of a special agent,
// usually Alexandria Linden.
- LLUUID getRootFolderID() const;
- LLUUID getLibraryOwnerID() const;
- LLUUID getLibraryRootFolderID() const;
+ const LLUUID &getRootFolderID() const;
+ const LLUUID &getLibraryOwnerID() const;
+ const LLUUID &getLibraryRootFolderID() const;
// These are set during login with data from the server
void setRootFolderID(const LLUUID& id);
@@ -420,9 +420,13 @@ protected:
void addCategory(LLViewerInventoryCategory* category);
void addItem(LLViewerInventoryItem* item);
+ // ! DEPRECRATE ! Remove this and add it into findCategoryUUIDForType,
+ // since that's the only function that uses this. It's too confusing
+ // having both methods.
+ //
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found
- LLUUID findCatUUID(LLAssetType::EType preferred_type);
+ const LLUUID &findCatUUID(LLAssetType::EType preferred_type) const;
// Empty the entire contents
void empty();
@@ -513,7 +517,7 @@ protected:
public:
// *NOTE: DEBUG functionality
- void dumpInventory();
+ void dumpInventory() const;
static bool isBulkFetchProcessingComplete();
static void stopBackgroundFetch(); // stop fetch process
diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp
index c83cde9d83..d910dbf718 100644
--- a/indra/newview/lllocationhistory.cpp
+++ b/indra/newview/lllocationhistory.cpp
@@ -37,59 +37,41 @@
#include <iomanip> // for std::setw()
#include "llui.h"
-
-const char LLLocationHistory::delimiter = '\t';
+#include "llsd.h"
+#include "llsdserialize.h"
LLLocationHistory::LLLocationHistory() :
mFilename("typed_locations.txt")
{
}
-void LLLocationHistory::addItem(const std::string & item, const std::string & tooltip) {
+void LLLocationHistory::addItem(const LLLocationHistoryItem& item) {
static LLUICachedControl<S32> max_items("LocationHistoryMaxSize", 100);
// check if this item doesn't duplicate any existing one
- std::vector<std::string>::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
- boost::bind(&LLLocationHistory::equalByRegionParcel,this,_1,item));
+ location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(),item);
if(item_iter != mItems.end()){
- /*replace duplicate.
- * If an item's region and item's parcel are equal.
- */
- mToolTips.erase(*item_iter);
mItems.erase(item_iter);
-
}
mItems.push_back(item);
- mToolTips[item] = tooltip;
-
+
// If the vector size exceeds the maximum, purge the oldest items.
if ((S32)mItems.size() > max_items) {
- for(std::vector<std::string>::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) {
- mToolTips.erase(*i);
- mItems.erase(i);
+ for(location_list_t::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) {
+ mItems.erase(i);
}
}
}
-/**
- * check if the history item is equal.
- * @return true - if region name and parcel is equal.
+/*
+ * @brief Try to find item in history.
+ * If item has been founded, it will be places into end of history.
+ * @return true - item has founded
*/
-bool LLLocationHistory::equalByRegionParcel(const std::string& item, const std::string& newItem){
-
-
- S32 itemIndex = item.find('(');
- S32 newItemIndex = newItem.find('(');
-
- std::string region_parcel = item.substr(0,itemIndex);
- std::string new_region_parcel = newItem.substr(0,newItemIndex);
-
- return region_parcel == new_region_parcel;
-}
-bool LLLocationHistory::touchItem(const std::string & item) {
+bool LLLocationHistory::touchItem(const LLLocationHistoryItem& item) {
bool result = false;
- std::vector<std::string>::iterator item_iter = std::find(mItems.begin(), mItems.end(), item);
+ location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(), item);
// the last used item should be the first in the history
if (item_iter != mItems.end()) {
@@ -104,13 +86,6 @@ bool LLLocationHistory::touchItem(const std::string & item) {
void LLLocationHistory::removeItems()
{
mItems.clear();
- mToolTips.clear();
-}
-
-std::string LLLocationHistory::getToolTip(const std::string & item) const {
- std::map<std::string, std::string>::const_iterator i = mToolTips.find(item);
-
- return i != mToolTips.end() ? i->second : "";
}
bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t& result) const
@@ -123,7 +98,7 @@ bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t&
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
{
- std::string haystack = *it;
+ std::string haystack = it->getLocation();
LLStringUtil::toLower(haystack);
if (haystack.find(needle) != std::string::npos)
@@ -139,7 +114,7 @@ void LLLocationHistory::dump() const
int i = 0;
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it, ++i)
{
- llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << *it << llendl;
+ llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << it->getLocation() << llendl;
}
}
@@ -158,11 +133,7 @@ void LLLocationHistory::save() const
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
{
- std::string tooltip = getToolTip(*it);
- if(!tooltip.empty())
- {
- file << (*it) << delimiter << tooltip << std::endl;
- }
+ file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
}
file.close();
@@ -186,16 +157,17 @@ void LLLocationHistory::load()
// add each line in the file to the list
std::string line;
-
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
while (std::getline(file, line)) {
- size_t dp = line.find(delimiter);
-
- if (dp != std::string::npos) {
- const std::string reg_name = line.substr(0, dp);
- const std::string tooltip = line.substr(dp + 1, std::string::npos);
-
- addItem(reg_name, tooltip);
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ llinfos<< "Parsing saved teleport history failed" << llendl;
+ break;
}
+
+ mItems.push_back(s_item);
}
file.close();
diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h
index 060a6b2fe8..5f9976f87a 100644
--- a/indra/newview/lllocationhistory.h
+++ b/indra/newview/lllocationhistory.h
@@ -40,21 +40,84 @@
#include <map>
#include <boost/function.hpp>
+class LLSD;
+
+enum ELocationType {
+ TYPED_REGION_SURL//region name or surl
+ ,LANDMARK // name of landmark
+ ,TELEPORT_HISTORY
+ };
+class LLLocationHistoryItem {
+
+public:
+ LLLocationHistoryItem(){}
+ LLLocationHistoryItem(std::string typed_location,
+ LLVector3d global_position, std::string tooltip,ELocationType type ):
+ mLocation(typed_location),
+ mGlobalPos(global_position),
+ mToolTip(tooltip),
+ mType(type)
+ {}
+ LLLocationHistoryItem(const LLLocationHistoryItem& item):
+ mGlobalPos(item.mGlobalPos),
+ mToolTip(item.mToolTip),
+ mLocation(item.mLocation),
+ mType(item.mType)
+ {}
+ LLLocationHistoryItem(const LLSD& data):
+ mLocation(data["location"]),
+ mGlobalPos(data["global_pos"]),
+ mToolTip(data["tooltip"]),
+ mType(ELocationType(data["item_type"].asInteger()))
+ {}
+
+ bool operator==(const LLLocationHistoryItem& item)
+ {
+ // do not compare mGlobalPos,
+ // because of a rounding off , the history can contain duplicates
+ return mLocation == item.mLocation && (mType == item.mType);
+ }
+ bool operator!=(const LLLocationHistoryItem& item)
+ {
+ return ! (*this == item);
+ }
+ LLSD toLLSD() const
+ {
+ LLSD val;
+ val["location"]= mLocation;
+ val["global_pos"] = mGlobalPos.getValue();
+ val["tooltip"] = mToolTip;
+ val["item_type"] = mType;
+ return val;
+ }
+ const std::string& getLocation() const { return mLocation; };
+ const std::string& getToolTip() const { return mToolTip; };
+ //static bool equalByRegionParcel(const LLLocationHistoryItem& item1, const LLLocationHistoryItem& item2);
+ static bool equalByLocation(const LLLocationHistoryItem& item1, const std::string& item_location)
+ {
+ return item1.getLocation() == item_location;
+ }
+
+ LLVector3d mGlobalPos; // global position
+ std::string mToolTip;// SURL
+ std::string mLocation;// typed_location
+ ELocationType mType;
+};
+
class LLLocationHistory: public LLSingleton<LLLocationHistory>
{
LOG_CLASS(LLLocationHistory);
public:
- typedef std::vector<std::string> location_list_t;
+ typedef std::vector<LLLocationHistoryItem> location_list_t;
typedef boost::function<void()> loaded_callback_t;
typedef boost::signals2::signal<void()> loaded_signal_t;
LLLocationHistory();
- void addItem(const std::string & item, const std::string & tooltip);
- bool touchItem(const std::string & item);
+ void addItem(const LLLocationHistoryItem& item);
+ bool touchItem(const LLLocationHistoryItem& item);
void removeItems();
- std::string getToolTip(const std::string & item) const;
size_t getItemCount() const { return mItems.size(); }
const location_list_t& getItems() const { return mItems; }
bool getMatchingItems(std::string substring, location_list_t& result) const;
@@ -65,10 +128,8 @@ public:
void dump() const;
private:
- bool equalByRegionParcel(const std::string& item, const std::string& item_to_add);
- const static char delimiter;
- std::vector<std::string> mItems;
- std::map<std::string, std::string> mToolTips;
+
+ location_list_t mItems;
std::string mFilename; /// File to store the history to.
loaded_signal_t mLoadedSignal;
};
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index a8ec826e88..1d9220cf3d 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -42,12 +42,14 @@
#include "llstring.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
+#include "lltooltip.h"
// newview includes
#include "llinventorymodel.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
#include "lllocationhistory.h"
+#include "llteleporthistory.h"
#include "llsidetray.h"
#include "llslurl.h"
#include "lltrans.h"
@@ -289,32 +291,40 @@ void LLLocationInputCtrl::hideList()
focusTextEntry();
}
-BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
// Let the buttons show their tooltips.
if (LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen) && !msg.empty())
{
- if (mList->getRect().pointInRect(x, y)) {
- LLLocationHistory* lh = LLLocationHistory::getInstance();
- const std::string tooltip = lh->getToolTip(msg);
-
- if (!tooltip.empty()) {
- msg = tooltip;
+ if (mList->getRect().pointInRect(x, y))
+ {
+ S32 loc_x, loc_y;
+ //x,y - contain coordinates related to the location input control, but without taking the expanded list into account
+ //So we have to convert it again into local coordinates of mList
+ localPointToOtherView(x,y,&loc_x,&loc_y,mList);
+
+ LLScrollListItem* item = mList->hitItem(loc_x,loc_y);
+ if (item)
+ {
+ LLSD value = item->getValue();
+ if (value.has("tooltip"))
+ {
+ LLToolTipMgr::instance().show(value["tooltip"]);
+ }
}
}
return TRUE;
}
- msg = LLUI::sShowXUINames ? getShowNamesToolTip() : "";
- return mTextEntry->getRect().pointInRect(x, y);
+ return FALSE;
}
BOOL LLLocationInputCtrl::handleKeyHere(KEY key, MASK mask)
{
BOOL result = LLComboBox::handleKeyHere(key, mask);
- if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0)
+ if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0 && !mList->getVisible())
{
showList();
}
@@ -448,18 +458,58 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data)
rebuildLocationHistory(filter);
//Let's add landmarks to the top of the list if any
- if( filter.size() !=0 )
+ if(!filter.empty() )
{
LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(filter, TRUE);
for(U32 i=0; i < landmark_items.size(); i++)
{
- mList->addSimpleElement(landmark_items[i]->getName(), ADD_TOP);
+ LLSD value;
+ //TODO:: DO we need tooltip for Landmark??
+
+ value["item_type"] = LANDMARK;
+ value["AssetUUID"] = landmark_items[i]->getAssetUUID();
+ add(landmark_items[i]->getName(), value);
+
+ }
+ //Let's add teleport history items
+ LLTeleportHistory* th = LLTeleportHistory::getInstance();
+ LLTeleportHistory::slurl_list_t th_items = th->getItems();
+
+ std::set<std::string> new_item_titles;// duplicate control
+ LLTeleportHistory::slurl_list_t::iterator result = std::find_if(
+ th_items.begin(), th_items.end(), boost::bind(
+ &LLLocationInputCtrl::findTeleportItemsByTitle, this,
+ _1, filter));
+
+ while (result != th_items.end())
+ {
+ //mTitile format - region_name[, parcel_name]
+ //mFullTitile format - region_name[, parcel_name] (local_x,local_y, local_z)
+ if (new_item_titles.insert(result->mFullTitle).second)
+ {
+ LLSD value;
+ value["item_type"] = TELEPORT_HISTORY;
+ value["global_pos"] = result->mGlobalPos.getValue();
+ std::string region_name = result->mTitle.substr(0, result->mTitle.find(','));
+ //TODO*: add Surl to teleportitem or parse region name from title
+ value["tooltip"] = LLSLURL::buildSLURLfromPosGlobal(region_name,
+ result->mGlobalPos, false);
+ add(result->getTitle(), value);
+ }
+ result = std::find_if(result + 1, th_items.end(), boost::bind(
+ &LLLocationInputCtrl::findTeleportItemsByTitle, this,
+ _1, filter));
}
}
+ sortByName();
+
mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
}
-
+bool LLLocationInputCtrl::findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter)
+{
+ return item.mTitle.find(filter) != std::string::npos;
+}
void LLLocationInputCtrl::onTextEditorRightClicked(S32 x, S32 y, MASK mask)
{
if (mLocationContextMenu)
@@ -519,7 +569,12 @@ void LLLocationInputCtrl::rebuildLocationHistory(std::string filter)
removeall();
for (LLLocationHistory::location_list_t::const_reverse_iterator it = itemsp->rbegin(); it != itemsp->rend(); it++)
{
- add(*it);
+ LLSD value;
+ value["tooltip"] = it->getToolTip();
+ //location history can contain only typed locations
+ value["item_type"] = TYPED_REGION_SURL;
+ value["global_pos"] = it->mGlobalPos.getValue();
+ add(it->getLocation(), value);
}
}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index d967df8257..6edae9a9e2 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -41,6 +41,7 @@ class LLLandmark;
class LLAddLandmarkObserver;
class LLRemoveLandmarkObserver;
class LLMenuGL;
+class LLTeleportHistoryItem;
/**
* Location input control.
@@ -70,7 +71,7 @@ public:
// LLView interface
/*virtual*/ void setEnabled(BOOL enabled);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
@@ -103,6 +104,7 @@ private:
void refresh();
void refreshLocation();
void rebuildLocationHistory(std::string filter = "");
+ bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter);
void setText(const LLStringExplicit& text);
void updateAddLandmarkButton();
void updateContextMenu();
diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h
index 0844b80c7c..d36ceaf3cc 100644
--- a/indra/newview/llloginhandler.h
+++ b/indra/newview/llloginhandler.h
@@ -39,7 +39,7 @@ class LLLoginHandler : public LLCommandHandler
{
public:
// allow from external browsers
- LLLoginHandler() : LLCommandHandler("login", false) { }
+ LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { }
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web);
// Fill in our internal fields from a SLURL like
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index d1d112c4bf..14a8b7cb59 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -49,7 +49,7 @@
#include "llbutton.h"
#include "llviewercontrol.h"
#include "llcriticaldamp.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
#include "llstatusbar.h"
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index cc2531d139..2153f77336 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -379,7 +379,7 @@ BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
}
else if (gSavedSettings.getBOOL("SnapToMouseCursor"))
{
- LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
+ LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY);
x = mouse_pos.mX;
y = mouse_pos.mY;
}
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 62b38f2b4a..09a7edaa43 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -916,15 +916,8 @@ void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self )
//
void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self )
{
+ // let the dispatcher handle blocking/throttling of SLURLs
std::string url = self->getClickURL();
- if (LLSLURL::isSLURLCommand(url)
- && !mTrusted)
- {
- // block handling of this secondlife:///app/ URL
- LLNotifications::instance().add("UnableToOpenCommandURL");
- return;
- }
-
LLURLDispatcher::dispatch(url, this, mTrusted);
}
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 3c7716e9c2..b3aa67733b 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -32,11 +32,11 @@
#include "llviewerprecompiledheaders.h"
-#include "indra_constants.h"
#include "llmemoryview.h"
#include "llappviewer.h"
#include "llallocator_heap_profile.h"
+#include "llgl.h" // LLGLSUIDefault
#include "llviewerwindow.h"
#include "llviewercontrol.h"
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 1b82c2dc18..8ef6b25c50 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -61,9 +61,9 @@ LLNameListCtrl::Params::Params()
LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
: LLScrollListCtrl(p),
- mAllowCallingCardDrop(p.allow_calling_card_drop),
+ mNameColumnIndex(p.name_column.column_index),
mNameColumn(p.name_column.column_name),
- mNameColumnIndex(p.name_column.column_index)
+ mAllowCallingCardDrop(p.allow_calling_card_drop)
{}
// public
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index e40568a0cb..b1db51dd26 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -45,7 +45,7 @@
#include "lllocationhistory.h"
#include "lllocationinputctrl.h"
#include "llteleporthistory.h"
-#include "llsearcheditor.h"
+#include "llsearchcombobox.h"
#include "llsidetray.h"
#include "llslurl.h"
#include "llurlsimstring.h"
@@ -62,6 +62,8 @@
#include "llfavoritesbar.h"
#include "llagentui.h"
+#include <boost/regex.hpp>
+
//-- LLTeleportHistoryMenuItem -----------------------------------------------
/**
@@ -82,7 +84,6 @@ public:
Mandatory<EType> item_type;
Params() {}
- Params(EType type, std::string title);
};
/*virtual*/ void draw();
@@ -104,24 +105,21 @@ private:
const std::string LLTeleportHistoryMenuItem::ICON_IMG_BACKWARD("teleport_history_backward.tga");
const std::string LLTeleportHistoryMenuItem::ICON_IMG_FORWARD("teleport_history_forward.tga");
-LLTeleportHistoryMenuItem::Params::Params(EType type, std::string title)
-{
- item_type(type);
- font.name("SANSSERIF");
-
- if (type == TYPE_CURRENT)
- font.style("BOLD");
- else
- title = " " + title;
-
- name(title);
- label(title);
-}
-
LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p)
: LLMenuItemCallGL(p),
mArrowIcon(NULL)
{
+ // Set appearance depending on the item type.
+ if (p.item_type == TYPE_CURRENT)
+ {
+ setFont(LLFontGL::getFontSansSerifBold());
+ }
+ else
+ {
+ setFont(LLFontGL::getFontSansSerif());
+ setLabel(std::string(" ") + std::string(p.label));
+ }
+
LLIconCtrl::Params icon_params;
icon_params.name("icon");
icon_params.rect(LLRect(0, ICON_HEIGHT, ICON_WIDTH, 0));
@@ -183,14 +181,11 @@ LLNavigationBar::LLNavigationBar()
mBtnForward(NULL),
mBtnHome(NULL),
mCmbLocation(NULL),
- mLeSearch(NULL),
+ mSearchComboBox(NULL),
mPurgeTPHistoryItems(false)
{
setIsChrome(TRUE);
- mParcelMgrConnection = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(
- boost::bind(&LLNavigationBar::onTeleportFinished, this, _1));
-
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml");
// set a listener function for LoginComplete event
@@ -202,8 +197,10 @@ LLNavigationBar::LLNavigationBar()
LLNavigationBar::~LLNavigationBar()
{
- mParcelMgrConnection.disconnect();
+ mTeleportFinishConnection.disconnect();
sInstance = 0;
+
+ LLSearchHistory::getInstance()->save();
}
BOOL LLNavigationBar::postBuild()
@@ -213,10 +210,12 @@ BOOL LLNavigationBar::postBuild()
mBtnHome = getChild<LLButton>("home_btn");
mCmbLocation= getChild<LLLocationInputCtrl>("location_combo");
- mLeSearch = getChild<LLSearchEditor>("search_input");
+ mSearchComboBox = getChild<LLSearchComboBox>("search_combo_box");
+
+ fillSearchComboBox();
if (!mBtnBack || !mBtnForward || !mBtnHome ||
- !mCmbLocation || !mLeSearch)
+ !mCmbLocation || !mSearchComboBox)
{
llwarns << "Malformed navigation bar" << llendl;
return FALSE;
@@ -234,7 +233,7 @@ BOOL LLNavigationBar::postBuild()
mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this));
- mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));
+ mSearchComboBox->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));
mDefaultNbRect = getRect();
mDefaultFpRect = getChild<LLFavoritesBarCtrl>("favorite")->getRect();
@@ -246,6 +245,25 @@ BOOL LLNavigationBar::postBuild()
return TRUE;
}
+void LLNavigationBar::fillSearchComboBox()
+{
+ if(!mSearchComboBox)
+ {
+ return;
+ }
+
+ LLSearchHistory::getInstance()->load();
+
+ LLSearchHistory::search_history_list_t search_list =
+ LLSearchHistory::getInstance()->getSearchHistoryList();
+ LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin();
+ for( ; search_list.end() != it; ++it)
+ {
+ LLSearchHistory::LLSearchHistoryItem item = *it;
+ mSearchComboBox->add(item.search_query);
+ }
+}
+
void LLNavigationBar::draw()
{
if(mPurgeTPHistoryItems)
@@ -280,7 +298,12 @@ void LLNavigationBar::onHomeButtonClicked()
void LLNavigationBar::onSearchCommit()
{
- invokeSearch(mLeSearch->getValue().asString());
+ std::string search_query = mSearchComboBox->getSimple();
+ if(!search_query.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(search_query);
+ }
+ invokeSearch(search_query);
}
void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata)
@@ -299,69 +322,107 @@ void LLNavigationBar::onLocationSelection()
if (typed_location.empty())
return;
+ LLSD value = mCmbLocation->getSelectedValue();
+
+ if(value.has("item_type"))
+ {
+
+ switch(value["item_type"].asInteger())
+ {
+ case LANDMARK:
+
+ if(value.has("AssetUUID"))
+ {
+
+ gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString()));
+ return;
+ }
+ else
+ {
+ LLInventoryModel::item_array_t landmark_items =
+ LLLandmarkActions::fetchLandmarksByName(typed_location,
+ FALSE);
+ if (!landmark_items.empty())
+ {
+ gAgent.teleportViaLandmark( landmark_items[0]->getAssetUUID());
+ return;
+ }
+ }
+ break;
+
+ case TELEPORT_HISTORY:
+ //in case of teleport item was selected, teleport by position too.
+ case TYPED_REGION_SURL:
+ if(value.has("global_pos"))
+ {
+ gAgent.teleportViaLocation(LLVector3d(value["global_pos"]));
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ //Let's parse surl or region name
+
std::string region_name;
LLVector3 local_coords(128, 128, 0);
S32 x = 0, y = 0, z = 0;
-
// Is the typed location a SLURL?
if (LLSLURL::isSLURL(typed_location))
{
// Yes. Extract region name and local coordinates from it.
if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), &region_name, &x, &y, &z))
- local_coords.set(x, y, z);
+ local_coords.set(x, y, z);
else
return;
- }
- else
+ }else
{
- //If it is not slurl let's look for landmarks
- LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(typed_location, FALSE);
- if ( !landmark_items.empty() )
- {
- gAgent.teleportViaLandmark(landmark_items[0]->getAssetUUID());
- return;
- }
- //No landmark match, check if it is a region name
- region_name = parseLocation(typed_location, &x, &y, &z);
- if (region_name != typed_location)
- local_coords.set(x, y, z);
-
- // Treat it as region name.
- // region_name = typed_location;
+ // assume that an user has typed the {region name} or possible {region_name, parcel}
+ region_name = typed_location.substr(0,typed_location.find(','));
}
-
+
// Resolve the region name to its global coordinates.
// If resolution succeeds we'll teleport.
LLWorldMap::url_callback_t cb = boost::bind(
&LLNavigationBar::onRegionNameResponse, this,
typed_location, region_name, local_coords, _1, _2, _3, _4);
+ // connect the callback each time, when user enter new location to get real location of agent after teleport
+ mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+ setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1,typed_location));
+
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false);
}
-void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos)
+void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location)
{
// Location is valid. Add it to the typed locations history.
LLLocationHistory* lh = LLLocationHistory::getInstance();
+ //TODO*: do we need convert surl into readable format?
std::string location;
/*NOTE:
* We can't use gAgent.getPositionAgent() in case of local teleport to build location.
* At this moment gAgent.getPositionAgent() contains previous coordinates.
* according to EXT-65 agent position is being reseted on each frame.
*/
- LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM,
- gAgent.getPosAgentFromGlobal(global_agent_pos));
+ LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM,
+ gAgent.getPosAgentFromGlobal(global_agent_pos));
+ std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false));
+ LLLocationHistoryItem item (location,
+ global_agent_pos, tooltip,TYPED_REGION_SURL);// we can add into history only TYPED location
//Touch it, if it is at list already, add new location otherwise
- if ( !lh->touchItem(location) ) {
- std::string tooltip = LLSLURL::buildSLURLfromPosGlobal(
- gAgent.getRegion()->getName(), global_agent_pos, false);
-
- lh->addItem(location, tooltip);
+ if ( !lh->touchItem(item) ) {
+ lh->addItem(item);
}
- llinfos << "Saving after on teleport finish" << llendl;
- lh->save();
+ lh->save();
+
+ if(mTeleportFinishConnection.connected())
+ mTeleportFinishConnection.disconnect();
+
}
void LLNavigationBar::onTeleportHistoryChanged()
@@ -411,9 +472,13 @@ void LLNavigationBar::rebuildTeleportHistoryMenu()
else
type = LLTeleportHistoryMenuItem::TYPE_CURRENT;
- LLTeleportHistoryMenuItem::Params item_params(type, hist_items[i].getTitle());
+ LLTeleportHistoryMenuItem::Params item_params;
+ item_params.label = item_params.name = hist_items[i].getTitle();
+ item_params.item_type = type;
item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i));
- mTeleportHistoryMenu->addChild(LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params));
+ LLTeleportHistoryMenuItem* new_itemp = LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params);
+ //new_itemp->setFont()
+ mTeleportHistoryMenu->addChild(new_itemp);
}
}
@@ -433,8 +498,8 @@ void LLNavigationBar::onRegionNameResponse(
// Teleport to the location.
LLVector3d region_pos = from_region_handle(region_handle);
LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
-
- llinfos << "Teleporting to: " << global_pos << llendl;
+
+ llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name, global_pos, false) << llendl;
gAgent.teleportViaLocation(global_pos);
}
@@ -472,35 +537,6 @@ void LLNavigationBar::invokeSearch(std::string search_text)
LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text)));
}
-std::string LLNavigationBar::parseLocation(const std::string & location, S32* x, S32* y, S32* z) {
- /*
- * This regular expression extracts numbers from the following string
- * construct: "(num1, num2, num3)", where num1, num2 and num3 are decimal
- * numbers. Leading and trailing spaces are also caught by the expression.
- */
- const boost::regex re("\\s*\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)\\s*");
-
- boost::smatch m;
- if (boost::regex_search(location, m, re)) {
- // string representations of parsed by regex++ numbers
- std::string xstr(m[1].first, m[1].second);
- std::string ystr(m[2].first, m[2].second);
- std::string zstr(m[3].first, m[3].second);
-
- *x = atoi(xstr.c_str());
- *y = atoi(ystr.c_str());
- *z = atoi(zstr.c_str());
- //erase commas in coordinates
- std::string region_parcel = boost::regex_replace(location, re, "");
- // cut region name
- return region_parcel.substr(0, region_parcel.find_first_of(','));
- }
-
- *x = *y = *z = 0;
-
- return location;
-}
-
void LLNavigationBar::clearHistoryCache()
{
mCmbLocation->removeall();
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 6932847854..8a65cd24fa 100644
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -41,6 +41,7 @@ class LLButton;
class LLLocationInputCtrl;
class LLMenuGL;
class LLSearchEditor;
+class LLSearchComboBox;
/**
* Web browser-like navigation bar.
@@ -69,12 +70,6 @@ private:
void rebuildTeleportHistoryMenu();
void showTeleportHistoryMenu();
void invokeSearch(std::string search_text);
-
- /**
- * Get region name and local coordinates from typed location
- */
- static std::string parseLocation(const std::string & location, S32* x, S32* y, S32* z);
-
// callbacks
void onTeleportHistoryMenuItemClicked(const LLSD& userdata);
void onTeleportHistoryChanged();
@@ -86,7 +81,7 @@ private:
void onLocationSelection();
void onLocationPrearrange(const LLSD& data);
void onSearchCommit();
- void onTeleportFinished(const LLVector3d& global_agent_pos);
+ void onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location);
void onRegionNameResponse(
std::string typed_location,
std::string region_name,
@@ -94,17 +89,19 @@ private:
U64 region_handle, const std::string& url,
const LLUUID& snapshot_id, bool teleport);
+ void fillSearchComboBox();
+
static LLNavigationBar *sInstance;
LLMenuGL* mTeleportHistoryMenu;
LLButton* mBtnBack;
LLButton* mBtnForward;
LLButton* mBtnHome;
- LLSearchEditor* mLeSearch;
+ LLSearchComboBox* mSearchComboBox;
LLLocationInputCtrl* mCmbLocation;
LLRect mDefaultNbRect;
LLRect mDefaultFpRect;
- boost::signals2::connection mParcelMgrConnection;
+ boost::signals2::connection mTeleportFinishConnection;
bool mPurgeTPHistoryItems;
};
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 3856a86da0..6150d5da37 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -183,9 +183,13 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color)
{
- std::string line = chat.mFromName;
- line +=": ";
- line +=chat.mText;
+ std::string line = chat.mText;
+
+ //chat.mText starts with Avatar Name if entered message was "/me <action>".
+ // In this case output chat message should be "<Avatar Name> <action>". See EXT-656
+ // See also process_chat_from_simulator() in the llviewermessage.cpp where ircstyle = TRUE;
+ if (CHAT_STYLE_IRC != chat.mChatStyle)
+ line = chat.mFromName + ": " + line;
bool prepend_newline = true;
if (gSavedSettings.getBOOL("ChatShowTimestamps"))
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index d4a9be0355..e348189ea9 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -32,6 +32,9 @@
#include "llviewerprecompiledheaders.h"
+#include "llfloaterreg.h"
+#include "lltrans.h"
+
#include "llnearbychatbar.h"
#include "llbottomtray.h"
#include "llagent.h"
@@ -45,7 +48,7 @@
S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
-// legacy calllback glue
+// legacy callback glue
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
static LLDefaultChildRegistry::Register<LLGestureComboBox> r("gesture_combo_box");
@@ -64,6 +67,7 @@ LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p)
: LLComboBox(p)
, mGestureLabelTimer()
, mLabel(p.label)
+ , mViewAllItemIndex(0)
{
setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this));
@@ -102,6 +106,11 @@ void LLGestureComboBox::refreshGestures()
}
sortByName();
+
+ // store index followed by the last added Gesture and add View All item at bottom
+ mViewAllItemIndex = idx;
+ addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex));
+
// Insert label after sorting, at top, with separator below it
addSeparator(ADD_TOP);
addSimpleElement(mLabel, ADD_TOP);
@@ -128,6 +137,15 @@ void LLGestureComboBox::onCommitGesture()
}
index = gestures->getSelectedValue().asInteger();
+
+ if (mViewAllItemIndex == index)
+ {
+ // The same behavior as Ctrl+G. EXT-823
+ LLFloaterReg::toggleInstance("gestures");
+ gestures->selectFirstItem();
+ return;
+ }
+
LLMultiGesture* gesture = mGestures.at(index);
if(gesture)
{
@@ -598,7 +616,7 @@ class LLChatHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
- LLChatHandler() : LLCommandHandler("chat", true) { }
+ LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index 19177e37b3..f310740f42 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -63,6 +63,7 @@ protected:
LLFrameTimer mGestureLabelTimer;
std::vector<LLMultiGesture*> mGestures;
std::string mLabel;
+ LLSD::Integer mViewAllItemIndex;
};
class LLNearbyChatBar
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 7b0b0c2fb7..5e65f2244d 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -35,15 +35,19 @@
#include "llnetmap.h"
+// Library includes (should move below)
#include "indra_constants.h"
#include "llmath.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
#include "llrender.h"
#include "llui.h"
+#include "lltooltip.h"
#include "llglheaders.h"
+// Viewer includes
#include "llagent.h"
#include "llappviewer.h" // for gDisconnected
#include "llcallingcard.h" // LLAvatarTracker
@@ -286,7 +290,7 @@ void LLNetMap::draw()
S32 local_mouse_x;
S32 local_mouse_y;
//localMouse(&local_mouse_x, &local_mouse_y);
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
mClosestAgentToCursor.setNull();
F32 closest_dist = F32_MAX;
@@ -496,9 +500,8 @@ BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
-BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen )
+BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen )
{
- BOOL handled = FALSE;
if (gDisconnected)
{
return FALSE;
@@ -530,19 +533,23 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec
msg = mToolTipMsg;
LLStringUtil::format(msg, args);
+ LLRect sticky_rect;
// set sticky_rect
if (region)
{
S32 SLOP = 4;
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;
+ &(sticky_rect.mLeft), &(sticky_rect.mBottom) );
+ sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP;
+ sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP;
}
-
- handled = TRUE;
- return handled;
+
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(msg)
+ .sticky_rect(sticky_rect));
+
+ return TRUE;
}
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index a673ea3f57..7598154480 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -67,7 +67,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen );
+ /*virtual*/ BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen );
void setScale( F32 scale );
void setRotateMap( BOOL b ) { mRotateMap = b; }
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
index d088c45710..49b48f5a8e 100644
--- a/indra/newview/lloutputmonitorctrl.cpp
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -38,6 +38,8 @@
// viewer includes
#include "llvoiceclient.h"
+#include "llmutelist.h"
+#include "llagent.h"
// default options set in output_monitor.xml
static LLDefaultChildRegistry::Register<LLOutputMonitorCtrl> r("output_monitor");
@@ -58,7 +60,9 @@ LLOutputMonitorCtrl::Params::Params()
image_on("image_on"),
image_level_1("image_level_1"),
image_level_2("image_level_2"),
- image_level_3("image_level_3")
+ image_level_3("image_level_3"),
+ auto_update("auto_update"),
+ speaker_id("speaker_id")
{
draw_border = true;
name = "output_monitor";
@@ -69,14 +73,14 @@ LLOutputMonitorCtrl::Params::Params()
LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
: LLView(p),
mPower(0),
- mIsMuted(true),
- mIsTalking(false),
mImageMute(p.image_mute),
mImageOff(p.image_off),
mImageOn(p.image_on),
mImageLevel1(p.image_level_1),
mImageLevel2(p.image_level_2),
- mImageLevel3(p.image_level_3)
+ mImageLevel3(p.image_level_3),
+ mAutoUpdate(p.auto_update),
+ mSpeakerId(p.speaker_id)
{
//static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange);
//static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red);
@@ -99,10 +103,14 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
//sRectHeightRatio = output_monitor_rect_height_ratio;
mBorder = p.draw_border;
+
+ //with checking mute state
+ setSpeakerId(mSpeakerId);
}
LLOutputMonitorCtrl::~LLOutputMonitorCtrl()
{
+ LLMuteList::getInstance()->removeObserver(this);
}
void LLOutputMonitorCtrl::setPower(F32 val)
@@ -121,6 +129,12 @@ void LLOutputMonitorCtrl::draw()
const F32 LEVEL_1 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL * 2.f / 3.f;
const F32 LEVEL_2 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
+ if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull())
+ {
+ setPower(gVoiceClient->getCurrentPower(mSpeakerId));
+ setIsTalking(gVoiceClient->getUserPTTState());
+ }
+
LLPointer<LLUIImage> icon;
if (mIsMuted)
{
@@ -205,3 +219,29 @@ void LLOutputMonitorCtrl::draw()
if(mBorder)
gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);
}
+
+void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id)
+{
+ if (speaker_id.isNull()) return;
+
+ mSpeakerId = speaker_id;
+
+ //mute management
+ if (mAutoUpdate)
+ {
+ if (speaker_id == gAgentID)
+ {
+ setIsMuted(false);
+ }
+ else
+ {
+ setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId));
+ LLMuteList::getInstance()->addObserver(this);
+ }
+ }
+}
+
+void LLOutputMonitorCtrl::onChange()
+{
+ setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId));
+}
diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
index 98b2fe9dc6..7a7b8bc3a1 100644
--- a/indra/newview/lloutputmonitorctrl.h
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -35,6 +35,7 @@
#include "v4color.h"
#include "llview.h"
+#include "llmutelist.h"
class LLTextBox;
class LLUICtrlFactory;
@@ -44,7 +45,7 @@ class LLUICtrlFactory;
//
class LLOutputMonitorCtrl
-: public LLView
+: public LLView, LLMuteListObserver
{
public:
struct Params : public LLInitParam::Block<Params, LLView::Params>
@@ -56,6 +57,8 @@ public:
image_level_1,
image_level_2,
image_level_3;
+ Optional<bool> auto_update;
+ Optional<LLUUID> speaker_id;
Params();
};
@@ -80,6 +83,11 @@ public:
// correct button image.
void setIsTalking(bool val) { mIsTalking = val; }
+ void setSpeakerId(const LLUUID& speaker_id);
+
+ //called by mute list
+ virtual void onChange();
+
private:
//static LLColor4 sColorMuted;
//static LLColor4 sColorNormal;
@@ -89,6 +97,8 @@ private:
//static F32 sRectWidthRatio;
//static F32 sRectHeightRatio;
+
+
F32 mPower;
bool mIsMuted;
bool mIsTalking;
@@ -98,6 +108,12 @@ private:
LLPointer<LLUIImage> mImageLevel1;
LLPointer<LLUIImage> mImageLevel2;
LLPointer<LLUIImage> mImageLevel3;
+
+ /** whether to deal with gVoiceClient directly */
+ bool mAutoUpdate;
+
+ /** uuid of a speaker being monitored */
+ LLUUID mSpeakerId;
};
#endif
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 6e94b087a6..b7f2f67a9a 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -35,7 +35,7 @@
#include "llagent.h"
#include "llavataractions.h"
-#include "llavatarconstants.h"
+#include "llavatarconstants.h" // AVATAR_ONLINE
#include "llcallingcard.h"
#include "llcombobox.h"
#include "llimview.h"
@@ -131,7 +131,8 @@ LLPanelAvatarNotes::LLPanelAvatarNotes()
void LLPanelAvatarNotes::updateData()
{
- LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_NOTES);
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarNotesRequest(getAvatarId());
}
BOOL LLPanelAvatarNotes::postBuild()
@@ -356,8 +357,10 @@ void LLPanelAvatarProfile::updateData()
{
if (getAvatarId().notNull())
{
- LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_PROPERTIES);
- LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_GROUPS);
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarPropertiesRequest(getAvatarId());
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarGroupsRequest(getAvatarId());
}
}
@@ -372,7 +375,6 @@ void LLPanelAvatarProfile::resetControls()
childSetVisible("status_me_panel", false);
childSetVisible("profile_me_buttons_panel", false);
childSetVisible("account_actions_panel", false);
- childSetVisible("partner_edit_link", false);
}
void LLPanelAvatarProfile::resetData()
@@ -444,7 +446,7 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
- childSetValue("register_date", avatar_data->born_on);
+ childSetValue("register_date", LLAvatarPropertiesProcessor::ageFromDate(avatar_data->born_on));
childSetValue("sl_description_edit", avatar_data->about_text);
childSetValue("fl_description_edit",avatar_data->fl_about_text);
childSetValue("2nd_life_pic", avatar_data->image_id);
@@ -487,59 +489,17 @@ void LLPanelAvatarProfile::fillOnlineStatus(const LLAvatarData* avatar_data)
void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data)
{
- std::string caption_text = avatar_data->caption_text;
- if(caption_text.empty())
- {
- LLStringUtil::format_map_t args;
- caption_text = getString("CaptionTextAcctInfo");
- BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED);
- BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED);
- BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED); // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
-
- const char* ACCT_TYPE[] = {
- "AcctTypeResident",
- "AcctTypeTrial",
- "AcctTypeCharterMember",
- "AcctTypeEmployee"
- };
- U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, (U8)(LL_ARRAY_SIZE(ACCT_TYPE)-1));
- args["[ACCTTYPE]"] = getString(ACCT_TYPE[caption_index]);
-
- std::string payment_text = " ";
- const S32 DEFAULT_CAPTION_LINDEN_INDEX = 3;
- if(caption_index != DEFAULT_CAPTION_LINDEN_INDEX)
- {
- if(transacted)
- {
- payment_text = "PaymentInfoUsed";
- }
- else if (identified)
- {
- payment_text = "PaymentInfoOnFile";
- }
- else
- {
- payment_text = "NoPaymentInfoOnFile";
- }
- args["[PAYMENTINFO]"] = getString(payment_text);
-
- std::string age_text = age_verified ? "AgeVerified" : "NotAgeVerified";
- // Do not display age verification status at this time
- //args["[[AGEVERIFICATION]]"] = mPanelSecondLife->getString(age_text);
- args["[AGEVERIFICATION]"] = " ";
- }
- else
- {
- args["[PAYMENTINFO]"] = " ";
- args["[AGEVERIFICATION]"] = " ";
- }
- LLStringUtil::format(caption_text, args);
- }
-
+ LLStringUtil::format_map_t args;
+ args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data);
+ args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data);
+ // *NOTE: AVATAR_AGEVERIFIED not currently getting set in
+ // dataserver/lldataavatar.cpp for privacy considerations
+ args["[AGEVERIFICATION]"] = "";
+ std::string caption_text = getString("CaptionTextAcctInfo", args);
childSetValue("acc_status_text", caption_text);
}
-void LLPanelAvatarProfile::onUrlTextboxClicked(std::string url)
+void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url)
{
LLWeb::loadURL(url);
}
@@ -595,9 +555,6 @@ BOOL LLPanelAvatarMeProfile::postBuild()
childSetCommitCallback("status_combo", boost::bind(&LLPanelAvatarMeProfile::onStatusChanged, this), NULL);
childSetCommitCallback("status_me_message_text", boost::bind(&LLPanelAvatarMeProfile::onStatusMessageChanged, this), NULL);
- childSetActionTextbox("payment_update_link", boost::bind(&LLPanelAvatarMeProfile::onUpdateAccountTextboxClicked, this));
- childSetActionTextbox("my_account_link", boost::bind(&LLPanelAvatarMeProfile::onMyAccountTextboxClicked, this));
- childSetActionTextbox("partner_edit_link", boost::bind(&LLPanelAvatarMeProfile::onPartnerEditTextboxClicked, this));
resetControls();
resetData();
@@ -676,18 +633,3 @@ void LLPanelAvatarMeProfile::onStatusMessageChanged()
{
updateData();
}
-
-void LLPanelAvatarMeProfile::onUpdateAccountTextboxClicked()
-{
- onUrlTextboxClicked(getString("payment_update_link_url"));
-}
-
-void LLPanelAvatarMeProfile::onMyAccountTextboxClicked()
-{
- onUrlTextboxClicked(getString("my_account_link_url"));
-}
-
-void LLPanelAvatarMeProfile::onPartnerEditTextboxClicked()
-{
- onUrlTextboxClicked(getString("partner_edit_link_url"));
-}
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index 51bd619901..1ed5fa4357 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -166,7 +166,7 @@ protected:
*/
virtual void fillAccountStatus(const LLAvatarData* avatar_data);
- void onUrlTextboxClicked(std::string url);
+ void onUrlTextboxClicked(const std::string& url);
void onHomepageTextboxClicked();
void onAddFriendButtonClick();
void onIMButtonClick();
@@ -203,9 +203,6 @@ protected:
void onStatusChanged();
void onStatusMessageChanged();
- void onUpdateAccountTextboxClicked();
- void onMyAccountTextboxClicked();
- void onPartnerEditTextboxClicked();
private:
diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp
new file mode 100644
index 0000000000..60d0f07285
--- /dev/null
+++ b/indra/newview/llpanelblockedlist.cpp
@@ -0,0 +1,279 @@
+/**
+ * @file llpanelblockedlist.cpp
+ * @brief Container for blocked Residents & Objects list
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llscrolllistctrl.h"
+
+#include "llpanelblockedlist.h"
+
+// project include
+#include "llfloateravatarpicker.h"
+#include "llsidetray.h"
+#include "llsidetraypanelcontainer.h"
+
+static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray");
+
+//
+// Constants
+//
+const std::string BLOCKED_PARAM_NAME = "blocked_to_select";
+
+//-----------------------------------------------------------------------------
+// LLPanelBlockedList()
+//-----------------------------------------------------------------------------
+
+LLPanelBlockedList::LLPanelBlockedList()
+: LLPanel()
+{
+ mCommitCallbackRegistrar.add("Block.ClickPick", boost::bind(&LLPanelBlockedList::onPickBtnClick, this));
+ mCommitCallbackRegistrar.add("Block.ClickBlockByName", boost::bind(&LLPanelBlockedList::onBlockByNameClick, this));
+ mCommitCallbackRegistrar.add("Block.ClickRemove", boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this));
+}
+
+LLPanelBlockedList::~LLPanelBlockedList()
+{
+ LLMuteList::getInstance()->removeObserver(this);
+}
+
+BOOL LLPanelBlockedList::postBuild()
+{
+ mBlockedList = getChild<LLScrollListCtrl>("blocked");
+ mBlockedList->setCommitOnSelectionChange(TRUE);
+
+ childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL);
+
+ LLMuteList::getInstance()->addObserver(this);
+
+ refreshBlockedList();
+
+ return LLPanel::postBuild();
+}
+
+void LLPanelBlockedList::draw()
+{
+ updateButtons();
+ LLPanel::draw();
+}
+
+void LLPanelBlockedList::onOpen(const LLSD& key)
+{
+ if (key.has(BLOCKED_PARAM_NAME) && key[BLOCKED_PARAM_NAME].asUUID().notNull())
+ {
+ selectBlocked(key[BLOCKED_PARAM_NAME].asUUID());
+ }
+}
+
+void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)
+{
+ mBlockedList->selectByID(mute_id);
+}
+
+void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)
+{
+ LLSideTray::getInstance()->showPanel("panel_block_list_sidetray", LLSD().insert(BLOCKED_PARAM_NAME, idToSelect));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+//////////////////////////////////////////////////////////////////////////
+void LLPanelBlockedList::refreshBlockedList()
+{
+ mBlockedList->deleteAllItems();
+
+ std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes();
+ std::vector<LLMute>::iterator it;
+ for (it = mutes.begin(); it != mutes.end(); ++it)
+ {
+ std::string display_name = it->getDisplayName();
+ mBlockedList->addStringUUIDItem(display_name, it->mID, ADD_BOTTOM, TRUE);
+ }
+}
+
+void LLPanelBlockedList::updateButtons()
+{
+ bool hasSelected = NULL != mBlockedList->getFirstSelected();
+ childSetEnabled("Unblock", hasSelected);
+}
+
+
+
+void LLPanelBlockedList::onBackBtnClick()
+{
+ LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if(parent)
+ {
+ parent->openPreviousPanel();
+ }
+}
+
+void LLPanelBlockedList::onRemoveBtnClick()
+{
+ std::string name = mBlockedList->getSelectedItemLabel();
+ LLUUID id = mBlockedList->getStringUUIDSelectedItem();
+ LLMute mute(id);
+ mute.setFromDisplayName(name);
+ // now mute.mName has the suffix trimmed off
+
+ S32 last_selected = mBlockedList->getFirstSelectedIndex();
+ if (LLMuteList::getInstance()->remove(mute))
+ {
+ // Above removals may rebuild this dialog.
+
+ if (last_selected == mBlockedList->getItemCount())
+ {
+ // we were on the last item, so select the last item again
+ mBlockedList->selectNthItem(last_selected - 1);
+ }
+ else
+ {
+ // else select the item after the last item previously selected
+ mBlockedList->selectNthItem(last_selected);
+ }
+ }
+}
+
+void LLPanelBlockedList::onPickBtnClick()
+{
+ const BOOL allow_multiple = FALSE;
+ const BOOL close_on_select = TRUE;
+ /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(callbackBlockPicked, this, allow_multiple, close_on_select);
+
+ // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed?
+ // old Floater dependency is not enable in panel
+ // addDependentFloater(picker);
+}
+
+void LLPanelBlockedList::onBlockByNameClick()
+{
+ LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);
+}
+
+//static
+void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data)
+{
+ if (names.empty() || ids.empty()) return;
+ LLMute mute(ids[0], names[0], LLMute::AGENT);
+ LLMuteList::getInstance()->add(mute);
+ showPanelAndSelect(mute.mID);
+}
+
+//static
+void LLPanelBlockedList::callbackBlockByName(const std::string& text)
+{
+ if (text.empty()) return;
+
+ LLMute mute(LLUUID::null, text, LLMute::BY_NAME);
+ BOOL success = LLMuteList::getInstance()->add(mute);
+ if (!success)
+ {
+ LLNotifications::instance().add("MuteByNameFailed");
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// LLFloaterGetBlockedObjectName
+//////////////////////////////////////////////////////////////////////////
+
+// Constructor/Destructor
+LLFloaterGetBlockedObjectName::LLFloaterGetBlockedObjectName(const LLSD& key)
+: LLFloater(key)
+, mGetObjectNameCallback(NULL)
+{
+}
+
+// Destroys the object
+LLFloaterGetBlockedObjectName::~LLFloaterGetBlockedObjectName()
+{
+ gFocusMgr.releaseFocusIfNeeded( this );
+}
+
+BOOL LLFloaterGetBlockedObjectName::postBuild()
+{
+ getChild<LLButton>("OK")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::applyBlocking, this));
+ getChild<LLButton>("Cancel")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::cancelBlocking, this));
+ center();
+
+ return LLFloater::postBuild();
+}
+
+BOOL LLFloaterGetBlockedObjectName::handleKeyHere(KEY key, MASK mask)
+{
+ if (key == KEY_RETURN && mask == MASK_NONE)
+ {
+ applyBlocking();
+ return TRUE;
+ }
+ else if (key == KEY_ESCAPE && mask == MASK_NONE)
+ {
+ cancelBlocking();
+ return TRUE;
+ }
+
+ return LLFloater::handleKeyHere(key, mask);
+}
+
+// static
+LLFloaterGetBlockedObjectName* LLFloaterGetBlockedObjectName::show(get_object_name_callback_t callback)
+{
+ LLFloaterGetBlockedObjectName* floater = LLFloaterReg::showTypedInstance<LLFloaterGetBlockedObjectName>("mute_object_by_name");
+
+ floater->mGetObjectNameCallback = callback;
+
+ // *TODO: mantipov: should LLFloaterGetBlockedObjectName be closed when panel is closed?
+ // old Floater dependency is not enable in panel
+ // addDependentFloater(floater);
+
+ return floater;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+void LLFloaterGetBlockedObjectName::applyBlocking()
+{
+ if (mGetObjectNameCallback)
+ {
+ const std::string& text = childGetValue("object_name").asString();
+ mGetObjectNameCallback(text);
+ }
+ closeFloater();
+}
+
+void LLFloaterGetBlockedObjectName::cancelBlocking()
+{
+ closeFloater();
+}
+
+//EOF
diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h
new file mode 100644
index 0000000000..52b74a184b
--- /dev/null
+++ b/indra/newview/llpanelblockedlist.h
@@ -0,0 +1,115 @@
+/**
+ * @file llpanelblockedlist.h
+ * @brief Container for blocked Residents & Objects list
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELBLOCKEDLIST_H
+#define LL_LLPANELBLOCKEDLIST_H
+
+#include "llpanel.h"
+#include "llmutelist.h"
+// #include <vector>
+
+// class LLButton;
+// class LLLineEditor;
+// class LLMessageSystem;
+// class LLUUID;
+ class LLScrollListCtrl;
+
+class LLPanelBlockedList
+ : public LLPanel, public LLMuteListObserver
+{
+public:
+ LLPanelBlockedList();
+ ~LLPanelBlockedList();
+
+ virtual BOOL postBuild();
+ virtual void draw();
+ virtual void onOpen(const LLSD& key);
+
+ void selectBlocked(const LLUUID& id);
+
+ /**
+ * Shows current Panel in side tray and select passed blocked item.
+ *
+ * @param idToSelect - LLUUID of blocked Resident or Object to be selected.
+ * If it is LLUUID::null, nothing will be selected.
+ */
+ static void showPanelAndSelect(const LLUUID& idToSelect);
+
+ // LLMuteListObserver callback interface implementation.
+ /* virtual */ void onChange() { refreshBlockedList();}
+
+private:
+ void refreshBlockedList();
+ void updateButtons();
+
+ // UI callbacks
+ void onBackBtnClick();
+ void onRemoveBtnClick();
+ void onPickBtnClick();
+ void onBlockByNameClick();
+
+ static void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data);
+ static void callbackBlockByName(const std::string& text);
+
+private:
+ LLScrollListCtrl* mBlockedList;
+};
+
+//-----------------------------------------------------------------------------
+// LLFloaterGetBlockedObjectName()
+//-----------------------------------------------------------------------------
+// Class for handling mute object by name floater.
+class LLFloaterGetBlockedObjectName : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+ typedef boost::function<void (const std::string&)> get_object_name_callback_t;
+
+ virtual BOOL postBuild();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ static LLFloaterGetBlockedObjectName* show(get_object_name_callback_t callback);
+
+private:
+ LLFloaterGetBlockedObjectName(const LLSD& key);
+ virtual ~LLFloaterGetBlockedObjectName();
+
+ // UI Callbacks
+ void applyBlocking();
+ void cancelBlocking();
+
+ get_object_name_callback_t mGetObjectNameCallback;
+};
+
+
+#endif // LL_LLPANELBLOCKEDLIST_H
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index c77d089af7..ee5d265220 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -119,7 +119,7 @@ class LLClassifiedTeleportHandler : public LLCommandHandler
{
public:
// don't allow from external browsers because it moves you immediately
- LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", true) { }
+ LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& queryMap)
{
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 4cbb018ce9..d1ce6b14ed 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -298,6 +298,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
if(button_create)
button_create->setVisible(is_null_group_id);
+ getChild<LLUICtrl>("prepend_founded_by")->setVisible(!is_null_group_id);
+
LLAccordionCtrlTab* tab_general = findChild<LLAccordionCtrlTab>("group_general_tab");
LLAccordionCtrlTab* tab_roles = findChild<LLAccordionCtrlTab>("group_roles_tab");
LLAccordionCtrlTab* tab_notices = findChild<LLAccordionCtrlTab>("group_notices_tab");
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 73ea990b3f..f3893a104c 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -113,6 +113,7 @@ BOOL LLPanelGroupGeneral::postBuild()
if (mListVisibleMembers)
{
mListVisibleMembers->setDoubleClickCallback(openProfile, this);
+ mListVisibleMembers->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
}
// Options
@@ -769,11 +770,6 @@ void LLPanelGroupGeneral::updateMembers()
}
// Owners show up in bold.
std::string style = "NORMAL";
- if ( member->isOwner() )
- {
- style = "BOLD";
- }
-
sd_timer.reset();
LLSD row;
row["id"] = member->getID();
@@ -793,7 +789,14 @@ void LLPanelGroupGeneral::updateMembers()
sSDTime += sd_timer.getElapsedTimeF32();
element_timer.reset();
- mListVisibleMembers->addElement(row);//, ADD_SORTED);
+ LLScrollListItem* member_row = mListVisibleMembers->addElement(row);//, ADD_SORTED);
+
+ if ( member->isOwner() )
+ {
+ LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(member_row->getColumn(0));
+ if (name_textp)
+ name_textp->setFontStyle(LLFontGL::BOLD);
+ }
sElementTime += element_timer.getElapsedTimeF32();
}
sAllTime += all_timer.getElapsedTimeF32();
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 4618b49df4..378a09e315 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -36,6 +36,7 @@
#include "llagent.h"
#include "llbutton.h"
+#include "llfiltereditor.h"
#include "llfloatergroupinvite.h"
#include "llavataractions.h"
#include "lliconctrl.h"
@@ -49,7 +50,6 @@
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexteditor.h"
-#include "llsearcheditor.h"
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
@@ -477,14 +477,12 @@ BOOL LLPanelGroupSubTab::postBuild()
{
// Hook up the search widgets.
bool recurse = true;
- mSearchEditor = getChild<LLSearchEditor>("filter_input", recurse);
+ mSearchEditor = getChild<LLFilterEditor>("filter_input", recurse);
if (!mSearchEditor)
return FALSE;
- mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::onClickSearch, this));
- mSearchEditor->setKeystrokeCallback(onSearchKeystroke, this);
-
+ mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::setSearchFilter, this, _2));
// Get icons for later use.
mActionIcons.clear();
@@ -517,26 +515,6 @@ void LLPanelGroupSubTab::setGroupID(const LLUUID& id)
}
}
-// static
-void LLPanelGroupSubTab::onSearchKeystroke(LLLineEditor* caller, void* user_data)
-{
- LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
- self->handleSearchKeystroke(caller);
-
-}
-
-void LLPanelGroupSubTab::handleSearchKeystroke(LLLineEditor* caller)
-{
- setSearchFilter( caller->getText() );
-}
-
-// static
-void LLPanelGroupSubTab::onClickSearch()
-{
- setSearchFilter( mSearchEditor->getText() );
-}
-
-
void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
{
lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
@@ -659,6 +637,12 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
row["columns"][1]["font"]["style"] = "BOLD";
LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
+
+ LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(title_row->getColumn(1));
+ if (name_textp)
+ name_textp->setFontStyle(LLFontGL::BOLD);
+
+
bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
@@ -837,6 +821,7 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
mMembersList->setCommitCallback(onMemberSelect, this);
// Show the member's profile on double click.
mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
+ mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
if ( button )
@@ -1731,6 +1716,8 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
mRolesList->setCommitOnSelectionChange(TRUE);
mRolesList->setCommitCallback(onRoleSelect, this);
+ mAssignedMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+
mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange, this);
mAllowedActionsList->setCommitOnSelectionChange(TRUE);
@@ -2397,6 +2384,7 @@ BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
mActionList->setCommitOnSelectionChange(TRUE);
mActionList->setCommitCallback(boost::bind(&LLPanelGroupActionsSubTab::handleActionSelect, this));
+ mActionList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
update(GC_ALL);
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 2a0f31fa0f..bd5fc1d235 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -35,6 +35,7 @@
#include "llpanelgroup.h"
+class LLFilterEditor;
class LLNameListCtrl;
class LLPanelGroupSubTab;
class LLPanelGroupMembersSubTab;
@@ -43,7 +44,6 @@ class LLPanelGroupActionsSubTab;
class LLScrollListCtrl;
class LLScrollListItem;
class LLTextEditor;
-class LLSearchEditor;
// Forward declare for friend usage.
//virtual BOOL LLPanelGroupSubTab::postBuildSubTab(LLView*);
@@ -111,11 +111,6 @@ public:
// This allows sub-tabs to collect child widgets from a higher level in the view hierarchy.
virtual BOOL postBuildSubTab(LLView* root) { return TRUE; }
- static void onSearchKeystroke(LLLineEditor* caller, void* user_data);
- void handleSearchKeystroke(LLLineEditor* caller);
-
- void onClickSearch();
-
virtual void setSearchFilter( const std::string& filter );
virtual void activate();
@@ -148,7 +143,7 @@ protected:
LLPanel* mHeader;
LLPanel* mFooter;
- LLSearchEditor* mSearchEditor;
+ LLFilterEditor* mSearchEditor;
std::string mSearchFilter;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index ef830d5f03..9caa751854 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -87,7 +87,7 @@ class LLLoginRefreshHandler : public LLCommandHandler
{
public:
// don't allow from external browsers
- LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { }
+ LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 9ec9874384..6a61e0f02f 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -39,9 +39,11 @@
#include "lleconomy.h"
#include "llerror.h"
#include "llfontgl.h"
+#include "llmaterialtable.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llvolume.h"
+#include "material_codes.h"
#include "m3math.h"
// project includes
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 697182c8fc..309a97a9f2 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -43,12 +43,12 @@
// newview
#include "llagent.h"
+#include "llavataractions.h"
#include "llavatarlist.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llfloateravatarpicker.h"
//#include "llfloaterminiinspector.h"
#include "llfriendcard.h"
-#include "llavataractions.h"
#include "llgroupactions.h"
#include "llgrouplist.h"
#include "llrecentpeople.h"
@@ -133,18 +133,23 @@ public:
class LLFriendListUpdater : public LLAvatarListUpdater, public LLFriendObserver
{
LOG_CLASS(LLFriendListUpdater);
+ class LLInventoryFriendCardObserver;
public:
+ friend class LLInventoryFriendCardObserver;
LLFriendListUpdater(callback_t cb)
: LLAvatarListUpdater(cb, FRIEND_LIST_UPDATE_TIMEOUT)
{
LLAvatarTracker::instance().addObserver(this);
+
// For notification when SIP online status changes.
LLVoiceClient::getInstance()->addObserver(this);
+ mInvObserver = new LLInventoryFriendCardObserver(this);
}
~LLFriendListUpdater()
{
+ delete mInvObserver;
LLVoiceClient::getInstance()->removeObserver(this);
LLAvatarTracker::instance().removeObserver(this);
}
@@ -166,6 +171,7 @@ public:
mMask |= mask;
}
+
/*virtual*/ BOOL tick()
{
if (updateList(mMask))
@@ -180,6 +186,75 @@ public:
private:
U32 mMask;
+ LLInventoryFriendCardObserver* mInvObserver;
+
+ /**
+ * This class is intended for updating Friend List when Inventory Friend Card is added/removed.
+ *
+ * The main usage is when Inventory Friends/All content is added while synchronizing with
+ * friends list on startup is performed. In this case Friend Panel should be updated when
+ * missing Inventory Friend Card is created.
+ * *NOTE: updating is fired when Inventory item is added into CallingCards/Friends subfolder.
+ * Otherwise LLFriendObserver functionality is enough to keep Friends Panel synchronized.
+ */
+ class LLInventoryFriendCardObserver : public LLInventoryObserver
+ {
+ LOG_CLASS(LLFriendListUpdater::LLInventoryFriendCardObserver);
+
+ friend class LLFriendListUpdater;
+
+ private:
+ LLInventoryFriendCardObserver(LLFriendListUpdater* updater) : mUpdater(updater)
+ {
+ gInventory.addObserver(this);
+ }
+ ~LLInventoryFriendCardObserver()
+ {
+ gInventory.removeObserver(this);
+ }
+ /*virtual*/ void changed(U32 mask)
+ {
+ lldebugs << "Inventory changed: " << mask << llendl;
+
+ // *NOTE: deleting of InventoryItem is performed via moving to Trash.
+ // That means LLInventoryObserver::STRUCTURE is present in MASK instead of LLInventoryObserver::REMOVE
+ if ((CALLINGCARD_ADDED & mask) == CALLINGCARD_ADDED)
+ {
+ lldebugs << "Calling card added: count: " << gInventory.getChangedIDs().size()
+ << ", first Inventory ID: "<< (*gInventory.getChangedIDs().begin())
+ << llendl;
+
+ bool friendFound = false;
+ std::set<LLUUID> changedIDs = gInventory.getChangedIDs();
+ for (std::set<LLUUID>::const_iterator it = changedIDs.begin(); it != changedIDs.end(); ++it)
+ {
+ if (isDescendentOfInventoryFriends(*it))
+ {
+ friendFound = true;
+ break;
+ }
+ }
+
+ if (friendFound)
+ {
+ lldebugs << "friend found, panel should be updated" << llendl;
+ mUpdater->changed(LLFriendObserver::ADD);
+ }
+ }
+ }
+
+ bool isDescendentOfInventoryFriends(const LLUUID& invItemID)
+ {
+ LLViewerInventoryItem * item = gInventory.getItem(invItemID);
+ if (NULL == item)
+ return false;
+
+ return LLFriendCardsManager::instance().isItemInAnyFriendsList(item);
+ }
+ LLFriendListUpdater* mUpdater;
+
+ static const U32 CALLINGCARD_ADDED = LLInventoryObserver::ADD | LLInventoryObserver::CALLING_CARD;
+ };
};
/**
@@ -326,6 +401,19 @@ LLPanelPeople::~LLPanelPeople()
LLView::deleteViewByHandle(mRecentViewSortMenuHandle);
}
+void onAvatarListTmpDoubleClicked(LLAvatarListTmp* list)
+{
+ LLUUID clicked_id = list->getCurrentID();
+
+ if (clicked_id.isNull())
+ return;
+
+#if 0 // SJB: Useful for testing, but not currently functional or to spec
+ LLAvatarActions::showProfile(clicked_id);
+#else // spec says open IM window
+ LLAvatarActions::startIM(clicked_id);
+#endif
+}
BOOL LLPanelPeople::postBuild()
{
@@ -342,7 +430,7 @@ BOOL LLPanelPeople::postBuild()
mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
- mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
+ mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarListTmp>("avatar_list");
mGroupList = getChild<LLGroupList>("group_list");
LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
@@ -357,11 +445,11 @@ BOOL LLPanelPeople::postBuild()
mOnlineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOnlineFriendList));
mAllFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mAllFriendList));
mNearbyList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mNearbyList));
- mRecentList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mRecentList));
+ mRecentList->setDoubleClickCallback(boost::bind(onAvatarListTmpDoubleClicked, mRecentList));
mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList));
mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList));
mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));
- mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList));
+ mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));
mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this));
mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));
@@ -438,8 +526,13 @@ bool LLPanelPeople::updateFriendList(U32 changed_mask)
LLFriendCardsManager::instance().collectFriendsLists(listMap);
if (listMap.size() > 0)
{
+ lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
mAllFriendVec = listMap.begin()->second;
}
+ else
+ {
+ lldebugs << "Friends Cards were not found" << llendl;
+ }
LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
for (; buddy_it != all_buddies.end(); ++buddy_it)
@@ -896,7 +989,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
}
}
-
void LLPanelPeople::onCallButtonClicked()
{
// *TODO: not implemented yet
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index 3358a70bac..c0c2f70614 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -40,6 +40,7 @@
class LLFilterEditor;
class LLTabContainer;
class LLAvatarList;
+class LLAvatarListTmp;
class LLGroupList;
class LLPanelPeople : public LLPanel
@@ -118,7 +119,7 @@ private:
LLAvatarList* mOnlineFriendList;
LLAvatarList* mAllFriendList;
LLAvatarList* mNearbyList;
- LLAvatarList* mRecentList;
+ LLAvatarListTmp* mRecentList;
LLGroupList* mGroupList;
LLHandle<LLView> mGroupPlusMenuHandle;
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index f7ca54c732..9ae58d1cb6 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -134,11 +134,13 @@ BOOL LLPanelPick::postBuild()
childSetAction("teleport_btn", boost::bind(&LLPanelPick::onClickTeleport, this));
childSetAction("show_on_map_btn", boost::bind(&LLPanelPick::onClickMap, this));
- if (!mBackCb.empty())
- {
- LLButton* button = findChild<LLButton>("back_btn");
- if (button) button->setClickedCallback(mBackCb);
- }
+ }
+
+ // EXT-822. We have to process "Back" button click in both Edit & View Modes
+ if (!mBackCb.empty())
+ {
+ LLButton* button = findChild<LLButton>("back_btn");
+ if (button) button->setClickedCallback(mBackCb);
}
return TRUE;
@@ -159,7 +161,7 @@ void LLPanelPick::requestData()
{
mDataReceived = FALSE;
LLAvatarPropertiesProcessor::instance().addObserver(mCreatorId, this);
- LLAvatarPropertiesProcessor::instance().sendDataRequest(mCreatorId, APT_PICK_INFO, &mPickId);
+ LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorId, mPickId);
}
void LLPanelPick::init(LLPickData *pick_data)
@@ -335,7 +337,7 @@ void LLPanelPick::sendUpdate()
mDataReceived = FALSE;
LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
- LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO);
+ LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
}
@@ -435,11 +437,8 @@ void LLPanelPick::updateButtons()
void LLPanelPick::setExitCallback(commit_callback_t cb)
{
mBackCb = cb;
- if (!mEditMode)
- {
- LLButton* button = findChild<LLButton>("back_btn");
- if (button) button->setClickedCallback(mBackCb);
- }
+ LLButton* button = findChild<LLButton>("back_btn");
+ if (button) button->setClickedCallback(mBackCb);
}
//static
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index 973afae73b..d374d24316 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -46,6 +46,7 @@
#include "llpanelprofile.h"
#include "llpanelpick.h"
#include "llscrollcontainer.h"
+#include "lllistctrl.h"
static const std::string XML_BTN_NEW = "new_btn";
static const std::string XML_BTN_DELETE = "trash_btn";
@@ -53,9 +54,10 @@ static const std::string XML_BTN_INFO = "info_btn";
static const std::string XML_BTN_TELEPORT = "teleport_btn";
static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn";
-static const std::string XML_PICKS_LIST = "back_panel";
+static const std::string PICK_ID("pick_id");
+static const std::string PICK_CREATOR_ID("pick_creator_id");
+static const std::string PICK_NAME("pick_name");
-#define PICK_ITEMS_BETWEEN 5
static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
@@ -65,9 +67,9 @@ static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
LLPanelPicks::LLPanelPicks()
: LLPanelProfileTab(),
mPopupMenu(NULL),
- mSelectedPickItem(NULL),
mProfilePanel(NULL),
- mPickPanel(NULL)
+ mPickPanel(NULL),
+ mPicksList(NULL)
{
}
@@ -86,7 +88,7 @@ void* LLPanelPicks::create(void* data /* = NULL */)
void LLPanelPicks::updateData()
{
- LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_PICKS);
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
}
void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
@@ -100,22 +102,8 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
gCacheName->getName(getAvatarId(),name,second_name);
childSetTextArg("pick_title", "[NAME]",name);
- LLView* picks_list = getPicksList();
-
- // to restore selection of the same item later
- LLUUID pick_id_selected(LLUUID::null);
- if (mSelectedPickItem) pick_id_selected = mSelectedPickItem->getPickId();
-
- clear();
-
- //*TODO move it somewhere else?
- picks_list->setEnabled(FALSE);
- childSetEnabled(XML_BTN_NEW, false);
- childSetEnabled(XML_BTN_DELETE, false);
- childSetEnabled(XML_BTN_INFO, false);
- childSetEnabled(XML_BTN_TELEPORT,!avatar_picks->picks_list.empty());
- childSetEnabled(XML_BTN_SHOW_ON_MAP,!avatar_picks->picks_list.empty());
-
+ mPicksList->clear();
+
LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin();
for(; avatar_picks->picks_list.end() != it; ++it)
{
@@ -124,109 +112,44 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
LLPickItem* picture = LLPickItem::create();
picture->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this));
-
- picks_list->addChild(picture);
-
picture->setPickName(pick_name);
picture->setPickId(pick_id);
picture->setCreatorId(getAvatarId());
LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture);
picture->update();
- mPickItemList.push_back(picture);
- if (pick_id_selected != LLUUID::null &&
- pick_id == pick_id_selected) setSelectedPickItem(picture);
+
+ LLSD pick_value = LLSD();
+ pick_value.insert(PICK_ID, pick_id);
+ pick_value.insert(PICK_NAME, pick_name);
+ pick_value.insert(PICK_CREATOR_ID, getAvatarId());
+
+ mPicksList->addItem(picture, pick_value);
+
+ picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1));
+ picture->setRightMouseDownCallback(boost::bind(&LLPanelPicks::onRightMouseDownItem, this, _1, _2, _3, _4));
+ picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
+ picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
- reshapePicksList();
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
-
updateButtons();
- if (!mSelectedPickItem && mPickItemList.size()) setSelectedPickItem(mPickItemList.back());
- picks_list->setEnabled(TRUE);
-
}
}
}
-void LLPanelPicks::clear()
-{
- LLView* scroll = getPicksList();
- picture_list_t::const_iterator it = mPickItemList.begin();
- for(; mPickItemList.end() != it; ++it)
- {
- scroll->removeChild(*it);
- delete *it;
- }
- mPickItemList.clear();
- mSelectedPickItem = NULL;
-}
-
-
LLPickItem* LLPanelPicks::getSelectedPickItem()
{
- return mSelectedPickItem;
-}
-
-
-void LLPanelPicks::removePickItem( LLPickItem* pick_item )
-{
- LLView* scroll = getPicksList();
- scroll->removeChild(pick_item);
- mPickItemList.remove(pick_item);
- if (mPickItemList.size() == 0)
- {
- mSelectedPickItem = NULL;
- }
- else
- {
- setSelectedPickItem(mPickItemList.back());
- }
-
- reshapePicksList();
-}
-
-void LLPanelPicks::reshapePicksList()
-{
- if (!mPickItemList.size()) return;
- LLView* pickList = getPicksList();
-
- //We don't need to update size of the 'pick list' before reshaping pick items. Don't need to reshape the pick list
- S32 height = mPickItemList.size() * (mPickItemList.front()->getRect().getHeight() + PICK_ITEMS_BETWEEN);
- LLRect rc = pickList->getRect();
- rc.setLeftTopAndSize(rc.mLeft, rc.mTop, rc.getWidth(), height);
- pickList->setRect(rc);
+ LLPanel* selected_item = mPicksList->getSelectedItem();
+ if (!selected_item) return NULL;
- S32 last_bottom = pickList->getRect().getHeight();
- std::list<LLPickItem*>::const_iterator pick_it, pick_first_it = mPickItemList.begin();
- for ( pick_it = pick_first_it; pick_it != mPickItemList.end(); ++pick_it)
- {
- LLView* const pick = *pick_it;
- if(pick_it != pick_first_it)
- {
- last_bottom -= pick->getRect().getHeight();
- last_bottom -= PICK_ITEMS_BETWEEN;
- }
- reshapePickItem(pick, last_bottom,pickList->getRect().getWidth());
- }
-}
-
-void LLPanelPicks::reshapePickItem(LLView* const pick_item, const S32 last_bottom, const S32 newWidth)
-{
- LLRect rc = pick_item->getRect();
- rc.mBottom = last_bottom - rc.getHeight();
- rc.mTop = last_bottom;
- pick_item->setRect(rc);
- pick_item->reshape(newWidth, rc.getHeight());
-}
-
-LLView* LLPanelPicks::getPicksList() const
-{
- return getChild<LLView>(XML_PICKS_LIST);
+ return dynamic_cast<LLPickItem*>(selected_item);
}
BOOL LLPanelPicks::postBuild()
{
+ mPicksList = getChild<LLListCtrl>("picks_list");
+
childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this));
childSetAction("teleport_btn", boost::bind(&LLPanelPicks::onClickTeleport, this));
@@ -270,6 +193,10 @@ void LLPanelPicks::onOpen(const LLSD& key)
{
childSetVisible("pick_title", !self);
childSetVisible("pick_title_agent", self);
+
+ mPopupMenu->setItemVisible("pick_delete", TRUE);
+ mPopupMenu->setItemVisible("pick_edit", TRUE);
+ mPopupMenu->setItemVisible("pick_separator", TRUE);
}
LLPanelProfileTab::onOpen(key);
@@ -278,11 +205,11 @@ void LLPanelPicks::onOpen(const LLSD& key)
//static
void LLPanelPicks::onClickDelete()
{
- LLPickItem* pick_item = getSelectedPickItem();
- if (!pick_item) return;
+ LLSD pick_value = mPicksList->getSelectedValue();
+ if (pick_value.isUndefined()) return;
LLSD args;
- args["PICK"] = pick_item->getPickName();
+ args["PICK"] = pick_value[PICK_NAME];
LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2));
}
@@ -290,12 +217,12 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response
{
S32 option = LLNotification::getSelectedOption(notification, response);
- LLPickItem* pick_item = getSelectedPickItem();
+ LLSD pick_value = mPicksList->getSelectedValue();
if (0 == option)
{
- LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_item->getPickId());
- removePickItem(pick_item);
+ LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]);
+ mPicksList->removeItemByValue(pick_value);
}
updateButtons();
return false;
@@ -329,101 +256,45 @@ void LLPanelPicks::onClickMap()
}
-BOOL LLPanelPicks::handleRightMouseDown(S32 x, S32 y, MASK mask)
+void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask)
{
- if (isMouseInPick(x, y))
+ if (mPopupMenu)
{
- if (mPopupMenu)
- {
- mPopupMenu->buildDrawLabels();
- mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
- ((LLContextMenu*)mPopupMenu)->show(x, y);
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
- }
- return TRUE;
+ mPopupMenu->buildDrawLabels();
+ mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ ((LLContextMenu*)mPopupMenu)->show(x, y);
+ LLMenuGL::showPopup(item, mPopupMenu, x, y);
}
- return LLPanel::handleRightMouseDown(x, y, mask);
}
-BOOL LLPanelPicks::handleMouseDown( S32 x, S32 y, MASK mask )
+void LLPanelPicks::onDoubleClickItem(LLUICtrl* item)
{
- isMouseInPick(x, y);
- return LLPanel::handleMouseDown(x, y, mask);
-}
-
-BOOL LLPanelPicks::handleDoubleClick(S32 x, S32 y, MASK mask)
-{
- if (isMouseInPick(x, y))
- {
- LLPickItem* pick_item = getSelectedPickItem();
- if (pick_item)
- {
- LLSD args;
- args["PICK"] = pick_item->getPickName();
- LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
- }
- return TRUE;
- }
- return LLPanel::handleDoubleClick(x, y, mask);
+ LLSD pick_value = mPicksList->getSelectedValue();
+ if (pick_value.isUndefined()) return;
+
+ LLSD args;
+ args["PICK"] = pick_value[PICK_NAME];
+ LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
}
void LLPanelPicks::updateButtons()
{
- int picks_num = mPickItemList.size();
- childSetEnabled(XML_BTN_INFO, picks_num > 0);
+ int picks_num = mPicksList->size();
+ bool has_selected = mPicksList->numSelected();
+
+ childSetEnabled(XML_BTN_INFO, has_selected);
if (getAvatarId() == gAgentID)
{
childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS);
- childSetEnabled(XML_BTN_DELETE, picks_num > 0);
-
- //*TODO move somewhere this calls
- // we'd better set them up earlier when a panel was being constructed
- mPopupMenu->setItemVisible("pick_delete", TRUE);
- mPopupMenu->setItemVisible("pick_edit", TRUE);
- mPopupMenu->setItemVisible("pick_separator", TRUE);
- }
-
- //*TODO update buttons like Show on Map, Teleport etc.
-
-}
-
-void LLPanelPicks::setSelectedPickItem(LLPickItem* item)
-{
- if (!item) return;
- if (mSelectedPickItem == item) return;
- if (mSelectedPickItem && mSelectedPickItem->isBackgroundVisible())
- {
- mSelectedPickItem->setBackgroundVisible(FALSE);
+ childSetEnabled(XML_BTN_DELETE, has_selected);
}
- item->setBackgroundVisible(TRUE);
- mSelectedPickItem = item;
-}
-BOOL LLPanelPicks::isMouseInPick( S32 x, S32 y )
-{
- S32 x_l = x;
- S32 y_l = y;
-
- if(!getChild<LLUICtrl>("profile_scroll")->getRect().pointInRect(x, y))
- {
- return FALSE;
- }
-
- picture_list_t::const_iterator it = mPickItemList.begin();
- for(; mPickItemList.end() != it; ++it)
- {
- localPointToOtherView(x, y, &x_l, &y_l, (*it));
- if ((*it)->pointInView(x_l, y_l))
- {
- setSelectedPickItem(*it);
- return TRUE;
- }
- }
- return FALSE;
+ childSetEnabled(XML_BTN_INFO, has_selected);
+ childSetEnabled(XML_BTN_TELEPORT, has_selected);
+ childSetEnabled(XML_BTN_SHOW_ON_MAP, has_selected);
}
-
void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
{
mProfilePanel = profile_panel;
@@ -449,12 +320,12 @@ void LLPanelPicks::onClickNew()
void LLPanelPicks::onClickInfo()
{
- LLPickItem* pick = getSelectedPickItem();
- if (!pick) return;
+ LLSD selected_value = mPicksList->getSelectedValue();
+ if (selected_value.isUndefined()) return;
buildPickPanel();
mPickPanel->reset();
- mPickPanel->init(pick->getCreatorId(), pick->getPickId());
+ mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
getProfilePanel()->togglePanel(mPickPanel);
}
@@ -466,12 +337,12 @@ void LLPanelPicks::onClickBack()
void LLPanelPicks::onClickMenuEdit()
{
//*TODO, refactor - most of that is similar to onClickInfo
- LLPickItem* pick = getSelectedPickItem();
- if (!pick) return;
+ LLSD selected_value = mPicksList->getSelectedValue();
+ if (selected_value.isUndefined()) return;
buildPickPanel();
mPickPanel->reset();
- mPickPanel->init(pick->getCreatorId(), pick->getPickId());
+ mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
mPickPanel->setEditMode(TRUE);
getProfilePanel()->togglePanel(mPickPanel);
}
@@ -576,7 +447,7 @@ const std::string LLPickItem::getDescription()
void LLPickItem::update()
{
mNeedData = true;
- LLAvatarPropertiesProcessor::instance().sendDataRequest(mCreatorID, APT_PICK_INFO, &mPickID);
+ LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID);
mNeedData = false;
}
@@ -601,3 +472,17 @@ void LLPanelPicks::onClose()
getProfilePanel()->togglePanel(mPickPanel);
}
}
+
+BOOL LLPickItem::postBuild()
+{
+ setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", true));
+ setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", false));
+ return TRUE;
+}
+
+void LLPickItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index da7bc32ab1..97e8e607c8 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -48,7 +48,7 @@ class LLPanelPick;
class LLAgent;
class LLMenuGL;
class LLPickItem;
-
+class LLListCtrl;
class LLPanelPicks
: public LLPanelProfileTab
@@ -67,18 +67,9 @@ public:
void updateData();
- void clear();
-
// returns the selected pick item
LLPickItem* getSelectedPickItem();
- // removes the specified pick item
- void removePickItem(LLPickItem* pick_item);
-
- /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
-
//*NOTE top down approch when panel toggling is done only by
// parent panels failed to work (picks related code was in me profile panel)
void setProfilePanel(LLPanelProfile* profile_panel);
@@ -106,25 +97,17 @@ private:
bool callbackDelete(const LLSD& notification, const LLSD& response);
bool callbackTeleport(const LLSD& notification, const LLSD& response);
- void reshapePicksList();
- void reshapePickItem(LLView* const pick_item, const S32 last_bottom, const S32 newWidth);
- LLView* getPicksList() const;
void updateButtons();
- void setSelectedPickItem(LLPickItem* item);
-
- BOOL isMouseInPick(S32 x, S32 y);
+ virtual void onDoubleClickItem(LLUICtrl* item);
+ virtual void onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask);
LLPanelProfile* getProfilePanel();
-
- typedef std::list<LLPickItem*> picture_list_t;
- picture_list_t mPickItemList;
-
LLMenuGL* mPopupMenu;
- LLPickItem* mSelectedPickItem;
LLPanelProfile* mProfilePanel;
LLPanelPick* mPickPanel;
+ LLListCtrl* mPicksList;
};
class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver
@@ -169,6 +152,11 @@ public:
~LLPickItem();
+ /*virtual*/ BOOL postBuild();
+
+ /** setting on/off background icon to indicate selected state */
+ /*virtual*/ void setValue(const LLSD& value);
+
protected:
LLUUID mPickID;
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 3926ee0f07..793c25455d 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -48,6 +48,8 @@
#include "llscrollcontainer.h"
#include "lltextbox.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloaterworldmap.h"
@@ -67,7 +69,6 @@ LLPanelPlaceInfo::LLPanelPlaceInfo()
: LLPanel(),
mParcelID(),
mRequestedID(),
- mPosRegion(),
mLandmarkID(),
mMinHeight(0),
mScrollingPanel(NULL),
@@ -94,14 +95,42 @@ BOOL LLPanelPlaceInfo::postBuild()
mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
mSnapshotCtrl->setEnabled(FALSE);
- mRegionName = getChild<LLTextBox>("region_name");
- mParcelName = getChild<LLTextBox>("parcel_name");
+ mRegionName = getChild<LLTextBox>("region_title");
+ mParcelName = getChild<LLTextBox>("parcel_title");
mDescEditor = getChild<LLTextEditor>("description");
- mRating = getChild<LLIconCtrl>("maturity");
- mRegionInfoDrillIn = getChild<LLButton>("region_info_drill_in");
- mMediaDrillIn = getChild<LLButton>("media_drill_in");
- mMediaDrillIn->setClickedCallback(boost::bind(&LLPanelPlaceInfo::toggleMediaPanel, this, TRUE));
+ mMaturityRatingText = getChild<LLTextBox>("maturity_value");
+ mParcelOwner = getChild<LLTextBox>("owner_value");
+ mLastVisited = getChild<LLTextBox>("last_visited_value");
+
+ mRatingText = getChild<LLTextBox>("rating_value");
+ mVoiceText = getChild<LLTextBox>("voice_value");
+ mFlyText = getChild<LLTextBox>("fly_value");
+ mPushText = getChild<LLTextBox>("push_value");
+ mBuildText = getChild<LLTextBox>("build_value");
+ mScriptsText = getChild<LLTextBox>("scripts_value");
+ mDamageText = getChild<LLTextBox>("damage_value");
+
+ mRegionNameText = getChild<LLTextBox>("region_name");
+ mRegionTypeText = getChild<LLTextBox>("region_type");
+ mRegionRatingText = getChild<LLTextBox>("region_rating");
+ mRegionOwnerText = getChild<LLTextBox>("region_owner");
+ mRegionGroupText = getChild<LLTextBox>("region_group");
+
+ mEstateNameText = getChild<LLTextBox>("estate_name");
+ mEstateRatingText = getChild<LLTextBox>("estate_rating");
+ mEstateOwnerText = getChild<LLTextBox>("estate_owner");
+ mCovenantText = getChild<LLTextEditor>("covenant");
+
+ mSalesPriceText = getChild<LLTextBox>("sales_price");
+ mAreaText = getChild<LLTextBox>("area");
+ mTrafficText = getChild<LLTextBox>("traffic");
+ mPrimitivesText = getChild<LLTextBox>("primitives");
+ mParcelScriptsText = getChild<LLTextBox>("parcel_scripts");
+ mTerraformLimitsText = getChild<LLTextBox>("terraform_limits");
+ mSubdivideText = getChild<LLTextEditor>("subdivide");
+ mResaleText = getChild<LLTextEditor>("resale");
+ mSaleToText = getChild<LLTextBox>("sale_to");
mOwner = getChild<LLTextBox>("owner");
mCreator = getChild<LLTextBox>("creator");
@@ -223,9 +252,10 @@ void LLPanelPlaceInfo::resetLocation()
mParcelID.setNull();
mRequestedID.setNull();
mLandmarkID.setNull();
- mPosRegion.clearVec();
std::string not_available = getString("not_available");
- mRating->setValue(not_available);
+ mMaturityRatingText->setValue(not_available);
+ mParcelOwner->setValue(not_available);
+ mLastVisited->setValue(not_available);
mRegionName->setText(not_available);
mParcelName->setText(not_available);
mDescEditor->setText(not_available);
@@ -236,6 +266,35 @@ void LLPanelPlaceInfo::resetLocation()
mNotesEditor->setText(LLStringUtil::null);
mSnapshotCtrl->setImageAssetID(LLUUID::null);
mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
+
+ mRatingText->setText(not_available);
+ mVoiceText->setText(not_available);
+ mFlyText->setText(not_available);
+ mPushText->setText(not_available);
+ mBuildText->setText(not_available);
+ mParcelScriptsText->setText(not_available);
+ mDamageText->setText(not_available);
+
+ mRegionNameText->setValue(not_available);
+ mRegionTypeText->setValue(not_available);
+ mRegionRatingText->setValue(not_available);
+ mRegionOwnerText->setValue(not_available);
+ mRegionGroupText->setValue(not_available);
+
+ mEstateNameText->setValue(not_available);
+ mEstateRatingText->setValue(not_available);
+ mEstateOwnerText->setValue(not_available);
+ mCovenantText->setValue(not_available);
+
+ mSalesPriceText->setValue(not_available);
+ mAreaText->setValue(not_available);
+ mTrafficText->setValue(not_available);
+ mPrimitivesText->setValue(not_available);
+ mParcelScriptsText->setValue(not_available);
+ mTerraformLimitsText->setValue(not_available);
+ mSubdivideText->setValue(not_available);
+ mResaleText->setValue(not_available);
+ mSaleToText->setValue(not_available);
}
//virtual
@@ -252,12 +311,21 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
bool is_info_type_agent = type == AGENT;
bool is_info_type_landmark = type == LANDMARK;
+ bool is_info_type_teleport_history = type == TELEPORT_HISTORY;
+
+ getChild<LLTextBox>("maturity_label")->setVisible(!is_info_type_agent);
+ mMaturityRatingText->setVisible(!is_info_type_agent);
+
+ getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent);
+ mParcelOwner->setVisible(is_info_type_agent);
+
+ getChild<LLTextBox>("last_visited_label")->setVisible(is_info_type_teleport_history);
+ mLastVisited->setVisible(is_info_type_teleport_history);
landmark_info_panel->setVisible(is_info_type_landmark);
landmark_edit_panel->setVisible(is_info_type_landmark || type == CREATE_LANDMARK);
- mRegionInfoDrillIn->setVisible(is_info_type_agent);
- mMediaDrillIn->setVisible(is_info_type_agent);
+ getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent);
switch(type)
{
@@ -275,26 +343,26 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
}
break;
- // Hide Media Panel if showing information about
- // a landmark or a teleport history item
case LANDMARK:
mCurrentTitle = getString("title_landmark");
break;
case TELEPORT_HISTORY:
- mCurrentTitle = getString("title_place");
+ mCurrentTitle = getString("title_teleport_history");
break;
}
- if (type != PLACE)
+ if (type != AGENT)
toggleMediaPanel(FALSE);
+
+ mInfoType = type;
}
BOOL LLPanelPlaceInfo::isMediaPanelVisible()
{
if (!mMediaPanel)
return FALSE;
-
+
return mMediaPanel->getVisible();
}
@@ -351,12 +419,16 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
}
- if( !parcel_data.name.empty())
+ if(!parcel_data.name.empty())
{
mParcelName->setText(parcel_data.name);
}
+ else
+ {
+ mParcelName->setText(LLStringUtil::null);
+ }
- if( !parcel_data.desc.empty())
+ if(!parcel_data.desc.empty())
{
mDescEditor->setText(parcel_data.desc);
}
@@ -364,38 +436,28 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
// HACK: Flag 0x2 == adult region,
// Flag 0x1 == mature region, otherwise assume PG
std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
- std::string rating_icon = "icon_event.tga";
if (parcel_data.flags & 0x2)
{
rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
- rating_icon = "icon_event_adult.tga";
}
else if (parcel_data.flags & 0x1)
{
rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
- rating_icon = "icon_event_mature.tga";
}
- mRating->setValue(rating_icon);
+
+ mMaturityRatingText->setValue(rating);
+ mRatingText->setValue(rating);
//update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE
//because we deal with remote parcel response format
bool isForSale = (parcel_data.flags & DFQ_FOR_SALE)? TRUE : FALSE;
getChild<LLIconCtrl>("icon_for_sale")->setVisible(isForSale);
-
- // Just use given region position for display
- S32 region_x = llround(mPosRegion.mV[0]);
- S32 region_y = llround(mPosRegion.mV[1]);
- S32 region_z = llround(mPosRegion.mV[2]);
- // If the region position is zero, grab position from the global
- if(mPosRegion.isExactlyZero())
- {
- region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
- region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
- region_z = llround(parcel_data.global_z);
- }
+ S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ S32 region_z = llround(parcel_data.global_z);
- std::string name;
+ std::string name = getString("not_available");
if (!parcel_data.sim_name.empty())
{
name = llformat("%s (%d, %d, %d)",
@@ -403,19 +465,25 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mRegionName->setText(name);
}
- if (mCurrentTitle != getString("title_landmark"))
+ if (mInfoType == CREATE_LANDMARK)
{
- mTitleEditor->setText(parcel_data.name);
+
+ if (parcel_data.name.empty())
+ {
+ mTitleEditor->setText(name);
+ }
+ else
+ {
+ mTitleEditor->setText(parcel_data.name);
+ }
+
mNotesEditor->setText(LLStringUtil::null);
}
}
-void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region,
- const LLUUID& region_id,
- const LLVector3d& pos_global)
+void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
+ const LLVector3d& pos_global)
{
- mPosRegion = pos_region;
-
LLViewerRegion* region = gAgent.getRegion();
if (!region)
return;
@@ -424,6 +492,10 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region,
std::string url = region->getCapability("RemoteParcelRequest");
if (!url.empty())
{
+ F32 region_x = (F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS);
+ F32 region_y = (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS);
+ LLVector3 pos_region(region_x, region_y, (F32)pos_global.mdV[VZ]);
+
body["location"] = ll_sd_from_vector3(pos_region);
if (!region_id.isNull())
{
@@ -442,15 +514,21 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region,
}
}
-void LLPanelPlaceInfo::displayAgentParcelInfo()
+void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel,
+ LLViewerRegion* region,
+ const LLVector3d& pos_global)
{
- mPosRegion = gAgent.getPositionAgent();
-
- LLViewerRegion* region = gAgent.getRegion();
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (!region || !parcel)
return;
+ // send EstateCovenantInfo message
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessage("EstateCovenantRequest");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->sendReliable(region->getHost());
+
LLParcelData parcel_data;
// HACK: Converting sim access flags to the format
@@ -466,25 +544,240 @@ void LLPanelPlaceInfo::displayAgentParcelInfo()
default:
parcel_data.flags = 0;
}
-
- // Adding "For Sale" flag in remote parcel response format.
- if (parcel->getForSale())
- {
- parcel_data.flags |= DFQ_FOR_SALE;
- }
-
parcel_data.desc = parcel->getDesc();
parcel_data.name = parcel->getName();
parcel_data.sim_name = gAgent.getRegion()->getName();
parcel_data.snapshot_id = parcel->getSnapshotID();
- LLVector3d global_pos = gAgent.getPositionGlobal();
- parcel_data.global_x = global_pos.mdV[0];
- parcel_data.global_y = global_pos.mdV[1];
- parcel_data.global_z = global_pos.mdV[2];
+ parcel_data.global_x = pos_global.mdV[0];
+ parcel_data.global_y = pos_global.mdV[1];
+ parcel_data.global_z = pos_global.mdV[2];
-
+ std::string on = getString("on");
+ std::string off = getString("off");
+
+ // Processing parcel characteristics
+ if (parcel->getParcelFlagAllowVoice())
+ {
+ mVoiceText->setText(on);
+ }
+ else
+ {
+ mVoiceText->setText(off);
+ }
+
+ if (!region->getBlockFly() && parcel->getAllowFly())
+ {
+ mFlyText->setText(on);
+ }
+ else
+ {
+ mFlyText->setText(off);
+ }
+
+ if (region->getRestrictPushObject() || parcel->getRestrictPushObject())
+ {
+ mPushText->setText(off);
+ }
+ else
+ {
+ mPushText->setText(on);
+ }
+
+ if (parcel->getAllowModify())
+ {
+ mBuildText->setText(on);
+ }
+ else
+ {
+ mBuildText->setText(off);
+ }
+
+ if((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) ||
+ (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) ||
+ !parcel->getAllowOtherScripts())
+ {
+ mScriptsText->setText(off);
+ }
+ else
+ {
+ mScriptsText->setText(on);
+ }
+
+ if (region->getAllowDamage() || parcel->getAllowDamage())
+ {
+ mDamageText->setText(on);
+ }
+ else
+ {
+ mDamageText->setText(off);
+ }
+
+ mRegionNameText->setText(region->getName());
+ mRegionTypeText->setText(region->getSimProductName());
+ mRegionRatingText->setText(region->getSimAccessString());
+
+ // Determine parcel owner
+ if (parcel->isPublic())
+ {
+ mParcelOwner->setText(getString("public"));
+ mRegionOwnerText->setText(getString("public"));
+ }
+ else
+ {
+ if (parcel->getIsGroupOwned())
+ {
+ mRegionOwnerText->setText(getString("group_owned_text"));
+
+ if(!parcel->getGroupID().isNull())
+ {
+ // FIXME: Using parcel group as region group.
+ gCacheName->get(parcel->getGroupID(), TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mRegionGroupText, _2, _3));
+
+ gCacheName->get(parcel->getGroupID(), TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mParcelOwner, _2, _3));
+ }
+ else
+ {
+ std::string owner = getString("none_text");
+ mRegionGroupText->setText(owner);
+ mParcelOwner->setText(owner);
+ }
+ }
+ else
+ {
+ // Figure out the owner's name
+ gCacheName->get(parcel->getOwnerID(), FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mParcelOwner, _2, _3));
+ gCacheName->get(region->getOwner(), FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mRegionOwnerText, _2, _3));
+ }
+
+ if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
+ {
+ mRegionOwnerText->setText(mRegionOwnerText->getText() + getString("sale_pending_text"));
+ }
+ }
+
+ mEstateRatingText->setText(region->getSimAccessString());
+
+ S32 area;
+ S32 claim_price;
+ S32 rent_price;
+ F32 dwell;
+ BOOL for_sale = parcel->getForSale();
+ LLViewerParcelMgr::getInstance()->getDisplayInfo(&area,
+ &claim_price,
+ &rent_price,
+ &for_sale,
+ &dwell);
+
+ if (for_sale)
+ {
+ // Adding "For Sale" flag in remote parcel response format.
+ parcel_data.flags |= DFQ_FOR_SALE;
+
+ const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
+ if(auth_buyer_id.notNull())
+ {
+ gCacheName->get(auth_buyer_id, TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mSaleToText, _2, _3));
+
+ // Show sales info to a specific person or a group he belongs to.
+ if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id))
+ {
+ for_sale = FALSE;
+ }
+ }
+ else
+ {
+ mSaleToText->setText(getString("anyone"));
+ }
+
+ const U8* sign = (U8*)getString("price_text").c_str();
+ const U8* sqm = (U8*)getString("area_text").c_str();
+
+ mSalesPriceText->setText(llformat("%s%d ", sign, parcel->getSalePrice()));
+ mAreaText->setText(llformat("%d %s", area, sqm));
+ mTrafficText->setText(llformat("%.0f", dwell));
+
+ // Can't have more than region max tasks, regardless of parcel
+ // object bonus factor.
+ S32 primitives = llmin(llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()),
+ (S32)region->getMaxTasks());
+
+ const U8* available = (U8*)getString("available").c_str();
+ const U8* allocated = (U8*)getString("allocated").c_str();
+
+ mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, available, parcel->getPrimCount(), allocated));
+
+ if (parcel->getAllowOtherScripts())
+ {
+ mParcelScriptsText->setText(getString("all_residents_text"));
+ }
+ else if (parcel->getAllowGroupScripts())
+ {
+ mParcelScriptsText->setText(getString("group_text"));
+ }
+ else
+ {
+ mParcelScriptsText->setText(off);
+ }
+
+ mTerraformLimitsText->setText(parcel->getAllowTerraform() ? on : off);
+
+ if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES)
+ {
+ mSubdivideText->setText(getString("can_change"));
+ }
+ else
+ {
+ mSubdivideText->setText(getString("can_not_change"));
+ }
+ if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
+ {
+ mResaleText->setText(getString("can_not_resell"));
+ }
+ else
+ {
+ mResaleText->setText(getString("can_resell"));
+ }
+ }
processParcelInfo(parcel_data);
+
+ getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale);
+}
+
+void LLPanelPlaceInfo::updateEstateName(const std::string& name)
+{
+ mEstateNameText->setText(name);
+}
+
+void LLPanelPlaceInfo::updateEstateOwnerName(const std::string& name)
+{
+ mEstateOwnerText->setText(name);
+}
+
+void LLPanelPlaceInfo::updateCovenantText(const std::string &text)
+{
+ mCovenantText->setText(text);
+}
+
+void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date)
+{
+ if (date.isNull())
+ {
+ mLastVisited->setText(getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquired_date");
+ LLSD substitution;
+ substitution["datetime"] = (S32) date.secondsSinceEpoch();
+ LLStringUtil::format (timeStr, substitution);
+ mLastVisited->setText(timeStr);
+ }
}
void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type)
@@ -512,7 +805,10 @@ void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type)
}
}
- if (item_value != current_value &&
+ LLStringUtil::trim(current_value);
+
+ if (!current_value.empty() &&
+ item_value != current_value &&
gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
@@ -544,11 +840,17 @@ void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id)
if (name.empty())
{
name = mParcelName->getText();
+
+ // If no parcel exists use the region name instead.
+ if (name.empty())
+ {
+ name = mRegionName->getText();
+ }
}
LLStringUtil::replaceChar(desc, '\n', ' ');
// If no folder chosen use the "Landmarks" folder.
- LLLandmarkActions::createLandmarkHere(name, desc,
+ LLLandmarkActions::createLandmarkHere(name, desc,
folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK));
}
@@ -561,19 +863,24 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& global_pos)
pick_data.pick_id = LLUUID::generateNewID();
pick_data.creator_id = gAgentID;
- //legacy var need to be deleted
+ //legacy var needs to be deleted
pick_data.top_pick = FALSE;
pick_data.parcel_id = mParcelID;
pick_data.name = mParcelName->getText();
+ if (pick_data.name.empty())
+ {
+ pick_data.name = mRegionName->getText();
+ }
pick_data.desc = mDescEditor->getText();
pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
pick_data.pos_global = global_pos;
pick_data.sort_order = 0;
pick_data.enabled = TRUE;
- LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO);
+ LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
}
+// virtual
void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (mMinHeight > 0 && mScrollingPanel != NULL)
@@ -583,3 +890,22 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
LLView::reshape(width, height, called_from_parent);
}
+
+// virtual
+void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Remove land selection when panel hides.
+ if (!new_visibility)
+ {
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectLand();
+ }
+ }
+}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 77ce2c6619..32ae4334aa 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -46,9 +46,11 @@
class LLButton;
class LLInventoryItem;
class LLLineEditor;
+class LLParcel;
class LLTextBox;
class LLTextEditor;
class LLTextureCtrl;
+class LLViewerRegion;
class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
{
@@ -97,13 +99,19 @@ public:
// Displays information about a remote parcel.
// Sends a request to the server.
- void displayParcelInfo(const LLVector3& pos_region,
- const LLUUID& region_id,
+ void displayParcelInfo(const LLUUID& region_id,
const LLVector3d& pos_global);
- // Displays information about the parcel the agent is currently on
+ // Displays information about the currently selected parcel
// without sending a request to the server.
- void displayAgentParcelInfo();
+ void displaySelectedParcelInfo(LLParcel* parcel,
+ LLViewerRegion* region,
+ const LLVector3d& pos_global);
+
+ void updateEstateName(const std::string& name);
+ void updateEstateOwnerName(const std::string& name);
+ void updateCovenantText(const std::string &text);
+ void updateLastVisitedText(const LLDate &date);
void nameUpdatedCallback(LLTextBox* text,
const std::string& first,
@@ -111,6 +119,7 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ void handleVisibilityChange (BOOL new_visibility);
private:
enum LANDMARK_INFO_TYPE
@@ -124,24 +133,53 @@ private:
LLUUID mParcelID;
LLUUID mRequestedID;
LLUUID mLandmarkID;
- LLVector3 mPosRegion;
std::string mCurrentTitle;
S32 mMinHeight;
+ INFO_TYPE mInfoType;
LLTextBox* mTitle;
LLTextureCtrl* mSnapshotCtrl;
LLTextBox* mRegionName;
LLTextBox* mParcelName;
LLTextEditor* mDescEditor;
- LLIconCtrl* mRating;
- LLButton* mRegionInfoDrillIn;
- LLButton* mMediaDrillIn;
+ LLTextBox* mMaturityRatingText;
+ LLTextBox* mParcelOwner;
+ LLTextBox* mLastVisited;
+
+ LLTextBox* mRatingText;
+ LLTextBox* mVoiceText;
+ LLTextBox* mFlyText;
+ LLTextBox* mPushText;
+ LLTextBox* mBuildText;
+ LLTextBox* mScriptsText;
+ LLTextBox* mDamageText;
+
+ LLTextBox* mRegionNameText;
+ LLTextBox* mRegionTypeText;
+ LLTextBox* mRegionRatingText;
+ LLTextBox* mRegionOwnerText;
+ LLTextBox* mRegionGroupText;
+
+ LLTextBox* mEstateNameText;
+ LLTextBox* mEstateRatingText;
+ LLTextBox* mEstateOwnerText;
+ LLTextEditor* mCovenantText;
+
+ LLTextBox* mSalesPriceText;
+ LLTextBox* mAreaText;
+ LLTextBox* mTrafficText;
+ LLTextBox* mPrimitivesText;
+ LLTextBox* mParcelScriptsText;
+ LLTextBox* mTerraformLimitsText;
+ LLTextEditor* mSubdivideText;
+ LLTextEditor* mResaleText;
+ LLTextBox* mSaleToText;
+
LLTextBox* mOwner;
LLTextBox* mCreator;
LLTextBox* mCreated;
LLLineEditor* mTitleEditor;
LLTextEditor* mNotesEditor;
- LLTextBox* mLocationEditor;
LLPanel* mScrollingPanel;
LLPanel* mInfoPanel;
LLMediaPanel* mMediaPanel;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 7cb9e61e72..11ddc3dd9a 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -31,10 +31,14 @@
#include "llviewerprecompiledheaders.h"
+#include "llpanelplaces.h"
+
#include "llassettype.h"
#include "llwindow.h"
+#include "llinventory.h"
#include "lllandmark.h"
+#include "llparcel.h"
#include "llfloaterreg.h"
#include "llnotifications.h"
@@ -44,18 +48,21 @@
#include "lluictrlfactory.h"
#include "llagent.h"
+#include "llfloaterworldmap.h"
+#include "llinventorymodel.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
-#include "llfloaterworldmap.h"
-#include "llpanelplaces.h"
+#include "llpanelplaceinfo.h"
#include "llpanellandmarks.h"
#include "llpanelteleporthistory.h"
#include "llsidetray.h"
+#include "llteleporthistorystorage.h"
#include "lltoggleablemenu.h"
#include "llviewerinventory.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
+#include "llviewerwindow.h"
static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250;
static const std::string AGENT_INFO_TYPE = "agent";
@@ -68,9 +75,41 @@ static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history";
static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
-static const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global);
static void onSLURLBuilt(std::string& slurl);
+//Observer classes
+class LLPlacesParcelObserver : public LLParcelObserver
+{
+public:
+ LLPlacesParcelObserver(LLPanelPlaces* places_panel)
+ : mPlaces(places_panel) {}
+
+ /*virtual*/ void changed()
+ {
+ if (mPlaces)
+ mPlaces->changedParcelSelection();
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+};
+
+class LLPlacesInventoryObserver : public LLInventoryObserver
+{
+public:
+ LLPlacesInventoryObserver(LLPanelPlaces* places_panel)
+ : mPlaces(places_panel) {}
+
+ /*virtual*/ void changed(U32 mask)
+ {
+ if (mPlaces)
+ mPlaces->changedInventory(mask);
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+};
+
static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places");
LLPanelPlaces::LLPanelPlaces()
@@ -81,11 +120,14 @@ LLPanelPlaces::LLPanelPlaces()
mPlaceInfo(NULL),
mItem(NULL),
mPlaceMenu(NULL),
- mLandmarkMenu(NULL),
+ mLandmarkMenu(NULL),
mLandmarkFoldersMenuHandle(),
mPosGlobal()
{
- gInventory.addObserver(this);
+ mParcelObserver = new LLPlacesParcelObserver(this);
+ mInventoryObserver = new LLPlacesInventoryObserver(this);
+
+ gInventory.addObserver(mInventoryObserver);
LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
boost::bind(&LLPanelPlaces::onAgentParcelChange, this));
@@ -95,10 +137,15 @@ LLPanelPlaces::LLPanelPlaces()
LLPanelPlaces::~LLPanelPlaces()
{
- if (gInventory.containsObserver(this))
- gInventory.removeObserver(this);
-
+ if (gInventory.containsObserver(mInventoryObserver))
+ gInventory.removeObserver(mInventoryObserver);
+
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
LLView::deleteViewByHandle(mLandmarkFoldersMenuHandle);
+
+ delete mInventoryObserver;
+ delete mParcelObserver;
}
BOOL LLPanelPlaces::postBuild()
@@ -119,9 +166,6 @@ BOOL LLPanelPlaces::postBuild()
//mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this));
mOverflowBtn = getChild<LLButton>("overflow_btn");
-
- // *TODO: Assign the action to an appropriate event.
- //mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::toggleMediaPanel, this));
mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -156,20 +200,17 @@ BOOL LLPanelPlaces::postBuild()
LLButton* back_btn = mPlaceInfo->getChild<LLButton>("back_btn");
back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
- // *TODO: Assign the action to an appropriate event.
- mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::toggleMediaPanel, this));
-
return TRUE;
}
void LLPanelPlaces::onOpen(const LLSD& key)
{
- mFilterEditor->clear();
- onFilterEdit("");
-
if(mPlaceInfo == NULL || key.size() == 0)
return;
+ mFilterEditor->clear();
+ onFilterEdit("");
+
mPlaceInfoType = key["type"].asString();
mPosGlobal.setZero();
togglePlaceInfoPanel(TRUE);
@@ -178,16 +219,10 @@ void LLPanelPlaces::onOpen(const LLSD& key)
if (mPlaceInfoType == AGENT_INFO_TYPE)
{
mPlaceInfo->setInfoType(LLPanelPlaceInfo::AGENT);
- mPlaceInfo->displayAgentParcelInfo();
-
- mPosGlobal = gAgent.getPositionGlobal();
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
mPlaceInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
- mPlaceInfo->displayAgentParcelInfo();
-
- mPosGlobal = gAgent.getPositionGlobal();
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
@@ -195,7 +230,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
LLInventoryItem* item = gInventory.getItem(item_uuid);
if (!item)
return;
-
+
setItem(item);
}
else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
@@ -210,26 +245,44 @@ void LLPanelPlaces::onOpen(const LLSD& key)
key["z"].asReal());
mPlaceInfo->setInfoType(LLPanelPlaceInfo::PLACE);
- mPlaceInfo->displayParcelInfo(get_pos_local_from_global(mPosGlobal),
- LLUUID(),
- mPosGlobal);
+ mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
}
else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
S32 index = key["id"].asInteger();
- const LLTeleportHistory::slurl_list_t& hist_items =
- LLTeleportHistory::getInstance()->getItems();
+ const LLTeleportHistoryStorage::slurl_list_t& hist_items =
+ LLTeleportHistoryStorage::getInstance()->getItems();
mPosGlobal = hist_items[index].mGlobalPos;
mPlaceInfo->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
- mPlaceInfo->displayParcelInfo(get_pos_local_from_global(mPosGlobal),
- hist_items[index].mRegionID,
- mPosGlobal);
+ mPlaceInfo->updateLastVisitedText(hist_items[index].mDate);
+ mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
}
-
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Start using LLViewerParcelMgr for land selection if
+ // information about nearby land is requested.
+ // Otherwise stop using land selection and deselect land.
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ parcel_mgr->addObserver(mParcelObserver);
+ parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
+ }
+ else
+ {
+ parcel_mgr->removeObserver(mParcelObserver);
+
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectLand();
+ }
+ }
}
void LLPanelPlaces::setItem(LLInventoryItem* item)
@@ -266,9 +319,7 @@ void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
LLUUID region_id;
landmark->getRegionID(region_id);
landmark->getGlobalPos(mPosGlobal);
- mPlaceInfo->displayParcelInfo(landmark->getRegionPos(),
- region_id,
- mPosGlobal);
+ mPlaceInfo->displayParcelInfo(region_id, mPosGlobal);
}
void LLPanelPlaces::onFilterEdit(const std::string& search_string)
@@ -389,7 +440,7 @@ void LLPanelPlaces::onOverflowButtonClicked()
mPlaceInfoType == "teleport_history") && mPlaceMenu != NULL)
{
menu = mPlaceMenu;
-
+
// Enable adding a landmark only for agent current parcel and if
// there is no landmark already pointing to that parcel in agent's inventory.
menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
@@ -512,8 +563,40 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
}
}
-//virtual
-void LLPanelPlaces::changed(U32 mask)
+void LLPanelPlaces::changedParcelSelection()
+{
+ if (!mPlaceInfo)
+ return;
+
+ mParcel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
+ LLParcel* parcel = mParcel->getParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+ if (!region || !parcel)
+ return;
+
+ // If agent is inside the selected parcel show agent's region<X, Y, Z>,
+ // otherwise show region<X, Y, Z> of agent's selection point.
+ if (region == gAgent.getRegion() &&
+ parcel->getLocalID() == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID())
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+ else
+ {
+ LLVector3d pos_global = gViewerWindow->getLastPick().mPosGlobal;
+ if (!pos_global.isExactlyZero())
+ {
+ mPosGlobal = pos_global;
+ }
+ }
+
+ mPlaceInfo->resetLocation();
+ mPlaceInfo->displaySelectedParcelInfo(parcel, region, mPosGlobal);
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::changedInventory(U32 mask)
{
if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance()))
return;
@@ -548,7 +631,7 @@ void LLPanelPlaces::changed(U32 mask)
// we don't need to monitor inventory changes anymore,
// so remove the observer
- gInventory.removeObserver(this);
+ gInventory.removeObserver(mInventoryObserver);
}
void LLPanelPlaces::onAgentParcelChange()
@@ -556,11 +639,7 @@ void LLPanelPlaces::onAgentParcelChange()
if (!mPlaceInfo)
return;
- if (mPlaceInfo->getVisible() && mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
- {
- onOpen(LLSD().insert("type", mPlaceInfoType));
- }
- else if (mPlaceInfo->isMediaPanelVisible())
+ if (mPlaceInfo->isMediaPanelVisible())
{
onOpen(LLSD().insert("type", AGENT_INFO_TYPE));
}
@@ -807,15 +886,6 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
}
}
-static const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global)
-{
- F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
- F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
-
- LLVector3 pos_local(region_x, region_y, (F32)pos_global.mdV[VZ]);
- return pos_local;
-}
-
static void onSLURLBuilt(std::string& slurl)
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 089a854762..54bc2b9003 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -32,33 +32,35 @@
#ifndef LL_LLPANELPLACES_H
#define LL_LLPANELPLACES_H
-#include "lltimer.h"
-
#include "llpanel.h"
-#include "llinventory.h"
-
-#include "llinventorymodel.h"
-#include "llpanelplaceinfo.h"
-
class LLInventoryItem;
+class LLFilterEditor;
class LLLandmark;
+class LLPanelPlaceInfo;
class LLPanelPlacesTab;
-class LLFilterEditor;
+class LLParcelSelection;
+class LLPlacesInventoryObserver;
+class LLPlacesParcelObserver;
class LLTabContainer;
+class LLToggleableMenu;
typedef std::pair<LLUUID, std::string> folder_pair_t;
-class LLPanelPlaces : public LLPanel, LLInventoryObserver
+class LLPanelPlaces : public LLPanel
{
public:
LLPanelPlaces();
virtual ~LLPanelPlaces();
/*virtual*/ BOOL postBuild();
- /*virtual*/ void changed(U32 mask);
/*virtual*/ void onOpen(const LLSD& key);
+ // Called on parcel selection change to update place information.
+ void changedParcelSelection();
+ // Called on agent inventory change to find out when inventory gets usable.
+ void changedInventory(U32 mask);
+
void setItem(LLInventoryItem* item);
private:
@@ -79,7 +81,7 @@ private:
void onAgentParcelChange();
void updateVerbs();
-
+
void showLandmarkFoldersMenu();
LLFilterEditor* mFilterEditor;
@@ -96,9 +98,12 @@ private:
LLButton* mShareBtn;
LLButton* mOverflowBtn;
+ LLPlacesInventoryObserver* mInventoryObserver;
+ LLPlacesParcelObserver* mParcelObserver;
+
// Pointer to a landmark item or to a linked landmark
LLPointer<LLInventoryItem> mItem;
-
+
// Absolute position of the location for teleport, may not
// be available (hence zero)
LLVector3d mPosGlobal;
@@ -118,11 +123,13 @@ private:
// List of folders to choose from when creating a landmark
folder_vec_t mLandmarkFoldersCache;
-
+
// If root view width or height is changed
// the pop-up menu must be updated
S32 mRootViewWidth;
S32 mRootViewHeight;
+
+ LLSafeHandle<LLParcelSelection> mParcel;
};
#endif //LL_LLPANELPLACES_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 6d3d307526..ce01568e99 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -46,7 +46,7 @@ class LLAgentHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLAgentHandler() : LLCommandHandler("agent", true) { }
+ LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
index 18184a6476..0762bbeb87 100644
--- a/indra/newview/llpanelprofileview.cpp
+++ b/indra/newview/llpanelprofileview.cpp
@@ -31,12 +31,16 @@
*/
#include "llviewerprecompiledheaders.h"
+
+#include "lluserrelations.h"
+
#include "llpanelprofileview.h"
+#include "llcallingcard.h"
#include "llpanelavatar.h"
#include "llpanelpicks.h"
-#include "llsidetraypanelcontainer.h"
#include "llpanelprofile.h"
+#include "llsidetraypanelcontainer.h"
static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("panel_profile_view");
@@ -45,6 +49,7 @@ static const std::string PANEL_PROFILE = "panel_profile";
LLPanelProfileView::LLPanelProfileView()
: LLPanelProfile()
+, mStatusText(NULL)
{
}
@@ -65,6 +70,10 @@ void LLPanelProfileView::onOpen(const LLSD& key)
setAvatarId(id);
}
+ // status should only show if viewer has permission to view online/offline. EXT-453
+ mStatusText->setVisible(isGrantedToSeeOnlineStatus());
+ updateOnlineStatus();
+
LLPanelProfile::onOpen(key);
}
@@ -78,6 +87,8 @@ BOOL LLPanelProfileView::postBuild()
getTabContainer()[PANEL_PROFILE]->childSetVisible("online_me_status_text", FALSE);
getTabContainer()[PANEL_PROFILE]->childSetVisible("status_combo", FALSE);
+ mStatusText = getChild<LLTextBox>("status");
+
childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL);
return TRUE;
@@ -94,3 +105,32 @@ void LLPanelProfileView::onBackBtnClick()
parent->openPreviousPanel();
}
}
+
+bool LLPanelProfileView::isGrantedToSeeOnlineStatus()
+{
+ const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ if (NULL == relationship)
+ return false;
+
+ // *NOTE: GRANT_ONLINE_STATUS is always set to false while changing any other status.
+ // When avatar disallow me to see her online status processOfflineNotification Message is received by the viewer
+ // see comments for ChangeUserRights template message. EXT-453.
+// return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS);
+ return true;
+}
+
+void LLPanelProfileView::updateOnlineStatus()
+{
+ const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ if (NULL == relationship)
+ return;
+
+ bool online = relationship->isOnline();
+// std::string statusName();
+
+ std::string status = getString(online ? "status_online" : "status_offline");
+
+ mStatusText->setValue(status);
+}
+
+// EOF
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
index 92def7b7ca..533ab94cc3 100644
--- a/indra/newview/llpanelprofileview.h
+++ b/indra/newview/llpanelprofileview.h
@@ -39,7 +39,7 @@
class LLPanelProfile;
class LLPanelProfileTab;
-
+class LLTextBox;
/**
* Panel for displaying Avatar's profile. It consists of three sub panels - Profile,
@@ -63,6 +63,11 @@ public:
protected:
void onBackBtnClick();
+ bool isGrantedToSeeOnlineStatus();
+ void updateOnlineStatus();
+
+private:
+ LLTextBox* mStatusText;
};
#endif //LL_LLPANELPROFILEVIEW_H
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 8b378c33e3..1fd7928bfc 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -37,6 +37,9 @@
#include "llpanelteleporthistory.h"
#include "llsidetray.h"
#include "llworldmap.h"
+#include "llteleporthistorystorage.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
// Not yet implemented; need to remove buildPanel() from constructor when we switch
//static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
@@ -45,7 +48,8 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
: LLPanelPlacesTab(),
mFilterSubString(LLStringUtil::null),
mTeleportHistory(NULL),
- mHistoryItems(NULL)
+ mHistoryAccordeon(NULL),
+ mLastSelectedScrollList(NULL)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history.xml");
}
@@ -56,18 +60,34 @@ LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
BOOL LLTeleportHistoryPanel::postBuild()
{
- mTeleportHistory = LLTeleportHistory::getInstance();
+ mTeleportHistory = LLTeleportHistoryStorage::getInstance();
if (mTeleportHistory)
{
mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::showTeleportHistory, this));
}
- mHistoryItems = getChild<LLScrollListCtrl>("history_items");
- if (mHistoryItems)
+ mHistoryAccordeon = getChild<LLAccordionCtrl>("history_accordion");
+
+ if (mHistoryAccordeon)
{
- mHistoryItems->setDoubleClickCallback(onDoubleClickItem, this);
- mHistoryItems->setCommitOnSelectionChange(FALSE);
- mHistoryItems->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, _2));
+
+ for (child_list_const_iter_t iter = mHistoryAccordeon->beginChild(); iter != mHistoryAccordeon->endChild(); iter++)
+ {
+ if (dynamic_cast<LLAccordionCtrlTab*>(*iter))
+ {
+ LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter;
+ mItemContainers.put(tab);
+
+ LLScrollListCtrl* sl = getScrollListFromTab(tab);
+ if (sl)
+ {
+ sl->setDoubleClickCallback(onDoubleClickItem, this);
+ sl->setCommitOnSelectionChange(FALSE);
+ sl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, sl));
+ }
+
+ }
+ }
}
return TRUE;
@@ -86,15 +106,16 @@ void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
// virtual
void LLTeleportHistoryPanel::onShowOnMap()
{
- LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
+ if (!mLastSelectedScrollList)
+ return;
+
+ LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected();
if(!itemp)
return;
S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
- const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
-
- LLVector3d global_pos = hist_items[index].mGlobalPos;
+ LLVector3d global_pos = mTeleportHistory->getItems()[mTeleportHistory->getItems().size() - 1 - index].mGlobalPos;
if (!global_pos.isExactlyZero())
{
@@ -106,14 +127,17 @@ void LLTeleportHistoryPanel::onShowOnMap()
// virtual
void LLTeleportHistoryPanel::onTeleport()
{
- LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
+ if (!mLastSelectedScrollList)
+ return;
+
+ LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected();
if(!itemp)
return;
S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
// teleport to existing item in history, so we don't add it again
- mTeleportHistory->goToItem(index);
+ mTeleportHistory->goToItem(mTeleportHistory->getItems().size() - 1 - index);
}
/*
@@ -146,30 +170,41 @@ void LLTeleportHistoryPanel::updateVerbs()
if (!isTabVisible())
return;
- S32 index = 0;
- S32 cur_item = 0;
-
- LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
- if (itemp)
+ if (!mLastSelectedScrollList)
{
- index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
- cur_item = mTeleportHistory->getCurrentItemIndex();
+ mTeleportBtn->setEnabled(false);
+ mShowOnMapBtn->setEnabled(false);
+ return;
}
- mTeleportBtn->setEnabled(index != cur_item);
- mShowOnMapBtn->setEnabled(itemp != NULL);
+ LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected();
+
+ mTeleportBtn->setEnabled(NULL != itemp && 0 < itemp->getColumn(LIST_INDEX)->getValue().asInteger());
+ mShowOnMapBtn->setEnabled(NULL != itemp);
}
void LLTeleportHistoryPanel::showTeleportHistory()
{
- const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
+ if (!mHistoryAccordeon)
+ return;
- mHistoryItems->deleteAllItems();
+ const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems();
- S32 cur_item = mTeleportHistory->getCurrentItemIndex();
+ const U32 seconds_in_day = 24 * 60 * 60;
+ LLDate curr_date = LLDate::now();
- for (LLTeleportHistory::slurl_list_t::const_iterator iter = hist_items.begin();
- iter != hist_items.end(); ++iter)
+ curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day);
+
+ S32 curr_tab = -1;
+ S32 tabs_cnt = mItemContainers.size();
+ S32 curr_year = 0, curr_month = 0, curr_day = 0;
+
+ LLScrollListCtrl *curr_scroll_list = NULL;
+
+ S32 index = 0;
+
+ for (LLTeleportHistoryStorage::slurl_list_t::const_reverse_iterator iter = hist_items.rbegin();
+ iter != hist_items.rend(); ++iter)
{
std::string landmark_title = (*iter).mTitle;
LLStringUtil::toUpper(landmark_title);
@@ -179,48 +214,83 @@ void LLTeleportHistoryPanel::showTeleportHistory()
if (!passed)
continue;
-
- S32 index = iter - hist_items.begin();
+
+ if (curr_tab < tabs_cnt - 1)
+ {
+ const LLDate &date = (*iter).mDate;
+
+ S32 year, month, day;
+ if (!date.split(&year, &month, &day))
+ {
+ llwarns << "Failed to split date: " << date << llendl;
+ continue;
+ }
+
+ if (day != curr_day || month != curr_month || year != curr_year)
+ {
+ LLAccordionCtrlTab* tab = NULL;
+ while (curr_tab < tabs_cnt - 1 && (day != curr_day || month != curr_month || year != curr_year))
+ {
+ curr_tab++;
+
+ tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab);
+ tab->setVisible(false);
+
+ curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day);
+ curr_date.split(&curr_year, &curr_month, &curr_day);
+ }
+
+ tab->setVisible(true);
+
+ curr_scroll_list = getScrollListFromTab(tab);
+ if (curr_scroll_list)
+ {
+ curr_scroll_list->deleteAllItems();
+ }
+ }
+ }
LLSD row;
row["id"] = index;
- LLSD& icon_column = row["columns"][LIST_ICON];
- icon_column["column"] = "landmark_icon";
- icon_column["type"] = "icon";
- icon_column["value"] = "inv_item_landmark.tga";
+ if (curr_scroll_list)
+ {
+ LLSD& icon_column = row["columns"][LIST_ICON];
+ icon_column["column"] = "landmark_icon";
+ icon_column["type"] = "icon";
+ icon_column["value"] = "inv_item_landmark.tga";
- LLSD& region_column = row["columns"][LIST_ITEM_TITLE];
- region_column["column"] = "region";
- region_column["type"] = "text";
- region_column["value"] = (*iter).mTitle;
+ LLSD& region_column = row["columns"][LIST_ITEM_TITLE];
+ region_column["column"] = "region";
+ region_column["type"] = "text";
+ region_column["value"] = (*iter).mTitle;
- LLSD& index_column = row["columns"][LIST_INDEX];
- index_column["column"] = "index";
- index_column["type"] = "text";
- index_column["value"] = index;
+ LLSD& index_column = row["columns"][LIST_INDEX];
+ index_column["column"] = "index";
+ index_column["type"] = "text";
+ index_column["value"] = index;
- mHistoryItems->addElement(row, ADD_TOP);
+ index++;
- if (cur_item == index)
- {
- LLScrollListItem* itemp = mHistoryItems->getItem(index);
- ((LLScrollListText*)itemp->getColumn(LIST_ITEM_TITLE))->setFontStyle(LLFontGL::BOLD);
+ curr_scroll_list->addElement(row);
}
}
+ mHistoryAccordeon->arrange();
+
updateVerbs();
}
-void LLTeleportHistoryPanel::handleItemSelect(const LLSD& data)
+void LLTeleportHistoryPanel::handleItemSelect(LLScrollListCtrl* sl)
{
+ mLastSelectedScrollList = sl;
updateVerbs();
}
//static
void LLTeleportHistoryPanel::onDoubleClickItem(void* user_data)
{
- LLTeleportHistoryPanel* self = (LLTeleportHistoryPanel*)user_data;
+ /*LLTeleportHistoryPanel* self = (LLTeleportHistoryPanel*)user_data;
LLScrollListItem* itemp = self->mHistoryItems->getFirstSelected();
if(!itemp)
@@ -230,5 +300,18 @@ void LLTeleportHistoryPanel::onDoubleClickItem(void* user_data)
key["type"] = "teleport_history";
key["id"] = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
- LLSideTray::getInstance()->showPanel("panel_places", key);
+ LLSideTray::getInstance()->showPanel("panel_places", key);*/
+}
+
+LLScrollListCtrl* LLTeleportHistoryPanel::getScrollListFromTab(LLAccordionCtrlTab *tab)
+{
+ for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++)
+ {
+ if (dynamic_cast<LLScrollListCtrl*>(*iter))
+ {
+ return (LLScrollListCtrl*)*iter; // There should be one scroll list per tab.
+ }
+ }
+
+ return NULL;
}
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index 553385b37e..a1c15d087b 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -39,6 +39,10 @@
#include "llpanelplacestab.h"
#include "llteleporthistory.h"
+class LLTeleportHistoryStorage;
+class LLAccordionCtrl;
+class LLAccordionCtrlTab;
+
class LLTeleportHistoryPanel : public LLPanelPlacesTab
{
public:
@@ -51,13 +55,14 @@ public:
/*virtual*/ void onTeleport();
///*virtual*/ void onCopySLURL();
/*virtual*/ void updateVerbs();
-
- void showTeleportHistory();
- void handleItemSelect(const LLSD& data);
+
+private:
static void onDoubleClickItem(void* user_data);
+ void showTeleportHistory();
+ void handleItemSelect(LLScrollListCtrl* );
+ LLScrollListCtrl* getScrollListFromTab(LLAccordionCtrlTab *);
-private:
enum TELEPORT_HISTORY_COLUMN_ORDER
{
LIST_ICON,
@@ -65,9 +70,13 @@ private:
LIST_INDEX
};
- LLTeleportHistory* mTeleportHistory;
- LLScrollListCtrl* mHistoryItems;
+ LLTeleportHistoryStorage* mTeleportHistory;
+ LLAccordionCtrl* mHistoryAccordeon;
+ LLScrollListCtrl* mLastSelectedScrollList;
std::string mFilterSubString;
+
+ typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t;
+ item_containers_t mItemContainers;
};
#endif //LL_LLPANELTELEPORTHISTORY_H
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index cadab71ba8..29320522d9 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -87,6 +87,7 @@ BOOL LLPreviewNotecard::postBuild()
LLViewerTextEditor *ed = getChild<LLViewerTextEditor>("Notecard Editor");
if (ed)
{
+ ed->setParseHTML(TRUE);
ed->setNotecardInfo(mItemUUID, mObjectID, getKey());
ed->makePristine();
}
@@ -126,7 +127,7 @@ void LLPreviewNotecard::draw()
{
LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
BOOL changed = !editor->isPristine();
-
+
childSetEnabled("Save", changed && getEnabled());
LLPreview::draw();
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index f70cfc59ec..aa603c417f 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -72,7 +72,6 @@ const S32 ANIMATION_FRAMES = 1; //13;
LLProgressView::LLProgressView(const LLRect &rect)
: LLPanel(),
mPercentDone( 0.f ),
- mURLInMessage(false),
mMouseDownInActiveArea( false )
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml");
@@ -207,12 +206,7 @@ void LLProgressView::setPercent(const F32 percent)
void LLProgressView::setMessage(const std::string& msg)
{
mMessage = msg;
- mURLInMessage = (mMessage.find( "https://" ) != std::string::npos ||
- mMessage.find( "http://" ) != std::string::npos ||
- mMessage.find( "ftp://" ) != std::string::npos);
-
getChild<LLTextBox>("message_text")->setWrappedText(LLStringExplicit(mMessage));
- getChild<LLTextBox>("message_text")->setHoverActive(mURLInMessage);
}
void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index 83574ff52a..865646c85d 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -74,7 +74,6 @@ protected:
LLFrameTimer mProgressTimer;
LLRect mOutlineRect;
bool mMouseDownInActiveArea;
- bool mURLInMessage;
static LLProgressView* sInstance;
};
diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp
index 0c16cea004..04abe36878 100644
--- a/indra/newview/llrecentpeople.cpp
+++ b/indra/newview/llrecentpeople.cpp
@@ -43,7 +43,8 @@ bool LLRecentPeople::add(const LLUUID& id)
if (contains(id) || id == gAgent.getID())
return false;
- mList.insert(id);
+ LLDate date_added = LLDate::now();
+ mList.insert(std::make_pair(id, date_added));
mChangedSignal();
return true;
}
@@ -56,8 +57,8 @@ bool LLRecentPeople::contains(const LLUUID& id) const
void LLRecentPeople::get(std::vector<LLUUID>& result) const
{
result.clear();
- for (std::set<LLUUID>::const_iterator pos = mList.begin(); pos != mList.end(); ++pos)
- result.push_back(*pos);
+ for (recent_people_t::const_iterator pos = mList.begin(); pos != mList.end(); ++pos)
+ result.push_back((*pos).first);
}
// virtual
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index 40ac80e8bc..c18116b4e5 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -41,6 +41,8 @@
#include <set>
#include <boost/signals2.hpp>
+class LLDate;
+
/**
* List of people the agent recently interacted with.
*
@@ -62,7 +64,7 @@ public:
* Add specified avatar to the list if it's not there already.
*
* @param id avatar to add.
- * @return false if the avatar is in the list already, true otherwisr
+ * @return false if the avatar is in the list already, true otherwise
*/
bool add(const LLUUID& id);
@@ -94,7 +96,8 @@ public:
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
private:
- std::set<LLUUID> mList;
+ typedef std::map<LLUUID, LLDate> recent_people_t;
+ recent_people_t mList;
signal_t mChangedSignal;
};
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 68996673be..2157f1af74 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -64,6 +64,7 @@ LLScreenChannel::LLScreenChannel(LLUUID& id): mOverflowToastPanel(NULL), mStartU
setMouseOpaque( false );
}
+//--------------------------------------------------------------------------
void LLScreenChannel::init(S32 channel_left, S32 channel_right)
{
S32 channel_top = getRootView()->getRect().getHeight() - gSavedSettings.getS32("NavBarMargin");
@@ -88,9 +89,12 @@ void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent)
//--------------------------------------------------------------------------
void LLScreenChannel::addToast(LLToast::Params p)
{
- bool store_toast = !mShowToasts && p.can_be_stored && mCanStoreToasts;
+ bool store_toast = false, show_toast = false;
+
+ show_toast = mShowToasts || p.force_show;
+ store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;
- if(!mShowToasts && !store_toast)
+ if(!show_toast && !store_toast)
{
mOnRejectToast(p);
return;
@@ -106,7 +110,7 @@ void LLScreenChannel::addToast(LLToast::Params p)
new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
}
- if(mShowToasts)
+ if(show_toast)
{
mToastList.push_back(new_toast_elem);
showToasts();
@@ -323,6 +327,7 @@ void LLScreenChannel::showToastsBottom()
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
+ (*it).toast->stopTimer();
mHiddenToastsNum++;
}
createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastTime"));
diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp
new file mode 100644
index 0000000000..0b7621daa5
--- /dev/null
+++ b/indra/newview/llsearchcombobox.cpp
@@ -0,0 +1,265 @@
+/**
+ * @file llsearchcombobox.cpp
+ * @brief Search Combobox implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsearchcombobox.h"
+
+#include "llkeyboard.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
+
+class LLSearchHistoryBuilder
+{
+public:
+ LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter);
+
+ virtual void buildSearchHistory();
+
+ virtual ~LLSearchHistoryBuilder(){}
+
+protected:
+
+ virtual bool filterSearchHistory();
+
+ LLSearchComboBox* mComboBox;
+ std::string mFilter;
+ LLSearchHistory::search_history_list_t mFilteredSearchHistory;
+};
+
+LLSearchComboBox::Params::Params()
+: search_button("search_button")
+, dropdown_button_visible("dropdown_button_visible", false)
+{
+}
+
+LLSearchComboBox::LLSearchComboBox(const Params&p)
+: LLComboBox(p)
+{
+ S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
+ S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
+ LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
+
+ LLButton::Params button_params(p.search_button);
+ button_params.name(std::string("search_btn"));
+ button_params.rect(search_btn_rect) ;
+ button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
+ button_params.tab_stop(false);
+ button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
+ mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
+ mTextEntry->addChild(mSearchButton);
+
+ setButtonVisible(p.dropdown_button_visible);
+ mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2));
+ mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL);
+ setSelectionCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
+ setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2));
+ mSearchButton->setCommitCallback(boost::bind(&LLSearchComboBox::onTextCommit, this, _2));
+}
+
+void LLSearchComboBox::rebuildSearchHistory(const std::string& filter)
+{
+ LLSearchHistoryBuilder builder(this, filter);
+ builder.buildSearchHistory();
+}
+
+void LLSearchComboBox::onSearchPrearrange(const LLSD& data)
+{
+ std::string filter = data.asString();
+ rebuildSearchHistory(filter);
+
+ mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
+}
+
+void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor)
+{
+ KEY key = gKeyboard->currentKey();
+
+ if (line_editor->getText().empty())
+ {
+ prearrangeList(); // resets filter
+ hideList();
+ }
+ // Typing? (moving cursor should not affect showing the list)
+ else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
+ {
+ prearrangeList(line_editor->getText());
+ if (mList->getItemCount() != 0)
+ {
+ showList();
+ focusTextEntry();
+ }
+ else
+ {
+ // Hide the list if it's empty.
+ hideList();
+ }
+ }
+ LLComboBox::onTextEntry(line_editor);
+}
+
+void LLSearchComboBox::focusTextEntry()
+{
+ // We can't use "mTextEntry->setFocus(TRUE)" instead because
+ // if the "select_on_focus" parameter is true it places the cursor
+ // at the beginning (after selecting text), thus screwing up updateSelection().
+ if (mTextEntry)
+ {
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+ }
+}
+
+void LLSearchComboBox::hideList()
+{
+ LLComboBox::hideList();
+ if (mTextEntry && hasFocus())
+ focusTextEntry();
+}
+
+LLSearchComboBox::~LLSearchComboBox()
+{
+}
+
+void LLSearchComboBox::onSelectionCommit()
+{
+ std::string search_query = getSimple();
+ LLStringUtil::trim(search_query);
+
+ // Order of add() and mTextEntry->setText does matter because add() will select first item
+ // in drop down list and its label will be copied to text box rewriting mTextEntry->setText() call
+ if(!search_query.empty())
+ {
+ remove(search_query);
+ add(search_query, ADD_TOP);
+ }
+
+ mTextEntry->setText(search_query);
+ setControlValue(search_query);
+}
+
+BOOL LLSearchComboBox::remove(const std::string& name)
+{
+ BOOL found = mList->selectItemByLabel(name, FALSE);
+
+ if (found)
+ {
+ LLScrollListItem* item = mList->getFirstSelected();
+ if (item)
+ {
+ LLComboBox::remove(mList->getItemIndex(item));
+ }
+ }
+
+ return found;
+}
+
+void LLSearchComboBox::clearHistory()
+{
+ removeall();
+ setTextEntry(LLStringUtil::null);
+}
+
+BOOL LLSearchComboBox::handleKeyHere(KEY key,MASK mask )
+{
+ if(mTextEntry->hasFocus() && MASK_NONE == mask && KEY_DOWN == key)
+ {
+ S32 first = 0;
+ S32 size = 0;
+
+ // get entered text (without auto-complete part)
+ mTextEntry->getSelectionRange(&first, &size);
+ std::string search_query = mTextEntry->getText();
+ search_query.erase(first, size);
+
+ onSearchPrearrange(search_query);
+ }
+ return LLComboBox::handleKeyHere(key, mask);
+}
+
+LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter)
+: mComboBox(combo_box)
+, mFilter(filter)
+{
+}
+
+bool LLSearchHistoryBuilder::filterSearchHistory()
+{
+ // *TODO: an STL algorithm would look nicer
+ mFilteredSearchHistory.clear();
+
+ std::string filter_copy = mFilter;
+ LLStringUtil::toLower(filter_copy);
+
+ LLSearchHistory::search_history_list_t history =
+ LLSearchHistory::getInstance()->getSearchHistoryList();
+
+ LLSearchHistory::search_history_list_t::const_iterator it = history.begin();
+ for ( ; it != history.end(); ++it)
+ {
+ std::string search_query = (*it).search_query;
+ LLStringUtil::toLower(search_query);
+
+ if (search_query.find(filter_copy) != std::string::npos)
+ mFilteredSearchHistory.push_back(*it);
+ }
+
+ return mFilteredSearchHistory.size();
+}
+
+void LLSearchHistoryBuilder::buildSearchHistory()
+{
+ mFilteredSearchHistory.clear();
+
+ LLSearchHistory::search_history_list_t filtered_items;
+ LLSearchHistory::search_history_list_t* itemsp = NULL;
+ LLSearchHistory* sh = LLSearchHistory::getInstance();
+
+ if (mFilter.empty())
+ {
+ itemsp = &sh->getSearchHistoryList();
+ }
+ else
+ {
+ filterSearchHistory();
+ itemsp = &mFilteredSearchHistory;
+ itemsp->sort();
+ }
+
+ mComboBox->removeall();
+
+ LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin();
+ for ( ; it != itemsp->end(); it++)
+ {
+ LLSearchHistory::LLSearchHistoryItem item = *it;
+ mComboBox->add(item.search_query);
+ }
+}
diff --git a/indra/newview/llsearchcombobox.h b/indra/newview/llsearchcombobox.h
new file mode 100644
index 0000000000..c23ebc8923
--- /dev/null
+++ b/indra/newview/llsearchcombobox.h
@@ -0,0 +1,110 @@
+/**
+ * @file llsearchcombobox.h
+ * @brief LLSearchComboBox class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSEARCHCOMBOBOX_H
+#define LL_LLSEARCHCOMBOBOX_H
+
+#include "llcombobox.h"
+#include "llsearchhistory.h"
+
+/**
+ * Search control with text box for search queries and a drop down list
+ * with recent queries. Supports text auto-complete and filtering of drop down list
+ * according to typed text.
+ */
+class LLSearchComboBox : public LLComboBox
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLComboBox::Params>
+ {
+ Optional<LLButton::Params> search_button;
+ Optional<bool> dropdown_button_visible;
+
+ Params();
+ };
+
+ /**
+ * Removes an entry from combo box, case insensitive
+ */
+ BOOL remove(const std::string& name);
+
+ /**
+ * Clears search history
+ */
+ void clearHistory();
+
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+
+ ~LLSearchComboBox();
+
+protected:
+
+ LLSearchComboBox(const Params&p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Handles typing in text box
+ */
+ void onTextEntry(LLLineEditor* line_editor);
+
+ /**
+ * Hides drop down list and focuses text box
+ */
+ void hideList();
+
+ /**
+ * Rebuilds search history, case insensitive
+ * If filter is an empty string - whole history will be added to combo box
+ * if filter is valid string - only matching entries will be added
+ */
+ virtual void rebuildSearchHistory(const std::string& filter);
+
+ /**
+ * Callback for prearrange event
+ */
+ void onSearchPrearrange(const LLSD& data);
+
+ /**
+ * Callback for text box or combo box commit
+ */
+ void onSelectionCommit();
+
+ /**
+ * Sets focus to text box
+ */
+ void focusTextEntry();
+
+ LLButton* mSearchButton;
+};
+
+#endif //LL_LLSEARCHCOMBOBOX_H
diff --git a/indra/newview/llsearchhistory.cpp b/indra/newview/llsearchhistory.cpp
new file mode 100644
index 0000000000..d45a1efa0e
--- /dev/null
+++ b/indra/newview/llsearchhistory.cpp
@@ -0,0 +1,154 @@
+/**
+ * @file llsearchhistory.cpp
+ * @brief Search history container implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsearchhistory.h"
+
+#include "llfile.h"
+#include "llsdserialize.h"
+#include "llxmlnode.h"
+
+std::string LLSearchHistory::SEARCH_QUERY = "search_query";
+std::string LLSearchHistory::SEARCH_HISTORY_FILE_NAME = "search_history.txt";
+
+LLSearchHistory::LLSearchHistory()
+{
+
+}
+
+bool LLSearchHistory::load()
+{
+ // build filename for each user
+ std::string resolved_filename = getHistoryFilePath();
+ llifstream file(resolved_filename);
+ if (!file.is_open())
+ {
+ return false;
+ }
+
+ clearHistory();
+
+ // add each line in the file to the list
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ while (std::getline(file, line))
+ {
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ break;
+ }
+
+ mSearchHistory.push_back(s_item);
+ }
+
+ file.close();
+
+ return true;
+}
+
+bool LLSearchHistory::save()
+{
+ // build filename for each user
+ std::string resolved_filename = getHistoryFilePath();
+ // open a file for writing
+ llofstream file (resolved_filename);
+ if (!file.is_open())
+ {
+ return false;
+ }
+
+ search_history_list_t::const_iterator it = mSearchHistory.begin();
+ for (; mSearchHistory.end() != it; ++it)
+ {
+ file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
+ }
+
+ file.close();
+ return true;
+}
+
+std::string LLSearchHistory::getHistoryFilePath()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SEARCH_HISTORY_FILE_NAME);
+}
+
+void LLSearchHistory::addEntry(const std::string& search_query)
+{
+ if(search_query.empty())
+ {
+ return;
+ }
+
+ search_history_list_t::iterator it =
+ find(mSearchHistory.begin(), mSearchHistory.end(), search_query);
+
+ if(mSearchHistory.end() != it)
+ {
+ mSearchHistory.erase(it);
+ }
+
+ LLSearchHistoryItem item(search_query);
+ mSearchHistory.push_front(item);
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator < (const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
+
+ return result < 0;
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator > (const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
+
+ return result > 0;
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator==(const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ return 0 == LLStringUtil::compareInsensitive(search_query, right.search_query);
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator==(const std::string& right)
+{
+ return 0 == LLStringUtil::compareInsensitive(search_query, right);
+}
+
+LLSD LLSearchHistory::LLSearchHistoryItem::toLLSD() const
+{
+ LLSD ret;
+ ret[SEARCH_QUERY] = search_query;
+ return ret;
+}
diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h
new file mode 100644
index 0000000000..253ef21e9e
--- /dev/null
+++ b/indra/newview/llsearchhistory.h
@@ -0,0 +1,138 @@
+/**
+ * @file llsearchhistory.h
+ * @brief Search history container definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSEARCHHISTORY_H
+#define LL_LLSEARCHHISTORY_H
+
+#include "llsingleton.h"
+/**
+ * Search history container able to save and load history from file.
+ * History is stored in chronological order, most recent at the beginning.
+ */
+class LLSearchHistory : public LLSingleton<LLSearchHistory>
+{
+public:
+
+ // Forward declaration
+ class LLSearchHistoryItem;
+
+ // Search history container
+ typedef std::list<LLSearchHistoryItem> search_history_list_t;
+
+ /**
+ * Saves search history to file
+ */
+ bool save();
+
+ /**
+ * loads search history from file
+ */
+ bool load();
+
+ /**
+ * Returns search history list
+ */
+ search_history_list_t& getSearchHistoryList() { return mSearchHistory; }
+
+ /**
+ * Deletes all search history queries from list.
+ */
+ void clearHistory() { mSearchHistory.clear(); }
+
+ /**
+ * Adds unique entry to front of search history list, case insensitive
+ * If entry is already in list, it will be deleted and added to front.
+ */
+ void addEntry(const std::string& search_text);
+
+ LLSearchHistory();
+
+ /**
+ * Class for storing data about single search request.
+ */
+ class LLSearchHistoryItem
+ {
+ public:
+
+ LLSearchHistoryItem()
+ {}
+
+ LLSearchHistoryItem(const std::string& query)
+ : search_query(query)
+ {}
+
+ LLSearchHistoryItem(const LLSD& item)
+ {
+ if(item.has(SEARCH_QUERY))
+ search_query = item[SEARCH_QUERY].asString();
+ }
+
+ std::string search_query;
+
+ /**
+ * Allows std::list sorting
+ */
+ bool operator < (const LLSearchHistory::LLSearchHistoryItem& right);
+
+ /**
+ * Allows std::list sorting
+ */
+ bool operator > (const LLSearchHistory::LLSearchHistoryItem& right);
+
+ bool operator==(const LLSearchHistoryItem& right);
+
+ bool operator==(const std::string& right);
+
+ /**
+ * Serializes search history item to LLSD
+ */
+ LLSD toLLSD() const;
+ };
+
+protected:
+
+ /**
+ * Returns path to search history file.
+ */
+ std::string getHistoryFilePath();
+
+ static std::string SEARCH_HISTORY_FILE_NAME;
+ static std::string SEARCH_QUERY;
+
+private:
+
+ search_history_list_t mSearchHistory;
+};
+
+class LLSearchComboBox;
+
+#endif //LL_LLSEARCHHISTORY_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 32fe996125..b25331e439 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -393,7 +393,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj,
}
// Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
root->addThisAndNonJointChildren(objects);
addAsFamily(objects, add_to_end);
@@ -439,7 +439,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV
BOOL send_to_sim)
{
// Collect all of the objects, children included
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
//clear primary object (no primary object)
mSelectedObjects->mPrimaryObject = NULL;
@@ -563,7 +563,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s
if(!object->isSelected()) return;
// Collect all of the objects, and remove them
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
if (include_entire_object)
{
@@ -779,47 +779,55 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face)
{
- // Always blitz hover list when setting
- mHoverObjects->deleteAllNodes();
-
if (!objectp)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select yourself
if (objectp->mID == gAgentID)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select land
if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
- // Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
objectp = objectp->getRootEdit();
- objectp->addThisAndNonJointChildren(objects);
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
+ // is the requested object the same as the existing hover object root?
+ // NOTE: there is only ever one linked set in mHoverObjects
+ if (mHoverObjects->getFirstRootObject() != objectp)
{
- LLViewerObject* cur_objectp = *iter;
- LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
- nodep->selectTE(face, TRUE);
- mHoverObjects->addNodeAtEnd(nodep);
+ // Collect all of the objects
+ std::vector<LLViewerObject*> objects;
+ objectp = objectp->getRootEdit();
+ objectp->addThisAndNonJointChildren(objects);
+
+ for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
+ iter != objects.end(); ++iter)
+ {
+ LLViewerObject* cur_objectp = *iter;
+ LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
+ nodep->selectTE(face, TRUE);
+ mHoverObjects->addNodeAtEnd(nodep);
+ }
+
+ requestObjectPropertiesFamily(objectp);
}
- requestObjectPropertiesFamily(objectp);
return mHoverObjects;
}
LLSelectNode *LLSelectMgr::getHoverNode()
{
- return getHoverObjects()->getFirstRootNode();
+ return mHoverObjects->getFirstRootNode();
}
void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
@@ -1286,7 +1294,7 @@ void LLSelectMgr::promoteSelectionToRoot()
//-----------------------------------------------------------------------------
void LLSelectMgr::demoteSelectionToIndividuals()
{
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
iter != getSelection()->root_end(); iter++)
@@ -1295,7 +1303,7 @@ void LLSelectMgr::demoteSelectionToIndividuals()
object->addThisAndNonJointChildren(objects);
}
- if (objects.getLength())
+ if (!objects.empty())
{
deselectAll();
for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
@@ -4480,7 +4488,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
return (node->getObject() && node->getObject()->mID == mID);
}
} func(id);
- LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func);
+ LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func);
if (node)
{
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index c41a86e355..08c2783746 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -411,6 +411,7 @@ public:
LLObjectSelectionHandle selectHighlightedObjects();
LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1);
+ LLSelectNode *getHoverNode();
void highlightObjectOnly(LLViewerObject *objectp);
void highlightObjectAndFamily(LLViewerObject *objectp);
@@ -445,14 +446,11 @@ public:
////////////////////////////////////////////////////////////////
// Selection accessors
////////////////////////////////////////////////////////////////
- LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; }
LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
// right now this just renders the selection with root/child colors instead of a single color
LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; }
LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; }
- LLSelectNode *getHoverNode();
-
////////////////////////////////////////////////////////////////
// Grid manipulation
////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index afa8e5f072..381e63f020 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -241,6 +241,13 @@ LLSideTray::LLSideTray(Params& params)
,mMaxBarWidth(params.rect.width)
{
mCollapsed=params.collapsed;
+
+
+ LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+
+ // register handler function to process data from the xml.
+ // panel_name should be specified via "parameter" attribute.
+ commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null));
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 477149194b..1fe7a75be7 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -186,6 +186,7 @@
#include "llagentlanguage.h"
#include "llwearable.h"
#include "llinventorybridge.h"
+#include "llappearancemgr.h"
#include "lllogin.h"
#include "llevents.h"
@@ -2618,10 +2619,10 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
}
else
{
- wear_outfit_by_name(outfit_folder_name);
+ LLAppearanceManager::wearOutfitByName(outfit_folder_name);
}
- wear_outfit_by_name(gestures);
- wear_outfit_by_name(COMMON_GESTURES_FOLDER);
+ LLAppearanceManager::wearOutfitByName(gestures);
+ LLAppearanceManager::wearOutfitByName(COMMON_GESTURES_FOLDER);
// This is really misnamed -- it means we have started loading
// an outfit/shape that will give the avatar a gender eventually. JC
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index c724fb5315..40b8445dcf 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -623,7 +623,7 @@ class LLBalanceHandler : public LLCommandHandler
{
public:
// Requires "trusted" browser/URL source
- LLBalanceHandler() : LLCommandHandler("balance", true) { }
+ LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (tokens.size() == 1
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 2bbb5a2767..98428bf0f7 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -38,31 +38,34 @@
#include "llviewercontrol.h"
#include "llviewerwindow.h"
+#include "llchiclet.h"
//---------------------------------------------------------------------------------
-LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLFloater(LLSD()),
+LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),
mChannel(NULL),
mScrollContainer(NULL),
mNotificationList(NULL)
{
+ LLIMMgr::getInstance()->addSessionObserver(this);
+ LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLSysWellWindow::findIMChiclet, this, _1));
}
//---------------------------------------------------------------------------------
BOOL LLSysWellWindow::postBuild()
{
mScrollContainer = getChild<LLScrollContainer>("notification_list_container");
+ mTwinListPanel = getChild<LLPanel>("twin_list_panel");
mNotificationList = getChild<LLScrollingPanelList>("notification_list");
+ mIMRowList = getChild<LLScrollingPanelList>("im_row_panel_list");
- gViewerWindow->setOnBottomTrayWidthChanged(boost::bind(&LLSysWellWindow::adjustWindowPosition, this)); // *TODO: won't be necessary after docking is realized
mScrollContainer->setBorderVisible(FALSE);
- mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
-
- return TRUE;
+ return LLDockableFloater::postBuild();
}
//---------------------------------------------------------------------------------
LLSysWellWindow::~LLSysWellWindow()
{
+ LLIMMgr::getInstance()->removeSessionObserver(this);
}
//---------------------------------------------------------------------------------
@@ -75,7 +78,6 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p)
LLSysWellItem* new_item = new LLSysWellItem(p);
mNotificationList->addPanel(dynamic_cast<LLScrollingPanel*>(new_item));
reshapeWindow();
- adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1));
new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1));
@@ -120,11 +122,6 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)
return;
reshapeWindow();
- adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
- // hide chiclet window if there are no items left
- S32 items_left = mNotificationList->getPanelList().size();
- if(items_left == 0)
- setVisible(FALSE);
}
//---------------------------------------------------------------------------------
@@ -142,12 +139,23 @@ void LLSysWellWindow::onItemClose(LLSysWellItem* item)
removeItemByID(id);
if(mChannel)
mChannel->killToastByNotificationID(id);
+
+ // hide chiclet window if there are no items left
+ setVisible(!isWindowEmpty());
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::toggleWindow()
{
+ if (getDockControl() == NULL)
+ {
+ setDockControl(new LLDockControl(
+ LLBottomTray::getInstance()->getSysWell(), this,
+ getDockTongue(), LLDockControl::TOP, isDocked()));
+ }
setVisible(!getVisible());
+ //set window in foreground
+ setFocus(getVisible());
}
//---------------------------------------------------------------------------------
@@ -156,58 +164,249 @@ void LLSysWellWindow::setVisible(BOOL visible)
// on Show adjust position of SysWell chiclet's window
if(visible)
{
+ if (LLBottomTray::instanceExists())
+ {
+ LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE);
+ }
if(mChannel)
mChannel->removeAndStoreAllVisibleToasts();
-
- adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
}
-
+ else
+ {
+ if (LLBottomTray::instanceExists())
+ {
+ LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE);
+ }
+ }
if(mChannel)
mChannel->setShowToasts(!visible);
- LLFloater::setVisible(visible);
+ LLDockableFloater::setVisible(visible);
}
//---------------------------------------------------------------------------------
-void LLSysWellWindow::adjustWindowPosition() // *TODO: won't be necessary after docking is realized
-{
- const S32 WINDOW_MARGIN = 5;
-
- LLRect btm_rect = LLBottomTray::getInstance()->getRect();
- LLRect this_rect = getRect();
- setOrigin(btm_rect.mRight - this_rect.getWidth() - WINDOW_MARGIN, WINDOW_MARGIN);
-}
-//---------------------------------------------------------------------------------
void LLSysWellWindow::reshapeWindow()
{
// Get size for scrollbar and floater's header
const LLUICachedControl<S32> SCROLLBAR_SIZE("UIScrollbarSize", 0);
const LLUICachedControl<S32> HEADER_SIZE("UIFloaterHeaderSize", 0);
- // Get item list
- const LLScrollingPanelList::panel_list_t list = mNotificationList->getPanelList();
+ LLRect notif_list_rect = mNotificationList->getRect();
+ LLRect im_list_rect = mIMRowList->getRect();
+ LLRect panel_rect = mTwinListPanel->getRect();
- // Get height for a scrolling panel list
- S32 list_height = mNotificationList->getRect().getHeight();
+ S32 notif_list_height = notif_list_rect.getHeight();
+ S32 im_list_height = im_list_rect.getHeight();
- // Check that the floater doesn't exceed its parent view limits after reshape
- S32 new_height = list_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + HEADER_SIZE;
+ S32 new_panel_height = notif_list_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + im_list_height;
+ S32 new_window_height = new_panel_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + HEADER_SIZE;
- if(new_height > MAX_WINDOW_HEIGHT)
+ U32 twinListWidth = 0;
+
+ if (new_window_height > MAX_WINDOW_HEIGHT)
{
- reshape(MIN_WINDOW_WIDTH, MAX_WINDOW_HEIGHT, FALSE);
- mNotificationList->reshape(MIN_PANELLIST_WIDTH - SCROLLBAR_SIZE, list_height, TRUE);
+ twinListWidth = MIN_PANELLIST_WIDTH - SCROLLBAR_SIZE;
+ new_window_height = MAX_WINDOW_HEIGHT;
}
else
{
- reshape(MIN_WINDOW_WIDTH, new_height, FALSE);
- mNotificationList->reshape(MIN_PANELLIST_WIDTH, list_height, TRUE);
+ twinListWidth = MIN_PANELLIST_WIDTH;
}
-
+
+ reshape(MIN_WINDOW_WIDTH, new_window_height, FALSE);
+ mTwinListPanel->reshape(twinListWidth, new_panel_height, TRUE);
+ mNotificationList->reshape(twinListWidth, notif_list_height, TRUE);
+ mIMRowList->reshape(twinListWidth, im_list_height, TRUE);
+
+ // arrange panel and lists
+ // move panel
+ panel_rect.setLeftTopAndSize(1, new_panel_height, twinListWidth, new_panel_height);
+ mTwinListPanel->setRect(panel_rect);
+ // move notif list panel
+ notif_list_rect.setLeftTopAndSize(notif_list_rect.mLeft, new_panel_height, twinListWidth, notif_list_height);
+ mNotificationList->setRect(notif_list_rect);
+ // move IM list panel
+ im_list_rect.setLeftTopAndSize(im_list_rect.mLeft, notif_list_rect.mBottom - LLScrollingPanelList::GAP_BETWEEN_PANELS, twinListWidth, im_list_height);
+ mIMRowList->setRect(im_list_rect);
+
mNotificationList->updatePanels(TRUE);
+ mIMRowList->updatePanels(TRUE);
+}
+
+//---------------------------------------------------------------------------------
+LLSysWellWindow::RowPanel * LLSysWellWindow::findIMRow(const LLUUID& sessionId)
+{
+ RowPanel * res = NULL;
+ const LLScrollingPanelList::panel_list_t &list = mIMRowList->getPanelList();
+ if (!list.empty())
+ {
+ for (LLScrollingPanelList::panel_list_t::const_iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ RowPanel *panel = static_cast<RowPanel*> (*iter);
+ if (panel->mChiclet->getSessionId() == sessionId)
+ {
+ res = panel;
+ break;
+ }
+ }
+ }
+ return res;
}
//---------------------------------------------------------------------------------
+LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId)
+{
+ LLChiclet* res = NULL;
+ RowPanel* panel = findIMRow(sessionId);
+ if (panel != NULL)
+ {
+ res = panel->mChiclet;
+ }
+ return res;
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
+ const std::string& name, const LLUUID& otherParticipantId)
+{
+ mIMRowList->addPanel(new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId));
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::delIMRow(const LLUUID& sessionId)
+{
+ RowPanel *panel = findIMRow(sessionId);
+ if (panel != NULL)
+ {
+ mIMRowList->removePanel(panel);
+ }
+
+ // hide chiclet window if there are no items left
+ setVisible(!isWindowEmpty());
+}
+
+//---------------------------------------------------------------------------------
+bool LLSysWellWindow::isWindowEmpty()
+{
+ if(mIMRowList->getPanelList().size() == 0 && LLBottomTray::getInstance()->getSysWell()->getCounter() == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+//---------------------------------------------------------------------------------
+//virtual
+void LLSysWellWindow::sessionAdded(const LLUUID& sessionId,
+ const std::string& name, const LLUUID& otherParticipantId)
+{
+ if (findIMRow(sessionId) == NULL)
+ {
+ S32 chicletCounter = 0;
+ LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap,
+ sessionId, (LLIMModel::LLIMSession*) NULL);
+ if (session != NULL)
+ {
+ chicletCounter = session->mNumUnread;
+ }
+ addIMRow(sessionId, chicletCounter, name, otherParticipantId);
+ reshapeWindow();
+ }
+}
+
+//---------------------------------------------------------------------------------
+//virtual
+void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)
+{
+ delIMRow(sessionId);
+ reshapeWindow();
+ LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
+}
+
+//---------------------------------------------------------------------------------
+LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId,
+ S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) :
+ LLScrollingPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL);
+
+ // Choose which of the pre-created chiclets (IM/group) to use.
+ // The other one gets hidden.
+
+ LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId);
+ switch (im_chiclet_type)
+ {
+ case LLIMChiclet::TYPE_GROUP:
+ mChiclet = getChild<LLIMChiclet>("group_chiclet");
+ childSetVisible("p2p_chiclet", false);
+ break;
+ case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway
+ case LLIMChiclet::TYPE_IM:
+ mChiclet = getChild<LLIMChiclet>("p2p_chiclet");
+ childSetVisible("group_chiclet", false);
+ break;
+ }
+
+ // Initialize chiclet.
+ mChiclet->setCounter(chicletCounter);
+ mChiclet->setSessionId(sessionId);
+ mChiclet->setIMSessionName(name);
+ mChiclet->setOtherParticipantId(otherParticipantId);
+
+ LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+ contactName->setValue(name);
+
+ mCloseBtn = getChild<LLButton>("hide_btn");
+ mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClose, this));
+}
+
+//---------------------------------------------------------------------------------
+LLSysWellWindow::RowPanel::~RowPanel()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::RowPanel::onClose()
+{
+ mParent->mIMRowList->removePanel(this);
+ gIMMgr->removeSession(mChiclet->getSessionId());
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));
+}
+
+//---------------------------------------------------------------------------------
+// virtual
+BOOL LLSysWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // Pass the mouse down event to the chiclet (EXT-596).
+ if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown()
+ mChiclet->onMouseDown();
+
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::RowPanel::updatePanel(BOOL allow_modify)
+{
+ S32 parent_width = getParent()->getRect().getWidth();
+ S32 panel_height = getRect().getHeight();
+
+ reshape(parent_width, panel_height, TRUE);
+}
+
+//---------------------------------------------------------------------------------
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 7a107af0d1..d76147b489 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -35,22 +35,27 @@
#include "llsyswellitem.h"
-#include "llfloater.h"
+#include "lldockablefloater.h"
#include "llbutton.h"
#include "llscreenchannel.h"
#include "llscrollcontainer.h"
+#include "llchiclet.h"
+#include "llimview.h"
#include "boost/shared_ptr.hpp"
-class LLSysWellWindow : public LLFloater
+class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver
{
public:
LLSysWellWindow(const LLSD& key);
~LLSysWellWindow();
BOOL postBuild();
+ // other interface functions
+ bool isWindowEmpty();
+
// change attributes
void setChannel(LLNotificationsUI::LLScreenChannel* channel) {mChannel = channel;}
@@ -64,6 +69,7 @@ public:
virtual void setVisible(BOOL visible);
void adjustWindowPosition();
void toggleWindow();
+ /*virtua*/BOOL canClose() { return FALSE; }
// Handlers
void onItemClick(LLSysWellItem* item);
@@ -75,15 +81,46 @@ public:
static const S32 MIN_PANELLIST_WIDTH = 318;
private:
-
+ class RowPanel;
void reshapeWindow();
+ RowPanel * findIMRow(const LLUUID& sessionId);
+ LLChiclet * findIMChiclet(const LLUUID& sessionId);
+ void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId);
+ void delIMRow(const LLUUID& sessionId);
+ // LLIMSessionObserver observe triggers
+ virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
+ virtual void sessionRemoved(const LLUUID& session_id);
// pointer to a corresponding channel's instance
LLNotificationsUI::LLScreenChannel* mChannel;
-
- LLUIImagePtr mDockTongue;
+ LLPanel* mTwinListPanel;
LLScrollContainer* mScrollContainer;
+ LLScrollingPanelList* mIMRowList;
LLScrollingPanelList* mNotificationList;
+
+private:
+ /**
+ * Scrolling row panel.
+ */
+ class RowPanel: public LLScrollingPanel
+ {
+ public:
+ RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter,
+ const std::string& name, const LLUUID& otherParticipantId);
+ virtual ~RowPanel();
+ /*virtual*/
+ void updatePanel(BOOL allow_modify);
+ void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
+ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ private:
+ void onClose();
+ public:
+ LLIMChiclet* mChiclet;
+ private:
+ LLButton* mCloseBtn;
+ const LLSysWellWindow* mParent;
+ };
};
#endif // LL_LLSYSWELLWINDOW_H
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index b31edf1e5d..0bb5a727e0 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -37,8 +37,11 @@
#include "llsd.h"
#include "llsdserialize.h"
#include "lldir.h"
+#include "llteleporthistory.h"
+#include "llagent.h"
-static LLTeleportHistoryStorage tpstorage;
+// Max offset for two global positions to consider them as equal
+const F64 MAX_GLOBAL_POS_OFFSET = 5.0f;
LLTeleportHistoryPersistentItem::LLTeleportHistoryPersistentItem(const LLSD& val)
{
@@ -58,15 +61,42 @@ LLSD LLTeleportHistoryPersistentItem::toLLSD() const
return val;
}
+struct LLSortItemsByDate
+{
+ bool operator()(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
+ {
+ return a.mDate < b.mDate;
+ }
+};
+
LLTeleportHistoryStorage::LLTeleportHistoryStorage() :
mFilename("teleport_history.txt")
{
+ LLTeleportHistory *th = LLTeleportHistory::getInstance();
+ if (th)
+ th->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryStorage::onTeleportHistoryChange, this));
+
+ load();
}
LLTeleportHistoryStorage::~LLTeleportHistoryStorage()
{
}
+void LLTeleportHistoryStorage::onTeleportHistoryChange()
+{
+ LLTeleportHistory *th = LLTeleportHistory::getInstance();
+ if (!th)
+ return;
+
+ const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()];
+
+ addItem(item.mTitle, item.mGlobalPos);
+ save();
+
+ mHistoryChangedSignal();
+}
+
void LLTeleportHistoryStorage::purgeItems()
{
mItems.clear();
@@ -74,12 +104,45 @@ void LLTeleportHistoryStorage::purgeItems()
void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos)
{
- mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos));
+ addItem(title, global_pos, LLDate::now());
+}
+
+
+bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
+{
+ return a.mTitle == b.mTitle && (a.mGlobalPos - b.mGlobalPos).length() < MAX_GLOBAL_POS_OFFSET;
}
void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date)
{
- mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos, date));
+
+ LLTeleportHistoryPersistentItem item(title, global_pos, date);
+
+ slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
+ boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item));
+
+ // If there is such item already, remove it, since new item is more recent
+ if (item_iter != mItems.end())
+ {
+ mItems.erase(item_iter);
+ }
+
+ mItems.push_back(item);
+
+ // Check whether sorting is needed
+ if (mItems.size() > 1)
+ {
+ item_iter = mItems.end();
+
+ item_iter--;
+ item_iter--;
+
+ // If second to last item is more recent than last, then resort items
+ if (item_iter->mDate > item.mDate)
+ {
+ std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
+ }
+ }
}
void LLTeleportHistoryStorage::removeItem(S32 idx)
@@ -145,6 +208,8 @@ void LLTeleportHistoryStorage::load()
}
file.close();
+
+ std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
}
void LLTeleportHistoryStorage::dump() const
@@ -162,3 +227,30 @@ void LLTeleportHistoryStorage::dump() const
}
}
+boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(history_callback_t cb)
+{
+ return mHistoryChangedSignal.connect(cb);
+}
+
+void LLTeleportHistoryStorage::goToItem(S32 idx)
+
+{
+ // Validate specified index.
+ if (idx < 0 || idx >= (S32)mItems.size())
+ {
+ llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl;
+ dump();
+ return;
+ }
+
+ if (idx == (S32)mItems.size() - 1)
+ {
+ llwarns << "Will not teleport to the same location." << llendl;
+ dump();
+ return;
+ }
+
+ // Attempt to teleport to the requested item.
+ gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
+}
+
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
index fa836c0326..f67c4e2fb9 100644
--- a/indra/newview/llteleporthistorystorage.h
+++ b/indra/newview/llteleporthistorystorage.h
@@ -78,7 +78,10 @@ class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>
public:
- typedef std::vector<LLTeleportHistoryPersistentItem> item_list_list_t;
+ typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t;
+
+ typedef boost::function<void()> history_callback_t;
+ typedef boost::signals2::signal<void()> history_signal_t;
LLTeleportHistoryStorage();
~LLTeleportHistoryStorage();
@@ -86,7 +89,7 @@ public:
/**
* @return history items.
*/
- const item_list_list_t& getItems() const { return mItems; }
+ const slurl_list_t& getItems() const { return mItems; }
void purgeItems();
void addItem(const std::string title, const LLVector3d& global_pos);
@@ -99,10 +102,34 @@ public:
void dump() const;
+ /**
+ * Set a callback to be called upon history changes.
+ *
+ * Multiple callbacks can be set.
+ */
+ boost::signals2::connection setHistoryChangedCallback(history_callback_t cb);
+
+ /**
+ * Go to specific item in the history.
+ *
+ * The item is specified by its index (starting from 0).
+ */
+ void goToItem(S32 idx);
+
private:
- item_list_list_t mItems;
- std::string mFilename;
+ void onTeleportHistoryChange();
+ bool compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b);
+
+ slurl_list_t mItems;
+ std::string mFilename;
+
+ /**
+ * Signal emitted when the history gets changed.
+ *
+ * Invokes callbacks set with setHistoryChangedCallback().
+ */
+ history_signal_t mHistoryChangedSignal;
};
#endif //LL_LLTELEPORTHISTORYSTORAGE_H
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 70a8ab9f61..9da2446354 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -43,7 +43,7 @@
#include "llimageworker.h"
#include "llrender.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llselectmgr.h"
#include "lltexlayer.h"
#include "lltexturecache.h"
@@ -662,16 +662,20 @@ void LLTextureView::draw()
#if 1
if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard))
{
- LLViewerObject *objectp = gHoverView->getLastHoverObject();
- if (objectp)
+ LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode();
+ if (hover_node)
{
- S32 tex_count = objectp->getNumTEs();
- for (S32 i = 0; i < tex_count; i++)
+ LLViewerObject *objectp = hover_node->getObject();
+ if (objectp)
{
- if (imagep == objectp->getTEImage(i))
+ S32 tex_count = objectp->getNumTEs();
+ for (S32 i = 0; i < tex_count; i++)
{
- pri += 2*HIGH_PRIORITY;
- break;
+ if (imagep == objectp->getTEImage(i))
+ {
+ pri += 2*HIGH_PRIORITY;
+ break;
+ }
}
}
}
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index 85814a98c9..fb7574d68b 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -84,11 +84,7 @@ LLToast::LLToast(LLToast::Params p) : LLFloater(LLSD()),
//--------------------------------------------------------------------------
BOOL LLToast::postBuild()
{
- if(mCanFade)
- {
- mTimer.start();
- }
- else
+ if(!mCanFade)
{
mTimer.stop();
}
@@ -209,6 +205,10 @@ void LLToast::setVisible(BOOL show)
if(show)
{
setBackgroundOpaque(TRUE);
+ if(!mTimer.getStarted())
+ {
+ mTimer.start();
+ }
}
LLPanel::setVisible(show);
if(mPanel)
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 969f3fd1cb..05e63a60c5 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -70,12 +70,16 @@ public:
bool enable_hide_btn;
bool is_modal;
bool is_tip;
+ bool force_show;
+ bool force_store;
Params() : can_fade(true),
can_be_stored(true),
is_modal(false),
is_tip(false),
enable_hide_btn(true),
+ force_show(false),
+ force_store(false),
panel(NULL),
timer_period(gSavedSettings.getS32("NotificationToastTime"))
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 6f26b4077c..6f373a74bd 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -40,7 +40,7 @@
#include "lliconctrl.h"
#include "llnotify.h"
#include "lltextbox.h"
-#include "lltexteditor.h"
+
#include "lluiconstants.h"
#include "llui.h"
#include "llviewercontrol.h"
@@ -53,6 +53,8 @@
#include "llfloaterinventory.h"
#include "llinventorytype.h"
+const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 4;
+
LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification)
: LLToastPanel(notification),
mInventoryOffer(NULL)
@@ -65,8 +67,6 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
}
- static const LLUIColor textColor = LLUIColorTable::instance().getColor("GroupNotifyTextColor");
-
//group icon
LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE);
pGroupIcon->setValue(groupData.mInsigniaID);
@@ -78,23 +78,16 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLTextBox* pTitleText = getChild<LLTextBox>("title");
pTitleText->setValue(from.str());
- //message body
+ //message subject
const std::string& subject = payload["subject"].asString();
+ //message body
const std::string& message = payload["message"].asString();
- LLTextEditor* pMessageText = getChild<LLTextEditor>("message");
- pMessageText->setValue("");
- pMessageText->setEnabled(FALSE);
- LLStyle::Params date_style;
- date_style.color = textColor;
- date_style.font.name = "SANSSERIF";
-
- LLStyle::Params header_style_params;
- header_style_params.color = textColor;
- header_style_params.font = LLFontGL::getFontSansSerifBig();
- pMessageText->appendStyledText(subject + "\n",false,false,header_style_params);
+ LLTextBox* pSubjectText = getChild<LLTextBox>("subject");
+ pSubjectText->setValue(subject);
+ LLTextBox* pDateTimeText = getChild<LLTextBox>("datetime");
std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],["
+LLTrans::getString("UTCTimeDay")+"] ["
+LLTrans::getString("UTCTimeMth")+"] ["
@@ -108,25 +101,38 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLSD substitution;
substitution["datetime"] = (S32) notice_date.secondsSinceEpoch();
LLStringUtil::format(timeStr, substitution);
- LLStyle::Params date_style_params;
- date_style_params.color = textColor;
- date_style_params.font = LLFontGL::getFontMonospace();
- pMessageText->appendStyledText(timeStr, false, false, date_style);
- pMessageText->appendColoredText(std::string("\n\n") + message, false,
- false, textColor);
+ pDateTimeText->setValue(timeStr);
+
+ LLTextBox* pMessageText = getChild<LLTextBox>("message");
+
+ //If message is empty let it be invisible and not take place at the panel
+ if(message.size() != 0)
+ {
+ pMessageText->setVisible(TRUE);
+ pMessageText->setValue(message);
+ }
+ else
+ {
+ pMessageText->setVisible(FALSE);
+ }
//attachment
BOOL hasInventory = payload["inventory_offer"].isDefined();
+
+ //attachment text
LLTextBox * pAttachLink = getChild<LLTextBox>("attachment");
+ //attachment icon
+ LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE);
+
+ //If attachment is empty let it be invisible and not take place at the panel
pAttachLink->setVisible(hasInventory);
+ pAttachIcon->setVisible(hasInventory);
if (hasInventory) {
pAttachLink->setValue(payload["inventory_name"]);
mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]);
childSetActionTextbox("attachment", boost::bind(
&LLToastGroupNotifyPanel::onClickAttachment, this));
- //attachment icon
- LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE);
LLUIImagePtr attachIconImg = get_item_icon(mInventoryOffer->mType,
LLInventoryType::IT_TEXTURE,
0, FALSE);
@@ -137,8 +143,15 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLButton* pOkBtn = getChild<LLButton>("btn_ok");
pOkBtn->setClickedCallback((boost::bind(&LLToastGroupNotifyPanel::onClickOk, this)));
setDefaultBtn(pOkBtn);
-}
+ S32 maxLinesCount;
+ std::istringstream ss( getString("message_max_lines_count") );
+ if (!(ss >> maxLinesCount))
+ {
+ maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+ }
+ snapToMessageHeight(pMessageText, maxLinesCount);
+}
// virtual
LLToastGroupNotifyPanel::~LLToastGroupNotifyPanel()
diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h
index ba98531251..e3d0ef45cb 100644
--- a/indra/newview/lltoastgroupnotifypanel.h
+++ b/indra/newview/lltoastgroupnotifypanel.h
@@ -68,6 +68,8 @@ protected:
private:
static bool isAttachmentOpenable(LLAssetType::EType);
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+
LLButton* mSaveInventoryBtn;
LLUUID mGroupID;
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index e41181c9e1..d401943020 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -34,9 +34,7 @@
#include "lltoastimpanel.h"
#include "llimpanel.h"
-const S32 LLToastIMPanel::MAX_MESSAGE_HEIGHT = 50;
-const S32 LLToastIMPanel::CAPTION_HEIGHT = 30;
-const S32 LLToastIMPanel::TOP_PAD = 5;
+const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
//--------------------------------------------------------------------------
LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification),
@@ -57,10 +55,29 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mUserName->setValue(p.from);
mTime->setValue(p.time);
mSessionID = p.session_id;
+ mNotification = p.notification;
- mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this));
+ // if message comes from the system - there shouldn't be a reply btn
+ if(p.from == "Second Life")
+ {
+ mReplyBtn->setVisible(FALSE);
+ S32 btn_height = mReplyBtn->getRect().getHeight();
+ LLRect msg_rect = mMessage->getRect();
+ msg_rect.setLeftTopAndSize(msg_rect.mLeft, msg_rect.mTop, msg_rect.getWidth(), msg_rect.getHeight() + btn_height);
+ mMessage->setRect(msg_rect);
+ }
+ else
+ {
+ mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this));
+ }
- snapToMessageHeight();
+ S32 maxLinesCount;
+ std::istringstream ss( getString("message_max_lines_count") );
+ if (!(ss >> maxLinesCount))
+ {
+ maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+ }
+ snapToMessageHeight(mMessage, maxLinesCount);
}
//--------------------------------------------------------------------------
@@ -69,25 +86,11 @@ LLToastIMPanel::~LLToastIMPanel()
}
//--------------------------------------------------------------------------
-void LLToastIMPanel::snapToMessageHeight()
-{
- S32 required_text_height = mMessage->getTextPixelHeight();
- S32 text_height = llmin(required_text_height, MAX_MESSAGE_HEIGHT);
- LLRect text_rect = mMessage->getRect();
- LLRect btn_rect = mReplyBtn->getRect();
-
-
- mMessage->reshape( text_rect.getWidth(), text_height, TRUE);
- mMessage->setValue(mMessage->getText());
-
- S32 panel_height = CAPTION_HEIGHT + text_height + btn_rect.getHeight() + TOP_PAD*5;
- reshape( getRect().getWidth(), panel_height, TRUE);
-}
-
-//--------------------------------------------------------------------------
void LLToastIMPanel::onClickReplyBtn()
{
- LLIMFloater::toggle(mSessionID);
+ LLSD response = mNotification->getResponseTemplate();
+ response["respondbutton"] = true;
+ mNotification->respond(response);
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
index 7f5d6eca1d..b51ce23364 100644
--- a/indra/newview/lltoastimpanel.h
+++ b/indra/newview/lltoastimpanel.h
@@ -59,13 +59,11 @@ public:
virtual ~LLToastIMPanel();
private:
- static const S32 MAX_MESSAGE_HEIGHT;
- static const S32 CAPTION_HEIGHT;
- static const S32 TOP_PAD;
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
void onClickReplyBtn();
- void snapToMessageHeight();
+ LLNotificationPtr mNotification;
LLUUID mSessionID;
LLAvatarIconCtrl* mAvatar;
LLTextBox* mUserName;
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 28052a33be..e884d89ce4 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -49,5 +49,36 @@ std::string LLToastPanel::getTitle()
return mNotification->getMessage();
}
+//snap to the message height if it is visible
+void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
+{
+ //Add message height if it is visible
+ if (message->getVisible())
+ {
+ S32 heightDelta = 0;
+ S32 maxTextHeight = (S32)(message->getFont()->getLineHeight() * maxLineCount);
+
+ LLRect messageRect = message->getRect();
+ S32 oldTextHeight = messageRect.getHeight();
+
+ //Reshape the toast to give the message max height.
+ //This needed to calculate lines count according to specified text
+ heightDelta = maxTextHeight - oldTextHeight;
+ reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
+ message->setValue(message->getText());
+
+ //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height
+ //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape.
+ S32 requiredTextHeight = message->getTextPixelHeight();
+ S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
+ //Calculate last delta height deducting previous heightDelta
+ heightDelta = newTextHeight - oldTextHeight - heightDelta;
+
+ //reshape the panel with new height
+ reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
+ message->setValue(message->getText());
+ }
+
+}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 2258eca273..bc9888f4b4 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -34,6 +34,7 @@
#define LL_LLTOASTPANEL_H
#include "llpanel.h"
+#include "lltextbox.h"
#include "llnotifications.h"
#include <string>
@@ -53,6 +54,7 @@ public:
virtual const LLUUID& getID() { return mNotification->id();}
protected:
LLNotificationPtr mNotification;
+ void snapToMessageHeight(LLTextBox* message, S32 maxLineCount);
};
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 7b058e9efa..ceb1358d1c 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -65,6 +65,20 @@ LLTool::~LLTool()
}
}
+BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+{
+ // 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
+ if (down)
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+
+ return LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+}
+
+
BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (gDebugClicks)
@@ -139,7 +153,7 @@ BOOL LLTool::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
// by default, didn't handle it
// llinfos << "LLTool::handleToolTip" << llendl;
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index f954a8c243..bef4a2e1fd 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -55,6 +55,7 @@ public:
virtual BOOL isView() const { return FALSE; }
// Virtual functions inherited from LLMouseHandler
+ virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
@@ -65,9 +66,7 @@ public:
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
-
- virtual EShowToolTip getShowToolTip() { return SHOW_ALWAYS; }; // tools should permit tips even when the mouse is down, as that's pretty normal for tools
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
// Return FALSE to allow context menu to be shown.
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const
diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
index 5478e0005a..c7c9f07504 100644
--- a/indra/newview/lltoolbar.cpp
+++ b/indra/newview/lltoolbar.cpp
@@ -60,6 +60,7 @@
#include "llui.h"
#include "llviewermenu.h"
#include "llfirstuse.h"
+#include "llpanelblockedlist.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
@@ -69,7 +70,6 @@
#include "lltoolgrab.h"
#include "llcombobox.h"
#include "llfloaterchat.h"
-#include "llfloatermute.h"
#include "llimpanel.h"
#include "lllayoutstack.h"
@@ -250,41 +250,6 @@ void LLToolBar::refresh()
BOOL mouselook = gAgent.cameraMouselook();
setVisible(show && !mouselook);
- BOOL sitting = FALSE;
- if (gAgent.getAvatarObject())
- {
- sitting = gAgent.getAvatarObject()->isSitting();
- }
-
- if (!gAgent.canFly())
- {
- gSavedSettings.setBOOL("FlyBtnEnabled", gAgent.getFlying() ? true : false);
- gSavedSettings.setBOOL("FlyBtnState", false);
- }
- else
- {
- gSavedSettings.setBOOL("FlyBtnEnabled", sitting ? false : true);
- }
-
- // Check to see if we're in build mode
- bool build_enabled = LLToolMgr::getInstance()->canEdit();
- if (build_enabled)
- {
- gSavedSettings.setBOOL("BuildBtnEnabled", true);
- bool build_mode = LLToolMgr::getInstance()->inEdit();
- // HACK: Not in mouselook and not just clicking on a scripted object
- if (gAgent.cameraMouselook() || LLToolGrab::getInstance()->getHideBuildHighlight())
- {
- build_mode = FALSE;
- }
- gSavedSettings.setBOOL("BuildBtnState", build_mode);
- }
- else
- {
- gSavedSettings.setBOOL("BuildBtnEnabled", false);
- gSavedSettings.setBOOL("BuildBtnState", false);
- }
-
if (isInVisibleChain())
{
updateCommunicateList();
@@ -332,11 +297,8 @@ void LLToolBar::updateCommunicateList()
communicate_button->addSeparator(ADD_TOP);
communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP);
communicate_button->addSeparator(ADD_TOP);
- LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute");
- if(mute_instance)
- {
- communicate_button->add(mute_instance->getShortTitle(), LLSD("mute list"), ADD_TOP);
- }
+ communicate_button->add(getString("Blocked List"), LLSD("mute list"), ADD_TOP);
+
std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
if (gIMMgr->getIMFloaterHandles().size() > 0)
@@ -414,7 +376,7 @@ void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, const LLSD& user_data)
}
else if (selected_option.asString() == "mute list")
{
- LLFloaterReg::showInstance("mute");
+ LLPanelBlockedList::showPanelAndSelect(LLUUID::null);
}
else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle
{
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index c58457d599..08040cfaa5 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -56,6 +56,7 @@
#include "llpreviewnotecard.h"
#include "llselectmgr.h"
#include "lltoolmgr.h"
+#include "lltooltip.h"
#include "lltrans.h"
#include "llui.h"
#include "llviewertexturelist.h"
@@ -72,6 +73,7 @@
#include "llimview.h"
#include "llrootview.h"
#include "llagentui.h"
+#include "llappearancemgr.h"
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
@@ -758,12 +760,13 @@ BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
return FALSE;
}
-BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen)
+BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
if (!mToolTipMsg.empty())
{
- msg = mToolTipMsg;
- //*sticky_rect_screen = gViewerWindow->getWindowRect();
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(mToolTipMsg)
+ .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
return TRUE;
}
return FALSE;
@@ -2506,7 +2509,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
if(drop)
{
BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
- wear_inventory_category(category, false, append);
+ LLAppearanceManager::wearInventoryCategory(category, false, append);
}
return ACCEPT_YES_MULTI;
}
@@ -2514,7 +2517,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
{
if(drop)
{
- wear_inventory_category(category, true, false);
+ LLAppearanceManager::wearInventoryCategory(category, true, false);
}
return ACCEPT_YES_MULTI;
}
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index f9e5bec143..c9fef26b58 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -57,7 +57,7 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleKey(KEY key, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
virtual void onMouseCaptureLost();
virtual void handleDeselect();
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index 297cf2c667..9400840bdf 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -45,7 +45,7 @@
#include "llbutton.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudmanager.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
@@ -287,12 +287,12 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL success = LLViewerCamera::getInstance()->projectPosAgentToScreen(focus_pos, mouse_pos);
if (success)
{
- LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
+ LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY);
}
}
else if (mMouseSteering)
{
- LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
+ LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY);
}
else
{
@@ -302,7 +302,7 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask)
else
{
// not a valid zoomable object
- LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
+ LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY);
}
// calls releaseMouse() internally
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index abadd251c1..b7a97562bd 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -134,7 +134,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
if (!gAgent.leftButtonGrabbed())
{
// can grab transparent objects (how touch event propagates, scripters rely on this)
- gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE);
+ gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE);
}
return TRUE;
}
@@ -996,7 +996,7 @@ void LLToolGrab::onMouseCaptureLost()
// ...move cursor "naturally", as if it had moved when hidden
S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX;
S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY;
- LLUI::setCursorPositionScreen(x, y);
+ LLUI::setMousePositionScreen(x, y);
}
else if (mHasMoved)
{
@@ -1006,13 +1006,13 @@ void LLToolGrab::onMouseCaptureLost()
LLCoordGL gl_point;
if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point))
{
- LLUI::setCursorPositionScreen(gl_point.mX, gl_point.mY);
+ LLUI::setMousePositionScreen(gl_point.mX, gl_point.mY);
}
}
else
{
// ...move cursor back to click position
- LLUI::setCursorPositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
+ LLUI::setMousePositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
}
gViewerWindow->showCursor();
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index d52e0b4b80..ded83debad 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -317,7 +317,6 @@ bool LLToolMgr::inBuildMode()
// cameraMouselook() actually starts returning true. Also, appearance edit
// sets build mode to true, so let's exclude that.
bool b=(inEdit()
- && gSavedSettings.getBOOL("BuildBtnState")
&& !gAgent.cameraMouselook()
&& mCurrentToolset != gFaceEditToolset);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 235d4acf9d..d6297c30c7 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -45,7 +45,7 @@
#include "llfloaterland.h"
#include "llfloaterreg.h"
#include "llfloaterscriptdebug.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llmenugl.h"
@@ -55,6 +55,7 @@
#include "lltoolgrab.h"
#include "lltoolmgr.h"
#include "lltoolselect.h"
+#include "lltrans.h"
#include "llviewercamera.h"
#include "llviewerparcelmedia.h"
#include "llviewermenu.h"
@@ -68,6 +69,7 @@
#include "llworld.h"
#include "llui.h"
#include "llweb.h"
+#include "llinspectavatar.h"
extern void handle_buy(void*);
@@ -91,7 +93,7 @@ LLToolPie::LLToolPie()
BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
{
//left mouse down always picks transparent
- gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE);
+ gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE);
mGrabMouseButtonDown = TRUE;
return TRUE;
}
@@ -108,7 +110,7 @@ void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info)
BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
// don't pick transparent so users can't "pay" transparent objects
- gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE);
+ gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE);
// claim not handled so UI focus stays same
return FALSE;
}
@@ -463,31 +465,13 @@ void LLToolPie::selectionPropertiesReceived()
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
{
- /*
- // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag
- // gets started.
- const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() );
- const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
- const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
- // ...normal modes can only yaw
- if (x < ROTATE_H_MARGIN)
- {
- gAgent.yaw(rotate_angle);
- mMouseOutsideSlop = TRUE;
- }
- else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
- {
- gAgent.yaw(-rotate_angle);
- mMouseOutsideSlop = TRUE;
- }
- */
+ mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
// FIXME: This was in the pluginapi branch, but I don't think it's correct.
// gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
- LLViewerObject *object = NULL;
LLViewerObject *parent = NULL;
- object = gViewerWindow->getHoverPick().getObject();
+ LLViewerObject *object = mHoverPick.getObject();
if (object)
{
@@ -500,7 +484,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
gViewerWindow->setCursor(cursor);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
- else if (handle_media_hover(gViewerWindow->getHoverPick()))
+ else if (handle_media_hover(mHoverPick))
{
// cursor set by media object
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
@@ -553,7 +537,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
// same object anymore.
gViewerWindow->setCursor(UI_CURSOR_ARROW);
// Make sure the hover-picked object is ignored.
- gHoverView->resetLastHoverObject();
+ //gToolTipView->resetLastHoverObject();
break;
default:
break;
@@ -584,41 +568,439 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
else if (mPick.mObjectID.notNull()
&& !mPick.mPosGlobal.isExactlyZero())
{
- // Hit an object
- // HACK: Call the last hit position the point we hit on the object
- //gLastHitPosGlobal += gLastHitObjectOffset;
handle_go_to();
return TRUE;
}
}
return FALSE;
+}
- /* JC - don't do go-there, because then double-clicking on physical
- objects gets you into trouble.
+//FIXME - RN: get this in LLToolSelectLand too or share some other way?
+const char* DEFAULT_DESC = "(No Description)";
- // If double-click on object or land, go there.
- LLViewerObject *object = gViewerWindow->getLastPick().getObject();
- if (object)
+BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect& sticky_rect_screen)
+{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
+ if (!mHoverPick.isValid()) return TRUE;
+
+ LLViewerObject* hover_object = mHoverPick.getObject();
+
+ // update hover object and hover parcel
+ LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace);
+
+ if (mHoverPick.mPickType == LLPickInfo::PICK_LAND)
+ {
+ LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal );
+ }
+
+ std::string tooltip_msg;
+ std::string line;
+
+ if ( hover_object )
{
- if (object->isAvatar())
+ if ( hover_object->isHUDAttachment() )
{
- LLFloaterAvatarInfo::showFromAvatar(object->getID());
+ // no hover tips for HUD elements, since they can obscure
+ // what the HUD is displaying
+ return TRUE;
+ }
+
+ if ( hover_object->isAttachment() )
+ {
+ // get root of attachment then parent, which is avatar
+ LLViewerObject* root_edit = hover_object->getRootEdit();
+ if (!root_edit)
+ {
+ // Strange parenting issue, don't show any text
+ return TRUE;
+ }
+ hover_object = (LLViewerObject*)root_edit->getParent();
+ if (!hover_object)
+ {
+ // another strange parenting issue, bail out
+ return TRUE;
+ }
+ }
+
+ line.clear();
+ if (hover_object->isAvatar())
+ {
+ // only show tooltip if inspector not already open
+ if (!LLFloaterReg::instanceVisible("inspect_avatar"))
+ {
+ std::string avatar_name;
+ LLNameValue* firstname = hover_object->getNVPair("FirstName");
+ LLNameValue* lastname = hover_object->getNVPair("LastName");
+ if (firstname && lastname)
+ {
+ avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
+ }
+ else
+ {
+ avatar_name = LLTrans::getString("TooltipPerson");
+ }
+ LLToolTipParams params;
+ params.message(avatar_name);
+ params.image.name("Info");
+ params.sticky_rect(gViewerWindow->getVirtualWorldViewRect());
+ params.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
+ LLToolTipMgr::instance().show(params);
+ }
}
else
{
- handle_go_to(NULL);
+ //
+ // We have hit a regular object (not an avatar or attachment)
+ //
+
+ //
+ // Default prefs will suppress display unless the object is interactive
+ //
+ BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip");
+
+ LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
+ if (nodep)
+ {
+ line.clear();
+ if (nodep->mName.empty())
+ {
+ line.append(LLTrans::getString("TooltipNoName"));
+ }
+ else
+ {
+ line.append( nodep->mName );
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ if (!nodep->mDescription.empty()
+ && nodep->mDescription != DEFAULT_DESC)
+ {
+ tooltip_msg.append( nodep->mDescription );
+ tooltip_msg.push_back('\n');
+ }
+
+ // Line: "Owner: James Linden"
+ line.clear();
+ line.append(LLTrans::getString("TooltipOwner") + " ");
+
+ if (nodep->mValid)
+ {
+ LLUUID owner;
+ std::string name;
+ if (!nodep->mPermissions->isGroupOwned())
+ {
+ owner = nodep->mPermissions->getOwner();
+ if (LLUUID::null == owner)
+ {
+ line.append(LLTrans::getString("TooltipPublic"));
+ }
+ else if(gCacheName->getFullName(owner, name))
+ {
+ line.append(name);
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ else
+ {
+ std::string name;
+ owner = nodep->mPermissions->getGroup();
+ if (gCacheName->getGroupName(owner, name))
+ {
+ line.append(name);
+ line.append(LLTrans::getString("TooltipIsGroup"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ // Build a line describing any special properties of this object.
+ LLViewerObject *object = hover_object;
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+
+ if (object &&
+ (object->usePhysics() ||
+ object->flagScripted() ||
+ object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ||
+ object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ||
+ object->flagAllowInventoryAdd() ||
+ object->flagTemporary() ||
+ object->flagPhantom()) )
+ {
+ line.clear();
+ if (object->flagScripted())
+ {
+ line.append(LLTrans::getString("TooltipFlagScript") + " ");
+ }
+
+ if (object->usePhysics())
+ {
+ line.append(LLTrans::getString("TooltipFlagPhysics") + " ");
+ }
+
+ if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) )
+ {
+ line.append(LLTrans::getString("TooltipFlagTouch") + " ");
+ suppressObjectHoverDisplay = FALSE; // Show tip
+ }
+
+ if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) )
+ {
+ line.append(LLTrans::getString("TooltipFlagL$") + " ");
+ suppressObjectHoverDisplay = FALSE; // Show tip
+ }
+
+ if (object->flagAllowInventoryAdd())
+ {
+ line.append(LLTrans::getString("TooltipFlagDropInventory") + " ");
+ suppressObjectHoverDisplay = FALSE; // Show tip
+ }
+
+ if (object->flagPhantom())
+ {
+ line.append(LLTrans::getString("TooltipFlagPhantom") + " ");
+ }
+
+ if (object->flagTemporary())
+ {
+ line.append(LLTrans::getString("TooltipFlagTemporary") + " ");
+ }
+
+ if (object->usePhysics() ||
+ object->flagHandleTouch() ||
+ (parent && parent->flagHandleTouch()) )
+ {
+ line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " ");
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+ }
+
+ // Free to copy / For Sale: L$
+ line.clear();
+ if (nodep->mValid)
+ {
+ BOOL for_copy = nodep->mPermissions->getMaskEveryone() & PERM_COPY && object->permCopy();
+ BOOL for_sale = nodep->mSaleInfo.isForSale() &&
+ nodep->mPermissions->getMaskOwner() & PERM_TRANSFER &&
+ (nodep->mPermissions->getMaskOwner() & PERM_COPY ||
+ nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
+ if (for_copy)
+ {
+ line.append(LLTrans::getString("TooltipFreeToCopy"));
+ suppressObjectHoverDisplay = FALSE; // Show tip
+ }
+ else if (for_sale)
+ {
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice());
+ line.append(LLTrans::getString("TooltipForSaleL$", args));
+ suppressObjectHoverDisplay = FALSE; // Show tip
+ }
+ else
+ {
+ // Nothing if not for sale
+ // line.append("Not for sale");
+ }
+ }
+ else
+ {
+ LLStringUtil::format_map_t args;
+ args["[MESSAGE]"] = LLTrans::getString("RetrievingData");
+ line.append(LLTrans::getString("TooltipForSaleMsg", args));
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ if (!suppressObjectHoverDisplay)
+ {
+ LLToolTipMgr::instance().show(tooltip_msg);
+ }
+ }
}
}
- else if (!gLastHitPosGlobal.isExactlyZero())
+ else if ( mHoverPick.mPickType == LLPickInfo::PICK_LAND )
{
- handle_go_to(NULL);
+ //
+ // Do not show hover for land unless prefs are set to allow it.
+ //
+
+ if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE;
+
+ // Didn't hit an object, but since we have a land point we
+ // must be hovering over land.
+
+ LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
+ LLUUID owner;
+ S32 width = 0;
+ S32 height = 0;
+
+ if ( hover_parcel )
+ {
+ owner = hover_parcel->getOwnerID();
+ width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
+ height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
+ }
+
+ // Line: "Land"
+ line.clear();
+ line.append(LLTrans::getString("TooltipLand"));
+ if (hover_parcel)
+ {
+ line.append(hover_parcel->getName());
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ // Line: "Owner: James Linden"
+ line.clear();
+ line.append(LLTrans::getString("TooltipOwner") + " ");
+
+ if ( hover_parcel )
+ {
+ std::string name;
+ if (LLUUID::null == owner)
+ {
+ line.append(LLTrans::getString("TooltipPublic"));
+ }
+ else if (hover_parcel->getIsGroupOwned())
+ {
+ if (gCacheName->getGroupName(owner, name))
+ {
+ line.append(name);
+ line.append(LLTrans::getString("TooltipIsGroup"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ else if(gCacheName->getFullName(owner, name))
+ {
+ line.append(name);
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ // Line: "no fly, not safe, no build"
+
+ // Don't display properties for your land. This is just
+ // confusing, because you can do anything on your own land.
+ if ( hover_parcel && owner != gAgent.getID() )
+ {
+ S32 words = 0;
+
+ line.clear();
+ // JC - Keep this in the same order as the checkboxes
+ // on the land info panel
+ if ( !hover_parcel->getAllowModify() )
+ {
+ if ( hover_parcel->getAllowGroupModify() )
+ {
+ line.append(LLTrans::getString("TooltipFlagGroupBuild"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("TooltipFlagNoBuild"));
+ }
+ words++;
+ }
+
+ if ( !hover_parcel->getAllowTerraform() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNoEdit"));
+ words++;
+ }
+
+ if ( hover_parcel->getAllowDamage() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNotSafe"));
+ words++;
+ }
+
+ // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
+ if ( !hover_parcel->getAllowFly() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNoFly"));
+ words++;
+ }
+
+ if ( !hover_parcel->getAllowOtherScripts() )
+ {
+ if (words) line.append(", ");
+ if ( hover_parcel->getAllowGroupScripts() )
+ {
+ line.append(LLTrans::getString("TooltipFlagGroupScripts"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("TooltipFlagNoScripts"));
+ }
+
+ words++;
+ }
+
+ if (words)
+ {
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+ }
+ }
+
+ if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
+ {
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice());
+ line = LLTrans::getString("TooltipForSaleL$", args);
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+ }
+ LLToolTipMgr::instance().show(tooltip_msg);
}
+
return TRUE;
- */
}
+// static
+void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
+{
+ LLSD params;
+ params["avatar_id"] = avatar_id;
+ if (LLToolTipMgr::instance().toolTipVisible())
+ {
+ LLRect rect = LLToolTipMgr::instance().getToolTipRect();
+ params["pos"]["x"] = rect.mLeft;
+ params["pos"]["y"] = rect.mTop;
+ }
+
+ LLFloaterReg::showInstance("inspect_avatar", params);
+}
void LLToolPie::handleDeselect()
{
@@ -627,6 +1009,7 @@ void LLToolPie::handleDeselect()
setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
}
// remove temporary selection for pie menu
+ LLSelectMgr::getInstance()->setHoverObject(NULL);
LLSelectMgr::getInstance()->validateSelection();
}
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index a55e435282..be6e539ffd 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -52,6 +52,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
virtual void render();
@@ -72,6 +73,7 @@ public:
static void selectionPropertiesReceived();
+ static void showAvatarInspector(const LLUUID& id);
private:
BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y);
@@ -84,6 +86,7 @@ private:
BOOL mGrabMouseButtonDown;
BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region
LLPickInfo mPick;
+ LLPickInfo mHoverPick;
LLPointer<LLViewerObject> mClickActionObject;
U8 mClickAction;
LLSafeHandle<LLObjectSelection> mLeftClickSelection;
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 878ed0f9a9..9a92f2ae3f 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -40,6 +40,7 @@
#include "lltoolpipette.h"
// Library includes
+#include "lltooltip.h"
// Viewer includes
#include "llviewerobjectlist.h"
@@ -92,15 +93,19 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen)
+BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect &sticky_rect_screen)
{
if (mTooltipMsg.empty())
{
return FALSE;
}
- // keep tooltip message up when mouse in this part of screen
- sticky_rect_screen->setCenterAndSize(x, y, 20, 20);
- msg = mTooltipMsg;
+
+ LLRect sticky_rect;
+ sticky_rect.setCenterAndSize(x, y, 20, 20);
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(mTooltipMsg)
+ .sticky_rect(sticky_rect));
+
return TRUE;
}
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 3b6ebec67e..cce5b6ce54 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -56,7 +56,7 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
// Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index de68dd6153..a7f4cb558e 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -65,6 +65,7 @@
// linden library headers
#include "llprimitive.h"
#include "llwindow.h" // incBusyCount()
+#include "material_codes.h"
const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index cb68045310..901d0594f1 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -158,7 +158,8 @@ bool LLURLDispatcherImpl::dispatchApp(const std::string& url,
LLMediaCtrl* web,
bool trusted_browser)
{
- if (!LLSLURL::isSLURL(url))
+ // ensure the URL is in the secondlife:///app/ format
+ if (!LLSLURL::isSLURLCommand(url))
{
return false;
}
@@ -170,7 +171,14 @@ bool LLURLDispatcherImpl::dispatchApp(const std::string& url,
pathArray.erase(0); // erase "cmd"
bool handled = LLCommandDispatcher::dispatch(
cmd, pathArray, uri.queryMap(), web, trusted_browser);
- return handled;
+
+ // alert if we didn't handle this secondlife:///app/ SLURL
+ // (but still return true because it is a valid app SLURL)
+ if (! handled)
+ {
+ LLNotifications::instance().add("UnsupportedCommandSLURL");
+ }
+ return true;
}
// static
@@ -323,7 +331,7 @@ public:
// Teleport requests *must* come from a trusted browser
// inside the app, otherwise a malicious web page could
// cause a constant teleport loop. JC
- LLTeleportHandler() : LLCommandHandler("teleport", true) { }
+ LLTeleportHandler() : LLCommandHandler("teleport", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 8e65c7e65e..6d2482d3f0 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1260,10 +1260,6 @@ void render_ui_2d()
stop_glerror();
}
gViewerWindow->draw();
- if (gDebugSelect)
- {
- gViewerWindow->drawPickBuffer();
- }
// reset current origin for font rendering, in case of tiling render
LLFontGL::sCurOrigin.set(0, 0);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index b85dc30e72..1fc387027d 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -78,7 +78,6 @@
#include "llfloaterlandholdings.h"
#include "llfloatermap.h"
#include "llfloatermemleak.h"
-#include "llfloatermute.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
#include "llfloateropenobject.h"
@@ -96,6 +95,7 @@
#include "llfloatersettingsdebug.h"
#include "llfloatersnapshot.h"
#include "llfloatertelehub.h"
+#include "llfloatertestinspectors.h"
#include "llfloatertestlistview.h"
#include "llfloatertools.h"
#include "llfloatertos.h"
@@ -110,6 +110,7 @@
#include "llmediaremotectrl.h"
#include "llmoveview.h"
#include "llnearbychat.h"
+#include "llpanelblockedlist.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
@@ -177,8 +178,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
- LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMute>);
- LLFloaterReg::add("mute_object", "floater_mute_object.xml", &LLFloaterMute::buildFloaterMuteObjectUI);
+ LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>);
@@ -208,6 +208,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("properties", "floater_inventory_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProperties>);
LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
+ LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml",
+ &LLFloaterReg::build<LLFloaterTestInspectors>);
LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build<LLFloater>);
LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 95ab40f9bf..f3557bb8f7 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -53,6 +53,7 @@
#include "llpreviewgesture.h"
#include "llviewerwindow.h"
#include "lltrans.h"
+#include "llappearancemgr.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -120,6 +121,41 @@ LLViewerInventoryItem::~LLViewerInventoryItem()
{
}
+BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const
+{
+ using std::string;
+ using std::stringstream;
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ BOOL result = FALSE;
+
+ if (separatorPos < string::npos)
+ {
+ if (sortField)
+ {
+ /*
+ * The conversion from string to S32 is made this way instead of old plain
+ * atoi() to ensure portability. If on some other platform S32 will not be
+ * defined to be signed int, this conversion will still work because of
+ * operators overloading, but atoi() may fail.
+ */
+ stringstream ss(mName.substr(0, separatorPos));
+ ss >> *sortField;
+ }
+
+ if (displayName)
+ {
+ *displayName = mName.substr(separatorPos + 1, string::npos);
+ }
+
+ result = TRUE;
+ }
+
+ return result;
+}
+
void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other)
{
LLInventoryItem::copyItem(other);
@@ -725,6 +761,11 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
}
}
+void ModifiedCOFCallback::fire(const LLUUID& inv_item)
+{
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+}
+
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
{
mAttach = attachmentp;
@@ -839,6 +880,27 @@ void link_inventory_item(
const LLAssetType::EType asset_type,
LLPointer<LLInventoryCallback> cb)
{
+ const LLInventoryObject *baseobj = gInventory.getObject(item_id);
+ if (!baseobj)
+ {
+ llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+ if (baseobj && baseobj->getIsLinkType())
+ {
+ llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+
+ if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
+ {
+ // Fail if item can be found but is of a type that can't be linked.
+ // Arguably should fail if the item can't be found too, but that could
+ // be a larger behavioral change.
+ llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
+ return;
+ }
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LinkInventoryItem);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -1102,7 +1164,70 @@ const std::string& LLViewerInventoryItem::getName() const
return linked_category->getName();
}
- return LLInventoryItem::getName();
+ return getDisplayName();
+}
+
+const std::string& LLViewerInventoryItem::getDisplayName() const
+{
+ std::string result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(0, &result);
+
+ return mDisplayName = hasSortField ? result : LLInventoryItem::getName();
+}
+
+S32 LLViewerInventoryItem::getSortField() const
+{
+ S32 result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0);
+
+ return hasSortField ? result : -1;
+}
+
+void LLViewerInventoryItem::setSortField(S32 sortField)
+{
+ using std::string;
+
+ std::stringstream ss;
+ ss << sortField;
+
+ string newSortField = ss.str();
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ // the name of the LLViewerInventoryItem already consists of sort field and display name.
+ mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos);
+ }
+ else
+ {
+ // there is no sort field in the name of LLViewerInventoryItem, we should add it
+ mName = newSortField + separator + mName;
+ }
+}
+
+void LLViewerInventoryItem::rename(const std::string& n)
+{
+ using std::string;
+
+ string new_name(n);
+ LLStringUtil::replaceNonstandardASCII(new_name, ' ');
+ LLStringUtil::replaceChar(new_name, '|', ' ');
+ LLStringUtil::trim(new_name);
+ LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ mName.replace(separatorPos + 1, string::npos, new_name);
+ }
+ else
+ {
+ mName = new_name;
+ }
}
const LLPermissions& LLViewerInventoryItem::getPermissions() const
@@ -1193,21 +1318,26 @@ bool LLViewerInventoryItem::getIsBrokenLink() const
return LLAssetType::lookupIsLinkType(getType());
}
-const LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
+LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
{
if (mType == LLAssetType::AT_LINK)
{
- const LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
+ LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
+ if (linked_item && linked_item->getIsLinkType())
+ {
+ llwarns << "Warning: Accessing link to link" << llendl;
+ return NULL;
+ }
return linked_item;
}
return NULL;
}
-const LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
+LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
{
if (mType == LLAssetType::AT_LINK_FOLDER)
{
- const LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
+ LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
return linked_category;
}
return NULL;
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 0bfb37f7e8..d5b99ac160 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -37,6 +37,8 @@
#include "llframetimer.h"
#include "llwearable.h"
+#include <boost/signals2.hpp> // boost::signals2::trackable
+
class LLFolderView;
class LLFolderBridge;
class LLViewerInventoryCategory;
@@ -55,11 +57,18 @@ public:
protected:
~LLViewerInventoryItem( void ); // ref counted
+ BOOL extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const;
+ static char getSeparator() { return '@'; }
+ mutable std::string mDisplayName;
public:
virtual LLAssetType::EType getType() const;
virtual const LLUUID& getAssetUUID() const;
virtual const std::string& getName() const;
+ virtual const std::string& getDisplayName() const;
+ virtual S32 getSortField() const;
+ virtual void setSortField(S32 sortField);
+ virtual void rename(const std::string& new_name);
virtual const LLPermissions& getPermissions() const;
virtual const LLUUID& getCreatorUUID() const;
virtual const std::string& getDescription() const;
@@ -142,8 +151,8 @@ public:
LLTransactionID getTransactionID() const { return mTransactionID; }
bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory.
- const LLViewerInventoryItem *getLinkedItem() const;
- const LLViewerInventoryCategory *getLinkedCategory() const;
+ LLViewerInventoryItem *getLinkedItem() const;
+ LLViewerInventoryCategory *getLinkedCategory() const;
// callback
void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
@@ -227,6 +236,11 @@ class WearOnAvatarCallback : public LLInventoryCallback
void fire(const LLUUID& inv_item);
};
+class ModifiedCOFCallback : public LLInventoryCallback
+{
+ void fire(const LLUUID& inv_item);
+};
+
class LLViewerJointAttachment;
class RezAttachmentCallback : public LLInventoryCallback
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index c3e6bd28da..5289037c7a 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -34,18 +34,17 @@
#include "llviewermedia.h"
#include "llviewermediafocus.h"
-#include "llhoverview.h"
#include "llmimetypes.h"
#include "llviewercontrol.h"
#include "llviewertexture.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
-#include "llviewerwindow.h"
#include "llversionviewer.h"
#include "llviewertexturelist.h"
#include "llpluginclassmedia.h"
#include "llevent.h" // LLSimpleListener
+#include "llnotifications.h"
#include "lluuid.h"
#include <boost/bind.hpp> // for SkinFolder listener
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 68a49662e7..9a61394383 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -180,10 +180,11 @@ public:
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; };
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { return FALSE; };
/*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; };
/*virtual*/ const std::string& getName() const { return LLStringUtil::null; };
+
/*virtual*/ BOOL isView() const { return FALSE; };
/*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 {};
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f6af2e3ca4..22fe0a043b 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -100,7 +100,6 @@
#include "llfloaterdirectory.h"
#include "llfloaterchatterbox.h"
#include "llfloaterfonttest.h"
-#include "llfloatergesture.h"
#include "llfloatergodtools.h"
#include "llfloatergroupinvite.h"
#include "llfloatergroups.h"
@@ -113,7 +112,6 @@
#include "llfloaterland.h"
#include "llfloaterlandholdings.h"
#include "llfloatermap.h"
-#include "llfloatermute.h"
#include "llfloateropenobject.h"
#include "llfloaterperms.h"
#include "llfloaterpostprocess.h"
@@ -135,7 +133,7 @@
#include "llmemoryview.h"
#include "llgivemoney.h"
#include "llgroupmgr.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llimage.h"
@@ -147,6 +145,7 @@
#include "llfloaterinventory.h"
#include "llkeyboard.h"
#include "llpanellogin.h"
+#include "llpanelblockedlist.h"
#include "llmenucommands.h"
#include "llmenugl.h"
#include "llmimetypes.h"
@@ -183,7 +182,6 @@
#include "lluuid.h"
#include "llviewercamera.h"
#include "llviewergenericmessage.h"
-#include "llviewergesture.h"
#include "llviewertexturelist.h" // gTextureList
#include "llviewerinventory.h"
#include "llviewermenufile.h" // init_menu_file()
@@ -210,9 +208,11 @@
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llfloaternotificationsconsole.h"
+#include "llfloatercamera.h"
#include "lluilistener.h"
#include "lltexlayer.h"
+#include "llappearancemgr.h"
using namespace LLVOAvatarDefines;
@@ -585,6 +585,8 @@ void init_menus()
gLoginMenuBarView->setBackgroundColor( color );
gMenuHolder->addChild(gLoginMenuBarView);
+ // tooltips are on top of EVERYTHING, including menus
+ gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
}
///////////////////
@@ -1520,14 +1522,6 @@ class LLAdvancedSendTestIms : public view_listener_t
}
};
-class LLAdvancedAvatarInspector : public view_listener_t
-{
- bool handleEvent(const LLSD& avatar_id)
- {
- LLFloaterReg::showInstance("inspect_avatar", avatar_id);
- return true;
- }
-};
///////////////
// XUI NAMES //
@@ -2899,7 +2893,7 @@ class LLObjectMute : public view_listener_t
else
{
LLMuteList::getInstance()->add(mute);
- LLFloaterReg::showInstance("mute");
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
return true;
@@ -2908,7 +2902,7 @@ class LLObjectMute : public view_listener_t
bool handle_go_to()
{
- // JAMESDEBUG try simulator autopilot
+ // try simulator autopilot
std::vector<std::string> strings;
std::string val;
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
@@ -3776,6 +3770,7 @@ void handle_reset_view()
else
{
reset_view_final( TRUE );
+ LLFloaterCamera::resetCameraMode();
}
}
@@ -6384,13 +6379,13 @@ void handle_selected_texture_info(void*)
void handle_test_male(void*)
{
- wear_outfit_by_name("Male Shape & Outfit");
+ LLAppearanceManager::wearOutfitByName("Male Shape & Outfit");
//gGestureList.requestResetFromServer( TRUE );
}
void handle_test_female(void*)
{
- wear_outfit_by_name("Female Shape & Outfit");
+ LLAppearanceManager::wearOutfitByName("Female Shape & Outfit");
//gGestureList.requestResetFromServer( FALSE );
}
@@ -6732,15 +6727,12 @@ BOOL enable_god_basic(void*)
void toggle_show_xui_names(void *)
{
- BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames");
-
- showXUINames = !showXUINames;
- gSavedSettings.setBOOL("ShowXUINames", showXUINames);
+ gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
}
BOOL check_show_xui_names(void *)
{
- return gSavedSettings.getBOOL("ShowXUINames");
+ return gSavedSettings.getBOOL("DebugShowXUINames");
}
class LLToolsSelectOnlyMyObjects : public view_listener_t
@@ -7160,7 +7152,7 @@ class LLViewShowHoverTips : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLHoverView::sShowHoverTips = !LLHoverView::sShowHoverTips;
+ gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
return true;
}
};
@@ -7169,7 +7161,7 @@ class LLViewCheckShowHoverTips : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- bool new_value = LLHoverView::sShowHoverTips;
+ bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
return new_value;
}
};
@@ -7855,7 +7847,6 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
- view_listener_t::addMenu(new LLAdvancedAvatarInspector(), "Advanced.AvatarInspector");
// Advanced > Character > Grab Baked Texture
view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index abe5fd8ce8..2a2b095833 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1,4 +1,3 @@
-
/**
* @file llviewermessage.cpp
* @brief Dumping ground for viewer-side message system callbacks.
@@ -83,7 +82,6 @@
#include "llfloaterregioninfo.h"
#include "llfloaterlandholdings.h"
#include "llurldispatcher.h"
-#include "llfloatermute.h"
#include "llfloaterpostcard.h"
#include "llfloaterpreference.h"
#include "llfollowcam.h"
@@ -138,6 +136,9 @@
#include "llkeythrottle.h"
#include "llgroupactions.h"
#include "llagentui.h"
+#include "llsidetray.h"
+#include "llpanelblockedlist.h"
+#include "llpanelplaceinfo.h"
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/split.hpp>
@@ -1000,9 +1001,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
LLMute mute(blocked_id, from_name, type);
if (LLMuteList::getInstance()->add(mute))
{
- LLFloaterReg::showInstance("mute");
- LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute");
- if(mute_instance) mute_instance->selectMute(blocked_id);
+ LLPanelBlockedList::showPanelAndSelect(blocked_id);
}
// purge the message queue of any previously queued inventory offers from the same source.
@@ -1472,6 +1471,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
EInstantMessage dialog = (EInstantMessage)d;
+ // make sure that we don't have an empty or all-whitespace name
+ LLStringUtil::trim(name);
+ if (name.empty())
+ {
+ name = LLTrans::getString("Unnamed");
+ }
+
BOOL is_busy = gAgent.getBusy();
BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
@@ -2397,6 +2403,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
// Look for IRC-style emotes
if (ircstyle)
{
+ // set CHAT_STYLE_IRC to avoid adding Avatar Name as author of message. See EXT-656
+ chat.mChatStyle = CHAT_STYLE_IRC;
+
// Do nothing, ircstyle is fixed above for chat bubbles
}
else
@@ -5565,6 +5574,12 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateEstateName(estate_name);
LLFloaterBuyLand::updateEstateName(estate_name);
+ LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
+ if (panel)
+ {
+ panel->updateEstateName(estate_name);
+ }
+
// standard message, not from system
std::string last_modified;
if (covenant_timestamp == 0)
@@ -5590,7 +5605,8 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateLastModified(last_modified);
LLFloaterBuyLand::updateLastModified(last_modified);
- gCacheName->get(estate_owner_id, false, &callbackCacheEstateOwnerName);
+ BOOL is_group = FALSE;
+ gCacheName->get(estate_owner_id, is_group, &callbackCacheEstateOwnerName);
// load the actual covenant asset data
const BOOL high_priority = TRUE;
@@ -5621,6 +5637,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelEstateCovenant::updateCovenantText(covenant_text, covenant_id);
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, covenant_id);
+ panel->updateCovenantText(covenant_text);
}
}
@@ -5641,6 +5658,12 @@ void callbackCacheEstateOwnerName(const LLUUID& id,
LLPanelEstateCovenant::updateEstateOwnerName(name);
LLPanelLandCovenant::updateEstateOwnerName(name);
LLFloaterBuyLand::updateEstateOwnerName(name);
+
+ LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
+ if (panel)
+ {
+ panel->updateEstateOwnerName(name);
+ }
}
void onCovenantLoadComplete(LLVFS *vfs,
@@ -5708,6 +5731,12 @@ void onCovenantLoadComplete(LLVFS *vfs,
LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid);
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
+
+ LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
+ if (panel)
+ {
+ panel->updateCovenantText(covenant_text);
+ }
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1594a68f36..cf77f7e2b6 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -582,9 +582,9 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
}
}
-void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects)
+void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
{
- objects.put(this);
+ objects.push_back(this);
for (child_list_t::iterator iter = mChildList.begin();
iter != mChildList.end(); iter++)
{
@@ -596,9 +596,9 @@ void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& obje
}
}
-void LLViewerObject::addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects)
+void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects)
{
- objects.put(this);
+ objects.push_back(this);
// don't add any attachments when temporarily selecting avatar
if (isAvatar())
{
@@ -3475,7 +3475,7 @@ void LLViewerObject::setMediaType(U8 media_type)
{
if (!mMedia)
{
- // JAMESDEBUG TODO what if we don't have a media pointer?
+ // TODO what if we don't have a media pointer?
}
else if (mMedia->mMediaType != media_type)
{
@@ -3677,7 +3677,7 @@ void LLViewerObject::sendTEUpdate() const
msg->addString("MediaURL", NULL);
}
- // JAMESDEBUG TODO send media type
+ // TODO send media type
packTEMessage(msg);
@@ -3688,7 +3688,7 @@ void LLViewerObject::sendTEUpdate() const
void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
{
LLPrimitive::setTE(te, texture_entry);
-// JAMESDEBUG This doesn't work, don't get any textures.
+// This doesn't work, don't get any textures.
// if (mDrawable.notNull() && mDrawable->isVisible())
// {
const LLUUID& image_id = getTE(te)->getID();
@@ -3865,7 +3865,7 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
{
- // JAMESDEBUG this might need work for media type
+ // this might need work for media type
S32 retval = 0;
const LLTextureEntry *tep = getTE(te);
if (!tep)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index cda2c5114f..836e05728f 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -242,8 +242,8 @@ public:
virtual void removeChild(LLViewerObject *childp);
const_child_list_t& getChildren() const { return mChildList; }
S32 numChildren() const { return mChildList.size(); }
- void addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects);
- void addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects);
+ void addThisAndAllChildren(std::vector<LLViewerObject*>& objects);
+ void addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects);
BOOL isChild(LLViewerObject *childp) const;
BOOL isSeat() const;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index a8232e9a9d..acdc2c2513 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -49,7 +49,7 @@
#include "llagent.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llworld.h"
#include "llstring.h"
#include "llhudtext.h"
@@ -574,10 +574,14 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
// Slam priorities for textures that we care about (hovered, selected, and focused)
// Hovered
// Assumes only one level deep of parenting
- objectp = gHoverView->getLastHoverObject();
- if (objectp)
+ LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
+ if (nodep)
{
- objectp->boostTexturePriority();
+ objectp = nodep->getObject();
+ if (objectp)
+ {
+ objectp->boostTexturePriority();
+ }
}
}
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index cb233085e5..86d51bfd4b 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -43,7 +43,7 @@
#include "message.h"
#include "llviewermediafocus.h"
#include "llviewerparcelmediaautoplay.h"
-#include "llviewerwindow.h"
+#include "llnotifications.h"
#include "llfirstuse.h"
#include "llpluginclassmedia.h"
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index d900ea9b33..a1db48529e 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1284,9 +1284,11 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag
}
-void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos)
+void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos)
{
- LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos );
+ //FIXME: only request parcel info when tooltip is shown
+ return;
+ /*LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos );
if (!region)
{
return;
@@ -1318,7 +1320,7 @@ void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos)
msg->addBOOL("SnapSelection", FALSE );
msg->sendReliable( region->getHost() );
- mHoverRequestResult = PARCEL_RESULT_NO_DATA;
+ mHoverRequestResult = PARCEL_RESULT_NO_DATA;*/
}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 7373366cd7..275c79fd3b 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -217,7 +217,7 @@ public:
void sendParcelDwellRequest();
// If the point is outside the current hover parcel, request more data
- void requestHoverParcelProperties(const LLVector3d& pos_global);
+ void setHoverParcel(const LLVector3d& pos_global);
bool canAgentBuyParcel(LLParcel*, bool forGroup) const;
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index 8bf7364714..21d4c72428 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -207,6 +207,8 @@
#include "patch_dct.h"
#include "sound_ids.h"
+// Builds work with all headers below commented out as of 2009-09-10 JC
+
// Library includes from llprimitive
#include "imageids.h"
#include "legacy_object_types.h"
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index de01e79803..ceb2698223 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -658,45 +658,6 @@ void LLViewerTextEditor::makePristine()
LLTextEditor::makePristine();
}
-///////////////////////////////////////////////////////////////////
-
-BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
-{
- 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->pointInView(local_x, local_y)
- && viewp->getVisible()
- && viewp->getEnabled()
- && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- return TRUE;
- }
- }
-
- if( mSegments.empty() )
- {
- return TRUE;
- }
-
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment && cur_segment->getToolTip( msg ) )
- {
- // 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;
-}
-
BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -814,38 +775,18 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
-
- // *TODO: Add right click menus for SLURLs
-// if(! handled)
-// {
-// const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
-// if( cur_segment )
-// {
-// if(cur_segment->getStyle()->isLink())
-// {
-// handled = TRUE;
-// mHTML = cur_segment->getStyle()->getLinkHREF();
-// }
-// }
-// }
-// LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
-// if(handled && menu && mParseHTML && mHTML.length() > 0)
-// {
-// menu->setVisible(TRUE);
-// menu->arrange();
-// menu->updateParent(LLMenuGL::sMenuContainer);
-// LLMenuGL::showPopup(this, menu, x, y);
-// mHTML = "";
-// }
-// else
-// {
-// if(menu && menu->getVisible())
-// {
-// menu->setVisible(FALSE);
-// }
-// }
- return handled;
+ // pop up a context menu for any Url under the cursor
+ if (handleRightMouseDownOverUrl(this, x, y))
+ {
+ return TRUE;
+ }
+
+ if (childrenHandleRightMouseDown(x, y, mask) != NULL)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
}
BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
@@ -1087,6 +1028,7 @@ llwchar LLViewerTextEditor::pasteEmbeddedItem(llwchar ext_char)
void LLViewerTextEditor::onValueChange(S32 start, S32 end)
{
updateSegments();
+ updateLinkSegments();
findEmbeddedItemSegments(start, end);
}
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index 9567bfbc48..100fa343af 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -35,7 +35,6 @@
#include "lltexteditor.h"
-
//
// Classes
//
@@ -69,7 +68,6 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type,
void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
@@ -137,9 +135,6 @@ private:
LLPointer<class LLEmbeddedNotecardOpener> mInventoryCallback;
- // *TODO: Add right click menus for SLURLs
- //LLViewHandle mPopupMenuHandle;
-
//
// Inner classes
//
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 6ea1522b47..ec82f62a8b 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1810,7 +1810,7 @@ void LLViewerLODTexture::processTextureStats()
// data than we need to.
/*if (mBoostLevel == LLViewerTexture::BOOST_UI ||
mBoostLevel == LLViewerTexture::BOOST_PREVIEW ||
- mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF?
+ mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // what about AVATAR_BAKED_SELF?
{
discard_level = 0; // full res
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c6ac9c9172..b4f1b5f4f5 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -78,6 +78,7 @@
#include "lltimer.h"
#include "timing.h"
#include "llviewermenu.h"
+#include "lltooltip.h"
// newview includes
#include "llagent.h"
@@ -115,7 +116,7 @@
#include "llfontfreetype.h"
#include "llgesturemgr.h"
#include "llglheaders.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudmanager.h"
#include "llhudview.h"
#include "llimagebmp.h"
@@ -213,22 +214,14 @@ extern BOOL gDebugClicks;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDepthDirty;
extern BOOL gResizeScreenTexture;
-extern S32 gJamesInt;
LLViewerWindow *gViewerWindow = NULL;
-
-BOOL gDebugSelect = FALSE;
-
-LLFrameTimer gMouseIdleTimer;
LLFrameTimer gAwayTimer;
LLFrameTimer gAwayTriggerTimer;
-LLFrameTimer gAlphaFadeTimer;
BOOL gShowOverlayTitle = FALSE;
-BOOL gPickTransparent = TRUE;
-BOOL gDebugFastUIRender = FALSE;
LLViewerObject* gDebugRaycastObject = NULL;
LLVector3 gDebugRaycastIntersection;
LLVector2 gDebugRaycastTexCoord;
@@ -239,7 +232,6 @@ S32 gDebugRaycastFaceHit;
// HUD display lines in lower right
BOOL gDisplayWindInfo = FALSE;
BOOL gDisplayCameraPos = FALSE;
-BOOL gDisplayNearestWater = FALSE;
BOOL gDisplayFOV = FALSE;
S32 CHAT_BAR_HEIGHT = 28;
@@ -604,21 +596,6 @@ void LLViewerWindow::updateDebugText()
// LLViewerWindow
//
-bool LLViewerWindow::shouldShowToolTipFor(LLMouseHandler *mh)
-{
- if (mToolTip && mh)
- {
- LLMouseHandler::EShowToolTip showlevel = mh->getShowToolTip();
-
- bool tool_tip_allowed = (showlevel == LLMouseHandler::SHOW_ALWAYS
- || (showlevel == LLMouseHandler::SHOW_IF_NOT_BLOCKED
- && !mToolTipBlocked));
-
- return tool_tip_allowed;
- }
- return false;
-}
-
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
std::string buttonname;
@@ -678,16 +655,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
mWindow->releaseMouse();
// Indicate mouse was active
- gMouseIdleTimer.reset();
-
- // Hide tooltips on mousedown
- mToolTipBlocked = down;
-
- // Also hide hover info on mousedown/mouseup
- if (gHoverView)
- {
- gHoverView->cancelHover();
- }
+ LLUI::resetMouseIdleTimer();
// Don't let the user move the mouse out of the window until mouse up.
if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
@@ -754,10 +722,6 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
if(LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
{
- // 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);
return TRUE;
}
}
@@ -875,13 +839,10 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask
// Save mouse point for access during idle() and display()
- LLCoordGL prev_saved_mouse_point = mCurrentMousePoint;
LLCoordGL mouse_point(x, y);
saveLastMouse(mouse_point);
- BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured
- ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position
- gMouseIdleTimer.reset();
+ LLUI::resetMouseIdleTimer();
mWindow->showCursorFromMouseMove();
@@ -889,17 +850,6 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask
{
gAgent.clearAFK();
}
-
- if(mouse_actually_moved)
- {
- mToolTipBlocked = FALSE;
- }
-
- // Activate the hover picker on mouse move.
- if (gHoverView)
- {
- gHoverView->setTyping(FALSE);
- }
}
void LLViewerWindow::handleMouseLeave(LLWindow *window)
@@ -907,10 +857,6 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window)
// Note: we won't get this if we have captured the mouse.
llassert( gFocusMgr.getMouseCapture() == NULL );
mMouseInWindow = FALSE;
- if (mToolTip)
- {
- mToolTip->setVisible( FALSE );
- }
}
BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
@@ -1250,16 +1196,12 @@ LLViewerWindow::LLViewerWindow(
mLeftMouseDown(FALSE),
mMiddleMouseDown(FALSE),
mRightMouseDown(FALSE),
- mToolTip(NULL),
- mToolTipBlocked(FALSE),
mMouseInWindow( FALSE ),
mLastMask( MASK_NONE ),
mToolStored( NULL ),
- mSuppressToolbox( FALSE ),
mHideCursorPermanent( FALSE ),
mCursorHidden(FALSE),
mIgnoreActivate( FALSE ),
- mHoverPick(),
mResDirty(false),
mStatesDirty(false),
mIsFullscreenChecked(false),
@@ -1485,7 +1427,7 @@ void LLViewerWindow::initBase()
cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
gConsole = LLUICtrlFactory::create<LLConsole>(cp);
- mRootView->addChild(gConsole);
+ getRootView()->addChild(gConsole);
// optionally forward warnings to chat console/chat floater
// for qa runs and dev builds
@@ -1505,11 +1447,11 @@ void LLViewerWindow::initBase()
debug_p.follows.flags(FOLLOWS_ALL);
debug_p.visible(true);
gDebugView = LLUICtrlFactory::create<LLDebugView>(debug_p);
- mRootView->addChild(gDebugView);
+ getRootView()->addChild(gDebugView);
// 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);
+ getRootView()->addChild(gFloaterView, -1);
+ getRootView()->addChild(gSnapshotFloaterView);
// notify above floaters!
LLRect notify_rect = floater_view_rect;
@@ -1519,28 +1461,18 @@ void LLViewerWindow::initBase()
p.mouse_opaque(false);
p.follows.flags(FOLLOWS_ALL);
gNotifyBoxView = LLUICtrlFactory::create<LLNotifyBoxView> (p);
- mRootView->addChild(gNotifyBoxView, -2);
-
- // Tooltips go above floaters
- LLTextBox::Params params;
- params.text("tool tip");
- params.name(params.text);
- params.rect(LLRect (0, 1, 1, 0));
- params.h_pad(4);
- params.v_pad(2);
- params.text_color(LLUIColorTable::instance().getColor( "ToolTipTextColor" ));
- params.border_color(LLUIColorTable::instance().getColor( "ToolTipBorderColor" ));
- params.border_visible(false);
- params.background_color(LLUIColorTable::instance().getColor( "ToolTipBgColor" ));
- params.bg_visible(true);
- params.font.style("NORMAL");
- params.border_drop_shadow_visible(true);
- params.visible(false);
- mToolTip = LLUICtrlFactory::create<LLTextBox> (params);
+ getRootView()->addChild(gNotifyBoxView, -2);
+
+ // View for tooltips
+ LLToolTipView::Params hvp;
+ hvp.name("tooltip view");
+ hvp.rect(full_window);
+ gToolTipView = LLUICtrlFactory::create<LLToolTipView>(hvp);
+ getRootView()->addChild(gToolTipView);
// Add the progress bar view (startup view), which overrides everything
mProgressView = new LLProgressView(full_window);
- mRootView->addChild(mProgressView);
+ getRootView()->addChild(mProgressView);
setShowProgress(FALSE);
setProgressCancelButtonVisible(FALSE);
}
@@ -1566,13 +1498,6 @@ void LLViewerWindow::initWorldUI()
LLBottomTray::getInstance()->reshape(rc.getWidth(),rc.getHeight(),FALSE);
LLBottomTray::getInstance()->setRect(rc);
- // View for hover information
- LLHoverView::Params hvp;
- hvp.name("gHoverview");
- hvp.rect(full_window);
- gHoverView = LLUICtrlFactory::create<LLHoverView>(hvp);
- mRootView->addChild(gHoverView);
-
// Pre initialize instance communicate instance;
// currently needs to happen before initializing chat or IM
LLFloaterReg::getInstance("communicate");
@@ -1590,7 +1515,7 @@ void LLViewerWindow::initWorldUI()
mvp.rect(morph_view_rect);
mvp.visible(false);
gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
- mRootView->addChild(gMorphView);
+ getRootView()->addChild(gMorphView);
// Make space for nav bar.
LLRect floater_view_rect = gFloaterView->getRect();
@@ -1602,8 +1527,6 @@ void LLViewerWindow::initWorldUI()
gFloaterView->setRect(floater_view_rect);
gNotifyBoxView->setRect(notify_view_rect);
- // *Note: this is where gFloaterMute used to be initialized.
-
LLWorldMapView::initClass();
// Force gFloaterWorldMap to initialize
@@ -1642,6 +1565,11 @@ void LLViewerWindow::initWorldUI()
navbar->showFavoritesPanel(FALSE);
}
+ if (!gSavedSettings.getBOOL("ShowCameraAndMoveControls"))
+ {
+ LLBottomTray::getInstance()->showCameraAndMoveControls(FALSE);
+ }
+
getRootView()->addChild(gStatusBar);
getRootView()->addChild(navbar);
@@ -1674,6 +1602,12 @@ void LLViewerWindow::initWorldUI()
// put behind everything else in the UI
getRootView()->addChildInBack(gHUDView);
}
+
+ // this allows not to see UI elements created while UI initializing after Alt+Tab was pressed during login. EXT-744.
+ moveProgressViewToFront();
+
+ // tooltips are always on top
+ getRootView()->sendChildToFront(gToolTipView);
}
// Destroy the UI
@@ -1691,10 +1625,6 @@ void LLViewerWindow::shutdownViews()
gMorphView->setVisible(FALSE);
}
- // Delete Tool Tip
- delete mToolTip;
- mToolTip = NULL;
-
// Delete all child views.
delete mRootView;
mRootView = NULL;
@@ -1702,7 +1632,7 @@ void LLViewerWindow::shutdownViews()
// Automatically deleted as children of mRootView. Fix the globals.
gStatusBar = NULL;
gIMMgr = NULL;
- gHoverView = NULL;
+ gToolTipView = NULL;
gFloaterView = NULL;
gMorphView = NULL;
@@ -1775,12 +1705,6 @@ void LLViewerWindow::showCursor()
void LLViewerWindow::hideCursor()
{
- // Hide tooltips
- if(mToolTip ) mToolTip->setVisible( FALSE );
-
- // Also hide hover info
- if (gHoverView) gHoverView->cancelHover();
-
// And hide the cursor
mWindow->hideCursor();
@@ -2035,9 +1959,9 @@ void LLViewerWindow::draw()
// No translation needed, this view is glued to 0,0
mRootView->draw();
- if (mToolTip->getVisible() && LLView::sDebugRects)
+ if (LLView::sDebugRects)
{
- gl_rect_2d(mToolTipStickyRect, LLColor4::white, false);
+ gToolTipView->drawStickyRect();
}
// Draw optional on-top-of-everyone view
@@ -2054,31 +1978,6 @@ void LLViewerWindow::draw()
LLUI::popMatrix();
}
- // Draw tooltips
- // Adjust their rectangle so they don't go off the top or bottom
- // of the screen.
- if( mToolTip && mToolTip->getVisible() )
- {
- glMatrixMode(GL_MODELVIEW);
- LLUI::pushMatrix();
- {
- S32 tip_height = mToolTip->getRect().getHeight();
-
- S32 screen_x, screen_y;
- mToolTip->localPointToScreen(0, -24 - tip_height,
- &screen_x, &screen_y);
-
- // If tooltip would draw off the bottom of the screen,
- // show it from the cursor tip position.
- if (screen_y < tip_height)
- {
- mToolTip->localPointToScreen(0, 0, &screen_x, &screen_y);
- }
- LLUI::translate( (F32) screen_x, (F32) screen_y, 0);
- mToolTip->draw();
- }
- LLUI::popMatrix();
- }
if( gShowOverlayTitle && !mOverlayTitle.empty() )
{
@@ -2120,26 +2019,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
}
}
- //// HACK look for UI editing keys
- //if (LLView::sEditingUI)
- //{
- // if (LLFloaterEditUI::processKeystroke(key, mask))
- // {
- // return TRUE;
- // }
- //}
-
- // Hide tooltips on keypress
- mToolTipBlocked = TRUE; // block until next time mouse is moved
-
- // Also hide hover info on keypress
- if (gHoverView)
- {
- gHoverView->cancelHover();
-
- gHoverView->setTyping(TRUE);
- }
-
+ // hide tooltips on keypress
+ LLToolTipMgr::instance().hideToolTips();
+
// Explicit hack for debug menu.
if ((MASK_ALT & mask) &&
(MASK_CONTROL & mask) &&
@@ -2197,6 +2079,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
{
return TRUE;
}
+ //some of context menus use this container, let context menu handle navigation keys
+ if(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))
+ {
+ return TRUE;
+ }
// Traverses up the hierarchy
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
@@ -2360,14 +2247,8 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
{
LLView::sMouseHandlerMessage.clear();
- gMouseIdleTimer.reset();
-
- // Hide tooltips
- if( mToolTip )
- {
- mToolTip->setVisible( FALSE );
- }
-
+ LLUI::resetMouseIdleTimer();
+
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
if( mouse_captor )
{
@@ -2420,7 +2301,7 @@ void LLViewerWindow::moveCursorToCenter()
mLastMousePoint.set(x,y);
mCurrentMouseDelta.set(0,0);
- LLUI::setCursorPositionScreen(x, y);
+ LLUI::setMousePositionScreen(x, y);
}
void LLViewerWindow::updateBottomTrayRect()
@@ -2452,6 +2333,35 @@ void LLViewerWindow::updateBottomTrayRect()
// Hover handlers
//
+void append_xui_tooltip(LLView* viewp, std::string& tool_tip_msg)
+{
+ if (viewp)
+ {
+ if (!tool_tip_msg.empty())
+ {
+ tool_tip_msg.append("\n---------\n");
+ }
+ LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
+ // NOTE: we skip "root" since it is assumed
+ for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
+ tooltip_it != end_tooltip_it;
+ ++tooltip_it)
+ {
+ LLView* viewp = *tooltip_it;
+
+ tool_tip_msg.append(viewp->getName());
+ LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
+ if (panelp && !panelp->getXMLFilename().empty())
+ {
+ tool_tip_msg.append("(");
+ tool_tip_msg.append(panelp->getXMLFilename());
+ tool_tip_msg.append(")");
+ }
+ tool_tip_msg.append("/");
+ }
+ }
+}
+
// Update UI based on stored mouse position from mouse-move
// event processing.
void LLViewerWindow::updateUI()
@@ -2460,7 +2370,7 @@ void LLViewerWindow::updateUI()
updateWorldViewRect();
- //updateBottomTrayRect();
+ updateBottomTrayRect();
LLView::sMouseHandlerMessage.clear();
@@ -2473,6 +2383,17 @@ void LLViewerWindow::updateUI()
return;
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
+ {
+ gDebugRaycastFaceHit = -1;
+ gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+ &gDebugRaycastFaceHit,
+ &gDebugRaycastIntersection,
+ &gDebugRaycastTexCoord,
+ &gDebugRaycastNormal,
+ &gDebugRaycastBinormal);
+ }
+
updateMouseDelta();
updateKeyboardFocus();
@@ -2500,8 +2421,8 @@ void LLViewerWindow::updateUI()
if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
{
// iterator over contents of top_ctrl, and throw into mouse_hover_set
- for (LLView::tree_iterator_t it = top_ctrl->beginTree();
- it != top_ctrl->endTree();
+ for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
+ it != top_ctrl->endTreeDFS();
++it)
{
LLView* viewp = *it;
@@ -2521,9 +2442,8 @@ void LLViewerWindow::updateUI()
else
{
// walk UI tree in depth-first order
- LLView::tree_iterator_t end_it;
- for (LLView::tree_iterator_t it = root_view->beginTree();
- it != end_it;
+ for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
+ it != root_view->endTreeDFS();
++it)
{
LLView* viewp = *it;
@@ -2536,7 +2456,7 @@ void LLViewerWindow::updateUI()
if (viewp->getMouseOpaque())
{
// constrain further iteration to children of this widget
- it = viewp->beginTree();
+ it = viewp->beginTreeDFS();
}
// we have a view that contains the mouse, add it to the set
@@ -2639,130 +2559,87 @@ void LLViewerWindow::updateUI()
}
}
- if( !handled )
+ if (!handled)
{
- lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl;
- }
- }
-
- // *NOTE: sometimes tools handle the mouse as a captor, so this
- // logic is a little confusing
- LLTool *tool = NULL;
- if (gHoverView)
- {
- tool = LLToolMgr::getInstance()->getCurrentTool();
-
- if(!handled && tool)
- {
- handled = tool->handleHover(x, y, mask);
+ LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
- if (!mWindow->isCursorHidden())
+ if(mMouseInWindow && tool)
{
- gHoverView->updateHover(tool);
+ handled = tool->handleHover(x, y, mask);
}
}
- else
- {
- // Cancel hovering if any UI element handled the event.
- gHoverView->cancelHover();
- }
-
- // Suppress the toolbox view if our source tool was the pie tool,
- // and we've overridden to something else.
- mSuppressToolbox =
- (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
- (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
-
}
- // Show a new tool tip (or update one that is alrady shown)
+ // Show a new tool tip (or update one that is already shown)
BOOL tool_tip_handled = FALSE;
std::string tool_tip_msg;
if( handled
- && !mWindow->isCursorHidden()
- && mToolTip)
+ && !mWindow->isCursorHidden())
{
- LLRect screen_sticky_rect;
- LLMouseHandler *tooltip_source = NULL;
+ LLRect screen_sticky_rect = mRootView->getLocalRect();
S32 local_x, local_y;
- if (mouse_captor)
- {
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- tooltip_source = mouse_captor;
- }
- else if (handled_by_top_ctrl)
- {
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- tooltip_source = top_ctrl;
- }
- else
- {
- local_x = x; local_y = y;
- tooltip_source = mRootView;
- }
- F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" );
- //HACK: hack for tool-based tooltips which need to pop up more quickly
- //Also for show xui names as tooltips debug mode
- if ((gFocusMgr.getMouseCapture()
- && !gFocusMgr.getMouseCapture()->isView())
- || LLUI::sShowXUINames)
+ if (gSavedSettings.getBOOL("DebugShowXUINames"))
{
- tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" );
- }
-
-
- BOOL tooltip_vis = FALSE;
- if (shouldShowToolTipFor(tooltip_source))
- {
- tool_tip_handled = tooltip_source->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect );
-
- // if we actually got a tooltip back...
- if( tool_tip_handled && !tool_tip_msg.empty() )
+ LLView* tooltip_view = mRootView;
+ LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
+ for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
{
- if (mToolTip->getVisible() // already showing a tooltip
- || gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay) // mouse has been still long enough to show the tooltip
+ LLView* viewp = *it;
+ LLRect screen_rect;
+ viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
+ if (!(viewp->getVisible()
+ && screen_rect.pointInRect(x, y)))
{
- // if tooltip has changed or mouse has moved outside of "sticky" rectangle...
- if (mLastToolTipMessage != tool_tip_msg
- || !mToolTipStickyRect.pointInRect(x, y))
+ it.skipDescendants();
+ }
+ else if (viewp->getMouseOpaque())
+ {
+ if (!viewp->hasAncestor(tooltip_view))
{
- //...update "sticky" rect and tooltip position
- mToolTipStickyRect = screen_sticky_rect;
- mToolTip->setOrigin( x, y );
+ append_xui_tooltip(tooltip_view, tool_tip_msg);
+ screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
}
-
- // remember this tooltip so we know when it changes
- mLastToolTipMessage = tool_tip_msg;
- mToolTip->setWrappedText( tool_tip_msg, 200 );
- mToolTip->reshapeToFitText();
- LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0);
- mToolTip->translateIntoRect( virtual_window_rect, FALSE );
- tooltip_vis = TRUE;
+ tooltip_view = viewp;
}
}
- }
- // HACK: assuming tooltip background is in ToolTipBGColor, perform fade out
- LLColor4 bg_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
- if (tooltip_vis)
+ append_xui_tooltip(tooltip_view, tool_tip_msg);
+ screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(tool_tip_msg)
+ .sticky_rect(screen_sticky_rect)
+ .width(400));
+ }
+ // if there is a mouse captor, nothing else gets a tooltip
+ else if (mouse_captor)
{
- mToolTipFadeTimer.stop();
- mToolTip->setBackgroundColor(bg_color);
+ mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
}
else
{
- if (!mToolTipFadeTimer.getStarted())
+ // next is top_ctrl
+ if (!tool_tip_handled && top_ctrl)
{
- mToolTipFadeTimer.start();
+ top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ }
+
+ if (!tool_tip_handled)
+ {
+ local_x = x; local_y = y;
+ tool_tip_handled = mRootView->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
}
- F32 tool_tip_fade_time = gSavedSettings.getF32("ToolTipFadeTime");
- bg_color.mV[VALPHA] = clamp_rescale(mToolTipFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, bg_color.mV[VALPHA], 0.f);
- mToolTip->setBackgroundColor(bg_color);
- }
- // above interpolation of bg_color alpha is guaranteed to reach 0.f exactly
- mToolTip->setVisible( bg_color.mV[VALPHA] != 0.f );
+ LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
+ if (!tool_tip_handled && current_tool)
+ {
+ current_tool->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = current_tool->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ }
+ }
}
updateLayout();
@@ -2779,67 +2656,8 @@ void LLViewerWindow::updateUI()
{
LLSelectMgr::getInstance()->deselectUnused();
}
-
- updatePicking(x, y, mask);
}
-void LLViewerWindow::updatePicking(S32 x, S32 y, MASK mask)
-{
- // per frame picking - for tooltips and changing cursor over interactive objects
- static S32 previous_x = -1;
- static S32 previous_y = -1;
- static BOOL mouse_moved_since_pick = FALSE;
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
- {
- gDebugRaycastFaceHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
- &gDebugRaycastFaceHit,
- &gDebugRaycastIntersection,
- &gDebugRaycastTexCoord,
- &gDebugRaycastNormal,
- &gDebugRaycastBinormal);
- }
-
-
- if ((previous_x != x) || (previous_y != y))
- mouse_moved_since_pick = TRUE;
-
- BOOL do_pick = FALSE;
-
- F32 picks_moving = gSavedSettings.getF32("PicksPerSecondMouseMoving");
- if ((mouse_moved_since_pick) && (picks_moving > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_moving))
- {
- do_pick = TRUE;
- }
-
- F32 picks_stationary = gSavedSettings.getF32("PicksPerSecondMouseStationary");
- if ((!mouse_moved_since_pick) && (picks_stationary > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_stationary))
- {
- do_pick = TRUE;
- }
-
- if (getCursorHidden())
- {
- do_pick = FALSE;
- }
-
- if(LLViewerMediaFocus::getInstance()->getFocus())
- {
- // When in-world media is in focus, pick every frame so that browser mouse-overs, dragging scrollbars, etc. work properly.
- do_pick = TRUE;
- }
-
- if (do_pick)
- {
- mouse_moved_since_pick = FALSE;
- mPickTimer.reset();
- pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE);
- }
-
- previous_x = x;
- previous_y = y;
-}
void LLViewerWindow::updateLayout()
{
@@ -2851,6 +2669,12 @@ void LLViewerWindow::updateLayout()
&& tool != LLToolDragAndDrop::getInstance()
&& !gSavedSettings.getBOOL("FreezeTime"))
{
+ // Suppress the toolbox view if our source tool was the pie tool,
+ // and we've overridden to something else.
+ bool suppress_toolbox =
+ (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
+ (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
+
LLMouseHandler *captor = gFocusMgr.getMouseCapture();
// With the null, inspect, or drag and drop tool, don't muck
// with visibility.
@@ -2858,7 +2682,7 @@ void LLViewerWindow::updateLayout()
if (gFloaterTools->isMinimized()
|| (tool != LLToolPie::getInstance() // not default tool
&& tool != LLToolCompGun::getInstance() // not coming out of mouselook
- && !mSuppressToolbox // not override in third person
+ && !suppress_toolbox // not override in third person
&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
&& (!captor || captor->isView()))) // not dragging
@@ -2876,7 +2700,7 @@ void LLViewerWindow::updateLayout()
{
gFloaterTools->setVisible(FALSE);
}
- gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
+ //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
}
// Always update console
@@ -3043,13 +2867,6 @@ void LLViewerWindow::updateWorldViewRect(bool use_full_window)
}
}
-/* static */
-void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
-{
- gViewerWindow->mHoverPick = pick_info;
-}
-
-
void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
{
// Store last mouse location.
@@ -3295,7 +3112,7 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe
return intersect;
}
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info)
+void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
{
if (gNoRender)
{
@@ -3329,7 +3146,7 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
LLRect screen_region = mPickScreenRegion;
screen_region.translate(mPicks.size() * PICK_DIAMETER, 0);
- LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback);
+ LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, TRUE, callback);
schedulePick(pick);
}
@@ -4423,8 +4240,7 @@ void LLViewerWindow::moveProgressViewToFront()
{
if( mProgressView && mRootView )
{
- mRootView->removeChild( mProgressView );
- mRootView->addChild( mProgressView );
+ mRootView->sendChildToFront(mProgressView);
}
}
@@ -4901,11 +4717,6 @@ F32 LLViewerWindow::getWorldViewAspectRatio() const
}
}
-void LLViewerWindow::drawPickBuffer() const
-{
- mHoverPick.drawPickBuffer();
-}
-
void LLViewerWindow::calcDisplayScale()
{
F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
@@ -5154,49 +4965,6 @@ void LLPickInfo::updateXYCoords()
}
}
-void LLPickInfo::drawPickBuffer() const
-{
- if (mPickBuffer)
- {
- gGL.pushMatrix();
- LLGLDisable no_blend(GL_BLEND);
- LLGLDisable no_alpha_test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glPixelZoom(10.f, 10.f);
- LLVector2 display_scale = gViewerWindow->getDisplayScale();
- glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
- glPixelZoom(1.f, 1.f);
- gGL.color4fv(LLColor4::white.mV);
- gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- FALSE);
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- gGL.translatef(10.f, 10.f, 0.f);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gGL.popMatrix();
- }
-}
-
void LLPickInfo::getSurfaceInfo()
{
// set values to uninitialized - this is what we return if no intersection is found
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 8502f7a719..5d54cf1b7f 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -47,20 +47,22 @@
#include "llwindowcallbacks.h"
#include "lltimer.h"
#include "llstat.h"
-#include "llnotifications.h"
#include "llmousehandler.h"
#include "llcursortypes.h"
#include "llhandle.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
#include <boost/scoped_ptr.hpp>
+
class LLView;
class LLViewerObject;
class LLUUID;
class LLProgressView;
class LLTool;
class LLVelocityBar;
-class LLTextBox;
+class LLPanel;
class LLImageRaw;
class LLHUDIcon;
class LLWindow;
@@ -73,6 +75,17 @@ class LLViewerWindowListener;
class LLPickInfo
{
public:
+ typedef enum
+ {
+ PICK_OBJECT,
+ PICK_FLORA,
+ PICK_LAND,
+ PICK_ICON,
+ PICK_PARCEL_WALL,
+ PICK_INVALID
+ } EPickType;
+
+public:
LLPickInfo();
LLPickInfo(const LLCoordGL& mouse_pos,
const LLRect& screen_region,
@@ -84,20 +97,10 @@ public:
void fetchResults();
LLPointer<LLViewerObject> getObject() const;
LLUUID getObjectID() const { return mObjectID; }
- void drawPickBuffer() const;
+ bool isValid() const { return mPickType != PICK_INVALID; }
static bool isFlora(LLViewerObject* object);
- typedef enum
- {
- PICK_OBJECT,
- PICK_FLORA,
- PICK_LAND,
- PICK_ICON,
- PICK_PARCEL_WALL,
- PICK_INVALID
- } EPickType;
-
public:
LLCoordGL mMousePt;
MASK mKeyMask;
@@ -150,6 +153,8 @@ public:
void adjustControlRectanglesForFirstUse(const LLRect& window);
void initWorldUI();
+ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
+
//
// LLWindowCallback interface implementation
//
@@ -157,7 +162,6 @@ public:
/*virtual*/ BOOL handleTranslatedKeyUp(KEY key, MASK mask);
/*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended
- /*virtual*/ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
/*virtual*/ BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleCloseRequest(LLWindow *window);
@@ -237,7 +241,6 @@ public:
BOOL getRightMouseDown() const { return mRightMouseDown; }
const LLPickInfo& getLastPick() const { return mLastPick; }
- const LLPickInfo& getHoverPick() const { return mHoverPick; }
void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0);
void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0);
@@ -284,7 +287,6 @@ public:
void updateLayout();
void updateMouseDelta();
void updateKeyboardFocus();
- void updatePicking(S32 x, S32 y, MASK mask);
void updateWorldViewRect(bool use_full_window=false);
void updateBottomTrayRect();
@@ -335,11 +337,8 @@ public:
void returnEmptyPicks();
- void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info),
- BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE);
+ void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), BOOL pick_transparent = FALSE);
LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent);
- static void hoverPickCallback(const LLPickInfo& pick_info);
-
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector3* intersection);
@@ -385,8 +384,6 @@ public:
const LLVector2& getDisplayScale() const { return mDisplayScale; }
void calcDisplayScale();
- void drawPickBuffer() const;
-
private:
bool shouldShowToolTipFor(LLMouseHandler *mh);
static bool onAlert(const LLSD& notify);
@@ -425,9 +422,8 @@ protected:
LLProgressView *mProgressView;
LLFrameTimer mToolTipFadeTimer;
- LLTextBox* mToolTip;
+ LLPanel* mToolTip;
std::string mLastToolTipMessage;
- BOOL mToolTipBlocked; // True after a key press or a mouse button event. False once the mouse moves again.
LLRect mToolTipStickyRect; // Once a tool tip is shown, it will stay visible until the mouse leaves this rect.
BOOL mMouseInWindow; // True if the mouse is over our window or if we have captured the mouse.
@@ -438,12 +434,9 @@ protected:
// Variables used for tool override switching based on modifier keys. JC
MASK mLastMask; // used to detect changes in modifier mask
LLTool* mToolStored; // the tool we're overriding
- BOOL mSuppressToolbox; // sometimes hide the toolbox, despite
- // having a camera tool selected
BOOL mHideCursorPermanent; // true during drags, mouselook
BOOL mCursorHidden;
LLPickInfo mLastPick;
- LLPickInfo mHoverPick;
std::vector<LLPickInfo> mPicks;
LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen)
LLTimer mPickTimer; // timer for scheduling n picks per second
@@ -482,13 +475,9 @@ void update_saved_window_size(const std::string& control,S32 delta_width, S32 de
extern LLViewerWindow* gViewerWindow;
-extern LLFrameTimer gMouseIdleTimer; // how long has it been since the mouse last moved?
extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true
extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away
-extern BOOL gDebugSelect;
-
-extern BOOL gDebugFastUIRender;
extern LLViewerObject* gDebugRaycastObject;
extern LLVector3 gDebugRaycastIntersection;
extern LLVector2 gDebugRaycastTexCoord;
@@ -500,7 +489,6 @@ extern S32 CHAT_BAR_HEIGHT;
extern BOOL gDisplayCameraPos;
extern BOOL gDisplayWindInfo;
-extern BOOL gDisplayNearestWater;
extern BOOL gDisplayFOV;
#endif
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index a2793accea..570a3334b9 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -38,7 +38,7 @@
#include "llviewercontrol.h"
#include "llagent.h"
-#include "llviewerwindow.h"
+#include "llnotifications.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 2304571cf1..746dc99e35 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6920,7 +6920,8 @@ void LLVoiceClient::notifyFriendObservers()
void LLVoiceClient::lookupName(const LLUUID &id)
{
- gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup);
+ BOOL is_group = FALSE;
+ gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
}
//static
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 300a5db7c3..3204c2d264 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -67,6 +67,7 @@ void LLWeb::initClass()
LLAlertDialog::setURLLoader(&sAlertURLLoader);
}
+
// static
void LLWeb::loadURL(const std::string& url)
{
@@ -76,12 +77,19 @@ void LLWeb::loadURL(const std::string& url)
}
else
{
- LLFloaterReg::showInstance("media_browser",url);
+ loadURLInternal(url);
}
}
// static
+void LLWeb::loadURLInternal(const std::string &url)
+{
+ LLFloaterReg::showInstance("media_browser", url);
+}
+
+
+// static
void LLWeb::loadURLExternal(const std::string& url)
{
std::string escaped_url = escapeURL(url);
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 71cc236621..96a53db2ca 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -36,23 +36,29 @@
#include <string>
+///
+/// The LLWeb class provides various static methods to display the
+/// contents of a Url in a web browser. Variations are provided to
+/// let you specifically use the Second Life internal browser, the
+/// operating system's default browser, or to respect the user's
+/// setting for which of these two they prefer to use with SL.
+///
class LLWeb
{
public:
static void initClass();
- // Loads unescaped url in either internal web browser or external
- // browser, depending on user settings.
+ /// Load the given url in the user's preferred web browser
static void loadURL(const std::string& url);
-
+ /// Load the given url in the user's preferred web browser
static void loadURL(const char* url) { loadURL( ll_safe_string(url) ); }
-
- // Loads unescaped url in external browser.
+ /// Load the given url in the Second Life internal web browser
+ static void loadURLInternal(const std::string &url);
+ /// Load the given url in the operating system's web browser
static void loadURLExternal(const std::string& url);
- // Returns escaped (eg, " " to "%20") url
+ // Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
-
};
#endif
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 67bc205f62..4d7423eaae 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -41,6 +41,7 @@
#include "lleventflags.h"
#include "llfloaterreg.h"
#include "llrender.h"
+#include "lltooltip.h"
#include "llagent.h"
#include "llcallingcard.h"
@@ -50,6 +51,7 @@
#include "llfloatermap.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
#include "lltextbox.h"
#include "lltextureview.h"
#include "lltracker.h"
@@ -1179,10 +1181,12 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
}
-BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen )
+BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen )
{
LLVector3d pos_global = viewPosToGlobal(x, y);
+ std::string tooltip_msg;
+
LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
if (info)
{
@@ -1217,22 +1221,26 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
}
}
}
- msg.assign( message );
+ tooltip_msg.assign( message );
// Optionally show region flags
std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags);
if (!region_flags.empty())
{
- msg += '\n';
- msg += region_flags;
+ tooltip_msg += '\n';
+ tooltip_msg += region_flags;
}
const S32 SLOP = 9;
S32 screen_x, screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
- sticky_rect_screen->setCenterAndSize(screen_x, screen_y, SLOP, SLOP);
+ sticky_rect_screen.setCenterAndSize(screen_x, screen_y, SLOP, SLOP);
+
+ LLToolTipMgr::instance().show(LLToolTipParams()
+ .message(tooltip_msg)
+ .sticky_rect(sticky_rect_screen));
}
return TRUE;
}
@@ -1744,7 +1752,7 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )
LLRect clip_rect = getRect();
clip_rect.stretch(-8);
clip_rect.clipPointToRect(mMouseDownX, mMouseDownY, local_x, local_y);
- LLUI::setCursorPositionLocal(this, local_x, local_y);
+ LLUI::setMousePositionLocal(this, local_x, local_y);
// finish the pan
mPanning = FALSE;
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index 41c9772694..8349d5399f 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -72,7 +72,7 @@ public:
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 handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen );
+ virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen );
bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track);
void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id);
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index a5ee78df2c..bdf7631770 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -138,8 +138,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,0,2425
- PRODUCTVERSION 2,0,0,2425
+ FILEVERSION 2,0,0,2639
+ PRODUCTVERSION 2,0,0,2639
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -156,12 +156,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Linden Lab"
VALUE "FileDescription", "Second Life"
- VALUE "FileVersion", "2.0.0.2425"
+ VALUE "FileVersion", "2.0.0.2639"
VALUE "InternalName", "Second Life"
- VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
+ VALUE "LegalCopyright", "Copyright � 2001-2008, Linden Research, Inc."
VALUE "OriginalFilename", "SecondLife.exe"
VALUE "ProductName", "Second Life"
- VALUE "ProductVersion", "2.0.0.2425"
+ VALUE "ProductVersion", "2.0.0.2639"
END
END
BLOCK "VarFileInfo"
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png
new file mode 100644
index 0000000000..6b725e153a
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png
new file mode 100644
index 0000000000..9f22080d13
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png
new file mode 100644
index 0000000000..5b2a8eb339
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png
new file mode 100644
index 0000000000..9acf7053d5
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png
new file mode 100644
index 0000000000..b5781718ec
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png
new file mode 100644
index 0000000000..c8560c0869
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png
new file mode 100644
index 0000000000..b09f7c64d3
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png
new file mode 100644
index 0000000000..ae2c57c207
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png
new file mode 100644
index 0000000000..c5cd8cca92
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png b/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png
new file mode 100644
index 0000000000..5a9346fd39
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png
new file mode 100644
index 0000000000..28ff6ba976
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png
new file mode 100644
index 0000000000..e2eb38e12d
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png
new file mode 100644
index 0000000000..f314d4e001
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png
new file mode 100644
index 0000000000..4dddc2b391
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png
new file mode 100644
index 0000000000..9f31d461b5
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png
new file mode 100644
index 0000000000..1b0192e685
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png
new file mode 100644
index 0000000000..9f42b7d5b2
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png
new file mode 100644
index 0000000000..80d227b6a7
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png
new file mode 100644
index 0000000000..d0a825a682
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png
new file mode 100644
index 0000000000..282e8d62de
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png
new file mode 100644
index 0000000000..b211371e64
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png
new file mode 100644
index 0000000000..5039e57c32
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png
new file mode 100644
index 0000000000..e937c3f012
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png
new file mode 100644
index 0000000000..9b9837cec1
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
new file mode 100644
index 0000000000..c71d4a7854
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png b/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png
new file mode 100644
index 0000000000..6f2726c3e6
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AddItem_Disabled.png b/indra/newview/skins/default/textures/icons/AddItem_Disabled.png
new file mode 100644
index 0000000000..cf88c89ae5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AddItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/DragHandle.png b/indra/newview/skins/default/textures/icons/DragHandle.png
new file mode 100644
index 0000000000..c3cbc07a33
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/DragHandle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Group.png b/indra/newview/skins/default/textures/icons/Generic_Group.png
new file mode 100644
index 0000000000..909334d862
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Group.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Group_Large.png b/indra/newview/skins/default/textures/icons/Generic_Group_Large.png
new file mode 100644
index 0000000000..4d4f1e1bee
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Group_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Person.png b/indra/newview/skins/default/textures/icons/Generic_Person.png
new file mode 100644
index 0000000000..01618ce2c0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Person.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Person_Large.png b/indra/newview/skins/default/textures/icons/Generic_Person_Large.png
new file mode 100644
index 0000000000..65b0ce8b67
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Person_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Animation.png b/indra/newview/skins/default/textures/icons/Inv_Animation.png
new file mode 100644
index 0000000000..8b69434066
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Animation.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_BodyShape.png b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
new file mode 100644
index 0000000000..9d98bfaa7d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_CallingCard.png b/indra/newview/skins/default/textures/icons/Inv_CallingCard.png
new file mode 100644
index 0000000000..1de96475f7
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_CallingCard.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Clothing.png b/indra/newview/skins/default/textures/icons/Inv_Clothing.png
new file mode 100644
index 0000000000..49a54b82e1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Clothing.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Eye.png b/indra/newview/skins/default/textures/icons/Inv_Eye.png
new file mode 100644
index 0000000000..6d0321dde9
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Eye.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
new file mode 100644
index 0000000000..30aa6e04ac
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
new file mode 100644
index 0000000000..792ef446e8
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gesture.png b/indra/newview/skins/default/textures/icons/Inv_Gesture.png
new file mode 100644
index 0000000000..c49ae523c8
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gesture.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gloves.png b/indra/newview/skins/default/textures/icons/Inv_Gloves.png
new file mode 100644
index 0000000000..d81bc961d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gloves.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Hair.png b/indra/newview/skins/default/textures/icons/Inv_Hair.png
new file mode 100644
index 0000000000..5e68f1ffea
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Hair.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Jacket.png b/indra/newview/skins/default/textures/icons/Inv_Jacket.png
new file mode 100644
index 0000000000..0e28f45f19
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Jacket.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Landmark.png b/indra/newview/skins/default/textures/icons/Inv_Landmark.png
new file mode 100644
index 0000000000..6648a23393
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Landmark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Notecard.png b/indra/newview/skins/default/textures/icons/Inv_Notecard.png
new file mode 100644
index 0000000000..830a71311f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Notecard.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Object.png b/indra/newview/skins/default/textures/icons/Inv_Object.png
new file mode 100644
index 0000000000..a88d0dc4b3
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Object.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Pants.png b/indra/newview/skins/default/textures/icons/Inv_Pants.png
new file mode 100644
index 0000000000..2527f7f9c3
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Pants.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Script.png b/indra/newview/skins/default/textures/icons/Inv_Script.png
new file mode 100644
index 0000000000..e9c9b163fd
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Script.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shirt.png b/indra/newview/skins/default/textures/icons/Inv_Shirt.png
new file mode 100644
index 0000000000..7cc880a124
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Shirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shoe.png b/indra/newview/skins/default/textures/icons/Inv_Shoe.png
new file mode 100644
index 0000000000..0b148647eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Shoe.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skin.png b/indra/newview/skins/default/textures/icons/Inv_Skin.png
new file mode 100644
index 0000000000..8e20638bba
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Skin.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skirt.png b/indra/newview/skins/default/textures/icons/Inv_Skirt.png
new file mode 100644
index 0000000000..40860a3599
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Skirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Snapshot.png b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
new file mode 100644
index 0000000000..17e710a843
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Socks.png b/indra/newview/skins/default/textures/icons/Inv_Socks.png
new file mode 100644
index 0000000000..b8169dcb36
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Socks.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Sound.png b/indra/newview/skins/default/textures/icons/Inv_Sound.png
new file mode 100644
index 0000000000..1a50dd17da
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Sound.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Texture.png b/indra/newview/skins/default/textures/icons/Inv_Texture.png
new file mode 100644
index 0000000000..2d6d1b54bb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Texture.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Underpants.png b/indra/newview/skins/default/textures/icons/Inv_Underpants.png
new file mode 100644
index 0000000000..77f56c574f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Underpants.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Undershirt.png b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
new file mode 100644
index 0000000000..954eab7660
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Lock.png b/indra/newview/skins/default/textures/icons/Lock.png
new file mode 100644
index 0000000000..eb5b5ae7a9
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Lock.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png b/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png
new file mode 100644
index 0000000000..fb341e9c83
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Refresh_Off.png b/indra/newview/skins/default/textures/icons/Refresh_Off.png
new file mode 100644
index 0000000000..a8acfda741
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Refresh_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png b/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png
new file mode 100644
index 0000000000..caaf45a99f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
new file mode 100644
index 0000000000..428da506f3
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
new file mode 100644
index 0000000000..9d7716c6de
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_adult.tga b/indra/newview/skins/default/textures/places_rating_adult.tga
new file mode 100644
index 0000000000..c344fb1e78
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_mature.tga b/indra/newview/skins/default/textures/places_rating_mature.tga
new file mode 100644
index 0000000000..61c879bc92
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_mature.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_pg.tga b/indra/newview/skins/default/textures/places_rating_pg.tga
new file mode 100644
index 0000000000..7805dbce60
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_pg.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 0bd5f114ed..136c092afc 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -7,17 +7,19 @@
<texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" />
<texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" />
+ <texture name="AddItem_Disabled" file_name="icons/AddItem_Disabled.png" preload="false" />
<texture name="AddItem_Off" file_name="icons/AddItem_Off.png" preload="false" />
<texture name="AddItem_Press" file_name="icons/AddItem_Press.png" preload="false" />
- <texture name="Arrow_Left_Off" file_name="navbar/Arrow_Left_Off.png" preload="true"/>
- <texture name="Arrow_Left_Press" file_name="navbar/Arrow_Left_Press.png" preload="true"/>
- <texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true"/>
- <texture name="Arrow_Right_Press" file_name="navbar/Arrow_Right_Press.png" preload="true"/>
+ <texture name="Arrow_Left_Off" file_name="navbar/Arrow_Left_Off.png" preload="true" />
+ <texture name="Arrow_Left_Press" file_name="navbar/Arrow_Left_Press.png" preload="true" />
+ <texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true" />
+ <texture name="Arrow_Right_Press" file_name="navbar/Arrow_Right_Press.png" preload="true" />
<texture name="Arrow_Up" file_name="widgets/Arrow_Up.png" preload="true" />
<texture name="Arrow_Down" file_name="widgets/Arrow_Down.png" preload="true" />
+ <texture name="BackArrow_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" />
<texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />
<texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" />
@@ -54,7 +56,7 @@
<texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />
<texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />
<texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
- <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false"/>
+ <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
<texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" />
<texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" />
@@ -62,13 +64,13 @@
<texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
<texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" />
- <texture name="Help_Off" file_name="navbar/Help_Off.png" preload="false"/>
- <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false"/>
+ <texture name="Help_Off" file_name="navbar/Help_Off.png" preload="false" />
+ <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" />
- <texture name="History_Arrow" file_name="navbar/History_Arrow.png" preload="true"/>
+ <texture name="History_Arrow" file_name="navbar/History_Arrow.png" preload="true" />
- <texture name="Home_Off" file_name="navbar/Home_Off.png" preload="false"/>
- <texture name="Home_Press" file_name="navbar/Home_Press.png" preload="false"/>
+ <texture name="Home_Off" file_name="navbar/Home_Off.png" preload="false" />
+ <texture name="Home_Press" file_name="navbar/Home_Press.png" preload="false" />
<texture name="Icon_Close_Background" file_name="windows/Icon_Close_Background.png" preload="true" />
<texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" />
@@ -79,20 +81,34 @@
<texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
<texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
- <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false"/>
- <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false"/>
- <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="false"/>
+ <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
+ <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" />
+ <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="false" />
- <texture name="Icon_Undock_Background" file_name="windows/Icon_Undock_Background.png" preload="true" />
- <texture name="Icon_Undock_Foreground" file_name="windows/Icon_Undock_Foreground.png" preload="true" />
- <texture name="Icon_Undock_Press" file_name="windows/Icon_Undock_Press.png" preload="true" />
+ <texture name="Icon_Help_Background" file_name="windows/Icon_Help_Background.png" preload="false" />
+ <texture name="Icon_Help_Foreground" file_name="windows/Icon_Help_Foreground.png" preload="false" />
+ <texture name="Icon_Help_Press" file_name="windows/Icon_Help_Press.png" preload="false" />
+ <texture name="Icon_Info" file_name="windows/Icon_Info.png" preload="false" />
+
+ <texture name="Icon_Minimize_Background" file_name="windows/Icon_Minimize_Background.png" preload="true" />
+ <texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" />
+ <texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" />
+
+ <texture name="Icon_Undock_Background" file_name="windows/Icon_Undock_Background.png" preload="false" />
+ <texture name="Icon_Undock_Foreground" file_name="windows/Icon_Undock_Foreground.png" preload="false" />
+ <texture name="Icon_Undock_Press" file_name="windows/Icon_Undock_Press.png" preload="false" />
<texture name="Info" file_name="icons/Info.png" preload="false" />
+ <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+ <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
- <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false"/>
- <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false"/>
+ <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false" />
+ <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" />
<texture name="ListItem_Select" file_name="widgets/ListItem_Select.png" preload="true" />
+ <texture name="ListItem_Over" file_name="widgets/ListItem_Over.png" preload="true" />
+
+ <texture name="Lock" file_name="icons/Lock.png" preload="false" />
<texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" />
@@ -104,6 +120,7 @@
<texture name="NearbyVoice_Lvl3" file_name="bottomtray/NearbyVoice_Lvl3.png" preload="false" />
<texture name="NearbyVoice_On" file_name="bottomtray/NearbyVoice_On.png" preload="false" />
+ <texture name="OptionsMenu_Disabled" file_name="icons/OptionsMenu_Disabled.png" preload="false" />
<texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
<texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
@@ -116,7 +133,7 @@
<texture name="PushButton_Selected" file_name="widgets/PushButton_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Selected_Press" file_name="widgets/PushButton_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Selected_Disabled" file_name="widgets/PushButton_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
-
+
<texture name="RadioButton_Press" file_name="widgets/RadioButton_Press.png" preload="true" />
<texture name="RadioButton_On_Press" file_name="widgets/RadioButton_On_Press.png" preload="true" />
<texture name="RadioButton_Off" file_name="widgets/RadioButton_Off.png" preload="true" />
@@ -124,7 +141,7 @@
<texture name="RadioButton_Disabled" file_name="widgets/RadioButton_Disabled.png" preload="true" />
<texture name="RadioButton_On_Disabled" file_name="widgets/RadioButton_On_Disabled.png" preload="true" />
- <texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true"/>
+ <texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
<texture name="Row_Selection" file_name="navbar/Row_Selection.png" preload="false" />
@@ -138,7 +155,7 @@
<texture name="ScrollTrack_Vert" file_name="widgets/ScrollTrack_Vert.png" preload="true" scale.left="2" scale.top="40" scale.bottom="13" scale.right="0" />
<texture name="ScrollTrack_Horiz" file_name="widgets/ScrollTrack_Horiz.png" preload="true" scale.left="4" scale.top="0" scale.bottom="0" scale.right="2" />
- <texture name="Search" file_name="navbar/Search.png" preload="false"/>
+ <texture name="Search" file_name="navbar/Search.png" preload="false" />
<texture name="SegmentedBtn_Left_Off" file_name="widgets/SegmentedBtn_Left_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
<texture name="SegmentedBtn_Left_Press" file_name="widgets/SegmentedBtn_Left_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
@@ -167,35 +184,35 @@
<texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />
<texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" />
- <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="true"/>
- <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="true"/>
- <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="true"/>
- <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="true"/>
- <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="true"/>
- <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="true"/>
+ <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="true" />
+ <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="true" />
+ <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="true" />
+ <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="true" />
+ <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="true" />
+ <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="true" />
<texture name="TabIcon_Appearance_Off" file_name="taskpanel/TabIcon_Appearance_Off.png" preload="false" />
- <texture name="TabIcon_Appearance_Over" file_name="taskpanel/TabIcon_Appearance_Over.png" preload="false"/>
+ <texture name="TabIcon_Appearance_Over" file_name="taskpanel/TabIcon_Appearance_Over.png" preload="false" />
<texture name="TabIcon_Appearance_Selected" file_name="taskpanel/TabIcon_Appearance_Selected.png" preload="false" />
<texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
- <texture name="TabIcon_Close_Over" file_name="taskpanel/TabIcon_Close_Over.png" preload="false"/>
+ <texture name="TabIcon_Close_Over" file_name="taskpanel/TabIcon_Close_Over.png" preload="false" />
<texture name="TabIcon_Home_Off" file_name="taskpanel/TabIcon_Home_Off.png" preload="false" />
- <texture name="TabIcon_Home_Over" file_name="taskpanel/TabIcon_Home_Over.png" preload="false"/>
+ <texture name="TabIcon_Home_Over" file_name="taskpanel/TabIcon_Home_Over.png" preload="false" />
<texture name="TabIcon_Home_Selected" file_name="taskpanel/TabIcon_Home_Selected.png" preload="false" />
<texture name="TabIcon_Me_Off" file_name="taskpanel/TabIcon_Me_Off.png" preload="false" />
- <texture name="TabIcon_Me_Over" file_name="taskpanel/TabIcon_Me_Over.png" preload="false"/>
+ <texture name="TabIcon_Me_Over" file_name="taskpanel/TabIcon_Me_Over.png" preload="false" />
<texture name="TabIcon_Me_Selected" file_name="taskpanel/TabIcon_Me_Selected.png" preload="false" />
<texture name="TabIcon_Open_Off" file_name="taskpanel/TabIcon_Open_Off.png" preload="false" />
- <texture name="TabIcon_Open_Over" file_name="taskpanel/TabIcon_Open_Over.png" preload="false"/>
+ <texture name="TabIcon_Open_Over" file_name="taskpanel/TabIcon_Open_Over.png" preload="false" />
<texture name="TabIcon_People_Off" file_name="taskpanel/TabIcon_People_Off.png" preload="false" />
- <texture name="TabIcon_People_Over" file_name="taskpanel/TabIcon_People_Over.png" preload="false"/>
+ <texture name="TabIcon_People_Over" file_name="taskpanel/TabIcon_People_Over.png" preload="false" />
<texture name="TabIcon_People_Selected" file_name="taskpanel/TabIcon_People_Selected.png" preload="false" />
- <texture name="TabIcon_Places_Over" file_name="taskpanel/TabIcon_Places_Over.png" preload="false"/>
+ <texture name="TabIcon_Places_Over" file_name="taskpanel/TabIcon_Places_Over.png" preload="false" />
<texture name="TabIcon_Places_Off" file_name="taskpanel/TabIcon_Places_Off.png" preload="false" />
<texture name="TabIcon_Places_Selected" file_name="taskpanel/TabIcon_Places_Selected.png" preload="false" />
<texture name="TabIcon_Things_Off" file_name="taskpanel/TabIcon_Things_Off.png" preload="false" />
<texture name="TabIcon_Things_Selected" file_name="taskpanel/TabIcon_Things_Selected.png" preload="false" />
- <texture name="TabIcon_Things_Over" file_name="taskpanel/TabIcon_Things_Over.png" preload="false"/>
+ <texture name="TabIcon_Things_Over" file_name="taskpanel/TabIcon_Things_Over.png" preload="false" />
<texture name="TabTop_Divider" file_name="containers/TabTop_Divider.png" preload="false" />
<texture name="TabTop_Left_Press" file_name="containers/TabTop_Left_Press.png" preload="false" />
@@ -205,8 +222,8 @@
<texture name="TabTop_Right_Selected" file_name="containers/TabTop_Right_Selected.png" preload="false" />
<texture name="TabTop_Middle_Off" file_name="containers/TabTop_Middle_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
<texture name="TabTop_Middle_Selected" file_name="containers/TabTop_Middle_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
- <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9"/>
- <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9"/>
+ <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
<texture name="TaskPanel_Tab_Off" file_name="taskpanel/TaskPanel_Tab_Off.png" preload="false" scale.left="4" scale.top="29" scale.right="36" scale.bottom="4" />
<texture name="TaskPanel_Tab_Selected" file_name="taskpanel/TaskPanel_Tab_Selected.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" />
@@ -234,6 +251,7 @@
<texture name="Toolbar_Right_Press" file_name="containers/Toolbar_Right_Press.png" preload="false" />
<texture name="Toolbar_Right_Selected" file_name="containers/Toolbar_Right_Selected.png" preload="false" />
+ <texture name="TrashItem_Disabled" file_name="icons/TrashItem_Disabled.png" preload="false" />
<texture name="TrashItem_Off" file_name="icons/TrashItem_Off.png" preload="false" />
<texture name="TrashItem_Press" file_name="icons/TrashItem_Press.png" preload="false" />
@@ -255,297 +273,297 @@
- <!--There are still references to this old textfield art in the code somewhere -erica-->
+ <!--WARNING OLD ART *do not use*-->
- <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0"/>
- <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0"/>
+ <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
+ <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
- <texture name="cam_rotate_out.tga" preload="false"/>
- <texture name="cam_rotate_in.tga" preload="false"/>
- <texture name="cam_zoom_out.tga" preload="false"/>
- <texture name="cam_zoom_plus_in.tga" preload="false"/>
- <texture name="cam_zoom_minus_in.tga" preload="false"/>
+ <texture name="cam_rotate_out.tga" preload="false" />
+ <texture name="cam_rotate_in.tga" preload="false" />
+ <texture name="cam_zoom_out.tga" preload="false" />
+ <texture name="cam_zoom_plus_in.tga" preload="false" />
+ <texture name="cam_zoom_minus_in.tga" preload="false" />
- <texture name="close_inactive_blue.tga"/>
- <texture name="closebox.tga"/>
+ <texture name="close_inactive_blue.tga" />
+ <texture name="closebox.tga" />
<texture name="icn_clear_lineeditor.tga" />
- <texture name="icn_chatbar.tga"/>
- <texture name="icn_media-pause.tga"/>
- <texture name="icn_media-play.tga"/>
- <texture name="icn_music-play.tga"/>
- <texture name="icn_music-pause.tga"/>
- <texture name="icn_media_web.tga" preload="true"/>
- <texture name="icn_media_movie.tga" preload="true"/>
-
- <texture name="icn_speaker-muted_dark.tga"/>
- <texture name="icn_speaker_dark.tga"/>
-
- <texture name="icn_voice-localchat.tga"/>
- <texture name="icn_voice-groupfocus.tga"/>
- <texture name="icn_voice-pvtfocus.tga"/>
-
- <texture name="jump_left_out.tga"/>
- <texture name="jump_left_in.tga"/>
- <texture name="jump_right_out.tga"/>
- <texture name="jump_right_in.tga"/>
-
- <texture name="move_forward_out.tga" preload="false"/>
- <texture name="move_forward_in.tga" preload="false"/>
- <texture name="move_left_out.tga" preload="false"/>
- <texture name="move_left_in.tga" preload="false"/>
- <texture name="move_turn_left_out.tga" preload="false"/>
- <texture name="move_turn_left_in.tga" preload="false"/>
- <texture name="move_turn_right_out.tga" preload="false"/>
- <texture name="move_turn_right_in.tga" preload="false"/>
- <texture name="move_right_out.tga" preload="false"/>
- <texture name="move_right_in.tga" preload="false"/>
- <texture name="move_up_in.tga" preload="false"/>
- <texture name="move_up_out.tga" preload="false"/>
- <texture name="move_down_in.tga" preload="false"/>
- <texture name="move_down_out.tga" preload="false"/>
-
- <texture name="tool_grab.tga"/>
- <texture name="tool_grab_active.tga"/>
-
- <texture name="tool_face.tga"/>
- <texture name="tool_face_active.tga"/>
-
- <texture name="tool_create.tga"/>
- <texture name="tool_create_active.tga"/>
-
- <texture name="up_arrow.tga" file_name="up_arrow.png"/>
- <texture name="down_arrow.tga" file_name="down_arrow.png"/>
-
- <texture name="restore_inactive.tga"/>
- <texture name="restore.tga"/>
- <texture name="restore_pressed.tga"/>
-
- <texture name="tearoffbox.tga"/>
- <texture name="tearoff_pressed.tga"/>
-
- <texture name="icn_label_music.tga"/>
- <texture name="icn_label_media.tga"/>
- <texture name="arrow_down.tga"/>
- <texture name="cloud-particle.j2c" use_mips="true"/>
+ <texture name="icn_chatbar.tga" />
+ <texture name="icn_media-pause.tga" />
+ <texture name="icn_media-play.tga" />
+ <texture name="icn_music-play.tga" />
+ <texture name="icn_music-pause.tga" />
+ <texture name="icn_media_web.tga" preload="true" />
+ <texture name="icn_media_movie.tga" preload="true" />
+
+ <texture name="icn_speaker-muted_dark.tga" />
+ <texture name="icn_speaker_dark.tga" />
+
+ <texture name="icn_voice-localchat.tga" />
+ <texture name="icn_voice-groupfocus.tga" />
+ <texture name="icn_voice-pvtfocus.tga" />
+
+ <texture name="jump_left_out.tga" />
+ <texture name="jump_left_in.tga" />
+ <texture name="jump_right_out.tga" />
+ <texture name="jump_right_in.tga" />
+
+ <texture name="move_forward_out.tga" preload="false" />
+ <texture name="move_forward_in.tga" preload="false" />
+ <texture name="move_left_out.tga" preload="false" />
+ <texture name="move_left_in.tga" preload="false" />
+ <texture name="move_turn_left_out.tga" preload="false" />
+ <texture name="move_turn_left_in.tga" preload="false" />
+ <texture name="move_turn_right_out.tga" preload="false" />
+ <texture name="move_turn_right_in.tga" preload="false" />
+ <texture name="move_right_out.tga" preload="false" />
+ <texture name="move_right_in.tga" preload="false" />
+ <texture name="move_up_in.tga" preload="false" />
+ <texture name="move_up_out.tga" preload="false" />
+ <texture name="move_down_in.tga" preload="false" />
+ <texture name="move_down_out.tga" preload="false" />
+
+ <texture name="tool_grab.tga" />
+ <texture name="tool_grab_active.tga" />
+
+ <texture name="tool_face.tga" />
+ <texture name="tool_face_active.tga" />
+
+ <texture name="tool_create.tga" />
+ <texture name="tool_create_active.tga" />
+
+ <texture name="up_arrow.tga" file_name="up_arrow.png" />
+ <texture name="down_arrow.tga" file_name="down_arrow.png" />
+
+ <texture name="restore_inactive.tga" />
+ <texture name="restore.tga" />
+ <texture name="restore_pressed.tga" />
+
+ <texture name="tearoffbox.tga" />
+ <texture name="tearoff_pressed.tga" />
+
+ <texture name="icn_label_music.tga" />
+ <texture name="icn_label_media.tga" />
+ <texture name="arrow_down.tga" />
+ <texture name="cloud-particle.j2c" use_mips="true" />
<texture name="skin_thumbnail_default.png" preload="false" />
- <texture name="icn_textfield_enabled.tga" scale.left="5" scale.top="5" scale.bottom="5" scale.right="5"/>
- <texture name="icn_rounded-text-field.tga" scale.left="14" scale.bottom="16" scale.top="16" scale.right="114"/>
+ <texture name="icn_textfield_enabled.tga" scale.left="5" scale.top="5" scale.bottom="5" scale.right="5" />
+ <texture name="icn_rounded-text-field.tga" scale.left="14" scale.bottom="16" scale.top="16" scale.right="114" />
<texture name="toolbar_btn_enabled.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" />
<texture name="toolbar_btn_disabled.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" />
<texture name="toolbar_btn_selected.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" />
- <texture name="minimize_inactive.tga" preload="true"/>
+<!--TODO: REPLACE CODE REFERENCE TO THIS ART WITH Icon_Minimize_Background above -->
+ <texture name="minimize_inactive.tga" preload="true" />
<texture name="minimize.tga" preload="true" />
- <texture name="minimize_pressed.tga" preload="true"/>
+ <texture name="minimize_pressed.tga" preload="true" />
- <texture name="sm_rounded_corners_simple.tga" scale.left="4" scale.top="4" scale.bottom="4" scale.right="4"/>
+ <texture name="sm_rounded_corners_simple.tga" scale.left="4" scale.top="4" scale.bottom="4" scale.right="4" />
<texture name="rounded_square.tga" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
- <texture name="rounded_square_soft.tga" file_name="rounded_square_soft.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16"/>
-
- <texture name="toolbar_tab.tga" preload="true" scale.left="6" scale.top="42" scale.right="104" scale.bottom="8"/>
- <texture name="toolbar_bg.tga" preload="true" scale.left="6" scale.top="42" scale.right="96" scale.bottom="16"/>
-
- <texture name="tab_top_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9"/>
- <texture name="tab_top_selected_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9"/>
-
- <texture name="startup_logo.j2c" preload="true"/>
- <texture name="color_swatch_alpha.tga" preload="true"/>
-
- <texture name="active_voice_tab.tga"/>
- <texture name="button_anim_pause.tga"/>
- <texture name="button_anim_pause_selected.tga"/>
- <texture name="button_anim_play.tga"/>
- <texture name="button_anim_play_selected.tga"/>
- <texture name="button_anim_stop.tga"/>
- <texture name="button_anim_stop_selected.tga"/>
- <texture name="crosshairs.tga"/>
- <texture name="direction_arrow.tga"/>
- <texture name="foot_shadow.j2c" use_mips="true"/>
-
- <texture name="icon_auction.tga"/>
- <texture name="icon_avatar_offline.tga"/>
- <texture name="icon_avatar_online.tga"/>
- <texture name="icon_day_cycle.tga"/>
- <texture name="icon_diurnal.tga"/>
- <texture name="icon_event.tga"/>
- <texture name="icon_event_mature.tga"/>
- <texture name="icon_for_sale.tga"/>
- <texture name="icon_group.tga"/>
- <texture name="icon_groupnotice.tga"/>
- <texture name="icon_groupnoticeinventory.tga"/>
- <texture name="icon_lock.tga"/>
- <texture name="icon_place.tga"/>
- <texture name="icon_place_for_sale.tga"/>
- <texture name="icon_popular.tga"/>
- <texture name="icon_top_pick.tga"/>
-
- <texture name="inv_folder_animation.tga"/>
- <texture name="inv_folder_bodypart.tga"/>
- <texture name="inv_folder_callingcard.tga"/>
- <texture name="inv_folder_clothing.tga"/>
- <texture name="inv_folder_current_outfit.tga"/>
- <texture name="inv_folder_gesture.tga"/>
- <texture name="inv_folder_landmark.tga"/>
- <texture name="inv_folder_lostandfound.tga"/>
- <texture name="inv_folder_my_outfits.tga"/>
- <texture name="inv_folder_notecard.tga"/>
- <texture name="inv_folder_object.tga"/>
- <texture name="inv_folder_outfit.tga"/>
- <texture name="inv_folder_plain_closed.tga"/>
- <texture name="inv_folder_script.tga"/>
- <texture name="inv_folder_snapshot.tga"/>
- <texture name="inv_folder_sound.tga"/>
- <texture name="inv_folder_texture.tga"/>
- <texture name="inv_folder_trash.tga"/>
-
- <texture name="inv_item_animation.tga"/>
- <texture name="inv_item_skin.tga"/>
- <texture name="inv_item_callingcard_offline.tga"/>
- <texture name="inv_item_callingcard_online.tga"/>
- <texture name="inv_item_eyes.tga"/>
- <texture name="inv_item_gesture.tga"/>
- <texture name="inv_item_gloves.tga"/>
- <texture name="inv_item_hair.tga"/>
- <texture name="inv_item_jacket.tga"/>
- <texture name="inv_item_landmark.tga"/>
- <texture name="inv_item_landmark_visited.tga"/>
- <texture name="inv_item_linkitem.tga"/>
- <texture name="inv_item_linkfolder.tga"/>
- <texture name="inv_item_notecard.tga"/>
- <texture name="inv_item_object.tga"/>
- <texture name="inv_item_object_multi.tga"/>
- <texture name="inv_item_pants.tga"/>
- <texture name="inv_item_script.tga"/>
- <texture name="inv_item_shape.tga"/>
- <texture name="inv_item_shirt.tga"/>
- <texture name="inv_item_shoes.tga"/>
- <texture name="inv_item_skirt.tga"/>
- <texture name="inv_item_snapshot.tga"/>
- <texture name="inv_item_socks.tga"/>
- <texture name="inv_item_sound.tga"/>
- <texture name="inv_item_texture.tga"/>
- <texture name="inv_item_underpants.tga"/>
- <texture name="inv_item_undershirt.tga"/>
-
- <texture name="lag_status_critical.tga"/>
- <texture name="lag_status_good.tga"/>
- <texture name="lag_status_warning.tga"/>
-
- <texture name="legend.tga"/>
-
- <texture name="map_avatar_16.tga"/>
- <texture name="map_avatar_8.tga"/>
- <texture name="map_avatar_you_8.tga"/>
- <texture name="map_event.tga"/>
- <texture name="map_event_mature.tga"/>
- <texture name="map_home.tga"/>
- <texture name="map_infohub.tga"/>
- <texture name="map_telehub.tga"/>
- <texture name="map_track_16.tga"/>
+ <texture name="rounded_square_soft.tga" file_name="rounded_square_soft.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
+
+ <texture name="toolbar_tab.tga" preload="true" scale.left="6" scale.top="42" scale.right="104" scale.bottom="8" />
+ <texture name="toolbar_bg.tga" preload="true" scale.left="6" scale.top="42" scale.right="96" scale.bottom="16" />
+
+ <texture name="tab_top_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="tab_top_selected_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
+
+ <texture name="startup_logo.j2c" preload="true" />
+ <texture name="color_swatch_alpha.tga" preload="true" />
+
+ <texture name="active_voice_tab.tga" />
+ <texture name="button_anim_pause.tga" />
+ <texture name="button_anim_pause_selected.tga" />
+ <texture name="button_anim_play.tga" />
+ <texture name="button_anim_play_selected.tga" />
+ <texture name="button_anim_stop.tga" />
+ <texture name="button_anim_stop_selected.tga" />
+ <texture name="crosshairs.tga" />
+ <texture name="direction_arrow.tga" />
+ <texture name="foot_shadow.j2c" use_mips="true" />
+
+ <texture name="icon_auction.tga" />
+ <texture name="icon_avatar_offline.tga" />
+ <texture name="icon_avatar_online.tga" />
+ <texture name="icon_day_cycle.tga" />
+ <texture name="icon_diurnal.tga" />
+ <texture name="icon_event.tga" />
+ <texture name="icon_event_mature.tga" />
+ <texture name="icon_for_sale.tga" />
+ <texture name="icon_group.tga" />
+ <texture name="icon_groupnotice.tga" />
+ <texture name="icon_groupnoticeinventory.tga" />
+ <texture name="icon_place.tga" />
+ <texture name="icon_place_for_sale.tga" />
+ <texture name="icon_popular.tga" />
+ <texture name="icon_top_pick.tga" />
+
+ <texture name="inv_folder_animation.tga" />
+ <texture name="inv_folder_bodypart.tga" />
+ <texture name="inv_folder_callingcard.tga" />
+ <texture name="inv_folder_clothing.tga" />
+ <texture name="inv_folder_current_outfit.tga" />
+ <texture name="inv_folder_gesture.tga" />
+ <texture name="inv_folder_landmark.tga" />
+ <texture name="inv_folder_lostandfound.tga" />
+ <texture name="inv_folder_my_outfits.tga" />
+ <texture name="inv_folder_notecard.tga" />
+ <texture name="inv_folder_object.tga" />
+ <texture name="inv_folder_outfit.tga" />
+ <texture name="inv_folder_plain_closed.tga" />
+ <texture name="inv_folder_script.tga" />
+ <texture name="inv_folder_snapshot.tga" />
+ <texture name="inv_folder_sound.tga" />
+ <texture name="inv_folder_texture.tga" />
+ <texture name="inv_folder_trash.tga" />
+
+ <texture name="inv_item_animation.tga" />
+ <texture name="inv_item_skin.tga" />
+ <texture name="inv_item_callingcard_offline.tga" />
+ <texture name="inv_item_callingcard_online.tga" />
+ <texture name="inv_item_eyes.tga" />
+ <texture name="inv_item_gesture.tga" />
+ <texture name="inv_item_gloves.tga" />
+ <texture name="inv_item_hair.tga" />
+ <texture name="inv_item_jacket.tga" />
+ <texture name="inv_item_landmark.tga" />
+ <texture name="inv_item_landmark_visited.tga" />
+ <texture name="inv_item_linkitem.tga" />
+ <texture name="inv_item_linkfolder.tga" />
+ <texture name="inv_item_notecard.tga" />
+ <texture name="inv_item_object.tga" />
+ <texture name="inv_item_object_multi.tga" />
+ <texture name="inv_item_pants.tga" />
+ <texture name="inv_item_script.tga" />
+ <texture name="inv_item_shape.tga" />
+ <texture name="inv_item_shirt.tga" />
+ <texture name="inv_item_shoes.tga" />
+ <texture name="inv_item_skirt.tga" />
+ <texture name="inv_item_snapshot.tga" />
+ <texture name="inv_item_socks.tga" />
+ <texture name="inv_item_sound.tga" />
+ <texture name="inv_item_texture.tga" />
+ <texture name="inv_item_underpants.tga" />
+ <texture name="inv_item_undershirt.tga" />
+
+ <texture name="lag_status_critical.tga" />
+ <texture name="lag_status_good.tga" />
+ <texture name="lag_status_warning.tga" />
+
+ <texture name="legend.tga" />
+
+ <texture name="map_avatar_16.tga" />
+ <texture name="map_avatar_8.tga" />
+ <texture name="map_avatar_you_8.tga" />
+ <texture name="map_event.tga" />
+ <texture name="map_event_mature.tga" />
+ <texture name="map_home.tga" />
+ <texture name="map_infohub.tga" />
+ <texture name="map_telehub.tga" />
+ <texture name="map_track_16.tga" />
<texture name="media_icon.tga" file_name="icn_label_media.tga" />
<texture name="music_icon.tga" file_name="icn_label_music.tga" />
<texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
<texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
- <texture name="notify_tip_icon.tga"/>
- <texture name="notify_caution_icon.tga"/>
- <texture name="notify_next.png" preload="true"/>
- <texture name="notify_box_icon.tga"/>
-
- <texture name="object_cone.tga"/>
- <texture name="object_cone_active.tga"/>
- <texture name="object_cube.tga"/>
- <texture name="object_cube_active.tga"/>
- <texture name="object_cylinder.tga"/>
- <texture name="object_cylinder_active.tga"/>
- <texture name="object_grass.tga"/>
- <texture name="object_grass_active.tga"/>
- <texture name="object_hemi_cone.tga"/>
- <texture name="object_hemi_cone_active.tga"/>
- <texture name="object_hemi_cylinder.tga"/>
- <texture name="object_hemi_cylinder_active.tga"/>
- <texture name="object_hemi_sphere.tga"/>
- <texture name="object_hemi_sphere_active.tga"/>
- <texture name="object_prism.tga"/>
- <texture name="object_prism_active.tga"/>
- <texture name="object_pyramid.tga"/>
- <texture name="object_pyramid_active.tga"/>
- <texture name="object_ring.tga"/>
- <texture name="object_ring_active.tga"/>
- <texture name="object_sphere.tga"/>
- <texture name="object_sphere_active.tga"/>
- <texture name="object_tetrahedron.tga"/>
- <texture name="object_tetrahedron_active.tga"/>
- <texture name="object_torus.tga"/>
- <texture name="object_torus_active.tga"/>
- <texture name="object_tree.tga"/>
- <texture name="object_tree_active.tga"/>
- <texture name="object_tube.tga"/>
- <texture name="object_tube_active.tga"/>
-
- <texture name="pixiesmall.j2c" use_mips="true"/>
- <texture name="script_error.j2c" use_mips="true"/>
- <texture name="silhouette.j2c" use_mips="true"/>
-
- <texture name="status_no_build.tga"/>
- <texture name="status_voice.tga"/>
- <texture name="status_buy_currency.tga"/>
- <texture name="status_buy_currency_pressed.tga"/>
- <texture name="status_buy_land.tga"/>
- <texture name="status_buy_land_pressed.tga"/>
- <texture name="status_no_fly.tga"/>
- <texture name="status_health.tga"/>
- <texture name="status_no_push.tga"/>
- <texture name="status_no_scripts.tga"/>
-
- <texture name="tool_dozer.tga"/>
- <texture name="tool_dozer_active.tga"/>
- <texture name="tool_zoom.tga"/>
- <texture name="tool_zoom_active.tga"/>
-
- <texture name="icn_active-speakers-dot-lvl0.tga"/>
- <texture name="icn_active-speakers-dot-lvl1.tga"/>
- <texture name="icn_active-speakers-dot-lvl2.tga"/>
- <texture name="icn_active-speakers-typing1.tga"/>
- <texture name="icn_active-speakers-typing2.tga"/>
- <texture name="icn_active-speakers-typing3.tga"/>
-
- <texture name="icn_voice_ptt-off.tga"/>
- <texture name="icn_voice_ptt-on.tga"/>
- <texture name="icn_voice_ptt-on-lvl1.tga"/>
- <texture name="icn_voice_ptt-on-lvl2.tga"/>
- <texture name="icn_voice_ptt-on-lvl3.tga"/>
- <texture name="icn_voice-call-end.tga"/>
- <texture name="icn_voice-call-start.tga"/>
-
- <texture name="mute_icon.tga"/>
-
- <texture name="default_land_picture.j2c"/>
- <texture name="default_profile_picture.j2c"/>
- <texture name="locked_image.j2c"/>
-
- <texture name="media_btn_back.png"/>
- <texture name="media_btn_done.png"/>
- <texture name="media_btn_forward.png"/>
- <texture name="media_btn_home.png"/>
- <texture name="media_btn_newwindow.png"/>
- <texture name="media_btn_optimalzoom.png"/>
- <texture name="media_btn_reload.png"/>
- <texture name="media_btn_scrolldown.png"/>
- <texture name="media_btn_scrollleft.png"/>
- <texture name="media_btn_scrollright.png"/>
- <texture name="media_btn_scrollup.png"/>
- <texture name="media_btn_stoploading.png"/>
- <texture name="media_panel_divider.png"/>
-
- <texture name="media_floater_border_16.png" scale_top="12" scale_left="4" scale_bottom="4" scale_right="12"/>
+ <texture name="notify_tip_icon.tga" />
+ <texture name="notify_caution_icon.tga" />
+ <texture name="notify_next.png" preload="true" />
+ <texture name="notify_box_icon.tga" />
+
+ <texture name="object_cone.tga" />
+ <texture name="object_cone_active.tga" />
+ <texture name="object_cube.tga" />
+ <texture name="object_cube_active.tga" />
+ <texture name="object_cylinder.tga" />
+ <texture name="object_cylinder_active.tga" />
+ <texture name="object_grass.tga" />
+ <texture name="object_grass_active.tga" />
+ <texture name="object_hemi_cone.tga" />
+ <texture name="object_hemi_cone_active.tga" />
+ <texture name="object_hemi_cylinder.tga" />
+ <texture name="object_hemi_cylinder_active.tga" />
+ <texture name="object_hemi_sphere.tga" />
+ <texture name="object_hemi_sphere_active.tga" />
+ <texture name="object_prism.tga" />
+ <texture name="object_prism_active.tga" />
+ <texture name="object_pyramid.tga" />
+ <texture name="object_pyramid_active.tga" />
+ <texture name="object_ring.tga" />
+ <texture name="object_ring_active.tga" />
+ <texture name="object_sphere.tga" />
+ <texture name="object_sphere_active.tga" />
+ <texture name="object_tetrahedron.tga" />
+ <texture name="object_tetrahedron_active.tga" />
+ <texture name="object_torus.tga" />
+ <texture name="object_torus_active.tga" />
+ <texture name="object_tree.tga" />
+ <texture name="object_tree_active.tga" />
+ <texture name="object_tube.tga" />
+ <texture name="object_tube_active.tga" />
+
+ <texture name="pixiesmall.j2c" use_mips="true" />
+ <texture name="script_error.j2c" use_mips="true" />
+ <texture name="silhouette.j2c" use_mips="true" />
+
+ <texture name="status_no_build.tga" />
+ <texture name="status_voice.tga" />
+ <texture name="status_buy_currency.tga" />
+ <texture name="status_buy_currency_pressed.tga" />
+ <texture name="status_buy_land.tga" />
+ <texture name="status_buy_land_pressed.tga" />
+ <texture name="status_no_fly.tga" />
+ <texture name="status_health.tga" />
+ <texture name="status_no_push.tga" />
+ <texture name="status_no_scripts.tga" />
+
+ <texture name="tool_dozer.tga" />
+ <texture name="tool_dozer_active.tga" />
+ <texture name="tool_zoom.tga" />
+ <texture name="tool_zoom_active.tga" />
+
+ <texture name="icn_active-speakers-dot-lvl0.tga" />
+ <texture name="icn_active-speakers-dot-lvl1.tga" />
+ <texture name="icn_active-speakers-dot-lvl2.tga" />
+ <texture name="icn_active-speakers-typing1.tga" />
+ <texture name="icn_active-speakers-typing2.tga" />
+ <texture name="icn_active-speakers-typing3.tga" />
+
+ <texture name="icn_voice_ptt-off.tga" />
+ <texture name="icn_voice_ptt-on.tga" />
+ <texture name="icn_voice_ptt-on-lvl1.tga" />
+ <texture name="icn_voice_ptt-on-lvl2.tga" />
+ <texture name="icn_voice_ptt-on-lvl3.tga" />
+ <texture name="icn_voice-call-end.tga" />
+ <texture name="icn_voice-call-start.tga" />
+
+ <texture name="mute_icon.tga" />
+
+ <texture name="default_land_picture.j2c" />
+ <texture name="default_profile_picture.j2c" />
+ <texture name="locked_image.j2c" />
+
+ <texture name="media_btn_back.png" />
+ <texture name="media_btn_done.png" />
+ <texture name="media_btn_forward.png" />
+ <texture name="media_btn_home.png" />
+ <texture name="media_btn_newwindow.png" />
+ <texture name="media_btn_optimalzoom.png" />
+ <texture name="media_btn_reload.png" />
+ <texture name="media_btn_scrolldown.png" />
+ <texture name="media_btn_scrollleft.png" />
+ <texture name="media_btn_scrollright.png" />
+ <texture name="media_btn_scrollup.png" />
+ <texture name="media_btn_stoploading.png" />
+ <texture name="media_panel_divider.png" />
+
+ <texture name="media_floater_border_16.png" scale_top="12" scale_left="4" scale_bottom="4" scale_right="12" />
<texture name="media_panel_bg.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" />
<texture name="media_panel_hoverrectangle.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" />
diff --git a/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png
new file mode 100644
index 0000000000..350a62c0ae
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Help_Press.png b/indra/newview/skins/default/textures/windows/Icon_Help_Press.png
new file mode 100644
index 0000000000..c2d401b131
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Help_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png
new file mode 100644
index 0000000000..a164edb62d
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png b/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png
new file mode 100644
index 0000000000..990e03e2b2
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_Background.png b/indra/newview/skins/default/textures/windows/Inspector_Background.png
new file mode 100644
index 0000000000..807e8e553c
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Inspector_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_Hover.png b/indra/newview/skins/default/textures/windows/Inspector_Hover.png
new file mode 100644
index 0000000000..feeee78033
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Inspector_Hover.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml
index 38c6d44fdf..0af4e1db54 100644
--- a/indra/newview/skins/default/xui/en/floater_activeim.xml
+++ b/indra/newview/skins/default/xui/en/floater_activeim.xml
@@ -5,7 +5,7 @@
top="26"
left="0"
height="22"
- width="350"
+ width="320"
follows="right|bottom"
background_visible="true"
can_close="true"
@@ -18,13 +18,14 @@
layout="topleft"
top="20"
left="1"
- width="349"
+ width="320"
height="2"
name="panel_list_container">
<scrolling_panel_list
follows="left|right"
layout="topleft"
+ left="1"
name="chiclet_row_panel_list"
- width="335"/>
+ width="318"/>
</scroll_container>
</floater> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 824df082d8..4463d44049 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -35,14 +35,14 @@
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -331,14 +331,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -586,14 +586,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -814,14 +814,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -1002,14 +1002,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -1223,14 +1223,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -1444,14 +1444,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -1665,14 +1665,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -1886,14 +1886,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -2119,14 +2119,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -2340,14 +2340,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -2561,14 +2561,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -2782,14 +2782,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -3003,14 +3003,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
@@ -3305,14 +3305,14 @@ scratch and wear it.
width="389">
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="333"
mouse_opaque="true"
name="square"
top="5"
- width="16" />
+ width="18" />
<icon
height="16"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
index 8babbaa273..744d434982 100644
--- a/indra/newview/skins/default/xui/en/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -65,6 +65,30 @@
<text
type="string"
length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SansSerifHuge"
+ font.style.="BOLD"
+ height="32"
+ layout="topleft"
+ left="16">
+ SansSerifHuge style=BOLD
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SansSerifBold"
+ font.size="Huge"
+ height="32"
+ layout="topleft"
+ left="16">
+ SansSerifBold size=Huge
+ </text>
+ <text
+ type="string"
+ length="1"
bottom_delta="40"
follows="left|top|right"
font="Monospace"
@@ -311,6 +335,7 @@
left="16">
Helvetica size=Large style=BOLD|ITALIC
</text>
+<!--
<text
type="string"
length="1"
@@ -333,4 +358,5 @@
left="16">
BogusFontName
</text>
+-->
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 37c6cbf391..e94ca1b30b 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -25,6 +25,8 @@
Fetched
</floater.string>
<filter_editor
+ search_button_visible="false"
+ text_pad_left="12"
follows="left|top|right"
height="16"
label="Type here to search"
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
index 467168ebd8..10bcee7c85 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
@@ -29,14 +29,14 @@
</floater.string>
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="294"
mouse_opaque="true"
name="IconLocked"
top="5"
- width="16" />
+ width="18" />
<text
type="string"
length="1"
@@ -410,7 +410,7 @@
width="330">
Mark Item:
</text-->
-
+
<!--radio_group
draw_border="false"
@@ -438,7 +438,7 @@
top_delta="0"
width="70" />
</radio_group-->
-
+
<!--text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index afc72a78a9..28b8139bfd 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -7,6 +7,7 @@
min_width="467"
name="floater_about"
save_rect="true"
+ single_instance="true"
title="Media Browser"
width="820">
<floater.string
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
index 90711e3acc..0f6504c875 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
@@ -76,7 +76,7 @@
height="40"
layout="topleft"
left_delta="84"
- name="desc"
+ name="desc2"
top_delta="-4"
width="180" />
@@ -116,17 +116,17 @@
<panel
class="floater_snapshot_capture"
filename="floater_snapshot_Info.xml"
- name="snapshot_capture_tab"/>
+ name="snapshot_capture_panel"/>
</accordion_tab>
<accordion_tab
min_height="100"
title="Permissions"
- name="snapshot_capture_tab"
+ name="snapshot_capture_tab2"
can_resize="false">
<panel
class="floater_snapshot_capture"
filename="floater_snapshot_Permissions.xml"
- name="snapshot_capture_tab"/>
+ name="snapshot_capture_panel2"/>
</accordion_tab>
</accordion>
<!--check_box
@@ -164,7 +164,7 @@
label="Cancel (not working)"
layout="topleft"
left_pad="5"
- name="save_btn"
+ name="cancel_btn"
top_delta="0"
width="80" />
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index a767b40b03..3e2045e1f7 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -29,14 +29,14 @@
</floater.string>
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="340"
mouse_opaque="true"
name="lock"
top="1"
- width="16" />
+ width="18" />
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index fcbc27a5f9..0da1e42986 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
- height="590"
+ height="600"
layout="topleft"
name="floater_report_abuse"
title="Report Abuse"
- width="390">
+ width="305">
<floater.string
name="Screenshot">
Screenshot
@@ -15,27 +15,28 @@
follows="left|top"
height="114"
layout="topleft"
- left="238"
+ left="10"
name="screenshot"
- top="36"
+ top="25"
width="134" />
<check_box
height="16"
label="Include screenshot"
layout="topleft"
- left="13"
+ left_pad="10"
name="screen_check"
- top="134"
+ top="110"
width="116" />
<text
type="string"
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
- left_delta="3"
+ left="10"
name="reporter_title"
- top_delta="-102"
+ top_pad="12"
width="50">
Reporter:
</text>
@@ -48,7 +49,7 @@
left_pad="12"
name="reporter_field"
top_delta="0"
- width="150">
+ width="193">
Loremipsum Dolorsitamut
</text>
<text
@@ -56,10 +57,11 @@
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
- left="16"
+ left="10"
name="sim_title"
- top="48"
+ top_pad="5"
width="60">
Region:
</text>
@@ -72,7 +74,7 @@
left_pad="2"
name="sim_field"
top_delta="0"
- width="120">
+ width="193">
Region Name
</text>
<text
@@ -80,10 +82,11 @@
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
- left="16"
+ left="10"
name="pos_title"
- top="64"
+ top_pad="5"
width="50">
Position:
</text>
@@ -96,18 +99,18 @@
left_pad="12"
name="pos_field"
top_delta="0"
- width="120">
+ width="193">
{128.1, 128.1, 15.4}
</text>
- <text
+ <text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
- left="16"
+ left="10"
name="select_object_label"
- top="82"
+ top_pad="5"
width="220">
Click the button then the object:
</text>
@@ -118,15 +121,16 @@
name="pick_btn"
picture_style="true"
tool_tip="Object Picker - Identify an object as the subject of this report"
- top_delta="14"
+ top_pad="0"
width="32" />
<text
type="string"
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
- left_pad="5"
+ left="48"
name="object_name_label"
top_delta="0"
width="60">
@@ -141,7 +145,7 @@
left_pad="6"
name="object_name"
top_delta="0"
- width="109">
+ width="157">
Consetetur Sadipscing
</text>
<text
@@ -149,10 +153,11 @@
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
- left="53"
+ left="48"
name="owner_name_label"
- top="112"
+ top_pad="5"
width="60">
Owner:
</text>
@@ -165,17 +170,17 @@
left_pad="6"
name="owner_name"
top_delta="0"
- width="109">
+ width="157">
Hendrerit Vulputate
- </text>
+ </text>
<combo_box
height="20"
layout="topleft"
- left="16"
+ left="10"
name="category_combo"
tool_tip="Category -- select the category that best describes this report"
- top="156"
- width="356">
+ top_pad="10"
+ width="265">
<combo_box.item
label="Select category"
name="Select_category"
@@ -338,156 +343,161 @@
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
left_delta="0"
name="abuser_name_title"
- top_pad="10"
- width="180">
+ top_pad="12"
+ width="265">
Abuser name:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="left|top"
- height="16"
+ height="20"
layout="topleft"
left_delta="0"
max_length="32"
name="abuser_name_edit"
top_pad="2"
- width="180" />
+ width="170" />
<button
height="20"
- label="Choose Resident"
+ font="SansSerifSmall"
+ label="Choose"
layout="topleft"
- left_pad="10"
+ left_pad="5"
name="select_abuser"
tool_tip="Select the name of the abuser from a list"
- top_delta="-2"
- width="160" />
+ top_delta="0"
+ width="90" />
<check_box
- height="16"
+ height="20"
label="Don&apos;t know abuser&apos;s name"
layout="topleft"
- left="13"
+ left="10"
name="omit_abuser_name"
tool_tip="Check this if you are unable to provide the abuser&apos;s name"
- top="224"
+ top_pad="2"
visible="false"
- width="116" />
+ width="250" />
<text
type="string"
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
left_delta="3"
name="abuser_name_title2"
- top_pad="8"
- width="180">
+ top_pad="10"
+ width="265">
Location of Abuse:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="left|top"
- height="16"
+ height="20"
layout="topleft"
- left_delta="0"
+ left="10"
max_length="256"
name="abuse_location_edit"
top_pad="2"
- width="356" />
+ width="265" />
<text
type="string"
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
left_delta="0"
name="sum_title"
- top_pad="8"
- width="180">
+ top_pad="10"
+ width="265">
Summary:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="left|top"
- height="16"
+ height="20"
layout="topleft"
left_delta="0"
max_length="64"
name="summary_edit"
top_pad="2"
- width="356" />
+ width="265" />
<text
type="string"
length="1"
follows="left|top"
height="16"
+ font.style="BOLD"
layout="topleft"
left_delta="0"
name="dscr_title"
- top_pad="8"
- width="180">
+ top_pad="10"
+ width="50">
Details:
</text>
<text
type="string"
length="1"
follows="left|top"
- height="48"
+ height="16"
layout="topleft"
- left_delta="54"
+ left_pad="5"
name="bug_aviso"
top_delta="0"
- width="308">
- Please be specific about the date, location, nature of
-abuse, relevant chat/IM text, and select the object
-if possible.
+ width="200">
+ Please be as specific as possible.
</text>
<text_editor
follows="left|top"
- height="146"
+ height="50"
layout="topleft"
- left="16"
+ left="10"
max_length="800"
mouse_opaque="false"
name="details_edit"
- top="386"
- width="356"
+ top_pad="2"
+ width="265"
word_wrap="true" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
+ height="50"
layout="topleft"
left_delta="0"
+ font.style="BOLD"
name="incomplete_title"
top_pad="8"
- width="342">
+ word_wrap="true"
+ width="265">
Note: Incomplete reports will not be investigated.
</text>
<button
- bottom="580"
+ bottom="590"
follows="right|bottom"
height="20"
label="Cancel"
label_selected="Cancel"
layout="topleft"
name="cancel_btn"
- right="373"
- width="150" />
+ right="275"
+ width="130" />
<button
- bottom="580"
+ bottom="590"
follows="right|bottom"
height="20"
label="Report Abuse"
label_selected="Report Abuse"
layout="topleft"
name="send_btn"
- right="217"
- width="150" />
+ right="140"
+ width="130" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml
index cb3ff92363..ef68478460 100644
--- a/indra/newview/skins/default/xui/en/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml
@@ -26,14 +26,14 @@
width="497" />
<icon
follows="top|right"
- height="16"
- image_name="icon_lock.tga"
+ height="18"
+ image_name="Lock"
layout="topleft"
left="444"
mouse_opaque="true"
name="lock"
top="3"
- width="16" />
+ width="18" />
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml
index 46c8960fbd..76b2e5c811 100644
--- a/indra/newview/skins/default/xui/en/floater_sys_well.xml
+++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml
@@ -1,19 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater
- background_opaque="false"
- background_visible="true"
bevel_style="in"
- bg_alpha_color="0.0 0.0 0.0 0.0"
- height="30"
left="0"
top="0"
follows="right|bottom"
layout="topleft"
name="notification_chiclet"
save_rect="true"
- title="NOTIFICATIONS"
+ title="NOTIFICATIONS"
width="320"
min_width="320"
+ height="60"
can_minimize="false"
can_tear_off="false"
can_resize="false"
@@ -21,20 +18,36 @@
can_close="false"
can_dock="true"
>
- <scroll_container
- follows="top|bottom"
- layout="topleft"
- name="notification_list_container"
- left="0"
- top="18"
- width="320"
- height="12">
- <scrolling_panel_list
- layout="topleft"
- name="notification_list"
- left="1"
- top="0"
- height="10"
- width="318" />
- </scroll_container>
+ <scroll_container
+ follows="top|bottom"
+ layout="topleft"
+ name="notification_list_container"
+ left="0"
+ top="18"
+ width="320"
+ height="42">
+ <panel
+ layout="topleft"
+ name="twin_list_panel"
+ left="1"
+ top="0"
+ width="318"
+ height="32"
+ bg_alpha_color="1.0 1.0 1.0 1.0">
+ <scrolling_panel_list
+ layout="topleft"
+ name="notification_list"
+ left="1"
+ top="0"
+ height="0"
+ width="318"/>
+ <scrolling_panel_list
+ layout="topleft"
+ name="im_row_panel_list"
+ left="1"
+ top="2"
+ height="0"
+ width="318"/>
+ </panel>
+</scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
new file mode 100644
index 0000000000..b23bf49435
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_inspectors"
+ title="Test Inspectors"
+ width="400">
+ <text
+ height="20"
+ left="10"
+ name="test_inspectors"
+ top="30"
+ width="300">
+ Click to spawn an inspector:
+ </text>
+ <!-- James Tester, 4 years old -->
+ <button
+ name="avatar_2d_btn1"
+ label="Avatar 2D"
+ top="50"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="22df1dcb-810a-4975-aab9-0159958fe155" />
+ <!-- DonkeyPuncher 2008-10-1 -->
+ <button
+ name="avatar_2d_btn5"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="d5330e4e-391a-4f00-9352-b797ed2f9a97" />
+ <!-- DonkeyPuncher 2009-01-15 -->
+ <button
+ name="avatar_2d_btn2"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="05511655-a58a-48b6-b645-966f69fc17a7" />
+ <!-- 2009-06-14 -->
+ <button
+ name="avatar_2d_btn3"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="6a164b3d-7c2c-43eb-880a-0ebc0687b3ec" />
+ <!-- jarvtest Bombastic 2009-10-3 -->
+ <button
+ name="avatar_2d_btn4"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="e7dc3c83-1e11-4fa7-beeb-4b18adfb4efa" />
+ <button
+ name="avatar_3d_btn"
+ label="Avatar 3D"
+ top="50"
+ left="150"
+ height="20"
+ width="100"/>
+ <button
+ name="object_2d_btn"
+ label="Object 2D"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="object_3d_btn"
+ label="Object 3D"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="group_btn"
+ label="Group"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="place_btn"
+ label="Place"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="event_btn"
+ label="Event"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 51e4d15e5d..e373da300c 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
follows="left|top|right"
- height="615"
+ height="570"
layout="topleft"
name="toolbox floater"
save_rect="true"
@@ -27,7 +27,7 @@
</floater.string>
<floater.string
name="status_camera">
- Click and drag to change view
+ Click and drag to move camera
</floater.string>
<floater.string
name="status_grab">
@@ -224,35 +224,27 @@
left="10"
follows="left|top"
control_name="EditLinkedParts"
- label="Edit linked prims"
+ label="Edit linked"
layout="topleft"
name="checkbox edit linked parts" />
- <text
- left="10"
- type="string"
- length="1"
- follows="left|top"
- layout="topleft"
- name="text ruler mode">
- Ruler:
- </text>
<combo_box
height="19"
- left="30"
+ left="10"
layout="topleft"
follows="left|top"
+ top_pad="0"
name="combobox grid mode"
- width="90">
+ width="120">
<combo_box.item
- label="World"
+ label="World ruler"
name="World"
value="World" />
<combo_box.item
- label="Local"
+ label="Local ruler"
name="Local"
value="Local" />
<combo_box.item
- label="Reference"
+ label="Reference ruler"
name="Reference"
value="Reference" />
</combo_box>
@@ -263,7 +255,7 @@
layout="topleft"
left="143"
name="checkbox uniform"
- top="54"
+ top="50"
width="134" />
<check_box
control_name="ScaleStretchTextures"
@@ -272,28 +264,28 @@
label="Stretch Textures"
layout="topleft"
name="checkbox stretch textures"
- top_pad="1"
+ top_pad="0"
width="134" />
<check_box
control_name="SnapEnabled"
height="19"
initial_value="true"
- label="Use Grid"
+ label="Snap to Grid"
layout="topleft"
name="checkbox snap to grid"
- top_pad="1"
+ top_pad="0"
width="134" />
<button
- follows="left|top"
- font="SansSerifSmall"
- height="19"
- left_delta="40"
- top_delta="20"
- label="Options..."
- label_selected="Options..."
+ left="163"
+ top_pad="0"
+ image_overlay="Arrow_Right_Off"
+ picture_style="true"
+ label_selected="Options"
layout="topleft"
name="Options..."
- width="78" />
+ tool_tip="Set the Grid Options"
+ width="26"
+ height="22" />
<button
follows="left|top"
height="24"
@@ -605,7 +597,7 @@
top_delta="15"
width="114" />
</radio_group>
-
+
<text
type="string"
length="1"
@@ -680,7 +672,7 @@
type="string"
text_color="LabelSelectedDisabledColor"
length="1"
- top_pad="7"
+ top_pad="4"
height="12"
follows="left|top"
halign="right"
@@ -722,7 +714,7 @@
top="16">
<panel.string
name="text deed continued">
- Deed...
+ Deed
</panel.string>
<panel.string
name="text deed">
@@ -776,7 +768,7 @@
layout="topleft"
left="10"
name="Name:"
- top_pad="8"
+ top="0"
width="90">
Name:
</text>
@@ -789,7 +781,7 @@
name="Object Name"
select_on_focus="true"
top_delta="0"
- width="172" />
+ width="165" />
<text
type="string"
length="1"
@@ -811,8 +803,7 @@
name="Object Description"
select_on_focus="true"
top_delta="0"
- width="172" />
-
+ width="165" />
<text
type="string"
left="10"
@@ -833,21 +824,9 @@
height="19"
layout="topleft"
name="Creator Name"
- width="150">
- Thrax Linden
+ width="175">
+ Esbee Linden
</text>
-<!--TODO: Kill this-->
-<!-- <button
- follows="top|right"
- font="SansSerifSmall"
- height="19"
- label="Profile..."
- label_selected="Profile..."
- layout="topleft"
- left_pad="6"
- name="button creator profile"
- tool_tip="View creator profile"
- width="78" />-->
<text
type="string"
length="1"
@@ -868,21 +847,9 @@
layout="topleft"
name="Owner Name"
left_pad="0"
- width="150">
- Thrax Linden
+ width="175">
+ Erica Linden
</text>
-<!--TODO: Kill this-->
-<!--<button
- follows="top|right"
- font="SansSerifSmall"
- height="19"
- label="Profile..."
- label_selected="Profile..."
- layout="topleft"
- left_pad="6"
- name="button owner profile"
- tool_tip="View owner profile"
- width="78" />-->
<text
type="string"
length="1"
@@ -891,40 +858,39 @@
left="10"
height="19"
name="Group:"
- width="90">
+ width="70">
Group:
</text>
<name_box
- follows="left|top|right"
+ follows="left|top"
height="19"
initial_value="Loading..."
layout="topleft"
left_pad="0"
name="Group Name Proxy"
- width="170" />
+ width="159" />
+ <button
+ follows="left|top"
+ left_pad="0"
+ image_overlay="Arrow_Right_Off"
+ picture_style="true"
+ layout="topleft"
+ name="button set group"
+ tool_tip="Choose a group to share this object's permissions"
+ width="26"
+ height="22" />
<button
- follows="top|right"
+ follows="top|left"
font="SansSerifSmall"
height="19"
- label="Deed..."
- label_selected="Deed..."
+ label="Deed"
+ label_selected="Deed"
layout="topleft"
name="button deed"
top_pad="0"
- left="102"
+ left="80"
tool_tip="Deeding gives this item away with Next Owner permissions. Group shared objects can be deeded by a group officer."
- width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="19"
- label="Set..."
- label_selected="Set..."
- layout="topleft"
- left_pad="7"
- name="button set group"
- tool_tip="Choose a group to share this object's permissions"
- width="80" />
+ width="90" />
<check_box
height="19"
follows="left|top"
@@ -932,18 +898,18 @@
layout="topleft"
name="checkbox share with group"
tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
- left="100"
+ left_pad="5"
width="93" />
<text
type="string"
length="1"
follows="left|top"
- height="19"
+ height="16"
layout="topleft"
- top_pad="7"
+ top_pad="15"
left="10"
name="label click action"
- width="90">
+ width="100">
Click to:
</text>
<combo_box
@@ -951,7 +917,7 @@
height="22"
layout="topleft"
name="clickaction"
- width="170"
+ width="155"
left_pad="0">
<combo_box.item
label="Touch (default)"
@@ -973,23 +939,15 @@
label="Open"
name="Open"
value="Open" />
-<!--TODO: Kill this-->
-<!-- <combo_box.item
- label="Play parcel media"
- name="Play"
- value="Play" />
- <combo_box.item
- label="Open parcel media"
- name="Opemmedia"
- value="Open Media" />-->
</combo_box>
<check_box
- height="20"
+ height="16"
+ top_pad="15"
label="For Sale:"
layout="topleft"
name="checkbox for sale"
left="10"
- width="90" />
+ width="100" />
<!-- NEW SALE TYPE COMBO BOX -->
<combo_box
left_pad="0"
@@ -997,19 +955,22 @@
follows="left|top"
allow_text_entry="false"
height="22"
- width="170"
+ width="155"
max_chars="20"
mouse_opaque="true"
name="sale type"
intial_value="2">
- <combo_item
- label="Copy"
+ <combo_box.item
+ name="Copy"
+ label="Copy"
value="2" />
- <combo_item
- label="Contents"
+ <combo_box.item
+ name="Contents"
+ label="Contents"
value="3" />
- <combo_item
- label="Original"
+ <combo_box.item
+ name="Original"
+ label="Original"
value="1" />
</combo_box>
<!-- NEW PRICE SPINNER -->
@@ -1017,118 +978,55 @@
follows="left|top"
decimal_digits="0"
increment="1"
+ top_pad="10"
control_name="Edit Cost"
name="Edit Cost"
label="Price: L$"
label_width="60"
- width="170"
+ width="155"
min_val="1"
height="19"
max_val="999999999" />
- <panel
+ <check_box
+ left="107"
+ height="15"
+ width="100"
+ label="Show in search"
+ layout="topleft"
+ name="search_check"
+ tool_tip="Let people see this object in search results"
+ />
+<panel
border="false"
- follows="left|top|right"
+ follows="left|top"
layout="topleft"
mouse_opaque="false"
background_visible="true"
bg_alpha_color="FloaterUnfocusBorderColor"
name="perms_build"
left="0"
- height="140"
+ top="240"
+ height="120"
width="280">
<text
type="string"
length="1"
left="10"
- top_pad="6"
- height="19"
+ top_pad="10"
+ text_color="EmphasisColor"
+ height="16"
follows="left|top|right"
layout="topleft"
name="perm_modify"
- width="180">
+ width="250">
You can modify this object
</text>
<text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- top_pad="0"
- follows="left|top"
- layout="topleft"
- left="17"
- name="B:"
- width="30">
- B:
- </text>
- <text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- follows="left|top"
- layout="topleft"
- left_pad="0"
- name="O:"
- width="30">
- O:
- </text>
- <text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- follows="left|top"
- layout="topleft"
- left_pad="0"
- name="G:"
- width="30">
- G:
- </text>
- <text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- follows="left|top"
- left_pad="0"
- layout="topleft"
- name="E:"
- width="30">
- E:
- </text>
- <text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- follows="left|top"
- layout="topleft"
- left_pad="0"
- name="N:"
- width="30">
- N:
- </text>
- <text
- type="string"
- text_color="LabelSelectedDisabledColor"
- length="1"
- follows="left|top"
- layout="topleft"
- left_pad="0"
- name="F:"
- width="30">
- F:
- </text>
- <check_box
- left="15"
- height="19"
- label="Show in search"
- layout="topleft"
- name="search_check"
- tool_tip="Let people see this object in search results"
- />
- <text
type="string"
follows="left|top"
name="Anyone can:"
width="250"
- top_pad="7"
+ top_pad="5"
left="10">
Anyone:
</text>
@@ -1145,13 +1043,20 @@
layout="topleft"
left_pad="0"
name="checkbox allow everyone copy"
- width="260" />
+ width="90" />
+ <check_box
+ height="19"
+ label="Use"
+ layout="topleft"
+ left_pad="0"
+ name="allow everyone to use"
+ width="90" />
<text
type="string"
follows="left|top"
height="19"
name="Next owner can:"
- width="270"
+ width="250"
left="10">
Next owner:
</text>
@@ -1180,192 +1085,134 @@
top_delta="0"
tool_tip="Next owner can give away or resell this object"
width="90" />
- </panel>
-<!--TODO: KILL THIS-->
-<!--<text
+ <text
type="string"
+ text_color="EmphasisColor_35"
length="1"
+ top_pad="5"
follows="left|top"
- height="19"
layout="topleft"
- left_pad="12"
- name="Cost"
- top_delta="0"
- width="78">
- Price: L$
+ left="18"
+ name="B:"
+ height="10"
+ width="30">
+ B:
</text>
- <line_editor
- follows="left|top|right"
- height="19"
+ <text
+ type="string"
+ text_color="EmphasisColor_35"
+ length="1"
+ follows="left|top"
layout="topleft"
left_pad="0"
- max_length="25"
- name="Edit Cost"
- top_delta="0"
- width="75" />-->
-<!--TODO: KILL THIS-->
-<!--<radio_group
- follows="left|top|right"
- height="19"
- left="15"
- layout="topleft"
- name="sale type"
- width="218">
- <radio_item
- height="19"
- label="Original"
- layout="topleft"
- left="0"
- name="Original"
- top="0"
- width="70" />
- <radio_item
- height="19"
- label="Copy"
- layout="topleft"
- left_delta="70"
- name="Copy"
- top_delta="0"
- width="70" />
- <radio_item
- height="19"
- label="Contents"
- layout="topleft"
- left_delta="70"
- name="Contents"
- top_delta="0"
- width="76" />
- </radio_group>-->
- </panel>
- <panel
- border="false"
- follows="left|top|right|bottom"
- height="367"
- label="Object"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="Object"
- top_delta="0"
- width="280">
+ name="O:"
+ height="10"
+ width="30">
+ O:
+ </text>
<text
type="string"
+ text_color="EmphasisColor_35"
length="1"
follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="G:"
height="10"
+ width="30">
+ G:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor_35"
+ length="1"
+ follows="left|top"
+ left_pad="0"
layout="topleft"
- left="10"
- name="select_single"
- top="10"
- width="252">
- Select only one primitive to edit parameters.
+ name="E:"
+ height="10"
+ width="30">
+ E:
</text>
<text
type="string"
+ text_color="EmphasisColor_35"
length="1"
follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="N:"
height="10"
+ width="30">
+ N:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor_35"
+ length="1"
+ follows="left|top"
layout="topleft"
- left_delta="0"
- name="edit_object"
- top_delta="0"
- width="252">
- Edit object parameters:
+ left_pad="0"
+ name="F:"
+ height="10"
+ width="30">
+ F:
</text>
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ follows="left|top|right|bottom"
+ height="367"
+ label="Object"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="Object"
+ top="16"
+ width="280">
<check_box
height="19"
label="Locked"
layout="topleft"
- left_delta="-2"
name="checkbox locked"
tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits."
- top_pad="10"
+ top_pad="5"
+ left="10"
width="123" />
<check_box
height="19"
label="Physical"
layout="topleft"
- left_delta="0"
name="Physical Checkbox Ctrl"
tool_tip="Allows object to be pushed and affected by gravity"
- top_pad="2"
+ top_pad="0"
width="123" />
<check_box
height="19"
label="Temporary"
layout="topleft"
- left_delta="0"
name="Temporary Checkbox Ctrl"
tool_tip="Causes object to be deleted 1 minute after creation."
- top_pad="2"
+ top_pad="0"
width="123" />
<check_box
height="19"
label="Phantom"
layout="topleft"
- left_delta="0"
name="Phantom Checkbox Ctrl"
tool_tip="Causes object to not collide with other objects or avatars"
- top_pad="2"
+ top_pad="0"
width="123" />
-
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- name="label material"
- top_pad="9"
- width="121">
- Material
- </text>
- <combo_box
- height="19"
- layout="topleft"
- left_delta="0"
- name="material"
- top_pad="4"
- width="95">
- <combo_box.item
- label="Stone"
- name="Stone"
- value="Stone" />
- <combo_box.item
- label="Metal"
- name="Metal"
- value="Metal" />
- <combo_box.item
- label="Glass"
- name="Glass"
- value="Glass" />
- <combo_box.item
- label="Wood"
- name="Wood"
- value="Wood" />
- <combo_box.item
- label="Flesh"
- name="Flesh"
- value="Flesh" />
- <combo_box.item
- label="Plastic"
- name="Plastic"
- value="Plastic" />
- <combo_box.item
- label="Rubber"
- name="Rubber"
- value="Rubber" />
- </combo_box>
+
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
- left_delta="2"
name="label position"
- top_pad="8"
+ top_pad="10"
width="121">
Position (meters)
</text>
@@ -1381,7 +1228,7 @@
max_val="512"
min_val="-256"
name="Pos X"
- text_enabled_color="0.43 0.06 0.06 1"
+ text_enabled_color="1 0 0.3 .7"
top_pad="5"
width="87" />
<spinner
@@ -1396,7 +1243,7 @@
max_val="512"
min_val="-256"
name="Pos Y"
- text_enabled_color="0 0.39 0.15 1"
+ text_enabled_color="EmphasisColor"
top_pad="3"
width="87" />
<spinner
@@ -1410,7 +1257,7 @@
left_delta="0"
max_val="4096"
name="Pos Z"
- text_enabled_color="0 0.26 0.51 1"
+ text_enabled_color="0 0.8 1 .65"
top_pad="3"
width="87" />
<text
@@ -1530,8 +1377,8 @@
text_enabled_color="1 1 1 1"
top_pad="3"
width="87" />
-
- <text
+
+ <!-- <text
type="string"
length="1"
follows="left|top"
@@ -1539,16 +1386,16 @@
layout="topleft"
left="125"
name="label basetype"
- top="26"
+ top="5"
width="150">
- Building Block Type
- </text>
+ Prim Type
+ </text>-->
<combo_box
height="19"
layout="topleft"
- left_delta="0"
name="comboBaseType"
- top_pad="4"
+ top="5"
+ left="125"
width="150">
<combo_box.item
label="Box"
@@ -1583,6 +1430,41 @@
name="Sculpted"
value="Sculpted" />
</combo_box>
+ <combo_box
+ height="19"
+ layout="topleft"
+ name="material"
+ top_pad="0"
+ width="150">
+ <combo_box.item
+ label="Stone"
+ name="Stone"
+ value="Stone" />
+ <combo_box.item
+ label="Metal"
+ name="Metal"
+ value="Metal" />
+ <combo_box.item
+ label="Glass"
+ name="Glass"
+ value="Glass" />
+ <combo_box.item
+ label="Wood"
+ name="Wood"
+ value="Wood" />
+ <combo_box.item
+ label="Flesh"
+ name="Flesh"
+ value="Flesh" />
+ <combo_box.item
+ label="Plastic"
+ name="Plastic"
+ value="Plastic" />
+ <combo_box.item
+ label="Rubber"
+ name="Rubber"
+ value="Rubber" />
+ </combo_box>
<text
type="string"
length="1"
@@ -1593,11 +1475,11 @@
name="text cut"
top_pad="6"
width="150">
- Path Cut Begin and End
+ Path Cut (begin/end)
</text>
<spinner
follows="left|top"
- height="19"
+ height="16"
increment="0.025"
initial_value="0"
label="B"
@@ -1610,7 +1492,7 @@
width="68" />
<spinner
follows="left|top"
- height="19"
+ height="16"
increment="0.025"
initial_value="1"
label="E"
@@ -1629,7 +1511,7 @@
layout="topleft"
left="125"
name="text hollow"
- top_pad="6"
+ top_pad="5"
width="68">
Hollow
</text>
@@ -1641,7 +1523,6 @@
layout="topleft"
left_pad="10"
name="text skew"
- top_delta="0"
width="63">
Skew
</text>
@@ -1678,7 +1559,7 @@
layout="topleft"
left="125"
name="Hollow Shape"
- top_pad="6"
+ top_pad="0"
width="150">
Hollow Shape
</text>
@@ -1714,9 +1595,9 @@
layout="topleft"
left_delta="0"
name="text twist"
- top_pad="4"
+ top_pad="8"
width="150">
- Twist Begin and End
+ Twist (begin/end)
</text>
<spinner
decimal_digits="0"
@@ -1808,7 +1689,7 @@
layout="topleft"
left="125"
name="text topshear"
- top_pad="6"
+ top_pad="3"
width="141">
Top Shear
</text>
@@ -1850,9 +1731,9 @@
layout="topleft"
left="125"
name="advanced_cut"
- top_pad="6"
+ top_pad="3"
width="150">
- Profile Cut Begin and End
+ Profile Cut (begin/end)
</text>
<text
type="string"
@@ -1864,7 +1745,7 @@
name="advanced_dimple"
top_delta="0"
width="150">
- Dimple Begin and End
+ Dimple (begin/end)
</text>
<text
type="string"
@@ -1876,7 +1757,7 @@
name="advanced_slice"
top_delta="0"
width="150">
- Slice Begin and End
+ Slice (begin/end)
</text>
<spinner
follows="left|top"
@@ -1889,7 +1770,7 @@
left_delta="0"
max_val="0.95"
name="Path Limit Begin"
- top_pad="4"
+ top_pad="3"
width="68" />
<spinner
follows="left|top"
@@ -1912,7 +1793,7 @@
layout="topleft"
left="125"
name="text taper2"
- top_pad="6"
+ top_pad="3"
width="150">
Taper
</text>
@@ -1928,7 +1809,7 @@
left_delta="0"
min_val="-1"
name="Taper X"
- top_pad="4"
+ top_pad="3"
width="68" />
<spinner
decimal_digits="2"
@@ -1952,7 +1833,7 @@
layout="topleft"
left="125"
name="text radius delta"
- top_pad="6"
+ top_pad="0"
width="78">
Radius
</text>
@@ -1964,7 +1845,6 @@
layout="topleft"
left_delta="78"
name="text revolutions"
- top_delta="0"
width="68">
Revolutions
</text>
@@ -2087,7 +1967,7 @@
layout="topleft"
left="10"
name="select_single"
- top="10"
+ top="5"
width="252">
Select only one primitive to edit features.
</text>
@@ -2097,9 +1977,9 @@
follows="left|top"
height="10"
layout="topleft"
- left_delta="0"
+ left="10"
name="edit_object"
- top_delta="0"
+ top="5"
width="252">
Edit object features:
</text>
@@ -2107,7 +1987,7 @@
height="19"
label="Flexible Path"
layout="topleft"
- left_delta="0"
+ left="10"
name="Flexible1D Checkbox Ctrl"
tool_tip="Allows object to flex about the Z axis. (Client-side only)"
top_pad="10"
@@ -2221,60 +2101,50 @@
top_pad="4"
width="128" />
<check_box
- height="19"
+ height="16"
label="Light"
layout="topleft"
- left_delta="0"
+ left="10"
name="Light Checkbox Ctrl"
tool_tip="Causes object to emit light"
- top_pad="14"
- width="121" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- name="label color"
top_pad="15"
- width="58">
- Color
- </text>
+ width="60" />
<color_swatch
- border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
+ bevel_style="none"
+ border_style="line"
color="0.5 0.5 0.5 1"
+ border.border_thickness="0"
follows="left|top"
- height="48"
+ height="50"
layout="topleft"
- left_delta="67"
+ left_pad="10"
+ top_pad="-17"
name="colorswatch"
tool_tip="Click to open Color Picker"
- top_delta="-10"
- width="32" />
+ width="40" />
<spinner
follows="left|top"
height="19"
initial_value="0.5"
label="Intensity"
- label_width="65"
+ label_width="70"
layout="topleft"
- left="10"
+ left_pad="15"
name="Light Intensity"
- top_pad="4"
+ top_pad="-50"
width="128" />
<spinner
follows="left|top"
height="19"
initial_value="5"
label="Radius"
- label_width="65"
+ label_width="70"
layout="topleft"
left_delta="0"
max_val="20"
name="Light Radius"
- top_pad="0"
+ top_pad="3"
width="128" />
<spinner
follows="left|top"
@@ -2282,12 +2152,12 @@
increment="0.25"
initial_value="1"
label="Falloff"
- label_width="65"
+ label_width="70"
layout="topleft"
left_delta="0"
max_val="2"
name="Light Falloff"
- top_pad="0"
+ top_pad="3"
width="128" />
</panel>
<panel
@@ -2396,16 +2266,16 @@
left="10"
name="tex gen"
top_pad="10"
- width="90">
+ width="87">
Mapping
</text>
<combo_box
- height="19"
+ height="22"
layout="topleft"
left_delta="0"
name="combobox texgen"
top_pad="4"
- width="80">
+ width="87">
<combo_box.item
label="Default"
name="Default"
@@ -2421,19 +2291,19 @@
follows="left|top"
height="10"
layout="topleft"
- left="100"
name="label shininess"
- top_pad="-33"
- width="70">
+ left_pad="5"
+ top_pad="-36"
+ width="80">
Shininess
</text>
<combo_box
- height="19"
+ height="22"
layout="topleft"
left_delta="0"
name="combobox shininess"
top_pad="4"
- width="70">
+ width="80">
<combo_box.item
label="None"
name="None"
@@ -2457,19 +2327,19 @@
follows="left|top"
height="10"
layout="topleft"
- left="180"
+ left_pad="5"
name="label bumpiness"
- top_pad="-33"
- width="80">
+ top_pad="-36"
+ width="87">
Bumpiness
</text>
<combo_box
- height="19"
+ height="22"
layout="topleft"
left_delta="0"
name="combobox bumpiness"
top_pad="4"
- width="80">
+ width="87">
<combo_box.item
label="None"
name="None"
@@ -2552,7 +2422,7 @@
left="10"
name="tex scale"
top_pad="15"
- width="160">
+ width="200">
Repeats per Face
</text>
<spinner
@@ -2647,13 +2517,12 @@
<button
follows="left|top"
font="SansSerifSmall"
- height="19"
+ height="22"
label="Apply"
label_selected="Apply"
layout="topleft"
left_pad="10"
name="button apply"
- top_delta="-4"
width="75" />
<text
type="string"
@@ -2664,8 +2533,8 @@
left="10"
name="tex offset"
top_pad="20"
- width="160">
- Offset
+ width="200">
+ Texture Offset
</text>
<spinner
follows="left|top"
@@ -2717,10 +2586,9 @@
top="340"
width="68" />-->
</panel>
- <panel
+ <panel
border="false"
follows="left|top|right|bottom"
- height="367"
label="Content"
layout="topleft"
left_delta="0"
@@ -2730,34 +2598,33 @@
width="280">
<button
follows="left|top"
- height="19"
+ height="22"
label="New Script"
- label_selected="New Script..."
+ label_selected="New Script"
layout="topleft"
left="10"
name="button new script"
top="10"
- width="100" />
+ width="120" />
<button
follows="left|top"
- height="19"
- label="Permissions..."
+ height="22"
+ label="Permissions"
layout="topleft"
- left_pad="10"
+ left_pad="8"
name="button permissions"
- top_delta="0"
- width="100" />
+ width="130" />
<panel_inventory
follows="left|top"
- height="300"
+ height="310"
layout="topleft"
left="10"
name="contents_inventory"
- top="35"
+ top="50"
width="260" />
</panel>
- </tab_container>
- <panel
+ </tab_container>
+ <panel
follows="left|top"
height="384"
layout="topleft"
@@ -2765,7 +2632,7 @@
name="land info panel"
top_delta="0"
width="280">
- <text
+ <text
type="string"
length="1"
font="SansSerifBig"
@@ -2804,9 +2671,9 @@
</text>
<button
follows="left|top"
- height="19"
- label="About Land..."
- label_selected="About Land..."
+ height="22"
+ label="Land profile"
+ label_selected="Land profile"
layout="topleft"
left_delta="0"
name="button about land"
@@ -2819,19 +2686,17 @@
layout="topleft"
left_delta="0"
name="checkbox show owners"
- tool_tip="Colour parcels according to their ownership"
+ tool_tip="Colorize the parcels according to the type of owner"
top_pad="8"
- width="140" />
+ width="205" />
<button
- follows="left|top"
- height="19"
- label="?"
- label_selected="?"
- layout="topleft"
+ image_overlay="Arrow_Right_Off"
+ picture_style="true"
left_pad="5"
name="button show owners help"
- top_delta="-2"
- width="18" />
+ tool_tip="See an explanation of colors"
+ width="26"
+ height="22" />
<text
type="string"
length="1"
@@ -2847,9 +2712,9 @@
</text>
<button
follows="left|top"
- height="19"
- label="Subdivide..."
- label_selected="Subdivide..."
+ height="22"
+ label="Subdivide"
+ label_selected="Subdivide"
layout="topleft"
left="30"
name="button subdivide land"
@@ -2857,9 +2722,9 @@
width="112" />
<button
follows="left|top"
- height="19"
- label="Join..."
- label_selected="Join..."
+ height="22"
+ label="Join"
+ label_selected="Join"
layout="topleft"
left_delta="0"
name="button join land"
@@ -2880,9 +2745,9 @@
</text>
<button
follows="left|top"
- height="19"
- label="Buy Land..."
- label_selected="Buy Land..."
+ height="22"
+ label="Buy Land"
+ label_selected="Buy Land"
layout="topleft"
left="30"
name="button buy land"
@@ -2891,8 +2756,8 @@
<button
follows="left|top"
height="19"
- label="Abandon Land..."
- label_selected="Abandon Land..."
+ label="Abandon Land"
+ label_selected="Abandon Land"
layout="topleft"
left_delta="0"
name="button abandon land"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index ced8ba83f7..dec9839d1a 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -2,7 +2,7 @@
<fonts>
<font name="default" comment="default font files (global fallbacks)">
- <file>DejaVuSansCondensed.ttf</file>
+ <file>DejaVuSans.ttf</file>
<os name="Windows">
<file>MSGOTHIC.TTC</file>
<file>gulim.ttc</file>
@@ -18,28 +18,45 @@
</os>
</font>
- <font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
- <file>Helvetica.dfont</file>
- <os name="Windows">
- <file>arial.ttf</file>
+ <font name="SansSerifBold"
+ comment="Name of bold sans-serif font">
+ <file>DejaVuSans-Bold.ttf</file>
+ <os name="Windows">
+ <file>arialbd.ttf</file>
</os>
<os name="Mac">
<file>Helvetica.dfont</file>
</os>
</font>
- <font name="SansSerifBold"
- comment="Name of bold sans-serif font"
- font_style="Bold">
- <file>Helvetica.dfont</file>
+ <font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
+ <file>DejaVuSans.ttf</file>
<os name="Windows">
- <file>arialbd.ttf</file>
+ <file>arial.ttf</file>
</os>
<os name="Mac">
<file>Helvetica.dfont</file>
</os>
</font>
+ <font name="SansSerif"
+ comment="Name of bold sans-serif font"
+ font_style="BOLD">
+ <file>DejaVuSans-Bold.ttf</file>
+ </font>
+
+ <font name="SansSerif"
+ comment="Name of italic sans-serif font"
+ font_style="ITALIC">
+ <file>DejaVuSans-Oblique.ttf</file>
+ </font>
+
+ <font name="SansSerif"
+ comment="Name of bold italic sans-serif font"
+ font_style="BOLD|ITALIC">
+ <file>DejaVuSans-BoldOblique.ttf</file>
+ </font>
+
<font name="Monospace"
comment="Name of monospace font">
<file>DejaVuSansMono.ttf</file>
@@ -53,47 +70,72 @@
<font name="DejaVu"
comment="Name of DejaVu font (bold)"
font_style="BOLD">
- <file>DejaVuSansBold.ttf</file>
+ <file>DejaVuSans-Bold.ttf</file>
</font>
<font name="DejaVu"
comment="Name of DejaVu font (italic)"
font_style="ITALIC">
- <file>DejaVuSansOblique.ttf</file>
+ <file>DejaVuSans-Oblique.ttf</file>
</font>
<font name="DejaVu"
comment="Name of DejaVu font (bold italic)"
font_style="BOLD|ITALIC">
- <file>DejaVuSansBoldOblique.ttf</file>
+ <file>DejaVuSans-BoldOblique.ttf</file>
</font>
<font name="Helvetica"
comment="Name of Helvetica font">
- <file>arial.ttf</file>
+ <file>DejaVuSans.ttf</file>
+ <os name="Windows">
+ <file>arial.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arial.ttf</file>
+ </os>
</font>
<font name="Helvetica"
comment="Name of Helvetica font (bold)"
font_style="BOLD">
- <file>arialbd.ttf</file>
+ <file>DejaVuSans-Bold.ttf</file>
+ <os name="Windows">
+ <file>arialbd.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arialbd.ttf</file>
+ </os>
</font>
<font name="Helvetica"
comment="Name of Helvetica font (italic)"
font_style="ITALIC">
- <file>ariali.ttf</file>
+ <file>DejaVuSans-Oblique.ttf</file>
+ <os name="Windows">
+ <file>ariali.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>ariali.ttf</file>
+ </os>
</font>
<font name="Helvetica"
comment="Name of Helvetica font (bold italic)"
font_style="BOLD|ITALIC">
- <file>arialbi.ttf</file>
+ <file>DejaVuSans-BoldOblique.ttf</file>
+ <os name="Windows">
+ <file>arialbi.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arialbi.ttf</file>
+ </os>
</font>
<font name="OverrideTest"
comment="Name of font to test overriding">
<file>times.ttf</file>
+ <file>DejaVuSans.ttf</file>
</font>
<font_size name="Monospace"
@@ -106,15 +148,15 @@
/>
<font_size name="Large"
comment="Size of large font (points, or 1/72 of an inch)"
- size="12.0"
+ size="10.0"
/>
<font_size name="Medium"
comment="Size of medium font (points, or 1/72 of an inch)"
- size="10.0"
+ size="9.0"
/>
<font_size name="Small"
comment="Size of small font (points, or 1/72 of an inch)"
- size="9"
+ size="8.0"
/>
</fonts>
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index cee789d435..f908e9d610 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -1,14 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
-<!-- No title to avoid window chrome -->
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
<floater
background_opaque="false"
background_visible="true"
bevel_style="in"
- bg_alpha_color="black"
+ bg_alpha_color="PanelDefaultBackgroundColor"
+ can_close="false"
can_minimize="false"
name="inspect_avatar"
+ single_instance="true"
+ sound_flags="0"
title=""
visible="true"
width="300"
@@ -16,28 +22,39 @@
left="0"
top="200"
>
+ <!-- Allowed fields include:
+ [BORN_ON] ("12/3/2008")
+ [SL_PROFILE] (Second Life profile),
+ [RW_PROFILE] (real world profile),
+ [ACCTTYPE] ("Resident"),
+ [PAYMENTINFO] ("Payment Info on File"),
+ [AGE] ("1 year 2 months") -->
+ <string name="Subtitle">
+[AGE]
+ </string>
+ <string name="Details">
+[ACCTTYPE], [PAYMENTINFO]
+Profile: [SL_PROFILE]
+ </string>
<text
- top="180" left="10" width="220" height="70" follows="left|top|right|bottom"
+ top="180" left="10" width="280" height="70" follows="left|top|right|bottom"
use_ellipses="true" word_wrap="true"
font="SansSerifHugeBold" text_color="white"
mouse_opaque="true" name="user_name" >
- Codex Linden
+ Test Name
</text>
+ <!-- General purpose subtitle area, not sure yet what goes here -->
<text
top="155" left="10" width="150" height="20" follows="left|top|right|bottom"
- font="SansSerifBig" font.style="UNDERLINE"
+ font="SansSerifBig"
text_color="white"
mouse_opaque="true"
- name="active_group" >
- The Guild
- </text>
+ name="user_subtitle" />
+ <!-- Leave text fields blank so it doesn't flash when data arrives off the network -->
<text
- top="110" left="10" width="290" height="50" follows="left|top|right|bottom"
+ top="115" left="10" width="290" height="50" follows="left|top|right|bottom"
font="SansSerifSmall" text_color="white" word_wrap="true"
- mouse_opaque="true" name="user_detail" >
-3 year-old account, Payment info on file
-Languages: English, Spanish; +5 Sexterity Vest
- </text>
+ mouse_opaque="true" name="user_details" />
<avatar_icon
top="185" left="230" width="60" height="60" follows="left|top|right|bottom"
color="1 1 1 1" enabled="true" mouse_opaque="true" name="avatar_icon"
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 1e911c2664..8a2955654e 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -97,18 +97,20 @@
layout="topleft"
name="Widget Test"
shortcut="control|shift|T">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="test_widgets" />
- </menu_item_call>
- <menu_item_call
- label="Avatar Inspector"
- name="Avatar Inspector"
- shortcut="control|shift|I">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="inspect_avatar" />
- </menu_item_call>
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="test_widgets" />
+ </menu_item_call>
+ <menu_item_call
+ label="Inspectors Test"
+ name="inspectors_test"
+ shortcut="control|shift|I"
+ >
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="test_inspectors" />
+ </menu_item_call>
+ <menu_item_separator />
<menu_item_call
label="Show TOS"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index bb5a4e51f7..6ef1eb9513 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -15,4 +15,8 @@
<menu_item_call name="organize_offline" label="Organize Offline Friends">
<menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
</menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" />
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
index 8c2c5e8c9e..2b0f029016 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -15,4 +15,8 @@
<menu_item_call name="view_icons" label="View People Icons">
<menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
</menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
index 00cf443cc6..88b0528e53 100644
--- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -12,4 +12,8 @@
<menu_item_call name="view_icons" label="View People Icons">
<menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
</menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml
new file mode 100644
index 0000000000..463a9fccb6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Resident Profile"
+ layout="topleft"
+ name="show_agent">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Name To Clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_group.xml b/indra/newview/skins/default/xui/en/menu_url_group.xml
new file mode 100644
index 0000000000..cec0aa421e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_group.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Group Information"
+ layout="topleft"
+ name="show_group">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Group To Clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_http.xml b/indra/newview/skins/default/xui/en/menu_url_http.xml
new file mode 100644
index 0000000000..2503b4a2a3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_http.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Open Web Page"
+ layout="topleft"
+ name="url_open">
+ <menu_item_call.on_click
+ function="Url.Open" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Open in Internal Browser"
+ layout="topleft"
+ name="url_open_internal">
+ <menu_item_call.on_click
+ function="Url.OpenInternal" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open in External Browser"
+ layout="topleft"
+ name="url_open_external">
+ <menu_item_call.on_click
+ function="Url.OpenExternal" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy URL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
new file mode 100644
index 0000000000..7d09403b15
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Object Information"
+ layout="topleft"
+ name="show_object">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Teleport to Object Location"
+ layout="topleft"
+ name="teleport_to_object">
+ <menu_item_call.on_click
+ function="Url.Teleport" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Object Name To Clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_parcel.xml b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
new file mode 100644
index 0000000000..bbd63c6d8c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Parcel Information"
+ layout="topleft"
+ name="show_parcel">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_slapp.xml b/indra/newview/skins/default/xui/en/menu_url_slapp.xml
new file mode 100644
index 0000000000..19df721b2b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_slapp.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Run This Command"
+ layout="topleft"
+ name="run_slapp">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_slurl.xml b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
new file mode 100644
index 0000000000..0e9525fa4b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Place Information"
+ layout="topleft"
+ name="show_place">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Teleport to Location"
+ layout="topleft"
+ name="teleport_to_location">
+ <menu_item_call.on_click
+ function="Url.Teleport" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_teleport.xml b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
new file mode 100644
index 0000000000..22cc035e49
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Teleport To This Location"
+ layout="topleft"
+ name="teleport">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLURL To Clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ef9e22d908..9306f83dde 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -229,7 +229,7 @@
function="Floater.Toggle"
parameter="communicate" />
</menu_item_check>
- <menu_item_call
+ <menu_item_call
label="(Temp) Media Remote Ctrl"
layout="topleft"
name="Preferences"
@@ -284,6 +284,44 @@
function="Floater.Show"
parameter="region_info" />
</menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Land Options"
+ layout="topleft"
+ name="Land"
+ tear_off="true">
+ <menu_item_check
+ label="Show Property Lines"
+ layout="topleft"
+ name="Property Lines"
+ shortcut="control|alt|shift|P">
+ <menu_item_check.on_check
+ control="ShowPropertyLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowPropertyLines" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Land Owners"
+ layout="topleft"
+ name="Land Owners">
+ <menu_item_check.on_check
+ control="ShowParcelOwners" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowParcelOwners" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Ban Lines"
+ layout="topleft"
+ name="Ban Lines">
+ <menu_item_check.on_check
+ control="ShowBanLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowBanLines" />
+ </menu_item_check>
+ </menu>
<menu_item_separator
layout="topleft" />
<menu
@@ -351,7 +389,7 @@
shortcut="control|shift|M">
<menu_item_check.on_check
function="Floater.Visible"
- parameter="mini_map" />
+ parameter="mini_map" />
<menu_item_check.on_click
function="Floater.Toggle"
parameter="mini_map" />
@@ -369,7 +407,7 @@
</menu_item_call>
<menu_item_separator
layout="topleft" />
- <menu
+ <menu
create_jump_keys="true"
label="Sun Settings"
layout="topleft"
@@ -430,87 +468,78 @@
</menu>
<menu_item_separator
layout="topleft" />
- <menu_item_check
- label="Build"
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Build"
+ layout="topleft"
+ name="BuildTools"
+ tear_off="true"
+ visible="true">
+ <menu_item_check
+ label="Show Build Tools"
layout="topleft"
- name="Build"
- shortcut="B">
+ name="Show Build Tools"
+ shortcut="control|B">
<menu_item_check.on_check
function="Build.Active" />
<menu_item_check.on_click
function="Build.Toggle" />
<menu_item_check.on_enable
function="Build.Enabled" />
- </menu_item_check>
- </menu>
- <menu
- label="Help"
- layout="topleft"
- name="Help"
- tear_off="true">
- <menu_item_call
- label="[SECOND_LIFE] Help"
- layout="topleft"
- name="Second Life Help"
- shortcut="F1">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="help f1" />
- </menu_item_call>
- <menu_item_call
- label="Tutorial"
- layout="topleft"
- name="Tutorial">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="hud" />
- </menu_item_call>
- <menu_item_check
- label="Show Quick Tips"
- layout="topleft"
- name="Show Quick Tips">
- <menu_item_check.on_check
- function="Help.CheckShowFirstTimeTip" />
- <menu_item_check.on_click
- function="Help.ShowQuickTips" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Report Bug..."
- layout="topleft"
- name="ReportBug">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="ReportBug_url"
- parameter="hud,http://help.secondlife.com/en/bugreport/" />
- </menu_item_call>
- <menu_item_call
- label="Report Abuse..."
- layout="topleft"
- name="Report Abuse">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="complaint reporter" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="About [APP_NAME]"
- layout="topleft"
- name="About Second Life">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="sl_about" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Tools"
- layout="topleft"
- name="BuildTools"
- tear_off="true"
- visible="false">
+ </menu_item_check>
+ <menu
+ create_jump_keys="true"
+ label="Select Build Tool"
+ layout="topleft"
+ name="Select Tool"
+ tear_off="true">
+ <menu_item_call
+ label="Focus Tool"
+ layout="topleft"
+ name="Focus"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="focus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Move Tool"
+ layout="topleft"
+ name="Move"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="move" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Tool"
+ layout="topleft"
+ name="Edit"
+ shortcut="control|3">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Tool"
+ layout="topleft"
+ name="Create"
+ shortcut="control|4">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="create" />
+ </menu_item_call>
+ <menu_item_call
+ label="Land Tool"
+ layout="topleft"
+ name="Land"
+ shortcut="control|5">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="land" />
+ </menu_item_call>
+ </menu>
<menu
create_jump_keys="true"
label="Edit"
@@ -612,6 +641,159 @@
function="Edit.EnableDeselect" />
</menu_item_call>
</menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Link"
+ layout="topleft"
+ name="Link"
+ shortcut="control|L">
+ <menu_item_call.on_click
+ function="Tools.Link" />
+ <menu_item_call.on_enable
+ function="Tools.EnableLink" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unlink"
+ layout="topleft"
+ name="Unlink"
+ shortcut="control|shift|L">
+ <menu_item_call.on_click
+ function="Tools.Unlink" />
+ <menu_item_call.on_enable
+ function="Tools.EnableUnlink" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Focus on Selection"
+ layout="topleft"
+ name="Focus on Selection"
+ shortcut="H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="focus" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom to Selection"
+ layout="topleft"
+ name="Zoom to Selection"
+ shortcut="shift|H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Object"
+ layout="topleft"
+ name="Object"
+ tear_off="true">
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ name="Menu Object Take"
+ visible="true">
+ <menu_item_call.on_click
+ function="Tools.BuyOrTake" />
+ <menu_item_call.on_enable
+ function="Tools.EnableBuyOrTake"
+ name="EnableBuyOrTake"
+ parameter="Buy,Take" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="Take Copy">
+ <menu_item_call.on_click
+ function="Tools.TakeCopy" />
+ <menu_item_call.on_enable
+ function="Tools.EnableTakeCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to My Inventory"
+ layout="topleft"
+ name="Save Object Back to My Inventory">
+ <menu_item_call.on_click
+ function="Tools.SaveToInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToInventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to Object Contents"
+ layout="topleft"
+ name="Save Object Back to Object Contents">
+ <menu_item_call.on_click
+ function="Tools.SaveToObjectInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToObjectInventory" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Scripts"
+ layout="topleft"
+ name="Scripts"
+ tear_off="true">
+ <menu_item_call
+ label="Recompile Scripts (Mono)"
+ layout="topleft"
+ name="Mono">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile mono" />
+ <menu_item_call.on_enable
+ function="EditableSelectedMono" />
+ </menu_item_call>
+ <menu_item_call
+ label="Recompile Scripts (LSL)"
+ layout="topleft"
+ name="LSL">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile lsl" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Scripts"
+ layout="topleft"
+ name="Reset Scripts">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="reset" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Running"
+ layout="topleft"
+ name="Set Scripts to Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="start" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Not Running"
+ layout="topleft"
+ name="Set Scripts to Not Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="stop" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
<menu
create_jump_keys="true"
label="Options"
@@ -800,196 +982,68 @@
parameter="CheesyBeacon" />
</menu_item_check>
</menu>
- <menu
- create_jump_keys="true"
- label="Land"
- layout="topleft"
- name="Land"
- tear_off="true">
- <menu_item_check
- label="Property Lines"
- layout="topleft"
- name="Property Lines"
- shortcut="control|alt|shift|P">
- <menu_item_check.on_check
- control="ShowPropertyLines" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowPropertyLines" />
- </menu_item_check>
- <menu_item_check
- label="Land Owners"
- layout="topleft"
- name="Land Owners">
- <menu_item_check.on_check
- control="ShowParcelOwners" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowParcelOwners" />
- </menu_item_check>
- <menu_item_check
- label="Ban Lines"
- layout="topleft"
- name="Ban Lines">
- <menu_item_check.on_check
- control="ShowBanLines" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowBanLines" />
- </menu_item_check>
- </menu>
</menu>
- <menu
- create_jump_keys="true"
- label="Actions"
+ </menu>
+ <menu
+ label="Help"
+ layout="topleft"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="[SECOND_LIFE] Help"
layout="topleft"
- name="Actions"
- tear_off="true">
- <menu_item_call
- label="Link"
- layout="topleft"
- name="Link"
- shortcut="control|L">
- <menu_item_call.on_click
- function="Tools.Link" />
- <menu_item_call.on_enable
- function="Tools.EnableLink" />
- </menu_item_call>
- <menu_item_call
- label="Unlink"
- layout="topleft"
- name="Unlink"
- shortcut="control|shift|L">
- <menu_item_call.on_click
- function="Tools.Unlink" />
- <menu_item_call.on_enable
- function="Tools.EnableUnlink" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Focus on Selection"
- layout="topleft"
- name="Focus on Selection"
- shortcut="H">
- <menu_item_call.on_click
- function="Tools.LookAtSelection"
- parameter="focus" />
- <menu_item_call.on_enable
- function="Tools.SomethingSelectedNoHUD" />
- </menu_item_call>
- <menu_item_call
- label="Zoom to Selection"
- layout="topleft"
- name="Zoom to Selection"
- shortcut="shift|H">
- <menu_item_call.on_click
- function="Tools.LookAtSelection"
- parameter="zoom" />
- <menu_item_call.on_enable
- function="Tools.SomethingSelectedNoHUD" />
- </menu_item_call>
- <menu_item_separator
+ name="Second Life Help"
+ shortcut="F1">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="help f1" />
+ </menu_item_call>
+ <menu_item_call
+ label="Tutorial"
+ layout="topleft"
+ name="Tutorial">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="hud" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show Quick Tips"
+ layout="topleft"
+ name="Show Quick Tips">
+ <menu_item_check.on_check
+ function="Help.CheckShowFirstTimeTip" />
+ <menu_item_check.on_click
+ function="Help.ShowQuickTips" />
+ </menu_item_check>
+ <menu_item_separator
layout="topleft" />
- <menu_item_call
- label="Buy Object"
- layout="topleft"
- name="Menu Object Take"
- visible="false">
- <menu_item_call.on_click
- function="Tools.BuyOrTake" />
- <menu_item_call.on_enable
- function="Tools.EnableBuyOrTake"
- name="EnableBuyOrTake"
- parameter="Buy,Take" />
- </menu_item_call>
- <menu_item_call
- label="Take Copy"
- layout="topleft"
- name="Take Copy">
- <menu_item_call.on_click
- function="Tools.TakeCopy" />
- <menu_item_call.on_enable
- function="Tools.EnableTakeCopy" />
- </menu_item_call>
- <menu_item_call
- label="Save Object Back to My Inventory"
+ <menu_item_call
+ label="Report Bug..."
layout="topleft"
- name="Save Object Back to My Inventory">
- <menu_item_call.on_click
- function="Tools.SaveToInventory" />
- <menu_item_call.on_enable
- function="Tools.EnableSaveToInventory" />
- </menu_item_call>
- <menu_item_call
- label="Save Object Back to Object Contents"
+ name="ReportBug">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="ReportBug_url"
+ parameter="hud,http://help.secondlife.com/en/bugreport/" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report Abuse..."
layout="topleft"
- name="Save Object Back to Object Contents">
+ name="Report Abuse">
<menu_item_call.on_click
- function="Tools.SaveToObjectInventory" />
- <menu_item_call.on_enable
- function="Tools.EnableSaveToObjectInventory" />
+ function="ShowFloater"
+ parameter="complaint reporter" />
</menu_item_call>
- <menu_item_separator
+ <menu_item_separator
layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Recompile Scripts in Selection"
- layout="topleft"
- name="Recompile Scripts in Selection"
- tear_off="true">
- <menu_item_call
- label="Mono"
- layout="topleft"
- name="Mono">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="compile mono" />
- <menu_item_call.on_enable
- function="EditableSelectedMono" />
- </menu_item_call>
- <menu_item_call
- label="LSL"
- layout="topleft"
- name="LSL">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="compile lsl" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- </menu>
- <menu_item_call
- label="Reset Scripts in Selection"
- layout="topleft"
- name="Reset Scripts in Selection">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="reset" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- <menu_item_call
- label="Set Scripts to Running in Selection"
- layout="topleft"
- name="Set Scripts to Running in Selection">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="start" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- <menu_item_call
- label="Set Scripts to Not Running in Selection"
- layout="topleft"
- name="Set Scripts to Not Running in Selection">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="stop" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- </menu>
+ <menu_item_call
+ label="About [APP_NAME]"
+ layout="topleft"
+ name="About Second Life">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="sl_about" />
+ </menu_item_call>
</menu>
<menu
label="Advanced"
@@ -1035,7 +1089,6 @@
function="World.AlwaysRun" />
</menu_item_check>
<menu_item_check
- control_name="FlyBtnState"
label="Fly"
layout="topleft"
name="Fly"
@@ -1451,6 +1504,17 @@
</menu_item_check>
<menu_item_separator
layout="topleft" />
+ <menu_item_check
+ label="Avatar Rendering Cost"
+ layout="topleft"
+ name="Avatar Rendering Cost">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shame" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shame" />
+ </menu_item_check>
<menu
create_jump_keys="true"
label="Rendering Types"
@@ -1827,7 +1891,7 @@
function="Advanced.ShowDebugSettings"
parameter="all" />
</menu_item_call>
- <menu_item_check
+ <menu_item_check
label="Debug (QA) Mode"
layout="topleft"
name="Debug Mode"
@@ -2210,8 +2274,7 @@
<menu_item_check
label="View Admin Options"
layout="topleft"
- name="View Admin Options"
- shortcut="control|alt|V">
+ name="View Admin Options">
<menu_item_check.on_check
function="Advanced.CheckViewAdminOptions"
parameter="ViewAdminOptions" />
@@ -2497,7 +2560,7 @@
name="Simple Web Browser Test">
<menu_item_call.on_click
function="Floater.Show"
- parameter="html_simple.http://www.secondlife.com" />
+ parameter="html_simple.http://www.secondlife.com" />
</menu_item_call>
<menu_item_call
label="UI/Color Settings"
@@ -2666,7 +2729,7 @@
name="Show Font Test">
<menu_item_call.on_click
function="Floater.Show"
- parameter="font_test" />
+ parameter="font_test" />
</menu_item_call>
<menu_item_call
label="Load from XML..."
@@ -2699,14 +2762,13 @@
<menu_item_call.on_click
function="Advanced.SendTestIMs" />
</menu_item_call>
- <!-- *HACK: Hard code James Tester's UUID -->
<menu_item_call
- label="Avatar Inspector"
- name="Avatar Inspector"
+ label="Test Inspectors"
+ name="Test Inspectors"
shortcut="control|shift|I">
<menu_item_call.on_click
- function="Advanced.AvatarInspector"
- parameter="22df1dcb-810a-4975-aab9-0159958fe155" />
+ function="Floater.Show"
+ parameter="test_inspectors" />
</menu_item_call>
</menu>
<menu
@@ -3144,7 +3206,7 @@
name="God Tools">
<menu_item_call.on_click
function="Floater.Show"
- parameter="god_tools" />
+ parameter="god_tools" />
<menu_item_call.on_enable
function="EnableGodCustomerService" />
</menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 98c9ec868a..7ede45a080 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4495,7 +4495,7 @@ Link to this from a web page to give others easy access to this location, or try
icon="alertmodal.tga"
name="GraphicsPreferencesHelp"
type="alertmodal">
-This panel controls window size and resolution and the quality of the client&apos;s graphics. The Preferences &gt; Graphics interface allows you to choose between four graphics levels: Low, Mid, High, and Ultra. You may also customize your graphics settings by checking the Custom checkbox and manipulating the following settings:
+This panel controls window size and resolution and the quality of the client&apos;s graphics. The Preferences &gt; Graphics interface allows you to choose between four graphics levels: Low, Mid, High, and Ultra. You may also customize your graphics settings by clicking the Advanced button and manipulating the following settings:
Shaders: Enable or disable various types of pixel shaders.
@@ -5029,7 +5029,7 @@ You must have payment information on file to visit this area. Do you want to go
icon="alertmodal.tga"
name="MissingString"
type="alertmodal">
-How odd. The string [STRING_NAME] is missing from strings.xml
+The string [STRING_NAME] is missing from strings.xml
</notification>
<notification
@@ -6495,10 +6495,10 @@ Click Accept to join the chat or Decline to decline the invitation. Click Block
<notification
icon="notifytip.tga"
- name="UnableToOpenCommandURL"
+ name="UnsupportedCommandSLURL"
priority="high"
type="notifytip">
- The link you clicked cannot be opened from this web browser.
+ The SLurl you clicked on is not supported.
</notification>
<notification name="IMToast" type="notifytoast">
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 8977f30a51..4dc4a9ff46 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -1,47 +1,62 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel
- follows="bottom|right"
+<panel
name="panel_activeim_row"
layout="topleft"
+ follows="left|right"
top="0"
left="0"
- height="40"
- width="332"
+ height="35"
+ width="318"
background_visible="true"
bevel_style="in"
bg_alpha_color="0 0 0 0">
- <chiclet_im
- name="chiclet"
+ <chiclet_im_p2p
+ name="p2p_chiclet"
layout="topleft"
- top="4"
- left="10"
- height="26"
+ follows="left"
+ top="5"
+ left="5"
+ height="25"
width="45">
- </chiclet_im>
+ </chiclet_im_p2p>
+ <chiclet_im_group
+ name="group_chiclet"
+ layout="topleft"
+ follows="left"
+ top="5"
+ left="5"
+ height="25"
+ width="45">
+ </chiclet_im_group>
<text
type="string"
name="contact_name"
layout="topleft"
top="8"
- left="70"
- height="20"
- width="230"
+ left_pad="6"
+ height="28"
+ width="235"
length="1"
- follows="left|top|right|bottom"
- font="SansSerifBigBold"
- text_color="White">Contact Name</text>
- <button
- name="hide_btn"
- layout="topleft"
- top="10"
- left="310"
- height="20"
- width="20"
- label=""
- image_unselected="toast_hide_btn.tga"
- image_disabled="toast_hide_btn.tga"
- image_selected="toast_hide_btn.tga"
- image_hover_selected="toast_hide_btn.tga"
- image_disabled_selected="toast_hide_btn.tga">
- </button>
+ follows="right|left"
+ font="SansSerifBold"
+ text_color="White">
+ Contact Name
+ </text>
+ <button
+ top="5"
+ left_pad="5"
+ width="15"
+ height="15"
+ layout="topleft"
+ follows="right"
+ name="hide_btn"
+ mouse_opaque="true"
+ label=""
+ tab_stop="false"
+ image_unselected="toast_hide_btn.tga"
+ image_disabled="toast_hide_btn.tga"
+ image_selected="toast_hide_btn.tga"
+ image_hover_selected="toast_hide_btn.tga"
+ image_disabled_selected="toast_hide_btn.tga"
+ />
</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index 3de3365539..f211ae0ad6 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -1,65 +1,89 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<!-- All our XML is utf-8 encoded. -->
-
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- name="avatar_list_item"
- title="avatar_list_item"
- visible="true"
- width="314"
- height="30"
- left="0"
- top="100"
- follows="bottom|right|left"
- min_width="150"
- max_height="30"
-
- background_opaque="false"
- background_visible="true"
- bevel_style="in"
- bg_alpha_color="0.3 0.3 0.3 1.0">
-
- <avatar_icon
- bottom="5" left="5" width="20" height="20" follows="top|left"
- color="1 1 1 1" enabled="true" image_name="smile.png"
- mouse_opaque="true" name="avatar_icon"
- />
-
- <text
- bottom="4" left="35" width="160" height="20" follows="right|left"
- font="SansSerifBigBold" text_color="white"
- mouse_opaque="true" name="user_name" >
- Boris Linden
- </text>
-
- <text
- bottom="3" left="190" width="40" height="20" follows="right"
- font="SansSerif" text_color="0.5 0.5 0.5 1.0"
- mouse_opaque="true" name="user_status" >
- Away
- </text>
-
- <icon
- bottom="5" left="230" width="20" height="20" follows="right"
- color="1 1 1 1" enabled="true" image_name="speaking_indicator.tga"
- mouse_opaque="true" name="locator"
- />
-
- <button
- bottom="5" left="260" width="20" height="20" follows="right"
- name="info_btn" label=""
- image_unselected="avatar_info_btn.tga" image_disabled="avatar_info_btn.tga"
- image_selected="avatar_info_btn_active.tga" image_hover_selected="avatar_info_btn_active.tga"
- image_disabled_selected="avatar_info_btn.tga" font="SansSerifBigBold"
- />
-
- <button
- bottom="5" left="290" width="20" height="20" follows="right"
- name="profile_btn" label=""
- image_unselected="profile_chevron_btn.tga" image_disabled="profile_chevron_btn.tga"
- image_selected="profile_chevron_btn_active.tga" image_hover_selected="profile_chevron_btn_active.tga"
- image_disabled_selected="profile_chevron_btn.tga" font="SansSerifBigBold"
- />
-
-
-
-</panel>
+ follows="top|right|left"
+ height="24"
+ layout="topleft"
+ left="0"
+ name="avatar_list_item"
+ top="0"
+ width="320">
+ <icon
+ follows="top|right|left"
+ height="24"
+ image_name="ListItem_Over"
+ layout="topleft"
+ left="0"
+ name="hovered_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <icon
+ height="24"
+ follows="top|right|left"
+ image_name="ListItem_Select"
+ layout="topleft"
+ left="0"
+ name="selected_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <avatar_icon
+ follows="top|left"
+ height="20"
+ image_name="smile.png"
+ layout="topleft"
+ left="5"
+ mouse_opaque="true"
+ top="2"
+ width="20" />
+ <text
+ follows="left|right"
+ font="SansSerifBigBold"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ name="avatar_name"
+ text_color="white"
+ top="4"
+ use_ellipses="true"
+ value="Unknown"
+ width="180" />
+ <text
+ follows="right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="avatar_status"
+ text_color="0.5 0.5 0.5 1"
+ value="Away"
+ width="50" />
+ <output_monitor
+ auto_update="true"
+ follows="right"
+ draw_border="false"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ mouse_opaque="true"
+ name="speaking_indicator"
+ top="4"
+ visible="true"
+ width="20" />
+ <button
+ follows="right"
+ font="SansSerifBigBold"
+ height="18"
+ image_disabled="Info"
+ image_disabled_selected="Info"
+ image_hover_selected="Info"
+ image_selected="Info"
+ image_unselected="Info"
+ layout="topleft"
+ left_pad="2"
+ name="info_btn"
+ picture_style="true"
+ top="2"
+ width="18" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..5c8a8ee208
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="left|top|right|bottom"
+ height="305"
+ layout="topleft"
+ name="block_list_panel"
+ min_height="350"
+ min_width="240"
+ width="280">
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="title_text"
+ text_color="white"
+ top="0"
+ width="250">
+ Blocked List
+ </text>
+ <button
+ follows="top|right"
+ height="25"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back"
+ right="-9"
+ tab_stop="false"
+ top="0"
+ width="25"/>
+ <scroll_list
+ follows="left|top|right|bottom"
+ height="200"
+ layout="topleft"
+ left="5"
+ name="blocked"
+ tool_tip="List of currently blocked residents"
+ top="30"
+ width="270" />
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Block Resident..."
+ label_selected="Block Resident..."
+ layout="topleft"
+ left_delta="0"
+ name="Block resident..."
+ tool_tip="Pick a resident to block"
+ top_pad="4"
+ width="210">
+ <button.commit_callback
+ function="Block.ClickPick" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Block object by name..."
+ label_selected="Block object by name..."
+ layout="topleft"
+ left_delta="0"
+ name="Block object by name..."
+ top_pad="4"
+ width="210" >
+ <button.commit_callback
+ function="Block.ClickBlockByName" />
+ </button>
+ <button
+ enabled="false"
+ follows="left|bottom"
+ height="20"
+ label="Unblock"
+ label_selected="Unblock"
+ layout="topleft"
+ left_delta="0"
+ name="Unblock"
+ tool_tip="Remove resident or object from blocked list"
+ top_pad="4"
+ width="210" >
+ <button.commit_callback
+ function="Block.ClickRemove" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index b6d0678cfb..6449059ef0 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
+ mouse_opaque="false"
background_visible="true"
bg_alpha_color="0.25 0.25 0.25 1"
bg_opaque_color="0.25 0.25 0.25 1"
@@ -12,6 +13,7 @@
border_visible="true"
width="1000">
<layout_stack
+ mouse_opaque="false"
border_size="0"
clip="false"
follows="left|right|bottom|top"
@@ -33,12 +35,14 @@
top="0"
width="5"/>
<layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
follows="left|right"
height="28"
layout="topleft"
left="5"
min_height="28"
- width="500"
+ width="600"
top="0"
min_width="305"
name="chat_bar"
@@ -56,6 +60,7 @@
top="0"
width="3"/>
<layout_panel
+ mouse_opaque="false"
auto_resize="false"
follows="right"
height="28"
@@ -95,6 +100,7 @@
top="0"
width="8"/>
<layout_panel
+ mouse_opaque="false"
auto_resize="false"
follows="right"
height="28"
@@ -187,6 +193,7 @@
top="0"
width="5"/>
<layout_panel
+ mouse_opaque="false"
follows="left|right"
height="28"
layout="topleft"
@@ -196,6 +203,7 @@
width="150"
user_resize="false">
<chiclet_panel
+ mouse_opaque="false"
follows="left|right"
height="25"
layout="topleft"
@@ -216,41 +224,7 @@
left="0"
top="0"
width="5"/>
- <layout_panel
- auto_resize="false"
- follows="right"
- height="28"
- layout="topleft"
- min_height="28"
- name="im_well_panel"
- width="40"
- top="0"
- min_width="40"
- user_resize="false">
- <chiclet_notification
- follows="right"
- height="25"
- layout="topleft"
- left="0"
- name="im_well"
- top="2"
- width="40">
- <button
- image_selected="im_notifications.tga"
- image_unselected="im_notifications.tga"/>
- <unread_notifications
- width="20"
- height="20"
- left="18"
- top="23"/>
-<!--
- <chiclet_notification.commit_callback
- function="Notification.Show"
- parameter="ClickUnimplemented" />
- -->
- </chiclet_notification>
- </layout_panel>
- <icon
+ <icon
auto_resize="false"
color="0 0 0 0"
follows="left|right"
@@ -300,7 +274,7 @@
top="2"
width="48">
<button
- image_selected="bottom_tray_sys_notifications.tga"
+ image_selected="bottom_tray_sys_notifications_selected.tga"
image_unselected="bottom_tray_sys_notifications.tga"/>
<unread_notifications
width="20"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
index 291803fbc5..5dd03656c6 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -9,6 +9,30 @@
name="panel_edit_pick"
top="0"
width="255">
+ <text
+ type="string"
+ length="1"
+ follows="top"
+ font="SansSerifHugeBold"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title"
+ text_color="white"
+ top="5"
+ width="250">
+ Edit Pick
+ </text>
+ <button
+ follows="top|right"
+ height="20"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ right="-20"
+ top="7"
+ width="20" />
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
@@ -27,64 +51,42 @@
left="0"
width="240"
height="575">
- <text
- type="string"
- length="1"
- follows="top"
- font="SansSerifHugeBold"
- height="15"
- layout="topleft"
- left="10"
- name="title"
- text_color="white"
- top="17"
- width="250">
- Edit Pick
- </text>
<panel
background_visible="true"
bg_alpha_color="DkGray2"
- width="280"
+ width="220"
follows="left|right|top|bottom"
height="560"
layout="topleft"
+ left="0"
+ top="0">
+ <texture_picker
+ follows="left|top|right"
+ height="190"
+ width="220"
+ layout="topleft"
+ top="20"
left="10"
- right="-10"
- top_pad="5">
- <panel
- follows="left|top|right"
- height="150"
- layout="topleft"
- left="10"
- right="-10"
- top="10">
- <panel
- follows="left|top|right"
- height="150"
- layout="topleft" >
- <texture_picker
- follows="left|top|right"
- height="150"
- layout="topleft"
- name="pick_snapshot" />
- </panel>
- <icon
- height="16"
- image_name="image_edit_icon.tga"
- layout="topleft"
- name="edit_icon"
- right="-25"
- top="30"
- visible="false"
- width="16" />
- </panel>
+ name="pick_snapshot" />
+ <icon
+ height="16"
+ image_name="image_edit_icon.tga"
+ layout="topleft"
+ name="edit_icon"
+ left="245"
+ top="35"
+ visible="true"
+ width="16" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
+ height="15"
+ font="SansSerifSmall"
+ font.style="BOLD"
layout="topleft"
left="10"
+ top="215"
name="Name:"
text_color="white">
Name:
@@ -95,46 +97,49 @@
height="20"
layout="topleft"
left="10"
+ top_pad="2"
max_length="63"
name="pick_name"
- right="-10"
text_color="black"
- width="255" />
+ width="220" />
<text
type="string"
length="1"
follows="left|top"
- height="30"
+ height="15"
+ font="SansSerifSmall"
+ font.style="BOLD"
layout="topleft"
left="10"
+ top_pad="20"
name="description_label"
- text_color="white"
- v_pad="15"
- valign="center">
+ text_color="white">
Description:
</text>
<text_editor
follows="left|top|right"
height="100"
+ width="220"
hide_scrollbar="true"
layout="topleft"
left="10"
+ top_pad="2"
max_length="1023"
name="pick_desc"
text_color="black"
- right="-10"
word_wrap="true" />
<text
type="string"
length="1"
+ font="SansSerifSmall"
+ font.style="BOLD"
follows="left|top"
- height="20"
+ height="15"
layout="topleft"
left="10"
name="location_label"
text_color="white"
- v_pad="15"
- valign="bottom">
+ top_pad="20">
Location:
</text>
<text
@@ -146,10 +151,9 @@
left="10"
name="pick_location"
right="-10"
+ top_pad="2"
text_color="white"
- v_pad="10"
width="250"
- valign="center"
word_wrap="true">
loading...
</text>
@@ -166,7 +170,7 @@
</scroll_container>
<panel
follows="left|right|bottom"
- height="25"
+ height="30"
label="bottom_panel"
layout="topleft"
left="10"
@@ -174,21 +178,21 @@
top_pad="2">
<button
follows="bottom|left"
- height="20"
+ height="25"
label="Save [WHAT]"
layout="topleft"
name="save_changes_btn"
- right="-120"
- top="5"
+ left="0"
+ top="0"
width="130" />
<button
follows="bottom|left"
- height="20"
+ height="25"
label="Cancel"
layout="topleft"
name="cancel_btn"
- right="-10"
- top="5"
- width="90" />
+ left_pad="5"
+ top_delta="0"
+ width="130" />
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index c0366437db..0d6d8ba97d 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -12,7 +12,45 @@
name="edit_profile_panel"
top="10"
width="255">
- <scroll_container
+ <string
+ name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string
+ name="AcctTypeResident"
+ value="Resident" />
+ <string
+ name="AcctTypeTrial"
+ value="Trial" />
+ <string
+ name="AcctTypeCharterMember"
+ value="Charter Member" />
+ <string
+ name="AcctTypeEmployee"
+ value="Linden Lab Employee" />
+ <string
+ name="PaymentInfoUsed"
+ value="Payment Info Used" />
+ <string
+ name="PaymentInfoOnFile"
+ value="Payment Info On File" />
+ <string
+ name="NoPaymentInfoOnFile"
+ value="No Payment Info On File" />
+ <string
+ name="AgeVerified"
+ value="Age-verified" />
+ <string
+ name="NotAgeVerified"
+ value="Not Age-verified" />
+ <string
+ name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=en
+ </string>
+ <string
+ name="no_partner_text"
+ value="None" />
+ <scroll_container
color="DkGray2"
follows="left|top|right|bottom"
height="300"
@@ -34,7 +72,7 @@
background_visible="true"
bg_alpha_color="DkGray2"
follows="left|top|right|bottom"
- height="620"
+ height="750"
layout="topleft"
left="0"
name="data_panel"
@@ -243,11 +281,10 @@
top_pad="15"
value="Account Status:"
width="100" />
- <link
+ <text
type="string"
follows="left|top"
font="SansSerifSmall"
- font.style="UNDERLINE"
height="15"
layout="topleft"
left_pad="10"
@@ -277,15 +314,14 @@
top_pad="15"
value="Partner:"
width="100" />
- <link
+ <text
follows="left|top"
height="15"
- font.style="UNDERLINE"
layout="topleft"
left_pad="10"
name="partner_edit_link"
top_delta="0"
- value="Edit"
+ value="[[URL] Edit]"
width="100" />
<panel
follows="left|top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index 2de41a9ee6..311caa4866 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -16,28 +16,28 @@
name="want_apply_text">
Do you want to apply these changes?
</panel.string>
-
- <button
- layout="topleft"
- name="back"
- right="-9"
- top="0"
- width="25"
- height="25"
+
+ <button
+ layout="topleft"
+ name="back"
+ right="-9"
+ top="0"
+ width="25"
+ height="25"
label=""
follows="top|left"
image_overlay="BackArrow_Off"
tab_stop="false" />
- <text
- layout="topleft"
- top="0"
- left="10"
- width="250"
- height="20"
- font="SansSerifHugeBold"
- text_color="white"
+ <text
+ layout="topleft"
+ top="0"
+ left="10"
+ width="250"
+ height="20"
+ font="SansSerifHugeBold"
+ text_color="white"
follows="top|left|right"
- mouse_opaque="true"
+ mouse_opaque="true"
name="group_name">(Loading...)</text>
<texture_picker
follows="left|top"
@@ -69,6 +69,7 @@
left_delta="0"
name="founder_name"
top_pad="10"
+ use_ellipses="true"
width="140" />
<button
top="632"
@@ -80,15 +81,15 @@
left="5"
width="65" />
<button
- top="632"
- left="75"
- height="20"
- font="SansSerifSmall"
- label="Refresh"
- label_selected="Refresh"
+ follows="top|left"
+ height="20"
+ image_overlay="Refresh_Off"
+ layout="topleft"
name="btn_refresh"
- follows="top|left"
- width="65" />
+ picture_style="true"
+ top="632"
+ left="75"
+ width="20" />
<button
top="632"
height="20"
diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml
index 8ebf1b69a7..f97daf922f 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notify.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel background_visible="true" bevel_style="in" bg_alpha_color="0 0 0 0"
- height="200" label="instant_message" layout="topleft" left="0"
+ height="155" label="instant_message" layout="topleft" left="0"
name="panel_group_notify" top="0" width="350">
- <panel background_visible="true" bevel_style="in" bg_alpha_color="black"
+ <string
+ name="message_max_lines_count">
+ 4
+ </string>
+ <panel follows="top" background_visible="true" bevel_style="in" bg_alpha_color="black"
height="50" label="header" layout="topleft" left="0" name="header"
top="0" width="350">
<icon follows="left|top|right|bottom" height="40" width="40" layout="topleft"
@@ -13,21 +17,61 @@
Sender Name / Group Name
</text>
</panel>
- <text_editor type="string" length="1" bg_readonly_color="0 0 0 0"
- follows="left|top|right|bottom" height="70" hide_scrollbar="true"
- hide_border="true" layout="topleft" top="55" left="25" name="message"
- text_color="GroupNotifyTextColor" text_readonly_color="GroupNotifyTextColor" width="300" word_wrap="true">
- Message
- Body
- </text_editor>
- <icon follows="left|top|right|bottom" height="16" width="16"
- layout="topleft" top="135" left="25" mouse_opaque="true" name="attachment_icon" />
+ <text
+ follows="top"
+ height="20"
+ layout="topleft"
+ left="25"
+ name="subject"
+ text_color="GroupNotifyTextColor"
+ font="SansSerifBig"
+ top="60"
+ use_ellipses="true"
+ value="subject"
+ width="300"
+ word_wrap="true">
+ subject
+ </text>
+ <text
+ follows="top"
+ height="20"
+ layout="topleft"
+ left="25"
+ name="datetime"
+ text_color="GroupNotifyTextColor"
+ font="SansSerif"
+ top="80"
+ use_ellipses="true"
+ value="datetime"
+ width="300"
+ word_wrap="true">
+ datetime
+ </text>
+ <text
+ follows="left|top|bottom|right"
+ height="0"
+ layout="topleft"
+ left="25"
+ name="message"
+ text_color="GroupNotifyTextColor"
+ top="100"
+ use_ellipses="true"
+ value="message"
+ width="300"
+ word_wrap="true"
+ visible="true" >
+ </text>
+ <icon
+ follows="left|bottom|right" height="15" width="15"
+ layout="topleft" bottom="122" left="25" mouse_opaque="true" name="attachment_icon" visible="true"
+ />
<text font="SansSerif" font.style="UNDERLINE" font_shadow="hard"
- type="string" length="1" follows="left|top|right|bottom" layout="topleft"
- left="45" top="135" height="15" width="280" name="attachment"
- text_color="GroupNotifyTextColor">
+ type="string" length="1" follows="left|bottom|right" layout="topleft"
+ left="45" bottom="122" height="15" width="280" name="attachment"
+ text_color="GroupNotifyTextColor" visible="true">
Attachment
- </text>
- <button label="OK" layout="topleft" top="170" left="140" height="20"
- width="70" name="btn_ok" />
-</panel>
+ </text>
+
+ <button label="OK" layout="topleft" bottom="145" left="140" height="20"
+ width="70" name="btn_ok" follows="bottom" />
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 9ae165cbb9..7b8bd8b337 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -185,7 +185,7 @@
Select multiple Members by holding the Ctrl key and
clicking on their names.
</panel.string>
- <search_editor
+ <filter_editor
layout="topleft"
top="10"
left="4"
@@ -193,17 +193,9 @@ clicking on their names.
height="20"
follows="left|top|right"
max_length="250"
- label="Filter People"
+ label="Filter Members"
name="filter_input"
- font="SansSerif"
- background_image="TextField_Search_Off"
- text_pad_left="10"
- text_color="black">
- <search_button label=""
- top_pad="4"
- left_pad="6"
- />
- </search_editor>
+ font="SansSerif" />
<!--<line_editor
border_style="line"
border_thickness="1"
@@ -318,7 +310,7 @@ including the Everyone and Owner Roles.
name="power_partial_icon">
checkbox_enabled_false.tga
</panel.string>
- <search_editor
+ <filter_editor
layout="topleft"
top="10"
left="4"
@@ -328,15 +320,7 @@ including the Everyone and Owner Roles.
max_length="250"
label="Filter Roles"
name="filter_input"
- font="SansSerif"
- background_image="TextField_Search_Off"
- text_pad_left="10"
- text_color="black">
- <search_button label=""
- top_pad="4"
- left_pad="6"
- />
- </search_editor>
+ font="SansSerif" />
<!--<line_editor
border_style="line"
border_thickness="1"
@@ -426,7 +410,7 @@ including the Everyone and Owner Roles.
Abilities allow Members in Roles to do specific
things in this group. There&apos;s a broad variety of Abilities.
</panel.string>
- <search_editor
+ <filter_editor
layout="topleft"
top="10"
left="4"
@@ -436,15 +420,7 @@ things in this group. There&apos;s a broad variety of Abilities.
max_length="250"
label="Filter Abilities"
name="filter_input"
- font="SansSerif"
- background_image="TextField_Search_Off"
- text_pad_left="10"
- text_color="black">
- <search_button label=""
- top_pad="4"
- left_pad="6"
- />
- </search_editor>
+ font="SansSerif" />
<!--<line_editor
border_style="line"
border_thickness="1"
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 169fde7b47..ace456918c 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -10,6 +10,10 @@
name="im_panel"
top="0"
width="350">
+ <string
+ name="message_max_lines_count">
+ 6
+ </string>
<panel
background_visible="true"
bevel_style="in"
@@ -56,7 +60,7 @@
width="50" />
</panel>
<text
- follows="left|bottom|right"
+ follows="left|top|bottom|right"
height="60"
layout="topleft"
left="10"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 794b69d7ed..d943b2ea23 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -55,6 +55,7 @@
max_length="31"
name="first_name_edit"
select_on_focus="true"
+ tool_tip="Enter first name here"
top_pad="4"
width="120" />
<text
@@ -111,6 +112,25 @@
select_on_focus="true"
top_pad="4"
width="120" />
+ <button
+ follows="left|bottom"
+ height="24"
+ label="Log In"
+ label_selected="Log In"
+ layout="topleft"
+ left="435"
+ name="connect_btn"
+ top="548"
+ width="120" />
+ <combo_box
+ allow_text_entry="true"
+ follows="left|bottom"
+ height="18"
+ layout="topleft"
+ left_pad="15"
+ name="server_combo"
+ top_delta="2"
+ width="120" />
<text
type="string"
length="1"
@@ -158,25 +178,7 @@
name="remember_check"
top_delta="3"
width="138" />
- <button
- follows="left|bottom"
- height="24"
- label="Log In"
- label_selected="Log In"
- layout="topleft"
- left="435"
- name="connect_btn"
- top="548"
- width="120" />
- <combo_box
- allow_text_entry="true"
- follows="left|bottom"
- height="18"
- layout="topleft"
- left_pad="15"
- name="server_combo"
- top_delta="2"
- width="120" />
+
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index dee911a45d..80dca8c0c1 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -107,8 +107,8 @@
<!-- picture_style="true" -->
<!-- top_delta="0" -->
<!-- width="168" /> -->
-
- <search_editor
+
+ <search_combo_box
bevel_style="none"
border_style="line"
border.border_thickness="0"
@@ -118,12 +118,15 @@
height="22"
label="Search"
layout="topleft"
- left_pad="7"
+ right="-10"
mouse_opaque="false"
- name="search_input"
+ name="search_combo_box"
tool_tip="Search"
top_delta="0"
- width="200" />
+ width="200" >
+ <combo_editor
+ label="Search" />
+ </search_combo_box>
</panel>
<favorites_bar
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 22823ea98b..310e3908ca 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -1,14 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- background_visible="true"
+background_visible="true"
+color="DkGray"
follows="all"
- height="400"
+ height="570"
label="People"
layout="topleft"
min_height="350"
- min_width="240"
name="people_panel"
- width="305">
+ top="0"
+ left="0"
+ bevel_style="none"
+ width="333">
<string
name="no_people"
value="No people" />
@@ -31,154 +34,128 @@
name="groups_filter_label"
value="Filter Groups" />
<filter_editor
- background_image="TextField_Search_Off"
follows="left|top|right"
font="SansSerif"
height="23"
layout="topleft"
left="15"
- max_length="270"
+ max_length="300"
name="filter_input"
text_color="black"
- text_pad_left="26"
top="3"
- width="256" />
- <button
- follows="left|top|right"
- height="13"
- image_selected="Search"
- image_unselected="Search"
- layout="topleft"
- left="20"
- name="people_search"
- picture_style="true"
- scale_image="false"
- top="8"
- width="13" />
+ width="300" />
<tab_container
- follows="left|top|right|bottom"
- height="326"
+ follows="all"
+ height="488"
layout="topleft"
- left="9"
+ left="10"
name="tabs"
+ bevel_style="in"
tab_position="top"
top_pad="15"
- width="285">
+ width="313">
<panel
- bevel_style="none"
- follows="left|top|right|bottom"
- height="390"
+ follows="all"
+ height="488"
label="Nearby"
layout="topleft"
+ left="0"
name="nearby_panel"
- width="285">
+ top="0"
+ width="313">
<avatar_list
- follows="left|top|right|bottom"
- height="357"
+ follows="all"
+ height="430"
layout="topleft"
left="0"
name="avatar_list"
- top="2"
+ top="0"
volume_column_width="20"
- width="285" />
+ width="313" />
<panel
background_visible="true"
bevel_style="none"
- bottom="390"
+ top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
layout="topleft"
left="0"
name="bottom_panel"
- width="285">
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="OptionsMenu_Press"
- image_unselected="OptionsMenu_Off"
- layout="topleft"
- left="20"
- name="nearby_view_sort_btn"
- picture_style="true"
- tool_tip="Change sort and view of Residents list"
- top="7"
- width="18" />
+ width="313">
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ tool_tip="Change sort and view of Residents list"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="nearby_view_sort_btn"
+ picture_style="true"
+ top="5"
+ width="18" />
</panel>
</panel>
<panel
background_visible="true"
bevel_style="none"
- follows="left|top|right|bottom"
- height="390"
+ follows="all"
+ color="DkGray2"
+ height="460"
+ left="0"
+ top="0"
label="Friends"
layout="topleft"
name="friends_panel"
- width="285">
+ width="313">
<accordion
- follows="left|top|right|bottom"
- height="357"
+ follows="all"
+ height="430"
layout="topleft"
left="0"
name="friends_accordion"
top="2"
- width="285">
+ width="313">
<accordion_tab
can_resize="false"
layout="topleft"
- min_height="100"
+ min_height="150"
name="tab_online"
title="Online">
- <panel
- follows="all"
- height="150"
- layout="topleft"
- left="0"
- name="tab_online_panel"
- top="100"
- width="285">
<avatar_list
draw_heading="false"
follows="all"
- height="145"
+ height="150"
layout="topleft"
left="0"
name="avatars_online"
top="0"
- width="285" />
- </panel>
+ width="313" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
- min_height="100"
+ height="230"
name="tab_all"
title="All">
- <panel
- follows="all"
- height="260"
- layout="topleft"
- left="0"
- name="tab_all_panel"
- top="100"
- width="285">
<avatar_list
draw_heading="false"
follows="all"
- height="255"
+ height="230"
layout="topleft"
left="0"
name="avatars_all"
top="0"
- width="285" />
- </panel>
+ width="313" />
</accordion_tab>
</accordion>
<panel
background_visible="true"
bevel_style="none"
- bottom="390"
+ top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
@@ -186,25 +163,27 @@
left="0"
name="bottom_panel"
width="285">
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="OptionsMenu_Press"
- image_unselected="OptionsMenu_Off"
- layout="topleft"
- left="20"
- name="friends_viewsort_btn"
- picture_style="true"
- tool_tip="Change sort and view of Friends list"
- top="7"
- width="18" />
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ tool_tip="Change sort and view of Friends list"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="friends_viewsort_btn"
+ picture_style="true"
+ top="5"
+ width="18" />
<button
follows="bottom|left"
font="SansSerifBigBold"
height="18"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
layout="topleft"
left_pad="5"
name="add_btn"
@@ -218,6 +197,7 @@
height="18"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
+ image_disabled="TrashItem_Disabled"
layout="topleft"
left_pad="180"
name="del_btn"
@@ -233,13 +213,16 @@
follows="left|top|right|bottom"
height="390"
label="Groups"
+ top="0"
layout="topleft"
name="groups_panel"
width="285">
<group_list
+ draw_heading="false"
follows="left|top|right|bottom"
height="357"
layout="topleft"
+ color="DkGray2"
left="0"
name="group_list"
top="2"
@@ -247,7 +230,7 @@
<panel
background_visible="true"
bevel_style="none"
- bottom="390"
+ top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
@@ -255,26 +238,28 @@
left="0"
name="bottom_panel"
width="285">
- <button
- enabled="false"
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="OptionsMenu_Press"
- image_unselected="OptionsMenu_Off"
- layout="topleft"
- left="20"
- name="gear_btn"
- picture_style="true"
- tool_tip="Change sort and view of Groups list"
- top="7"
- width="18" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ tool_tip="Change sort and view of Groups list"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="gear_btn"
+ picture_style="true"
+ top="5"
+ width="18" />
<button
follows="bottom|left"
font="SansSerifBigBold"
height="18"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
layout="topleft"
left_pad="5"
name="plus_btn"
@@ -314,13 +299,15 @@
<panel
background_visible="true"
bevel_style="none"
+ top="0"
follows="left|top|right|bottom"
height="390"
label="Recent"
layout="topleft"
name="recent_panel"
width="285">
- <avatar_list
+ <avatar_list_tmp
+ color="DkGray2"
follows="left|top|right|bottom"
height="357"
layout="topleft"
@@ -331,7 +318,7 @@
<panel
background_visible="true"
bevel_style="none"
- bottom="390"
+ top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
@@ -339,19 +326,20 @@
left="0"
name="bottom_panel"
width="285">
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="OptionsMenu_Press"
- image_unselected="OptionsMenu_Off"
- layout="topleft"
- left="20"
- name="recent_viewsort_btn"
- picture_style="true"
- tool_tip="Change sort and view of Residents list"
- top="7"
- width="18" />
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ tool_tip="Change sort and view of Recent Residents list"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="recent_viewsort_btn"
+ picture_style="true"
+ top="5"
+ width="18" />
</panel>
</panel>
</tab_container>
@@ -364,7 +352,7 @@
left="10"
name="button_bar"
orientation="horizontal"
- width="295">
+ width="313">
<layout_panel
default_tab_group="1"
follows="left|top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 80fa99c257..9edd14ce49 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -2,143 +2,102 @@
<panel
bevel_style="in"
follows="left|top|right|bottom"
- height="420"
+ height="570"
layout="topleft"
left="0"
name="panel_pick_info"
top="0"
- width="255">
- <scroll_container
- color="DkGray2"
- follows="left|top|right|bottom"
- height="300"
- layout="topleft"
- left="0"
- name="profile_scroll"
- reserve_scroll_corner="true"
- opaque="true"
- width="255">
- <panel
- name="scroll_content_panel"
- follows="left|top|right"
+ width="333">
+ <button
+ follows="top|left"
+ height="25"
+ width="25"
+ image_overlay="BackArrow_Off"
layout="topleft"
- top="0"
- left="0"
- width="240"
- height="575">
+ name="back_btn"
+ picture_style="true"
+ left="10"
+ top="7" />
<text
- follows="top"
+ follows="top|left"
font="SansSerifHugeBold"
- height="15"
+ height="22"
layout="topleft"
- left="10"
+ left_pad="15"
name="title"
text_color="white"
- top="5"
value="Pick Info"
- width="150" />
- <button
- follows="top|right"
- height="20"
- image_overlay="BackArrow_Off"
+ width="270" />
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ follows="left|top|bottom"
+ height="490"
layout="topleft"
- name="back_btn"
- picture_style="true"
- right="-20"
- top="7"
- width="20" />
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ reserve_scroll_corner="true"
+ width="313">
<panel
- background_visible="true"
- bg_alpha_color="DkGray2"
- follows="left|right|top|bottom"
- height="550"
+ name="scroll_content_panel"
+ follows="left|top|right|bottom"
+ min_height="300"
layout="topleft"
+ top="0"
+ background_visible="false"
+ height="488"
left="0"
- min_height="300"
- top="30"
- width="255">
+ width="311">
<texture_picker
enabled="false"
- follows="left|top|right"
- height="300"
- layout="topleft"
- left="10"
- name="pick_snapshot"
- top="10"
- width="245" />
- <text
follows="left|top"
- font="SansSerifBigBold"
- height="15"
+ height="197"
layout="topleft"
left="10"
- name="Name:"
- text_color="white"
- value="Name:" />
+ name="pick_snapshot"
+ top="20"
+ width="290" />
<text
follows="left|top|right"
- height="15"
+ height="20"
+ width="291"
layout="topleft"
+ font="SansSerifBig"
+ font.style="BOLD"
left="10"
+ top_pad="10"
name="pick_name"
- right="-10"
text_color="white"
value="[name]"
word_wrap="true" />
<text
follows="left|top"
- font="SansSerifBigBold"
- height="15"
+ height="25"
layout="topleft"
left="10"
- name="description_label"
- text_color="white"
- top_pad="20"
- valign="center"
- value="Description:" />
+ name="pick_location"
+ width="291"
+ word_wrap="true"
+ value="[loading...]" />
<text
follows="left|top|right"
- height="60"
+ height="400"
layout="topleft"
left="10"
name="pick_desc"
- right="-10"
- text_color="white"
- valign="center"
+ width="290"
value="[description]"
- width="255"
word_wrap="true" />
- <text
- follows="left|top"
- font="SansSerifBigBold"
- height="20"
- layout="topleft"
- left="10"
- name="location_label"
- text_color="white"
- top_pad="20"
- valign="bottom"
- value="Location:" />
- <text
- follows="left|top"
- height="30"
- layout="topleft"
- left="10"
- name="pick_location"
- text_color="white"
- valign="center"
- value="[loading...]" />
- </panel>
</panel>
</scroll_container>
<panel
follows="left|right|bottom"
height="30"
layout="topleft"
- top_pad="2"
- left="8"
- name="buttons"
- right="-10">
+ top_pad="5"
+ left="10"
+ name="buttons">
<button
follows="bottom|left"
font="SansSerifSmallBold"
@@ -148,14 +107,14 @@
left="0"
name="edit_btn"
top="0"
- width="50" />
+ width="80" />
<button
follows="bottom|left"
font="SansSerifSmallBold"
height="25"
label="Teleport"
layout="topleft"
- left_pad="2"
+ left_pad="5"
name="teleport_btn"
top="0"
width="80" />
@@ -165,9 +124,9 @@
height="25"
label="Map"
layout="topleft"
- left_pad="2"
+ left_pad="5"
name="show_on_map_btn"
top="0"
- width="100" />
+ width="80" />
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
index 6f4110067b..37e873b6a8 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -7,7 +7,27 @@
left="0"
name="picture_item"
top="0"
- width="275">
+ width="305">
+ <icon
+ height="120"
+ image_name="ListItem_Over"
+ left="0"
+ mouse_opaque="false"
+ name="hovered_icon"
+ top="0"
+ scale_image="true"
+ visible="false"
+ width="305"/>
+ <icon
+ height="120"
+ image_name="ListItem_Select"
+ left="0"
+ mouse_opaque="false"
+ name="selected_icon"
+ top="0"
+ scale_image="true"
+ visible="false"
+ width="305"/>
<texture_picker
allow_no_texture="true"
default_image_name="None"
@@ -20,6 +40,7 @@
name="picture"
tab_stop="false"
top="5"
+ top_pad="5"
width="120" />
<text
follows="top|left|right"
@@ -30,7 +51,7 @@
text_color="white"
top="5"
use_ellipses="true"
- width="120"
+ width="130"
word_wrap="true" />
<text
follows="top|left|right"
@@ -50,8 +71,8 @@
layout="topleft"
name="info_chevron"
picture_style="true"
- right="262"
+ right="290"
tab_stop="false"
- top="3"
+ top="5"
width="16" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index ff161cc2ab..bceaedcdb4 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -1,40 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="left|top|right|bottom"
- height="420"
+ height="515"
label="Picks"
layout="topleft"
left="0"
name="panel_picks"
top="0"
- width="285">
- <layout_stack
- name="layout"
- orientation="vertical"
- follows="all"
- layout="topleft"
- left="0"
- top="0"
- height="420"
- width="284"
- border_size="0">
+ width="313">
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
- height="350"
+ height="495"
layout="topleft"
- left="2"
+ left="0"
name="profile_scroll"
opaque="true"
top="0"
- width="284">
- <panel
- height="115"
+ width="313">
+ <list
+ height="120"
layout="topleft"
left="0"
- name="back_panel"
+ name="picks_list"
top="0"
- width="284" />
+ width="305" />
</scroll_container>
<panel
background_visible="true"
@@ -42,12 +32,13 @@
enabled="false"
auto_resize="false"
follows="bottom"
- height="30"
+ left="0"
+ height="23"
label="bottom_panel"
layout="topleft"
name="edit_panel"
- top_pad="5"
- width="284">
+ top_pad="0"
+ width="313">
<button
enabled="false"
follows="bottom|left"
@@ -55,6 +46,7 @@
height="18"
image_selected="OptionsMenu_Press"
image_unselected="OptionsMenu_Off"
+ image_disabled="OptionsMenu_Disabled"
layout="topleft"
left="10"
name="gear_menu_btn"
@@ -65,8 +57,7 @@
follows="bottom|left"
font="SansSerifBigBold"
height="18"
- image_disabled="AddItem_Off"
- image_disabled_selected="AddItem_Press"
+ image_disabled="AddItem_Disabled"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
layout="topleft"
@@ -80,8 +71,7 @@
follows="bottom|right"
font="SansSerifBigBold"
height="18"
- image_disabled="TrashItem_Off"
- image_disabled_selected="TrashItem_Press"
+ image_disabled="TrashItem_Disabled"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
layout="topleft"
@@ -93,11 +83,11 @@
</panel>
<panel
follows="bottom"
- height="30"
auto_resize="false"
layout="topleft"
+ height="30"
name="buttons_cucks"
- width="284">
+ width="313">
<button
enabled="false"
follows="bottom|left"
@@ -108,5 +98,4 @@
name="show_on_map_btn"
width="85" />
</panel>
- </layout_stack>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index bff28718a7..b379ad2276 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -16,7 +16,6 @@
name="teleport_history_tab_title"
value="Teleport History" />
<filter_editor
- background_image="TextField_Search_Off"
follows="left|top|right"
font="SansSerif"
height="23"
@@ -24,22 +23,8 @@
layout="topleft"
left="15"
name="Filter"
- text_color="black"
- text_pad_left="26"
top="3"
width="256" />
- <button
- follows="left|top|right"
- height="13"
- image_selected="Search"
- image_unselected="Search"
- layout="topleft"
- left="20"
- name="landmark_search"
- picture_style="true"
- scale_image="false"
- top="8"
- width="13" />
<tab_container
follows="all"
height="326"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 060d84b2e4..88bf3d3b22 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -120,7 +120,7 @@
height="10"
left="30"
text_color="EmphasisColor"
- name="text_box1"
+ name="heading1"
top_pad="30"
width="270">
Camera:
@@ -166,7 +166,7 @@ Camera:
length="1"
height="10"
left="30"
- name="text_box1"
+ name="heading2"
width="270">
Automatic positioning for:
</text>
@@ -194,7 +194,7 @@ Automatic positioning for:
height="10"
left="30"
text_color="EmphasisColor"
- name="text_box1"
+ name="heading3"
top_pad="30"
width="270">
My Avatar:
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index 95d8d2ce2a..70292a38aa 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -260,7 +260,7 @@
label="Show my name"
layout="topleft"
left_delta="0"
- name="show_my_name_checkbox"
+ name="show_my_name_checkbox1"
top_pad="5"
width="300" />
<check_box
@@ -280,7 +280,7 @@
label="Show group titles"
layout="topleft"
left_delta="-175"
- name="show_all_title_checkbox"
+ name="show_all_title_checkbox1"
top_pad="5"
width="300" />
<text
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index d90be9ea25..2a800f809b 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -1,46 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- bevel_style="out"
- follows="left|top|right|bottom"
- height="420"
+ follows="all"
+ height="515"
label="Profile"
layout="topleft"
left="0"
name="panel_profile"
top="0"
- width="255">
+ width="313">
<string
name="CaptionTextAcctInfo">
[ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
</string>
<string
- name="AcctTypeResident"
- value="Resident" />
- <string
- name="AcctTypeTrial"
- value="Trial" />
- <string
- name="AcctTypeCharterMember"
- value="Charter Member" />
- <string
- name="AcctTypeEmployee"
- value="Linden Lab Employee" />
- <string
- name="PaymentInfoUsed"
- value="Payment Info Used" />
- <string
- name="PaymentInfoOnFile"
- value="Payment Info On File" />
- <string
- name="NoPaymentInfoOnFile"
- value="No Payment Info On File" />
- <string
- name="AgeVerified"
- value="Age-verified" />
- <string
- name="NotAgeVerified"
- value="Not Age-verified" />
- <string
name="payment_update_link_url">
http://www.secondlife.com/account/billing.php?lang=en
</string>
@@ -48,30 +20,27 @@
name="my_account_link_url"
value="http://secondlife.com/account" />
<string
- name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=en
- </string>
- <string
name="no_partner_text"
value="None" />
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
- height="300"
+ height="515"
+ min_height="300"
layout="topleft"
- left="0"
name="profile_scroll"
reserve_scroll_corner="true"
opaque="true"
- width="255">
+ top="0"
+ width="313">
<panel
name="scroll_content_panel"
follows="left|top|right"
layout="topleft"
top="0"
left="0"
- width="240"
- height="780">
+ width="284"
+ height="700">
<panel
follows="left|top"
height="117"
@@ -79,7 +48,7 @@
left="10"
name="second_life_image_panel"
top="10"
- width="260">
+ width="280">
<texture_picker
allow_no_texture="true"
default_image_name="None"
@@ -102,13 +71,13 @@
text_color="white"
top_delta="0"
value="[SECOND_LIFE]:"
- width="130" />
+ width="170" />
<text
follows="left|top|right"
- height="70"
+ height="90"
layout="topleft"
name="sl_description_edit"
- width="130"
+ width="170"
word_wrap="true">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
</text>
@@ -120,7 +89,7 @@
top_pad="10"
left="10"
name="first_life_image_panel"
- width="260">
+ width="280">
<texture_picker
allow_no_texture="true"
default_image_name="None"
@@ -142,13 +111,13 @@
text_color="white"
top_delta="0"
value="Real World:"
- width="130" />
+ width="175" />
<text
follows="left|top|right"
- height="70"
+ height="90"
layout="topleft"
name="fl_description_edit"
- width="130"
+ width="180"
word_wrap="true">
Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
</text>
@@ -164,19 +133,17 @@
name="me_homepage_text"
text_color="white"
top_pad="10"
- width="255">
+ width="280">
Homepage:
</text>
- <link
- follows="left|top|right"
+ <text
+ follows="left|top"
height="15"
layout="topleft"
- font.style="UNDERLINE"
left="10"
name="homepage_edit"
- top_pad="5"
value="http://librarianavengers.org"
- width="225"
+ width="280"
word_wrap="false" />
<text
follows="left|top"
@@ -189,16 +156,16 @@
text_color="white"
top_pad="20"
value="Member Since:"
- width="255" />
+ width="280" />
<text
- follows="left|top|right"
+ follows="left|top"
height="15"
layout="topleft"
left="10"
name="register_date"
top_pad="5"
value="05/31/1976"
- width="160"
+ width="280"
word_wrap="true" />
<text
follows="left|top"
@@ -211,12 +178,11 @@
text_color="white"
top_pad="15"
value="Account Status:"
- width="100" />
- <!-- <link
+ width="280" />
+ <!-- <text
type="string"
follows="left|top"
font="SansSerifSmall"
- font.style="UNDERLINE"
height="15"
layout="topleft"
left_pad="10"
@@ -225,14 +191,14 @@
value="Go to Dashboard"
width="100"/> -->
<text
- follows="left|top|right"
+ follows="left|top"
height="15"
layout="topleft"
left="10"
name="acc_status_text"
top_pad="5"
value="Resident. No payment info on file."
- width="255"
+ width="280"
word_wrap="true" />
<text
follows="left|top"
@@ -245,34 +211,24 @@
text_color="white"
top_pad="15"
value="Partner:"
- width="100" />
- <!--<link
- follows="left|top"
- height="15"
- font.style="UNDERLINE"
- layout="topleft"
- left_pad="10"
- name="partner_edit_link"
- top_delta="0"
- value="Edit"
- width="100" /> -->
+ width="280" />
<panel
- follows="left|top|right"
+ follows="left|top"
height="15"
layout="topleft"
left="10"
name="partner_data_panel"
top_pad="5"
- width="255">
+ width="280">
<text
- follows="left|top|right"
+ follows="left|top"
height="15"
layout="topleft"
left="0"
name="partner_text"
top="0"
value="[FIRST] [LAST]"
- width="240"
+ width="280"
word_wrap="true" />
</panel>
<text
@@ -286,28 +242,28 @@
text_color="white"
top_pad="15"
value="Groups:"
- width="255" />
+ width="280" />
<text
- follows="left|top|right|bottom"
+ follows="left|top|bottom"
height="160"
layout="topleft"
left="10"
name="sl_groups"
top_pad="5"
- width="130"
+ width="280"
word_wrap="true">
Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
</text>
</panel>
</scroll_container>
+
<panel
follows="bottom|left"
- height="30"
layout="topleft"
- left="10"
+ left="0"
name="profile_buttons_panel"
- top_pad="5"
- width="280">
+ top_pad="0"
+ width="313">
<button
follows="bottom|left"
font="SansSerifSmallBold"
@@ -352,13 +308,13 @@
width="75" />
</panel>
<panel
- height="30"
+ follows="bottom|left"
layout="topleft"
- left="10"
+ left="0"
name="profile_me_buttons_panel"
- top_pad="5"
+ top_pad="0"
visible="false"
- width="280">
+ width="313">
<button
follows="bottom|left"
font="SansSerifSmallBold"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index 32223d542d..9aa2c304f2 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -8,6 +8,14 @@
min_width="240"
name="panel_target_profile"
width="305">
+ <string
+ name="status_online">
+ Online
+ </string>
+ <string
+ name="status_offline">
+ Offline
+ </string>
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 4f23c4d26d..9b2461db7c 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -99,12 +99,12 @@
halign="left"
height="100"
layout="topleft"
- left="30"
+ left="45"
line_spacing="2"
name="message_text"
text_color="LoginProgressBoxTextColor"
top="145"
- width="610" />
+ width="550" />
</layout_panel>
<layout_panel
height="200"
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index e9eac2c9dc..200c67b321 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -3,14 +3,14 @@
name="sidebar"
background_visible="false"
mouse_opaque="true"
- width="305"
+ width="333"
collapsed="true"
>
<sidetray_tab
name="sidebar_home"
tab_title="Home"
description="Home."
- image="icn_voice-groupfocus.tga"
+ image="BackArrow_Off"
mouse_opaque="false"
background_opaque="false"
background_visible="true"
@@ -50,11 +50,18 @@
border="true"
font="SansSerifBold"
/>
- <panel
- class="panel_group_info_sidetray"
- name="panel_group_info_sidetray"
- filename="panel_group_info_sidetray.xml"
- label="Group Info"
+ <panel
+ class="panel_group_info_sidetray"
+ name="panel_group_info_sidetray"
+ filename="panel_group_info_sidetray.xml"
+ label="Group Info"
+ border="true"
+ />
+ <panel
+ class="panel_block_list_sidetray"
+ name="panel_block_list_sidetray"
+ filename="panel_block_list_sidetray.xml"
+ label="Blocked Residents &amp; Objects"
border="true"
/>
@@ -80,7 +87,7 @@
<sidetray_tab
name="sidebar_me"
- tab_title="My Profile"
+ tab_title="Me"
description="Change your profile, your look and quick links to your outfits."
image="TabIcon_Me_Off"
mouse_opaque="false"
@@ -90,7 +97,7 @@
class="panel_me_profile_view"
name="panel_me_profile"
filename="panel_me_profile.xml"
- label="My Profile"
+ label="Me"
border="true"
font="SansSerifBold"
/>
@@ -101,16 +108,15 @@
tab_title="Appearance"
description="Change your looks and appearance."
image="TabIcon_Appearance_Off"
- mouse_opaque="false"
- background_opaque="false"
- background_visible="true"
- bg_opaque_color="0.5 0.5 0.5 1.0"
+ mouse_opaque="false"
+ background_opaque="false"
+ background_visible="true"
>
- <panel
+ <panel
class="panel_appearance"
- name="panel_appearance"
- filename="panel_appearance.xml"
- border="true"
+ name="panel_appearance"
+ filename="panel_appearance.xml"
+ border="true"
/>
</sidetray_tab>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
index 82d6945e0f..70198dc626 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -1,12 +1,162 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="Teleport History" bottom="0" height="326" left="0" width="380"
- border="true" follows="left|top|right|bottom">
- <scroll_list bottom="0" column_padding="0" draw_heading="false"
- draw_stripes="false" follows="left|top|bottom|right" left="0"
- multi_select="false" name="history_items" search_column="1"
- sort_column="1" height="326" width="380" >
+ border="true" follows="left|top|right|bottom">
+ <accordion
+ follows="left|top|right|bottom"
+ height="326"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="history_accordion"
+ width="380">
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="today"
+ title="Today">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="today_items"
+ top="0"
+ width="285">
<column name="landmark_icon" width="20" />
<column dynamic_width="true" label="Region" name="region" />
<column name="index" width="0" />
- </scroll_list>
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="yesterday"
+ title="Yesterday">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="yesterday_items"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="3_days_ago"
+ title="3 days ago">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="3_days_ago"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="4_days_ago"
+ title="4 days ago">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="4_days_ago"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="5_days_ago"
+ title="5 days ago">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="5_days_ago_items"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="6_days_ago"
+ title="6 days ago">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="6_days_ago"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ min_height="100"
+ name="older_than_6_days"
+ title="Older than 6 days">
+ <scroll_list
+ draw_heading="false"
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="older_than_6_days_items"
+ top="0"
+ width="285">
+ <column name="landmark_icon" width="20" />
+ <column dynamic_width="true" label="Region" name="region" />
+ <column name="index" width="0" />
+ </scroll_list>
+ </accordion_tab>
+
+ </accordion>
+
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml
index 441caffa28..01fd84e09d 100644
--- a/indra/newview/skins/default/xui/en/panel_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -11,8 +11,6 @@
left="100"
top="500"
follows="right|bottom"
- background_opaque="true"
- background_visible="true"
bevel_style="in"
can_minimize="false"
can_tear_off="false"
@@ -20,7 +18,7 @@
can_drag_on_left="false"
can_close="false"
can_dock="false"
- bg_alpha_color="0.3 0.3 0.3 1.0">
+ >
<text
visible="false"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 4c9b1897d5..4206b87c2b 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -46,7 +46,7 @@
<string name="AgentLostConnection">This region may be experiencing trouble. Please check your connection to the Internet.</string>
- <!-- Tooltip, llhoverview.cpp -->
+ <!-- Tooltip, lltooltipview.cpp -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
<string name="TooltipOwner">Owner:</string> <!-- Owner name follows -->
@@ -74,6 +74,18 @@
<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
<string name="TooltipAltLeft">Alt-Left arrow for previous tab</string>
<string name="TooltipAltRight">Alt-Right arrow for next tab</string>
+
+ <!-- tooltips for Urls -->
+ <string name="TooltipHttpUrl">Click to view this web page</string>
+ <string name="TooltipSLURL">Click to view this location's information</string>
+ <string name="TooltipAgentUrl">Click to view this resident's profile</string>
+ <string name="TooltipGroupUrl">Click to view this group's description</string>
+ <string name="TooltipEventUrl">Click to view this event's description</string>
+ <string name="TooltipClassifiedUrl">Click to view this classified</string>
+ <string name="TooltipParcelUrl">Click to view this parcel's description</string>
+ <string name="TooltipTeleportUrl">Click to teleport to this location</string>
+ <string name="TooltipObjectIMUrl">Click to view this object's description</string>
+ <string name="TooltipSLAPP">Click to run the secondlife:// command</string>
<!-- ButtonToolTips, llfloater.cpp -->
<string name="BUTTON_CLOSE_DARWIN">Close (&#8984;-W)</string>
@@ -259,6 +271,7 @@
<!-- IM -->
<string name="IM_logging_string">-- Instant message logging enabled --</string>
+ <string name="Unnamed">(Unnamed)</string>
<!-- Sim Access labels -->
<string name="SIM_ACCESS_PG">PG</string>
@@ -288,358 +301,1439 @@
<string name="choose_the_directory">Choose Directory</string>
<!-- LSL Usage Hover Tips -->
- <string name="LSLTipSleepTime">Sleeps script for [SLEEP_TIME] seconds.</string>
+ <string name="LSLTipSleepTime">
+Sleeps script for [SLEEP_TIME] seconds.
+ </string>
- <string name="LSLTipText_llSin">float llSin(float theta)\ntheta in radians</string>
- <string name="LSLTipText_llCos">float llCos(float theta)\ntheta in radians</string>
- <string name="LSLTipText_llTan">float llTan(float theta)\ntheta radians</string>
- <string name="LSLTipText_llAtan2">float llAtan2(float y, float x)</string>
- <string name="LSLTipText_llSqrt">float llSqrt(float val)\nreturns 0 and triggers a Math Error for imaginary results</string>
- <string name="LSLTipText_llPow">float llPow(float base, float exponent)\nreturns 0 and triggers Math Error for imaginary results</string>
- <string name="LSLTipText_llAbs">integer llAbs(integer val)</string>
- <string name="LSLTipText_llFabs">float llFabs(float val)</string>
- <string name="LSLTipText_llFrand">float llFrand(float mag)\nreturns random number in range [0,mag)</string>
- <string name="LSLTipText_llFloor">integer llFloor(float val)\nreturns largest integer value &lt;= val</string>
- <string name="LSLTipText_llCeil">integer llCeil(float val)\nreturns smallest integer value &gt;= val</string>
- <string name="LSLTipText_llRound">integer llRound(float val)\nreturns val rounded to the nearest integer</string>
- <string name="LSLTipText_llVecMag">float llVecMag(vector v)\nreturns the magnitude of v</string>
- <string name="LSLTipText_llVecNorm">vector llVecNorm(vector v)\nreturns the v normalized</string>
- <string name="LSLTipText_llVecDist">float llVecDist(vector v1, vector v2)\nreturns the 3D distance between v1 and v2</string>
- <string name="LSLTipText_llRot2Euler">vector llRot2Euler(rotation q)\nreturns the Euler representation (roll, pitch, yaw) of q</string>
- <string name="LSLTipText_llEuler2Rot">rotation llEuler2Rot(vector v)\nreturns the rotation representation of Euler Angles v</string>
- <string name="LSLTipText_llAxes2Rot">rotation llAxes2Rot(vector fwd, vector left, vector up)\nreturns the rotation defined by the coordinate axes</string>
- <string name="LSLTipText_llRot2Fwd">vector llRot2Fwd(rotation q)\nreturns the forward vector defined by q</string>
- <string name="LSLTipText_llRot2Left">vector llRot2Left(rotation q)\nreturns the left vector defined by q</string>
- <string name="LSLTipText_llRot2Up">vector llRot2Up(rotation q)\nreturns the up vector defined by q</string>
- <string name="LSLTipText_llRotBetween">rotation llRotBetween(vector v1, vector v2)\nreturns the rotation to rotate v1 to v2</string>
- <string name="LSLTipText_llWhisper">llWhisper(integer channel, string msg)\nwhispers msg on channel</string>
- <string name="LSLTipText_llSay">llSay(integer channel, string msg)\nsays msg on channel</string>
- <string name="LSLTipText_llShout">llShout(integer channel, string msg)\nshouts msg on channel</string>
- <string name="LSLTipText_llListen">integer llListen(integer channel, string name, key id, string msg)\nsets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen</string>
- <string name="LSLTipText_llListenControl">llListenControl(integer number, integer active)\nmakes a listen event callback active or inactive</string>
- <string name="LSLTipText_llListenRemove">llListenRemove(integer number)\nremoves listen event callback number</string>
- <string name="LSLTipText_llSensor">llSensor(string name, key id, integer type, float range, float arc)\nPerforms a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0)</string>
- <string name="LSLTipText_llSensorRepeat">llSensorRepeat(string name, key id, integer type, float range, float arc, float rate)\nsets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds</string>
- <string name="LSLTipText_llSensorRemove">llSensorRemove()\nremoves sensor</string>
- <string name="LSLTipText_llDetectedName">string llDetectedName(integer number)\nreturns the name of detected object number (returns empty string if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedKey">key llDetectedKey(integer number)\nreturns the key of detected object number (returns empty key if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedOwner">key llDetectedOwner(integer number)\nreturns the key of detected object&apos;s owner (returns empty key if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedType">integer llDetectedType(integer number)\nreturns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedPos">vector llDetectedPos(integer number)\nreturns the position of detected object number (returns &lt;0,0,0&gt; if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedVel">vector llDetectedVel(integer number)\nreturns the velocity of detected object number (returns &lt;0,0,0&gt; if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedGrab">vector llDetectedGrab(integer number)\nreturns the grab offset of the user touching object (returns &lt;0,0,0&gt; if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedRot">rotation llDetectedRot(integer number)\nreturns the rotation of detected object number (returns &lt;0,0,0,1&gt; if number is not valid sensed object)</string>
- <string name="LSLTipText_llDetectedGroup">integer llDetectedGroup(integer number)\nReturns TRUE if detected object is part of same group as owner</string>
- <string name="LSLTipText_llDetectedLinkNumber">integer llDetectedLinkNumber(integer number)\nreturns the link position of the triggered event for touches and collisions only</string>
- <string name="LSLTipText_llDie">llDie()\ndeletes the object</string>
- <string name="LSLTipText_llGround">float llGround(vector v)\nreturns the ground height below the object position + v</string>
- <string name="LSLTipText_llCloud">float llCloud(vector v)\nreturns the cloud density at the object position + v</string>
- <string name="LSLTipText_llWind">vector llWind(vector v)\nreturns the wind velocity at the object position + v</string>
- <string name="LSLTipText_llSetStatus">llSetStatus(integer status, integer value)\nsets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB,\nSTATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value</string>
- <string name="LSLTipText_llGetStatus">integer llGetStatus(integer status)\ngets value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB,\nSTATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z)</string>
- <string name="LSLTipText_llSetScale">llSetScale(vector scale)\nsets the scale</string>
- <string name="LSLTipText_llGetScale">vector llGetScale()\ngets the scale</string>
- <string name="LSLTipText_llSetColor">llSetColor(vector color, integer face)\nsets the color</string>
- <string name="LSLTipText_llGetAlpha">float llGetAlpha(integer face)\ngets the alpha</string>
- <string name="LSLTipText_llSetAlpha">llSetAlpha(float alpha, integer face)\nsets the alpha</string>
- <string name="LSLTipText_llGetColor">vector llGetColor(integer face)\ngets the color</string>
- <string name="LSLTipText_llSetTexture">llSetTexture(string texture, integer face)\nsets the texture of face</string>
- <string name="LSLTipText_llScaleTexture">llScaleTexture(float scales, float scalet, integer face)\nsets the texture s, t scales for the chosen face</string>
- <string name="LSLTipText_llOffsetTexture">llOffsetTexture(float offsets, float offsett, integer face)\nsets the texture s, t offsets for the chosen face</string>
- <string name="LSLTipText_llRotateTexture">llRotateTexture(float rotation, integer face)\nsets the texture rotation for the chosen face</string>
- <string name="LSLTipText_llGetTexture">string llGetTexture(integer face)\ngets the texture of face (if it&apos;s a texture in the object inventory, otherwise the key in a string)</string>
- <string name="LSLTipText_llSetPos">llSetPos(vector pos)\nsets the position (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llGetPos">vector llGetPos()\ngets the position (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llGetLocalPos">vector llGetLocalPos()\ngets the position relative to the root (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llSetRot">llSetRot(rotation rot)\nsets the rotation (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llGetRot">rotation llGetRot()\ngets the rotation (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llGetLocalRot">rotation llGetLocalRot()\ngets the rotation local to the root (if the script isn&apos;t physical)</string>
- <string name="LSLTipText_llSetForce">llSetForce(vector force, integer local)\nsets force on object, in local coords if local == TRUE (if the script is physical)</string>
- <string name="LSLTipText_llGetForce">vector llGetForce()\ngets the force (if the script is physical)</string>
- <string name="LSLTipText_llTarget">integer llTarget(vector position, float range)\nset positions within range of position as a target and return an ID for the target</string>
- <string name="LSLTipText_llTargetRemove">llTargetRemove(integer number)\nremoves target number</string>
- <string name="LSLTipText_llRotTarget">integer llRotTarget(rotation rot, float error)\nset rotations with error of rot as a rotational target and return an ID for the rotational target</string>
- <string name="LSLTipText_llRotTargetRemove">llRotTargetRemove(integer number)\nremoves rotational target number</string>
- <string name="LSLTipText_llMoveToTarget">llMoveToTarget(vector target, float tau)\ncritically damp to target in tau seconds (if the script is physical)</string>
- <string name="LSLTipText_llStopMoveToTarget">llStopMoveToTarget()\nStops critically damped motion</string>
- <string name="LSLTipText_llApplyImpulse">llApplyImpulse(vector force, integer local)\napplies impulse to object, in local coords if local == TRUE (if the script is physical)</string>
- <string name="LSLTipText_llApplyRotationalImpulse">llApplyRotationalImpulse(vector force, integer local)\napplies rotational impulse to object, in local coords if local == TRUE (if the script is physical)</string>
- <string name="LSLTipText_llSetTorque">llSetTorque(vector torque, integer local)\nsets the torque of object, in local coords if local == TRUE (if the script is physical)</string>
- <string name="LSLTipText_llGetTorque">vector llGetTorque()\ngets the torque (if the script is physical)</string>
- <string name="LSLTipText_llSetForceAndTorque">llSetForceAndTorque(vector force, vector torque, integer local)\nsets the force and torque of object, in local coords if local == TRUE (if the script is physical)</string>
- <string name="LSLTipText_llGetVel">vector llGetVel()\ngets the velocity</string>
- <string name="LSLTipText_llGetAccel">vector llGetAccel()\ngets the acceleration</string>
- <string name="LSLTipText_llGetOmega">vector llGetOmega()\ngets the omega</string>
- <string name="LSLTipText_llGetTimeOfDay">float llGetTimeOfDay()\ngets the time in seconds since Second Life server midnight (or since server up-time; whichever is smaller)</string>
- <string name="LSLTipText_llGetWallclock">float llGetWallclock()\ngets the time in seconds since midnight</string>
- <string name="LSLTipText_llGetTime">float llGetTime()\ngets the time in seconds since creation</string>
- <string name="LSLTipText_llResetTime">llResetTime()\nsets the time to zero</string>
- <string name="LSLTipText_llGetAndResetTime">float llGetAndResetTime()\ngets the time in seconds since creation and sets the time to zero</string>
- <string name="LSLTipText_llSound">llSound(string sound, float volume, integer queue, integer loop)\nplays sound at volume and whether it should loop or not</string>
- <string name="LSLTipText_llPlaySound">llPlaySound(string sound, float volume)\nplays attached sound once at volume (0.0 - 1.0)</string>
- <string name="LSLTipText_llLoopSound">llLoopSound(string sound, float volume)\nplays attached sound looping indefinitely at volume (0.0 - 1.0)</string>
- <string name="LSLTipText_llLoopSoundMaster">llLoopSoundMaster(string sound, float volume)\nplays attached sound looping at volume (0.0 - 1.0), declares it a sync master</string>
- <string name="LSLTipText_llLoopSoundSlave">llLoopSoundSlave(string sound, float volume)\nplays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master</string>
- <string name="LSLTipText_llPlaySoundSlave">llPlaySoundSlave(string sound, float volume)\nplays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master</string>
- <string name="LSLTipText_llTriggerSound">llTriggerSound(string sound, float volume)\nplays sound at volume (0.0 - 1.0), centered at but not attached to object</string>
- <string name="LSLTipText_llStopSound">llStopSound()\nStops currently attached sound</string>
- <string name="LSLTipText_llPreloadSound">llPreloadSound(string sound)\npreloads a sound on viewers within range</string>
- <string name="LSLTipText_llGetSubString">string llGetSubString(string src, integer start, integer end)\nreturns the indicated substring</string>
- <string name="LSLTipText_llDeleteSubString">string llDeleteSubString(string src, integer start, integer end)\nremoves the indicated substring and returns the result</string>
- <string name="LSLTipText_llInsertString">string llInsertString(string dst, integer position, string src)\ninserts src into dst at position and returns the result</string>
- <string name="LSLTipText_llToUpper">string llToUpper(string src)\nconvert src to all upper case and returns the result</string>
- <string name="LSLTipText_llToLower">string llToLower(string src)\nconvert src to all lower case and returns the result</string>
- <string name="LSLTipText_llGiveMoney">llGiveMoney(key destination, integer amount)\ntransfer amount of money from script owner to destination</string>
- <string name="LSLTipText_llMakeExplosion">llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake a round explosion of particles</string>
- <string name="LSLTipText_llMakeFountain">llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset)\nMake a fountain of particles</string>
- <string name="LSLTipText_llMakeSmoke">llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake smoke like particles</string>
- <string name="LSLTipText_llMakeFire">llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake fire like particles</string>
- <string name="LSLTipText_llRezObject">llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param)\nInstanciate owners inventory object at pos with velocity vel and rotation rot with start parameter param</string>
- <string name="LSLTipText_llLookAt">llLookAt(vector target, F32 strength, F32 damping)\nCause object name to point it&apos;s forward axis towards target</string>
- <string name="LSLTipText_llStopLookAt">llStopLookAt()\nStop causing object name to point at a target</string>
- <string name="LSLTipText_llSetTimerEvent">llSetTimerEvent(float sec)\nCause the timer event to be triggered every sec seconds</string>
- <string name="LSLTipText_llSleep">llSleep(float sec)\nPut script to sleep for sec seconds</string>
- <string name="LSLTipText_llGetMass">float llGetMass()\nGet the mass of task name that script is attached to</string>
- <string name="LSLTipText_llCollisionFilter">llCollisionFilter(string name, key id, integer accept)\nif accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id</string>
- <string name="LSLTipText_llTakeControls">llTakeControls(integer controls, integer accept, integer pass_on)\nTake controls from agent task has permissions for. If (accept == (controls &amp; input)), send input to task. If pass_on send to agent also.</string>
- <string name="LSLTipText_llReleaseControls">llReleaseControls()\nStop taking inputs</string>
- <string name="LSLTipText_llAttachToAvatar">llAttachToAvatar(integer attachment)\nAttach to avatar task has permissions for at point attachment</string>
- <string name="LSLTipText_llDetachFromAvatar">llDetachFromAvatar()\nDrop off of avatar</string>
- <string name="LSLTipText_llTakeCamera">llTakeCamera(key avatar)\nMove avatar&apos;s viewpoint to task</string>
- <string name="LSLTipText_llReleaseCamera">llReleaseCamera(key avatar)\nReturn camera to agent</string>
- <string name="LSLTipText_llGetOwner">key llGetOwner()\nReturns the owner of the task</string>
- <string name="LSLTipText_llInstantMessage">llInstantMessage(key user, string message)\nIMs message to the user</string>
- <string name="LSLTipText_llEmail">llEmail(string address, string subject, string message)\nSends email to address with subject and message</string>
- <string name="LSLTipText_llGetNextEmail">llGetNextEmail(string address, string subject)\nGet the next waiting email with appropriate address and/or subject (if blank they are ignored)</string>
- <string name="LSLTipText_llGetKey">key llGetKey()\nGet the key for the task the script is attached to</string>
- <string name="LSLTipText_llSetBuoyancy">llSetBuoyancy(float buoyancy)\nSet the tasks buoyancy (0 is none, &lt; 1.0 sinks, 1.0 floats, > 1.0 rises)</string>
- <string name="LSLTipText_llSetHoverHeight">llSetHoverHeight(float height, integer water, float tau)\nCritically damps to a height (either above ground level or above the higher of land and water if water == TRUE)</string>
- <string name="LSLTipText_llStopHover">llStopHover()\nStop hovering to a height</string>
- <string name="LSLTipText_llMinEventDelay">llMinEventDelay(float delay)\nSet the minimum time between events being handled</string>
- <string name="LSLTipText_llSoundPreload">llSoundPreload(string sound)\npreloads a sound on viewers within range</string>
- <string name="LSLTipText_llRotLookAt">llRotLookAt(rotation target, F32 strength, F32 damping)\nCause object name to point it&apos;s forward axis towards target</string>
- <string name="LSLTipText_llStringLength">integer llStringLength(string str)\nReturns the length of string</string>
- <string name="LSLTipText_llStartAnimation">llStartAnimation(string anim)\nStart animation anim for agent that owns object</string>
- <string name="LSLTipText_llStopAnimation">llStopAnimation(string anim)\nStop animation anim for agent that owns object</string>
- <string name="LSLTipText_llPointAt">llPointAt(vector pos)\nMake agent that owns object point at pos</string>
- <string name="LSLTipText_llStopPointAt">llStopPointAt()\nStop agent that owns object pointing</string>
- <string name="LSLTipText_llTargetOmega">llTargetOmega(vector axis, float spinrate, float gain)\nAttempt to spin at spinrate with strength gain</string>
- <string name="LSLTipText_llGetStartParameter">integer llGetStartParameter()\nGet's the start paramter passed to llRezObject</string>
- <string name="LSLTipText_llGodLikeRezObject">llGodLikeRezObject(key inventory, vector pos)\nrez directly off of a UUID if owner has dog-bit set</string>
- <string name="LSLTipText_llRequestPermissions">llRequestPermissions(key agent, integer perm)\nask agent to allow the script to do perm (NB: Debit, ownership, link, joint, and permission requests can only go to the task's owner)</string>
- <string name="LSLTipText_llGetPermissionsKey">key llGetPermissionsKey()\nReturn agent that permissions are enabled for. NULL_KEY if not enabled</string>
- <string name="LSLTipText_llGetPermissions">integer llGetPermissions()\nreturn what permissions have been enabled</string>
- <string name="LSLTipText_llGetLinkNumber">integer llGetLinkNumber()\nReturns what number in a link set the script is attached to (0 means no link, 1 the root, 2 for first child, etc)</string>
- <string name="LSLTipText_llSetLinkColor">llSetLinkColor(integer linknumber, vector color, integer face)\nIf a task exists in the link chain at linknumber, set face to color</string>
- <string name="LSLTipText_llCreateLink">llCreateLink(key target, integer parent)\nAttempt to link task script is attached to and target (requires permission PERMISSION_CHANGE_LINKS be set). If parent == TRUE, task script is attached to is the root</string>
- <string name="LSLTipText_llBreakLink">llBreakLink(integer linknum)\nDelinks the task with the given link number (requires permission PERMISSION_CHANGE_LINKS be set)</string>
- <string name="LSLTipText_llBreakAllLinks">llBreakAllLinks()\nDelinks all tasks in the link set (requires permission PERMISSION_CHANGE_LINKS be set)</string>
- <string name="LSLTipText_llGetLinkKey">key llGetLinkKey(integer linknum)\nGet the key of linknumber in link set</string>
- <string name="LSLTipText_llGetLinkName">string llGetLinkName(integer linknum)\nGet the name of linknumber in link set</string>
- <string name="LSLTipText_llGetInventoryNumber">integer llGetInventoryNumber(integer type)\nGet the number of items of a given type in the task's inventory.\nValid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ALL</string>
- <string name="LSLTipText_llGetInventoryName">string llGetInventoryName(integer type, integer number)\nGet the name of the inventory item number of type</string>
- <string name="LSLTipText_llSetScriptState">llSetScriptState(string name, integer run)\nControl the state of a script name.</string>
- <string name="LSLTipText_llGetEnergy">float llGetEnergy()\nReturns how much energy is in the object as a percentage of maximum</string>
- <string name="LSLTipText_llGiveInventory">llGiveInventory(key destination, string inventory)\nGive inventory to destination</string>
- <string name="LSLTipText_llRemoveInventory">llRemoveInventory(string inventory)\nRemove the named inventory item</string>
- <string name="LSLTipText_llSetText">llSetText(string text, vector color, float alpha)\nSet text floating over object</string>
- <string name="LSLTipText_llWater">float llWater(vector v)\nreturns the water height below the object position + v</string>
- <string name="LSLTipText_llPassTouches">llPassTouches(integer pass)\nif pass == TRUE, touches are passed from children on to parents (default is FALSE)</string>
- <string name="LSLTipText_llRequestAgentData">key llRequestAgentData(key id, integer data)\nRequests data about agent id. When data is available the dataserver event will be raised</string>
- <string name="LSLTipText_llRequestInventoryData">key llRequestInventoryData(string name)\nRequests data from object's inventory object. When data is available the dataserver event will be raised</string>
- <string name="LSLTipText_llSetDamage">llSetDamage(float damage)\nSets the amount of damage that will be done to an object that this task hits. Task will be killed.</string>
- <string name="LSLTipText_llTeleportAgentHome">llTeleportAgentHome(key id)\nTeleports agent on owner's land to agent's home location</string>
- <string name="LSLTipText_llModifyLand">llModifyLand(integer action, integer size)\nModify land with action (LAND_LEVEL, LAND_RAISE, LAND_LOWER, LAND_SMOOTH, LAND_NOISE, LAND_REVERT)\non size (LAND_SMALL_BRUSH, LAND_MEDIUM_BRUSH, LAND_LARGE_BRUSH)</string>
- <string name="LSLTipText_llCollisionSound">llCollisionSound(string impact_sound, float impact_volume)\nSuppress default collision sounds, replace default impact sounds with impact_sound (empty string to just suppress)</string>
- <string name="LSLTipText_llCollisionSprite">llCollisionSprite(string impact_sprite)\nSuppress default collision sprites, replace default impact sprite with impact_sprite (empty string to just suppress)</string>
- <string name="LSLTipText_llGetAnimation">string llGetAnimation(key id)\nGet the currently playing locomotion animation for avatar id</string>
- <string name="LSLTipText_llResetScript">llResetScript()\nResets the script</string>
- <string name="LSLTipText_llMessageLinked">llMessageLinked(integer linknum, integer num, string str, key id)\nSends num, str, and id to members of the link set (LINK_ROOT sends to root task in a linked set,\nLINK_SET sends to all tasks,\nLINK_ALL_OTHERS to all other tasks,\nLINK_ALL_CHILDREN to all children,\nLINK_THIS to the task the script it is in)</string>
- <string name="LSLTipText_llPushObject">llPushObject(key id, vector impulse, vector ang_impulse, integer local)\nApplies impulse and ang_impulse to object id</string>
- <string name="LSLTipText_llPassCollisions">llPassCollisions(integer pass)\nif pass == TRUE, collisions are passed from children on to parents (default is FALSE)</string>
- <string name="LSLTipText_llGetScriptName">llGetScriptName()\nReturns the script name</string>
- <string name="LSLTipText_llGetNumberOfSides">integer llGetNumberOfSides()\nReturns the number of sides</string>
- <string name="LSLTipText_llAxisAngle2Rot">rotation llAxisAngle2Rot(vector axis, float angle)\nReturns the rotation generated angle about axis</string>
- <string name="LSLTipText_llRot2Axis">vector llRot2Axis(rotation rot)\nReturns the rotation axis represented by rot</string>
- <string name="LSLTipText_llRot2Angle">float llRot2Angle(rotation rot)\nReturns the rotation angle represented by rot</string>
- <string name="LSLTipText_llAcos">float llAcos(float val)\nReturns the arccosine in radians of val</string>
- <string name="LSLTipText_llAsin">float llAsin(float val)\nReturns the arcsine in radians of val</string>
- <string name="LSLTipText_llAngleBetween">float llAngleBetween(rotation a, rotation b)\nReturns angle between rotation a and b</string>
- <string name="LSLTipText_llGetInventoryKey">key llGetInventoryKey(string name)\nReturns the key of the inventory name</string>
- <string name="LSLTipText_llAllowInventoryDrop">llAllowInventoryDrop(integer add)\nIf add == TRUE, users without permissions can still drop inventory items onto task</string>
- <string name="LSLTipText_llGetSunDirection">vector llGetSunDirection()\nReturns the sun direction on the simulator</string>
- <string name="LSLTipText_llGetTextureOffset">vector llGetTextureOffset(integer side)\nReturns the texture offset of side in the x and y components of a vector</string>
- <string name="LSLTipText_llGetTextureScale">vector llGetTextureScale(integer side)\nReturns the texture scale of side in the x and y components of a vector</string>
- <string name="LSLTipText_llGetTextureRot">float llGetTextureRot(integer side)\nReturns the texture rotation of side</string>
- <string name="LSLTipText_llSubStringIndex">integer llSubStringIndex(string source, string pattern)\nFinds index in source where pattern first appears (returns -1 if not found)</string>
- <string name="LSLTipText_llGetOwnerKey">key llGetOwnerKey(key id)\nFind the owner of id</string>
- <string name="LSLTipText_llGetCenterOfMass">vector llGetCenterOfMass()\nGet the object's center of mass</string>
- <string name="LSLTipText_llListSort">list llListSort(list src, integer stride, integer ascending)\nSort the list into blocks of stride in ascending order if ascending == TRUE. Note that sort only works between same types.</string>
- <string name="LSLTipText_llGetListLength">integer llGetListLength(list src)\nGet the number of elements in the list</string>
- <string name="LSLTipText_llList2Integer">integer llList2Integer(list src, integer index)\nCopy the integer at index in the list</string>
- <string name="LSLTipText_llList2Float">float llList2Float(list src, integer index)\nCopy the float at index in the list</string>
- <string name="LSLTipText_llList2String">string llList2String(list src, integer index)\nCopy the string at index in the list</string>
- <string name="LSLTipText_llList2Key">key llList2Key(list src, integer index)\nCopy the key at index in the list</string>
- <string name="LSLTipText_llList2Vector">vector llList2Vector(list src, integer index)\nCopy the vector at index in the list</string>
- <string name="LSLTipText_llList2Rot">rotation llList2Rot(list src, integer index)\nCopy the rotation at index in the list</string>
- <string name="LSLTipText_llList2List">list llList2List(list src, integer start, integer end)\nCopy the slice of the list from start to end</string>
- <string name="LSLTipText_llDeleteSubList">list llDeleteSubList(list src, integer start, integer end)\nRemove the slice from the list and return the remainder</string>
- <string name="LSLTipText_llGetListEntryType">integer llGetListEntryType(list src, integer index)\nReturns the type of the index entry in the list\n(TYPE_INTEGER, TYPE_FLOAT, TYPE_STRING, TYPE_KEY, TYPE_VECTOR, TYPE_ROTATION, or TYPE_INVALID if index is off list)</string>
- <string name="LSLTipText_llList2CSV">string llList2CSV(list src)\nCreate a string of comma separated values from list</string>
- <string name="LSLTipText_llCSV2List">list llCSV2List(string src)\nCreate a list from a string of comma separated values</string>
- <string name="LSLTipText_llListRandomize">list llListRandomize(list src, integer stride)\nReturns a randomized list of blocks of size stride</string>
- <string name="LSLTipText_llList2ListStrided">list llList2ListStrided(list src, integer start, integer end, integer stride)\nCopy the strided slice of the list from start to end</string>
- <string name="LSLTipText_llGetRegionCorner">vector llGetRegionCorner()\nReturns a vector with the south west corner x,y position of the region the object is in</string>
- <string name="LSLTipText_llListInsertList">list llListInsertList(list dest, list src, integer start)\nInserts src into dest at position start</string>
- <string name="LSLTipText_llListFindList">integer llListFindList(list src, list test)\nReturns the start of the first instance of test in src, -1 if not found</string>
- <string name="LSLTipText_llGetObjectName">string llGetObjectName()\nReturns the name of the object script is attached to</string>
- <string name="LSLTipText_llSetObjectName">llSetObjectName(string name)\nSets the objects name</string>
- <string name="LSLTipText_llGetDate">string llGetDate()\nGets the date as YYYY-MM-DD</string>
- <string name="LSLTipText_llEdgeOfWorld">integer llEdgeOfWorld(vector pos, vector dir)\nChecks to see whether the border hit by dir from pos is the edge of the world (has no neighboring simulator)</string>
- <string name="LSLTipText_llGetAgentInfo">integer llGetAgentInfo(key id)\nGets information about agent ID.\nReturns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR.</string>
- <string name="LSLTipText_llAdjustSoundVolume">llAdjustSoundVolume(float volume)\nadjusts volume of attached sound (0.0 - 1.0)</string>
- <string name="LSLTipText_llSetSoundQueueing">llSetSoundQueueing(integer queue)\ndetermines whether attached sound calls wait for the current sound to finish (0 = no [default], nonzero = yes)</string>
- <string name="LSLTipText_llSetSoundRadius">llSetSoundRadius(float radius)\nestablishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered)</string>
- <string name="LSLTipText_llKey2Name">string llKey2Name(key id)\nReturns the name of the object key, iff the object is in the current simulator, otherwise the empty string</string>
- <string name="LSLTipText_llSetTextureAnim">llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate)\nAnimate the texture on the specified face/faces</string>
- <string name="LSLTipText_llTriggerSoundLimited">llTriggerSoundLimited(string sound, float volume, vector tne, vector bsw)\nplays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to AABB defined by vectors top-north-east and bottom-south-west</string>
- <string name="LSLTipText_llEjectFromLand">llEjectFromLand(key pest)\nEjects pest from land that you own</string>
- <string name="LSLTipText_llParseString2List">list llParseString2List(string src, list separators, list spacers)\nBreaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each)</string>
- <string name="LSLTipText_llOverMyLand">integer llOverMyLand(key id)\nReturns TRUE if id is over land owner of object owns, FALSE otherwise</string>
- <string name="LSLTipText_llGetLandOwnerAt">key llGetLandOwnerAt(vector pos)\nReturns the key of the land owner, NULL_KEY if public</string>
- <string name="LSLTipText_llGetNotecardLine">key llGetNotecardLine(string name, integer line)\nReturns line line of notecard name via the dataserver event</string>
- <string name="LSLTipText_llGetAgentSize">vector llGetAgentSize(key id)\nIf the agent is in the same sim as the object, returns the size of the avatar</string>
- <string name="LSLTipText_llSameGroup">integer llSameGroup(key id)\nReturns TRUE if ID is in the same sim and has the same active group, otherwise FALSE</string>
- <string name="LSLTipText_llUnSit">key llUnSit(key id)\nIf agent identified by id is sitting on the object the script is attached to or is over land owned by the objects owner, the agent is forced to stand up</string>
- <string name="LSLTipText_llGroundSlope">vector llGroundSlope(vector v)\nreturns the ground slope below the object position + v</string>
- <string name="LSLTipText_llGroundNormal">vector llGroundNormal(vector v)\nreturns the ground normal below the object position + v</string>
- <string name="LSLTipText_llGroundContour">vector llGroundCountour(vector v)\nreturns the ground contour below the object position + v</string>
- <string name="LSLTipText_llGetAttached">integer llGetAttached()\nreturns the object attachment point or 0 if not attached</string>
- <string name="LSLTipText_llGetFreeMemory">integer llGetFreeMemory()\nreturns the available heap space for the current script</string>
- <string name="LSLTipText_llGetRegionName">string llGetRegionName()\nreturns the current region name</string>
- <string name="LSLTipText_llGetRegionTimeDilation">float llGetRegionTimeDilation()\nreturns the current time dilation as a float between 0 and 1</string>
- <string name="LSLTipText_llGetRegionFPS">float llGetRegionFPS()\nreturns the mean region frames per second</string>
- <string name="LSLTipText_llParticleSystem">llParticleSystem(list rules)\nCreates a particle system based on rules. Empty list removes particle system from object.\nList format is [ rule1, data1, rule2, data2 . . . rulen, datan ]</string>
- <string name="LSLTipText_llGroundRepel">llGroundRepel(float height, integer water, float tau)\nCritically damps to height if within height*0.5 of level (either above ground level or above the higher of land and water if water == TRUE)</string>
- <string name="LSLTipText_llGiveInventoryList">llGiveInventoryList(key destination, string category, list inventory)\nGive inventory to destination in a new category</string>
- <string name="LSLTipText_llSetVehicleType">llSetVehicleType(integer type)\nsets vehicle to one of the default types</string>
- <string name="LSLTipText_llSetVehicleFloatParam">llSetVehicleFloatParam(integer param, float value)\nsets the specified vehicle float parameter</string>
- <string name="LSLTipText_llSetVehicleVectorParam">llSetVehicleVectorParam(integer param, vector vec)\nsets the specified vehicle vector parameter</string>
- <string name="LSLTipText_llSetVehicleRotationParam">llSetVehicleVectorParam(integer param, rotation rot)\nsets the specified vehicle rotation parameter</string>
- <string name="LSLTipText_llSetVehicleFlags">llSetVehicleFlags(integer flags)\nsets the enabled bits in 'flags'</string>
- <string name="LSLTipText_llRemoveVehicleFlags">llRemoveVehicleFlags(integer flags)\nremoves the enabled bits in 'flags'</string>
- <string name="LSLTipText_llSitTarget">llSitTarget(vector offset, rotation rot)\nSet the sit location for this object (if offset == &lt;0,0,0&gt; clear it)</string>
- <string name="LSLTipText_llAvatarOnSitTarget">key llAvatarOnSitTarget()\nIf an avatar is sitting on the sit target, return the avatar's key, NULL_KEY otherwise</string>
- <string name="LSLTipText_llAddToLandPassList">llAddToLandPassList(key avatar, float hours)\nAdd avatar to the land pass list for hours</string>
- <string name="LSLTipText_llSetTouchText">llSetTouchText(string text)\nDisplays text in pie menu that acts as a touch</string>
- <string name="LSLTipText_llSetSitText">llSetSitText(string text)\nDisplays text rather than sit in pie menu</string>
- <string name="LSLTipText_llSetCameraEyeOffset">llSetCameraEyeOffset(vector offset)\nSets the camera eye offset used in this object if an avatar sits on it</string>
- <string name="LSLTipText_llSetCameraAtOffset">llSetCameraAtOffset(vector offset)\nSets the camera at offset used in this object if an avatar sits on it</string>
- <string name="LSLTipText_llDumpList2String">string llDumpList2String(list src, string separator)\nWrite the list out in a single string using separator between values</string>
- <string name="LSLTipText_llScriptDanger">integer llScriptDanger(vector pos)\nReturns true if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts</string>
- <string name="LSLTipText_llDialog">llDialog(key avatar, string message, list buttons, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nUp to 12 strings in the list form buttons.\nIf a button is clicked, the name is chatted on chat_channel.</string>
- <string name="LSLTipText_llVolumeDetect">llVolumeDetect(integer detect)\nIf detect = TRUE, object becomes phantom but triggers collision_start and collision_end events\nwhen other objects start and stop interpenetrating.\nMust be applied to the root object.</string>
- <string name="LSLTipText_llResetOtherScript">llResetOtherScript(string name)\nResets script name</string>
- <string name="LSLTipText_llGetScriptState">integer llGetScriptState(string name)\nResets TRUE if script name is running</string>
- <string name="LSLTipText_llRemoteLoadScript">Deprecated. Please use llRemoteLoadScriptPin instead.</string>
- <string name="LSLTipText_llSetRemoteScriptAccessPin">llSetRemoteScriptAccessPin(integer pin)\nIf pin is set to a non-zero number, the task will accept remote script\nloads via llRemoteLoadScriptPin if it passes in the correct pin.\nOthersise, llRemoteLoadScriptPin is ignored.</string>
- <string name="LSLTipText_llRemoteLoadScriptPin">llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)\nIf the owner of the object this script is attached can modify target,\nthey are in the same region,\nand the matching pin is used,\ncopy script name onto target,\nif running == TRUE, start the script with param.</string>
- <string name="LSLTipText_llOpenRemoteDataChannel">llOpenRemoteDataChannel()\nCreates a channel to listen for XML-RPC calls. Will trigger a remote_data event with channel id once it is available.</string>
- <string name="LSLTipText_llSendRemoteData">key llSendRemoteData(key channel, string dest, integer idata, string sdata)\nSend an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata.\nA message identifier key is returned.\nAn XML-RPC reply will trigger a remote_data event and reference the message id.\nThe message_id is returned.</string>
- <string name="LSLTipText_llRemoteDataReply">llRemoteDataReply(key channel, key message_id, string sdata, integer idata)\nSend an XML-RPC reply to message_id on channel with payload of string sdata and integer idata</string>
- <string name="LSLTipText_llCloseRemoteDataChannel">llCloseRemoteDataChannel(key channel)\nCloses XML-RPC channel.</string>
- <string name="LSLTipText_llMD5String">string llMD5String(string src, integer nonce)\nPerforms a RSA Data Security, Inc. MD5 Message-Digest Algorithm on string with nonce. Returns a 32 character hex string.</string>
- <string name="LSLTipText_llSetPrimitiveParams">llSetPrimitiveParams(list rules)\nSet primitive parameters based on rules.</string>
- <string name="LSLTipText_llStringToBase64">string llStringToBase64(string str)\nConverts a string to the Base 64 representation of the string.</string>
- <string name="LSLTipText_llBase64ToString">string llBase64ToString(string str)\nConverts a Base 64 string to a conventional string. If the conversion creates any unprintable characters, they are converted to spaces.</string>
- <string name="LSLTipText_llXorBase64Strings">string llXorBase64Strings(string s1, string s2)\nDEPRECATED! Please use llXorBase64StringsCorrect instead!! Incorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability.</string>
- <string name="LSLTipText_llRemoteDataSetRegion">llRemoteDataSetRegion()\nIf an object using remote data channels changes regions, you must call this function to reregister the remote data channels.\nYou do not need to make this call if you don't change regions.</string>
- <string name="LSLTipText_llLog10">float llLog10(float val)\nReturns the base 10 log of val if val &gt; 0, otherwise returns 0.</string>
- <string name="LSLTipText_llLog">float llLog(float val)\nReturns the base e log of val if val &gt; 0, otherwise returns 0.</string>
- <string name="LSLTipText_llGetAnimationList">list llGetAnimationList(key id)\nGets a list of all playing animations for avatar id</string>
- <string name="LSLTipText_llSetParcelMusicURL">llSetParcelMusicURL(string url)\nSets the streaming audio URL for the parcel object is on</string>
- <string name="LSLTipText_llGetRootPosition">vector llGetRootPosition()\nGets the global position of the root object of the object script is attached to</string>
- <string name="LSLTipText_llGetRootRotation">rotation llGetRootRotation()\nGets the global rotation of the root object of the object script is attached to</string>
- <string name="LSLTipText_llGetObjectDesc">string llGetObjectDesc()\nReturns the description of the object the script is attached to</string>
- <string name="LSLTipText_llSetObjectDesc">llSetObjectDesc(string name)\nSets the object's description</string>
- <string name="LSLTipText_llGetCreator">key llGetCreator()\nReturns the creator of the object</string>
- <string name="LSLTipText_llGetTimestamp">string llGetTimestamp()\nGets the timestamp in the format: YYYY-MM-DDThh:mm:ss.ff..fZ</string>
- <string name="LSLTipText_llSetLinkAlpha">llSetLinkAlpha(integer linknumber, float alpha, integer face)\nIf a prim exists in the link chain at linknumber, set face to alpha</string>
- <string name="LSLTipText_llGetNumberOfPrims">integer llGetNumberOfPrims()\nReturns the number of prims in a link set the script is attached to</string>
- <string name="LSLTipText_llGetNumberOfNotecardLines">key llGetNumberOfNotecardLines(string name)\nReturns number of lines in notecard 'name' via the dataserver event (cast return value to integer)</string>
- <string name="LSLTipText_llGetBoundingBox">list llGetBoundingBox(key object)\nReturns the bounding box around an object (including any linked prims) relative to the root prim, in a list: [ (vector) min_corner, (vector) max_corner ]</string>
- <string name="LSLTipText_llGetGeometricCenter">vector llGetGeometricCenter()\nReturns the geometric center of the linked set the script is attached to.</string>
- <string name="LSLTipText_llGetPrimitiveParams">list llGetPrimitiveParams(list params)\nGets primitive parameters specified in the params list.</string>
- <string name="LSLTipText_llIntegerToBase64">string llIntegerToBase64(integer number)\nBig endian encode of of integer as a Base64 string.</string>
- <string name="LSLTipText_llBase64ToInteger">integer llBase64ToInteger(string str)\nBig endian decode of a Base64 string into an integer.</string>
- <string name="LSLTipText_llGetGMTclock">float llGetGMTclock()\nGets the time in seconds since midnight in GMT</string>
- <string name="LSLTipText_llGetSimulatorHostname">string llGetSimulatorHostname()\nGets the hostname of the machine script is running on (same as string in viewer Help dialog)</string>
- <string name="LSLTipText_llSetLocalRot">llSetLocalRot(rotation rot)\nsets the rotation of a child prim relative to the root prim</string>
- <string name="LSLTipText_llParseStringKeepNulls">list llParseStringKeepNulls(string src, list separators, list spacers)\nBreaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each), keeping any null values generated.</string>
- <string name="LSLTipText_llRezAtRoot">llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param)\nInstantiate owner's inventory object at pos with velocity vel and rotation rot with start parameter param.\nThe last selected root object's location will be set to pos</string>
- <string name="LSLTipText_llGetObjectPermMask">integer llGetObjectPermMask(integer mask)\nReturns the requested permission mask for the root object the task is attached to.</string>
- <string name="LSLTipText_llSetObjectPermMask">llSetObjectPermMask(integer mask, integer value)\nSets the given permission mask to the new value on the root object the task is attached to.</string>
- <string name="LSLTipText_llGetInventoryPermMask">integer llGetInventoryPermMask(string item, integer mask)\nReturns the requested permission mask for the inventory item.</string>
- <string name="LSLTipText_llSetInventoryPermMask">llSetInventoryPermMask(string item, integer mask, integer value)\nSets the given permission mask to the new value on the inventory item.</string>
- <string name="LSLTipText_llGetInventoryCreator">key llGetInventoryCreator(string item)\nReturns the key for the creator of the inventory item.</string>
- <string name="LSLTipText_llOwnerSay">llOwnerSay(string msg)\nsays msg to owner only (if owner in sim)</string>
- <string name="LSLTipText_llRequestSimulatorData">key llRequestSimulatorData(string simulator, integer data)\nRequests data about simulator. When data is available the dataserver event will be raised</string>
- <string name="LSLTipText_llForceMouselook">llForceMouselook(integer mouselook)\nIf mouselook is TRUE any avatar that sits on this object is forced into mouselook mode</string>
- <string name="LSLTipText_llGetObjectMass">float llGetObjectMass(key id)\nGet the mass of the object with key id</string>
- <string name="LSLTipText_llListReplaceList">list llListReplaceList(list dest, list src, integer start, integer end)\nReplaces start through end of dest with src.</string>
- <string name="LSLTipText_llLoadURL">llLoadURL(key avatar_id, string message, string url)\nShows dialog to avatar avatar_id offering to load web page at URL. If user clicks yes, launches their web browser.</string>
- <string name="LSLTipText_llParcelMediaCommandList">llParcelMediaCommandList(list command)\nSends a list of commands, some with arguments, to a parcel.</string>
- <string name="LSLTipText_llParcelMediaQuery">list llParcelMediaQuery(list query)\nSends a list of queries, returns a list of results.</string>
- <string name="LSLTipText_llModPow">integer llModPow(integer a, integer b, integer c)\nReturns a raised to the b power, mod c. ( (a**b)%c ). b is capped at 0xFFFF (16 bits).</string>
- <string name="LSLTipText_llGetInventoryType">integer llGetInventoryType(string name)\nReturns the type of the inventory name</string>
- <string name="LSLTipText_llSetPayPrice">llSetPayPrice(integer price, list quick_pay_buttons)\nSets the default amount when someone chooses to pay this object.</string>
- <string name="LSLTipText_llGetCameraPos">vector llGetCameraPos()\nGets current camera position for agent task has permissions for.</string>
- <string name="LSLTipText_llGetCameraRot">rotation llGetCameraRot()\nGets current camera orientation for agent task has permissions for.</string>
- <string name="LSLTipText_llSetPrimURL">llSetPrimURL(string url)\nUpdates the URL for the web page shown on the sides of the object.</string>
- <string name="LSLTipText_llRefreshPrimURL">llRefreshPrimURL()\nReloads the web page shown on the sides of the object.</string>
- <string name="LSLTipText_llEscapeURL">string llEscapeURL(string url)\nReturns and escaped/encoded version of url, replacing spaces with %20 etc.</string>
- <string name="LSLTipText_llUnescapeURL">string llUnescapeURL(string url)\nReturns and unescaped/unencoded version of url, replacing %20 with spaces etc.</string>
- <string name="LSLTipText_llMapDestination">llMapDestination(string simname, vector pos, vector look_at)\nOpens world map centered on region with pos highlighted.\nOnly works for scripts attached to avatar, or during touch events.\n(NOTE: look_at currently does nothing)</string>
- <string name="LSLTipText_llAddToLandBanList">llAddToLandBanList(key avatar, float hours)\nAdd avatar to the land ban list for hours</string>
- <string name="LSLTipText_llRemoveFromLandPassList">llRemoveFromLandPassList(key avatar)\nRemove avatar from the land pass list</string>
- <string name="LSLTipText_llRemoveFromLandBanList">llRemoveFromLandBanList(key avatar)\nRemove avatar from the land ban list</string>
- <string name="LSLTipText_llSetCameraParams">llSetCameraParams(list rules)\nSets multiple camera parameters at once.\nList format is [ rule1, data1, rule2, data2 . . . rulen, datan ]</string>
- <string name="LSLTipText_llClearCameraParams">llClearCameraParams()\nResets all camera parameters to default values and turns off scripted camera control.</string>
- <string name="LSLTipText_llListStatistics">float llListStatistics(integer operation, list l)\nPerform statistical aggregate functions on list l using LIST_STAT_* operations.</string>
- <string name="LSLTipText_llGetUnixTime">integer llGetUnixTime()\nGet the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock.</string>
- <string name="LSLTipText_llGetParcelFlags">integer llGetParcelFlags(vector pos)\nGet the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos.</string>
- <string name="LSLTipText_llGetRegionFlags">integer llGetRegionFlags()\nGet the region flags (REGION_FLAG_*) for the region the object is in.</string>
- <string name="LSLTipText_llXorBase64StringsCorrect">string llXorBase64StringsCorrect(string s1, string s2)\nCorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1.</string>
- <string name="LSLTipText_llHTTPRequest">llHTTPRequest(string url, list parameters, string body)\nSend an HTTP request.</string>
- <string name="LSLTipText_llResetLandBanList">llResetLandBanList()\nRemoves all residents from the land ban list.</string>
- <string name="LSLTipText_llResetLandPassList">llResetLandPassList()\nRemoves all residents from the land access/pass list.</string>
- <string name="LSLTipText_llGetObjectPrimCount">integer llGetObjectPrimCount(key object_id)\nReturns the total number of prims for an object.</string>
- <string name="LSLTipText_llGetParcelPrimOwners">list llGetParcelPrimOwners(vector pos)\nReturns a list of all residents who own objects on the parcel and the number of objects they own.\nRequires owner-like permissions for the parcel.</string>
- <string name="LSLTipText_llGetParcelPrimCount">integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)\nGets the number of prims on the parcel of the given category.\nCategories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP.</string>
- <string name="LSLTipText_llGetParcelMaxPrims">integer llGetParcelMaxPrims(vector pos, integer sim_wide)\nGets the maximum number of prims allowed on the parcel at pos.</string>
- <string name="LSLTipText_llGetParcelDetails">list llGetParcelDetails(vector pos, list params)\nGets the parcel details specified in params for the parcel at pos.\nParams is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA</string>
- <string name="LSLTipText_llSetLinkPrimitiveParams">llSetLinkPrimitiveParams(integer linknumber, list rules)\nSet primitive parameters for linknumber based on rules.</string>
- <string name="LSLTipText_llSetLinkTexture">llSetLinkTexture(integer link_pos, string texture, integer face)\nSets the texture of face for link_pos</string>
- <string name="LSLTipText_llStringTrim">string llStringTrim(string src, integer trim_type)\nTrim leading and/or trailing spaces from a string.\nUses trim_type of STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL.</string>
- <string name="LSLTipText_llRegionSay">llRegionSay(integer channel, string msg)\nbroadcasts msg to entire region on channel (not 0.)</string>
- <string name="LSLTipText_llGetObjectDetails">list llGetObjectDetails(key id, list params)\nGets the object details specified in params for the object with key id.\nDetails are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR.</string>
- <string name="LSLTipText_llSetClickAction">llSetClickAction(integer action)\nSets the action performed when a prim is clicked upon.</string>
- <string name="LSLTipText_llGetRegionAgentCount">int llGetRegionAgentCount()\nreturns the number of agents in a region</string>
- <string name="LSLTipText_llTextBox">llTextBox(key avatar, string message, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nA text box asks for input, and if entered the text is chatted on chat_channel.</string>
- <string name="LSLTipText_llGetAgentLanguage">string llGetAgentLanguage(key id)\nGets the agents preferred language..</string>
- <string name="LSLTipText_llDetectedTouchUV">vector llDetectedTouchUV(integer number)\nreturns the u and v coordinates in the first two components of a vector, for a triggered touch event</string>
- <string name="LSLTipText_llDetectedTouchFace">integer llDetectedTouchFace(integer number)\nreturns the index of the face on the object for a triggered touch event</string>
- <string name="LSLTipText_llDetectedTouchPos">vector llDetectedTouchPos(integer number)\nreturns the position touched for a triggered touch event</string>
- <string name="LSLTipText_llDetectedTouchNormal">vector llDetectedTouchNormal(integer number)\nreturns the surface normal for a triggered touch event</string>
- <string name="LSLTipText_llDetectedTouchBinormal">vector llDetectedTouchBinormal(integer number)\nreturns the surface binormal for a triggered touch event</string>
- <string name="LSLTipText_llDetectedTouchST">vector llDetectedTouchST(integer number)\nreturns the s and t coordinates in the first two components of a vector, for a triggered touch event</string>
- <string name="LSLTipText_llSHA1String">string llSHA1String(string sr)\nPerforms a SHA1 security Hash. Returns a 40 character hex string.</string>
- <string name="LSLTipText_llGetFreeURLs">integer llGetFreeURLs()\nreturns the available urls for the current script</string>
- <string name="LSLTipText_llRequestURL">key llRequestURL()\nRequests one HTTP:// url for use by this object\nTriggers an http_server event with results.</string>
- <string name="LSLTipText_llRequestSecureURL">key llRequestSecureURL()\nRequests one HTTPS:// (SSL) url for use by this object\nTriggers an http_server event with results.</string>
- <string name="LSLTipText_llReleaseURL">llReleaseURL(string url)\nReleases the specified URL, it will no longer be usable.</string>
- <string name="LSLTipText_llHTTPResponse">llHTTPResponse(key id, integer status, string body)\nResponds to request id with status and body.</string>
- <string name="LSLTipText_llGetHTTPHeader">string llGetHTTPHeader(key id, string header)\nGet the value for header for request id.</string>
+ <string name="LSLTipText_llSin">
+float llSin(float theta)
+theta in radians
+ </string>
+ <string name="LSLTipText_llCos">
+float llCos(float theta)
+theta in radians
+ </string>
+ <string name="LSLTipText_llTan">
+float llTan(float theta)
+theta radians
+ </string>
+ <string name="LSLTipText_llAtan2">
+float llAtan2(float y, float x)
+ </string>
+ <string name="LSLTipText_llSqrt">
+float llSqrt(float val)
+returns 0 and triggers a Math Error for imaginary results
+ </string>
+ <string name="LSLTipText_llPow">
+float llPow(float base, float exponent)
+returns 0 and triggers Math Error for imaginary results
+ </string>
+ <string name="LSLTipText_llAbs">
+integer llAbs(integer val)
+ </string>
+ <string name="LSLTipText_llFabs">
+float llFabs(float val)
+ </string>
+ <string name="LSLTipText_llFrand">
+float llFrand(float mag)
+returns random number in range [0,mag)
+ </string>
+ <string name="LSLTipText_llFloor">
+integer llFloor(float val)
+returns largest integer value &lt;= val
+ </string>
+ <string name="LSLTipText_llCeil">
+integer llCeil(float val)
+returns smallest integer value &gt;= val
+ </string>
+ <string name="LSLTipText_llRound">
+integer llRound(float val)
+returns val rounded to the nearest integer
+ </string>
+ <string name="LSLTipText_llVecMag">
+float llVecMag(vector v)
+returns the magnitude of v
+ </string>
+ <string name="LSLTipText_llVecNorm">
+vector llVecNorm(vector v)
+returns the v normalized
+ </string>
+ <string name="LSLTipText_llVecDist">
+float llVecDist(vector v1, vector v2)
+returns the 3D distance between v1 and v2
+ </string>
+ <string name="LSLTipText_llRot2Euler">
+vector llRot2Euler(rotation q)
+returns the Euler representation (roll, pitch, yaw) of q
+ </string>
+ <string name="LSLTipText_llEuler2Rot">
+rotation llEuler2Rot(vector v)
+returns the rotation representation of Euler Angles v
+ </string>
+ <string name="LSLTipText_llAxes2Rot">
+rotation llAxes2Rot(vector fwd, vector left, vector up)
+returns the rotation defined by the coordinate axes
+ </string>
+ <string name="LSLTipText_llRot2Fwd">
+vector llRot2Fwd(rotation q)
+returns the forward vector defined by q
+ </string>
+ <string name="LSLTipText_llRot2Left">
+vector llRot2Left(rotation q)
+returns the left vector defined by q
+ </string>
+ <string name="LSLTipText_llRot2Up">
+vector llRot2Up(rotation q)
+returns the up vector defined by q
+ </string>
+ <string name="LSLTipText_llRotBetween">
+rotation llRotBetween(vector v1, vector v2)
+returns the rotation to rotate v1 to v2
+ </string>
+ <string name="LSLTipText_llWhisper">
+llWhisper(integer channel, string msg)
+whispers msg on channel
+ </string>
+ <string name="LSLTipText_llSay">
+llSay(integer channel, string msg)
+says msg on channel
+ </string>
+ <string name="LSLTipText_llShout">
+llShout(integer channel, string msg)
+shouts msg on channel
+ </string>
+ <string name="LSLTipText_llListen">
+integer llListen(integer channel, string name, key id, string msg)
+sets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen
+ </string>
+ <string name="LSLTipText_llListenControl">
+llListenControl(integer number, integer active)
+makes a listen event callback active or inactive
+ </string>
+ <string name="LSLTipText_llListenRemove">
+llListenRemove(integer number)
+removes listen event callback number
+ </string>
+ <string name="LSLTipText_llSensor">
+llSensor(string name, key id, integer type, float range, float arc)
+Performs a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0)
+ </string>
+ <string name="LSLTipText_llSensorRepeat">
+llSensorRepeat(string name, key id, integer type, float range, float arc, float rate)
+sets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds
+ </string>
+ <string name="LSLTipText_llSensorRemove">
+llSensorRemove()
+removes sensor
+ </string>
+ <string name="LSLTipText_llDetectedName">
+string llDetectedName(integer number)
+returns the name of detected object number (returns empty string if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedKey">
+key llDetectedKey(integer number)
+returns the key of detected object number (returns empty key if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedOwner">
+key llDetectedOwner(integer number)
+returns the key of detected object&apos;s owner (returns empty key if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedType">
+integer llDetectedType(integer number)
+returns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedPos">
+vector llDetectedPos(integer number)
+returns the position of detected object number (returns &lt;0,0,0&gt; if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedVel">
+vector llDetectedVel(integer number)
+returns the velocity of detected object number (returns &lt;0,0,0&gt; if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedGrab">
+vector llDetectedGrab(integer number)
+returns the grab offset of the user touching object (returns &lt;0,0,0&gt; if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedRot">
+rotation llDetectedRot(integer number)
+returns the rotation of detected object number (returns &lt;0,0,0,1&gt; if number is not valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedGroup">
+integer llDetectedGroup(integer number)
+Returns TRUE if detected object is part of same group as owner
+ </string>
+ <string name="LSLTipText_llDetectedLinkNumber">
+integer llDetectedLinkNumber(integer number)
+returns the link position of the triggered event for touches and collisions only
+ </string>
+ <string name="LSLTipText_llDie">
+llDie()
+deletes the object
+ </string>
+ <string name="LSLTipText_llGround">
+float llGround(vector v)
+returns the ground height below the object position + v
+ </string>
+ <string name="LSLTipText_llCloud">
+float llCloud(vector v)
+returns the cloud density at the object position + v
+ </string>
+ <string name="LSLTipText_llWind">
+vector llWind(vector v)
+returns the wind velocity at the object position + v
+ </string>
+ <string name="LSLTipText_llSetStatus">
+llSetStatus(integer status, integer value)
+sets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value
+ </string>
+ <string name="LSLTipText_llGetStatus">
+integer llGetStatus(integer status)
+gets value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z)
+ </string>
+ <string name="LSLTipText_llSetScale">
+llSetScale(vector scale)
+sets the scale
+ </string>
+ <string name="LSLTipText_llGetScale">
+vector llGetScale()
+gets the scale
+ </string>
+ <string name="LSLTipText_llSetColor">
+llSetColor(vector color, integer face)
+sets the color
+ </string>
+ <string name="LSLTipText_llGetAlpha">
+float llGetAlpha(integer face)
+gets the alpha
+ </string>
+ <string name="LSLTipText_llSetAlpha">
+llSetAlpha(float alpha, integer face)
+sets the alpha
+ </string>
+ <string name="LSLTipText_llGetColor">
+vector llGetColor(integer face)
+gets the color
+ </string>
+ <string name="LSLTipText_llSetTexture">
+llSetTexture(string texture, integer face)
+sets the texture of face
+ </string>
+ <string name="LSLTipText_llScaleTexture">
+llScaleTexture(float scales, float scalet, integer face)
+sets the texture s, t scales for the chosen face
+ </string>
+ <string name="LSLTipText_llOffsetTexture">
+llOffsetTexture(float offsets, float offsett, integer face)
+sets the texture s, t offsets for the chosen face
+ </string>
+ <string name="LSLTipText_llRotateTexture">
+llRotateTexture(float rotation, integer face)
+sets the texture rotation for the chosen face
+ </string>
+ <string name="LSLTipText_llGetTexture">
+string llGetTexture(integer face)
+gets the texture of face (if it&apos;s a texture in the object inventory, otherwise the key in a string)
+ </string>
+ <string name="LSLTipText_llSetPos">
+llSetPos(vector pos)
+sets the position (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llGetPos">
+vector llGetPos()
+gets the position (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llGetLocalPos">
+vector llGetLocalPos()
+gets the position relative to the root (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llSetRot">
+llSetRot(rotation rot)
+sets the rotation (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llGetRot">
+rotation llGetRot()
+gets the rotation (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llGetLocalRot">
+rotation llGetLocalRot()
+gets the rotation local to the root (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llSetForce">
+llSetForce(vector force, integer local)
+sets force on object, in local coords if local == TRUE (if the script is physical)
+ </string>
+ <string name="LSLTipText_llGetForce">
+vector llGetForce()
+gets the force (if the script is physical)
+ </string>
+ <string name="LSLTipText_llTarget">
+integer llTarget(vector position, float range)
+set positions within range of position as a target and return an ID for the target
+ </string>
+ <string name="LSLTipText_llTargetRemove">
+llTargetRemove(integer number)
+removes target number
+ </string>
+ <string name="LSLTipText_llRotTarget">
+integer llRotTarget(rotation rot, float error)
+set rotations with error of rot as a rotational target and return an ID for the rotational target
+ </string>
+ <string name="LSLTipText_llRotTargetRemove">
+llRotTargetRemove(integer number)
+removes rotational target number
+ </string>
+ <string name="LSLTipText_llMoveToTarget">
+llMoveToTarget(vector target, float tau)
+critically damp to target in tau seconds (if the script is physical)
+ </string>
+ <string name="LSLTipText_llStopMoveToTarget">
+llStopMoveToTarget()
+Stops critically damped motion
+ </string>
+ <string name="LSLTipText_llApplyImpulse">
+llApplyImpulse(vector force, integer local)
+applies impulse to object, in local coords if local == TRUE (if the script is physical)
+ </string>
+ <string name="LSLTipText_llApplyRotationalImpulse">
+llApplyRotationalImpulse(vector force, integer local)
+applies rotational impulse to object, in local coords if local == TRUE (if the script is physical)
+ </string>
+ <string name="LSLTipText_llSetTorque">
+llSetTorque(vector torque, integer local)
+sets the torque of object, in local coords if local == TRUE (if the script is physical)
+ </string>
+ <string name="LSLTipText_llGetTorque">
+vector llGetTorque()
+gets the torque (if the script is physical)
+ </string>
+ <string name="LSLTipText_llSetForceAndTorque">
+llSetForceAndTorque(vector force, vector torque, integer local)
+sets the force and torque of object, in local coords if local == TRUE (if the script is physical)
+ </string>
+ <string name="LSLTipText_llGetVel">
+vector llGetVel()
+gets the velocity
+ </string>
+ <string name="LSLTipText_llGetAccel">
+vector llGetAccel()
+gets the acceleration
+ </string>
+ <string name="LSLTipText_llGetOmega">
+vector llGetOmega()
+gets the omega
+ </string>
+ <string name="LSLTipText_llGetTimeOfDay">
+float llGetTimeOfDay()
+gets the time in seconds since [SECOND_LIFE] server midnight (or since server up-time; whichever is smaller)
+ </string>
+ <string name="LSLTipText_llGetWallclock">
+float llGetWallclock()
+gets the time in seconds since midnight
+ </string>
+ <string name="LSLTipText_llGetTime">
+float llGetTime()
+gets the time in seconds since creation
+ </string>
+ <string name="LSLTipText_llResetTime">
+llResetTime()
+sets the time to zero
+ </string>
+ <string name="LSLTipText_llGetAndResetTime">
+float llGetAndResetTime()
+gets the time in seconds since creation and sets the time to zero
+ </string>
+ <string name="LSLTipText_llSound">
+llSound(string sound, float volume, integer queue, integer loop)
+plays sound at volume and whether it should loop or not
+ </string>
+ <string name="LSLTipText_llPlaySound">
+llPlaySound(string sound, float volume)
+plays attached sound once at volume (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llLoopSound">
+llLoopSound(string sound, float volume)
+plays attached sound looping indefinitely at volume (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llLoopSoundMaster">
+llLoopSoundMaster(string sound, float volume)
+plays attached sound looping at volume (0.0 - 1.0), declares it a sync master
+ </string>
+ <string name="LSLTipText_llLoopSoundSlave">
+llLoopSoundSlave(string sound, float volume)
+plays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master
+ </string>
+ <string name="LSLTipText_llPlaySoundSlave">
+llPlaySoundSlave(string sound, float volume)
+plays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master
+ </string>
+ <string name="LSLTipText_llTriggerSound">
+llTriggerSound(string sound, float volume)
+plays sound at volume (0.0 - 1.0), centered at but not attached to object
+ </string>
+ <string name="LSLTipText_llStopSound">
+llStopSound()
+Stops currently attached sound
+ </string>
+ <string name="LSLTipText_llPreloadSound">
+llPreloadSound(string sound)
+preloads a sound on viewers within range
+ </string>
+ <string name="LSLTipText_llGetSubString">
+string llGetSubString(string src, integer start, integer end)
+returns the indicated substring
+ </string>
+ <string name="LSLTipText_llDeleteSubString">
+string llDeleteSubString(string src, integer start, integer end)
+removes the indicated substring and returns the result
+ </string>
+ <string name="LSLTipText_llInsertString">
+string llInsertString(string dst, integer position, string src)
+inserts src into dst at position and returns the result
+ </string>
+ <string name="LSLTipText_llToUpper">
+string llToUpper(string src)
+convert src to all upper case and returns the result
+ </string>
+ <string name="LSLTipText_llToLower">
+string llToLower(string src)
+convert src to all lower case and returns the result
+ </string>
+ <string name="LSLTipText_llGiveMoney">
+llGiveMoney(key destination, integer amount)
+transfer amount of money from script owner to destination
+ </string>
+ <string name="LSLTipText_llMakeExplosion">
+llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Make a round explosion of particles
+ </string>
+ <string name="LSLTipText_llMakeFountain">
+llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset)
+Make a fountain of particles
+ </string>
+ <string name="LSLTipText_llMakeSmoke">
+llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Make smoke like particles
+ </string>
+ <string name="LSLTipText_llMakeFire">
+llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Make fire like particles
+ </string>
+ <string name="LSLTipText_llRezObject">
+llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param)
+Instanciate owners inventory object at pos with velocity vel and rotation rot with start parameter param
+ </string>
+ <string name="LSLTipText_llLookAt">
+llLookAt(vector target, F32 strength, F32 damping)
+Cause object name to point it&apos;s forward axis towards target
+ </string>
+ <string name="LSLTipText_llStopLookAt">
+llStopLookAt()
+Stop causing object name to point at a target
+ </string>
+ <string name="LSLTipText_llSetTimerEvent">
+llSetTimerEvent(float sec)
+Cause the timer event to be triggered every sec seconds
+ </string>
+ <string name="LSLTipText_llSleep">
+llSleep(float sec)
+Put script to sleep for sec seconds
+ </string>
+ <string name="LSLTipText_llGetMass">
+float llGetMass()
+Get the mass of task name that script is attached to
+ </string>
+ <string name="LSLTipText_llCollisionFilter">
+llCollisionFilter(string name, key id, integer accept)
+if accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id
+ </string>
+ <string name="LSLTipText_llTakeControls">
+llTakeControls(integer controls, integer accept, integer pass_on)
+Take controls from agent task has permissions for. If (accept == (controls &amp; input)), send input to task. If pass_on send to agent also.
+ </string>
+ <string name="LSLTipText_llReleaseControls">
+llReleaseControls()
+Stop taking inputs
+ </string>
+ <string name="LSLTipText_llAttachToAvatar">
+llAttachToAvatar(integer attachment)
+Attach to avatar task has permissions for at point attachment
+ </string>
+ <string name="LSLTipText_llDetachFromAvatar">
+llDetachFromAvatar()
+Drop off of avatar
+ </string>
+ <string name="LSLTipText_llTakeCamera">
+llTakeCamera(key avatar)
+Move avatar&apos;s viewpoint to task
+ </string>
+ <string name="LSLTipText_llReleaseCamera">
+llReleaseCamera(key avatar)
+Return camera to agent
+ </string>
+ <string name="LSLTipText_llGetOwner">
+key llGetOwner()
+Returns the owner of the task
+ </string>
+ <string name="LSLTipText_llInstantMessage">
+llInstantMessage(key user, string message)
+IMs message to the user
+ </string>
+ <string name="LSLTipText_llEmail">
+llEmail(string address, string subject, string message)
+Sends email to address with subject and message
+ </string>
+ <string name="LSLTipText_llGetNextEmail">
+llGetNextEmail(string address, string subject)
+Get the next waiting email with appropriate address and/or subject (if blank they are ignored)
+ </string>
+ <string name="LSLTipText_llGetKey">
+key llGetKey()
+Get the key for the task the script is attached to
+ </string>
+ <string name="LSLTipText_llSetBuoyancy">
+llSetBuoyancy(float buoyancy)
+Set the tasks buoyancy (0 is none, &lt; 1.0 sinks, 1.0 floats, > 1.0 rises)
+ </string>
+ <string name="LSLTipText_llSetHoverHeight">
+llSetHoverHeight(float height, integer water, float tau)
+Critically damps to a height (either above ground level or above the higher of land and water if water == TRUE)
+ </string>
+ <string name="LSLTipText_llStopHover">
+llStopHover()
+Stop hovering to a height
+ </string>
+ <string name="LSLTipText_llMinEventDelay">
+llMinEventDelay(float delay)
+Set the minimum time between events being handled
+ </string>
+ <string name="LSLTipText_llSoundPreload">
+llSoundPreload(string sound)
+preloads a sound on viewers within range
+ </string>
+ <string name="LSLTipText_llRotLookAt">
+llRotLookAt(rotation target, F32 strength, F32 damping)
+Cause object name to point it&apos;s forward axis towards target
+ </string>
+ <string name="LSLTipText_llStringLength">
+integer llStringLength(string str)
+Returns the length of string
+ </string>
+ <string name="LSLTipText_llStartAnimation">
+llStartAnimation(string anim)
+Start animation anim for agent that owns object
+ </string>
+ <string name="LSLTipText_llStopAnimation">
+llStopAnimation(string anim)
+Stop animation anim for agent that owns object
+ </string>
+ <string name="LSLTipText_llPointAt">
+llPointAt(vector pos)
+Make agent that owns object point at pos
+ </string>
+ <string name="LSLTipText_llStopPointAt">
+llStopPointAt()
+Stop agent that owns object pointing
+ </string>
+ <string name="LSLTipText_llTargetOmega">
+llTargetOmega(vector axis, float spinrate, float gain)
+Attempt to spin at spinrate with strength gain
+ </string>
+ <string name="LSLTipText_llGetStartParameter">
+integer llGetStartParameter()
+Get's the start paramter passed to llRezObject
+ </string>
+ <string name="LSLTipText_llGodLikeRezObject">
+llGodLikeRezObject(key inventory, vector pos)
+rez directly off of a UUID if owner has dog-bit set
+ </string>
+ <string name="LSLTipText_llRequestPermissions">
+llRequestPermissions(key agent, integer perm)
+ask agent to allow the script to do perm (NB: Debit, ownership, link, joint, and permission requests can only go to the task's owner)
+ </string>
+ <string name="LSLTipText_llGetPermissionsKey">
+key llGetPermissionsKey()
+Return agent that permissions are enabled for. NULL_KEY if not enabled
+ </string>
+ <string name="LSLTipText_llGetPermissions">
+integer llGetPermissions()
+return what permissions have been enabled
+ </string>
+ <string name="LSLTipText_llGetLinkNumber">
+integer llGetLinkNumber()
+Returns what number in a link set the script is attached to (0 means no link, 1 the root, 2 for first child, etc)
+ </string>
+ <string name="LSLTipText_llSetLinkColor">
+llSetLinkColor(integer linknumber, vector color, integer face)
+If a task exists in the link chain at linknumber, set face to color
+ </string>
+ <string name="LSLTipText_llCreateLink">
+llCreateLink(key target, integer parent)
+Attempt to link task script is attached to and target (requires permission PERMISSION_CHANGE_LINKS be set). If parent == TRUE, task script is attached to is the root
+ </string>
+ <string name="LSLTipText_llBreakLink">
+llBreakLink(integer linknum)
+Delinks the task with the given link number (requires permission PERMISSION_CHANGE_LINKS be set)
+ </string>
+ <string name="LSLTipText_llBreakAllLinks">
+llBreakAllLinks()
+Delinks all tasks in the link set (requires permission PERMISSION_CHANGE_LINKS be set)
+ </string>
+ <string name="LSLTipText_llGetLinkKey">
+key llGetLinkKey(integer linknum)
+Get the key of linknumber in link set
+ </string>
+ <string name="LSLTipText_llGetLinkName">
+string llGetLinkName(integer linknum)
+Get the name of linknumber in link set
+ </string>
+ <string name="LSLTipText_llGetInventoryNumber">
+integer llGetInventoryNumber(integer type)
+Get the number of items of a given type in the task's inventory.
+Valid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ALL
+ </string>
+ <string name="LSLTipText_llGetInventoryName">
+string llGetInventoryName(integer type, integer number)
+Get the name of the inventory item number of type
+ </string>
+ <string name="LSLTipText_llSetScriptState">
+llSetScriptState(string name, integer run)
+Control the state of a script name.
+ </string>
+ <string name="LSLTipText_llGetEnergy">
+float llGetEnergy()
+Returns how much energy is in the object as a percentage of maximum
+ </string>
+ <string name="LSLTipText_llGiveInventory">
+llGiveInventory(key destination, string inventory)
+Give inventory to destination
+ </string>
+ <string name="LSLTipText_llRemoveInventory">
+llRemoveInventory(string inventory)
+Remove the named inventory item
+ </string>
+ <string name="LSLTipText_llSetText">
+llSetText(string text, vector color, float alpha)
+Set text floating over object
+ </string>
+ <string name="LSLTipText_llWater">
+float llWater(vector v)
+returns the water height below the object position + v
+ </string>
+ <string name="LSLTipText_llPassTouches">
+llPassTouches(integer pass)
+if pass == TRUE, touches are passed from children on to parents (default is FALSE)
+ </string>
+ <string name="LSLTipText_llRequestAgentData">
+key llRequestAgentData(key id, integer data)
+Requests data about agent id. When data is available the dataserver event will be raised
+ </string>
+ <string name="LSLTipText_llRequestInventoryData">
+key llRequestInventoryData(string name)
+Requests data from object's inventory object. When data is available the dataserver event will be raised
+ </string>
+ <string name="LSLTipText_llSetDamage">
+llSetDamage(float damage)
+Sets the amount of damage that will be done to an object that this task hits. Task will be killed.
+ </string>
+ <string name="LSLTipText_llTeleportAgentHome">
+llTeleportAgentHome(key id)
+Teleports agent on owner's land to agent's home location
+ </string>
+ <string name="LSLTipText_llModifyLand">
+llModifyLand(integer action, integer size)
+Modify land with action (LAND_LEVEL, LAND_RAISE, LAND_LOWER, LAND_SMOOTH, LAND_NOISE, LAND_REVERT)
+on size (LAND_SMALL_BRUSH, LAND_MEDIUM_BRUSH, LAND_LARGE_BRUSH)
+ </string>
+ <string name="LSLTipText_llCollisionSound">
+llCollisionSound(string impact_sound, float impact_volume)
+Suppress default collision sounds, replace default impact sounds with impact_sound (empty string to just suppress)
+ </string>
+ <string name="LSLTipText_llCollisionSprite">
+llCollisionSprite(string impact_sprite)
+Suppress default collision sprites, replace default impact sprite with impact_sprite (empty string to just suppress)
+ </string>
+ <string name="LSLTipText_llGetAnimation">
+string llGetAnimation(key id)
+Get the currently playing locomotion animation for avatar id
+ </string>
+ <string name="LSLTipText_llResetScript">
+llResetScript()
+Resets the script
+ </string>
+ <string name="LSLTipText_llMessageLinked">
+llMessageLinked(integer linknum, integer num, string str, key id)
+Sends num, str, and id to members of the link set
+(LINK_ROOT sends to root task in a linked set,
+LINK_SET sends to all tasks,
+LINK_ALL_OTHERS to all other tasks,
+LINK_ALL_CHILDREN to all children,
+LINK_THIS to the task the script it is in)
+ </string>
+ <string name="LSLTipText_llPushObject">
+llPushObject(key id, vector impulse, vector ang_impulse, integer local)
+Applies impulse and ang_impulse to object id
+ </string>
+ <string name="LSLTipText_llPassCollisions">
+llPassCollisions(integer pass)
+if pass == TRUE, collisions are passed from children on to parents (default is FALSE)
+ </string>
+ <string name="LSLTipText_llGetScriptName">
+llGetScriptName()
+Returns the script name
+ </string>
+ <string name="LSLTipText_llGetNumberOfSides">
+integer llGetNumberOfSides()
+Returns the number of sides
+ </string>
+ <string name="LSLTipText_llAxisAngle2Rot">
+rotation llAxisAngle2Rot(vector axis, float angle)
+Returns the rotation generated angle about axis
+ </string>
+ <string name="LSLTipText_llRot2Axis">
+vector llRot2Axis(rotation rot)
+Returns the rotation axis represented by rot
+ </string>
+ <string name="LSLTipText_llRot2Angle">
+float llRot2Angle(rotation rot)
+Returns the rotation angle represented by rot
+ </string>
+ <string name="LSLTipText_llAcos">
+float llAcos(float val)
+Returns the arccosine in radians of val
+ </string>
+ <string name="LSLTipText_llAsin">
+float llAsin(float val)
+Returns the arcsine in radians of val
+ </string>
+ <string name="LSLTipText_llAngleBetween">
+float llAngleBetween(rotation a, rotation b)
+Returns angle between rotation a and b
+ </string>
+ <string name="LSLTipText_llGetInventoryKey">
+key llGetInventoryKey(string name)
+Returns the key of the inventory name
+ </string>
+ <string name="LSLTipText_llAllowInventoryDrop">
+llAllowInventoryDrop(integer add)
+If add == TRUE, users without permissions can still drop inventory items onto task
+ </string>
+ <string name="LSLTipText_llGetSunDirection">
+vector llGetSunDirection()
+Returns the sun direction on the simulator
+ </string>
+ <string name="LSLTipText_llGetTextureOffset">
+vector llGetTextureOffset(integer side)
+Returns the texture offset of side in the x and y components of a vector
+ </string>
+ <string name="LSLTipText_llGetTextureScale">
+vector llGetTextureScale(integer side)
+Returns the texture scale of side in the x and y components of a vector
+ </string>
+ <string name="LSLTipText_llGetTextureRot">
+float llGetTextureRot(integer side)
+Returns the texture rotation of side
+ </string>
+ <string name="LSLTipText_llSubStringIndex">
+integer llSubStringIndex(string source, string pattern)
+Finds index in source where pattern first appears (returns -1 if not found)
+ </string>
+ <string name="LSLTipText_llGetOwnerKey">
+key llGetOwnerKey(key id)
+Find the owner of id
+ </string>
+ <string name="LSLTipText_llGetCenterOfMass">
+vector llGetCenterOfMass()
+Get the object's center of mass
+ </string>
+ <string name="LSLTipText_llListSort">
+list llListSort(list src, integer stride, integer ascending)
+Sort the list into blocks of stride in ascending order if ascending == TRUE. Note that sort only works between same types.
+ </string>
+ <string name="LSLTipText_llGetListLength">
+integer llGetListLength(list src)
+Get the number of elements in the list
+ </string>
+ <string name="LSLTipText_llList2Integer">
+integer llList2Integer(list src, integer index)
+Copy the integer at index in the list
+ </string>
+ <string name="LSLTipText_llList2Float">
+float llList2Float(list src, integer index)
+Copy the float at index in the list
+ </string>
+ <string name="LSLTipText_llList2String">
+string llList2String(list src, integer index)
+Copy the string at index in the list
+ </string>
+ <string name="LSLTipText_llList2Key">
+key llList2Key(list src, integer index)
+Copy the key at index in the list
+ </string>
+ <string name="LSLTipText_llList2Vector">
+vector llList2Vector(list src, integer index)
+Copy the vector at index in the list
+ </string>
+ <string name="LSLTipText_llList2Rot">
+rotation llList2Rot(list src, integer index)
+Copy the rotation at index in the list
+ </string>
+ <string name="LSLTipText_llList2List">
+list llList2List(list src, integer start, integer end)
+Copy the slice of the list from start to end
+ </string>
+ <string name="LSLTipText_llDeleteSubList">
+list llDeleteSubList(list src, integer start, integer end)
+Remove the slice from the list and return the remainder
+ </string>
+ <string name="LSLTipText_llGetListEntryType">
+integer llGetListEntryType(list src, integer index)
+Returns the type of the index entry in the list
+(TYPE_INTEGER, TYPE_FLOAT, TYPE_STRING, TYPE_KEY, TYPE_VECTOR, TYPE_ROTATION, or TYPE_INVALID if index is off list)
+ </string>
+ <string name="LSLTipText_llList2CSV">
+string llList2CSV(list src)
+Create a string of comma separated values from list
+ </string>
+ <string name="LSLTipText_llCSV2List">
+list llCSV2List(string src)
+Create a list from a string of comma separated values
+ </string>
+ <string name="LSLTipText_llListRandomize">
+list llListRandomize(list src, integer stride)
+Returns a randomized list of blocks of size stride
+ </string>
+ <string name="LSLTipText_llList2ListStrided">
+list llList2ListStrided(list src, integer start, integer end, integer stride)
+Copy the strided slice of the list from start to end
+ </string>
+ <string name="LSLTipText_llGetRegionCorner">
+vector llGetRegionCorner()
+Returns a vector with the south west corner x,y position of the region the object is in
+ </string>
+ <string name="LSLTipText_llListInsertList">
+list llListInsertList(list dest, list src, integer start)
+Inserts src into dest at position start
+ </string>
+ <string name="LSLTipText_llListFindList">
+integer llListFindList(list src, list test)
+Returns the start of the first instance of test in src, -1 if not found
+ </string>
+ <string name="LSLTipText_llGetObjectName">
+string llGetObjectName()
+Returns the name of the object script is attached to
+ </string>
+ <string name="LSLTipText_llSetObjectName">
+llSetObjectName(string name)
+Sets the objects name
+ </string>
+ <string name="LSLTipText_llGetDate">
+string llGetDate()
+Gets the date as YYYY-MM-DD
+ </string>
+ <string name="LSLTipText_llEdgeOfWorld">
+integer llEdgeOfWorld(vector pos, vector dir)
+Checks to see whether the border hit by dir from pos is the edge of the world (has no neighboring simulator)
+ </string>
+ <string name="LSLTipText_llGetAgentInfo">
+integer llGetAgentInfo(key id)
+Gets information about agent ID.
+Returns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR.
+ </string>
+ <string name="LSLTipText_llAdjustSoundVolume">
+llAdjustSoundVolume(float volume)
+adjusts volume of attached sound (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llSetSoundQueueing">
+llSetSoundQueueing(integer queue)
+determines whether attached sound calls wait for the current sound to finish (0 = no [default], nonzero = yes)
+ </string>
+ <string name="LSLTipText_llSetSoundRadius">
+llSetSoundRadius(float radius)
+establishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered)
+ </string>
+ <string name="LSLTipText_llKey2Name">
+string llKey2Name(key id)
+Returns the name of the object key, iff the object is in the current simulator, otherwise the empty string
+ </string>
+ <string name="LSLTipText_llSetTextureAnim">
+llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate)
+Animate the texture on the specified face/faces
+ </string>
+ <string name="LSLTipText_llTriggerSoundLimited">
+llTriggerSoundLimited(string sound, float volume, vector tne, vector bsw)
+plays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to AABB defined by vectors top-north-east and bottom-south-west
+ </string>
+ <string name="LSLTipText_llEjectFromLand">
+llEjectFromLand(key pest)
+Ejects pest from land that you own
+ </string>
+ <string name="LSLTipText_llParseString2List">
+list llParseString2List(string src, list separators, list spacers)
+Breaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each)
+ </string>
+ <string name="LSLTipText_llOverMyLand">
+integer llOverMyLand(key id)
+Returns TRUE if id is over land owner of object owns, FALSE otherwise
+ </string>
+ <string name="LSLTipText_llGetLandOwnerAt">
+key llGetLandOwnerAt(vector pos)
+Returns the key of the land owner, NULL_KEY if public
+ </string>
+ <string name="LSLTipText_llGetNotecardLine">
+key llGetNotecardLine(string name, integer line)
+Returns line line of notecard name via the dataserver event
+ </string>
+ <string name="LSLTipText_llGetAgentSize">
+vector llGetAgentSize(key id)
+If the agent is in the same sim as the object, returns the size of the avatar
+ </string>
+ <string name="LSLTipText_llSameGroup">
+integer llSameGroup(key id)
+Returns TRUE if ID is in the same sim and has the same active group, otherwise FALSE
+ </string>
+ <string name="LSLTipText_llUnSit">
+key llUnSit(key id)
+If agent identified by id is sitting on the object the script is attached to or is over land owned by the objects owner, the agent is forced to stand up
+ </string>
+ <string name="LSLTipText_llGroundSlope">
+vector llGroundSlope(vector v)
+returns the ground slope below the object position + v
+ </string>
+ <string name="LSLTipText_llGroundNormal">
+vector llGroundNormal(vector v)
+returns the ground normal below the object position + v
+ </string>
+ <string name="LSLTipText_llGroundContour">
+vector llGroundCountour(vector v)
+returns the ground contour below the object position + v
+ </string>
+ <string name="LSLTipText_llGetAttached">
+integer llGetAttached()
+returns the object attachment point or 0 if not attached
+ </string>
+ <string name="LSLTipText_llGetFreeMemory">
+integer llGetFreeMemory()
+returns the available heap space for the current script
+ </string>
+ <string name="LSLTipText_llGetRegionName">
+string llGetRegionName()
+returns the current region name
+ </string>
+ <string name="LSLTipText_llGetRegionTimeDilation">
+float llGetRegionTimeDilation()
+returns the current time dilation as a float between 0 and 1
+ </string>
+ <string name="LSLTipText_llGetRegionFPS">
+float llGetRegionFPS()
+returns the mean region frames per second
+ </string>
+ <string name="LSLTipText_llParticleSystem">
+llParticleSystem(list rules)
+Creates a particle system based on rules. Empty list removes particle system from object.
+List format is [ rule1, data1, rule2, data2 . . . rulen, datan ]
+ </string>
+ <string name="LSLTipText_llGroundRepel">
+llGroundRepel(float height, integer water, float tau)
+Critically damps to height if within height*0.5 of level (either above ground level or above the higher of land and water if water == TRUE)
+ </string>
+ <string name="LSLTipText_llGiveInventoryList">
+llGiveInventoryList(key destination, string category, list inventory)
+Give inventory to destination in a new category
+ </string>
+ <string name="LSLTipText_llSetVehicleType">
+llSetVehicleType(integer type)
+sets vehicle to one of the default types
+ </string>
+ <string name="LSLTipText_llSetVehicleFloatParam">
+llSetVehicleFloatParam(integer param, float value)
+sets the specified vehicle float parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleVectorParam">
+llSetVehicleVectorParam(integer param, vector vec)
+sets the specified vehicle vector parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleRotationParam">
+llSetVehicleVectorParam(integer param, rotation rot)
+sets the specified vehicle rotation parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleFlags">
+llSetVehicleFlags(integer flags)
+sets the enabled bits in 'flags'
+ </string>
+ <string name="LSLTipText_llRemoveVehicleFlags">
+llRemoveVehicleFlags(integer flags)
+removes the enabled bits in 'flags'
+ </string>
+ <string name="LSLTipText_llSitTarget">
+llSitTarget(vector offset, rotation rot)
+Set the sit location for this object (if offset == &lt;0,0,0&gt; clear it)
+ </string>
+ <string name="LSLTipText_llAvatarOnSitTarget">
+key llAvatarOnSitTarget()
+If an avatar is sitting on the sit target, return the avatar's key, NULL_KEY otherwise
+ </string>
+ <string name="LSLTipText_llAddToLandPassList">
+llAddToLandPassList(key avatar, float hours)
+Add avatar to the land pass list for hours
+ </string>
+ <string name="LSLTipText_llSetTouchText">
+llSetTouchText(string text)
+Displays text in pie menu that acts as a touch
+ </string>
+ <string name="LSLTipText_llSetSitText">
+llSetSitText(string text)
+Displays text rather than sit in pie menu
+ </string>
+ <string name="LSLTipText_llSetCameraEyeOffset">
+llSetCameraEyeOffset(vector offset)
+Sets the camera eye offset used in this object if an avatar sits on it
+ </string>
+ <string name="LSLTipText_llSetCameraAtOffset">
+llSetCameraAtOffset(vector offset)
+Sets the camera at offset used in this object if an avatar sits on it
+ </string>
+ <string name="LSLTipText_llDumpList2String">
+string llDumpList2String(list src, string separator)
+Write the list out in a single string using separator between values
+ </string>
+ <string name="LSLTipText_llScriptDanger">
+integer llScriptDanger(vector pos)
+Returns true if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts
+ </string>
+ <string name="LSLTipText_llDialog">
+llDialog(key avatar, string message, list buttons, integer chat_channel
+Shows a dialog box on the avatar's screen with the message.
+Up to 12 strings in the list form buttons.
+If a button is clicked, the name is chatted on chat_channel.
+ </string>
+ <string name="LSLTipText_llVolumeDetect">
+llVolumeDetect(integer detect)
+If detect = TRUE, object becomes phantom but triggers collision_start and collision_end events when other objects start and stop interpenetrating.
+Must be applied to the root object.
+ </string>
+ <string name="LSLTipText_llResetOtherScript">
+llResetOtherScript(string name)
+Resets script name
+ </string>
+ <string name="LSLTipText_llGetScriptState">
+integer llGetScriptState(string name)
+Resets TRUE if script name is running
+ </string>
+ <string name="LSLTipText_llRemoteLoadScript">
+Deprecated. Please use llRemoteLoadScriptPin instead.
+ </string>
+ <string name="LSLTipText_llSetRemoteScriptAccessPin">
+llSetRemoteScriptAccessPin(integer pin)
+If pin is set to a non-zero number, the task will accept remote script loads via llRemoteLoadScriptPin if it passes in the correct pin.
+Othersise, llRemoteLoadScriptPin is ignored.
+ </string>
+ <string name="LSLTipText_llRemoteLoadScriptPin">
+llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)
+If the owner of the object this script is attached can modify target,
+they are in the same region, and the matching pin is used,
+copy script name onto target,
+if running == TRUE, start the script with param.
+ </string>
+ <string name="LSLTipText_llOpenRemoteDataChannel">
+llOpenRemoteDataChannel()
+Creates a channel to listen for XML-RPC calls. Will trigger a remote_data event with channel id once it is available.
+ </string>
+ <string name="LSLTipText_llSendRemoteData">
+key llSendRemoteData(key channel, string dest, integer idata, string sdata)
+Send an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata.
+A message identifier key is returned.
+An XML-RPC reply will trigger a remote_data event and reference the message id.
+The message_id is returned.
+ </string>
+ <string name="LSLTipText_llRemoteDataReply">
+llRemoteDataReply(key channel, key message_id, string sdata, integer idata)
+Send an XML-RPC reply to message_id on channel with payload of string sdata and integer idata
+ </string>
+ <string name="LSLTipText_llCloseRemoteDataChannel">
+llCloseRemoteDataChannel(key channel)
+Closes XML-RPC channel.
+ </string>
+ <string name="LSLTipText_llMD5String">
+string llMD5String(string src, integer nonce)
+Performs a RSA Data Security, Inc. MD5 Message-Digest Algorithm on string with nonce. Returns a 32 character hex string.
+ </string>
+ <string name="LSLTipText_llSetPrimitiveParams">
+llSetPrimitiveParams(list rules)
+Set primitive parameters based on rules.
+ </string>
+ <string name="LSLTipText_llStringToBase64">
+string llStringToBase64(string str)
+Converts a string to the Base 64 representation of the string.
+ </string>
+ <string name="LSLTipText_llBase64ToString">
+string llBase64ToString(string str)
+Converts a Base 64 string to a conventional string. If the conversion creates any unprintable characters, they are converted to spaces.
+ </string>
+ <string name="LSLTipText_llXorBase64Strings">
+string llXorBase64Strings(string s1, string s2)
+DEPRECATED! Please use llXorBase64StringsCorrect instead!! Incorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability.
+ </string>
+ <string name="LSLTipText_llRemoteDataSetRegion">
+llRemoteDataSetRegion()
+If an object using remote data channels changes regions, you must call this function to reregister the remote data channels.
+You do not need to make this call if you don't change regions.
+ </string>
+ <string name="LSLTipText_llLog10">
+float llLog10(float val)
+Returns the base 10 log of val if val &gt; 0, otherwise returns 0.
+ </string>
+ <string name="LSLTipText_llLog">
+float llLog(float val)
+Returns the base e log of val if val &gt; 0, otherwise returns 0.
+ </string>
+ <string name="LSLTipText_llGetAnimationList">
+list llGetAnimationList(key id)
+Gets a list of all playing animations for avatar id
+ </string>
+ <string name="LSLTipText_llSetParcelMusicURL">
+llSetParcelMusicURL(string url)
+Sets the streaming audio URL for the parcel object is on
+ </string>
+ <string name="LSLTipText_llGetRootPosition">
+vector llGetRootPosition()
+Gets the global position of the root object of the object script is attached to
+ </string>
+ <string name="LSLTipText_llGetRootRotation">
+rotation llGetRootRotation()
+Gets the global rotation of the root object of the object script is attached to
+ </string>
+ <string name="LSLTipText_llGetObjectDesc">
+string llGetObjectDesc()
+Returns the description of the object the script is attached to
+ </string>
+ <string name="LSLTipText_llSetObjectDesc">
+llSetObjectDesc(string name)
+Sets the object's description
+ </string>
+ <string name="LSLTipText_llGetCreator">
+key llGetCreator()
+Returns the creator of the object
+ </string>
+ <string name="LSLTipText_llGetTimestamp">
+string llGetTimestamp()
+Gets the timestamp in the format: YYYY-MM-DDThh:mm:ss.ff..fZ
+ </string>
+ <string name="LSLTipText_llSetLinkAlpha">
+llSetLinkAlpha(integer linknumber, float alpha, integer face)
+If a prim exists in the link chain at linknumber, set face to alpha
+ </string>
+ <string name="LSLTipText_llGetNumberOfPrims">
+integer llGetNumberOfPrims()
+Returns the number of prims in a link set the script is attached to
+ </string>
+ <string name="LSLTipText_llGetNumberOfNotecardLines">
+key llGetNumberOfNotecardLines(string name)
+Returns number of lines in notecard 'name' via the dataserver event (cast return value to integer)
+ </string>
+ <string name="LSLTipText_llGetBoundingBox">
+list llGetBoundingBox(key object)
+Returns the bounding box around an object (including any linked prims) relative to the root prim, in a list: [ (vector) min_corner, (vector) max_corner ]
+ </string>
+ <string name="LSLTipText_llGetGeometricCenter">
+vector llGetGeometricCenter()
+Returns the geometric center of the linked set the script is attached to.
+ </string>
+ <string name="LSLTipText_llGetPrimitiveParams">
+list llGetPrimitiveParams(list params)
+Gets primitive parameters specified in the params list.
+ </string>
+ <string name="LSLTipText_llIntegerToBase64">
+string llIntegerToBase64(integer number)
+Big endian encode of of integer as a Base64 string.
+ </string>
+ <string name="LSLTipText_llBase64ToInteger">
+integer llBase64ToInteger(string str)
+Big endian decode of a Base64 string into an integer.
+ </string>
+ <string name="LSLTipText_llGetGMTclock">
+float llGetGMTclock()
+Gets the time in seconds since midnight in GMT
+ </string>
+ <string name="LSLTipText_llGetSimulatorHostname">
+string llGetSimulatorHostname()
+Gets the hostname of the machine script is running on (same as string in viewer Help dialog)
+ </string>
+ <string name="LSLTipText_llSetLocalRot">
+llSetLocalRot(rotation rot)
+sets the rotation of a child prim relative to the root prim
+ </string>
+ <string name="LSLTipText_llParseStringKeepNulls">
+list llParseStringKeepNulls(string src, list separators, list spacers)
+Breaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each), keeping any null values generated.
+ </string>
+ <string name="LSLTipText_llRezAtRoot">
+llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param)
+Instantiate owner's inventory object at pos with velocity vel and rotation rot with start parameter param.
+The last selected root object's location will be set to pos
+ </string>
+ <string name="LSLTipText_llGetObjectPermMask">
+integer llGetObjectPermMask(integer mask)
+Returns the requested permission mask for the root object the task is attached to.
+ </string>
+ <string name="LSLTipText_llSetObjectPermMask">
+llSetObjectPermMask(integer mask, integer value)
+Sets the given permission mask to the new value on the root object the task is attached to.
+ </string>
+ <string name="LSLTipText_llGetInventoryPermMask">
+integer llGetInventoryPermMask(string item, integer mask)
+Returns the requested permission mask for the inventory item.
+ </string>
+ <string name="LSLTipText_llSetInventoryPermMask">
+llSetInventoryPermMask(string item, integer mask, integer value)
+Sets the given permission mask to the new value on the inventory item.
+ </string>
+ <string name="LSLTipText_llGetInventoryCreator">
+key llGetInventoryCreator(string item)
+Returns the key for the creator of the inventory item.
+ </string>
+ <string name="LSLTipText_llOwnerSay">
+llOwnerSay(string msg)
+says msg to owner only (if owner in sim)
+ </string>
+ <string name="LSLTipText_llRequestSimulatorData">
+key llRequestSimulatorData(string simulator, integer data)
+Requests data about simulator. When data is available the dataserver event will be raised
+ </string>
+ <string name="LSLTipText_llForceMouselook">
+llForceMouselook(integer mouselook)
+If mouselook is TRUE any avatar that sits on this object is forced into mouselook mode
+ </string>
+ <string name="LSLTipText_llGetObjectMass">
+float llGetObjectMass(key id)
+Get the mass of the object with key id
+ </string>
+ <string name="LSLTipText_llListReplaceList">
+list llListReplaceList(list dest, list src, integer start, integer end)
+Replaces start through end of dest with src.
+ </string>
+ <string name="LSLTipText_llLoadURL">
+llLoadURL(key avatar_id, string message, string url)
+Shows dialog to avatar avatar_id offering to load web page at URL. If user clicks yes, launches their web browser.
+ </string>
+ <string name="LSLTipText_llParcelMediaCommandList">
+llParcelMediaCommandList(list command)
+Sends a list of commands, some with arguments, to a parcel.
+ </string>
+ <string name="LSLTipText_llParcelMediaQuery">
+list llParcelMediaQuery(list query)
+Sends a list of queries, returns a list of results.
+ </string>
+ <string name="LSLTipText_llModPow">
+integer llModPow(integer a, integer b, integer c)
+Returns a raised to the b power, mod c. ( (a**b)%c ). b is capped at 0xFFFF (16 bits).
+ </string>
+ <string name="LSLTipText_llGetInventoryType">
+integer llGetInventoryType(string name)
+Returns the type of the inventory name
+ </string>
+ <string name="LSLTipText_llSetPayPrice">
+llSetPayPrice(integer price, list quick_pay_buttons)
+Sets the default amount when someone chooses to pay this object.
+ </string>
+ <string name="LSLTipText_llGetCameraPos">
+vector llGetCameraPos()
+Gets current camera position for agent task has permissions for.
+ </string>
+ <string name="LSLTipText_llGetCameraRot">
+rotation llGetCameraRot()
+Gets current camera orientation for agent task has permissions for.
+ </string>
+ <string name="LSLTipText_llSetPrimURL">
+llSetPrimURL(string url)
+Updates the URL for the web page shown on the sides of the object.
+ </string>
+ <string name="LSLTipText_llRefreshPrimURL">
+llRefreshPrimURL()
+Reloads the web page shown on the sides of the object.
+ </string>
+ <string name="LSLTipText_llEscapeURL">
+string llEscapeURL(string url)
+Returns and escaped/encoded version of url, replacing spaces with %20 etc.
+ </string>
+ <string name="LSLTipText_llUnescapeURL">
+string llUnescapeURL(string url)
+Returns and unescaped/unencoded version of url, replacing %20 with spaces etc.
+ </string>
+ <string name="LSLTipText_llMapDestination">
+llMapDestination(string simname, vector pos, vector look_at)
+Opens world map centered on region with pos highlighted.
+Only works for scripts attached to avatar, or during touch events.
+(NOTE: look_at currently does nothing)
+ </string>
+ <string name="LSLTipText_llAddToLandBanList">
+llAddToLandBanList(key avatar, float hours)
+Add avatar to the land ban list for hours
+ </string>
+ <string name="LSLTipText_llRemoveFromLandPassList">
+llRemoveFromLandPassList(key avatar)
+Remove avatar from the land pass list
+ </string>
+ <string name="LSLTipText_llRemoveFromLandBanList">
+llRemoveFromLandBanList(key avatar)
+Remove avatar from the land ban list
+ </string>
+ <string name="LSLTipText_llSetCameraParams">
+llSetCameraParams(list rules)
+Sets multiple camera parameters at once.
+List format is [ rule1, data1, rule2, data2 . . . rulen, datan ]
+ </string>
+ <string name="LSLTipText_llClearCameraParams">
+llClearCameraParams()
+Resets all camera parameters to default values and turns off scripted camera control.
+ </string>
+ <string name="LSLTipText_llListStatistics">
+float llListStatistics(integer operation, list l)
+Perform statistical aggregate functions on list l using LIST_STAT_* operations.
+ </string>
+ <string name="LSLTipText_llGetUnixTime">
+integer llGetUnixTime()
+Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock.
+ </string>
+ <string name="LSLTipText_llGetParcelFlags">
+integer llGetParcelFlags(vector pos)
+Get the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos.
+ </string>
+ <string name="LSLTipText_llGetRegionFlags">
+integer llGetRegionFlags()
+Get the region flags (REGION_FLAG_*) for the region the object is in.
+ </string>
+ <string name="LSLTipText_llXorBase64StringsCorrect">
+string llXorBase64StringsCorrect(string s1, string s2)
+Correctly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1.
+ </string>
+ <string name="LSLTipText_llHTTPRequest">
+llHTTPRequest(string url, list parameters, string body)
+Send an HTTP request.
+ </string>
+ <string name="LSLTipText_llResetLandBanList">
+llResetLandBanList()
+Removes all residents from the land ban list.
+ </string>
+ <string name="LSLTipText_llResetLandPassList">
+llResetLandPassList()
+Removes all residents from the land access/pass list.
+ </string>
+ <string name="LSLTipText_llGetObjectPrimCount">
+integer llGetObjectPrimCount(key object_id)
+Returns the total number of prims for an object.
+ </string>
+ <string name="LSLTipText_llGetParcelPrimOwners">
+list llGetParcelPrimOwners(vector pos)
+Returns a list of all residents who own objects on the parcel and the number of objects they own.
+Requires owner-like permissions for the parcel.
+ </string>
+ <string name="LSLTipText_llGetParcelPrimCount">
+integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)
+Gets the number of prims on the parcel of the given category.
+Categories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP.
+ </string>
+ <string name="LSLTipText_llGetParcelMaxPrims">
+integer llGetParcelMaxPrims(vector pos, integer sim_wide)
+Gets the maximum number of prims allowed on the parcel at pos.
+ </string>
+ <string name="LSLTipText_llGetParcelDetails">
+list llGetParcelDetails(vector pos, list params)
+Gets the parcel details specified in params for the parcel at pos.
+Params is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA
+ </string>
+ <string name="LSLTipText_llSetLinkPrimitiveParams">
+llSetLinkPrimitiveParams(integer linknumber, list rules)
+Set primitive parameters for linknumber based on rules.
+ </string>
+ <string name="LSLTipText_llSetLinkTexture">
+llSetLinkTexture(integer link_pos, string texture, integer face)
+Sets the texture of face for link_pos
+ </string>
+ <string name="LSLTipText_llStringTrim">
+string llStringTrim(string src, integer trim_type)
+Trim leading and/or trailing spaces from a string.
+Uses trim_type of STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL.
+ </string>
+ <string name="LSLTipText_llRegionSay">
+llRegionSay(integer channel, string msg)
+broadcasts msg to entire region on channel (not 0.)
+ </string>
+ <string name="LSLTipText_llGetObjectDetails">
+list llGetObjectDetails(key id, list params)
+Gets the object details specified in params for the object with key id.
+Details are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR.
+ </string>
+ <string name="LSLTipText_llSetClickAction">
+llSetClickAction(integer action)
+Sets the action performed when a prim is clicked upon.
+ </string>
+ <string name="LSLTipText_llGetRegionAgentCount">
+int llGetRegionAgentCount()
+returns the number of agents in a region
+ </string>
+ <string name="LSLTipText_llTextBox">
+llTextBox(key avatar, string message, integer chat_channel
+Shows a dialog box on the avatar's screen with the message.
+A text box asks for input, and if entered the text is chatted on chat_channel.
+ </string>
+ <string name="LSLTipText_llGetAgentLanguage">
+string llGetAgentLanguage(key id)
+Gets the agents preferred language..
+ </string>
+ <string name="LSLTipText_llDetectedTouchUV">
+vector llDetectedTouchUV(integer number)
+returns the u and v coordinates in the first two components of a vector, for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchFace">
+integer llDetectedTouchFace(integer number)
+returns the index of the face on the object for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchPos">
+vector llDetectedTouchPos(integer number)
+returns the position touched for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchNormal">
+vector llDetectedTouchNormal(integer number)
+returns the surface normal for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchBinormal">
+vector llDetectedTouchBinormal(integer number)
+returns the surface binormal for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchST">
+vector llDetectedTouchST(integer number)
+returns the s and t coordinates in the first two components of a vector, for a triggered touch event
+ </string>
+ <string name="LSLTipText_llSHA1String">
+string llSHA1String(string sr)
+Performs a SHA1 security Hash. Returns a 40 character hex string.
+ </string>
+ <string name="LSLTipText_llGetFreeURLs">
+integer llGetFreeURLs()
+returns the available urls for the current script
+ </string>
+ <string name="LSLTipText_llRequestURL">
+key llRequestURL()
+Requests one HTTP:// url for use by this object
+Triggers an http_server event with results.
+ </string>
+ <string name="LSLTipText_llRequestSecureURL">
+key llRequestSecureURL()
+Requests one HTTPS:// (SSL) url for use by this object
+Triggers an http_server event with results.
+ </string>
+ <string name="LSLTipText_llReleaseURL">
+llReleaseURL(string url)
+Releases the specified URL, it will no longer be usable.
+ </string>
+ <string name="LSLTipText_llHTTPResponse">
+llHTTPResponse(key id, integer status, string body)
+Responds to request id with status and body.
+ </string>
+ <string name="LSLTipText_llGetHTTPHeader">
+string llGetHTTPHeader(key id, string header)
+Get the value for header for request id.
+ </string>
<!-- Avatar busy/away mode -->
<string name="AvatarSetNotAway">Set Not Away</string>
@@ -724,6 +1818,7 @@ this texture in your inventory
<string name="AnimFlagStart" value=" Start Animation : " />
<string name="Wave" value=" Wave " />
<string name="HelloAvatar" value=" Hello, avatar! " />
+ <string name="ViewAllGestures" value=" View All >>" />
<!-- inventory filter -->
<!-- use value="" because they have preceding spaces -->
@@ -819,8 +1914,35 @@ this texture in your inventory
<string name="Stomach">Stomach</string>
<string name="Left Pec">Left Pec</string>
<string name="Right Pec">Right Pec</string>
-
- <!-- HUD Position -->
+
+ <!-- Avatar age computation, see LLAvatarPropertiesProcessor::ageFromDate -->
+ <string name="YearsMonthsOld">[AGEYEARS][AGEMONTHS]old</string>
+ <string name="WeeksOld">[AGEWEEKS]old</string>
+ <string name="DaysOld">[AGEDAYS]old</string>
+ <string name="TodayOld">Joined today</string>
+
+ <!-- Use value="" because of trailing spaces -->
+ <string name="AgeYears" value="[YEARS] years " />
+ <string name="Age1Year" value="1 year "/>
+ <string name="AgeMonths" value="[MONTHS] months "/>
+ <string name="Age1Month" value="1 month "/>
+ <string name="AgeWeeks" value="[WEEKS] weeks "/>
+ <string name="Age1Week" value="1 week "/>
+ <string name="AgeDays" value="[DAYS] days "/>
+ <string name="Age1Day" value="1 day "/>
+
+ <!-- Account types, see LLAvatarPropertiesProcessor -->
+ <string name="AcctTypeResident">Resident</string>
+ <string name="AcctTypeTrial">Trial</string>
+ <string name="AcctTypeCharterMember">Charter Member</string>
+ <string name="AcctTypeEmployee">Linden Lab Employee</string>
+ <string name="PaymentInfoUsed">Payment Info Used</string>
+ <string name="PaymentInfoOnFile">Payment Info On File</string>
+ <string name="NoPaymentInfoOnFile">No Payment Info On File</string>
+ <string name="AgeVerified">Age-verified</string>
+ <string name="NotAgeVerified">Not Age-verified</string>
+
+ <!-- HUD Position -->
<string name="Center 2">Center 2</string>
<string name="Top Right">Top Right</string>
<string name="Top">Top</string>
@@ -1331,4 +2453,48 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="UpdaterFailStartTitle">
Failed to start viewer
</string>
+
+ <!-- IM system messages -->
+ <string name="only_user_message">
+ You are the only user in this session.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] is offline.
+ </string>
+ <string name="invite_message">
+ Click the [BUTTON NAME] button to accept/connect to this voice chat.
+ </string>
+ <string name="muted_message">
+ You have blocked this resident. Sending a message will automatically unblock them.
+ </string>
+ <string name="generic_request_error">
+ Error making request, please try again later.
+ </string>
+ <string name="insufficient_perms_error">
+ You do not have sufficient permissions.
+ </string>
+ <string name="session_does_not_exist_error">
+ The session no longer exists
+ </string>
+ <string name="no_ability_error">
+ You do not have that ability.
+ </string>
+ <string name="not_a_mod_error">
+ You are not a session moderator.
+ </string>
+ <string name="muted_error">
+ A group moderator disabled your text chat.
+ </string>
+ <string name="add_session_event">
+ Unable to add users to chat session with [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Unable to send your message to the chat session with [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ You have been removed from the group.
+ </string>
+ <string name="close_on_no_ability">
+ You no longer have the ability to be in the chat session.
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
new file mode 100644
index 0000000000..eabacbecb2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<accordion_tab
+ header_collapse_img="accordion_collapsed.tga"
+ header_collapse_img_pressed="accordion_collapsed.tga"
+ header_expand_img="accordion_expanded.tga"
+ header_expand_img_pressed="accordion_expanded.tga" />
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index a34b005448..ada258fbec 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -1,8 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<filter_editor select_on_focus="true"
- background_image_disabled="TextField_Search_Disabled"
- background_image_focused="TextField_Search_Active">
- <clear_filter_button label=""
- image_unselected="Icon_Close_Foreground"
- image_selected="Icon_Close_Press" />
+<filter_editor
+ clear_button_visible="true"
+ search_button_visible="true"
+ text_pad_left="4"
+ select_on_focus="true"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active" >
+ <search_button label=""
+ top_pad="4"
+ left_pad="4"
+ width="13"
+ height="13"
+ image_unselected="Search"
+ image_selected="Search" />
+ <clear_button label=""
+ image_unselected="Icon_Close_Foreground"
+ image_selected="Icon_Close_Press" />
</filter_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml b/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
new file mode 100644
index 0000000000..24d072a573
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<flat_list_view
+ allow_select="true"
+ item_pad="5"
+ keep_one_selected="true"
+ multi_select="false"
+ opaque="true" /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
new file mode 100644
index 0000000000..4a866c2eb2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater name="floater"
+ bg_opaque_color="FloaterFocusBackgroundColor"
+ bg_alpha_color="FloaterDefaultBackgroundColor"
+ background_visible="true"
+ background_opaque="false"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/list.xml b/indra/newview/skins/default/xui/en/widgets/list.xml
new file mode 100644
index 0000000000..4a59716464
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/list.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<list
+ allow_select="true"
+ bg_opaque_color="PanelFocusBackgroundColor"
+ bg_alpha_color="PanelDefaultBackgroundColor"
+ background_visible="false"
+ background_opaque="false"
+ item_pad="5"
+ keep_one_selected="true"
+ multi_select="false" /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml
index 8f4d0edf95..a37ed76c51 100644
--- a/indra/newview/skins/default/xui/en/widgets/location_input.xml
+++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml
@@ -17,6 +17,7 @@
show_text_as_tentative="false"
max_chars="20"
follows="left|top"
+ allow_new_values="true"
>
<info_button name="Place Information"
label=""
@@ -43,7 +44,7 @@
label=""
pad_right="0"
tool_tip="My Location History"/>
- <combo_list bg_writeable_color="MenuDefaultBgColor"/>
+ <combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10"/>
<combo_editor name="Combo Text Entry"
text_pad_left="20"
select_on_focus="false"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
new file mode 100644
index 0000000000..6e73e997e0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<search_combo_box
+ allow_text_entry="true"
+ list_position="BELOW"
+ show_text_as_tentative="false"
+ dropdown_button_visible="false"
+ max_chars="256"
+ allow_new_values="true"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active">
+ <combo_editor
+ select_on_focus="true"
+ text_pad_left="20"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active"/>
+ <combo_list
+ multi_select="false"
+ page_lines="10" />
+ <search_button label=""
+ top_pad="4"
+ left_pad="4"
+ width="13"
+ height="13"
+ image_unselected="Search"
+ image_selected="Search" />
+</search_combo_box> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index 15b23ea9b3..f482ff3b89 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<search_editor
+ clear_button_visible="false"
+ search_button_visible="true"
text_pad_left="4"
select_on_focus="true"
background_image="TextField_Search_Off"
@@ -12,4 +14,7 @@
height="13"
image_unselected="Search"
image_selected="Search" />
+ <clear_button label=""
+ image_unselected="Icon_Close_Foreground"
+ image_selected="Icon_Close_Press" />
</search_editor>
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 3e42f6929b..6a93537a38 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -14,6 +14,7 @@ include(LScript)
include(Linking)
include(Tut)
+include(GoogleMock)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -24,6 +25,7 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
set(test_SOURCE_FILES
@@ -127,7 +129,8 @@ target_link_libraries(test
${LLXML_LIBRARIES}
${LSCRIPT_LIBRARIES}
${LLCOMMON_LIBRARIES}
- ${EXPAT_LIBRARIES}
+ ${EXPAT_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
${APRICONV_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
diff --git a/indra/test/llhttpdate_tut.cpp b/indra/test/llhttpdate_tut.cpp
index b9733dc030..8762938186 100644
--- a/indra/test/llhttpdate_tut.cpp
+++ b/indra/test/llhttpdate_tut.cpp
@@ -37,6 +37,9 @@
#include "lldate.h"
#include "llframetimer.h"
+#include <time.h>
+#include <locale.h>
+
namespace tut
{
struct httpdate_data
@@ -94,4 +97,70 @@ namespace tut
// probably not a good idea to use strcmp but this is just a unit test
ensure("Current time in RFC 1123", (strcmp(expected, actual.c_str()) == 0));
}
+
+ void test_date_string(const std::string &locale, struct tm *t,
+ const std::string &fmt, const std::string &expected)
+ {
+ std::string result = LLDate::toHTTPDateString(t, fmt);
+ LLStringUtil::toLower(result);
+ std::string label = std::string("toHTTPDateString - ") + locale;
+ ensure_equals(label.c_str(), result, expected);
+ }
+
+ template<> template<>
+ void httpdate_object::test<4>()
+ {
+ // test localization of http dates
+#if LL_WINDOWS
+ const char *en_locale = "english";
+ const char *fr_locale = "french";
+#else
+ const char *en_locale = "en_GB.UTF-8";
+ const char *fr_locale = "fr_FR.UTF-8";
+#endif
+
+ std::string prev_locale = LLStringUtil::getLocale();
+ std::string prev_clocale = std::string(setlocale(LC_TIME, NULL));
+ time_t test_time = 1252374030; // 8 Sep 2009 01:40:01
+ struct tm *t = gmtime(&test_time);
+
+ setlocale(LC_TIME, en_locale);
+ if (strcmp(setlocale(LC_TIME, NULL), en_locale) != 0)
+ {
+ setlocale(LC_TIME, prev_clocale.c_str());
+ skip("Cannot set English locale");
+ }
+
+ LLStringUtil::setLocale(en_locale);
+ test_date_string(en_locale, t, "%d %B %Y - %H:%M", "08 september 2009 - 01:40");
+ test_date_string(en_locale, t, "%H", "01");
+ test_date_string(en_locale, t, "%M", "40");
+ test_date_string(en_locale, t, "%I", "01");
+ test_date_string(en_locale, t, "%d", "08");
+ test_date_string(en_locale, t, "%Y", "2009");
+ test_date_string(en_locale, t, "%p", "am");
+ test_date_string(en_locale, t, "%A", "tuesday");
+ test_date_string(en_locale, t, "%B", "september");
+
+ setlocale(LC_TIME, fr_locale);
+ if (strcmp(setlocale(LC_TIME, NULL), fr_locale) != 0)
+ {
+ LLStringUtil::setLocale(prev_locale);
+ setlocale(LC_TIME, prev_clocale.c_str());
+ skip("Cannot set French locale");
+ }
+
+ LLStringUtil::setLocale(fr_locale);
+ test_date_string(fr_locale, t, "%d %B %Y - %H:%M", "08 septembre 2009 - 01:40");
+ test_date_string(fr_locale, t, "%H", "01");
+ test_date_string(fr_locale, t, "%M", "40");
+ test_date_string(fr_locale, t, "%I", "01");
+ test_date_string(fr_locale, t, "%d", "08");
+ test_date_string(fr_locale, t, "%Y", "2009");
+ test_date_string(fr_locale, t, "%A", "mardi");
+ test_date_string(fr_locale, t, "%B", "septembre");
+
+ LLStringUtil::setLocale(prev_locale);
+ setlocale(LC_TIME, prev_clocale.c_str());
+ }
}
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index f4457b6d15..ca15314e69 100755
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -355,7 +355,7 @@ namespace tut
{
char binData[] = "abcdefghijklmnop";
- addValue(messageBlockData, "testBinData", &binData, MVT_FIXED, sizeof(binData));
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_FIXED, sizeof(binData));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -395,7 +395,7 @@ namespace tut
{
U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts
- addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -415,7 +415,7 @@ namespace tut
{
U32 binData[] = {9,8,7,6,5,4,3,2,1};
- addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -435,7 +435,7 @@ namespace tut
{
U8 data = 0xa5;
- addValue(messageBlockData, "testBinData", &data, MVT_U8, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -452,7 +452,7 @@ namespace tut
{
U16 data = 0xa55a;
- addValue(messageBlockData, "testBinData", &data, MVT_U16, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -469,7 +469,7 @@ namespace tut
{
U32 data = 0xa55a7117;
- addValue(messageBlockData, "testBinData", &data, MVT_U32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -485,7 +485,7 @@ namespace tut
void LLSDMessageBuilderTestObject::test<27>()
{
U64 data = U64L(0xa55a711711223344);
- addValue(messageBlockData, "testBinData", &data, MVT_U64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -502,7 +502,7 @@ namespace tut
{
S8 data = -31;
- addValue(messageBlockData, "testBinData", &data, MVT_S8, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -519,7 +519,7 @@ namespace tut
{
S16 data = -31;
- addValue(messageBlockData, "testBinData", &data, MVT_S16, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -536,7 +536,7 @@ namespace tut
{
S32 data = -3100;
- addValue(messageBlockData, "testBinData", &data, MVT_S32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -553,7 +553,7 @@ namespace tut
{
S64 data = -31003100;
- addValue(messageBlockData, "testBinData", &data, MVT_S64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -570,7 +570,7 @@ namespace tut
{
F32 data = 1234.1234f;
- addValue(messageBlockData, "testBinData", &data, MVT_F32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -587,7 +587,7 @@ namespace tut
{
F64 data = 1234.1234;
- addValue(messageBlockData, "testBinData", &data, MVT_F64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -604,7 +604,7 @@ namespace tut
{
LLVector3 data(1,2,3);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector3, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -621,7 +621,7 @@ namespace tut
{
LLVector3d data(1,2,3);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector3d, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3d, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -639,7 +639,7 @@ namespace tut
LLVector4 data(1,2,3,4);
LLSD v = ll_sd_from_vector4(data);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector4, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector4, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -659,7 +659,7 @@ namespace tut
//we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
LLVector3 vec = data.packToVector3();
- addValue(messageBlockData, "testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
+ addValue(messageBlockData, (char *)"testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -676,7 +676,7 @@ namespace tut
{
LLUUID data("01234567-0123-0123-0123-234567abcdef");
- addValue(messageBlockData, "testBinData", &data, MVT_LLUUID, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLUUID, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -698,8 +698,8 @@ namespace tut
LLMsgData* md = new LLMsgData("testMessage");
LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
- addValue(mbd, "testBoolFalse", &valueFalse, MVT_BOOL, sizeof(BOOL));
- addValue(mbd, "testBoolTrue", &valueTrue, MVT_BOOL, sizeof(BOOL));
+ addValue(mbd, (char *)"testBoolFalse", &valueFalse, MVT_BOOL, sizeof(BOOL));
+ addValue(mbd, (char *)"testBoolTrue", &valueTrue, MVT_BOOL, sizeof(BOOL));
md->addBlock(mbd);
LLSDMessageBuilder builder = defaultBuilder();
@@ -717,7 +717,7 @@ namespace tut
U32 data(0xff887766);
LLSD v = ll_sd_from_ipaddr(data);
- addValue(messageBlockData, "testBinData", &data, MVT_IP_ADDR, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_ADDR, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -734,7 +734,7 @@ namespace tut
{
U16 data = 0xff88;
- addValue(messageBlockData, "testBinData", &data, MVT_IP_PORT, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_PORT, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -751,7 +751,7 @@ namespace tut
{
U16 data[3] = {0,1,2};
- addValue(messageBlockData, "testBinData", &data, MVT_U16Vec3, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Vec3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -771,7 +771,7 @@ namespace tut
{
U16 data[4] = {0,1,2,4};
- addValue(messageBlockData, "testBinData", &data, MVT_U16Quat, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Quat, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -791,7 +791,7 @@ namespace tut
{
S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};
- addValue(messageBlockData, "testBinData", &data, MVT_S16Array, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16Array, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 0ba5758e15..07e187ce45 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,11 @@
# include "ctype_workaround.h"
#endif
+#ifndef LL_WINDOWS
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#endif
+
namespace tut
{
std::string sSourceDir;
@@ -245,6 +250,11 @@ void wouldHaveCrashed(const std::string& message)
int main(int argc, char **argv)
{
+ // The following line must be executed to initialize Google Mock
+ // (and Google Test) before running the tests.
+#ifndef LL_WINDOWS
+ ::testing::InitGoogleMock(&argc, argv);
+#endif
LLError::initForApplication(".");
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index f668867a02..7869763302 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -283,7 +283,7 @@ void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alig
////////////////////////////////////////////////////////////////////////////////
//
-bool LLMediaPluginTest::checkGLError(char *name)
+bool LLMediaPluginTest::checkGLError(const char *name)
{
bool result = false;
GLenum error = glGetError();
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h
index 2d0ba0e3f6..c2b2baba95 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.h
+++ b/indra/test_apps/llplugintest/llmediaplugintest.h
@@ -35,6 +35,7 @@
#include <vector>
#include <string>
#include "llpluginclassmedia.h"
+#include "llgl.h"
// Forward declarations
class GLUI_Rotation;
@@ -87,7 +88,7 @@ class LLMediaPluginTest : public LLPluginClassMediaOwner
void mouseMove( int x, int y );
void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
- bool checkGLError(char *name = "OpenGL");
+ bool checkGLError(const char *name = "OpenGL");
void drawGeometry( int panel );
void startPanelHighlight( float red, float green, float blue, float line_width );
void endPanelHighlight();