From 6c4cadbb04d633ad7b762058bdeba6e1f650dafd Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Fri, 8 May 2009 01:26:20 +0000 Subject: Update version to 2.0.0.0 !!! --- indra/llcommon/llversionviewer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 15f0e98330..0730087662 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -33,8 +33,8 @@ #ifndef LL_LLVERSIONVIEWER_H #define LL_LLVERSIONVIEWER_H -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 24; +const S32 LL_VERSION_MAJOR = 2; +const S32 LL_VERSION_MINOR = 0; const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; -- cgit v1.2.3 From a4000c3744e42fcbb638e742f3b63fa31a0dee15 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Fri, 8 May 2009 07:43:08 +0000 Subject: merge trunk@116587 skinning-7@119389 -> viewer-2.0.0-skinning-7 --- indra/CMakeLists.txt | 4 + indra/cmake/LLAddBuildTest.cmake | 1 + indra/cmake/Variables.cmake | 1 + indra/integration_tests/CMakeLists.txt | 3 + .../integration_tests/llui_libtest/CMakeLists.txt | 96 + .../llui_libtest/llui_libtest.cpp | 149 + .../integration_tests/llui_libtest/llui_libtest.h | 36 + .../integration_tests/llui_libtest/llwidgetreg.cpp | 107 + indra/integration_tests/llui_libtest/llwidgetreg.h | 43 + indra/llaudio/llaudiodecodemgr.cpp | 2 +- indra/llcharacter/llbvhloader.cpp | 161 +- indra/llcharacter/llbvhloader.h | 51 +- indra/llcharacter/llcharacter.h | 2 +- indra/llcharacter/lljointstate.h | 2 +- indra/llcharacter/llkeyframemotionparam.cpp | 7 +- indra/llcharacter/llmultigesture.cpp | 64 +- indra/llcharacter/llmultigesture.h | 10 +- indra/llcharacter/llpose.h | 6 +- indra/llcommon/CMakeLists.txt | 18 + indra/llcommon/is_approx_equal_fraction.h | 23 + indra/llcommon/linden_common.h | 18 +- indra/llcommon/llassettype.cpp | 5 +- indra/llcommon/llassettype.h | 5 +- indra/llcommon/llboost.h | 15 + indra/llcommon/llcommon.cpp | 2 + indra/llcommon/llcommon.h | 3 +- indra/llcommon/lldate.cpp | 58 +- indra/llcommon/lldate.h | 4 +- indra/llcommon/lldoubledispatch.h | 332 + indra/llcommon/llerrorthread.cpp | 2 + indra/llcommon/llevent.h | 2 +- indra/llcommon/llinstancetracker.h | 100 + indra/llcommon/llmd5.cpp | 1 + indra/llcommon/llmemory.cpp | 25 +- indra/llcommon/llmemory.h | 428 +- indra/llcommon/llmemtype.h | 5 +- indra/llcommon/llpointer.h | 177 + indra/llcommon/llptrto.cpp | 108 + indra/llcommon/llptrto.h | 93 + indra/llcommon/llqueuedthread.cpp | 2 + indra/llcommon/llrefcount.cpp | 49 + indra/llcommon/llrefcount.h | 78 + indra/llcommon/llsafehandle.h | 167 + indra/llcommon/llsdserialize.cpp | 2 +- indra/llcommon/llsdserialize.h | 3 +- indra/llcommon/llsdutil.cpp | 9 + indra/llcommon/llsdutil.h | 1 + indra/llcommon/llsecondlifeurls.cpp | 34 +- indra/llcommon/llsecondlifeurls.h | 13 +- indra/llcommon/llsingleton.h | 158 + indra/llcommon/llstat.cpp | 42 +- indra/llcommon/llstat.h | 25 +- indra/llcommon/llstring.cpp | 76 + indra/llcommon/llstring.h | 251 +- indra/llcommon/llthread.h | 1 - indra/llcommon/lltimer.cpp | 9 +- indra/llcommon/lltimer.h | 9 +- indra/llcommon/lltreeiterators.h | 691 ++ indra/llcrashlogger/llcrashlogger.cpp | 1 + indra/llimage/llimage.h | 2 +- indra/llimage/llimagedxt.h | 1 + indra/llimage/llimagetga.cpp | 4 +- indra/llimage/llimageworker.h | 1 + indra/llimagej2coj/llimagej2coj.cpp | 2 +- indra/llinventory/lleconomy.h | 2 +- indra/llinventory/llinventory.cpp | 105 +- indra/llinventory/llinventory.h | 4 +- indra/llinventory/llinventorytype.cpp | 4 + indra/llinventory/llinventorytype.h | 3 +- indra/llinventory/llnotecard.h | 2 +- indra/llinventory/llparcel.cpp | 4 +- indra/llinventory/llparcel.h | 1 + indra/llinventory/llpermissions.cpp | 63 +- indra/llinventory/llpermissions.h | 3 - indra/llinventory/llsaleinfo.cpp | 34 +- indra/llinventory/llsaleinfo.h | 3 - indra/llmath/llmath.h | 4 +- indra/llmath/llrect.h | 6 +- indra/llmath/llsdutil_math.cpp | 5 +- indra/llmath/llvolume.h | 2 +- indra/llmath/llvolumemgr.h | 2 +- indra/llmath/v4color.cpp | 34 + indra/llmath/v4color.h | 15 +- indra/llmath/v4coloru.h | 6 + indra/llmessage/llares.h | 3 +- indra/llmessage/llcachename.cpp | 213 +- indra/llmessage/llcachename.h | 27 +- indra/llmessage/llhttpclientadapter.cpp | 7 +- indra/llmessage/llhttpclientadapter.h | 9 +- indra/llmessage/llhttpclientinterface.h | 7 +- indra/llmessage/llhttpnode.h | 3 +- indra/llmessage/llhttpnodeadapter.h | 15 +- indra/llmessage/llinstantmessage.cpp | 2 +- indra/llmessage/llinstantmessage.h | 3 +- indra/llmessage/llmessagesenderinterface.h | 7 +- indra/llmessage/llregionpresenceverifier.cpp | 25 +- indra/llmessage/llregionpresenceverifier.h | 25 +- indra/llmessage/llstoredmessage.cpp | 2 +- indra/llmessage/llstoredmessage.h | 2 +- indra/llmessage/lltemplatemessagedispatcher.cpp | 17 +- indra/llmessage/lltemplatemessagedispatcher.h | 17 +- indra/llmessage/lltransfersourceasset.cpp | 2 + indra/llmessage/lltrustedmessageservice.cpp | 17 +- indra/llmessage/lltrustedmessageservice.h | 17 +- indra/llmessage/message.h | 2 +- indra/llmessage/message_prehash.cpp | 2 +- indra/llmessage/tests/commtest.h | 23 + indra/llmessage/tests/llcurl_stub.cpp | 10 +- indra/llmessage/tests/llhttpclientadapter_test.cpp | 7 +- .../tests/lltemplatemessagedispatcher_test.cpp | 17 +- indra/llmessage/tests/lltesthttpclientadapter.cpp | 2 +- indra/llmessage/tests/lltesthttpclientadapter.h | 2 +- indra/llmessage/tests/lltestmessagesender.cpp | 2 +- indra/llmessage/tests/lltestmessagesender.h | 2 +- .../tests/lltrustedmessageservice_test.cpp | 17 +- indra/llmessage/tests/networkio.h | 23 + indra/llprimitive/llmaterialtable.cpp | 11 + indra/llprimitive/llmaterialtable.h | 2 + indra/llprimitive/llprimitive.h | 2 +- indra/llprimitive/llprimtexturelist.cpp | 7 +- indra/llprimitive/llprimtexturelist.h | 7 +- indra/llrender/llfontbitmapcache.cpp | 7 +- indra/llrender/llfontbitmapcache.h | 7 +- indra/llrender/llfontgl.cpp | 118 +- indra/llrender/llfontgl.h | 47 +- indra/llrender/llfontregistry.cpp | 19 +- indra/llrender/llfontregistry.h | 13 +- indra/llrender/llimagegl.h | 3 +- indra/llrender/llrender.h | 2 +- indra/llrender/llvertexbuffer.cpp | 1 - indra/llrender/llvertexbuffer.h | 1 - indra/llui/CMakeLists.txt | 48 +- indra/llui/llbutton.cpp | 680 +- indra/llui/llbutton.h | 195 +- indra/llui/llcallbackmap.h | 19 +- indra/llui/llcheckboxctrl.cpp | 278 +- indra/llui/llcheckboxctrl.h | 73 +- indra/llui/llcombobox.cpp | 555 +- indra/llui/llcombobox.h | 126 +- indra/llui/llconsole.cpp | 393 + indra/llui/llconsole.h | 162 + indra/llui/llcontainerview.cpp | 301 + indra/llui/llcontainerview.h | 92 + indra/llui/lldraghandle.cpp | 105 +- indra/llui/lldraghandle.h | 44 +- indra/llui/llf32uictrl.cpp | 57 + indra/llui/llf32uictrl.h | 83 + indra/llui/llfloater.cpp | 1649 ++-- indra/llui/llfloater.h | 297 +- indra/llui/llfloaterreg.cpp | 423 + indra/llui/llfloaterreg.h | 149 + indra/llui/llflyoutbutton.cpp | 94 + indra/llui/llflyoutbutton.h | 71 + indra/llui/llfocusmgr.cpp | 20 +- indra/llui/llfunctorregistry.h | 2 +- indra/llui/lliconctrl.cpp | 126 +- indra/llui/lliconctrl.h | 32 +- indra/llui/llkeywords.cpp | 4 +- indra/llui/lllayoutstack.cpp | 718 ++ indra/llui/lllayoutstack.h | 102 + indra/llui/lllazyvalue.h | 83 + indra/llui/lllineeditor.cpp | 690 +- indra/llui/lllineeditor.h | 177 +- indra/llui/llmenugl.cpp | 3256 +++----- indra/llui/llmenugl.h | 583 +- indra/llui/llmodaldialog.cpp | 48 +- indra/llui/llmodaldialog.h | 2 +- indra/llui/llmultifloater.cpp | 510 ++ indra/llui/llmultifloater.h | 107 + indra/llui/llmultislider.cpp | 218 +- indra/llui/llmultislider.h | 97 +- indra/llui/llmultisliderctrl.cpp | 392 +- indra/llui/llmultisliderctrl.h | 71 +- indra/llui/llnotifications.cpp | 164 +- indra/llui/llnotifications.h | 97 +- indra/llui/llpanel.cpp | 1133 +-- indra/llui/llpanel.h | 164 +- indra/llui/llprogressbar.cpp | 135 +- indra/llui/llprogressbar.h | 45 +- indra/llui/llradiogroup.cpp | 248 +- indra/llui/llradiogroup.h | 74 +- indra/llui/llresizebar.cpp | 37 +- indra/llui/llresizebar.h | 26 +- indra/llui/llresizehandle.cpp | 57 +- indra/llui/llresizehandle.h | 13 +- indra/llui/llresmgr.cpp | 147 +- indra/llui/llresmgr.h | 25 +- indra/llui/llscrollbar.cpp | 237 +- indra/llui/llscrollbar.h | 72 +- indra/llui/llscrollcontainer.cpp | 303 +- indra/llui/llscrollcontainer.h | 36 +- indra/llui/llscrollingpanellist.cpp | 62 +- indra/llui/llscrollingpanellist.h | 30 +- indra/llui/llscrolllistcell.cpp | 413 + indra/llui/llscrolllistcell.h | 223 + indra/llui/llscrolllistcolumn.cpp | 320 + indra/llui/llscrolllistcolumn.h | 189 + indra/llui/llscrolllistctrl.cpp | 1884 +---- indra/llui/llscrolllistctrl.h | 433 +- indra/llui/llscrolllistitem.cpp | 157 + indra/llui/llscrolllistitem.h | 129 + indra/llui/llsdparam.cpp | 158 + indra/llui/llsdparam.h | 107 + indra/llui/llsearcheditor.cpp | 124 + indra/llui/llsearcheditor.h | 98 + indra/llui/llslider.cpp | 155 +- indra/llui/llslider.h | 71 +- indra/llui/llsliderctrl.cpp | 339 +- indra/llui/llsliderctrl.h | 119 +- indra/llui/llspinctrl.cpp | 371 +- indra/llui/llspinctrl.h | 74 +- indra/llui/llstatbar.cpp | 295 + indra/llui/llstatbar.h | 108 + indra/llui/llstatgraph.cpp | 163 + indra/llui/llstatgraph.h | 76 + indra/llui/llstatview.cpp | 66 + indra/llui/llstatview.h | 63 + indra/llui/llstyle.cpp | 32 +- indra/llui/llstyle.h | 9 +- indra/llui/lltabcontainer.cpp | 790 +- indra/llui/lltabcontainer.h | 119 +- indra/llui/lltextbox.cpp | 245 +- indra/llui/lltextbox.h | 81 +- indra/llui/lltexteditor.cpp | 572 +- indra/llui/lltexteditor.h | 110 +- indra/llui/lltextparser.cpp | 55 +- indra/llui/lltextparser.h | 34 +- indra/llui/llui.cpp | 386 +- indra/llui/llui.h | 312 +- indra/llui/lluictrl.cpp | 354 +- indra/llui/lluictrl.h | 179 +- indra/llui/lluictrlfactory.cpp | 984 ++- indra/llui/lluictrlfactory.h | 320 +- indra/llui/lluifwd.h | 1 - indra/llui/lluiimage.cpp | 158 + indra/llui/lluiimage.h | 113 + indra/llui/lluistring.cpp | 7 +- indra/llui/llview.cpp | 1226 ++- indra/llui/llview.h | 345 +- indra/llui/llviewborder.cpp | 139 +- indra/llui/llviewborder.h | 57 +- indra/llui/llviewmodel.cpp | 163 + indra/llui/llviewmodel.h | 219 + indra/llui/llviewquery.h | 2 +- indra/llvfs/lldir.cpp | 55 +- indra/llvfs/lldir.h | 34 +- indra/llvfs/lldir_linux.cpp | 8 +- indra/llvfs/lldir_linux.h | 3 +- indra/llvfs/lldir_mac.cpp | 8 +- indra/llvfs/lldir_mac.h | 3 +- indra/llvfs/lldir_solaris.cpp | 8 +- indra/llvfs/lldir_solaris.h | 3 +- indra/llvfs/lldir_win32.cpp | 17 +- indra/llvfs/lldir_win32.h | 3 +- indra/llvfs/lllfsthread.h | 2 +- indra/llvfs/llpidlock.cpp | 7 +- indra/llvfs/llpidlock.h | 7 +- indra/llvfs/llvfs.cpp | 2 + indra/llwindow/CMakeLists.txt | 6 +- indra/llwindow/lldxhardware.cpp | 1 + indra/llwindow/llkeyboard.cpp | 2 +- indra/llwindow/llkeyboardmacosx.cpp | 2 +- indra/llwindow/llkeyboardsdl.cpp | 2 +- indra/llwindow/llkeyboardwin32.cpp | 10 +- indra/llwindow/llpreeditor.h | 2 +- indra/llwindow/llwindow.cpp | 233 +- indra/llwindow/llwindow.h | 83 +- indra/llwindow/llwindowcallbacks.cpp | 201 + indra/llwindow/llwindowcallbacks.h | 85 + indra/llwindow/llwindowheadless.cpp | 6 +- indra/llwindow/llwindowheadless.h | 9 +- indra/llwindow/llwindowmacosx.cpp | 27 +- indra/llwindow/llwindowmacosx.h | 6 +- indra/llwindow/llwindowsdl.cpp | 16 +- indra/llwindow/llwindowsdl.h | 5 +- indra/llwindow/llwindowwin32.cpp | 121 +- indra/llwindow/llwindowwin32.h | 4 +- indra/llxml/CMakeLists.txt | 3 + indra/llxml/llcontrol.cpp | 724 +- indra/llxml/llcontrol.h | 286 +- indra/llxml/llcontrolgroupreader.h | 73 +- indra/llxml/llxmlnode.cpp | 148 +- indra/llxml/llxmlnode.h | 30 +- indra/lscript/lscript_execute.h | 2 + indra/newview/CMakeLists.txt | 106 +- indra/newview/app_settings/ignorable_dialogs.xml | 291 + indra/newview/app_settings/settings.xml | 8060 +++++++------------- indra/newview/app_settings/settings_files.xml | 61 +- indra/newview/app_settings/std_bump.ini | 30 +- indra/newview/llagent.cpp | 232 +- indra/newview/llagent.h | 25 +- indra/newview/llagentaccess.cpp | 52 +- indra/newview/llagentaccess.h | 32 +- indra/newview/llagentlanguage.h | 2 +- indra/newview/llagentpilot.cpp | 3 - indra/newview/llappviewer.cpp | 351 +- indra/newview/llappviewer.h | 15 +- indra/newview/llappviewerwin32.cpp | 24 +- indra/newview/llassetuploadresponders.cpp | 236 +- indra/newview/llavatariconctrl.cpp | 244 + indra/newview/llavatariconctrl.h | 86 + indra/newview/llavatarpropertiesprocessor.cpp | 138 + indra/newview/llavatarpropertiesprocessor.h | 80 + indra/newview/llcallingcard.cpp | 2 +- indra/newview/llchatbar.cpp | 79 +- indra/newview/llchatbar.h | 4 +- indra/newview/llcloud.h | 2 +- indra/newview/llcolorswatch.cpp | 152 +- indra/newview/llcolorswatch.h | 57 +- indra/newview/llcompilequeue.cpp | 255 +- indra/newview/llcompilequeue.h | 65 +- indra/newview/llcurrencyuimanager.cpp | 4 +- indra/newview/lldebugmessagebox.cpp | 131 +- indra/newview/lldebugmessagebox.h | 4 +- indra/newview/lldebugview.cpp | 58 +- indra/newview/lldebugview.h | 14 +- indra/newview/lldirpicker.cpp | 1 + indra/newview/lldrawable.h | 1 - indra/newview/lldrawpoolavatar.cpp | 23 +- indra/newview/lldrawpoolbump.cpp | 8 +- indra/newview/lldrawpoolsky.cpp | 1 - indra/newview/lldrawpooltree.cpp | 1 - indra/newview/lldrawpoolwater.cpp | 1 - indra/newview/lldynamictexture.cpp | 5 + indra/newview/lleventnotifier.cpp | 5 +- indra/newview/llface.h | 1 - indra/newview/llfasttimerview.cpp | 23 +- indra/newview/llfasttimerview.h | 2 +- indra/newview/llfavoritesbar.cpp | 328 + indra/newview/llfavoritesbar.h | 70 + indra/newview/llfilepicker.cpp | 8 + indra/newview/llfirstuse.cpp | 66 +- indra/newview/llflexibleobject.h | 1 - indra/newview/llfloaterabout.cpp | 129 +- indra/newview/llfloaterabout.h | 13 +- indra/newview/llfloateranimpreview.cpp | 180 +- indra/newview/llfloateranimpreview.h | 8 +- indra/newview/llfloaterauction.cpp | 40 +- indra/newview/llfloaterauction.h | 14 +- indra/newview/llfloateravatarpicker.cpp | 78 +- indra/newview/llfloateravatarpicker.h | 5 +- indra/newview/llfloateravatartextures.cpp | 29 +- indra/newview/llfloateravatartextures.h | 1 + indra/newview/llfloaterbeacons.cpp | 8 +- indra/newview/llfloaterbeacons.h | 4 +- indra/newview/llfloaterbuildoptions.cpp | 48 +- indra/newview/llfloaterbuildoptions.h | 13 +- indra/newview/llfloaterbulkpermission.cpp | 19 +- indra/newview/llfloaterbulkpermission.h | 1 + indra/newview/llfloaterbump.cpp | 56 +- indra/newview/llfloaterbump.h | 17 +- indra/newview/llfloaterbuy.cpp | 23 +- indra/newview/llfloaterbuy.h | 2 +- indra/newview/llfloaterbuycontents.cpp | 15 +- indra/newview/llfloaterbuycontents.h | 2 +- indra/newview/llfloaterbuycurrency.cpp | 20 +- indra/newview/llfloaterbuyland.cpp | 39 +- indra/newview/llfloatercamera.cpp | 56 +- indra/newview/llfloatercamera.h | 2 +- indra/newview/llfloaterchat.cpp | 182 +- indra/newview/llfloaterchat.h | 24 +- indra/newview/llfloaterchatterbox.cpp | 92 +- indra/newview/llfloaterchatterbox.h | 101 +- indra/newview/llfloatercolorpicker.cpp | 254 +- indra/newview/llfloatercolorpicker.h | 10 +- indra/newview/llfloaterdaycycle.cpp | 14 +- indra/newview/llfloaterdaycycle.h | 2 +- indra/newview/llfloaterenvsettings.cpp | 72 +- indra/newview/llfloaterenvsettings.h | 4 +- indra/newview/llfloaterevent.cpp | 12 +- indra/newview/llfloaterevent.h | 2 +- indra/newview/llfloaterfonttest.cpp | 11 +- indra/newview/llfloaterfonttest.h | 7 +- indra/newview/llfloaterfriends.cpp | 77 +- indra/newview/llfloaterfriends.h | 10 +- indra/newview/llfloatergesture.cpp | 74 +- indra/newview/llfloatergesture.h | 2 +- indra/newview/llfloatergodtools.cpp | 194 +- indra/newview/llfloatergodtools.h | 25 +- indra/newview/llfloatergroupinvite.cpp | 41 +- indra/newview/llfloatergroupinvite.h | 5 +- indra/newview/llfloatergroups.cpp | 40 +- indra/newview/llfloatergroups.h | 11 +- indra/newview/llfloaterhandler.cpp | 2 +- indra/newview/llfloaterhardwaresettings.cpp | 23 +- indra/newview/llfloaterhardwaresettings.h | 6 +- indra/newview/llfloaterhud.cpp | 17 +- indra/newview/llfloaterinspect.cpp | 29 +- indra/newview/llfloaterjoystick.cpp | 60 +- indra/newview/llfloaterjoystick.h | 5 +- indra/newview/llfloaterlagmeter.cpp | 18 +- indra/newview/llfloaterlagmeter.h | 4 +- indra/newview/llfloaterland.cpp | 135 +- indra/newview/llfloaterland.h | 9 +- indra/newview/llfloaterlandholdings.cpp | 20 +- indra/newview/llfloatermap.cpp | 178 +- indra/newview/llfloatermap.h | 44 +- indra/newview/llfloatermemleak.cpp | 8 +- indra/newview/llfloaternamedesc.cpp | 7 +- indra/newview/llfloaternotificationsconsole.cpp | 28 +- indra/newview/llfloaternotificationsconsole.h | 1 + indra/newview/llfloateropenobject.cpp | 33 +- indra/newview/llfloateropenobject.h | 3 +- indra/newview/llfloaterparcel.cpp | 12 +- indra/newview/llfloaterparcel.h | 2 +- indra/newview/llfloaterperms.cpp | 7 +- indra/newview/llfloaterpostcard.cpp | 33 +- indra/newview/llfloaterpostcard.h | 6 +- indra/newview/llfloaterpostprocess.cpp | 33 +- indra/newview/llfloaterpostprocess.h | 4 +- indra/newview/llfloaterpreference.cpp | 507 +- indra/newview/llfloaterpreference.h | 78 +- indra/newview/llfloaterproperties.cpp | 85 +- indra/newview/llfloaterproperties.h | 12 +- indra/newview/llfloaterregioninfo.cpp | 104 +- indra/newview/llfloaterregioninfo.h | 14 +- indra/newview/llfloaterreporter.cpp | 254 +- indra/newview/llfloaterreporter.h | 8 +- indra/newview/llfloaterscriptdebug.cpp | 84 +- indra/newview/llfloaterscriptdebug.h | 10 +- indra/newview/llfloatersellland.cpp | 19 +- indra/newview/llfloatersellland.h | 3 +- indra/newview/llfloatersettingsdebug.cpp | 77 +- indra/newview/llfloatersettingsdebug.h | 8 +- indra/newview/llfloatersnapshot.cpp | 168 +- indra/newview/llfloatersnapshot.h | 27 +- indra/newview/llfloatertelehub.cpp | 10 +- indra/newview/llfloatertelehub.h | 2 +- indra/newview/llfloatertools.cpp | 528 +- indra/newview/llfloatertools.h | 50 +- indra/newview/llfloatertopobjects.cpp | 23 +- indra/newview/llfloatertos.cpp | 4 +- indra/newview/llfloateruipreview.cpp | 1507 ++++ indra/newview/llfloateruipreview.h | 215 + indra/newview/llfloaterurldisplay.cpp | 3 +- indra/newview/llfloaterurlentry.cpp | 34 +- indra/newview/llfloaterurlentry.h | 2 +- indra/newview/llfloatervoicedevicesettings.cpp | 19 +- indra/newview/llfloatervoicedevicesettings.h | 6 +- indra/newview/llfloaterwater.cpp | 61 +- indra/newview/llfloaterwater.h | 4 +- indra/newview/llfloaterwindlight.cpp | 66 +- indra/newview/llfloaterwindlight.h | 4 +- indra/newview/llfloaterworldmap.cpp | 226 +- indra/newview/llfloaterworldmap.h | 25 +- indra/newview/llfolderview.cpp | 289 +- indra/newview/llfolderview.h | 95 +- indra/newview/llglsandbox.cpp | 122 - indra/newview/llgroupmgr.cpp | 2 +- indra/newview/llhudeffect.h | 3 - indra/newview/llhudicon.h | 2 +- indra/newview/llhudmanager.cpp | 4 +- indra/newview/llhudmanager.h | 2 +- indra/newview/llhudobject.h | 2 +- indra/newview/llhudrender.cpp | 6 +- indra/newview/llhudrender.h | 2 + indra/newview/llhudtext.cpp | 10 +- indra/newview/llhudtext.h | 2 +- indra/newview/llhudview.cpp | 7 +- indra/newview/llimpanel.cpp | 141 +- indra/newview/llimpanel.h | 16 +- indra/newview/llimview.cpp | 347 +- indra/newview/llimview.h | 29 +- indra/newview/llinventoryactions.h | 47 + indra/newview/llinventorybridge.cpp | 970 +-- indra/newview/llinventorybridge.h | 233 +- indra/newview/llinventorymodel.cpp | 6 +- indra/newview/lljoystickbutton.cpp | 183 +- indra/newview/lljoystickbutton.h | 74 +- indra/newview/lllocationhistory.cpp | 130 + indra/newview/lllocationhistory.h | 69 + indra/newview/lllocationinputctrl.cpp | 1126 +++ indra/newview/lllocationinputctrl.h | 248 + indra/newview/lllogchat.cpp | 24 +- indra/newview/llloginhandler.cpp | 10 +- indra/newview/llmanip.cpp | 41 +- indra/newview/llmaniprotate.cpp | 38 +- indra/newview/llmanipscale.cpp | 6 +- indra/newview/llmaniptranslate.cpp | 6 +- indra/newview/llmemoryview.cpp | 7 +- indra/newview/llmemoryview.h | 10 +- indra/newview/llmenucommands.cpp | 43 +- indra/newview/llmenucommands.h | 6 - indra/newview/llmorphview.cpp | 10 +- indra/newview/llmorphview.h | 10 +- indra/newview/llmoveview.cpp | 43 +- indra/newview/llmoveview.h | 4 +- indra/newview/llmutelist.cpp | 37 +- indra/newview/llnamebox.cpp | 17 +- indra/newview/llnamebox.h | 17 +- indra/newview/llnameeditor.cpp | 60 +- indra/newview/llnameeditor.h | 26 +- indra/newview/llnamelistctrl.cpp | 324 +- indra/newview/llnamelistctrl.h | 66 +- indra/newview/llnavigationbar.cpp | 523 ++ indra/newview/llnavigationbar.h | 106 + indra/newview/llnetmap.cpp | 420 +- indra/newview/llnetmap.h | 106 +- indra/newview/lloutputmonitorctrl.cpp | 134 + indra/newview/lloutputmonitorctrl.h | 88 + indra/newview/lloverlaybar.cpp | 22 +- indra/newview/lloverlaybar.h | 1 - indra/newview/llpanelavatar.cpp | 445 +- indra/newview/llpanelavatar.h | 26 +- indra/newview/llpanelclassified.cpp | 74 +- indra/newview/llpanelcontents.cpp | 58 +- indra/newview/llpanelcontents.h | 2 +- indra/newview/llpanelface.cpp | 72 +- indra/newview/llpanelface.h | 23 +- indra/newview/llpanelgroup.cpp | 196 +- indra/newview/llpanelgroup.h | 15 +- indra/newview/llpanelgroupgeneral.cpp | 71 +- indra/newview/llpanelgroupgeneral.h | 2 +- indra/newview/llpanelgroupinvite.cpp | 33 +- indra/newview/llpanelgroupinvite.h | 2 +- indra/newview/llpanelgrouplandmoney.cpp | 69 +- indra/newview/llpanelgrouplandmoney.h | 2 +- indra/newview/llpanelgroupnotices.cpp | 90 +- indra/newview/llpanelgroupnotices.h | 4 +- indra/newview/llpanelgrouproles.cpp | 151 +- indra/newview/llpanelgrouproles.h | 23 +- indra/newview/llpanelland.cpp | 4 +- indra/newview/llpanelland.h | 2 +- indra/newview/llpanellandmedia.cpp | 6 +- indra/newview/llpanellogin.cpp | 94 +- indra/newview/llpanellogin.h | 6 +- indra/newview/llpanelobject.cpp | 79 +- indra/newview/llpanelobject.h | 14 +- indra/newview/llpanelpermissions.cpp | 71 +- indra/newview/llpanelpermissions.h | 14 +- indra/newview/llpanelpick.cpp | 103 +- indra/newview/llpanelpick.h | 3 +- indra/newview/llpanelplace.cpp | 45 +- indra/newview/llpanelvolume.cpp | 28 +- indra/newview/llpanelvolume.h | 10 +- indra/newview/llparcelselection.h | 3 +- indra/newview/llpreview.cpp | 300 +- indra/newview/llpreview.h | 58 +- indra/newview/llpreviewanim.cpp | 69 +- indra/newview/llpreviewanim.h | 11 +- indra/newview/llpreviewgesture.cpp | 239 +- indra/newview/llpreviewgesture.h | 31 +- indra/newview/llpreviewnotecard.cpp | 172 +- indra/newview/llpreviewnotecard.h | 21 +- indra/newview/llpreviewscript.cpp | 737 +- indra/newview/llpreviewscript.h | 96 +- indra/newview/llpreviewsound.cpp | 37 +- indra/newview/llpreviewsound.h | 7 +- indra/newview/llpreviewtexture.cpp | 182 +- indra/newview/llpreviewtexture.h | 25 +- indra/newview/llprogressview.cpp | 9 +- indra/newview/llprogressview.h | 2 +- indra/newview/llsavedsettingsglue.cpp | 30 +- indra/newview/llsavedsettingsglue.h | 10 +- indra/newview/llselectmgr.cpp | 38 +- indra/newview/llselectmgr.h | 10 +- indra/newview/llslurl.cpp | 114 + indra/newview/llslurl.h | 85 + indra/newview/llspatialpartition.h | 3 +- indra/newview/llstartup.cpp | 257 +- indra/newview/llstartup.h | 4 + indra/newview/llstatusbar.cpp | 119 +- indra/newview/llstatusbar.h | 6 +- indra/newview/llstylemap.cpp | 6 +- indra/newview/llsurface.cpp | 1 - indra/newview/llsurface.h | 1 - indra/newview/llsurfacepatch.h | 2 +- indra/newview/llteleporthistory.cpp | 251 + indra/newview/llteleporthistory.h | 212 + indra/newview/lltexturecache.cpp | 2 +- indra/newview/lltexturectrl.cpp | 509 +- indra/newview/lltexturectrl.h | 72 +- indra/newview/lltextureview.cpp | 53 +- indra/newview/lltextureview.h | 4 +- indra/newview/lltool.cpp | 2 +- indra/newview/lltoolbar.cpp | 253 +- indra/newview/lltoolbar.h | 21 +- indra/newview/lltoolbrush.cpp | 2 +- indra/newview/lltoolcomp.cpp | 9 +- indra/newview/lltooldraganddrop.cpp | 12 +- indra/newview/lltoolface.cpp | 7 +- indra/newview/lltoolgrab.h | 2 +- indra/newview/lltoolgun.cpp | 5 +- indra/newview/lltoolindividual.cpp | 5 +- indra/newview/lltoolmgr.cpp | 93 +- indra/newview/lltoolmgr.h | 8 +- indra/newview/lltoolmorph.cpp | 1 - indra/newview/lltoolobjpicker.cpp | 2 +- indra/newview/lltoolpie.cpp | 270 +- indra/newview/lltoolpie.h | 10 +- indra/newview/lltoolpipette.cpp | 24 +- indra/newview/lltoolpipette.h | 13 +- indra/newview/lltoolplacer.cpp | 100 +- indra/newview/lltoolplacer.h | 39 - indra/newview/lltoolselect.cpp | 6 +- indra/newview/lltoolselectland.cpp | 9 +- indra/newview/lltoolselectrect.cpp | 3 +- indra/newview/lltoolview.cpp | 4 +- indra/newview/lltracker.cpp | 23 +- indra/newview/lltracker.h | 2 +- indra/newview/lluploaddialog.cpp | 16 +- indra/newview/llurldispatcher.cpp | 109 +- indra/newview/llurldispatcher.h | 9 - indra/newview/llviewchildren.cpp | 8 +- indra/newview/llviewercamera.cpp | 21 +- indra/newview/llviewercontrol.cpp | 378 +- indra/newview/llviewercontrol.h | 116 +- indra/newview/llviewerdisplay.cpp | 23 +- indra/newview/llviewerfloaterreg.cpp | 95 + indra/newview/llviewerfloaterreg.h | 43 + indra/newview/llviewerinventory.cpp | 10 +- indra/newview/llviewerkeyboard.cpp | 2 +- indra/newview/llviewermedia.cpp | 2 +- indra/newview/llviewermenu.cpp | 5218 +++++++------ indra/newview/llviewermenu.h | 51 +- indra/newview/llviewermenufile.cpp | 103 +- indra/newview/llviewermessage.cpp | 184 +- indra/newview/llviewermessage.h | 2 +- indra/newview/llviewernetwork.cpp | 2 +- indra/newview/llviewerobject.cpp | 9 +- indra/newview/llviewerobject.h | 2 +- indra/newview/llviewerobjectlist.cpp | 23 +- indra/newview/llviewerobjectlist.h | 13 +- indra/newview/llviewerparcelmedia.cpp | 8 +- indra/newview/llviewerparcelmgr.cpp | 38 +- indra/newview/llviewerparcelmgr.h | 19 +- indra/newview/llviewerparceloverlay.cpp | 29 +- indra/newview/llviewerpartsim.h | 2 +- indra/newview/llviewerpartsource.h | 3 +- indra/newview/llviewerprecompiledheaders.h | 24 +- indra/newview/llviewerregion.cpp | 6 +- indra/newview/llviewerregion.h | 3 - indra/newview/llviewerstats.cpp | 100 +- indra/newview/llviewerstats.h | 23 +- indra/newview/llviewertexteditor.cpp | 244 +- indra/newview/llviewertexteditor.h | 41 +- indra/newview/llviewerwindow.cpp | 869 ++- indra/newview/llviewerwindow.h | 44 +- indra/newview/llvoavatar.cpp | 250 +- indra/newview/llvoavatar.h | 4 +- indra/newview/llvoavatardefines.cpp | 7 +- indra/newview/llvoavatardefines.h | 7 +- indra/newview/llvograss.cpp | 10 - indra/newview/llvoiceclient.cpp | 112 +- indra/newview/llvoiceclient.h | 4 +- indra/newview/llvoicevisualizer.cpp | 26 +- indra/newview/llvosky.cpp | 2 +- indra/newview/llvotree.cpp | 2 +- indra/newview/llvovolume.cpp | 11 +- indra/newview/llwearable.cpp | 28 +- indra/newview/llwearable.h | 3 +- indra/newview/llwearablelist.cpp | 5 +- indra/newview/llweb.cpp | 31 +- indra/newview/llweb.h | 7 - indra/newview/llwldaycycle.cpp | 3 +- indra/newview/llwldaycycle.h | 2 - indra/newview/llworld.h | 2 +- indra/newview/llworldmap.cpp | 18 +- indra/newview/llworldmap.h | 7 +- indra/newview/llworldmapview.cpp | 111 +- indra/newview/llworldmapview.h | 2 +- indra/newview/macview_Prefix.h | 2 - indra/newview/pipeline.cpp | 23 +- indra/newview/pipeline.h | 4 +- indra/newview/res/bitmap2.bmp | Bin 0 -> 25118 bytes indra/newview/res/install_icon.BMP | Bin 0 -> 262198 bytes indra/newview/res/loginbackground.bmp | Bin 0 -> 336054 bytes indra/newview/res/uninstall_icon.BMP | Bin 0 -> 262198 bytes indra/newview/skins/default/colors.xml | 3192 +++++++- .../skins/default/textures/jump_left_in.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_left_out.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_right_in.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_right_out.tga | Bin 0 -> 812 bytes .../skins/default/textures/menu_separator.png | Bin 0 -> 2831 bytes indra/newview/skins/default/textures/textures.xml | 184 +- .../newview/skins/default/textures/transparent.j2c | Bin 0 -> 172 bytes .../skins/default/textures/voice_meter_dot.j2c | Bin 0 -> 499 bytes .../skins/default/textures/voice_meter_rings.j2c | Bin 0 -> 2518 bytes .../newview/skins/default/xui/da/floater_about.xml | 72 +- .../skins/default/xui/da/floater_about_land.xml | 919 ++- .../default/xui/da/floater_animation_preview.xml | 344 +- .../skins/default/xui/da/floater_auction.xml | 18 +- .../skins/default/xui/da/floater_avatar_picker.xml | 30 +- .../default/xui/da/floater_avatar_textures.xml | 60 +- .../skins/default/xui/da/floater_beacons.xml | 30 +- .../skins/default/xui/da/floater_build_options.xml | 16 +- .../newview/skins/default/xui/da/floater_bumps.xml | 42 +- .../skins/default/xui/da/floater_buy_contents.xml | 42 +- .../skins/default/xui/da/floater_buy_currency.xml | 136 +- .../skins/default/xui/da/floater_buy_land.xml | 458 +- .../skins/default/xui/da/floater_buy_object.xml | 52 +- .../skins/default/xui/da/floater_camera.xml | 24 +- .../skins/default/xui/da/floater_choose_group.xml | 16 +- .../skins/default/xui/da/floater_color_picker.xml | 62 +- .../skins/default/xui/da/floater_critical.xml | 22 +- .../skins/default/xui/da/floater_customize.xml | 894 +-- .../default/xui/da/floater_day_cycle_options.xml | 194 +- .../default/xui/da/floater_device_settings.xml | 4 +- .../skins/default/xui/da/floater_inventory.xml | 94 +- .../xui/da/floater_inventory_item_properties.xml | 170 +- .../skins/default/xui/da/floater_joystick.xml | 176 +- .../skins/default/xui/da/floater_lagmeter.xml | 312 +- .../skins/default/xui/da/floater_land_holdings.xml | 78 +- .../default/xui/da/floater_live_lsleditor.xml | 24 +- .../skins/default/xui/da/floater_lsl_guide.xml | 14 +- .../skins/default/xui/da/floater_media_browser.xml | 38 +- .../skins/default/xui/da/floater_moveview.xml | 22 +- .../skins/default/xui/da/floater_mute_object.xml | 24 +- .../skins/default/xui/da/floater_my_friends.xml | 14 +- .../skins/default/xui/da/floater_openobject.xml | 20 +- indra/newview/skins/default/xui/da/floater_pay.xml | 42 +- .../skins/default/xui/da/floater_pay_object.xml | 60 +- .../skins/default/xui/da/floater_postcard.xml | 72 +- .../skins/default/xui/da/floater_preferences.xml | 16 +- .../default/xui/da/floater_preview_animation.xml | 20 +- .../default/xui/da/floater_preview_classified.xml | 4 +- .../skins/default/xui/da/floater_preview_event.xml | 4 +- .../default/xui/da/floater_preview_gesture.xml | 112 +- .../default/xui/da/floater_preview_notecard.xml | 26 +- .../skins/default/xui/da/floater_preview_sound.xml | 20 +- .../default/xui/da/floater_preview_texture.xml | 18 +- .../skins/default/xui/da/floater_report_abuse.xml | 368 +- .../skins/default/xui/da/floater_script_debug.xml | 12 +- .../default/xui/da/floater_script_preview.xml | 12 +- .../skins/default/xui/da/floater_script_queue.xml | 8 +- .../skins/default/xui/da/floater_script_search.xml | 26 +- .../skins/default/xui/da/floater_select_key.xml | 14 +- .../skins/default/xui/da/floater_sell_land.xml | 136 +- .../default/xui/da/floater_settings_debug.xml | 34 +- .../skins/default/xui/da/floater_snapshot.xml | 254 +- .../skins/default/xui/da/floater_sound_preview.xml | 22 +- .../skins/default/xui/da/floater_telehub.xml | 56 +- .../skins/default/xui/da/floater_texture_ctrl.xml | 48 +- .../newview/skins/default/xui/da/floater_tools.xml | 1112 +-- indra/newview/skins/default/xui/da/floater_tos.xml | 30 +- .../default/xui/da/floater_wearable_save_as.xml | 22 +- .../skins/default/xui/da/floater_world_map.xml | 162 +- .../skins/default/xui/da/menu_inventory.xml | 130 +- indra/newview/skins/default/xui/da/menu_login.xml | 26 +- indra/newview/skins/default/xui/da/menu_slurl.xml | 12 +- indra/newview/skins/default/xui/da/menu_viewer.xml | 422 +- indra/newview/skins/default/xui/da/panel_login.xml | 86 +- .../default/xui/da/panel_preferences_chat.xml | 122 +- .../default/xui/da/panel_preferences_general.xml | 236 +- .../default/xui/da/panel_preferences_graphics1.xml | 358 +- indra/newview/skins/default/xui/da/strings.xml | 810 +- indra/newview/skins/default/xui/da/xui_version.xml | 8 +- .../default/xui/de/floater_animation_preview.xml | 148 +- .../skins/default/xui/de/floater_beacons.xml | 30 +- .../skins/default/xui/de/floater_buy_land.xml | 12 +- .../skins/default/xui/de/floater_camera.xml | 24 +- .../default/xui/de/floater_day_cycle_options.xml | 192 +- .../default/xui/de/floater_device_settings.xml | 4 +- .../skins/default/xui/de/floater_env_settings.xml | 48 +- .../skins/default/xui/de/floater_god_tools.xml | 24 +- .../default/xui/de/floater_hardware_settings.xml | 80 +- indra/newview/skins/default/xui/de/floater_hud.xml | 4 +- .../skins/default/xui/de/floater_image_preview.xml | 40 +- .../skins/default/xui/de/floater_inspect.xml | 28 +- .../skins/default/xui/de/floater_joystick.xml | 152 +- .../skins/default/xui/de/floater_lagmeter.xml | 304 +- .../skins/default/xui/de/floater_lsl_guide.xml | 14 +- .../skins/default/xui/de/floater_media_browser.xml | 38 +- .../skins/default/xui/de/floater_mem_leaking.xml | 36 +- .../skins/default/xui/de/floater_mute_object.xml | 24 +- .../skins/default/xui/de/floater_my_friends.xml | 14 +- .../skins/default/xui/de/floater_post_process.xml | 106 +- .../default/xui/de/floater_preview_classified.xml | 4 +- .../skins/default/xui/de/floater_preview_event.xml | 4 +- .../skins/default/xui/de/floater_region_info.xml | 4 +- .../skins/default/xui/de/floater_select_key.xml | 16 +- .../skins/default/xui/de/floater_sell_land.xml | 12 +- .../default/xui/de/floater_settings_debug.xml | 8 +- .../skins/default/xui/de/floater_snapshot.xml | 108 +- .../newview/skins/default/xui/de/floater_tools.xml | 289 +- .../skins/default/xui/de/floater_url_entry.xml | 24 +- .../newview/skins/default/xui/de/floater_water.xml | 178 +- .../default/xui/de/floater_windlight_options.xml | 380 +- .../skins/default/xui/de/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/de/menu_login.xml | 26 +- indra/newview/skins/default/xui/de/menu_slurl.xml | 12 +- indra/newview/skins/default/xui/de/mime_types.xml | 460 +- .../skins/default/xui/de/panel_audio_device.xml | 50 +- .../newview/skins/default/xui/de/panel_friends.xml | 82 +- .../newview/skins/default/xui/de/panel_groups.xml | 30 +- indra/newview/skins/default/xui/de/panel_login.xml | 12 +- .../default/xui/de/panel_preferences_general.xml | 72 +- .../default/xui/de/panel_preferences_graphics1.xml | 36 +- indra/newview/skins/default/xui/de/strings.xml | 886 +-- .../skins/default/xui/de/teleport_strings.xml | 180 +- .../newview/skins/default/xui/es/floater_about.xml | 72 +- .../skins/default/xui/es/floater_about_land.xml | 856 +-- .../default/xui/es/floater_animation_preview.xml | 328 +- .../skins/default/xui/es/floater_auction.xml | 18 +- .../skins/default/xui/es/floater_avatar_picker.xml | 30 +- .../default/xui/es/floater_avatar_textures.xml | 60 +- .../skins/default/xui/es/floater_build_options.xml | 16 +- .../newview/skins/default/xui/es/floater_bumps.xml | 42 +- .../skins/default/xui/es/floater_buy_contents.xml | 42 +- .../skins/default/xui/es/floater_buy_currency.xml | 136 +- .../skins/default/xui/es/floater_buy_land.xml | 456 +- .../skins/default/xui/es/floater_buy_object.xml | 52 +- .../skins/default/xui/es/floater_choose_group.xml | 16 +- .../skins/default/xui/es/floater_color_picker.xml | 60 +- .../skins/default/xui/es/floater_critical.xml | 22 +- .../skins/default/xui/es/floater_customize.xml | 854 +-- .../skins/default/xui/es/floater_gesture.xml | 30 +- .../skins/default/xui/es/floater_god_tools.xml | 294 +- indra/newview/skins/default/xui/es/floater_im.xml | 90 +- .../skins/default/xui/es/floater_image_preview.xml | 104 +- .../skins/default/xui/es/floater_inventory.xml | 94 +- .../xui/es/floater_inventory_item_properties.xml | 170 +- .../xui/es/floater_inventory_view_finder.xml | 48 +- .../skins/default/xui/es/floater_land_holdings.xml | 78 +- .../default/xui/es/floater_live_lsleditor.xml | 24 +- .../skins/default/xui/es/floater_moveview.xml | 22 +- .../skins/default/xui/es/floater_openobject.xml | 16 +- indra/newview/skins/default/xui/es/floater_pay.xml | 42 +- .../skins/default/xui/es/floater_pay_object.xml | 60 +- .../skins/default/xui/es/floater_postcard.xml | 72 +- .../skins/default/xui/es/floater_preferences.xml | 16 +- .../default/xui/es/floater_preview_animation.xml | 16 +- .../default/xui/es/floater_preview_gesture.xml | 120 +- .../default/xui/es/floater_preview_notecard.xml | 32 +- .../skins/default/xui/es/floater_preview_sound.xml | 16 +- .../default/xui/es/floater_preview_texture.xml | 18 +- .../skins/default/xui/es/floater_report_abuse.xml | 360 +- .../skins/default/xui/es/floater_script_debug.xml | 12 +- .../default/xui/es/floater_script_preview.xml | 12 +- .../skins/default/xui/es/floater_script_queue.xml | 8 +- .../skins/default/xui/es/floater_script_search.xml | 26 +- .../skins/default/xui/es/floater_sell_land.xml | 136 +- .../default/xui/es/floater_settings_debug.xml | 34 +- .../skins/default/xui/es/floater_snapshot.xml | 270 +- .../skins/default/xui/es/floater_sound_preview.xml | 22 +- .../skins/default/xui/es/floater_telehub.xml | 56 +- .../skins/default/xui/es/floater_texture_ctrl.xml | 48 +- .../newview/skins/default/xui/es/floater_tools.xml | 1222 +-- .../skins/default/xui/es/floater_top_objects.xml | 110 +- indra/newview/skins/default/xui/es/floater_tos.xml | 32 +- .../default/xui/es/floater_wearable_save_as.xml | 22 +- .../skins/default/xui/es/floater_world_map.xml | 148 +- .../skins/default/xui/es/menu_inventory.xml | 130 +- indra/newview/skins/default/xui/es/menu_viewer.xml | 406 +- .../skins/default/xui/es/panel_group_general.xml | 142 +- .../skins/default/xui/es/panel_group_invite.xml | 46 +- .../default/xui/es/panel_group_land_money.xml | 150 +- .../skins/default/xui/es/panel_group_notices.xml | 142 +- .../skins/default/xui/es/panel_group_roles.xml | 300 +- indra/newview/skins/default/xui/es/panel_login.xml | 86 +- .../default/xui/es/panel_preferences_chat.xml | 114 +- .../default/xui/es/panel_preferences_general.xml | 228 +- .../default/xui/es/panel_preferences_graphics1.xml | 352 +- .../skins/default/xui/es/panel_region_covenant.xml | 100 +- .../skins/default/xui/es/panel_region_debug.xml | 80 +- .../skins/default/xui/es/panel_region_estate.xml | 138 +- .../skins/default/xui/es/panel_region_general.xml | 92 +- .../skins/default/xui/es/panel_region_terrain.xml | 54 +- .../skins/default/xui/es/panel_region_texture.xml | 114 +- .../skins/default/xui/es/panel_scrolling_param.xml | 20 +- .../skins/default/xui/es/panel_status_bar.xml | 76 +- indra/newview/skins/default/xui/es/xui_version.xml | 8 +- .../newview/skins/default/xui/fr/floater_about.xml | 68 +- .../skins/default/xui/fr/floater_about_land.xml | 880 +-- .../default/xui/fr/floater_animation_preview.xml | 330 +- .../skins/default/xui/fr/floater_auction.xml | 36 +- .../skins/default/xui/fr/floater_avatar_picker.xml | 42 +- .../default/xui/fr/floater_avatar_textures.xml | 76 +- .../skins/default/xui/fr/floater_beacons.xml | 30 +- .../skins/default/xui/fr/floater_build_options.xml | 16 +- .../newview/skins/default/xui/fr/floater_bumps.xml | 42 +- .../skins/default/xui/fr/floater_buy_contents.xml | 42 +- .../skins/default/xui/fr/floater_buy_currency.xml | 136 +- .../skins/default/xui/fr/floater_buy_land.xml | 472 +- .../skins/default/xui/fr/floater_buy_object.xml | 52 +- .../skins/default/xui/fr/floater_camera.xml | 24 +- .../skins/default/xui/fr/floater_choose_group.xml | 16 +- .../skins/default/xui/fr/floater_color_picker.xml | 64 +- .../skins/default/xui/fr/floater_critical.xml | 22 +- .../skins/default/xui/fr/floater_customize.xml | 898 +-- .../default/xui/fr/floater_day_cycle_options.xml | 194 +- .../default/xui/fr/floater_device_settings.xml | 6 +- .../skins/default/xui/fr/floater_env_settings.xml | 54 +- .../skins/default/xui/fr/floater_font_test.xml | 20 +- .../skins/default/xui/fr/floater_gesture.xml | 36 +- .../skins/default/xui/fr/floater_god_tools.xml | 222 +- .../default/xui/fr/floater_hardware_settings.xml | 76 +- indra/newview/skins/default/xui/fr/floater_hud.xml | 4 +- indra/newview/skins/default/xui/fr/floater_im.xml | 90 +- .../skins/default/xui/fr/floater_image_preview.xml | 104 +- .../skins/default/xui/fr/floater_inspect.xml | 28 +- .../skins/default/xui/fr/floater_inventory.xml | 110 +- .../xui/fr/floater_inventory_item_properties.xml | 170 +- .../xui/fr/floater_inventory_view_finder.xml | 48 +- .../skins/default/xui/fr/floater_joystick.xml | 170 +- .../skins/default/xui/fr/floater_lagmeter.xml | 304 +- .../skins/default/xui/fr/floater_land_holdings.xml | 82 +- .../default/xui/fr/floater_live_lsleditor.xml | 24 +- .../skins/default/xui/fr/floater_lsl_guide.xml | 14 +- .../skins/default/xui/fr/floater_media_browser.xml | 40 +- .../skins/default/xui/fr/floater_mem_leaking.xml | 36 +- .../skins/default/xui/fr/floater_moveview.xml | 24 +- .../skins/default/xui/fr/floater_mute_object.xml | 24 +- .../skins/default/xui/fr/floater_my_friends.xml | 14 +- .../skins/default/xui/fr/floater_openobject.xml | 16 +- indra/newview/skins/default/xui/fr/floater_pay.xml | 44 +- .../skins/default/xui/fr/floater_pay_object.xml | 62 +- .../skins/default/xui/fr/floater_post_process.xml | 108 +- .../skins/default/xui/fr/floater_postcard.xml | 90 +- .../skins/default/xui/fr/floater_preferences.xml | 18 +- .../default/xui/fr/floater_preview_animation.xml | 20 +- .../default/xui/fr/floater_preview_classified.xml | 4 +- .../skins/default/xui/fr/floater_preview_event.xml | 4 +- .../default/xui/fr/floater_preview_gesture.xml | 130 +- .../default/xui/fr/floater_preview_notecard.xml | 32 +- .../skins/default/xui/fr/floater_preview_sound.xml | 24 +- .../default/xui/fr/floater_preview_texture.xml | 18 +- .../skins/default/xui/fr/floater_region_info.xml | 4 +- .../skins/default/xui/fr/floater_report_abuse.xml | 366 +- .../skins/default/xui/fr/floater_script_debug.xml | 12 +- .../default/xui/fr/floater_script_preview.xml | 12 +- .../skins/default/xui/fr/floater_script_queue.xml | 8 +- .../skins/default/xui/fr/floater_script_search.xml | 30 +- .../skins/default/xui/fr/floater_select_key.xml | 14 +- .../skins/default/xui/fr/floater_sell_land.xml | 144 +- .../default/xui/fr/floater_settings_debug.xml | 34 +- .../skins/default/xui/fr/floater_snapshot.xml | 274 +- .../skins/default/xui/fr/floater_sound_preview.xml | 56 +- .../skins/default/xui/fr/floater_telehub.xml | 62 +- .../skins/default/xui/fr/floater_texture_ctrl.xml | 48 +- .../newview/skins/default/xui/fr/floater_tools.xml | 1248 +-- .../skins/default/xui/fr/floater_top_objects.xml | 110 +- indra/newview/skins/default/xui/fr/floater_tos.xml | 54 +- .../skins/default/xui/fr/floater_url_entry.xml | 26 +- .../newview/skins/default/xui/fr/floater_water.xml | 178 +- .../default/xui/fr/floater_wearable_save_as.xml | 22 +- .../default/xui/fr/floater_windlight_options.xml | 380 +- .../skins/default/xui/fr/floater_world_map.xml | 178 +- indra/newview/skins/default/xui/fr/fonts.xml | 18 +- .../skins/default/xui/fr/menu_inventory.xml | 132 +- indra/newview/skins/default/xui/fr/menu_login.xml | 26 +- indra/newview/skins/default/xui/fr/menu_slurl.xml | 12 +- indra/newview/skins/default/xui/fr/menu_viewer.xml | 422 +- indra/newview/skins/default/xui/fr/mime_types.xml | 460 +- .../skins/default/xui/fr/panel_audio_device.xml | 50 +- .../newview/skins/default/xui/fr/panel_friends.xml | 40 +- .../skins/default/xui/fr/panel_group_general.xml | 160 +- .../skins/default/xui/fr/panel_group_invite.xml | 52 +- .../default/xui/fr/panel_group_land_money.xml | 170 +- .../skins/default/xui/fr/panel_group_notices.xml | 144 +- .../skins/default/xui/fr/panel_group_roles.xml | 320 +- .../newview/skins/default/xui/fr/panel_groups.xml | 32 +- indra/newview/skins/default/xui/fr/panel_login.xml | 104 +- .../default/xui/fr/panel_preferences_chat.xml | 118 +- .../default/xui/fr/panel_preferences_general.xml | 238 +- .../default/xui/fr/panel_preferences_graphics1.xml | 390 +- .../skins/default/xui/fr/panel_region_covenant.xml | 102 +- .../skins/default/xui/fr/panel_region_debug.xml | 80 +- .../skins/default/xui/fr/panel_region_estate.xml | 156 +- .../skins/default/xui/fr/panel_region_general.xml | 90 +- .../skins/default/xui/fr/panel_region_terrain.xml | 54 +- .../skins/default/xui/fr/panel_region_texture.xml | 144 +- .../skins/default/xui/fr/panel_scrolling_param.xml | 24 +- .../skins/default/xui/fr/panel_status_bar.xml | 82 +- .../newview/skins/default/xui/fr/role_actions.xml | 402 +- indra/newview/skins/default/xui/fr/strings.xml | 932 +-- .../skins/default/xui/fr/teleport_strings.xml | 180 +- indra/newview/skins/default/xui/fr/xui_version.xml | 8 +- .../skins/default/xui/it/floater_snapshot.xml | 8 +- .../default/xui/ja/floater_animation_preview.xml | 148 +- .../skins/default/xui/ja/floater_beacons.xml | 30 +- .../skins/default/xui/ja/floater_buy_land.xml | 12 +- .../skins/default/xui/ja/floater_camera.xml | 24 +- .../default/xui/ja/floater_day_cycle_options.xml | 194 +- .../default/xui/ja/floater_device_settings.xml | 2 +- .../skins/default/xui/ja/floater_env_settings.xml | 48 +- .../skins/default/xui/ja/floater_god_tools.xml | 24 +- .../default/xui/ja/floater_hardware_settings.xml | 84 +- indra/newview/skins/default/xui/ja/floater_hud.xml | 4 +- .../skins/default/xui/ja/floater_image_preview.xml | 40 +- .../skins/default/xui/ja/floater_inspect.xml | 28 +- .../skins/default/xui/ja/floater_joystick.xml | 250 +- .../skins/default/xui/ja/floater_lagmeter.xml | 304 +- .../skins/default/xui/ja/floater_lsl_guide.xml | 14 +- .../skins/default/xui/ja/floater_media_browser.xml | 38 +- .../skins/default/xui/ja/floater_mem_leaking.xml | 38 +- .../skins/default/xui/ja/floater_mute_object.xml | 24 +- .../skins/default/xui/ja/floater_my_friends.xml | 14 +- .../skins/default/xui/ja/floater_post_process.xml | 108 +- .../default/xui/ja/floater_preview_classified.xml | 4 +- .../skins/default/xui/ja/floater_preview_event.xml | 4 +- .../skins/default/xui/ja/floater_region_info.xml | 4 +- .../skins/default/xui/ja/floater_select_key.xml | 14 +- .../skins/default/xui/ja/floater_sell_land.xml | 12 +- .../default/xui/ja/floater_settings_debug.xml | 8 +- .../skins/default/xui/ja/floater_snapshot.xml | 108 +- .../skins/default/xui/ja/floater_url_entry.xml | 26 +- .../newview/skins/default/xui/ja/floater_water.xml | 178 +- .../default/xui/ja/floater_windlight_options.xml | 380 +- .../skins/default/xui/ja/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/ja/menu_login.xml | 26 +- indra/newview/skins/default/xui/ja/menu_slurl.xml | 12 +- indra/newview/skins/default/xui/ja/mime_types.xml | 460 +- .../skins/default/xui/ja/panel_audio_device.xml | 52 +- .../newview/skins/default/xui/ja/panel_friends.xml | 106 +- .../newview/skins/default/xui/ja/panel_groups.xml | 32 +- indra/newview/skins/default/xui/ja/panel_login.xml | 12 +- .../default/xui/ja/panel_preferences_graphics1.xml | 36 +- indra/newview/skins/default/xui/ja/strings.xml | 932 +-- .../skins/default/xui/ja/teleport_strings.xml | 174 +- .../skins/default/xui/nl/floater_snapshot.xml | 8 +- .../default/xui/pl/floater_animation_preview.xml | 148 +- .../skins/default/xui/pl/floater_beacons.xml | 30 +- .../skins/default/xui/pl/floater_buy_land.xml | 12 +- .../skins/default/xui/pl/floater_god_tools.xml | 24 +- .../default/xui/pl/floater_hardware_settings.xml | 20 +- .../skins/default/xui/pl/floater_image_preview.xml | 40 +- .../skins/default/xui/pl/floater_sell_land.xml | 12 +- .../default/xui/pl/floater_settings_debug.xml | 8 +- .../skins/default/xui/pl/floater_snapshot.xml | 108 +- .../newview/skins/default/xui/pl/floater_tools.xml | 288 +- .../skins/default/xui/pl/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/pl/panel_login.xml | 14 +- .../default/xui/pl/panel_preferences_general.xml | 64 +- .../default/xui/pl/panel_preferences_graphics1.xml | 36 +- .../newview/skins/default/xui/pt/floater_about.xml | 72 +- .../skins/default/xui/pt/floater_about_land.xml | 864 +-- .../default/xui/pt/floater_animation_preview.xml | 322 +- .../skins/default/xui/pt/floater_auction.xml | 18 +- .../skins/default/xui/pt/floater_avatar_picker.xml | 30 +- .../default/xui/pt/floater_avatar_textures.xml | 60 +- .../skins/default/xui/pt/floater_beacons.xml | 30 +- .../skins/default/xui/pt/floater_build_options.xml | 16 +- .../newview/skins/default/xui/pt/floater_bumps.xml | 42 +- .../skins/default/xui/pt/floater_buy_contents.xml | 42 +- .../skins/default/xui/pt/floater_buy_currency.xml | 136 +- .../skins/default/xui/pt/floater_buy_land.xml | 450 +- .../skins/default/xui/pt/floater_buy_object.xml | 52 +- .../skins/default/xui/pt/floater_camera.xml | 24 +- .../skins/default/xui/pt/floater_choose_group.xml | 16 +- .../skins/default/xui/pt/floater_color_picker.xml | 60 +- .../skins/default/xui/pt/floater_critical.xml | 22 +- .../skins/default/xui/pt/floater_customize.xml | 902 +-- .../default/xui/pt/floater_day_cycle_options.xml | 134 +- .../skins/default/xui/pt/floater_env_settings.xml | 46 +- .../skins/default/xui/pt/floater_gesture.xml | 30 +- .../skins/default/xui/pt/floater_god_tools.xml | 212 +- .../default/xui/pt/floater_hardware_settings.xml | 76 +- indra/newview/skins/default/xui/pt/floater_hud.xml | 4 +- indra/newview/skins/default/xui/pt/floater_im.xml | 90 +- .../skins/default/xui/pt/floater_image_preview.xml | 104 +- .../skins/default/xui/pt/floater_inspect.xml | 22 +- .../skins/default/xui/pt/floater_inventory.xml | 94 +- .../xui/pt/floater_inventory_item_properties.xml | 170 +- .../xui/pt/floater_inventory_view_finder.xml | 48 +- .../skins/default/xui/pt/floater_joystick.xml | 166 +- .../skins/default/xui/pt/floater_lagmeter.xml | 304 +- .../skins/default/xui/pt/floater_land_holdings.xml | 76 +- .../default/xui/pt/floater_live_lsleditor.xml | 24 +- .../skins/default/xui/pt/floater_lsl_guide.xml | 14 +- .../skins/default/xui/pt/floater_media_browser.xml | 40 +- .../skins/default/xui/pt/floater_mem_leaking.xml | 24 +- .../skins/default/xui/pt/floater_moveview.xml | 22 +- .../skins/default/xui/pt/floater_mute_object.xml | 22 +- .../skins/default/xui/pt/floater_openobject.xml | 16 +- indra/newview/skins/default/xui/pt/floater_pay.xml | 42 +- .../skins/default/xui/pt/floater_pay_object.xml | 62 +- .../skins/default/xui/pt/floater_postcard.xml | 80 +- .../skins/default/xui/pt/floater_preferences.xml | 16 +- .../default/xui/pt/floater_preview_animation.xml | 16 +- .../default/xui/pt/floater_preview_classified.xml | 4 +- .../skins/default/xui/pt/floater_preview_event.xml | 4 +- .../default/xui/pt/floater_preview_gesture.xml | 118 +- .../default/xui/pt/floater_preview_notecard.xml | 32 +- .../skins/default/xui/pt/floater_preview_sound.xml | 16 +- .../default/xui/pt/floater_preview_texture.xml | 18 +- .../skins/default/xui/pt/floater_region_info.xml | 4 +- .../skins/default/xui/pt/floater_report_abuse.xml | 362 +- .../skins/default/xui/pt/floater_script_debug.xml | 12 +- .../default/xui/pt/floater_script_preview.xml | 12 +- .../skins/default/xui/pt/floater_script_queue.xml | 8 +- .../skins/default/xui/pt/floater_script_search.xml | 26 +- .../skins/default/xui/pt/floater_sell_land.xml | 136 +- .../default/xui/pt/floater_settings_debug.xml | 34 +- .../skins/default/xui/pt/floater_snapshot.xml | 274 +- .../skins/default/xui/pt/floater_sound_preview.xml | 22 +- .../skins/default/xui/pt/floater_telehub.xml | 56 +- .../skins/default/xui/pt/floater_texture_ctrl.xml | 46 +- .../newview/skins/default/xui/pt/floater_tools.xml | 1220 +-- .../skins/default/xui/pt/floater_top_objects.xml | 110 +- indra/newview/skins/default/xui/pt/floater_tos.xml | 30 +- .../skins/default/xui/pt/floater_url_entry.xml | 24 +- .../newview/skins/default/xui/pt/floater_water.xml | 170 +- .../default/xui/pt/floater_wearable_save_as.xml | 22 +- .../default/xui/pt/floater_windlight_options.xml | 372 +- .../skins/default/xui/pt/floater_world_map.xml | 126 +- .../skins/default/xui/pt/menu_inventory.xml | 130 +- indra/newview/skins/default/xui/pt/menu_login.xml | 26 +- indra/newview/skins/default/xui/pt/menu_slurl.xml | 12 +- indra/newview/skins/default/xui/pt/menu_viewer.xml | 406 +- indra/newview/skins/default/xui/pt/mime_types.xml | 460 +- .../skins/default/xui/pt/panel_audio_device.xml | 50 +- .../newview/skins/default/xui/pt/panel_friends.xml | 40 +- .../skins/default/xui/pt/panel_group_general.xml | 132 +- .../skins/default/xui/pt/panel_group_invite.xml | 46 +- .../default/xui/pt/panel_group_land_money.xml | 148 +- .../skins/default/xui/pt/panel_group_notices.xml | 140 +- .../skins/default/xui/pt/panel_group_roles.xml | 278 +- indra/newview/skins/default/xui/pt/panel_login.xml | 74 +- .../default/xui/pt/panel_preferences_chat.xml | 118 +- .../default/xui/pt/panel_preferences_general.xml | 228 +- .../default/xui/pt/panel_preferences_graphics1.xml | 354 +- .../skins/default/xui/pt/panel_region_covenant.xml | 100 +- .../skins/default/xui/pt/panel_region_debug.xml | 80 +- .../skins/default/xui/pt/panel_region_estate.xml | 138 +- .../skins/default/xui/pt/panel_region_general.xml | 88 +- .../skins/default/xui/pt/panel_region_terrain.xml | 54 +- .../skins/default/xui/pt/panel_region_texture.xml | 114 +- .../skins/default/xui/pt/panel_scrolling_param.xml | 20 +- .../skins/default/xui/pt/panel_status_bar.xml | 76 +- .../newview/skins/default/xui/pt/role_actions.xml | 372 +- indra/newview/skins/default/xui/pt/strings.xml | 842 +- .../skins/default/xui/pt/teleport_strings.xml | 150 +- indra/newview/skins/default/xui/pt/xui_version.xml | 8 +- indra/newview/tests/llagentaccess_test.cpp | 137 +- indra/newview/viewer_manifest.py | 1 + indra/test/CMakeLists.txt | 6 +- indra/test/lldoubledispatch_tut.cpp | 245 + indra/test/llpermissions_tut.cpp | 11 +- indra/test/llsaleinfo_tut.cpp | 15 +- indra/test/llscriptresource_tut.cpp | 7 +- indra/test/lltimestampcache_tut.cpp | 7 +- indra/test/lltranscode_tut.cpp | 7 +- indra/test/test.h | 5 +- 1134 files changed, 72992 insertions(+), 62605 deletions(-) create mode 100644 indra/integration_tests/CMakeLists.txt create mode 100644 indra/integration_tests/llui_libtest/CMakeLists.txt create mode 100644 indra/integration_tests/llui_libtest/llui_libtest.cpp create mode 100644 indra/integration_tests/llui_libtest/llui_libtest.h create mode 100644 indra/integration_tests/llui_libtest/llwidgetreg.cpp create mode 100644 indra/integration_tests/llui_libtest/llwidgetreg.h create mode 100755 indra/llcommon/lldoubledispatch.h create mode 100644 indra/llcommon/llinstancetracker.h create mode 100644 indra/llcommon/llpointer.h create mode 100644 indra/llcommon/llptrto.cpp create mode 100644 indra/llcommon/llptrto.h create mode 100644 indra/llcommon/llrefcount.cpp create mode 100644 indra/llcommon/llrefcount.h create mode 100644 indra/llcommon/llsafehandle.h create mode 100644 indra/llcommon/llsingleton.h create mode 100644 indra/llcommon/lltreeiterators.h create mode 100644 indra/llui/llconsole.cpp create mode 100644 indra/llui/llconsole.h create mode 100644 indra/llui/llcontainerview.cpp create mode 100644 indra/llui/llcontainerview.h create mode 100644 indra/llui/llf32uictrl.cpp create mode 100644 indra/llui/llf32uictrl.h create mode 100644 indra/llui/llfloaterreg.cpp create mode 100644 indra/llui/llfloaterreg.h create mode 100644 indra/llui/llflyoutbutton.cpp create mode 100644 indra/llui/llflyoutbutton.h create mode 100644 indra/llui/lllayoutstack.cpp create mode 100644 indra/llui/lllayoutstack.h create mode 100644 indra/llui/lllazyvalue.h create mode 100644 indra/llui/llmultifloater.cpp create mode 100644 indra/llui/llmultifloater.h create mode 100644 indra/llui/llscrolllistcell.cpp create mode 100644 indra/llui/llscrolllistcell.h create mode 100644 indra/llui/llscrolllistcolumn.cpp create mode 100644 indra/llui/llscrolllistcolumn.h create mode 100644 indra/llui/llscrolllistitem.cpp create mode 100644 indra/llui/llscrolllistitem.h create mode 100644 indra/llui/llsdparam.cpp create mode 100644 indra/llui/llsdparam.h create mode 100644 indra/llui/llsearcheditor.cpp create mode 100644 indra/llui/llsearcheditor.h create mode 100644 indra/llui/llstatbar.cpp create mode 100644 indra/llui/llstatbar.h create mode 100644 indra/llui/llstatgraph.cpp create mode 100644 indra/llui/llstatgraph.h create mode 100644 indra/llui/llstatview.cpp create mode 100644 indra/llui/llstatview.h create mode 100644 indra/llui/lluiimage.cpp create mode 100644 indra/llui/lluiimage.h create mode 100644 indra/llui/llviewmodel.cpp create mode 100644 indra/llui/llviewmodel.h create mode 100644 indra/llwindow/llwindowcallbacks.cpp create mode 100644 indra/llwindow/llwindowcallbacks.h create mode 100644 indra/newview/app_settings/ignorable_dialogs.xml create mode 100644 indra/newview/llavatariconctrl.cpp create mode 100644 indra/newview/llavatariconctrl.h create mode 100644 indra/newview/llavatarpropertiesprocessor.cpp create mode 100644 indra/newview/llavatarpropertiesprocessor.h create mode 100644 indra/newview/llfavoritesbar.cpp create mode 100644 indra/newview/llfavoritesbar.h create mode 100644 indra/newview/llfloateruipreview.cpp create mode 100644 indra/newview/llfloateruipreview.h create mode 100644 indra/newview/llinventoryactions.h create mode 100644 indra/newview/lllocationhistory.cpp create mode 100644 indra/newview/lllocationhistory.h create mode 100644 indra/newview/lllocationinputctrl.cpp create mode 100644 indra/newview/lllocationinputctrl.h create mode 100644 indra/newview/llnavigationbar.cpp create mode 100644 indra/newview/llnavigationbar.h create mode 100644 indra/newview/lloutputmonitorctrl.cpp create mode 100644 indra/newview/lloutputmonitorctrl.h create mode 100644 indra/newview/llslurl.cpp create mode 100644 indra/newview/llslurl.h create mode 100644 indra/newview/llteleporthistory.cpp create mode 100644 indra/newview/llteleporthistory.h create mode 100644 indra/newview/llviewerfloaterreg.cpp create mode 100644 indra/newview/llviewerfloaterreg.h create mode 100644 indra/newview/res/bitmap2.bmp create mode 100644 indra/newview/res/install_icon.BMP create mode 100644 indra/newview/res/loginbackground.bmp create mode 100644 indra/newview/res/uninstall_icon.BMP create mode 100644 indra/newview/skins/default/textures/jump_left_in.tga create mode 100644 indra/newview/skins/default/textures/jump_left_out.tga create mode 100644 indra/newview/skins/default/textures/jump_right_in.tga create mode 100644 indra/newview/skins/default/textures/jump_right_out.tga create mode 100644 indra/newview/skins/default/textures/menu_separator.png create mode 100644 indra/newview/skins/default/textures/transparent.j2c create mode 100644 indra/newview/skins/default/textures/voice_meter_dot.j2c create mode 100644 indra/newview/skins/default/textures/voice_meter_rings.j2c create mode 100755 indra/test/lldoubledispatch_tut.cpp (limited to 'indra') diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 7f4c2c33c1..c285bcae4b 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -110,3 +110,7 @@ if (SERVER) add_subdirectory(${SERVER_PREFIX}tools) endif (WINDOWS) endif (SERVER) + +# Define after the custom viewer and server targets are created so individual +# apps can add themselves as dependencies +add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 08151bc732..b19eebe1fe 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -31,6 +31,7 @@ MACRO(ADD_BUILD_TEST name parent) SET(basic_libraries ${LLCOMMON_LIBRARIES} + ${LLMATH_LIBRARIES} ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${PTHREAD_LIBRARY} diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index c4dcc7eae7..adff01197f 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -23,6 +23,7 @@ set(LIBS_SERVER_PREFIX) set(SCRIPTS_PREFIX ../scripts) set(SERVER_PREFIX) set(VIEWER_PREFIX) +set(INTEGRATION_TESTS_PREFIX) set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX}) set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX}) diff --git a/indra/integration_tests/CMakeLists.txt b/indra/integration_tests/CMakeLists.txt new file mode 100644 index 0000000000..67e8fbf1f2 --- /dev/null +++ b/indra/integration_tests/CMakeLists.txt @@ -0,0 +1,3 @@ +# -*- cmake -*- + +add_subdirectory(llui_libtest) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt new file mode 100644 index 0000000000..71a47f1475 --- /dev/null +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -0,0 +1,96 @@ +# -*- cmake -*- + +project (llui_libtest) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLImageJ2COJ) # ugh, needed for images +include(LLMath) +include(LLRender) +include(LLWindow) +include(LLUI) +include(LLVFS) # ugh, needed for LLDir +include(LLXML) +include(Linking) +# include(Tut) + +include_directories( + ${FREETYPE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ) + +set(llui_libtest_SOURCE_FILES + llui_libtest.cpp + llwidgetreg.cpp + ) + +set(llui_libtest_HEADER_FILES + CMakeLists.txt + llui_libtest.h + llwidgetreg.h + ) + +set_source_files_properties(${llui_libtest_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llui_libtest_SOURCE_FILES ${llui_libtest_HEADER_FILES}) + +add_executable(llui_libtest ${llui_libtest_SOURCE_FILES}) + +# Link with OS-specific libraries for LLWindow dependency +if (DARWIN) + find_library(COCOA_LIBRARY Cocoa) + set(OS_LIBRARIES ${COCOA_LIBRARY}) +elseif (WINDOWS) + set(OS_LIBRARIES ${WINDOWS_LIBRARIES}) +elseif (LINUX) + set(OS_LIBRARIES) +else (DARWIN) + message(FATAL_ERROR "unknown platform") +endif (DARWIN) + +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +target_link_libraries(llui_libtest + llui + ${OS_LIBRARIES} + ) + +if (WINDOWS) + set_target_properties(llui_libtest + PROPERTIES + LINK_FLAGS "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMTD" + ) + + # Copy over OpenJPEG.dll + # *NOTE: On Windows with VS2005, only the first comment prints + set(OPENJPEG_RELEASE + "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/openjpeg.dll") + add_custom_command( TARGET llui_libtest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copying OpenJPEG DLLs to binary directory" + ) + set(OPENJPEG_DEBUG + "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/openjpegd.dll") + add_custom_command( TARGET llui_libtest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR} + ) +endif (WINDOWS) + +if (VIEWER) + # Ensure people working on the viewer don't break this library + # *NOTE: This could be removed, or only built by Parabuild, if the build + # and link times become too long. JC + add_dependencies(viewer llui_libtest) +endif (VIEWER) diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp new file mode 100644 index 0000000000..599bcabfcb --- /dev/null +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -0,0 +1,149 @@ +/** + * @file llui_libtest.cpp + * @brief Integration test for the LLUI library + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llui_libtest.h" + +// project includes +#include "llwidgetreg.h" + +// linden library includes +#include "llcontrol.h" // LLControlGroup +#include "lldir.h" +#include "llerrorcontrol.h" +#include "llfloater.h" +#include "llfontgl.h" +#include "lltrans.h" +#include "llui.h" +#include "lluictrlfactory.h" + +#include + +// *TODO: switch to using TUT +// *TODO: teach Parabuild about this program, run automatically after full builds + +static std::string get_xui_dir() +{ + std::string delim = gDirUtilp->getDirDelimiter(); + return gDirUtilp->getAppRODataDir() + delim + std::string("skins") + delim + "default" + delim + "xui" + delim; +} + +int main(int argc, char** argv) +{ + // Must init LLError for llerrs to actually cause errors. + LLError::initForApplication("."); + + // Font lookup needs directory support + gDirUtilp->initAppDirs("SecondLife", "../../../newview"); + gDirUtilp->setSkinFolder("default"); + + std::string config_filename = gDirUtilp->getExpandedFilename( + LL_PATH_APP_SETTINGS, "settings.xml"); + LLControlGroup config_group("config"); + config_group.loadFromFile(config_filename); + + std::string color_filename = gDirUtilp->getExpandedFilename( + LL_PATH_DEFAULT_SKIN, "colors.xml"); + LLControlGroup color_group("color"); + color_group.loadFromFile(color_filename); + + LLControlGroup floater_group("floater"); + LLControlGroup ignores_group("ignores"); + LLUI::settings_map_t settings; + settings["config"] = &config_group; + settings["color"] = &color_group; + settings["floater"] = &floater_group; + settings["ignores"] = &ignores_group; + + LLImageProviderInterface* image_provider = NULL; + LLUI::initClass(settings, image_provider); + + const bool no_register_widgets = false; + LLWidgetReg::initClass( no_register_widgets ); + + // Unclear if this is needed + LLUI::setupPaths(); + // Otherwise we get translation warnings when setting up floaters + // (tooltips for buttons) + std::set default_args; + LLTrans::parseStrings("strings.xml", default_args); + + LLFontManager::initClass(); + + // Creating widgets apparently requires fonts to be initialized, + // otherwise it crashes. + LLFontGL::initClass(96.f, 1.f, 1.f, + gDirUtilp->getAppRODataDir(), + LLUI::getXUIPaths(), + false ); // don't create gl textures + + LLFloaterView::Params fvparams; + fvparams.name("Floater View"); + fvparams.rect( LLRect(0,480,640,0) ); + fvparams.mouse_opaque(false); + fvparams.follows.flags(FOLLOWS_ALL); + fvparams.tab_stop(false); + gFloaterView = LLUICtrlFactory::create (fvparams); + + // Convert all test floaters to new XML format + std::string delim = gDirUtilp->getDirDelimiter(); + std::string xui_dir = get_xui_dir() + "en-us" + delim; + std::string filename; + while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false)) + { + if (filename.find("_new.xml") != std::string::npos) + { + // don't re-export other test floaters + continue; + } + llinfos << "Converting " << filename << llendl; + // Build a floater and output new attributes + LLXMLNodePtr output_node = new LLXMLNode(); + LLFloater* floater = new LLFloater(); + LLUICtrlFactory::getInstance()->buildFloater(floater, + filename, + FALSE, // don't open floater + output_node); + std::string out_filename = xui_dir + filename; + std::string::size_type extension_pos = out_filename.rfind(".xml"); + out_filename.resize(extension_pos); + out_filename += "_new.xml"; + + llinfos << "Output: " << out_filename << llendl; + LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w"); + LLXMLNode::writeHeaderToFile(floater_file); + const char* const indent = " "; + output_node->writeToFile(floater_file, indent); + fclose(floater_file); + } + return 0; +} diff --git a/indra/integration_tests/llui_libtest/llui_libtest.h b/indra/integration_tests/llui_libtest/llui_libtest.h new file mode 100644 index 0000000000..a84d57dba9 --- /dev/null +++ b/indra/integration_tests/llui_libtest/llui_libtest.h @@ -0,0 +1,36 @@ +/** + * @file llui_libtest.h + * + * $LicenseInfo:firstyear=2009&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 LLUI_LIBTEST_H +#define LLUI_LIBTEST_H + +// TODO + +#endif diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp new file mode 100644 index 0000000000..f4a4665cc5 --- /dev/null +++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp @@ -0,0 +1,107 @@ +/** + * @file llwidgetreg.cpp + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llwidgetreg.h" + +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llcontainerview.h" +#include "lliconctrl.h" +#include "llmenugl.h" +#include "llmultislider.h" +#include "llmultisliderctrl.h" +#include "llprogressbar.h" +#include "llradiogroup.h" +#include "llscrollcontainer.h" +#include "llscrollingpanellist.h" +#include "llscrolllistctrl.h" +#include "llslider.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "llstatview.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "llflyoutbutton.h" +#include "llsearcheditor.h" +#include "lllayoutstack.h" + +void LLWidgetReg::initClass(bool register_widgets) +{ + // Only need to register if the Windows linker has optimized away the + // references to the object files. + if (register_widgets) + { + LLRegisterWidget button("button"); + LLRegisterWidget check_box("check_box"); + LLRegisterWidget combo_box("combo_box"); + LLRegisterWidget flyout_button("flyout_button"); + LLRegisterWidget container_view("container_view"); + LLRegisterWidget icon("icon"); + LLRegisterWidget line_editor("line_editor"); + LLRegisterWidget search_editor("search_editor"); + LLRegisterWidget menu_item_separator("menu_item_separator"); + LLRegisterWidget menu_item_call_gl("menu_item_call"); + LLRegisterWidget menu_item_check_gl("menu_item_check"); + LLRegisterWidget menu("menu"); + LLRegisterWidget menu_bar("menu_bar"); + LLRegisterWidget context_menu("context_menu"); + LLRegisterWidget multi_slider_bar("multi_slider_bar"); + LLRegisterWidget multi_slider("multi_slider"); + LLRegisterWidget panel("panel", &LLPanel::fromXML); + LLRegisterWidget layout_stack("layout_stack", &LLLayoutStack::fromXML); + LLRegisterWidget progress_bar("progress_bar"); + LLRegisterWidget radio_group("radio_group"); + LLRegisterWidget radio_item("radio_item"); + LLRegisterWidget scroll_container("scroll_container"); + LLRegisterWidget scrolling_panel_list("scrolling_panel_list"); + LLRegisterWidget scroll_list("scroll_list"); + LLRegisterWidget slider_bar("slider_bar"); + LLRegisterWidget volume_slider("volume_slider"); + LLRegisterWidget slider("slider"); + LLRegisterWidget spinner("spinner"); + LLRegisterWidget stat_bar("stat_bar"); + //LLRegisterWidget placeholder("placeholder"); + LLRegisterWidget tab_container("tab_container"); + LLRegisterWidget text("text"); + LLRegisterWidget simple_text_editor("simple_text_editor"); + LLRegisterWidget ui_ctrl("ui_ctrl"); + LLRegisterWidget stat_view("stat_view"); + //LLRegisterWidget locate("locate"); + //LLRegisterWidget pad("pad"); + LLRegisterWidget view_border("view_border"); + } + + // *HACK: Usually this is registered as a viewer text editor + LLRegisterWidget text_editor("text_editor"); +} diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.h b/indra/integration_tests/llui_libtest/llwidgetreg.h new file mode 100644 index 0000000000..263e3958c9 --- /dev/null +++ b/indra/integration_tests/llui_libtest/llwidgetreg.h @@ -0,0 +1,43 @@ +/** + * @file llwidgetreg.h + * + * $LicenseInfo:firstyear=2009&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 LLWIDGETREG_H +#define LLWIDGETREG_H + +// Register all widgets with the builder registry. +// Useful on Windows where linker discards all references to the +// static LLRegisterWidget<> calls. +class LLWidgetReg +{ +public: + static void initClass(bool register_widgets); +}; + +#endif diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 5b6db3bd87..6a494d1983 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -40,8 +40,8 @@ #include "llstring.h" #include "lldir.h" #include "llendianswizzle.h" -#include "audioengine.h" #include "llassetstorage.h" +#include "llrefcount.h" #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index e1f8ce53fb..24391eb8f3 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -56,7 +56,7 @@ const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ char gOutFile[1024]; /* Flawfinder: ignore */ - +/* //------------------------------------------------------------------------ // Status Codes //------------------------------------------------------------------------ @@ -91,7 +91,7 @@ const char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values."; const char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values."; const char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value."; const char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name."; - +*/ //------------------------------------------------------------------------ // find_next_whitespace() //------------------------------------------------------------------------ @@ -124,7 +124,9 @@ LLQuaternion::Order bvhStringToOrder( char *str ) //----------------------------------------------------------------------------- // LLBVHLoader() //----------------------------------------------------------------------------- -LLBVHLoader::LLBVHLoader(const char* buffer) + +/* + LLBVHLoader::LLBVHLoader(const char* buffer) { reset(); @@ -144,7 +146,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer) } } - char error_text[128]; /* Flawfinder: ignore */ + char error_text[128]; // Flawfinder: ignore S32 error_line; mStatus = loadBVHFile(buffer, error_text, error_line); if (mStatus != LLBVHLoader::ST_OK) @@ -158,6 +160,49 @@ LLBVHLoader::LLBVHLoader(const char* buffer) mInitialized = TRUE; } +*/ +LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine) +{ + reset(); + errorLine = 0; + mStatus = loadTranslationTable("anim.ini"); + loadStatus = mStatus; + llinfos<<"Load Status 00 : "<< loadStatus << llendl; + if (mStatus == E_ST_NO_XLT_FILE) + { + //llwarns << "NOTE: No translation table found." << llendl; + loadStatus = mStatus; + return; + } + else + { + if (mStatus != E_ST_OK) + { + //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl; + errorLine = getLineNumber(); + loadStatus = mStatus; + return; + } + } + + char error_text[128]; /* Flawfinder: ignore */ + S32 error_line; + mStatus = loadBVHFile(buffer, error_text, error_line); + + if (mStatus != E_ST_OK) + { + //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl; + loadStatus = mStatus; + errorLine = getLineNumber(); + return; + } + + applyTranslations(); + optimize(); + + mInitialized = TRUE; +} + LLBVHLoader::~LLBVHLoader() { @@ -167,7 +212,7 @@ LLBVHLoader::~LLBVHLoader() //------------------------------------------------------------------------ // LLBVHLoader::loadTranslationTable() //------------------------------------------------------------------------ -LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) +ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) { mLineNumber = 0; mTranslations.clear(); @@ -182,7 +227,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) infile.open(path, LL_APR_R); apr_file_t *fp = infile.getFileHandle(); if (!fp) - return ST_NO_XLT_FILE; + return E_ST_NO_XLT_FILE; llinfos << "NOTE: Loading translation table: " << fileName << llendl; @@ -194,9 +239,9 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) // load header //-------------------------------------------------------------------- if ( ! getLine(fp) ) - return ST_EOF; + return E_ST_EOF; if ( strncmp(mLine, "Translations 1.0", 16) ) - return ST_NO_XLT_HEADER; + return E_ST_NO_XLT_HEADER; //-------------------------------------------------------------------- // load data one line at a time @@ -222,7 +267,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char name[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " [%127[^]]", name) != 1 ) - return ST_NO_XLT_NAME; + return E_ST_NO_XLT_NAME; if (strcmp(name, "GLOBALS")==0) { @@ -245,7 +290,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char emote_str[1024]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EMOTE; + return E_ST_NO_XLT_EMOTE; mEmoteName.assign( emote_str ); // llinfos << "NOTE: Emote: " << mEmoteName.c_str() << llendl; @@ -260,7 +305,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 priority; if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return ST_NO_XLT_PRIORITY; + return E_ST_NO_XLT_PRIORITY; mPriority = priority; // llinfos << "NOTE: Priority: " << mPriority << llendl; @@ -288,7 +333,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_LOOP; + return E_ST_NO_XLT_LOOP; } mLoopInPoint = loop_in * mDuration; @@ -305,7 +350,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) F32 duration; char type[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EASEIN; + return E_ST_NO_XLT_EASEIN; mEaseIn = duration; continue; @@ -319,7 +364,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) F32 duration; char type[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EASEOUT; + return E_ST_NO_XLT_EASEOUT; mEaseOut = duration; continue; @@ -332,7 +377,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 handMorph; if (sscanf(mLine, " %*s = %d", &handMorph) != 1) - return ST_NO_XLT_HAND; + return E_ST_NO_XLT_HAND; mHand = handMorph; continue; @@ -380,7 +425,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &constraint.mTargetOffset.mV[VY], &constraint.mTargetOffset.mV[VZ]) != 13) { - return ST_NO_CONSTRAINT; + return E_ST_NO_CONSTRAINT; } } else @@ -440,7 +485,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &constraint.mTargetOffset.mV[VY], &constraint.mTargetOffset.mV[VZ]) != 13) { - return ST_NO_CONSTRAINT; + return E_ST_NO_CONSTRAINT; } } else @@ -463,7 +508,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) // at this point there must be a valid trans pointer //---------------------------------------------------------------- if ( ! trans ) - return ST_NO_XLT_NAME; + return E_ST_NO_XLT_NAME; //---------------------------------------------------------------- // check for ignore flag @@ -472,7 +517,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char trueFalse[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_IGNORE; + return E_ST_NO_XLT_IGNORE; trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); continue; @@ -497,12 +542,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } continue; @@ -523,12 +568,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } continue; @@ -541,7 +586,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char outName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_OUTNAME; + return E_ST_NO_XLT_OUTNAME; trans->mOutName = outName; continue; @@ -557,7 +602,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2], &fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2], &fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 ) - return ST_NO_XLT_MATRIX; + return E_ST_NO_XLT_MATRIX; trans->mFrameMatrix = fm; continue; @@ -573,7 +618,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2], &om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2], &om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 ) - return ST_NO_XLT_MATRIX; + return E_ST_NO_XLT_MATRIX; trans->mOffsetMatrix = om; continue; @@ -586,7 +631,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char mergeParentName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_MERGEPARENT; + return E_ST_NO_XLT_MERGEPARENT; trans->mMergeParentName = mergeParentName; continue; @@ -599,7 +644,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char mergeChildName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_MERGECHILD; + return E_ST_NO_XLT_MERGECHILD; trans->mMergeChildName = mergeChildName; continue; @@ -612,7 +657,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 priority; if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return ST_NO_XLT_PRIORITY; + return E_ST_NO_XLT_PRIORITY; trans->mPriorityModifier = priority; continue; @@ -621,14 +666,14 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } infile.close() ; - return ST_OK; + return E_ST_OK; } //------------------------------------------------------------------------ // LLBVHLoader::loadBVHFile() //------------------------------------------------------------------------ -LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line) +ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line) { std::string line; @@ -650,14 +695,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // consume hierarchy //-------------------------------------------------------------------- if (iter == tokens.end()) - return ST_EOF; + return E_ST_EOF; line = (*(iter++)); err_line++; if ( !strstr(line.c_str(), "HIERARCHY") ) { // llinfos << line << llendl; - return ST_NO_HIER; + return E_ST_NO_HIER; } //-------------------------------------------------------------------- @@ -669,7 +714,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // get next line //---------------------------------------------------------------- if (iter == tokens.end()) - return ST_EOF; + return E_ST_EOF; line = (*(iter++)); err_line++; @@ -719,7 +764,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex else { strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ - return ST_NO_JOINT; + return E_ST_NO_JOINT; } //---------------------------------------------------------------- @@ -729,7 +774,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 ) /* Flawfinder: ignore */ { strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ - return ST_NO_NAME; + return E_ST_NO_NAME; } //---------------------------------------------------------------- @@ -754,7 +799,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -765,7 +810,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "{") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_OFFSET; + return E_ST_NO_OFFSET; } else { @@ -777,7 +822,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -788,7 +833,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "OFFSET") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_OFFSET; + return E_ST_NO_OFFSET; } //---------------------------------------------------------------- @@ -796,7 +841,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -807,7 +852,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "CHANNELS") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_CHANNELS; + return E_ST_NO_CHANNELS; } //---------------------------------------------------------------- @@ -820,14 +865,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROTATION; + return E_ST_NO_ROTATION; } const char axis = *(p - 1); if ((axis != 'X') && (axis != 'Y') && (axis != 'Z')) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_AXIS; + return E_ST_NO_AXIS; } joint->mOrder[i] = axis; @@ -842,7 +887,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "MOTION") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_MOTION; + return E_ST_NO_MOTION; } //-------------------------------------------------------------------- @@ -850,7 +895,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //-------------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -858,13 +903,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "Frames:") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAMES; + return E_ST_NO_FRAMES; } if ( sscanf(line.c_str(), "Frames: %d", &mNumFrames) != 1 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAMES; + return E_ST_NO_FRAMES; } //-------------------------------------------------------------------- @@ -872,7 +917,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //-------------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -880,13 +925,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "Frame Time:") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAME_TIME; + return E_ST_NO_FRAME_TIME; } if ( sscanf(line.c_str(), "Frame Time: %f", &mFrameTime) != 1 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAME_TIME; + return E_ST_NO_FRAME_TIME; } mDuration = (F32)mNumFrames * mFrameTime; @@ -903,7 +948,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // get next line if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -922,7 +967,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_POS; + return E_ST_NO_POS; } } @@ -931,19 +976,19 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p = find_next_whitespace(++p); if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p = find_next_whitespace(++p); if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } // get 3 rot values for joint @@ -951,7 +996,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p++; @@ -962,7 +1007,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex } } - return ST_OK; + return E_ST_OK; } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 6937b9d835..ecdfc95478 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -184,6 +184,41 @@ public: S32 mPriorityModifier; }; +typedef enum e_load_status + { + E_ST_OK, + E_ST_EOF, + E_ST_NO_CONSTRAINT, + E_ST_NO_FILE, + E_ST_NO_HIER, + E_ST_NO_JOINT, + E_ST_NO_NAME, + E_ST_NO_OFFSET, + E_ST_NO_CHANNELS, + E_ST_NO_ROTATION, + E_ST_NO_AXIS, + E_ST_NO_MOTION, + E_ST_NO_FRAMES, + E_ST_NO_FRAME_TIME, + E_ST_NO_POS, + E_ST_NO_ROT, + E_ST_NO_XLT_FILE, + E_ST_NO_XLT_HEADER, + E_ST_NO_XLT_NAME, + E_ST_NO_XLT_IGNORE, + E_ST_NO_XLT_RELATIVE, + E_ST_NO_XLT_OUTNAME, + E_ST_NO_XLT_MATRIX, + E_ST_NO_XLT_MERGECHILD, + E_ST_NO_XLT_MERGEPARENT, + E_ST_NO_XLT_PRIORITY, + E_ST_NO_XLT_LOOP, + E_ST_NO_XLT_EASEIN, + E_ST_NO_XLT_EASEOUT, + E_ST_NO_XLT_HAND, + E_ST_NO_XLT_EMOTE + } ELoadStatus; + //------------------------------------------------------------------------ // TranslationMap //------------------------------------------------------------------------ @@ -194,9 +229,11 @@ class LLBVHLoader friend class LLKeyframeMotion; public: // Constructor - LLBVHLoader(const char* buffer); +// LLBVHLoader(const char* buffer); + LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); ~LLBVHLoader(); - + +/* // Status Codes typedef const char *Status; static const char *ST_OK; @@ -230,13 +267,13 @@ public: static const char *ST_NO_XLT_EASEOUT; static const char *ST_NO_XLT_HAND; static const char *ST_NO_XLT_EMOTE; - +*/ // Loads the specified translation table. - Status loadTranslationTable(const char *fileName); + ELoadStatus loadTranslationTable(const char *fileName); // Load the specified BVH file. // Returns status code. - Status loadBVHFile(const char *buffer, char *error_text, S32 &error_line); + ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line); // Applies translations to BVH data loaded. void applyTranslations(); @@ -260,7 +297,7 @@ public: BOOL isInitialized() { return mInitialized; } - Status getStatus() { return mStatus; } + ELoadStatus getStatus() { return mStatus; } protected: // Consumes one line of input from file. @@ -287,7 +324,7 @@ protected: std::string mEmoteName; BOOL mInitialized; - Status mStatus; + ELoadStatus mStatus; // computed values F32 mDuration; }; diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 0112788884..66c4c188ed 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -42,7 +42,7 @@ #include "llmotioncontroller.h" #include "llvisualparam.h" #include "string_table.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLPolyMesh; diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h index 16ad0e1200..e40cf2673f 100644 --- a/indra/llcharacter/lljointstate.h +++ b/indra/llcharacter/lljointstate.h @@ -37,7 +37,7 @@ // Header Files //----------------------------------------------------------------------------- #include "lljoint.h" -#include "llmemory.h" +#include "llrefcount.h" //----------------------------------------------------------------------------- // class LLJointState diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index 622405a5e1..c4333fc0fd 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -347,8 +347,11 @@ BOOL LLKeyframeMotionParam::loadMotions() // Load named file by concatenating the character prefix with the motion name. // Load data into a buffer to be parsed. //------------------------------------------------------------------------- - std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) - + "_" + getName() + ".llp"; + //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) + // + "_" + getName() + ".llp"; + //RN: deprecated unused reference to "motion" directory + std::string path; + //------------------------------------------------------------------------- // open the file diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 7fe21dbc93..701d6889ca 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -243,7 +243,7 @@ void LLMultiGesture::dump() //--------------------------------------------------------------------------- LLGestureStepAnimation::LLGestureStepAnimation() : LLGestureStep(), - mAnimName("None"), + mAnimName("None"), mAnimAssetID(), mFlags(0x0) { } @@ -292,20 +292,27 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepAnimation::getLabel() const +// *TODO: Translate +std::vector LLGestureStepAnimation::getLabel() const { - std::string label; + std::vector strings; + +// std::string label; if (mFlags & ANIM_FLAG_STOP) { - label = "Stop Animation: "; + strings.push_back( "AnimFlagStop"); + +// label = "Stop Animation: "; } else { - label = "Start Animation: "; + strings.push_back( "AnimFlagStart"); + +// label = "Start Animation: "; } - label += mAnimName; - return label; + strings.push_back( mAnimName); +// label += mAnimName; + return strings; } void LLGestureStepAnimation::dump() @@ -359,12 +366,15 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepSound::getLabel() const +// *TODO: Translate +std::vector LLGestureStepSound::getLabel() const { - std::string label("Sound: "); - label += mSoundName; - return label; + std::vector strings; + strings.push_back( "Sound"); + strings.push_back( mSoundName); +// std::string label("Sound: "); +// label += mSoundName; + return strings; } void LLGestureStepSound::dump() @@ -414,12 +424,13 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepChat::getLabel() const +// *TODO: Translate +std::vector LLGestureStepChat::getLabel() const { - std::string label("Chat: "); - label += mChatText; - return label; + std::vector strings; + strings.push_back("Chat"); + strings.push_back(mChatText); + return strings; } void LLGestureStepChat::dump() @@ -467,22 +478,27 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepWait::getLabel() const +// *TODO: Translate +std::vector LLGestureStepWait::getLabel() const { - std::string label("--- Wait: "); + std::vector strings; + strings.push_back( "Wait" ); + +// std::string label("--- Wait: "); if (mFlags & WAIT_FLAG_TIME) { char buffer[64]; /* Flawfinder: ignore */ snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */ - label += buffer; + strings.push_back(buffer); +// label += buffer; } else if (mFlags & WAIT_FLAG_ALL_ANIM) { - label += "until animations are done"; + strings.push_back("until animations are done"); + // label += "until animations are done"; } - return label; + return strings; } diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index eb15f600ca..fdffb35c31 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -130,7 +130,7 @@ public: virtual EStepType getType() = 0; // Return a user-readable label for this step - virtual std::string getLabel() const = 0; + virtual std::vector getLabel() const = 0; virtual S32 getMaxSerialSize() const = 0; virtual BOOL serialize(LLDataPacker& dp) const = 0; @@ -152,7 +152,7 @@ public: virtual EStepType getType() { return STEP_ANIMATION; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -175,7 +175,7 @@ public: virtual EStepType getType() { return STEP_SOUND; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -198,7 +198,7 @@ public: virtual EStepType getType() { return STEP_CHAT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -223,7 +223,7 @@ public: virtual EStepType getType() { return STEP_WAIT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 5698f21614..2b976b219d 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -36,12 +36,14 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include -#include "llmap.h" #include "lljointstate.h" #include "lljoint.h" +#include "llmap.h" +#include "llpointer.h" + #include +#include //----------------------------------------------------------------------------- diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3f14be6e18..c4663cc145 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -4,6 +4,7 @@ project(llcommon) include(00-Common) include(LLCommon) +include(Boost) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -11,6 +12,11 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ) +# add_executable(lltreeiterators lltreeiterators.cpp) +# +# target_link_libraries(lltreeiterators +# ${LLCOMMON_LIBRARIES}) + set(llcommon_SOURCE_FILES llapp.cpp llapr.cpp @@ -44,6 +50,7 @@ set(llcommon_SOURCE_FILES llprocessor.cpp llqueuedthread.cpp llrand.cpp + llrefcount.cpp llrun.cpp llsd.cpp llsdserialize.cpp @@ -98,6 +105,7 @@ set(llcommon_HEADER_FILES lldefs.h lldepthstack.h lldlinked.h + lldoubledispatch.h lldqueueptr.h llendianswizzle.h llenum.h @@ -119,6 +127,7 @@ set(llcommon_HEADER_FILES llhttpstatuscodes.h llindexedqueue.h llindraconfigfile.h + llinstancetracker.h llkeythrottle.h lllinkedqueue.h llliveappconfig.h @@ -134,20 +143,26 @@ set(llcommon_HEADER_FILES llmetrics.h llmortician.h llnametable.h + llpointer.h llpreprocessor.h llpriqueuemap.h llprocessor.h llptrskiplist.h llptrskipmap.h + llptrto.h llqueuedthread.h llrand.h + llrefcount.h llrun.h + llrefcount.h + llsafehandle.h llsd.h llsdserialize.h llsdserialize_xml.h llsdutil.h llsecondlifeurls.h llsimplehash.h + llsingleton.h llskiplist.h llskipmap.h llstack.h @@ -161,6 +176,7 @@ set(llcommon_HEADER_FILES llsys.h llthread.h lltimer.h + lltreeiterators.h lluri.h lluuid.h lluuidhashmap.h @@ -195,4 +211,6 @@ target_link_libraries( ${APR_LIBRARIES} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} + ${BOOST_PROGRAM_OPTIONS_LIBRARY} + ${BOOST_REGEX_LIBRARY} ) diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h index f95b148590..d369fbc5b3 100644 --- a/indra/llcommon/is_approx_equal_fraction.h +++ b/indra/llcommon/is_approx_equal_fraction.h @@ -7,7 +7,30 @@ * making llcommon depend on llmath. * * $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$ */ diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index f9d5877ab2..9adf24a492 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -33,6 +33,11 @@ #ifndef LL_LINDEN_COMMON_H #define LL_LINDEN_COMMON_H +// *NOTE: Please keep includes here to a minimum! +// +// Files included here are included in every library .cpp file and +// are not precompiled. + #if defined(LL_WINDOWS) && defined(_DEBUG) # if _MSC_VER >= 1400 // Visual C++ 2005 or later # define _CRTDBG_MAP_ALLOC @@ -51,23 +56,22 @@ #include #include #include -#include -#include +#include -// Work Microsoft compiler warnings +// Work around Microsoft compiler warnings in STL headers #ifdef LL_WINDOWS #pragma warning (disable : 4702) // unreachable code #pragma warning (disable : 4244) // conversion from time_t to S32 #endif // LL_WINDOWS -#include #include #include #include #include #ifdef LL_WINDOWS -#pragma warning (3 : 4702) // we like level 3, not 4 +// Reenable warnings we disabled above +#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4 // level 4 warnings that we need to disable: #pragma warning (disable : 4100) // unreferenced formal parameter #pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) @@ -78,6 +82,7 @@ #endif // LL_WINDOWS // Linden only libs in alpha-order other than stdtypes.h +// *NOTE: Please keep includes here to a minimum, see above. #include "stdtypes.h" #include "lldefs.h" #include "llerror.h" @@ -85,8 +90,5 @@ #include "llfasttimer.h" #include "llfile.h" #include "llformat.h" -#include "llstring.h" -#include "llsys.h" -#include "lltimer.h" #endif diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index cf3bf89b4f..fc2ac9dcbc 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -70,6 +70,7 @@ asset_info_t asset_types[] = { LLAssetType::AT_ANIMATION, "ANIMATION" }, { LLAssetType::AT_GESTURE, "GESTURE" }, { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, + { LLAssetType::AT_FAVORITE, "FAVORITE" }, { LLAssetType::AT_NONE, "NONE" }, }; @@ -129,7 +130,8 @@ const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] = "jpeg", "animatn", "gesture", - "simstate" + "simstate", + "favorite" }; // This table is meant for decoding to human readable form. Put any @@ -160,6 +162,7 @@ const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] = "animation", "gesture", "simstate" + "favorite" }; ///---------------------------------------------------------------------------- diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 4077b8d2c1..0ee4ae2821 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -131,6 +131,9 @@ public: // simstate file AT_SIMSTATE = 22, + // favorite items + AT_FAVORITE = 23, + // +*********************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | // +*********************************************+ @@ -140,7 +143,7 @@ public: // | 4. ADD TO LLAssetType::mAssetTypeHumanNames | // +*********************************************+ - AT_COUNT = 23, + AT_COUNT = 24, AT_NONE = -1 }; diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h index 4df9dbf3bd..f4bfc2bfa2 100644 --- a/indra/llcommon/llboost.h +++ b/indra/llcommon/llboost.h @@ -46,4 +46,19 @@ */ typedef boost::tokenizer > boost_tokenizer; +// Useful combiner for boost signals that retturn a vool (e.g. validation) +// returns false if any of the callbacks return false +struct boost_boolean_combiner +{ + typedef bool result_type; + template + bool operator()(InputIterator first, InputIterator last) const + { + bool res = true; + while (first != last) + res &= *first++; + return res; + } +}; + #endif // LL_LLBOOST_H diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 2cbb71855f..36a0018995 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -32,6 +32,8 @@ #include "linden_common.h" #include "llcommon.h" + +#include "llmemory.h" #include "llthread.h" //static diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index 5f77988336..a1808e8a6c 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -32,9 +32,8 @@ #ifndef LL_COMMON_H #define LL_COMMON_H -#include "llmemory.h" +// *TODO: remove these? #include "llapr.h" -// #include "llframecallbackmanager.h" #include "lltimer.h" #include "llfile.h" diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 41a3af398f..7bc9e16bc9 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -38,10 +38,13 @@ #include "apr_time.h" #include +#include +#include #include #include #include "lltimer.h" +#include "llstring.h" static const F64 DATE_EPOCH = 0.0; @@ -88,45 +91,36 @@ std::string LLDate::asString() const // is one of the standards used and the prefered format std::string LLDate::asRFC1123() const { - std::ostringstream stream; - toHTTPDateStream(stream); - return stream.str(); + return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -void LLDate::toHTTPDateStream(std::ostream& s) const +std::string LLDate::toHTTPDateString (std::string fmt) const { - // http://apr.apache.org/docs/apr/0.9/group__apr__time.html - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + std::ostringstream stream; + time_t locSeconds = (time_t) mSecondsSinceEpoch; + struct tm * gmt = gmtime (&locSeconds); - apr_time_exp_t exp_time ; //Apache time module + stream.imbue (std::locale(LLStringUtil::getLocale().c_str())); + toHTTPDateStream (stream, gmt, fmt); + return stream.str(); +} - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) - { - // Return Epoch UTC date - s << "Thursday, 01 Jan 1970 00:00:00 GMT" ; - return; - } +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(); +} - s << std::dec << std::setfill('0'); -#if( LL_WINDOWS || __GNUC__ > 2) - s << std::right ; -#else - s.setf(ios::right); -#endif - std::string day = weekdays[exp_time.tm_wday]; - std::string month = months[exp_time.tm_mon]; - - s << std::setw(day.length()) << (day) - << ", " << std::setw(2) << (exp_time.tm_mday) - << ' ' << std::setw(month.length()) << (month) - << ' ' << std::setw(4) << (exp_time.tm_year + 1900) - << ' ' << std::setw(2) << (exp_time.tm_hour) - << ':' << std::setw(2) << (exp_time.tm_min) - << ':' << std::setw(2) << (exp_time.tm_sec) - << " GMT"; +void LLDate::toHTTPDateStream(std::ostream& s, tm * gmt, std::string fmt) +{ + using namespace std; - // RFC 1123 date does not use microseconds - //llinfos << "Date in RFC 1123 format is " << s << llendl; + const char * pBeg = fmt.c_str(); + const char * pEnd = pBeg + fmt.length(); + const time_put& tp = use_facet >(s.getloc()); + tp.put (s, s, s.fill(), gmt, pBeg, pEnd); } void LLDate::toStream(std::ostream& s) const diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 32825b18dc..29a9030b6d 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -84,7 +84,9 @@ public: std::string asString() const; std::string asRFC1123() const; void toStream(std::ostream&) const; - void toHTTPDateStream(std::ostream&) 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/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h new file mode 100755 index 0000000000..60678d44fb --- /dev/null +++ b/indra/llcommon/lldoubledispatch.h @@ -0,0 +1,332 @@ +/** + * @file lldoubledispatch.h + * @author Nat Goodspeed + * @date 2008-11-11 + * @brief function calls virtual on more than one parameter + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +#if ! defined(LL_LLDOUBLEDISPATCH_H) +#define LL_LLDOUBLEDISPATCH_H + +#include +#include +#include +#include +#include + +/** + * This class supports function calls which are virtual on the dynamic type of + * more than one parameter. Specifically, we address a limited but useful + * subset of that problem: function calls which accept two parameters, and + * select which particular function to call depending on the dynamic type of + * both. + * + * Scott Meyers, in More Effective C++ (Item 31), talks about some of the perils + * and pitfalls lurking down this pathway. He discusses and dismisses the + * straightforward approaches of using single-dispatch virtual functions twice, + * and of using a family of single-dispatch virtual functions which each examine + * RTTI for their other parameter. He advocates using a registry in which you + * look up the actual types of both parameters (he uses the classes' string names, + * via typeid(param).name()) to obtain a pointer to a free (non-member) function + * that will accept this pair of parameters. + * + * He does point out that his approach doesn't handle inheritance. If you have a + * registry entry for SpaceShip, and you have in hand a MilitaryShip (subclass of + * SpaceShip) and an Asteroid, you'd like to call the function appropriate for + * SpaceShips and Asteroids -- but alas, his lookup fails because the class name + * for your MilitaryShip subclass isn't in the registry. + * + * This class extends his idea to build a registry whose entries can examine the + * dynamic type of the parameter in a more flexible way -- using dynamic_cast<> + * -- thereby supporting inheritance relationships. + * + * Of course we must allow for the ambiguity this permits. We choose to use a + * sequence container rather than a map, and require that the client code + * specify the order in which dispatch-table entries should be searched. The + * result resembles the semantics of the catch clauses for a try/catch block: + * you must code catch clauses in decreasing order of specificity, because if + * you catch ErrorBaseClass before you catch ErrorSubclass, then any + * ErrorSubclass exceptions thrown by the protected code will always match + * ErrorBaseClass, and you will never reach your catch(ErrorSubclass) clause. + * + * So, in a similar way, if you have a specific routine to process + * MilitaryShip and Asteroid, you'd better place that in the table @em before + * your more general routine that processes SpaceShip and Asteroid, or else + * the MilitaryShip variant will never be called. + * + * @todo This implementation doesn't attempt to deal with + * const-correctness of arguments. Our container stores templated + * objects into which the specific parameter types have been "frozen." But to + * store all these in the same container, they are all instances of a base + * class with a virtual invocation method. Naturally the base-class virtual + * method definition cannot know the const-ness of the particular + * types with which its template subclass is instantiated. + * + * One is tempted to suggest four different virtual methods, one for each + * combination of @c const and non-const arguments. Then the client + * will select the particular virtual method that best fits the + * const-ness of the arguments in hand. The trouble with that idea is + * that in order to instantiate the subclass instance, we must compile all + * four of its virtual method overrides, which means we must be prepared to + * pass all four combinations of @c const and non-const arguments to + * the registered callable. That only works when the registered callable + * accepts both parameters as @c const. + * + * Of course the virtual method overrides could use @c const_cast to force + * them to compile correctly regardless of the const-ness of the + * registered callable's parameter declarations. But if we're going to force + * the issue with @c const_cast anyway, why bother with the four different + * virtual methods? Why not just require canonical parameter + * const-ness for any callables used with this mechanism? + * + * We therefore require that your callable accept both params as + * non-const. (This is more general than @c const: you can perform @c + * const operations on a non-const parameter, but you can't perform + * non-const operations on a @c const parameter.) + * + * For ease of use, though, our invocation method accepts both params as @c + * const. Again, you can pass a non-const object to a @c const param, + * but not the other way around. We take care of the @c const_cast for you. + */ +// LLDoubleDispatch is a template because we have to assume that all parameter +// types are subclasses of some common base class -- but we don't have to +// impose that base class on client code. Instead, we let IT tell US the +// common parameter base class. +template +class LLDoubleDispatch +{ + typedef LLDoubleDispatch self_type; + +public: + LLDoubleDispatch() {} + + /** + * Call the first matching entry. If there's no registered Functor + * appropriate for this pair of parameter types, this call will do + * @em nothing! (If you want notification in this case, simply add a new + * Functor for (ParamBaseType&, ParamBaseType&) at the end of the table. + * The two base-class entries should match anything that isn't matched by + * any more specific entry.) + * + * See note in class documentation about const-correctness. + */ + inline + ReturnType operator()(const ParamBaseType& param1, const ParamBaseType& param2) const; + + // Borrow a trick from Alexandrescu: use a Type class to "wrap" a type + // for purposes of passing the type itself into a template method. + template + struct Type {}; + + /** + * Add a new Entry for a given @a Functor. As mentioned above, the order + * in which you add these entries is very important. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(const Type& t1, const Type& t2, Functor func, bool symmetrical=false) + { + insert(t1, t2, func); + if (symmetrical) + { + // Use boost::bind() to construct a param-swapping thunk. Don't + // forget to reverse the parameters too. + insert(t2, t1, boost::bind(func, _2, _1)); + } + } + + /** + * Add a new Entry for a given @a Functor, explicitly passing instances of + * the Functor's leaf param types to help us figure out where to insert. + * Because it can use RTTI, this add() method isn't order-sensitive like + * the other one. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(const Type1& prototype1, const Type2& prototype2, Functor func, bool symmetrical=false) + { + // Because we expect our caller to pass leaf param types, we can just + // perform an ordinary search to find the first matching iterator. If + // we find an existing Entry that matches both params, either the + // param types are the same, or the existing Entry uses the base class + // for one or both params, and the new Entry must precede that. Assume + // our client won't register two callables with exactly the SAME set + // of types; in that case we'll insert the new one before any earlier + // ones, meaning the last one registered will "win." Note that if + // find() doesn't find any matching Entry, it will return end(), + // meaning the new Entry will be last, which is fine. + typename DispatchTable::iterator insertion = find(prototype1, prototype2); + insert(Type(), Type(), func, insertion); + if (symmetrical) + { + insert(Type(), Type(), boost::bind(func, _2, _1), insertion); + } + } + + /** + * Add a new Entry for a given @a Functor, specifying the Functor's leaf + * param types as explicit template arguments. This will instantiate + * temporary objects of each of these types, which requires that they have + * a lightweight default constructor. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(Functor func, bool symmetrical=false) + { + // This is a convenience wrapper for the add() variant taking explicit + // instances. + add(Type1(), Type2(), func, symmetrical); + } + +private: + /// This is the base class for each entry in our dispatch table. + struct EntryBase + { + virtual ~EntryBase() {} + virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const = 0; + virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const = 0; + }; + + /// Here's the template subclass that actually creates each entry. + template + class Entry: public EntryBase + { + public: + Entry(Functor func): mFunc(func) {} + /// Is this entry appropriate for these arguments? + virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const + { + return (dynamic_cast(¶m1) && + dynamic_cast(¶m2)); + } + /// invocation + virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const + { + // We perform the downcast so callable can accept leaf param + // types, instead of accepting ParamBaseType and downcasting + // explicitly. + return mFunc(dynamic_cast(param1), dynamic_cast(param2)); + } + private: + /// Bind whatever function or function object the instantiator passed. + Functor mFunc; + }; + + /// shared_ptr manages Entry lifespan for us + typedef boost::shared_ptr EntryPtr; + /// use a @c list to make it easy to insert + typedef std::list DispatchTable; + DispatchTable mDispatch; + + /// Look up the location of the first matching entry. + typename DispatchTable::const_iterator find(const ParamBaseType& param1, const ParamBaseType& param2) const + { + // We assert that it's safe to call the non-const find() method on a + // const LLDoubleDispatch instance. Cast away the const-ness of 'this'. + return const_cast(this)->find(param1, param2); + } + + /// Look up the location of the first matching entry. + typename DispatchTable::iterator find(const ParamBaseType& param1, const ParamBaseType& param2) + { + return std::find_if(mDispatch.begin(), mDispatch.end(), + boost::bind(&EntryBase::matches, _1, + boost::ref(param1), boost::ref(param2))); + } + + /// Look up the first matching entry. + EntryPtr lookup(const ParamBaseType& param1, const ParamBaseType& param2) const + { + typename DispatchTable::const_iterator found = find(param1, param2); + if (found != mDispatch.end()) + { + // Dereferencing the list iterator gets us an EntryPtr + return *found; + } + // not found + return EntryPtr(); + } + + // Break out the actual insert operation so the public add() template + // function can avoid calling itself recursively. See add() comments. + template + void insert(const Type& param1, const Type& param2, Functor func) + { + insert(param1, param2, func, mDispatch.end()); + } + + // Break out the actual insert operation so the public add() template + // function can avoid calling itself recursively. See add() comments. + template + void insert(const Type&, const Type&, Functor func, + typename DispatchTable::iterator where) + { + mDispatch.insert(where, EntryPtr(new Entry(func))); + } + + /// Don't implement the copy ctor. Everyone will be happier if the + /// LLDoubleDispatch object isn't copied. + LLDoubleDispatch(const LLDoubleDispatch& src); +}; + +template +ReturnType LLDoubleDispatch::operator()(const ParamBaseType& param1, + const ParamBaseType& param2) const +{ + EntryPtr found = lookup(param1, param2); + if (found.get() == 0) + return ReturnType(); // bogus return value + + // otherwise, call the Functor we found + return (*found)(const_cast(param1), const_cast(param2)); +} + +#endif /* ! defined(LL_LLDOUBLEDISPATCH_H) */ diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index 4c779c58c8..f0e46ae78d 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llerrorthread.h" + #include "llapp.h" +#include "lltimer.h" // ms_sleep() LLErrorThread::LLErrorThread() : LLThread("Error"), diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h index 60887a060a..2b8f276df1 100644 --- a/indra/llcommon/llevent.h +++ b/indra/llcommon/llevent.h @@ -35,7 +35,7 @@ #define LL_EVENT_H #include "llsd.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLEventListener; diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h new file mode 100644 index 0000000000..11f4063a1d --- /dev/null +++ b/indra/llcommon/llinstancetracker.h @@ -0,0 +1,100 @@ +/** + * @file llinstancetracker.h + * @brief LLInstanceTracker is a mixin class that automatically tracks object + * instances with or without an associated key + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINSTANCETRACKER_H +#define LL_LLINSTANCETRACKER_H + +#include + +#include "string_table.h" +#include + +// This mix-in class adds support for tracking all instances of the specificed class parameter T +// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +// If KEY is not provided, then instances are stored in a simple list +template +class LLInstanceTracker : boost::noncopyable +{ +public: + typedef typename std::map::iterator instance_iter; + typedef typename std::map::const_iterator instance_const_iter; + + static T* getInstance(const KEY& k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; } + + static instance_iter beginInstances() { return sInstances.begin(); } + static instance_iter endInstances() { return sInstances.end(); } + static S32 instanceCount() { return sInstances.size(); } +protected: + LLInstanceTracker(KEY key) { add(key); } + virtual ~LLInstanceTracker() { remove(); } + virtual void setKey(KEY key) { remove(); add(key); } + virtual const KEY& getKey() const { return mKey; } + +private: + void add(KEY key) + { + mKey = key; + sInstances[key] = static_cast(this); + } + void remove() { sInstances.erase(mKey); } + +private: + + KEY mKey; + static std::map sInstances; +}; + +template +class LLInstanceTracker +{ +public: + typedef typename std::set::iterator instance_iter; + typedef typename std::set::const_iterator instance_const_iter; + + static instance_iter instancesBegin() { return sInstances.begin(); } + static instance_iter instancesEnd() { return sInstances.end(); } + static S32 instanceCount() { return sInstances.size(); } + +protected: + LLInstanceTracker() { sInstances.insert(static_cast(this)); } + virtual ~LLInstanceTracker() { sInstances.erase(static_cast(this)); } + + LLInstanceTracker(const LLInstanceTracker& other) { sInstances.insert(static_cast(this)); } + + static std::set sInstances; +}; + +template std::map LLInstanceTracker::sInstances; +template std::set LLInstanceTracker::sInstances; + +#endif diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 14b4f9f4b0..da9cb94e13 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -83,6 +83,7 @@ documentation and/or software. #include "llmd5.h" #include +#include // cerr // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index a6de3d2d69..5d54cfcade 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -275,27 +275,12 @@ void operator delete[] (void *p) } #endif - -//---------------------------------------------------------------------------- - -LLRefCount::LLRefCount() : - mRef(0) -{ -} - -LLRefCount::~LLRefCount() -{ - if (mRef != 0) - { - llerrs << "deleting non-zero reference" << llendl; - } -} //---------------------------------------------------------------------------- #if defined(LL_WINDOWS) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { HANDLE self = GetCurrentProcess(); PROCESS_MEMORY_COUNTERS counters; @@ -333,7 +318,7 @@ U64 getCurrentRSS() // } // } -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { U64 residentSize = 0; task_basic_info_data_t basicInfo; @@ -357,7 +342,7 @@ U64 getCurrentRSS() #elif defined(LL_LINUX) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { static const char statPath[] = "/proc/self/stat"; LLFILE *fp = LLFile::fopen(statPath, "r"); @@ -396,7 +381,7 @@ bail: #define _STRUCTURED_PROC 1 #include -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { char path [LL_MAX_PATH]; /* Flawfinder: ignore */ @@ -419,7 +404,7 @@ U64 getCurrentRSS() } #else -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { return 0; } diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index b5c0711484..a72e58034b 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -29,444 +29,34 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ -#ifndef LL_MEMORY_H -#define LL_MEMORY_H +#ifndef LLMEMORY_H +#define LLMEMORY_H -#include -#include -#include "llerror.h" extern S32 gTotalDAlloc; extern S32 gTotalDAUse; extern S32 gDACount; -const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA; - -//---------------------------------------------------------------------------- - class LLMemory { public: static void initClass(); static void cleanupClass(); static void freeReserve(); + // Return the resident set size of the current process, in bytes. + // Return value is zero if not known. + static U64 getCurrentRSS(); private: static char* reserveMem; }; -//---------------------------------------------------------------------------- -// RefCount objects should generally only be accessed by way of LLPointer<>'s -// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE -// if LLFoo::LLFoo() does anything like put itself in an update queue. -// The queue may get accessed before it gets assigned to x. -// The correct implementation is: -// LLPointer x = new LLFoo; // constructor does not do anything interesting -// x->instantiate(); // does stuff like place x into an update queue - -// see llthread.h for LLThreadSafeRefCount - -//---------------------------------------------------------------------------- - -class LLRefCount -{ -protected: - LLRefCount(const LLRefCount&); // not implemented -private: - LLRefCount&operator=(const LLRefCount&); // not implemented - -protected: - virtual ~LLRefCount(); // use unref() - -public: - LLRefCount(); - - void ref() - { - mRef++; - } - - S32 unref() - { - llassert(mRef >= 1); - if (0 == --mRef) - { - delete this; - return 0; - } - return mRef; - } - - S32 getNumRefs() const - { - return mRef; - } - -private: - S32 mRef; -}; - -//---------------------------------------------------------------------------- - -// Note: relies on Type having ref() and unref() methods -template class LLPointer -{ -public: - - LLPointer() : - mPointer(NULL) - { - } - - LLPointer(Type* ptr) : - mPointer(ptr) - { - ref(); - } - - LLPointer(const LLPointer& ptr) : - mPointer(ptr.mPointer) - { - ref(); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer(const LLPointer& ptr) : - mPointer(ptr.get()) - { - ref(); - } - - ~LLPointer() - { - unref(); - } - - Type* get() const { return mPointer; } - const Type* operator->() const { return mPointer; } - Type* operator->() { return mPointer; } - const Type& operator*() const { return *mPointer; } - Type& operator*() { return *mPointer; } - - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } - bool operator!() const { return (mPointer == NULL); } - bool isNull() const { return (mPointer == NULL); } - bool notNull() const { return (mPointer != NULL); } - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } - - LLPointer& operator =(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - - return *this; - } - - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } - return *this; - } - - // Just exchange the pointers, which will not change the reference counts. - static void swap(LLPointer& a, LLPointer& b) - { - Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; - } - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - -protected: - Type* mPointer; -}; - -//template -//class LLPointerTraits -//{ -// static Type* null(); -//}; -// -// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. -// This is useful in instances where operations on NULL pointers are semantically safe and/or -// when error checking occurs at a different granularity or in a different part of the code -// than when referencing an object via a LLSafeHandle. -// +// LLRefCount moved to llrefcount.h -template -class LLSafeHandle -{ -public: - LLSafeHandle() : - mPointer(NULL) - { - } - - LLSafeHandle(Type* ptr) : - mPointer(NULL) - { - assign(ptr); - } - - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.mPointer); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.get()); - } - - ~LLSafeHandle() - { - unref(); - } - - const Type* operator->() const { return nonNull(mPointer); } - Type* operator->() { return nonNull(mPointer); } - - Type* get() const { return mPointer; } - // we disallow these operations as they expose our null objects to direct manipulation - // and bypass the reference counting semantics - //const Type& operator*() const { return *nonNull(mPointer); } - //Type& operator*() { return *nonNull(mPointer); } - - operator BOOL() const { return mPointer != NULL; } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool isNull() const { return mPointer == NULL; } - bool notNull() const { return mPointer != NULL; } - - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } - - LLSafeHandle& operator =(Type* ptr) - { - assign(ptr); - return *this; - } - - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.mPointer); - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.get()); - return *this; - } - -public: - typedef Type* (*NullFunc)(); - static const NullFunc sNullFunc; - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - - void assign(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - } - - static Type* nonNull(Type* ptr) - { - return ptr == NULL ? sNullFunc() : ptr; - } - -protected: - Type* mPointer; -}; - -// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL -// NOT a smart pointer like LLPointer<> -// Useful for example in std::map > -// (std::map uses the default constructor for creating new entries) -template class LLInitializedPointer -{ -public: - LLInitializedPointer() : mPointer(NULL) {} - ~LLInitializedPointer() { delete mPointer; } - - const T* operator->() const { return mPointer; } - T* operator->() { return mPointer; } - const T& operator*() const { return *mPointer; } - T& operator*() { return *mPointer; } - operator const T*() const { return mPointer; } - operator T*() { return mPointer; } - T* operator=(T* x) { return (mPointer = x); } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool operator==(T* rhs) { return mPointer == rhs; } - bool operator==(const LLInitializedPointer* rhs) { return mPointer == rhs.mPointer; } - -protected: - T* mPointer; -}; - -//---------------------------------------------------------------------------- - -// LLSingleton implements the getInstance() method part of the Singleton -// pattern. It can't make the derived class constructors protected, though, so -// you have to do that yourself. -// -// There are two ways to use LLSingleton. The first way is to inherit from it -// while using the typename that you'd like to be static as the template -// parameter, like so: -// -// class Foo: public LLSingleton{}; -// -// Foo& instance = Foo::instance(); -// -// The second way is to use the singleton class directly, without inheritance: -// -// typedef LLSingleton FooSingleton; -// -// Foo& instance = FooSingleton::instance(); -// -// In this case, the class being managed as a singleton needs to provide an -// initSingleton() method since the LLSingleton virtual method won't be -// available -// -// As currently written, it is not thread-safe. -template -class LLSingleton -{ -public: - virtual ~LLSingleton() {} -#ifdef LL_MSVC7 -// workaround for VC7 compiler bug -// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx -// our version doesn't introduce a nested struct so that you can still declare LLSingleton -// a friend and hide your constructor - static T* getInstance() - { - LLSingleton singleton; - return singleton.vsHack(); - } - - T* vsHack() -#else - static T* getInstance() -#endif - { - static T instance; - static bool needs_init = true; - if (needs_init) - { - needs_init = false; - instance.initSingleton(); - } - return &instance; - } - - static T& instance() - { - return *getInstance(); - } - -private: - virtual void initSingleton() {} -}; +// LLPointer moved to llpointer.h -//---------------------------------------------------------------------------- +// LLSafeHandle moved to llsafehandle.h -// Return the resident set size of the current process, in bytes. -// Return value is zero if not known. -U64 getCurrentRSS(); +// LLSingleton moved to llsingleton.h #endif diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index a9ebc2062f..b7cef4de4a 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -41,7 +41,10 @@ class LLMemType; extern void* ll_allocate (size_t size); extern void ll_release (void *p); -#define MEM_TRACK_MEM 0 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// WARNING: Never commit with MEM_TRACK_MEM == 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#define MEM_TRACK_MEM (0 && LL_WINDOWS) #define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM) #if MEM_TRACK_TYPE diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h new file mode 100644 index 0000000000..2c37eadcc6 --- /dev/null +++ b/indra/llcommon/llpointer.h @@ -0,0 +1,177 @@ +/** + * @file llpointer.h + * @brief A reference-counted pointer for objects derived from LLRefCount + * + * $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 LLPOINTER_H +#define LLPOINTER_H + +#include "llerror.h" // *TODO: consider eliminating this + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE +// if LLFoo::LLFoo() does anything like put itself in an update queue. +// The queue may get accessed before it gets assigned to x. +// The correct implementation is: +// LLPointer x = new LLFoo; // constructor does not do anything interesting +// x->instantiate(); // does stuff like place x into an update queue + +// see llthread.h for LLThreadSafeRefCount + +//---------------------------------------------------------------------------- + +// Note: relies on Type having ref() and unref() methods +template class LLPointer +{ +public: + + LLPointer() : + mPointer(NULL) + { + } + + LLPointer(Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLPointer(const LLPointer& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer(const LLPointer& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLPointer() + { + unref(); + } + + Type* get() const { return mPointer; } + const Type* operator->() const { return mPointer; } + Type* operator->() { return mPointer; } + const Type& operator*() const { return *mPointer; } + Type& operator*() { return *mPointer; } + + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } + bool operator!() const { return (mPointer == NULL); } + bool isNull() const { return (mPointer == NULL); } + bool notNull() const { return (mPointer != NULL); } + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } + + LLPointer& operator =(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + + return *this; + } + + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.get() ) + { + unref(); + mPointer = ptr.get(); + ref(); + } + return *this; + } + + // Just exchange the pointers, which will not change the reference counts. + static void swap(LLPointer& a, LLPointer& b) + { + Type* temp = a.mPointer; + a.mPointer = b.mPointer; + b.mPointer = temp; + } + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llptrto.cpp b/indra/llcommon/llptrto.cpp new file mode 100644 index 0000000000..ce93f09489 --- /dev/null +++ b/indra/llcommon/llptrto.cpp @@ -0,0 +1,108 @@ +/** + * @file llptrto.cpp + * @author Nat Goodspeed + * @date 2008-08-20 + * @brief Test for llptrto.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llptrto.h" +// STL headers +// std headers +// external library headers +#include +#include +// other Linden headers +#include "llmemory.h" + +// a refcounted class +class RCFoo: public LLRefCount +{ +public: + RCFoo() {} +}; + +// a refcounted subclass +class RCSubFoo: public RCFoo +{ +public: + RCSubFoo() {} +}; + +// a refcounted class using the other refcount base class +class TSRCFoo: public LLThreadSafeRefCount +{ +public: + TSRCFoo() {} +}; + +// a non-refcounted class +class Bar +{ +public: + Bar() {} +}; + +// a non-refcounted subclass +class SubBar: public Bar +{ +public: + SubBar() {} +}; + +int main(int argc, char *argv[]) +{ + // test LLPtrTo<> + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, Bar*>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, SubBar*>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, int*>::value)); + + // Test LLRemovePointer<>. Note that we remove both pointer variants from + // each kind of type, regardless of whether the variant makes sense. + BOOST_STATIC_ASSERT((boost::is_same::type, RCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, RCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, RCSubFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, RCSubFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, TSRCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, TSRCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, Bar>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, Bar>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, SubBar>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, SubBar>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, int>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, int>::value)); + + return 0; +} diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h new file mode 100644 index 0000000000..74c117a7f6 --- /dev/null +++ b/indra/llcommon/llptrto.h @@ -0,0 +1,93 @@ +/** + * @file llptrto.h + * @author Nat Goodspeed + * @date 2008-08-19 + * @brief LLPtrTo is a template helper to pick either TARGET* or -- when + * TARGET is a subclass of LLRefCount or LLThreadSafeRefCount -- + * LLPointer. LLPtrTo<> chooses whichever pointer type is best. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +#if ! defined(LL_LLPTRTO_H) +#define LL_LLPTRTO_H + +#include "llpointer.h" +#include "llrefcount.h" // LLRefCount +#include "llthread.h" // LLThreadSafeRefCount +#include +#include +#include + +/** + * LLPtrTo::type is either of two things: + * + * * When TARGET is a subclass of either LLRefCount or LLThreadSafeRefCount, + * LLPtrTo::type is LLPointer. + * * Otherwise, LLPtrTo::type is TARGET*. + * + * This way, a class template can use LLPtrTo::type to select an + * appropriate pointer type to store. + */ +template +struct LLPtrTo +{ + typedef T* type; +}; + +/// specialize for subclasses of LLRefCount +template +struct LLPtrTo >::type> +{ + typedef LLPointer type; +}; + +/// specialize for subclasses of LLThreadSafeRefCount +template +struct LLPtrTo >::type> +{ + typedef LLPointer type; +}; + +/** + * LLRemovePointer::type gets you the underlying (pointee) type. + */ +template +struct LLRemovePointer +{ + typedef typename boost::remove_pointer::type type; +}; + +/// specialize for LLPointer +template +struct LLRemovePointer< LLPointer > +{ + typedef SOMECLASS type; +}; + +#endif /* ! defined(LL_LLPTRTO_H) */ diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index cd53e701d2..3db5c36545 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llqueuedthread.h" + #include "llstl.h" +#include "lltimer.h" // ms_sleep() //============================================================================ diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp new file mode 100644 index 0000000000..33b6875fb0 --- /dev/null +++ b/indra/llcommon/llrefcount.cpp @@ -0,0 +1,49 @@ +/** + * @file llrefcount.cpp + * @brief Base class for reference counted objects for use with LLPointer + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llrefcount.h" + +#include "llerror.h" + +LLRefCount::LLRefCount() : + mRef(0) +{ +} + +LLRefCount::~LLRefCount() +{ + if (mRef != 0) + { + llerrs << "deleting non-zero reference" << llendl; + } +} diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h new file mode 100644 index 0000000000..540a18b8a0 --- /dev/null +++ b/indra/llcommon/llrefcount.h @@ -0,0 +1,78 @@ +/** + * @file llrefcount.h + * @brief Base class for reference counted objects for use with LLPointer + * + * $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 LLREFCOUNT_H +#define LLREFCOUNT_H + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// see llthread.h for LLThreadSafeRefCount +//---------------------------------------------------------------------------- + +class LLRefCount +{ +protected: + LLRefCount(const LLRefCount&); // not implemented +private: + LLRefCount&operator=(const LLRefCount&); // not implemented + +protected: + virtual ~LLRefCount(); // use unref() + +public: + LLRefCount(); + + void ref() + { + mRef++; + } + + S32 unref() + { + llassert(mRef >= 1); + if (0 == --mRef) + { + delete this; + return 0; + } + return mRef; + } + + S32 getNumRefs() const + { + return mRef; + } + +private: + S32 mRef; +}; + +#endif diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h new file mode 100644 index 0000000000..1f7c682fd1 --- /dev/null +++ b/indra/llcommon/llsafehandle.h @@ -0,0 +1,167 @@ +/** + * @file llsafehandle.h + * @brief Reference-counted object where Object() is valid, not NULL. + * + * $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 LLSAFEHANDLE_H +#define LLSAFEHANDLE_H + +#include "llerror.h" // *TODO: consider eliminating this + +// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. +// This is useful in instances where operations on NULL pointers are semantically safe and/or +// when error checking occurs at a different granularity or in a different part of the code +// than when referencing an object via a LLSafeHandle. + +template +class LLSafeHandle +{ +public: + LLSafeHandle() : + mPointer(NULL) + { + } + + LLSafeHandle(Type* ptr) : + mPointer(NULL) + { + assign(ptr); + } + + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.mPointer); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.get()); + } + + ~LLSafeHandle() + { + unref(); + } + + const Type* operator->() const { return nonNull(mPointer); } + Type* operator->() { return nonNull(mPointer); } + + Type* get() const { return mPointer; } + // we disallow these operations as they expose our null objects to direct manipulation + // and bypass the reference counting semantics + //const Type& operator*() const { return *nonNull(mPointer); } + //Type& operator*() { return *nonNull(mPointer); } + + operator BOOL() const { return mPointer != NULL; } + operator bool() const { return mPointer != NULL; } + bool operator!() const { return mPointer == NULL; } + bool isNull() const { return mPointer == NULL; } + bool notNull() const { return mPointer != NULL; } + + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } + + LLSafeHandle& operator =(Type* ptr) + { + assign(ptr); + return *this; + } + + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.mPointer); + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.get()); + return *this; + } + +public: + typedef Type* (*NullFunc)(); + static const NullFunc sNullFunc; + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + + void assign(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + } + + static Type* nonNull(Type* ptr) + { + return ptr == NULL ? sNullFunc() : ptr; + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 7a66d70d3f..cf337be161 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,7 +34,7 @@ #include "linden_common.h" #include "llsdserialize.h" -#include "llmemory.h" +#include "llpointer.h" #include "llstreamtools.h" // for fullread #include diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index bb38b75d8f..7463d1e5dd 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -36,8 +36,9 @@ #define LL_LLSDSERIALIZE_H #include +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" -#include "llmemory.h" /** * @class LLSDParser diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index aa0e0f3696..0202a033c3 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -171,6 +171,15 @@ char* ll_print_sd(const LLSD& sd) return buffer; } +char* ll_pretty_print_sd_ptr(const LLSD* sd) +{ + if (sd) + { + return ll_pretty_print_sd(*sd); + } + return NULL; +} + char* ll_pretty_print_sd(const LLSD& sd) { const U32 bufferSize = 10 * 1024; diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index b67ad521ea..501600f1d9 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -89,6 +89,7 @@ LLSD ll_binary_from_string(const LLSD& sd); char* ll_print_sd(const LLSD& sd); // Serializes sd to static buffer and returns pointer, using "pretty printing" mode. +char* ll_pretty_print_sd_ptr(const LLSD* sd); char* ll_pretty_print_sd(const LLSD& sd); //compares the structure of an LLSD to a template LLSD and stores the diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp index 36d8e8870f..6323d9d36b 100644 --- a/indra/llcommon/llsecondlifeurls.cpp +++ b/indra/llcommon/llsecondlifeurls.cpp @@ -32,57 +32,59 @@ #include "linden_common.h" #include "llsecondlifeurls.h" - +/* const std::string CREATE_ACCOUNT_URL ( "http://secondlife.com/registration/"); const std::string MANAGE_ACCOUNT ( - "http://secondlife.com/account/"); + "http://secondlife.com/account/"); // *TODO: NOT USED const std::string AUCTION_URL ( "http://secondlife.com/auctions/auction-detail.php?id="); const std::string EVENTS_URL ( "http://secondlife.com/events/"); - +*/ const std::string TIER_UP_URL ( - "http://secondlife.com/app/landtier"); + "http://secondlife.com/app/landtier"); // *TODO: Translate (simulator) +const std::string DIRECTX_9_URL ( + "http://secondlife.com/support/"); // *TODO: NOT USED +/* const std::string LAND_URL ( - "http://secondlife.com/app/landtier"); + "http://secondlife.com/app/landtier"); // *TODO: NOT USED const std::string UPGRADE_TO_PREMIUM_URL ( - "http://secondlife.com/app/upgrade/"); - -const std::string DIRECTX_9_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/app/upgrade/"); // *TODO: NOT USED const std::string AMD_AGP_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string VIA_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string SUPPORT_URL ( "http://secondlife.com/support/"); const std::string INTEL_CHIPSET_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string SIS_CHIPSET_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string BLOGS_URL ( - "http://blog.secondlife.com/"); + "http://blog.secondlife.com/"); // *TODO: NOT USED const std::string BUY_CURRENCY_URL ( "http://secondlife.com/app/currency/"); const std::string LSL_DOC_URL ( - "http://secondlife.com/app/lsldoc/"); + "http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED const std::string SL_KB_URL ( - "http://secondlife.com/knowledgebase/"); + "http://secondlife.com/knowledgebase/"); // *TODO: NOT USED const std::string RELEASE_NOTES_BASE_URL ( "http://secondlife.com/app/releasenotes/"); +*/ + diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h index 9fd75c363b..a2e5f0b9c6 100644 --- a/indra/llcommon/llsecondlifeurls.h +++ b/indra/llcommon/llsecondlifeurls.h @@ -32,7 +32,7 @@ #ifndef LL_LLSECONDLIFEURLS_H #define LL_LLSECONDLIFEURLS_H - +/* // Account registration web page extern const std::string CREATE_ACCOUNT_URL; @@ -42,18 +42,21 @@ extern const std::string MANAGE_ACCOUNT; extern const std::string AUCTION_URL; extern const std::string EVENTS_URL; - +*/ // Tier up to a new land level. extern const std::string TIER_UP_URL; + // Tier up to a new land level. extern const std::string LAND_URL; +// How to get DirectX 9 +extern const std::string DIRECTX_9_URL; + +/* // Upgrade from basic membership to premium membership extern const std::string UPGRADE_TO_PREMIUM_URL; -// How to get DirectX 9 -extern const std::string DIRECTX_9_URL; // Out of date VIA chipset extern const std::string VIA_URL; @@ -75,5 +78,5 @@ extern const std::string SL_KB_URL; // Release Notes Redirect URL for Server and Viewer extern const std::string RELEASE_NOTES_BASE_URL; - +*/ #endif diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h new file mode 100644 index 0000000000..dc1457e4f7 --- /dev/null +++ b/indra/llcommon/llsingleton.h @@ -0,0 +1,158 @@ +/** + * @file llsingleton.h + * + * $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 LLSINGLETON_H +#define LLSINGLETON_H + +#include "llerror.h" // *TODO: eliminate this + +#include + +// LLSingleton implements the getInstance() method part of the Singleton +// pattern. It can't make the derived class constructors protected, though, so +// you have to do that yourself. +// +// There are two ways to use LLSingleton. The first way is to inherit from it +// while using the typename that you'd like to be static as the template +// parameter, like so: +// +// class Foo: public LLSingleton{}; +// +// Foo& instance = Foo::instance(); +// +// The second way is to use the singleton class directly, without inheritance: +// +// typedef LLSingleton FooSingleton; +// +// Foo& instance = FooSingleton::instance(); +// +// In this case, the class being managed as a singleton needs to provide an +// initSingleton() method since the LLSingleton virtual method won't be +// available +// +// As currently written, it is not thread-safe. + +template +class LLSingleton : private boost::noncopyable +{ + +private: + typedef enum e_init_state + { + UNINITIALIZED, + CONSTRUCTING, + INITIALIZING, + INITIALIZED, + DELETED + } EInitState; + + static void deleteSingleton() + { + delete getData().mSingletonInstance; + getData().mSingletonInstance = NULL; + } + + // stores pointer to singleton instance + // and tracks initialization state of singleton + struct SingletonInstanceData + { + EInitState mInitState; + DERIVED_TYPE* mSingletonInstance; + + SingletonInstanceData() + : mSingletonInstance(NULL), + mInitState(UNINITIALIZED) + {} + + ~SingletonInstanceData() + { + deleteSingleton(); + } + }; + +public: + virtual ~LLSingleton() + { + SingletonInstanceData& data = getData(); + data.mSingletonInstance = NULL; + data.mInitState = DELETED; + } + + static SingletonInstanceData& getData() + { + static SingletonInstanceData data; + return data; + } + + static DERIVED_TYPE* getInstance() + { + SingletonInstanceData& data = getData(); + + if (data.mInitState == CONSTRUCTING) + { + llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; + } + + if (data.mInitState == DELETED) + { + llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; + } + + if (!data.mSingletonInstance) + { + data.mInitState = CONSTRUCTING; + data.mSingletonInstance = new DERIVED_TYPE(); + data.mInitState = INITIALIZING; + data.mSingletonInstance->initSingleton(); + data.mInitState = INITIALIZED; + } + + return data.mSingletonInstance; + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton already been deleted? + // Use this to avoid accessing singletons from a static object's destructor + static bool destroyed() + { + return getData().mInitState == DELETED; + } + +private: + virtual void initSingleton() {} +}; + +#endif diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index e411a1c798..eab1241b5c 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -46,6 +46,7 @@ BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information 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; //------------------------------------------------------------------------ // Live config file to trigger stats logging @@ -724,28 +725,48 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, LLTimer LLStat::sTimer; LLFrameTimer LLStat::sFrameTimer; -LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) +void LLStat::init() { - llassert(num_bins > 0); - U32 i; - mUseFrameTimer = use_frame_timer; + llassert(mNumBins > 0); mNumValues = 0; mLastValue = 0.f; mLastTime = 0.f; - mNumBins = num_bins; mCurBin = (mNumBins-1); mNextBin = 0; mBins = new F32[mNumBins]; mBeginTime = new F64[mNumBins]; mTime = new F64[mNumBins]; mDT = new F32[mNumBins]; - for (i = 0; i < mNumBins; i++) + for (U32 i = 0; i < mNumBins; i++) { mBins[i] = 0.f; mBeginTime[i] = 0.0; mTime[i] = 0.0; mDT[i] = 0.f; } + + if (!mName.empty()) + { + stat_map_t::iterator iter = sStatList.find(mName); + if (iter != sStatList.end()) + llwarns << "LLStat with duplicate name: " << mName << llendl; + sStatList.insert(std::make_pair(mName, this)); + } +} + +LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins) +{ + init(); +} + +LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins), + mName(name) +{ + init(); } LLStat::~LLStat() @@ -754,6 +775,15 @@ LLStat::~LLStat() delete[] mBeginTime; delete[] mTime; delete[] mDT; + + if (!mName.empty()) + { + // handle multiple entries with the same name + stat_map_t::iterator iter = sStatList.find(mName); + while (iter != sStatList.end() && iter->second != this) + ++iter; + sStatList.erase(iter); + } } void LLStat::reset() diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 61aaac45bf..bad18f46a0 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -258,8 +258,15 @@ private: // ---------------------------------------------------------------------------- class LLStat { +private: + typedef std::multimap stat_map_t; + static stat_map_t sStatList; + + void init(); + public: - LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); ~LLStat(); void reset(); @@ -322,8 +329,22 @@ private: F32 *mDT; S32 mCurBin; S32 mNextBin; + + std::string mName; + static LLTimer sTimer; static LLFrameTimer sFrameTimer; + +public: + static LLStat* getStat(const std::string& name) + { + // return the first stat that matches 'name' + stat_map_t::iterator iter = sStatList.find(name); + if (iter != sStatList.end()) + return iter->second; + else + return NULL; + } }; - + #endif // LL_STAT_ diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 1f653c159c..ec1718a8cb 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -71,6 +71,24 @@ U8 hex_as_nybble(char hex) return 0; // uh - oh, not hex any more... } +bool iswindividual(llwchar elem) +{ + U32 cur_char = (U32)elem; + bool result = false; + if (0x2E80<= cur_char && cur_char <= 0x9FFF) + { + result = true; + } + else if (0xAC00<= cur_char && cur_char <= 0xD7A0 ) + { + result = true; + } + else if (0xF900<= cur_char && cur_char <= 0xFA60 ) + { + result = true; + } + return result; +} bool _read_file_into_string(std::string& str, const std::string& filename) { @@ -650,6 +668,11 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } #endif // LL_WINDOWS +long LLStringOps::sltOffset; +long LLStringOps::localTimeOffset; +bool LLStringOps::daylightSavings; +std::map LLStringOps::datetimeToCodes; + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -661,6 +684,59 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b) #endif } +void LLStringOps::setupDatetimeInfo (bool daylight) +{ + time_t nowT, localT, gmtT; + struct tm * tmpT; + + nowT = time (NULL); + + tmpT = localtime (&nowT); + localT = mktime (tmpT); + + tmpT = gmtime (&nowT); + gmtT = mktime (tmpT); + + localTimeOffset = (long) (gmtT - localT); + + + daylightSavings = daylight; + sltOffset = (daylightSavings? 7 : 8 ) * 60 * 60; + + datetimeToCodes["wkday"] = "%a"; // Thu + datetimeToCodes["weekday"] = "%A"; // Thursday + datetimeToCodes["year4"] = "%Y"; // 2009 + datetimeToCodes["year"] = "%Y"; // 2009 + datetimeToCodes["year2"] = "%y"; // 09 + datetimeToCodes["mth"] = "%b"; // Aug + datetimeToCodes["month"] = "%B"; // August + datetimeToCodes["mthnum"] = "%m"; // 08 + datetimeToCodes["day"] = "%d"; // 31 + datetimeToCodes["hour24"] = "%H"; // 14 + datetimeToCodes["hour"] = "%H"; // 14 + datetimeToCodes["hour12"] = "%I"; // 02 + datetimeToCodes["min"] = "%M"; // 59 + datetimeToCodes["ampm"] = "%p"; // AM + datetimeToCodes["second"] = "%S"; // 59 + datetimeToCodes["timezone"] = "%Z"; // PST +} + +std::string LLStringOps::getDatetimeCode (std::string key) +{ + std::map::iterator iter; + + iter = datetimeToCodes.find (key); + if (iter != datetimeToCodes.end()) + { + return iter->second; + } + else + { + return std::string(""); + } +} + + namespace LLStringFn { // NOTE - this restricts output to ascii diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 99a9b9e269..1aba001353 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -34,6 +34,10 @@ #define LL_LLSTRING_H #include +#include +#include +#include +#include "llsd.h" #if LL_LINUX || LL_SOLARIS #include @@ -145,6 +149,12 @@ struct char_traits class LLStringOps { +private: + static long sltOffset; + static long localTimeOffset; + static bool daylightSavings; + static std::map datetimeToCodes; + public: static char toUpper(char elem) { return toupper((unsigned char)elem); } static llwchar toUpper(llwchar elem) { return towupper(elem); } @@ -172,6 +182,12 @@ public: static S32 collate(const char* a, const char* b) { return strcoll(a, b); } static S32 collate(const llwchar* a, const llwchar* b); + + static void setupDatetimeInfo (bool daylight); + static long getSltOffset (void) {return sltOffset;} + static long getLocalTimeOffset (void) {return localTimeOffset;} + static bool getDaylightSavings (void) {return daylightSavings;} + static std::string getDatetimeCode (std::string key); }; /** @@ -201,6 +217,9 @@ private: template class LLStringUtilBase { +private: + static std::string sLocale; + public: typedef typename std::basic_string::size_type size_type; @@ -211,7 +230,14 @@ public: static std::basic_string null; typedef std::map format_map_t; + static void getTokens (std::basic_string input, std::vector >& tokens); + static void formatNumber(std::basic_string& numStr, std::basic_string decimals); + static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, const LLSD& substitutions); + static S32 format(std::basic_string& s, const LLSD& substitutions); static S32 format(std::basic_string& s, const format_map_t& fmt_map); + static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + static void setLocale (std::string inLocale) {sLocale = inLocale;}; + static std::string getLocale (void) {return sLocale;}; static bool isValidIndex(const std::basic_string& string, size_type i) { @@ -299,6 +325,7 @@ public: }; template std::basic_string LLStringUtilBase::null; +template std::string LLStringUtilBase::sLocale; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; @@ -360,6 +387,7 @@ U8 hex_as_nybble(char hex); * @return Returns true on success. If false, str is unmodified. */ bool _read_file_into_string(std::string& str, const std::string& filename); +bool iswindividual(llwchar elem); /** * Unicode support @@ -546,63 +574,214 @@ namespace LLStringFn //////////////////////////////////////////////////////////// -// LLStringBase::format() -// -// This function takes a string 's' and a map 'fmt_map' of strings-to-strings. -// All occurances of strings in 's' from the left-hand side of 'fmt_map' are -// then replaced with the corresponding right-hand side of 'fmt_map', non- -// recursively. The function returns the number of substitutions made. +//static +template +void LLStringUtilBase::getTokens (std::basic_string input, std::vector >& tokens) +{ + const std::basic_string delims (","); + std::basic_string currToken; + size_type begIdx, endIdx; + + begIdx = input.find_first_not_of (delims); + while (begIdx != std::basic_string::npos) + { + endIdx = input.find_first_of (delims, begIdx); + if (endIdx == std::basic_string::npos) + { + endIdx = input.length(); + } + + currToken = input.substr(begIdx, endIdx - begIdx); + trim (currToken); + tokens.push_back(currToken); + begIdx = input.find_first_not_of (delims, endIdx); + } +} // static template S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& fmt_map) { - typedef typename std::basic_string::size_type string_size_type_t; - string_size_type_t scanstart = 0; + LLSD llsdMap; + + for (format_map_t::const_iterator iter = fmt_map.begin(); + iter != fmt_map.end(); + ++iter) + { + llsdMap[iter->first] = iter->second; + } + + return format (s, llsdMap); +} + +//static +template +S32 LLStringUtilBase::format(std::basic_string& s, const LLSD& substitutions) +{ S32 res = 0; - // Look for the first match of any keyword, replace that keyword, - // repeat from the end of the replacement string. This avoids - // accidentally performing substitution on a substituted string. - while (1) + if (!substitutions.isMap()) + { + return res; + } + + std::basic_ostringstream 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::const_iterator start = s.begin(); + typename std::basic_string::const_iterator end = s.end(); + boost::smatch match; + + + while (boost::regex_search(start, end, match, key, boost::match_default)) { - string_size_type_t first_match_pos = scanstart; - string_size_type_t first_match_str_length = 0; - std::basic_string first_match_str_replacement; + bool found_replacement = false; + std::vector > tokens; + std::basic_string replacement; - for (format_map_t::const_iterator iter = fmt_map.begin(); - iter != fmt_map.end(); - ++iter) + getTokens (std::basic_string(match[1].first, match[1].second), tokens); + + if (tokens.size() == 1) { - string_size_type_t n = s.find(iter->first, scanstart); - if (n != std::basic_string::npos && - (n < first_match_pos || - 0 == first_match_str_length)) - { - first_match_pos = n; - first_match_str_length = iter->first.length(); - first_match_str_replacement = iter->second; - } + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); } + else if (tokens[1] == "number") + { + std::basic_string param = "0"; - if (0 == first_match_str_length) + 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") { - // no more keys found to substitute from this point - // in the string forward. - break; + std::basic_string param; + if (tokens.size() > 2) param = tokens[2]; + + found_replacement = formatDatetime (replacement, tokens[0], param, substitutions); + } + + if (found_replacement) + { + output << std::basic_string(start, match[0].first) << replacement; + res++; } else { - s.erase(first_match_pos, first_match_str_length); - s.insert(first_match_pos, first_match_str_replacement); - scanstart = first_match_pos + - first_match_str_replacement.length(); - ++res; + // 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(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(start, end); + s = output.str(); return res; } +// static +template +bool LLStringUtilBase::simpleReplacement(std::basic_string &replacement, std::basic_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::basic_string("[" + token + "]"))) + { + replacement = substitutions[std::basic_string("[" + token + "]")].asString(); + return true; + } + + return false; +} + +// static +template +void LLStringUtilBase::formatNumber(std::basic_string& numStr, std::basic_string decimals) +{ + typedef typename std::basic_string::size_type string_size_type_t; + std::basic_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 LLStringUtilBase::formatDatetime(std::basic_string& replacement, std::basic_string token, + std::basic_string param, const LLSD& substitutions) +{ + S32 secFromEpoch = (long) substitutions["datetime"].asInteger(); + + if (param == "local") + { + secFromEpoch -= LLStringOps::getLocalTimeOffset(); + } + else if (param != "utc") + { + secFromEpoch -= LLStringOps::getSltOffset(); + } + + 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 S32 LLStringUtilBase::compareStrings(const T* lhs, const T* rhs) diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index c8c9fd4eec..f25339f48d 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -35,7 +35,6 @@ #include "llapr.h" #include "llapp.h" -#include "llmemory.h" #include "apr_thread_cond.h" diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index fa6efaf38e..f8066d56ed 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -561,32 +561,27 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring) // ////////////////////////////////////////////////////////////////////////////// -std::list LLEventTimer::sActiveList; - LLEventTimer::LLEventTimer(F32 period) : mEventTimer() { mPeriod = period; - sActiveList.push_back(this); } LLEventTimer::LLEventTimer(const LLDate& time) : mEventTimer() { mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); - sActiveList.push_back(this); } -LLEventTimer::~LLEventTimer() +LLEventTimer::~LLEventTimer() { - sActiveList.remove(this); } void LLEventTimer::updateClass() { std::list completed_timers; - for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) + for (instance_iter iter = instancesBegin(); iter != instancesEnd(); ) { LLEventTimer* timer = *iter++; F32 et = timer->mEventTimer.getElapsedTimeF32(); diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index e2cf1c7689..0319bec45b 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -40,6 +40,7 @@ #include "stdtypes.h" #include "lldate.h" +#include "llinstancetracker.h" #include #include @@ -171,13 +172,13 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring); void secondsToTimecodeString(F32 current_time, std::string& tcstring); // class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LLEventTimer +class LLEventTimer : protected LLInstanceTracker { public: LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds LLEventTimer(const LLDate& time); virtual ~LLEventTimer(); - + //function to be called at the supplied frequency // Normally return FALSE; TRUE will delete the timer after the function returns. virtual BOOL tick() = 0; @@ -187,10 +188,6 @@ public: protected: LLTimer mEventTimer; F32 mPeriod; - -private: - //list of active timers - static std::list sActiveList; // TODO should this be a vector }; #endif diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h new file mode 100644 index 0000000000..7ab94b0e6d --- /dev/null +++ b/indra/llcommon/lltreeiterators.h @@ -0,0 +1,691 @@ +/** + * @file lltreeiterators.h + * @author Nat Goodspeed + * @date 2008-08-19 + * @brief This file defines iterators useful for traversing arbitrary node + * classes, potentially polymorphic, linked into strict tree + * structures. + * + * Dereferencing any one of these iterators actually yields a @em + * pointer to the node in question. For example, given an + * LLLinkedIter li, *li gets you a pointer + * to MyNode, and **li gets you the MyNode instance itself. + * More commonly, instead of writing li->member, you write + * (*li)->member -- as you would if you were traversing an + * STL container of MyNode pointers. + * + * It would certainly be possible to build these iterators so that + * *iterator would return a reference to the node itself + * rather than a pointer to the node, and for many purposes it would + * even be more convenient. However, that would be insufficiently + * flexible. If you want to use an iterator range to (e.g.) initialize + * a std::vector collecting results -- you rarely want to actually @em + * copy the nodes in question. You're much more likely to want to copy + * pointers to the traversed nodes. Hence these iterators + * produce pointers. + * + * Though you specify the actual NODE class as the template parameter, + * these iterators internally use LLPtrTo<> to discover whether to + * store and return an LLPointer or a simple NODE*. + * + * By strict tree structures, we mean that each child must have + * exactly one parent. This forbids a child claiming any ancestor as a + * child of its own. Child nodes with multiple parents will be visited + * once for each parent. Cycles in the graph will result in either an + * infinite loop or an out-of-memory crash. You Have Been Warned. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +#if ! defined(LL_LLTREEITERATORS_H) +#define LL_LLTREEITERATORS_H + +#include "llptrto.h" +#include +#include +#include +#include +#include + +namespace LLTreeIter +{ + /// Discriminator between LLTreeUpIter and LLTreeDownIter + enum RootIter { UP, DOWN }; + /// Discriminator between LLTreeDFSIter, LLTreeDFSPostIter and LLTreeBFSIter + enum WalkIter { DFS_PRE, DFS_POST, BFS }; +} + +/** + * LLBaseIter defines some machinery common to all these iterators. We use + * boost::iterator_facade to define the iterator boilerplate: the conventional + * operators and methods necessary to implement a standards-conforming + * iterator. That allows us to specify the actual iterator semantics in terms + * of equal(), dereference() and increment() methods. + */ +template +class LLBaseIter: public boost::iterator_facade::type, + boost::forward_traversal_tag> +{ +protected: + /// LLPtrTo::type is either NODE* or LLPointer, as appropriate + typedef typename LLPtrTo::type ptr_type; + /// function that advances from this node to next accepts a node pointer + /// and returns another + typedef boost::function func_type; + typedef SELFTYPE self_type; +}; + +/// Functor returning NULL, suitable for an end-iterator's 'next' functor +template +typename LLPtrTo::type LLNullNextFunctor(const typename LLPtrTo::type&) +{ + return typename LLPtrTo::type(); +} + +/** + * LLLinkedIter is an iterator over an intrusive singly-linked list. The + * beginning of the list is represented by LLLinkedIter(list head); the end is + * represented by LLLinkedIter(). + * + * The begin LLLinkedIter must be instantiated with a functor to extract the + * 'next' pointer from the current node. Supposing that the link pointer is @c + * public, something like: + * + * @code + * NODE* mNext; + * @endcode + * + * you can use (e.g.) boost::bind(&NODE::mNext, _1) for the purpose. + * Alternatively, you can bind whatever accessor method is normally used to + * advance to the next node, e.g. for: + * + * @code + * NODE* next() const; + * @endcode + * + * you can use boost::bind(&NODE::next, _1). + */ +template +class LLLinkedIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; +protected: + /// some methods need to return a reference to self + typedef typename super::self_type self_type; + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +public: + /// Instantiate an LLLinkedIter to start a range, or to end a range before + /// a particular list entry. Pass a functor to extract the 'next' pointer + /// from the current node. + LLLinkedIter(const ptr_type& entry, const func_type& nextfunc): + mCurrent(entry), + mNextFunc(nextfunc) + {} + /// Instantiate an LLLinkedIter to end a range at the end of the list + LLLinkedIter(): + mCurrent(), + mNextFunc(LLNullNextFunctor) + {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mCurrent = mNextFunc(mCurrent); + } + /// equality + bool equal(const self_type& that) const { return this->mCurrent == that.mCurrent; } + /// dereference + ptr_type& dereference() const { return const_cast(mCurrent); } + + ptr_type mCurrent; + func_type mNextFunc; +}; + +/** + * LLTreeUpIter walks from the node in hand to the root of the tree. The term + * "up" is applied to a tree visualized with the root at the top. + * + * LLTreeUpIter is an alias for LLLinkedIter, since any linked tree that you + * can navigate that way at all contains parent pointers. + */ +template +class LLTreeUpIter: public LLLinkedIter +{ + typedef LLLinkedIter super; +public: + /// Instantiate an LLTreeUpIter to start from a particular tree node, or + /// to end a parent traversal before reaching a particular ancestor. Pass + /// a functor to extract the 'parent' pointer from the current node. + LLTreeUpIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// Instantiate an LLTreeUpIter to end a range at the root of the tree + LLTreeUpIter(): + super() + {} +}; + +/** + * LLTreeDownIter walks from the root of the tree to the node in hand. The + * term "down" is applied to a tree visualized with the root at the top. + * + * Though you instantiate the begin() LLTreeDownIter with a pointer to some + * node at an arbitrary location in the tree, the root will be the first node + * you dereference and the passed node will be the last node you dereference. + * + * On construction, LLTreeDownIter walks from the current node to the root, + * capturing the path. Then in use, it replays that walk in reverse. As with + * all traversals of interesting data structures, it is actively dangerous to + * modify the tree during an LLTreeDownIter walk. + */ +template +class LLTreeDownIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDownIter to end at a particular tree node. Pass a + /// functor to extract the 'parent' pointer from the current node. + LLTreeDownIter(const ptr_type& node, + const func_type& parentfunc) + { + for (ptr_type n = node; n; n = parentfunc(n)) + mParents.push_back(n); + } + /// Instantiate an LLTreeDownIter representing "here", the end of the loop + LLTreeDownIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mParents.pop_back(); + } + /// equality + bool equal(const self_type& that) const { return this->mParents == that.mParents; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mParents.back()); } + + list_type mParents; +}; + +/** + * When you want to select between LLTreeUpIter and LLTreeDownIter with a + * compile-time discriminator, use LLTreeRootIter with an LLTreeIter::RootIter + * template arg. + */ +template +class LLTreeRootIter +{ + enum { use_a_valid_LLTreeIter_RootIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeRootIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } + LLTreeRootIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } +}; + +/// Specialize for LLTreeIter::UP +template +class LLTreeRootIter: public LLTreeUpIter +{ + typedef LLTreeUpIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DOWN +template +class LLTreeRootIter: public LLTreeDownIter +{ + typedef LLTreeDownIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSIter "flattens" + * a depth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeDFSIter must be instantiated with functors to obtain from + * a given node begin() and end() iterators for that node's children. For this + * reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc), + mSkipChildren(false) + { + // Only push back this node if it's non-NULL! + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeDFSIter to mark the end of the walk + LLTreeDFSIter() {} + + /// flags iterator logic to skip traversing children of current node on next increment + void skipChildren(bool skip = true) { mSkipChildren = skip; } + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.back(); + // Remove it from mPending so we don't process it again later + mPending.pop_back(); + if (!mSkipChildren) + { + // Add all its children to mPending + addChildren(current); + } + // reset flag after each step + mSkipChildren = false; + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back()); } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // reverse-copy the children into the newly-expanded space + std::copy(chi, chend, mPending.rbegin()); + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; + /// flag which controls traversal of children (skip children of current node if true) + bool mSkipChildren; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSPostIter + * "flattens" a depth-first tree walk through that node and all its + * descendants. Whereas LLTreeDFSIter visits each node before visiting any of + * its children, LLTreeDFSPostIter visits all of a node's children before + * visiting the node itself. + * + * The begin() LLTreeDFSPostIter must be instantiated with functors to obtain + * from a given node begin() and end() iterators for that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSPostIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSPostIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // Upon reaching a given node in our pending list, we need to know whether + // we've already pushed that node's children, so we must associate a bool + // with each node pointer. + typedef std::vector< std::pair > list_type; +public: + /// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc) + { + if (! node) + return; + mPending.push_back(typename list_type::value_type(node, false)); + makeCurrent(); + } + /// Instantiate an LLTreeDFSPostIter to mark the end of the walk + LLTreeDFSPostIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Pop the previous current node + mPending.pop_back(); + makeCurrent(); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back().first); } + + /// Call this each time we change mPending.back() -- that is, every time + /// we're about to change the value returned by dereference(). If we + /// haven't yet pushed the new node's children, do so now. + void makeCurrent() + { + // Once we've popped the last node, this becomes a no-op. + if (mPending.empty()) + return; + // Here mPending.back() holds the node pointer we're proposing to + // dereference next. Have we pushed that node's children yet? + if (mPending.back().second) + return; // if so, it's okay to visit this node now + // We haven't yet pushed this node's children. Do so now. Remember + // that we did -- while the node in question is still back(). + mPending.back().second = true; + addChildren(mPending.back().first); + // Now, because we've just changed mPending.back(), make that new node + // current. + makeCurrent(); + } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // Reverse-copy the children into the newly-expanded space. We can't + // just use std::copy() because the source is a ptr_type, whereas the + // dest is a pair of (ptr_type, bool). + for (typename list_type::reverse_iterator pi = mPending.rbegin(); chi != chend; ++chi, ++pi) + { + pi->first = *chi; // copy the child pointer + pi->second = false; // we haven't yet pushed this child's chldren + } + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeBFSIter "flattens" + * a breadth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeBFSIter must be instantiated with functors to obtain from + * a given node the begin() and end() iterators of that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeBFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeBFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // We need a FIFO queue rather than a LIFO stack. Use a deque rather than + // a vector, since vector can't implement pop_front() efficiently. + typedef std::deque list_type; +public: + /// Instantiate an LLTreeBFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeBFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc) + { + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeBFSIter to mark the end of the walk + LLTreeBFSIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Breadth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.front(); + // Remove it from mPending so we don't process it again later + mPending.pop_front(); + // Add all its children to mPending + CHILDITER chend = mEndFunc(current); + for (CHILDITER chi = mBeginFunc(current); chi != chend; ++chi) + mPending.push_back(*chi); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.front()); } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; +}; + +/** + * When you want to select between LLTreeDFSIter, LLTreeDFSPostIter and + * LLTreeBFSIter with a compile-time discriminator, use LLTreeWalkIter with an + * LLTreeIter::WalkIter template arg. + */ +template +class LLTreeWalkIter +{ + enum { use_a_valid_LLTreeIter_WalkIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeWalkIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } + LLTreeWalkIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } +}; + +/// Specialize for LLTreeIter::DFS_PRE +template +class LLTreeWalkIter: + public LLTreeDFSIter +{ + typedef LLTreeDFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DFS_POST +template +class LLTreeWalkIter: + public LLTreeDFSPostIter +{ + typedef LLTreeDFSPostIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::BFS +template +class LLTreeWalkIter: + public LLTreeBFSIter +{ + typedef LLTreeBFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +#endif /* ! defined(LL_LLTREEITERATORS_H) */ diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 78c4f8e742..822fb390f3 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -86,6 +86,7 @@ void LLCrashLoggerText::updateApplication(const std::string& message) LLCrashLogger::LLCrashLogger() : mCrashBehavior(CRASH_BEHAVIOR_ASK), mCrashInPreviousExec(false), + mCrashSettings("CrashSettings"), mSentCrashLogs(false), mCrashHost("") { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index bd609b638c..c0c81e9771 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -35,7 +35,7 @@ #include "lluuid.h" #include "llstring.h" -#include "llmemory.h" +//#include "llmemory.h" #include "llthread.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h index bc2d6522d2..1a297536b4 100644 --- a/indra/llimage/llimagedxt.h +++ b/indra/llimage/llimagedxt.h @@ -33,6 +33,7 @@ #define LL_LLIMAGEDXT_H #include "llimage.h" +#include "llpointer.h" // This class decodes and encodes LL DXT files (which may unclude uncompressed RGB or RGBA mipped data) diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index a6721bfa0f..d8f8003593 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -31,10 +31,12 @@ #include "linden_common.h" -#include "lldir.h" #include "llimagetga.h" + +#include "lldir.h" #include "llerror.h" #include "llmath.h" +#include "llpointer.h" // For expanding 5-bit pixel values to 8-bit with best rounding // static diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 879fcf5565..0d66695d6e 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -34,6 +34,7 @@ #define LL_LLIMAGEWORKER_H #include "llimage.h" +#include "llpointer.h" #include "llworkerthread.h" class LLImageWorker : public LLWorkerClass diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index be6b6c817b..ec6264dcf5 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -37,7 +37,7 @@ #include "openjpeg.h" #include "lltimer.h" -#include "llmemory.h" +//#include "llmemory.h" const char* fallbackEngineInfoLLImageJ2CImpl() { diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index 2e2adc4d45..e480085453 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -32,7 +32,7 @@ #ifndef LL_LLECONOMY_H #define LL_LLECONOMY_H -#include "llmemory.h" +#include "llsingleton.h" class LLMessageSystem; class LLVector3; diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2823cf7be9..ce2e4e9cfa 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1097,109 +1097,8 @@ fail: } -LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const -{ - LLMemType m1(LLMemType::MTYPE_INVENTORY); - LLXMLNode *ret = new LLXMLNode("item", FALSE); - - ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID); - ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID); - - mPermissions.exportFileXML()->setParent(ret); - - // Check for permissions to see the asset id, and if so write it - // out as an asset id. Otherwise, apply our cheesy encryption. - if(include_asset_key) - { - U32 mask = mPermissions.getMaskBase(); - if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - || (mAssetUUID.isNull())) - { - ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID); - } - else - { - LLUUID shadow_id(mAssetUUID); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.encrypt(shadow_id.mData, UUID_BYTES); - - ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id); - } - } - - std::string type_str = LLAssetType::lookup(mType); - std::string inv_type_str = LLInventoryType::lookup(mInventoryType); - - ret->createChild("asset_type", FALSE)->setStringValue(type_str); - ret->createChild("inventory_type", FALSE)->setStringValue(inv_type_str); - S32 tmp_flags = (S32) mFlags; - ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX); - - mSaleInfo.exportFileXML()->setParent(ret); - - std::string temp; - temp.assign(mName); - ret->createChild("name", FALSE)->setStringValue(temp); - temp.assign(mDescription); - ret->createChild("description", FALSE)->setStringValue(temp); - S32 date = mCreationDate; - ret->createChild("creation_date", FALSE)->setIntValue(1, &date); - - return ret; -} - -BOOL LLInventoryItem::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("uuid", sub_node)) - success = (1 == sub_node->getUUIDValue(1, &mUUID)); - if (node->getChild("parent_uuid", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID)); - if (node->getChild("permissions", sub_node)) - success = success && mPermissions.importXML(sub_node); - if (node->getChild("asset_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - if (node->getChild("shadow_id", sub_node)) - { - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - } - if (node->getChild("asset_type", sub_node)) - mType = LLAssetType::lookup(sub_node->getValue()); - if (node->getChild("inventory_type", sub_node)) - mInventoryType = LLInventoryType::lookup(sub_node->getValue()); - if (node->getChild("flags", sub_node)) - { - S32 tmp_flags = 0; - success = success && (1 == sub_node->getIntValue(1, &tmp_flags)); - mFlags = (U32) tmp_flags; - } - if (node->getChild("sale_info", sub_node)) - success = success && mSaleInfo.importXML(sub_node); - if (node->getChild("name", sub_node)) - mName = sub_node->getValue(); - if (node->getChild("description", sub_node)) - mDescription = sub_node->getValue(); - if (node->getChild("creation_date", sub_node)) - { - S32 date = 0; - success = success && (1 == sub_node->getIntValue(1, &date)); - mCreationDate = date; - } - - if (!success) - { - lldebugs << "LLInventory::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index d34046c310..bdf444d34f 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -40,6 +40,7 @@ #include "llinventorytype.h" #include "llmemtype.h" #include "llpermissions.h" +#include "llrefcount.h" #include "llsaleinfo.h" #include "llsd.h" #include "lluuid.h" @@ -273,9 +274,6 @@ public: virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; - virtual LLXMLNode *exportFileXML(BOOL include_asset_key = TRUE) const; - BOOL importXML(LLXMLNode* node); - // helper functions // pack all information needed to reconstruct this item into the given binary bucket. diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a161a0ee00..d905fe3ea7 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -63,6 +63,7 @@ static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = "wearable", "animation", "gesture", // 20 + "favorite" //21 }; // This table is meant for decoding to human readable form. Put any @@ -91,6 +92,7 @@ static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = "wearable", "animation", "gesture", // 20 + "favorite" // 21 }; // Maps asset types to the default inventory type for that kind of asset. @@ -120,6 +122,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_IMAGE_JPEG LLInventoryType::IT_ANIMATION, // AT_ANIMATION LLInventoryType::IT_GESTURE, // AT_GESTURE + LLInventoryType::IT_FAVORITE, // AT_FAVORITE }; static const int MAX_POSSIBLE_ASSET_TYPES = 2; @@ -147,6 +150,7 @@ INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE + { LLAssetType::AT_FAVORITE, LLAssetType::AT_NONE }, // IT_FAVORITE }; // static diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index d3effc0e6d..c9ba97d7b6 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -67,7 +67,8 @@ public: IT_WEARABLE = 18, IT_ANIMATION = 19, IT_GESTURE = 20, - IT_COUNT = 21, + IT_FAVORITE = 21, + IT_COUNT = 22, IT_NONE = -1 }; diff --git a/indra/llinventory/llnotecard.h b/indra/llinventory/llnotecard.h index b903f1fdb0..092ab2ce35 100644 --- a/indra/llinventory/llnotecard.h +++ b/indra/llinventory/llnotecard.h @@ -33,7 +33,7 @@ #ifndef LL_NOTECARD_H #define LL_NOTECARD_H -#include "llmemory.h" +#include "llpointer.h" #include "llinventory.h" class LLNotecard diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 9c27476b0a..60ebc44a3e 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -85,13 +85,13 @@ static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] = "None", "Linden Location", "Adult", - "Arts & Culture", + "Arts and Culture", "Business", "Educational", "Gaming", "Hangout", "Newcomer Friendly", - "Parks & Nature", + "Parks and Nature", "Residential", "Shopping", "Stage", diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 6f5ae87ebd..021ad89e52 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llparcelflags.h" #include "llpermissions.h" +#include "lltimer.h" #include "v3math.h" diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 328ed4588b..559a5631dc 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -831,67 +831,8 @@ BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const return TRUE; } - -LLXMLNode *LLPermissions::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("permissions", FALSE); - - ret->createChild("group_owned", TRUE)->setBoolValue(mIsGroupOwned); - - ret->createChild("base_mask", FALSE)->setByteValue(4, (U8*)&mMaskBase, LLXMLNode::ENCODING_HEX); - ret->createChild("owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskOwner, LLXMLNode::ENCODING_HEX); - ret->createChild("group_mask", FALSE)->setByteValue(4, (U8*)&mMaskGroup, LLXMLNode::ENCODING_HEX); - ret->createChild("everyone_mask", FALSE)->setByteValue(4, (U8*)&mMaskEveryone, LLXMLNode::ENCODING_HEX); - ret->createChild("next_owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskNextOwner, LLXMLNode::ENCODING_HEX); - - ret->createChild("creator_id", FALSE)->setUUIDValue(1, &mCreator); - ret->createChild("owner_id", FALSE)->setUUIDValue(1, &mOwner); - ret->createChild("last_owner_id", FALSE)->setUUIDValue(1, &mLastOwner); - ret->createChild("group_id", FALSE)->setUUIDValue(1, &mGroup); - - return ret; -} - -bool LLPermissions::importXML(LLXMLNode* node) -{ - bool success = false; - if (node) - { - success = true; - LLXMLNodePtr sub_node; - if (node->getChild("base_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskBase)); - if (node->getChild("owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskOwner)); - if (node->getChild("group_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskGroup)); - if (node->getChild("everyone_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskEveryone)); - if (node->getChild("next_owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskNextOwner)); - - if (node->getChild("creator_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mCreator)); - if (node->getChild("owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mOwner)); - if (node->getChild("last_owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mLastOwner)); - if (node->getChild("group_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mGroup)); - if (node->getChild("group_owned", sub_node)) - { - BOOL tmpbool = FALSE; - success = success && (1 == sub_node->getBoolValue(1, &tmpbool)); - mIsGroupOwned = (bool)tmpbool; - } - if (!success) - { - lldebugs << "LLPermissions::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLPermissions::exportFileXML() and LLPermissions::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC bool LLPermissions::operator==(const LLPermissions &rhs) const { diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 5587f8c3c8..2035b57f5c 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -314,9 +314,6 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; - LLXMLNode *exportFileXML() const; - bool importXML(LLXMLNode* node); - bool operator==(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index b7afb28adf..930901f309 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -135,38 +135,8 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) return true; } -LLXMLNode *LLSaleInfo::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("sale_info", FALSE); - std::string type_str = ll_safe_string( lookup(mSaleType)); - ret->createChild("type", TRUE)->setStringValue(1, &type_str); - ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice); - return ret; -} - -BOOL LLSaleInfo::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("type", sub_node)) - { - mSaleType = lookup(sub_node->getValue().c_str()); - } - if (node->getChild("price", sub_node)) - { - success &= (1 == sub_node->getIntValue(1, &mSalePrice)); - } - if (!success) - { - lldebugs << "LLSaleInfo::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) { diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index d546c49fd7..3461a128be 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -101,9 +101,6 @@ public: bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); - LLXMLNode *exportFileXML() const; - BOOL importXML(LLXMLNode* node); - LLSD packMessage() const; void unpackMessage(LLSD sales); diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 66451b1a27..f85c4f39f4 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -36,8 +36,8 @@ #include #include #include "lldefs.h" -#include "llstl.h" // *TODO: Remove when LLString is gone -#include "llstring.h" // *TODO: Remove when LLString is gone +//#include "llstl.h" // *TODO: Remove when LLString is gone +//#include "llstring.h" // *TODO: Remove when LLString is gone // lltut.h uses is_approx_equal_fraction(). This was moved to its own header // file in llcommon so we can use lltut.h for llcommon tests without making // llcommon depend on llmath. diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index 9eb58dbbe9..98aceb0597 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -271,8 +271,8 @@ public: << " W " << rect.getWidth() << " H " << rect.getHeight() << " }"; return s; } - - bool operator==(const LLRectBase &b) + + bool operator==(const LLRectBase &b) const { return ((mLeft == b.mLeft) && (mTop == b.mTop) && @@ -280,7 +280,7 @@ public: (mBottom == b.mBottom)); } - bool operator!=(const LLRectBase &b) + bool operator!=(const LLRectBase &b) const { return ((mLeft != b.mLeft) || (mTop != b.mTop) || diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp index 073cb2e3bd..c5176681ce 100644 --- a/indra/llmath/llsdutil_math.cpp +++ b/indra/llmath/llsdutil_math.cpp @@ -165,9 +165,6 @@ LLSD ll_sd_from_color4(const LLColor4& c) LLColor4 ll_color4_from_sd(const LLSD& sd) { LLColor4 c; - c.mV[0] = (F32)sd[0].asReal(); - c.mV[1] = (F32)sd[1].asReal(); - c.mV[2] = (F32)sd[2].asReal(); - c.mV[3] = (F32)sd[3].asReal(); + c.setValue(sd); return c; } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index e55fe52c91..af46da05d8 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -52,7 +52,7 @@ class LLVolume; #include "llquaternion.h" #include "llstrider.h" #include "v4coloru.h" -#include "llmemory.h" +#include "llrefcount.h" #include "llfile.h" //============================================================================ diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index e10ad94dba..57d789e73a 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -36,7 +36,7 @@ #include #include "llvolume.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLVolumeParams; diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index 0cbfce07c9..34337b3ac8 100644 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp @@ -227,6 +227,40 @@ const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a) return (*this); } +void LLColor4::setValue(const LLSD& sd) +{ +#if 0 + // Clamping on setValue from LLSD is inconsistent with other set behavior + F32 val; + bool out_of_range = false; + val = sd[0].asReal(); + mV[0] = llclamp(val, 0.f, 1.f); + out_of_range = mV[0] != val; + + val = sd[1].asReal(); + mV[1] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[1] != val; + + val = sd[2].asReal(); + mV[2] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[2] != val; + + val = sd[3].asReal(); + mV[3] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[3] != val; + + if (out_of_range) + { + llwarns << "LLSD color value out of range!" << llendl; + } +#else + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); + mV[2] = (F32) sd[2].asReal(); + mV[3] = (F32) sd[3].asReal(); +#endif +} + const LLColor4& LLColor4::operator=(const LLColor3 &a) { mV[VX] = a.mV[VX]; diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 785b47dd37..f2a5cd39ed 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -72,13 +72,7 @@ class LLColor4 return ret; } - void setValue(const LLSD& sd) - { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); - mV[3] = (F32) sd[3].asReal(); - } + void setValue(const LLSD& sd); void calcHSL(F32* hue, F32* saturation, F32* luminance) const; @@ -249,7 +243,7 @@ inline LLColor4::LLColor4(void) inline LLColor4::LLColor4(const LLSD& sd) { - *this = sd; + this->setValue(sd); } inline LLColor4::LLColor4(F32 r, F32 g, F32 b) @@ -641,10 +635,7 @@ void LLColor4::clamp() inline const LLColor4& LLColor4::operator=(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); - mV[3] = (F32) sd[3].asReal(); + setValue(sd); return *this; } diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index 082d0efbb1..c0390fa0b2 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -138,6 +138,12 @@ public: static BOOL parseColor4U(const std::string& buf, LLColor4U* value); + // conversion + operator const LLColor4() const + { + return LLColor4(*this); + } + static LLColor4U white; static LLColor4U black; static LLColor4U red; diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h index 96d7f6dd31..c709a08499 100644 --- a/indra/llmessage/llares.h +++ b/indra/llmessage/llares.h @@ -45,7 +45,8 @@ # include #endif -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "lluri.h" class LLQueryResponder; diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 799bc83e20..629bd3836d 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -43,11 +43,6 @@ #include "lluuid.h" #include "message.h" -// Constants -static const std::string CN_WAITING("(Loading...)"); // *TODO: translate -static const std::string CN_NOBODY("(nobody)"); // *TODO: translate -static const std::string CN_NONE("(none)"); // *TODO: translate - // llsd serialization constants static const std::string AGENTS("agents"); static const std::string GROUPS("groups"); @@ -65,6 +60,7 @@ const S32 CN_FILE_VERSION = 2; // Globals LLCacheName* gCacheName = NULL; +std::map LLCacheName::sCacheName; /// --------------------------------------------------------------------------- /// class LLCacheNameEntry @@ -92,17 +88,19 @@ class PendingReply { public: LLUUID mID; - LLCacheNameCallback mCallback; + LLCacheNameSignal mSignal; LLHost mHost; - void* mData; - PendingReply(const LLUUID& id, LLCacheNameCallback callback, void* data = NULL) - : mID(id), mCallback(callback), mData(data) - { } - + PendingReply(const LLUUID& id, const LLHost& host) - : mID(id), mCallback(0), mHost(host) - { } - + : mID(id), mHost(host) + { + } + + boost::signals::connection setCallback(const LLCacheNameCallback& cb) + { + return mSignal.connect(cb); + } + void done() { mID.setNull(); } bool isDone() const { return mID.isNull() != FALSE; } }; @@ -187,10 +185,9 @@ void ReplySender::flush() typedef std::set AskQueue; -typedef std::vector ReplyQueue; +typedef std::list ReplyQueue; typedef std::map PendingQueue; typedef std::map Cache; -typedef std::vector Observers; class LLCacheName::Impl { @@ -211,13 +208,16 @@ public: ReplyQueue mReplyQueue; // requests awaiting replies from us - Observers mObservers; + LLCacheNameSignal mSignal; LLFrameTimer mProcessTimer; Impl(LLMessageSystem* msg); ~Impl(); - + + boost::signals::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback); + void addPending(const LLUUID& id, const LLHost& host); + void processPendingAsks(); void processPendingReplies(); void sendRequest(const char* msg_name, const AskQueue& queue); @@ -231,8 +231,6 @@ public: static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata); static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata); static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata); - - void notifyObservers(const LLUUID& id, const std::string& first, const std::string& last, BOOL group); }; @@ -247,6 +245,9 @@ LLCacheName::LLCacheName(LLMessageSystem* msg) LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host) : impl(* new Impl(msg)) { + sCacheName["waiting"] = "(Loading...)"; + sCacheName["nobody"] = "(nobody)"; + sCacheName["none"] = "(none)"; setUpstream(upstream_host); } @@ -272,52 +273,31 @@ LLCacheName::Impl::Impl(LLMessageSystem* msg) LLCacheName::Impl::~Impl() { for_each(mCache.begin(), mCache.end(), DeletePairedPointer()); + for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer()); } - -void LLCacheName::setUpstream(const LLHost& upstream_host) +boost::signals::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback) { - impl.mUpstreamHost = upstream_host; + PendingReply* reply = new PendingReply(id, LLHost()); + boost::signals::connection res = reply->setCallback(callback); + mReplyQueue.push_back(reply); + return res; } -void LLCacheName::addObserver(LLCacheNameCallback callback) +void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host) { - impl.mObservers.push_back(callback); + PendingReply* reply = new PendingReply(id, host); + mReplyQueue.push_back(reply); } -void LLCacheName::removeObserver(LLCacheNameCallback callback) +void LLCacheName::setUpstream(const LLHost& upstream_host) { - Observers::iterator it = impl.mObservers.begin(); - Observers::iterator end = impl.mObservers.end(); - - for ( ; it != end; ++it) - { - const LLCacheNameCallback& cb = (*it); - if (cb == callback) - { - impl.mObservers.erase(it); - return; - } - } + impl.mUpstreamHost = upstream_host; } -void LLCacheName::cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data) +boost::signals::connection LLCacheName::addObserver(const LLCacheNameCallback& callback) { - ReplyQueue::iterator it = impl.mReplyQueue.begin(); - ReplyQueue::iterator end = impl.mReplyQueue.end(); - - for(; it != end; ++it) - { - const PendingReply& reply = (*it); - - if ((callback == reply.mCallback) - && (id == reply.mID) - && (user_data == reply.mData) ) - { - impl.mReplyQueue.erase(it); - return; - } - } + return impl.mSignal.connect(callback); } void LLCacheName::importFile(LLFILE* fp) @@ -493,7 +473,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las { if(id.isNull()) { - first = CN_NOBODY; + first = sCacheName["nobody"]; last.clear(); return FALSE; } @@ -507,7 +487,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las } else { - first = CN_WAITING; + first = sCacheName["waiting"]; last.clear(); if (!impl.isRequestPending(id)) { @@ -517,6 +497,14 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las } } +// static +void LLCacheName::LocalizeCacheName(std::string key, std::string value) +{ + if (key!="" && value!= "" ) + sCacheName[key]=value; + else + llwarns<< " Error localizing cache key " << key << " To "<< value<mIsGroup) { - callback(id, entry->mGroupName, "", entry->mIsGroup, user_data); + signal(id, entry->mGroupName, "", entry->mIsGroup); } else { - callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data); + signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup); } } else @@ -597,8 +595,14 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb impl.mAskNameQueue.insert(id); } } - impl.mReplyQueue.push_back(PendingReply(id, callback, user_data)); + res = impl.addPending(id, callback); } + return res; +} + +boost::signals::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data) +{ + return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data)); } void LLCacheName::processPending() @@ -684,14 +688,14 @@ void LLCacheName::dumpStats() << " AskGroup=" << impl.mAskGroupQueue.size() << " Pending=" << impl.mPendingQueue.size() << " Reply=" << impl.mReplyQueue.size() - << " Observers=" << impl.mObservers.size() +// << " Observers=" << impl.mSignal.size() << llendl; } //static std::string LLCacheName::getDefaultName() { - return CN_WAITING; + return sCacheName["waiting"]; } void LLCacheName::Impl::processPendingAsks() @@ -704,50 +708,49 @@ void LLCacheName::Impl::processPendingAsks() void LLCacheName::Impl::processPendingReplies() { - ReplyQueue::iterator it = mReplyQueue.begin(); - ReplyQueue::iterator end = mReplyQueue.end(); - // First call all the callbacks, because they might send messages. - for(; it != end; ++it) + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it) { - LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID); + PendingReply* reply = *it; + LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID); if(!entry) continue; - if (it->mCallback) + if (!entry->mIsGroup) { - if (!entry->mIsGroup) - { - (it->mCallback)(it->mID, - entry->mFirstName, entry->mLastName, - FALSE, it->mData); - } - else { - (it->mCallback)(it->mID, - entry->mGroupName, "", - TRUE, it->mData); - } + (reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE); + } + else + { + (reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE); } } // Forward on all replies, if needed. ReplySender sender(mMsg); - for (it = mReplyQueue.begin(); it != end; ++it) + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it) { - LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID); + PendingReply* reply = *it; + LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID); if(!entry) continue; - if (it->mHost.isOk()) + if (reply->mHost.isOk()) { - sender.send(it->mID, *entry, it->mHost); + sender.send(reply->mID, *entry, reply->mHost); } - it->done(); + reply->done(); + } + + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ) + { + ReplyQueue::iterator curit = it++; + PendingReply* reply = *curit; + if (reply->isDone()) + { + delete reply; + mReplyQueue.erase(curit); + } } - - mReplyQueue.erase( - remove_if(mReplyQueue.begin(), mReplyQueue.end(), - std::mem_fun_ref(&PendingReply::isDone)), - mReplyQueue.end()); } @@ -785,18 +788,6 @@ void LLCacheName::Impl::sendRequest( } } -void LLCacheName::Impl::notifyObservers(const LLUUID& id, - const std::string& first, const std::string& last, BOOL is_group) -{ - for (Observers::const_iterator i = mObservers.begin(), - end = mObservers.end(); - i != end; - ++i) - { - (**i)(id, first, last, is_group, NULL); - } -} - bool LLCacheName::Impl::isRequestPending(const LLUUID& id) { U32 now = (U32)time(NULL); @@ -863,7 +854,7 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup) } } - mReplyQueue.push_back(PendingReply(id, fromHost)); + addPending(id, fromHost); } } } @@ -901,11 +892,11 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) if (!isGroup) { - notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE); + mSignal(id, entry->mFirstName, entry->mLastName, FALSE); } else { - notifyObservers(id, entry->mGroupName, "", TRUE); + mSignal(id, entry->mGroupName, "", TRUE); } } } diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 2757b86a7c..414b6590f6 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -33,12 +33,22 @@ #ifndef LL_LLCACHENAME_H #define LL_LLCACHENAME_H +#include +#include + class LLMessageSystem; class LLHost; class LLUUID; -// agent_id/group_id, first_name, last_name, is_group, user_data -typedef void (*LLCacheNameCallback)(const LLUUID&, const std::string&, const std::string&, BOOL, void*); + +typedef boost::signal LLCacheNameSignal; +typedef LLCacheNameSignal::slot_type LLCacheNameCallback; + +// Old callback with user data for compatability +typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*); // Here's the theory: // If you request a name that isn't in the cache, it returns "waiting" @@ -59,10 +69,7 @@ public: // for simulators, this is the data server void setUpstream(const LLHost& upstream_host); - void addObserver(LLCacheNameCallback callback); - void removeObserver(LLCacheNameCallback callback); - - void cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL); + boost::signals::connection addObserver(const LLCacheNameCallback& callback); // janky old format. Remove after a while. Phoenix. 2008-01-30 void importFile(LLFILE* fp); @@ -89,11 +96,10 @@ public: // If the data is currently available, may call the callback immediatly // otherwise, will request the data, and will call the callback when // available. There is no garuntee the callback will ever be called. - void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); + boost::signals::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback); // LEGACY - void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL) - { get(id, FALSE, callback, user_data); } + boost::signals::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. @@ -107,7 +113,8 @@ public: void dumpStats(); // Dumps the sizes of the cache and associated queues. static std::string getDefaultName(); - + static void LocalizeCacheName(std::string key, std::string value); + static std::map sCacheName; private: class Impl; diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index bbb56960df..b6988224ce 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2009&license=viewergpl$ * - * Copyright (c) 2001-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 @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h index d5f3aeaf2c..7f76390d0c 100644 --- a/indra/llmessage/llhttpclientadapter.h +++ b/indra/llmessage/llhttpclientadapter.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, @@ -33,7 +34,7 @@ #define LL_HTTPCLIENTADAPTER_H #include "llhttpclientinterface.h" -#include "llmemory.h" // LLSingleton<> +#include "llsingleton.h" // LLSingleton<> class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton { diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h index 1f13d46447..42a8e5cd0a 100644 --- a/indra/llmessage/llhttpclientinterface.h +++ b/indra/llmessage/llhttpclientinterface.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 17ffd66e8f..3f4da69a1d 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -33,7 +33,8 @@ #ifndef LL_LLHTTPNODE_H #define LL_LLHTTPNODE_H -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" class LLChainIOFactory; diff --git a/indra/llmessage/llhttpnodeadapter.h b/indra/llmessage/llhttpnodeadapter.h index 08b5664162..7c3e9d81d1 100644 --- a/indra/llmessage/llhttpnodeadapter.h +++ b/indra/llmessage/llhttpnodeadapter.h @@ -3,26 +3,27 @@ * @brief Declaration of llhttpnode adapter classes * * $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://secondlife.com/developers/opensource/gplv2 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 44be3ae388..aa64232e42 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -41,7 +41,7 @@ #include "llsd.h" #include "llsdserialize.h" #include "llsdutil.h" -#include "llmemory.h" +#include "llpointer.h" #include "message.h" #include "message.h" diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 9ce6a10c80..272e753f3c 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -36,7 +36,8 @@ #include "llhost.h" #include "lluuid.h" #include "llsd.h" -#include "llmemory.h" +#include "llrefcount.h" +#include "llpointer.h" #include "v3math.h" class LLMessageSystem; diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h index 4082666339..119eb1d7f7 100644 --- a/indra/llmessage/llmessagesenderinterface.h +++ b/indra/llmessage/llmessagesenderinterface.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 552cf4cbdb..0527d5cb8d 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -4,14 +4,25 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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. + * 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, diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index d1de608ec6..10602450d8 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -4,14 +4,25 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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. + * 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, diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp index 615eff405d..32cbb15cb3 100644 --- a/indra/llmessage/llstoredmessage.cpp +++ b/indra/llmessage/llstoredmessage.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2009&license=viewergpl$ * - * Copyright (c) 2001-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 diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h index e817f19bd2..5069c2cb2e 100644 --- a/indra/llmessage/llstoredmessage.h +++ b/indra/llmessage/llstoredmessage.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2009&license=viewergpl$ * - * Copyright (c) 2001-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 diff --git a/indra/llmessage/lltemplatemessagedispatcher.cpp b/indra/llmessage/lltemplatemessagedispatcher.cpp index 3bbf3a058d..ab1beb362b 100644 --- a/indra/llmessage/lltemplatemessagedispatcher.cpp +++ b/indra/llmessage/lltemplatemessagedispatcher.cpp @@ -3,26 +3,27 @@ * @brief LLTemplateMessageDispatcher class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/lltemplatemessagedispatcher.h b/indra/llmessage/lltemplatemessagedispatcher.h index b1e74f47bb..fa861e4e42 100644 --- a/indra/llmessage/lltemplatemessagedispatcher.h +++ b/indra/llmessage/lltemplatemessagedispatcher.h @@ -3,26 +3,27 @@ * @brief LLTemplateMessageDispatcher class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index a4d59275b9..059c1bdfa1 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -270,6 +270,7 @@ 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: @@ -292,6 +293,7 @@ bool is_asset_id_knowable(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/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp index c1a6c437a7..505ece57b0 100644 --- a/indra/llmessage/lltrustedmessageservice.cpp +++ b/indra/llmessage/lltrustedmessageservice.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService implementation * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h index bc824565f1..dc37702471 100644 --- a/indra/llmessage/lltrustedmessageservice.h +++ b/indra/llmessage/lltrustedmessageservice.h @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index b25b27eb0f..3d7d8984ad 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -59,10 +59,10 @@ #include "llhttpclient.h" #include "llhttpnode.h" #include "llpacketack.h" +#include "llsingleton.h" #include "message_prehash.h" #include "llstl.h" #include "llmsgvariabletype.h" -#include "llmsgvariabletype.h" #include "llmessagesenderinterface.h" #include "llstoredmessage.h" diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 43b5f8e224..4e657067cd 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -405,7 +405,7 @@ char* _PREHASH_GlobalX = LLMessageStringTable::getInstance()->getString("GlobalX char* _PREHASH_GlobalY = LLMessageStringTable::getInstance()->getString("GlobalY"); char* _PREHASH_CopyRotates = LLMessageStringTable::getInstance()->getString("CopyRotates"); char* _PREHASH_KickUserAck = LLMessageStringTable::getInstance()->getString("KickUserAck"); -char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); +char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); //legacy var need to be deleted -angela char* _PREHASH_SessionID = LLMessageStringTable::getInstance()->getString("SessionID"); char* _PREHASH_GlobalZ = LLMessageStringTable::getInstance()->getString("GlobalZ"); char* _PREHASH_DeclineFriendship = LLMessageStringTable::getInstance()->getString("DeclineFriendship"); diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 7360230451..cf1461ed2b 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -5,7 +5,30 @@ * @brief * * $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$ */ diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index 9d1d3fa221..afd38b0655 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -3,16 +3,16 @@ * @brief stub class to allow unit testing * * $LicenseInfo:firstyear=2008&license=internal$ - * - * Copyright (c) 2008, Linden Research, Inc. - * + * + * Copyright (c) 2008-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") { } + * 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. diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp index bde76db08b..250fa100b6 100644 --- a/indra/llmessage/tests/llhttpclientadapter_test.cpp +++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index a6f5659352..d57f17f270 100644 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService unit tests * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp index 1140458918..9bb597feec 100644 --- a/indra/llmessage/tests/lltesthttpclientadapter.cpp +++ b/indra/llmessage/tests/lltesthttpclientadapter.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=internal$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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 diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h index d032503685..8853fc44ec 100644 --- a/indra/llmessage/tests/lltesthttpclientadapter.h +++ b/indra/llmessage/tests/lltesthttpclientadapter.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=internal$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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 diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp index a37aa4c566..2c8456e0a8 100644 --- a/indra/llmessage/tests/lltestmessagesender.cpp +++ b/indra/llmessage/tests/lltestmessagesender.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=internal$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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 diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h index 83c0eff4d3..dfbef6be64 100644 --- a/indra/llmessage/tests/lltestmessagesender.h +++ b/indra/llmessage/tests/lltestmessagesender.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=internal$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-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 diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index 44595391df..0a3da4b467 100644 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService unit tests * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-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 * 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 - * + * 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://secondlife.com/developers/opensource/flossexception - * + * 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. diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 11c5cc07fc..0ebe369ea2 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -5,7 +5,30 @@ * @brief * * $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$ */ diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp index 4c22203eb9..18787c47c5 100644 --- a/indra/llprimitive/llmaterialtable.cpp +++ b/indra/llprimitive/llmaterialtable.cpp @@ -124,6 +124,17 @@ LLMaterialTable::~LLMaterialTable() mMaterialInfoList.clear(); } +void LLMaterialTable::initTableTransNames(std::map namemap) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + std::string name = infop->mName; + infop->mName = namemap[name]; + } +} + void LLMaterialTable::initBasicTable() { // *TODO: Translate diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h index ca9017abd0..2c0b046fa7 100644 --- a/indra/llprimitive/llmaterialtable.h +++ b/indra/llprimitive/llmaterialtable.h @@ -147,6 +147,8 @@ public: void initBasicTable(); + void initTableTransNames(std::map namemap); + BOOL add(U8 mcode, const std::string& name, const LLUUID &uuid); BOOL addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid); BOOL addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index c25df0a40f..b3a337ce5d 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -37,7 +37,7 @@ #include "v3math.h" #include "xform.h" #include "message.h" -#include "llmemory.h" +#include "llpointer.h" #include "llvolume.h" #include "lltextureentry.h" #include "llprimtexturelist.h" diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index c9632ebdad..d03150fc78 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2007, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 61285bd1bf..6254878b99 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2007, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index f6321b0534..052510e6ed 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index e5c09f8826..4beea0d026 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index beecb6b7c1..048bfe8e0d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -32,16 +32,20 @@ #include "linden_common.h" -#include +#include "llfontgl.h" +// Linden library includes #include "llfont.h" -#include "llfontgl.h" #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" +#include "llimagegl.h" #include "llrender.h" -#include "v4color.h" #include "llstl.h" +#include "v4color.h" + +// Third party library includes +#include const S32 BOLD_OFFSET = 1; @@ -102,14 +106,6 @@ U8 LLFontGL::getStyleFromString(const std::string &style) { ret |= UNDERLINE; } - if (style.find("SHADOW") != style.npos) - { - ret |= DROP_SHADOW; - } - if (style.find("SOFT_SHADOW") != style.npos) - { - ret |= DROP_SHADOW_SOFT; - } return ret; } @@ -215,11 +211,11 @@ bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) } // static -BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, - const std::vector& xui_paths) + const std::vector& xui_paths, + bool create_gl_textures) { - bool succ = true; sVertDPI = (F32)llfloor(screen_dpi * y_scale); sHorizDPI = (F32)llfloor(screen_dpi * x_scale); sScaleX = x_scale; @@ -229,24 +225,30 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, // Font registry init if (!sFontRegistry) { - sFontRegistry = new LLFontRegistry(xui_paths); + sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); sFontRegistry->parseFontInfo("fonts.xml"); } else { sFontRegistry->reset(); } +} - // Force standard fonts to get generated up front. - // This is primarily for error detection purposes. - succ &= (NULL != getFontSansSerifSmall()); - succ &= (NULL != getFontSansSerif()); - succ &= (NULL != getFontSansSerifBig()); - succ &= (NULL != getFontSansSerifHuge()); - succ &= (NULL != getFontSansSerifBold()); - succ &= (NULL != getFontMonospace()); +// Force standard fonts to get generated up front. +// This is primarily for error detection purposes. +// Don't do this during initClass because it can be slow and we want to get +// the viewer window on screen first. JC +// static +bool LLFontGL::loadDefaultFonts() +{ + bool succ = true; + succ &= (NULL != getFontSansSerifSmall()); + succ &= (NULL != getFontSansSerif()); + succ &= (NULL != getFontSansSerifBig()); + succ &= (NULL != getFontSansSerifHuge()); + succ &= (NULL != getFontSansSerifBold()); + succ &= (NULL != getFontMonospace()); succ &= (NULL != getFontExtChar()); - return succ; } @@ -341,6 +343,34 @@ LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) return sFontRegistry->getFont(desc); } +//static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ + // check for most common fonts first + if (name == "SANSSERIF") + { + return getFontSansSerif(); + } + else if (name == "SANSSERIF_SMALL") + { + return getFontSansSerifSmall(); + } + else if (name == "SANSSERIF_BIG") + { + return getFontSansSerifBig(); + } + else if (name == "SMALL" || name == "OCRA") + { + // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore? + // Does "SMALL" mean "SERIF"? + return getFontMonospace(); + } + else + { + return NULL; + } +} + BOOL LLFontGL::addChar(const llwchar wch) const { if (!LLFont::addChar(wch)) @@ -364,12 +394,13 @@ S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, + ShadowType shadow, const S32 max_chars, const S32 max_pixels, F32* right_x, BOOL use_ellipses) const { LLWString wstr = utf8str_to_wstring(text); - return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses); + return render(wstr, offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); } S32 LLFontGL::render(const LLWString &wstr, @@ -378,6 +409,7 @@ S32 LLFontGL::render(const LLWString &wstr, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, + ShadowType shadow, const S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, @@ -401,14 +433,14 @@ S32 LLFontGL::render(const LLWString &wstr, style = style & (~getFontDesc().getStyle()); F32 drop_shadow_strength = 0.f; - if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) + if (shadow != NO_SHADOW) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { - style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT); + shadow = NO_SHADOW; } } @@ -547,7 +579,7 @@ S32 LLFontGL::render(const LLWString &wstr, LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); - drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength); if (!label.empty()) { @@ -559,7 +591,7 @@ S32 LLFontGL::render(const LLWString &wstr, /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), /*llfloor*/(cur_y / sScaleY), color, - halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL, + halign, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, TRUE ); gGL.popMatrix(); } @@ -613,7 +645,7 @@ S32 LLFontGL::render(const LLWString &wstr, llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); - drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -671,6 +703,7 @@ S32 LLFontGL::render(const LLWString &wstr, color, LEFT, valign, style, + shadow, S32_MAX, max_pixels, right_x, FALSE); @@ -838,13 +871,28 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch { if (iswspace(wch)) { - in_word = FALSE; + if(wch !=(0x00A0)) + { + in_word = FALSE; + } + } + if (iswindividual(wch)) + { + if (iswpunct(wchars[i+1])) + { + in_word=TRUE; + } + else + { + in_word=FALSE; + start_of_last_word = i; + } } } else { start_of_last_word = i; - if (!iswspace(wch)) + if (!iswspace(wch)||!iswindividual(wch)) { in_word = TRUE; } @@ -1108,7 +1156,7 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3 llfont_round_y(screen_rect.mBottom)); } -void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const +void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const { F32 slant_offset; slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); @@ -1128,7 +1176,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con renderQuad(screen_rect_offset, uv_rect, slant_offset); } } - else if (style & DROP_SHADOW_SOFT) + else if (shadow == DROP_SHADOW_SOFT) { LLColor4 shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH; @@ -1161,7 +1209,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con gGL.color4fv(color.mV); renderQuad(screen_rect, uv_rect, slant_offset); } - else if (style & DROP_SHADOW) + else if (shadow == DROP_SHADOW) { LLColor4 shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength; diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 6cb1727ff4..204c6908af 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -34,16 +34,15 @@ #ifndef LL_LLFONTGL_H #define LL_LLFONTGL_H -#include "llfont.h" -#include "llimagegl.h" -#include "v2math.h" #include "llcoord.h" -#include "llrect.h" - +#include "llfont.h" #include "llfontregistry.h" +#include "llpointer.h" +#include "llrect.h" +#include "v2math.h" class LLColor4; - +class LLImageGL; // Key used to request a font. class LLFontDescriptor; @@ -73,12 +72,18 @@ public: enum StyleFlags { // text style to render. May be combined (these are bit flags) + // TODO:: Maybe change the value to 0x01 << 0 for 1 0x01 << 1 for 2, 0x01 << 2 for 4 NORMAL = 0, BOLD = 1, ITALIC = 2, - UNDERLINE = 4, - DROP_SHADOW = 8, - DROP_SHADOW_SOFT = 16 + UNDERLINE = 4 + }; + + enum ShadowType + { + NO_SHADOW, + DROP_SHADOW, + DROP_SHADOW_SOFT }; // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" @@ -93,10 +98,14 @@ public: LLFontGL &operator=(const LLFontGL &source); - static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, - const std::vector& xui_paths); + const std::vector& xui_paths, + bool create_gl_textures = true); + // Load sans-serif, sans-serif-small, etc. + // Slow, requires multiple seconds to load fonts. + static bool loadDefaultFonts(); static void destroyDefaultFonts(); static void destroyAllGL(); void destroyGL(); @@ -111,17 +120,17 @@ public: const LLColor4 &color) const { return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - LEFT, BASELINE, NORMAL, - S32_MAX, S32_MAX, NULL, FALSE); + LEFT, BASELINE, NORMAL, NO_SHADOW, + S32_MAX, S32_MAX, NULL, FALSE); } S32 renderUTF8(const std::string &text, const S32 begin_offset, S32 x, S32 y, const LLColor4 &color, - HAlign halign, VAlign valign, U8 style = NORMAL) const + HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const { return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - halign, valign, style, + halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE); } @@ -133,6 +142,7 @@ public: HAlign halign, VAlign valign, U8 style, + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, @@ -143,7 +153,7 @@ public: const LLColor4 &color) const { return render(text, begin_offset, x, y, color, - LEFT, BASELINE, NORMAL, + LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE); } @@ -155,6 +165,7 @@ public: HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL, + ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, @@ -220,7 +231,7 @@ protected: F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; void clearEmbeddedChars(); void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; - void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const; + void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; public: static F32 sVertDPI; @@ -238,6 +249,8 @@ public: static LLFontGL* getFontSansSerifBold(); static LLFontGL* getFontExtChar(); static LLFontGL* getFont(const LLFontDescriptor& desc); + // Use with legacy names like "SANSSERIF_SMALL" or "OCRA" + static LLFontGL* getFontByName(const std::string& name); static LLColor4 sShadowColor; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 9b5bc5d0af..18e4a6915d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,12 +13,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, @@ -167,7 +168,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); } -LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths) +LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths, + bool create_gl_textures) +: mCreateGLTextures(create_gl_textures) { // Propagate this down from LLUICtrlFactory so LLRender doesn't // need an upstream dependency on LLUI. @@ -215,8 +218,8 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) success = success || init_succ; } } - if (success) - dump(); + //if (success) + // dump(); return success; } @@ -426,7 +429,9 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) { LLFontGL *fontp = new LLFontGL; std::string font_path = local_path + *file_name_it; - BOOL is_fallback = !is_first_found; + // *HACK: Fallback fonts don't render, so we can use that to suppress + // creation of OpenGL textures for test apps. JC + BOOL is_fallback = !is_first_found || !mCreateGLTextures; F32 extra_scale = (is_fallback)?fallback_scale:1.0; if (!fontp->loadFace(font_path, extra_scale * point_size, LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index ed775eeed0..198ca0b920 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,12 +13,13 @@ * ("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 + * 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://secondlife.com/developers/opensource/flossexception + * 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, @@ -70,7 +71,10 @@ private: class LLFontRegistry { public: - LLFontRegistry(const string_vec_t& xui_paths); + // create_gl_textures - set to false for test apps with no OpenGL window, + // such as llui_libtest + LLFontRegistry(const string_vec_t& xui_paths, + bool create_gl_textures); ~LLFontRegistry(); // Load standard font info from XML file(s). @@ -108,6 +112,7 @@ private: string_vec_t mUltimateFallbackList; string_vec_t mXUIPaths; + bool mCreateGLTextures; }; #endif // LL_LLFONTREGISTRY_H diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 4f737bcaae..53b0b70cae 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,7 +37,8 @@ #include "llimage.h" #include "llgltypes.h" -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "v2math.h" #include "llrender.h" diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 437c715c2f..5b52fa1a52 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -44,7 +44,7 @@ #include "v3math.h" #include "v4coloru.h" #include "llstrider.h" -#include "llmemory.h" +#include "llpointer.h" #include "llglheaders.h" class LLVertexBuffer; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 5d88ea464d..fc2a6954c3 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -37,7 +37,6 @@ #include "llvertexbuffer.h" // #include "llrender.h" #include "llglheaders.h" -#include "llmemory.h" #include "llmemtype.h" #include "llrender.h" diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index aad948e17f..b785a22976 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -39,7 +39,6 @@ #include "v4math.h" #include "v4coloru.h" #include "llstrider.h" -#include "llmemory.h" #include "llrender.h" #include #include diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 5de8dc76af..f3595a7b05 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -31,17 +31,25 @@ set(llui_SOURCE_FILES llcheckboxctrl.cpp llclipboard.cpp llcombobox.cpp + llconsole.cpp + llcontainerview.cpp llctrlselectioninterface.cpp lldraghandle.cpp lleditmenuhandler.cpp + llf32uictrl.cpp llfloater.cpp + llfloaterreg.cpp + llflyoutbutton.cpp llfocusmgr.cpp llfunctorregistry.cpp lliconctrl.cpp + llinitparam.cpp llkeywords.cpp + lllayoutstack.cpp lllineeditor.cpp llmenugl.cpp llmodaldialog.cpp + llmultifloater.cpp llmultislider.cpp llmultisliderctrl.cpp llnotifications.cpp @@ -51,27 +59,35 @@ set(llui_SOURCE_FILES llresizebar.cpp llresizehandle.cpp llresmgr.cpp - llrootview.cpp llscrollbar.cpp llscrollcontainer.cpp llscrollingpanellist.cpp + llscrolllistcell.cpp + llscrolllistcolumn.cpp llscrolllistctrl.cpp + llscrolllistitem.cpp + llsdparam.cpp + llsearcheditor.cpp llslider.cpp llsliderctrl.cpp llspinctrl.cpp + llstatbar.cpp + llstatgraph.cpp + llstatview.cpp llstyle.cpp lltabcontainer.cpp - lltabcontainervertical.cpp lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltrans.cpp llui.cpp lluictrl.cpp lluictrlfactory.cpp + lluiimage.cpp lluistring.cpp - lluitrans.cpp llundo.cpp llviewborder.cpp + llviewmodel.cpp llview.cpp llviewquery.cpp ) @@ -85,52 +101,68 @@ set(llui_HEADER_FILES llcheckboxctrl.h llclipboard.h llcombobox.h + llconsole.h + llcontainerview.h llctrlselectioninterface.h lldraghandle.h lleditmenuhandler.h + llf32uictrl.h llfloater.h + llfloaterreg.h + llflyoutbutton.h llfocusmgr.h llfunctorregistry.h llhtmlhelp.h lliconctrl.h + llinitparam.h llkeywords.h + lllayoutstack.h + lllazyvalue.h lllineeditor.h - llmemberlistener.h llmenugl.h llmodaldialog.h + llmultifloater.h llmultisliderctrl.h llmultislider.h llnotifications.h llpanel.h llprogressbar.h llradiogroup.h + llregistry.h llresizebar.h llresizehandle.h llresmgr.h - llrootview.h + llsearcheditor.h llscrollbar.h llscrollcontainer.h llscrollingpanellist.h + llscrolllistcell.h + llscrolllistcolumn.h llscrolllistctrl.h + llscrolllistitem.h + llsdparam.h llsliderctrl.h llslider.h llspinctrl.h + llstatbar.h + llstatgraph.h + llstatview.h llstyle.h lltabcontainer.h - lltabcontainervertical.h lltextbox.h lltexteditor.h lltextparser.h + lltrans.h lluiconstants.h lluictrlfactory.h lluictrl.h lluifwd.h llui.h + lluiimage.h lluistring.h - lluitrans.h - lluixmltags.h llundo.h llviewborder.h + llviewmodel.h llview.h llviewquery.h ) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 2c2c1c25d8..1f6cd6ddf9 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -32,6 +32,7 @@ #include "linden_common.h" +#define INSTANTIATE_GETCHILD_BUTTON #include "llbutton.h" // Linden library includes @@ -45,183 +46,167 @@ #include "lluiconstants.h" #include "llresmgr.h" #include "llcriticaldamp.h" +#include "llfloater.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llwindow.h" #include "llrender.h" +#include "lluictrlfactory.h" static LLRegisterWidget r("button"); // globals loaded from settings.xml -S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI S32 LLBUTTON_H_PAD = 0; S32 LLBUTTON_V_PAD = 0; S32 BTN_HEIGHT_SMALL= 0; S32 BTN_HEIGHT = 0; -S32 BTN_GRID = 12; -S32 BORDER_SIZE = 1; - -LLButton::LLButton( const std::string& name, const LLRect& rect, const std::string& control_name, void (*click_callback)(void*), void *callback_data) -: LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), - mMouseDownFrame( 0 ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mHoverGlowStrength(0.15f), - mCurGlowStrength(0.f), - mNeedsHighlight(FALSE), - mCommitOnReturn(TRUE), - mImagep( NULL ) +template LLButton* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; + +LLButton::Params::Params() +: label_selected("label_selected"), // requires is_toggle true + label_dropshadow("label_shadow", true), + auto_resize("auto_resize", false), + image_unselected("image_unselected"), + image_selected("image_selected"), + image_hover_selected("image_hover_selected"), + image_hover_unselected("image_hover_unselected"), + image_disabled_selected("image_disabled_selected"), + image_disabled("image_disabled"), + image_overlay("image_overlay"), + image_overlay_alignment("image_overlay_alignment", std::string("center")), + label_color("label_color"), + label_color_selected("label_color_selected"), // requires is_toggle true + label_color_disabled("label_color_disabled"), + label_color_disabled_selected("label_color_disabled_selected"), + highlight_color("highlight_color"), + image_color("image_color"), + image_color_disabled("image_color_disabled"), + image_overlay_color("image_overlay_color", LLColor4::white), + flash_color("flash_color"), + pad_right("pad_right", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), + pad_left("pad_left", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), + click_callback("click_callback"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + mouse_held_callback("mouse_held_callback"), + mouse_held_once_callback("mouse_held_once_callback"), + is_toggle("is_toggle", false), + scale_image("scale_image", true), + help_url("help_url"), + hover_glow_amount("hover_glow_amount"), + commit_on_return("commit_on_return", true), + picture_style("picture_style", false) { - mUnselectedLabel = name; - mSelectedLabel = name; - - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); - - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - - init(click_callback, callback_data, NULL, control_name); + addSynonym(is_toggle, "toggle"); + held_down_delay.seconds = 0.5f; + initial_value.set(LLSD(false), false); } -LLButton::LLButton(const std::string& name, const LLRect& rect, - const std::string &unselected_image_name, - const std::string &selected_image_name, - const std::string& control_name, - void (*click_callback)(void*), - void *callback_data, - const LLFontGL *font, - const std::string& unselected_label, - const std::string& selected_label ) -: LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), - mMouseDownFrame( 0 ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), +LLButton::LLButton(const LLButton::Params& p) +: LLUICtrl(p), + mMouseDownFrame(0), + mMouseHeldDownCount(0), mBorderEnabled( FALSE ), mFlashing( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mHoverGlowStrength(0.25f), mCurGlowStrength(0.f), mNeedsHighlight(FALSE), - mCommitOnReturn(TRUE), - mImagep( NULL ) + mImagep( NULL ), + mUnselectedLabel(p.label()), + mSelectedLabel(p.label_selected()), + mGLFont(p.font), + mHeldDownDelay(p.held_down_delay.seconds), // seconds until held-down callback is called + mHeldDownFrameDelay(p.held_down_delay.frames), + mImageUnselected(p.image_unselected), + mImageSelected(p.image_selected), + mImageDisabled(p.image_disabled), + mImageDisabledSelected(p.image_disabled_selected), + mImageHoverSelected(p.image_hover_selected), + mImageHoverUnselected(p.image_hover_unselected), + mUnselectedLabelColor(p.label_color()), + mSelectedLabelColor(p.label_color_selected()), + mDisabledLabelColor(p.label_color_disabled()), + mDisabledSelectedLabelColor(p.label_color_disabled_selected()), + mHighlightColor(p.highlight_color()), + mImageColor(p.image_color()), + mFlashBgColor(p.flash_color()), + mDisabledImageColor(p.image_color_disabled()), + mImageOverlay(p.image_overlay()), + mImageOverlayColor(p.image_overlay_color()), + mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), + mIsToggle(p.is_toggle), + mScaleImage(p.scale_image), + mDropShadowedText(p.label_dropshadow), + mAutoResize(p.auto_resize), + mHAlign(p.font_halign), + mLeftHPad(p.pad_left), + mRightHPad(p.pad_right), + mHoverGlowStrength(p.hover_glow_amount), + mCommitOnReturn(p.commit_on_return), + mFadeWhenDisabled(FALSE) { - mUnselectedLabel = unselected_label; - mSelectedLabel = selected_label; + static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); + static LLButton::Params default_params(LLUICtrlFactory::getDefaultParams()); - // by default, disabled color is same as enabled - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - - if( unselected_image_name != "" ) - { - // user-specified image - don't use fixed borders unless requested - setImageUnselected(unselected_image_name); - setImageDisabled(unselected_image_name); - - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else + //if we aren't a picture_style button set label as name if not provided + if (!p.picture_style.isProvided() || !p.picture_style) { - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); - } - - if( selected_image_name != "" ) - { - // user-specified image - don't use fixed borders unless requested - setImageSelected(selected_image_name); - setImageDisabledSelected(selected_image_name); - - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else - { - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); + if (!p.label.isProvided()) + { + mUnselectedLabel = p.name(); + } + if (!p.label_selected.isProvided()) + { + mSelectedLabel = mUnselectedLabel.getString(); + } } - init(click_callback, callback_data, font, control_name); -} - -void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name) -{ - mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); - // Hack to make sure there is space for at least one character if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { // Use old defaults - mLeftHPad = LLBUTTON_ORIG_H_PAD; - mRightHPad = LLBUTTON_ORIG_H_PAD; + mLeftHPad = llbutton_orig_h_pad; + mRightHPad = llbutton_orig_h_pad; } - mCallbackUserData = callback_data; mMouseDownTimer.stop(); - setControlName(control_name, NULL); - - mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) ); - mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) ); - mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) ); - mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) ); - mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) ); - mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) ); - mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) ); - mFlashBgColor = ( LLUI::sColorsGroup->getColor( "ButtonFlashBgColor" ) ); + if (p.help_url.isProvided()) + { + setHelpURLCallback(p.help_url); + } - mImageOverlayAlignment = LLFontGL::HCENTER; - mImageOverlayColor = LLColor4::white; -} + // if custom unselected button image provided... + if (p.image_unselected != default_params.image_unselected) + { + //...fade it out for disabled image by default... + if (p.image_disabled() == default_params.image_disabled() ) + { + mImageDisabled = p.image_unselected; + mFadeWhenDisabled = TRUE; + } + } -LLButton::~LLButton() -{ - if( hasMouseCapture() ) + // if custom selected button image provided... + if (p.image_selected != default_params.image_selected) { - gFocusMgr.setMouseCapture( NULL ); + //...fade it out for disabled image by default... + if (p.image_disabled_selected() == default_params.image_disabled_selected()) + { + mImageDisabledSelected = p.image_selected; + mFadeWhenDisabled = TRUE; + } } + + if (p.click_callback.isProvided()) + initCommitCallback(p.click_callback, mCommitSignal); // alias -> commit_callback + if (p.mouse_down_callback.isProvided()) + initCommitCallback(p.mouse_down_callback, mMouseDownSignal); + if (p.mouse_up_callback.isProvided()) + initCommitCallback(p.mouse_up_callback, mMouseUpSignal); + if (p.mouse_held_callback.isProvided()) + initCommitCallback(p.mouse_held_callback, mHeldDownSignal); } // HACK: Committing a button is the same as instantly clicking it. @@ -229,19 +214,12 @@ LLButton::~LLButton() void LLButton::onCommit() { // WARNING: Sometimes clicking a button destroys the floater or - // panel containing it. Therefore we need to call mClickedCallback + // panel containing it. Therefore we need to call LLUICtrl::onCommit() // LAST, otherwise this becomes deleted memory. - LLUICtrl::onCommit(); - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + mMouseDownSignal(this, LLSD()); - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + mMouseUpSignal(this, LLSD()); if (getSoundFlags() & MOUSE_DOWN) { @@ -259,14 +237,49 @@ void LLButton::onCommit() } // do this last, as it can result in destroying this button - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } +boost::signals::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb ) +{ + return mCommitSignal.connect(cb); +} +boost::signals::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + return mMouseDownSignal.connect(cb); +} +boost::signals::connection LLButton::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + return mMouseUpSignal.connect(cb); +} +boost::signals::connection LLButton::setHeldDownCallback( const commit_signal_t::slot_type& cb ) +{ + return mHeldDownSignal.connect(cb); +} +// *TODO: Deprecate (for backwards compatability only) +boost::signals::connection LLButton::setClickedCallback( button_callback_t cb, void* data ) +{ + return setClickedCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setMouseDownCallback( button_callback_t cb, void* data ) +{ + return setMouseDownCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setMouseUpCallback( button_callback_t cb, void* data ) +{ + return setMouseUpCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setHeldDownCallback( button_callback_t cb, void* data ) +{ + return setHeldDownCallback(boost::bind(cb, data)); +} +BOOL LLButton::postBuild() +{ + autoResize(); + return TRUE; +} BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) { BOOL handled = FALSE; @@ -278,10 +291,8 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); + handled = TRUE; } return handled; @@ -299,10 +310,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask ) handled = TRUE; - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } return handled; } @@ -318,13 +326,11 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); } - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + mMouseDownSignal(this, LLSD()); mMouseDownTimer.start(); mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseHeldDownCount = 0; if (getSoundFlags() & MOUSE_DOWN) { @@ -344,13 +350,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) gFocusMgr.setMouseCapture( NULL ); // Regardless of where mouseup occurs, handle callback - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + mMouseUpSignal(this, LLSD()); - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + resetMouseDownTimer(); // 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 @@ -366,10 +368,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } } @@ -377,20 +376,27 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) } -BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) +void LLButton::onMouseEnter(S32 x, S32 y, MASK mask) { - LLMouseHandler* other_captor = gFocusMgr.getMouseCapture(); - mNeedsHighlight = other_captor == NULL || - other_captor == this || - // this following bit is to support modal dialogs - (other_captor->isView() && hasAncestor((LLView*)other_captor)); + if (getEnabled()) + mNeedsHighlight = TRUE; +} - if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) +void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mNeedsHighlight = FALSE; +} + +BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) +{ + if (mMouseDownTimer.getStarted()) { F32 elapsed = getHeldDownTime(); if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) { - mHeldDownCallback( mCallbackUserData ); + LLSD param; + param["count"] = mMouseHeldDownCount++; + mHeldDownSignal(this, param); } } @@ -406,12 +412,15 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) void LLButton::draw() { BOOL flash = FALSE; + static LLUICachedControl button_flash_rate("ButtonFlashRate", 0); + static LLUICachedControl button_flash_count("ButtonFlashCount", 0); + if( mFlashing ) { F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f); + S32 flash_count = S32(elapsed * button_flash_rate * 2.f); // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)LLUI::sConfigGroup->getS32("ButtonFlashCount") * 2.f); + flash = (flash_count % 2 == 0) || flash_count > S32((F32)button_flash_count * 2.f); } BOOL pressed_by_keyboard = FALSE; @@ -427,7 +436,7 @@ void LLButton::draw() BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) - || mToggleState; + || getToggleState(); BOOL use_glow_effect = FALSE; LLColor4 glow_color = LLColor4::white; @@ -470,12 +479,14 @@ void LLButton::draw() if (mFlashing) { + LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow + if (mNeedsHighlight) // highlighted AND flashing - glow_color = (glow_color*0.5f + mFlashBgColor*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity + glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity else - glow_color = mFlashBgColor; + glow_color = flash_color; } // Override if more data is available @@ -508,31 +519,31 @@ void LLButton::draw() // label changes when button state changes, not when pressed if ( getEnabled() ) { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mSelectedLabelColor; + label_color = mSelectedLabelColor.get(); } else { - label_color = mUnselectedLabelColor; + label_color = mUnselectedLabelColor.get(); } } else { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mDisabledSelectedLabelColor; + label_color = mDisabledSelectedLabelColor.get(); } else { - label_color = mDisabledLabelColor; + label_color = mDisabledLabelColor.get(); } } // Unselected label assignments LLWString label; - if( mToggleState ) + if( getToggleState() ) { if( getEnabled() || mDisabledSelectedLabel.empty() ) { @@ -578,9 +589,11 @@ void LLButton::draw() // Otherwise draw basic rectangular button. if (mImagep.notNull()) { + // apply automatic 50% alpha fade to disabled image + LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); if ( mScaleImage) { - mImagep->draw(getLocalRect(), getEnabled() ? mImageColor : mDisabledImageColor ); + mImagep->draw(getLocalRect(), getEnabled() ? mImageColor.get() : disabled_color ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); @@ -590,7 +603,7 @@ void LLButton::draw() } else { - mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor ); + mImagep->draw(0, 0, getEnabled() ? mImageColor.get() : disabled_color ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); @@ -634,7 +647,7 @@ void LLButton::draw() } // fade out overlay images on disabled buttons - LLColor4 overlay_color = mImageOverlayColor; + LLColor4 overlay_color = mImageOverlayColor.get(); if (!getEnabled()) { overlay_color.mV[VALPHA] = 0.5f; @@ -707,23 +720,18 @@ void LLButton::draw() mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), label_color, mHAlign, LLFontGL::BOTTOM, - mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL, + LLFontGL::NORMAL, + mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, U32_MAX, text_width, NULL, FALSE, FALSE); } - if (sDebugRects - || (LLView::sEditingUI && this == LLView::sEditingUIView)) - { - drawDebugRect(); - } - - // reset hover status for next frame - mNeedsHighlight = FALSE; + LLView::draw(); } void LLButton::drawBorder(const LLColor4& color, S32 size) { + if (mImagep.isNull()) return; if (mScaleImage) { mImagep->drawBorder(getLocalRect(), color, size); @@ -734,22 +742,19 @@ void LLButton::drawBorder(const LLColor4& color, S32 size) } } -void LLButton::setClickedCallback(void (*cb)(void*), void* userdata) +BOOL LLButton::getToggleState() const { - mClickedCallback = cb; - if (userdata) - { - mCallbackUserData = userdata; - } + return getValue().asBoolean(); } - void LLButton::setToggleState(BOOL b) { - if( b != mToggleState ) + if( b != getToggleState() ) { setControlValue(b); // will fire LLControlVariable callbacks (if any) - mToggleState = b; // may or may not be redundant + setValue(b); // may or may not be redundant + // Unselected label assignments + autoResize(); } } @@ -764,19 +769,11 @@ void LLButton::setFlashing( BOOL b ) BOOL LLButton::toggleState() -{ - setToggleState( !mToggleState ); - return mToggleState; -} - -void LLButton::setValue(const LLSD& value ) { - mToggleState = value.asBoolean(); -} + bool flipped = ! getToggleState(); + setToggleState(flipped); -LLSD LLButton::getValue() const -{ - return mToggleState == TRUE; + return flipped; } void LLButton::setLabel( const LLStringExplicit& label ) @@ -818,6 +815,49 @@ void LLButton::setImageUnselected(LLPointer image) mImageUnselected = image; } +void LLButton::autoResize() +{ + LLUIString label; + if(getToggleState()) + { + if( getEnabled() || mDisabledSelectedLabel.empty() ) + { + label = mSelectedLabel; + } + else + { + label = mDisabledSelectedLabel; + } + } + else + { + if( getEnabled() || mDisabledLabel.empty() ) + { + label = mUnselectedLabel; + } + else + { + label = mDisabledLabel; + } + } + resize(label); +} + +void LLButton::resize(LLUIString label) +{ + // get label length + S32 label_width = mGLFont->getWidth(label.getString()); + // get current btn length + S32 btn_width =getRect().getWidth(); + // check if it need resize + if (mAutoResize == TRUE) + { + if (btn_width - (mRightHPad + mLeftHPad) < label_width) + { + setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight+ label_width + mLeftHPad + mRightHPad , getRect().mBottom)); + } + } +} void LLButton::setImages( const std::string &image_name, const std::string &selected_name ) { setImageUnselected(image_name); @@ -845,14 +885,20 @@ void LLButton::setImageDisabled(LLPointer image) { mImageDisabled = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; + mFadeWhenDisabled = TRUE; } void LLButton::setImageDisabledSelected(LLPointer image) { mImageDisabledSelected = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; + mFadeWhenDisabled = TRUE; +} + +void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name) +{ + setDisabledImages( image_name, selected_name, mImageColor.get()); + mFadeWhenDisabled = TRUE; } void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name, const LLColor4& c ) @@ -867,13 +913,6 @@ void LLButton::setImageHoverSelected(LLPointer image) mImageHoverSelected = image; } -void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name) -{ - LLColor4 clr = mImageColor; - clr.mV[VALPHA] *= .5f; - setDisabledImages( image_name, selected_name, clr ); -} - void LLButton::setImageHoverUnselected(LLPointer image) { mImageHoverUnselected = image; @@ -899,11 +938,9 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a } } - void LLButton::onMouseCaptureLost() { - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + resetMouseDownTimer(); } //------------------------------------------------------------------------- @@ -975,28 +1012,6 @@ void LLButton::addImageAttributeToXML(LLXMLNodePtr node, } } -// virtual -LLXMLNodePtr LLButton::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->createChild("label", TRUE)->setStringValue(getLabelUnselected()); - node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected()); - node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); - node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); - - addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,std::string("image_unselected")); - addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,std::string("image_selected")); - addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,std::string("image_hover_selected")); - addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,std::string("image_hover_unselected")); - addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,std::string("image_disabled")); - addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,std::string("image_disabled_selected")); - - node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage); - - return node; -} - void clicked_help(void* data) { LLButton* self = (LLButton*)data; @@ -1010,114 +1025,53 @@ void clicked_help(void* data) LLUI::sHtmlHelp->show(self->getHelpURL()); } -// static -LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +void LLButton::setHelpURLCallback(const std::string &help_url) { - std::string name("button"); - node->getAttributeString("name", name); - - std::string label = name; - node->getAttributeString("label", label); - - std::string label_selected = label; - node->getAttributeString("label_selected", label_selected); - - LLFontGL* font = selectFont(node); - - std::string image_unselected; - if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected); - - std::string image_selected; - if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected); - - std::string image_hover_selected; - if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected); - - std::string image_hover_unselected; - if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected); - - std::string image_disabled_selected; - if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected); - - std::string image_disabled; - if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled); - - std::string image_overlay; - node->getAttributeString("image_overlay", image_overlay); - - LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER; - std::string image_overlay_alignment_string; - if (node->hasAttribute("image_overlay_alignment")) - { - node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string); - image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string); - } - - - LLButton *button = new LLButton(name, - LLRect(), - image_unselected, - image_selected, - LLStringUtil::null, - NULL, - parent, - font, - label, - label_selected); - - node->getAttributeS32("pad_right", button->mRightHPad); - node->getAttributeS32("pad_left", button->mLeftHPad); + mHelpURL = help_url; + setClickedCallback(clicked_help,this); +} - BOOL is_toggle = button->getIsToggle(); - node->getAttributeBOOL("toggle", is_toggle); - button->setIsToggle(is_toggle); +// static +void LLButton::toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname) +{ + bool floater_vis = LLFloaterReg::toggleInstance(sdname.asString()); + LLButton* button = dynamic_cast(ctrl); + if (button) + button->setToggleState(floater_vis); +} - if(image_hover_selected != LLStringUtil::null) button->setImageHoverSelected(image_hover_selected); - - if(image_hover_unselected != LLStringUtil::null) button->setImageHoverUnselected(image_hover_unselected); - - if(image_disabled_selected != LLStringUtil::null) button->setImageDisabledSelected(image_disabled_selected ); - - if(image_disabled != LLStringUtil::null) button->setImageDisabled(image_disabled); - - if(image_overlay != LLStringUtil::null) button->setImageOverlay(image_overlay, image_overlay_alignment); +// static +// Gets called once +void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname) +{ + LLButton* button = dynamic_cast(ctrl); + if (!button) + return; + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) + button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name)); + // Set the clicked callback to toggle the floater + button->setClickedCallback(boost::bind(&LLFloaterReg::toggleFloaterInstance, sdname)); +} - if (node->hasAttribute("halign")) - { - LLFontGL::HAlign halign = selectFontHAlign(node); - button->setHAlign(halign); - } +void LLButton::resetMouseDownTimer() +{ + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); +} - if (node->hasAttribute("scale_image")) - { - BOOL needsScale = FALSE; - node->getAttributeBOOL("scale_image",needsScale); - button->setScaleImage( needsScale ); - } - if(label.empty()) - { - button->setLabelUnselected(node->getTextContents()); - } - if (label_selected.empty()) - { - button->setLabelSelected(node->getTextContents()); - } - - if (node->hasAttribute("help_url")) +// *TODO: Remove this function after the initial XUI XML re-export pass. +// static +void LLButton::setupParamsForExport(Params& p, LLView* parent) +{ + std::string label = p.label; + if (label.empty()) { - std::string help_url; - node->getAttributeString("help_url",help_url); - button->setHelpURLCallback(help_url); + //if our label is empty this is a picture style button + p.picture_style = true; } - button->initFromXML(node, parent); - - return button; -} - -void LLButton::setHelpURLCallback(const std::string &help_url) -{ - mHelpURL = help_url; - setClickedCallback(clicked_help,this); + LLUICtrl::setupParamsForExport(p, parent); } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 724b77541a..f146ef9dc2 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -39,7 +39,7 @@ #include "v4color.h" #include "llframetimer.h" #include "llfontgl.h" -#include "llimage.h" +#include "lluiimage.h" #include "lluistring.h" // @@ -53,9 +53,6 @@ extern S32 LLBUTTON_V_PAD; extern S32 BTN_HEIGHT_SMALL; extern S32 BTN_HEIGHT; -// All button widths should be rounded up to this size -extern S32 BTN_GRID; - // // Helpful functions // @@ -72,36 +69,80 @@ class LLButton : public LLUICtrl { public: - // simple button with text label - LLButton(const std::string& name, const LLRect &rect, const std::string& control_name = std::string(), - void (*on_click)(void*) = NULL, void *data = NULL); - - LLButton(const std::string& name, const LLRect& rect, - const std::string &unselected_image, - const std::string &selected_image, - const std::string& control_name, - void (*click_callback)(void*), - void *callback_data = NULL, - const LLFontGL* mGLFont = NULL, - const std::string& unselected_label = LLStringUtil::null, - const std::string& selected_label = LLStringUtil::null ); - - virtual ~LLButton(); - void init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name); - + struct Params + : public LLInitParam::Block + { + // text label + Optional label_selected; + Optional label_dropshadow; + Optional auto_resize; + + // images + Optional image_unselected, + image_selected, + image_hover_selected, + image_hover_unselected, + image_disabled_selected, + image_disabled, + image_overlay; + + Optional image_overlay_alignment; + + // colors + Optional label_color, + label_color_selected, + label_color_disabled, + label_color_disabled_selected, + highlight_color, + image_color, + image_color_disabled, + image_overlay_color, + flash_color; + + // layout + Optional pad_right; + Optional pad_left; + + // callbacks + Optional click_callback, // alias -> commit_callback + mouse_down_callback, + mouse_up_callback, + mouse_held_callback, + mouse_held_once_callback; + + // misc + Optional is_toggle, + scale_image, + commit_on_return, + picture_style; //if true, don't display label + + Optional help_url; + Optional hover_glow_amount; + Optional held_down_delay; + + Params(); + }; +protected: + friend class LLUICtrlFactory; + LLButton(const Params&); + +public: + // For backward compatability only + typedef boost::function button_callback_t; + void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, const LLUUID& imageID,const std::string& xmlTagName) const; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual void draw(); + /*virtual*/ BOOL postBuild(); + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual void onMouseCaptureLost(); virtual void onCommit(); @@ -109,18 +150,24 @@ public: void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; } void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; } - void setClickedCallback( void (*cb)(void *data), void* data = NULL ); // mouse down and up within button - void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button - void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON - void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button + boost::signals::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button + boost::signals::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON + // Passes a 'count' parameter in the commit param payload, i.e. param["count"]) + boost::signals::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button + + // *TODO: Deprecate (for backwards compatability only) + boost::signals::connection setClickedCallback( button_callback_t cb, void* data ); + boost::signals::connection setMouseDownCallback( button_callback_t cb, void* data ); + boost::signals::connection setMouseUpCallback( button_callback_t cb, void* data ); + boost::signals::connection setHeldDownCallback( button_callback_t cb, void* data ); + void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } - + F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } - BOOL getIsToggle() const { return mIsToggle; } - void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; } BOOL toggleState(); - BOOL getToggleState() const { return mToggleState; } + BOOL getToggleState() const; void setToggleState(BOOL b); void setFlashing( BOOL b ); @@ -150,11 +197,9 @@ public: void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); LLPointer getImageOverlay() { return mImageOverlay; } - - - virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; + void autoResize(); // resize with label of current btn state + void resize(LLUIString label); // resize with label input void setLabel( const LLStringExplicit& label); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); void setLabelUnselected(const LLStringExplicit& label); @@ -172,8 +217,6 @@ public: void setBorderEnabled(BOOL b) { mBorderEnabled = b; } - static void onHeldDown(void *userdata); // to be called by gIdleCallbacks - void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } void setImageUnselected(const std::string &image_name); @@ -198,6 +241,10 @@ public: void setHelpURLCallback(const std::string &help_url); const std::string& getHelpURL() const { return mHelpURL; } + static void onHeldDown(void *userdata); // to be called by gIdleCallbacks + static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname); + static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); + protected: virtual void drawBorder(const LLColor4& color, S32 size); @@ -212,45 +259,48 @@ protected: void setImageDisabledSelectedID(const LLUUID &image_id); const LLPointer& getImageUnselected() const { return mImageUnselected; } const LLPointer& getImageSelected() const { return mImageSelected; } + void resetMouseDownTimer(); LLFrameTimer mMouseDownTimer; -private: - - void (*mClickedCallback)(void* data ); - void (*mMouseDownCallback)(void *data); - void (*mMouseUpCallback)(void *data); - void (*mHeldDownCallback)(void *data); + // If the label is empty, set the picture_style attribute + static void setupParamsForExport(Params& p, LLView* parent); +private: + commit_signal_t mMouseDownSignal; + commit_signal_t mMouseUpSignal; + commit_signal_t mHeldDownSignal; + const LLFontGL *mGLFont; S32 mMouseDownFrame; - F32 mHeldDownDelay; // seconds, after which held-down callbacks get called + S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback + F32 mHeldDownDelay; // seconds, after which held-down callbacks get called S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called - LLPointer mImageOverlay; - LLFontGL::HAlign mImageOverlayAlignment; - LLColor4 mImageOverlayColor; + LLPointer mImageOverlay; + LLFontGL::HAlign mImageOverlayAlignment; + LLUIColor mImageOverlayColor; - LLPointer mImageUnselected; - LLUIString mUnselectedLabel; - LLColor4 mUnselectedLabelColor; + LLPointer mImageUnselected; + LLUIString mUnselectedLabel; + LLUIColor mUnselectedLabelColor; - LLPointer mImageSelected; - LLUIString mSelectedLabel; - LLColor4 mSelectedLabelColor; + LLPointer mImageSelected; + LLUIString mSelectedLabel; + LLUIColor mSelectedLabelColor; - LLPointer mImageHoverSelected; + LLPointer mImageHoverSelected; - LLPointer mImageHoverUnselected; + LLPointer mImageHoverUnselected; - LLPointer mImageDisabled; - LLUIString mDisabledLabel; - LLColor4 mDisabledLabelColor; + LLPointer mImageDisabled; + LLUIString mDisabledLabel; + LLUIColor mDisabledLabelColor; - LLPointer mImageDisabledSelected; - LLUIString mDisabledSelectedLabel; - LLColor4 mDisabledSelectedLabelColor; + LLPointer mImageDisabledSelected; + LLUIString mDisabledSelectedLabel; + LLUIColor mDisabledSelectedLabelColor; LLUUID mImageUnselectedID; LLUUID mImageSelectedID; @@ -265,20 +315,17 @@ private: std::string mImageDisabledName; std::string mImageDisabledSelectedName; - LLColor4 mHighlightColor; - LLColor4 mUnselectedBgColor; - LLColor4 mSelectedBgColor; - LLColor4 mFlashBgColor; + LLUIColor mHighlightColor; + LLUIColor mFlashBgColor; - LLColor4 mImageColor; - LLColor4 mDisabledImageColor; + LLUIColor mImageColor; + LLUIColor mDisabledImageColor; BOOL mIsToggle; - BOOL mToggleState; BOOL mScaleImage; BOOL mDropShadowedText; - + BOOL mAutoResize; BOOL mBorderEnabled; BOOL mFlashing; @@ -292,6 +339,7 @@ private: BOOL mNeedsHighlight; BOOL mCommitOnReturn; + BOOL mFadeWhenDisabled; std::string mHelpURL; @@ -300,4 +348,11 @@ private: LLFrameTimer mFlashingTimer; }; +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_BUTTON +#pragma warning (disable : 4231) +extern template LLButton* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif + #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index eadb9c98f3..97b1e2fc50 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -30,11 +30,11 @@ * $/LicenseInfo$ */ -#ifndef LL_CALLBACK_MAP_H -#define LL_CALLBACK_MAP_H +#ifndef LLCALLBACKMAP_H +#define LLCALLBACKMAP_H #include -#include "llstring.h" +#include class LLCallbackMap { @@ -45,12 +45,19 @@ public: typedef std::map map_t; typedef map_t::iterator map_iter_t; typedef map_t::const_iterator map_const_iter_t; - + + template + static void* buildPanel(void* data) + { + T* panel = new T(); + return (void*)panel; + } + LLCallbackMap() : mCallback(NULL), mData(NULL) { } - LLCallbackMap(callback_t callback, void* data) : mCallback(callback), mData(data) { } + LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } callback_t mCallback; void* mData; }; -#endif // LL_CALLBACK_MAP_H +#endif // LLCALLBACKMAP_H diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index eda9467d87..7b37344db7 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -31,6 +31,7 @@ */ // The mutants are coming! +#define INSTANTIATE_GETCHILD_CHECKBOX #include "linden_common.h" @@ -49,101 +50,88 @@ const U32 MAX_STRING_LENGTH = 10; +template LLCheckBoxCtrl* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; + static LLRegisterWidget r("check_box"); - -LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, - const std::string& label, - const LLFontGL* font, - void (*commit_callback)(LLUICtrl* ctrl, void* userdata), - void* callback_user_data, - BOOL initial_value, - BOOL use_radio_style, - const std::string& control_which) -: LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data, FOLLOWS_LEFT | FOLLOWS_TOP), - mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), - mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), - mRadioStyle( use_radio_style ), - mInitialValue( initial_value ), - mSetValue( initial_value ) +LLCheckBoxCtrl::Params::Params() +: text_enabled_color("text_enabled_color"), + text_disabled_color("text_disabled_color"), + initial_value("initial_value", false), + label_text("label_text"), + check_button("check_button"), + radio_style("radio_style") +{} + + +LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) +: LLUICtrl(p), + mTextEnabledColor(p.text_enabled_color()), + mTextDisabledColor(p.text_disabled_color()), + mFont(p.font()) { - if (font) - { - mFont = font; - } - else - { - mFont = LLFontGL::getFontSansSerifSmall(); - } + mViewModel->setValue(LLSD(p.initial_value)); + mViewModel->resetDirty(); + static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); + static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); + static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); + static LLUICachedControl llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0); // must be big enough to hold all children setUseBoundingRect(TRUE); - mKeyboardFocusOnClick = TRUE; - // Label (add a little space to make sure text actually renders) const S32 FUDGE = 10; - S32 text_width = mFont->getWidth( label ) + FUDGE; + S32 text_width = mFont->getWidth( p.label ) + FUDGE; S32 text_height = llround(mFont->getLineHeight()); LLRect label_rect; label_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING, - LLCHECKBOXCTRL_VPAD + 1, // padding to get better alignment - text_width + LLCHECKBOXCTRL_HPAD, + llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing, + llcheckboxctrl_vpad + 1, // padding to get better alignment + text_width + llcheckboxctrl_hpad, text_height ); // *HACK Get rid of this with SL-55508... // this allows blank check boxes and radio boxes for now - std::string local_label = label; + std::string local_label = p.label; if(local_label.empty()) { local_label = " "; } - mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, local_label, mFont ); - mLabel->setFollowsLeft(); - mLabel->setFollowsBottom(); + LLTextBox::Params tbparams = p.label_text; + tbparams.rect(label_rect); + tbparams.text(local_label); + if (p.font.isProvided()) + { + tbparams.font(p.font); + } + mLabel = LLUICtrlFactory::create (tbparams); + addChild(mLabel); // Button // Note: button cover the label by extending all the way to the right. LLRect btn_rect; btn_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD, - LLCHECKBOXCTRL_VPAD, - LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width + LLCHECKBOXCTRL_HPAD, - llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) + LLCHECKBOXCTRL_VPAD); + llcheckboxctrl_hpad, + llcheckboxctrl_vpad, + llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width + llcheckboxctrl_hpad, + llmax( text_height, llcheckboxctrl_btn_size() ) + llcheckboxctrl_vpad); std::string active_true_id, active_false_id; std::string inactive_true_id, inactive_false_id; - if (mRadioStyle) - { - active_true_id = "UIImgRadioActiveSelectedUUID"; - active_false_id = "UIImgRadioActiveUUID"; - inactive_true_id = "UIImgRadioInactiveSelectedUUID"; - inactive_false_id = "UIImgRadioInactiveUUID"; - mButton = new LLButton(std::string("Radio control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } - else - { - active_false_id = "UIImgCheckboxActiveUUID"; - active_true_id = "UIImgCheckboxActiveSelectedUUID"; - inactive_true_id = "UIImgCheckboxInactiveSelectedUUID"; - inactive_false_id = "UIImgCheckboxInactiveUUID"; - mButton = new LLButton(std::string("Checkbox control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } - mButton->setIsToggle(TRUE); - mButton->setToggleState( initial_value ); - mButton->setFollowsLeft(); - mButton->setFollowsBottom(); - mButton->setCommitOnReturn(FALSE); + + LLButton::Params params = p.check_button; + params.rect(btn_rect); + //params.control_name(p.control_name); + params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2)); + params.commit_on_return(false); + // Checkboxes only allow boolean initial values, but buttons can + // take any LLSD. + params.initial_value(LLSD(p.initial_value)); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + + mButton = LLUICtrlFactory::create(params); addChild(mButton); } @@ -154,24 +142,14 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl() // static -void LLCheckBoxCtrl::onButtonPress( void *userdata ) +void LLCheckBoxCtrl::onButtonPress( const LLSD& data ) { - LLCheckBoxCtrl* self = (LLCheckBoxCtrl*) userdata; + //if (mRadioStyle) + //{ + // setValue(TRUE); + //} - if (self->mRadioStyle) - { - self->setValue(TRUE); - } - - self->setControlValue(self->getValue()); - // HACK: because buttons don't normally commit - self->onCommit(); - - if (self->mKeyboardFocusOnClick) - { - self->setFocus( TRUE ); - self->onFocusReceived(); - } + onCommit(); } void LLCheckBoxCtrl::onCommit() @@ -179,6 +157,7 @@ void LLCheckBoxCtrl::onCommit() if( getEnabled() ) { setTentative(FALSE); + setControlValue(getValue()); LLUICtrl::onCommit(); } } @@ -187,6 +166,15 @@ void LLCheckBoxCtrl::setEnabled(BOOL b) { LLView::setEnabled(b); mButton->setEnabled(b); + + if (b) + { + mLabel->setColor( mTextEnabledColor.get() ); + } + else + { + mLabel->setColor( mTextDisabledColor.get() ); + } } void LLCheckBoxCtrl::clear() @@ -197,43 +185,33 @@ void LLCheckBoxCtrl::clear() void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) { //stretch or shrink bounding rectangle of label when rebuilding UI at new scale + static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); + static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); + static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); + static LLUICachedControl llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0); + const S32 FUDGE = 10; S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE; S32 text_height = llround(mFont->getLineHeight()); LLRect label_rect; label_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING, - LLCHECKBOXCTRL_VPAD, + llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing, + llcheckboxctrl_vpad, text_width, text_height ); mLabel->setRect(label_rect); LLRect btn_rect; btn_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD, - LLCHECKBOXCTRL_VPAD, - LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width, - llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) ); + llcheckboxctrl_hpad, + llcheckboxctrl_vpad, + llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width, + llmax( text_height, llcheckboxctrl_btn_size() ) ); mButton->setRect( btn_rect ); LLUICtrl::reshape(width, height, called_from_parent); } -void LLCheckBoxCtrl::draw() -{ - if (getEnabled()) - { - mLabel->setColor( mTextEnabledColor ); - } - else - { - mLabel->setColor( mTextDisabledColor ); - } - - // Draw children - LLUICtrl::draw(); -} - //virtual void LLCheckBoxCtrl::setValue(const LLSD& value ) { @@ -246,6 +224,18 @@ LLSD LLCheckBoxCtrl::getValue() const return mButton->getValue(); } +//virtual +void LLCheckBoxCtrl::setTentative(BOOL b) +{ + mButton->setTentative(b); +} + +//virtual +BOOL LLCheckBoxCtrl::getTentative() const +{ + return mButton->getTentative(); +} + void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label ) { mLabel->setText( label ); @@ -264,12 +254,6 @@ BOOL LLCheckBoxCtrl::setLabelArg( const std::string& key, const LLStringExplicit return res; } -//virtual -std::string LLCheckBoxCtrl::getControlName() const -{ - return mButton->getControlName(); -} - // virtual void LLCheckBoxCtrl::setControlName(const std::string& control_name, LLView* context) { @@ -282,7 +266,7 @@ BOOL LLCheckBoxCtrl::isDirty() const { if ( mButton ) { - return (mSetValue != mButton->getToggleState()); + return mButton->isDirty(); } return FALSE; // Shouldn't get here } @@ -293,78 +277,6 @@ void LLCheckBoxCtrl::resetDirty() { if ( mButton ) { - mSetValue = mButton->getToggleState(); - } -} - - - -// virtual -LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->createChild("label", TRUE)->setStringValue(mLabel->getText()); - - std::string control_name = mButton->getControlName(); - - node->createChild("initial_value", TRUE)->setBoolValue(mInitialValue); - - node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFont)); - - node->createChild("radio_style", TRUE)->setBoolValue(mRadioStyle); - - return node; -} - -// static -LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name("checkbox"); - node->getAttributeString("name", name); - - std::string label(""); - node->getAttributeString("label", label); - - LLFontGL* font = LLView::selectFont(node); - - BOOL radio_style = FALSE; - node->getAttributeBOOL("radio_style", radio_style); - - LLUICtrlCallback callback = NULL; - - if (label.empty()) - { - label.assign(node->getTextContents()); + mButton->resetDirty(); } - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl(name, - rect, - label, - font, - callback, - NULL, - FALSE, - radio_style); // if true, draw radio button style icons - - BOOL initial_value = checkbox->getValue().asBoolean(); - node->getAttributeBOOL("initial_value", initial_value); - - LLColor4 color; - color = LLUI::sColorsGroup->getColor( "LabelTextColor" ); - LLUICtrlFactory::getAttributeColor(node,"text_enabled_color", color); - checkbox->setEnabledColor(color); - - color = LLUI::sColorsGroup->getColor( "LabelDisabledColor" ); - LLUICtrlFactory::getAttributeColor(node,"text_disabled_color", color); - checkbox->setDisabledColor(color); - - checkbox->setValue(initial_value); - - checkbox->initFromXML(node, parent); - - return checkbox; } diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index ff867f5193..fe719e3b6a 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -33,24 +33,14 @@ #ifndef LL_LLCHECKBOXCTRL_H #define LL_LLCHECKBOXCTRL_H - -#include "stdtypes.h" #include "lluictrl.h" #include "llbutton.h" +#include "lltextbox.h" #include "v4color.h" -#include "llrect.h" // // Constants // -const S32 LLCHECKBOXCTRL_BTN_SIZE = 13; -const S32 LLCHECKBOXCTRL_VPAD = 2; -const S32 LLCHECKBOXCTRL_HPAD = 2; -const S32 LLCHECKBOXCTRL_SPACING = 5; -const S32 LLCHECKBOXCTRL_HEIGHT = 16; - -// Deprecated, don't use. -#define CHECKBOXCTRL_HEIGHT LLCHECKBOXCTRL_HEIGHT const BOOL RADIO_STYLE = TRUE; const BOOL CHECK_STYLE = FALSE; @@ -59,30 +49,38 @@ const BOOL CHECK_STYLE = FALSE; // Classes // class LLFontGL; -class LLTextBox; class LLViewBorder; class LLCheckBoxCtrl : public LLUICtrl { public: - LLCheckBoxCtrl(const std::string& name, const LLRect& rect, const std::string& label, - const LLFontGL* font = NULL, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void* callback_userdata = NULL, - BOOL initial_value = FALSE, - BOOL use_radio_style = FALSE, // if true, draw radio button style icons - const std::string& control_which = LLStringUtil::null); + struct Params + : public LLInitParam::Block + { + Optional text_enabled_color; + Optional text_disabled_color; + Optional initial_value; // override LLUICtrl initial_value + + Optional label_text; + Optional check_button; + + Deprecated radio_style; + + Params(); + }; + virtual ~LLCheckBoxCtrl(); - // LLView interface +protected: + LLCheckBoxCtrl(const Params&); + friend class LLUICtrlFactory; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); +public: + // LLView interface virtual void setEnabled( BOOL b ); - virtual void draw(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // LLUICtrl interface @@ -91,8 +89,8 @@ public: BOOL get() { return (BOOL)getValue().asBoolean(); } void set(BOOL value) { setValue(value); } - virtual void setTentative(BOOL b) { mButton->setTentative(b); } - virtual BOOL getTentative() const { return mButton->getTentative(); } + virtual void setTentative(BOOL b); + virtual BOOL getTentative() const; virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); @@ -108,10 +106,11 @@ public: void setLabel( const LLStringExplicit& label ); std::string getLabel() const; + void setFont( const LLFontGL* font ) { mFont = font; } + virtual void setControlName(const std::string& control_name, LLView* context); - virtual std::string getControlName() const; - static void onButtonPress(void *userdata); + void onButtonPress(const LLSD& data); virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. virtual void resetDirty(); // Clear dirty state @@ -121,19 +120,17 @@ protected: LLButton* mButton; LLTextBox* mLabel; const LLFontGL* mFont; - LLColor4 mTextEnabledColor; - LLColor4 mTextDisabledColor; - BOOL mRadioStyle; - BOOL mInitialValue; // Value set in constructor - BOOL mSetValue; // Value set programmatically - BOOL mKeyboardFocusOnClick; - LLViewBorder* mBorder; -}; + LLUIColor mTextEnabledColor; + LLUIColor mTextDisabledColor; +}; -// HACK: fix old capitalization problem -//typedef LLCheckBoxCtrl LLCheckboxCtrl; -#define LLCheckboxCtrl LLCheckBoxCtrl +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_CHECKBOX +#pragma warning (disable : 4231) +extern template LLCheckBoxCtrl* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif #endif // LL_LLCHECKBOXCTRL_H diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 28a05c13f5..09f7a6c813 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -33,6 +33,8 @@ // A control that displays the name of the chosen item, which when // clicked shows a scrolling box of options. +#define INSTANTIATE_GETCHILD_COMBOBOX + #include "linden_common.h" // file includes @@ -48,167 +50,128 @@ #include "llwindow.h" #include "llfloater.h" #include "llscrollbar.h" +#include "llscrolllistcell.h" +#include "llscrolllistitem.h" #include "llcontrol.h" #include "llfocusmgr.h" #include "lllineeditor.h" #include "v2math.h" +#include "lluictrlfactory.h" // Globals S32 LLCOMBOBOX_HEIGHT = 0; S32 LLCOMBOBOX_WIDTH = 0; S32 MAX_COMBO_WIDTH = 500; -static LLRegisterWidget r1("combo_box"); +template LLComboBox* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::string& label, - void (*commit_callback)(LLUICtrl*,void*), - void *callback_userdata - ) -: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, - FOLLOWS_LEFT | FOLLOWS_TOP), - mTextEntry(NULL), - mArrowImage(NULL), - mAllowTextEntry(FALSE), - mMaxChars(20), - mTextEntryTentative(TRUE), - mListPosition(BELOW), - mPrearrangeCallback( NULL ), - mTextEntryCallback( NULL ), - mLabel(label) -{ - // Always use text box - // Text label button - mButton = new LLButton(mLabel, - LLRect(), - LLStringUtil::null, - NULL, this); - mButton->setImageUnselected(std::string("square_btn_32x128.tga")); - mButton->setImageSelected(std::string("square_btn_selected_32x128.tga")); - mButton->setImageDisabled(std::string("square_btn_32x128.tga")); - mButton->setImageDisabledSelected(std::string("square_btn_selected_32x128.tga")); - mButton->setScaleImage(TRUE); - - mButton->setMouseDownCallback(onButtonDown); - mButton->setFont(LLFontGL::getFontSansSerifSmall()); - mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); - mButton->setHAlign( LLFontGL::LEFT ); - mButton->setRightHPad(2); - addChild(mButton); +static LLRegisterWidget register_combo_box("combo_box"); - // disallow multiple selection - mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(), - &LLComboBox::onItemSelected, this, FALSE); - mList->setVisible(FALSE); - mList->setBgWriteableColor( LLColor4(1,1,1,1) ); - mList->setCommitOnKeyboardMovement(FALSE); - addChild(mList); - - mArrowImage = LLUI::sImageProvider->getUIImage("combobox_arrow.tga"); - mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT); +void LLComboBox::PreferredPositionValues::declareValues() +{ + declare("above", ABOVE); + declare("below", BELOW); +} - updateLayout(); +LLComboBox::ItemParams::ItemParams() +: label("label") +{ } -LLComboBox::~LLComboBox() +LLComboBox::Params::Params() +: allow_text_entry("allow_text_entry", false), + show_text_as_tentative("show_text_as_tentative", true), + max_chars("max_chars", 20), + arrow_image("arrow_image"), + list_position("list_position", BELOW), + items("item"), + combo_button("combo_button"), + combo_list("combo_list"), + combo_editor("combo_editor") { - // children automatically deleted, including mMenu, mButton + addSynonym(items, "combo_item"); } -// virtual -LLXMLNodePtr LLComboBox::getXML(bool save_children) const + +LLComboBox::LLComboBox(const LLComboBox::Params& p) +: LLUICtrl(p), + mTextEntry(NULL), + mTextEntryTentative(p.show_text_as_tentative), + mAllowTextEntry(p.allow_text_entry), + mMaxChars(p.max_chars), + mPrearrangeCallback(p.prearrange_callback()), + mTextEntryCallback(p.text_entry_callback()), + mSelectionCallback(p.selection_callback()), + mArrowImage(p.arrow_image), + mListPosition(p.list_position) { - LLXMLNodePtr node = LLUICtrl::getXML(); + // Text label button - // Attributes + LLButton::Params button_params = p.combo_button; + button_params.mouse_down_callback.function(boost::bind(&LLComboBox::onButtonDown, this)); + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + button_params.rect(p.rect); + button_params.pad_right(2); - node->createChild("allow_text_entry", TRUE)->setBoolValue(mAllowTextEntry); + mButton = LLUICtrlFactory::create(button_params); + mButton->setRightHPad(2); //redo to compensate for button hack that leaves space for a character + addChild(mButton); - node->createChild("max_chars", TRUE)->setIntValue(mMaxChars); + LLScrollListCtrl::Params params = p.combo_list; + params.name("ComboBox"); + params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); - // Contents + mList = LLUICtrlFactory::create(params); + addChild(mList); - std::vector data_list = mList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (LLInitParam::ParamIterator::const_iterator it = p.items().begin(); + it != p.items().end(); + ++it) { - LLScrollListItem* item = *data_itor; - LLScrollListCell* cell = item->getColumn(0); - if (cell) + LLScrollListItem::Params item_params = *it; + if (it->label.isProvided()) { - LLXMLNodePtr item_node = node->createChild("combo_item", FALSE); - LLSD value = item->getValue(); - item_node->createChild("value", TRUE)->setStringValue(value.asString()); - item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled()); - item_node->setStringValue(cell->getValue().asString()); + item_params.cells.add().value(it->label()); } + + mList->addRow(item_params); } - return node; + createLineEditor(p); + + setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); } -// static -LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +void LLComboBox::initFromParams(const LLComboBox::Params& p) { - std::string name("combo_box"); - node->getAttributeString("name", name); - - std::string label(""); - node->getAttributeString("label", label); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - BOOL allow_text_entry = FALSE; - node->getAttributeBOOL("allow_text_entry", allow_text_entry); - - S32 max_chars = 20; - node->getAttributeS32("max_chars", max_chars); - - LLUICtrlCallback callback = NULL; - - LLComboBox* combo_box = new LLComboBox(name, - rect, - label, - callback, - NULL); - combo_box->setAllowTextEntry(allow_text_entry, max_chars); + LLUICtrl::initFromParams(p); - combo_box->initFromXML(node, parent); - - const std::string& contents = node->getValue(); - - if (contents.find_first_not_of(" \n\t") != contents.npos) - { - llerrs << "Legacy combo box item format used! Please convert to tags!" << llendl; - } - else + if (!acceptsTextInput() && mLabel.empty()) { - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("combo_item")) - { - std::string label = child->getTextContents(); - - std::string value = label; - child->getAttributeString("value", value); - - combo_box->add(label, LLSD(value) ); - } - } + selectFirstItem(); } +} - // if providing user text entry or descriptive label - // don't select an item under the hood - if (!combo_box->acceptsTextInput() && combo_box->mLabel.empty()) +// virtual +BOOL LLComboBox::postBuild() +{ + if (mControlVariable) { - combo_box->selectFirstItem(); + setValue(mControlVariable->getValue()); // selects the appropriate item } + return TRUE; +} + - return combo_box; +LLComboBox::~LLComboBox() +{ + // children automatically deleted, including mMenu, mButton } + void LLComboBox::setEnabled(BOOL enabled) { LLView::setEnabled(enabled); @@ -237,6 +200,7 @@ void LLComboBox::onCommit() mTextEntry->setValue(getSimple()); mTextEntry->setTentative(FALSE); } + setControlValue(getValue()); LLUICtrl::onCommit(); } @@ -431,6 +395,7 @@ BOOL LLComboBox::remove(S32 index) if (index < mList->getItemCount()) { mList->deleteSingleItem(index); + setLabel(mList->getSelectedItemLabel()); return TRUE; } return FALSE; @@ -448,21 +413,17 @@ void LLComboBox::onFocusLost() LLUICtrl::onFocusLost(); } -void LLComboBox::onLostTop() -{ - hideList(); -} - - void LLComboBox::setButtonVisible(BOOL visible) { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); + mButton->setVisible(visible); if (mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); if (visible) { - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); + text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -498,54 +459,48 @@ S32 LLComboBox::getCurrentIndex() const } -void LLComboBox::updateLayout() +void LLComboBox::createLineEditor(const LLComboBox::Params& p) { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); LLRect rect = getLocalRect(); if (mAllowTextEntry) { - S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton"); + S32 shadow_size = drop_shadow_button; mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); mButton->setTabStop(FALSE); + mButton->setHAlign(LLFontGL::HCENTER); - if (!mTextEntry) - { - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); - // clear label on button - std::string cur_label = mButton->getLabelSelected(); - mTextEntry = new LLLineEditor(std::string("combo_text_entry"), - text_entry_rect, - LLStringUtil::null, - LLFontGL::getFontSansSerifSmall(), - mMaxChars, - onTextCommit, - onTextEntry, - NULL, - this); - mTextEntry->setSelectAllonFocusReceived(TRUE); - mTextEntry->setHandleEditKeysDirectly(TRUE); - mTextEntry->setCommitOnFocusLost(FALSE); - mTextEntry->setText(cur_label); - mTextEntry->setIgnoreTab(TRUE); - mTextEntry->setFollowsAll(); - addChild(mTextEntry); - } - else - { - mTextEntry->setVisible(TRUE); - mTextEntry->setMaxTextLength(mMaxChars); - } + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; + // clear label on button + std::string cur_label = mButton->getLabelSelected(); + LLLineEditor::Params params = p.combo_editor; + params.rect(text_entry_rect); + params.default_text(LLStringUtil::null); + params.max_length_bytes(mMaxChars); + params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); + params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); + params.focus_lost_callback(NULL); + params.select_on_focus(true); + params.handle_edit_keys_directly(true); + params.commit_on_focus_lost(false); + params.follows.flags(FOLLOWS_ALL); + mTextEntry = LLUICtrlFactory::create (params); + mTextEntry->setText(cur_label); + mTextEntry->setIgnoreTab(TRUE); + addChild(mTextEntry); // clear label on button setLabel(LLStringUtil::null); mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); } - else if (!mAllowTextEntry) + else { mButton->setRect(rect); mButton->setTabStop(TRUE); + mButton->setHAlign(LLFontGL::LEFT); if (mTextEntry) { @@ -672,7 +627,7 @@ void LLComboBox::hideList() mButton->setToggleState(FALSE); mList->setVisible(FALSE); - mList->highlightNthItem(-1); + mList->mouseOverHighlightNthItem(-1); setUseBoundingRect(FALSE); if( gFocusMgr.getTopCtrl() == this ) @@ -681,74 +636,74 @@ void LLComboBox::hideList() } } -//------------------------------------------------------------------ -// static functions -//------------------------------------------------------------------ - -// static -void LLComboBox::onButtonDown(void *userdata) +void LLComboBox::onButtonDown() { - LLComboBox *self = (LLComboBox *)userdata; - - if (!self->mList->getVisible()) + if (!mList->getVisible()) { - LLScrollListItem* last_selected_item = self->mList->getLastSelectedItem(); + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); if (last_selected_item) { // highlight the original selection before potentially selecting a new item - self->mList->highlightNthItem(self->mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } - if( self->mPrearrangeCallback ) + if( mPrearrangeCallback ) { - self->mPrearrangeCallback( self, self->mCallbackUserData ); + mPrearrangeCallback( this, LLSD() ); } - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } - self->setFocus( TRUE ); + setFocus( TRUE ); // pass mouse capture on to list if button is depressed - if (self->mButton->hasMouseCapture()) + if (mButton->hasMouseCapture()) { - gFocusMgr.setMouseCapture(self->mList); + gFocusMgr.setMouseCapture(mList); } } else { - self->hideList(); + hideList(); } } -// static -void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata) -{ - // Note: item is the LLScrollListCtrl - LLComboBox *self = (LLComboBox *) userdata; - const std::string name = self->mList->getSelectedItemLabel(); +//------------------------------------------------------------------ +// static functions +//------------------------------------------------------------------ - S32 cur_id = self->getCurrentIndex(); +void LLComboBox::onItemSelected(const LLSD& data) +{ + const std::string name = mList->getSelectedItemLabel(); + + S32 cur_id = getCurrentIndex(); if (cur_id != -1) { - self->setLabel(name); + setLabel(name); - if (self->mAllowTextEntry) + if (mAllowTextEntry) { - gFocusMgr.setKeyboardFocus(self->mTextEntry); - self->mTextEntry->selectAll(); + gFocusMgr.setKeyboardFocus(mTextEntry); + mTextEntry->selectAll(); } } // hiding the list reasserts the old value stored in the text editor/dropdown button - self->hideList(); + hideList(); // commit does the reverse, asserting the value in the list - self->onCommit(); + onCommit(); + + // call the callback if it exists + if(mSelectionCallback) + { + mSelectionCallback(this, data); + } } BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) @@ -804,7 +759,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleKeyHere(key, mask); @@ -838,7 +793,7 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleUnicodeCharHere(uni_char); if (mList->getLastSelectedItem() != last_selected_item) @@ -850,15 +805,6 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) return result; } -void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative) -{ - mAllowTextEntry = allow; - mTextEntryTentative = set_tentative; - mMaxChars = max_chars; - - updateLayout(); -} - void LLComboBox::setTextEntry(const LLStringExplicit& text) { if (mTextEntry) @@ -868,28 +814,25 @@ void LLComboBox::setTextEntry(const LLStringExplicit& text) } } -//static -void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) +void LLComboBox::onTextEntry(LLLineEditor* line_editor) { - LLComboBox* self = (LLComboBox*)user_data; - - if (self->mTextEntryCallback) + if (mTextEntryCallback != NULL) { - (*self->mTextEntryCallback)(line_editor, self->mCallbackUserData); + (mTextEntryCallback)(line_editor, LLSD()); } KEY key = gKeyboard->currentKey(); if (key == KEY_BACKSPACE || key == KEY_DELETE) { - if (self->mList->selectItemByLabel(line_editor->getText(), FALSE)) + if (mList->selectItemByLabel(line_editor->getText(), FALSE)) { line_editor->setTentative(FALSE); } else { - line_editor->setTentative(self->mTextEntryTentative); - self->mList->deselectAllItems(); + line_editor->setTentative(mTextEntryTentative); + mList->deselectAllItems(); } return; } @@ -902,17 +845,17 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) if (key == KEY_DOWN) { - self->setCurrentByIndex(llmin(self->getItemCount() - 1, self->getCurrentIndex() + 1)); - if (!self->mList->getVisible()) + setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); + if (!mList->getVisible()) { - if( self->mPrearrangeCallback ) + if( mPrearrangeCallback ) { - self->mPrearrangeCallback( self, self->mCallbackUserData ); + mPrearrangeCallback( this, LLSD() ); } - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } } line_editor->selectAll(); @@ -920,17 +863,17 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) } else if (key == KEY_UP) { - self->setCurrentByIndex(llmax(0, self->getCurrentIndex() - 1)); - if (!self->mList->getVisible()) + setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); + if (!mList->getVisible()) { - if( self->mPrearrangeCallback ) + if( mPrearrangeCallback ) { - self->mPrearrangeCallback( self, self->mCallbackUserData ); + mPrearrangeCallback( this, LLSD() ); } - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } } line_editor->selectAll(); @@ -939,7 +882,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) else { // RN: presumably text entry - self->updateSelection(); + updateSelection(); } } @@ -958,7 +901,7 @@ void LLComboBox::updateSelection() { if (mPrearrangeCallback) { - mPrearrangeCallback( this, mCallbackUserData ); + mPrearrangeCallback( this, LLSD() ); } } @@ -983,14 +926,12 @@ void LLComboBox::updateSelection() } } -//static -void LLComboBox::onTextCommit(LLUICtrl* caller, void* user_data) +void LLComboBox::onTextCommit(const LLSD& data) { - LLComboBox* self = (LLComboBox*)user_data; - std::string text = self->mTextEntry->getText(); - self->setSimple(text); - self->onCommit(); - self->mTextEntry->selectAll(); + std::string text = mTextEntry->getText(); + setSimple(text); + onCommit(); + mTextEntry->selectAll(); } void LLComboBox::setFocus(BOOL b) @@ -1114,155 +1055,3 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last ) { return mList->selectItemRange(first, last); } - - -// -// LLFlyoutButton -// - -static LLRegisterWidget r2("flyout_button"); - -const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; - -LLFlyoutButton::LLFlyoutButton( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) , - void *callback_userdata) -: LLComboBox(name, rect, LLStringUtil::null, commit_callback, callback_userdata), - mToggleState(FALSE), - mActionButton(NULL) -{ - // Always use text box - // Text label button - mActionButton = new LLButton(label, - LLRect(), LLStringUtil::null, NULL, this); - mActionButton->setScaleImage(TRUE); - - mActionButton->setClickedCallback(onActionButtonClick); - mActionButton->setFollowsAll(); - mActionButton->setHAlign( LLFontGL::HCENTER ); - mActionButton->setLabel(label); - addChild(mActionButton); - - mActionButtonImage = LLUI::getUIImage("flyout_btn_left.tga"); - mExpanderButtonImage = LLUI::getUIImage("flyout_btn_right.tga"); - mActionButtonImageSelected = LLUI::getUIImage("flyout_btn_left_selected.tga"); - mExpanderButtonImageSelected = LLUI::getUIImage("flyout_btn_right_selected.tga"); - mActionButtonImageDisabled = LLUI::getUIImage("flyout_btn_left_disabled.tga"); - mExpanderButtonImageDisabled = LLUI::getUIImage("flyout_btn_right_disabled.tga"); - - mActionButton->setImageSelected(mActionButtonImageSelected); - mActionButton->setImageUnselected(mActionButtonImage); - mActionButton->setImageDisabled(mActionButtonImageDisabled); - mActionButton->setImageDisabledSelected(LLPointer(NULL)); - - mButton->setImageSelected(mExpanderButtonImageSelected); - mButton->setImageUnselected(mExpanderButtonImage); - mButton->setImageDisabled(mExpanderButtonImageDisabled); - mButton->setImageDisabledSelected(LLPointer(NULL)); - mButton->setRightHPad(6); - - updateLayout(); -} - -//static -LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name = "flyout_button"; - node->getAttributeString("name", name); - - std::string label(""); - node->getAttributeString("label", label); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLUICtrlCallback callback = NULL; - - LLFlyoutButton* flyout_button = new LLFlyoutButton(name, - rect, - label, - callback, - NULL); - - std::string list_position; - node->getAttributeString("list_position", list_position); - if (list_position == "below") - { - flyout_button->mListPosition = BELOW; - } - else if (list_position == "above") - { - flyout_button->mListPosition = ABOVE; - } - - - flyout_button->initFromXML(node, parent); - - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("flyout_button_item")) - { - std::string label = child->getTextContents(); - - std::string value = label; - child->getAttributeString("value", value); - - flyout_button->add(label, LLSD(value) ); - } - } - - flyout_button->updateLayout(); - - return flyout_button; -} - -void LLFlyoutButton::updateLayout() -{ - LLComboBox::updateLayout(); - - mButton->setOrigin(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0); - mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); - mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - mButton->setTabStop(FALSE); - mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT); - - mActionButton->setOrigin(0, 0); - mActionButton->reshape(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); -} - -//static -void LLFlyoutButton::onActionButtonClick(void *user_data) -{ - LLFlyoutButton* buttonp = (LLFlyoutButton*)user_data; - // remember last list selection? - buttonp->mList->deselect(); - buttonp->onCommit(); -} - -void LLFlyoutButton::draw() -{ - mActionButton->setToggleState(mToggleState); - mButton->setToggleState(mToggleState); - - //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or - // the label reflects the last selected item, for now we have to manually remove the label - mButton->setLabel(LLStringUtil::null); - LLComboBox::draw(); -} - -void LLFlyoutButton::setEnabled(BOOL enabled) -{ - mActionButton->setEnabled(enabled); - LLComboBox::setEnabled(enabled); -} - - -void LLFlyoutButton::setToggleState(BOOL state) -{ - mToggleState = state; -} - diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 33e1baa748..e7a864eb82 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -41,14 +41,13 @@ #include "llctrlselectioninterface.h" #include "llimagegl.h" #include "llrect.h" +#include "llscrolllistctrl.h" +#include "lllineeditor.h" +#include // Classes class LLFontGL; -class LLButton; -class LLSquareButton; -class LLScrollListCtrl; -class LLLineEditor; class LLViewBorder; extern S32 LLCOMBOBOX_HEIGHT; @@ -57,30 +56,61 @@ extern S32 LLCOMBOBOX_WIDTH; class LLComboBox : public LLUICtrl, public LLCtrlListInterface { -public: +public: typedef enum e_preferred_position { ABOVE, BELOW } EPreferredPosition; - LLComboBox( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void *callback_userdata = NULL - ); - virtual ~LLComboBox(); + struct PreferredPositionValues : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; - // LLView interface - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + struct ItemParams : public LLInitParam::Block + { + Optional label; + ItemParams(); + }; + + struct Params + : public LLInitParam::Block + { + Optional allow_text_entry, + show_text_as_tentative; + Optional max_chars; + Optional prearrange_callback, + text_entry_callback, + selection_callback; + Optional arrow_image; + + Optional list_position; + + // components + Optional combo_button; + Optional combo_list; + Optional combo_editor; + + Multiple items; + + Params(); + }; + + virtual ~LLComboBox(); + /*virtual*/ BOOL postBuild(); + +protected: + friend class LLUICtrlFactory; + LLComboBox(const Params&); + void initFromParams(const Params&); + +public: + // LLView interface virtual void draw(); virtual void onFocusLost(); - virtual void onLostTop(); virtual void setEnabled(BOOL enabled); @@ -105,7 +135,6 @@ public: // items, this is just the label. virtual LLSD getValue() const; - void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE); void setTextEntry(const LLStringExplicit& text); LLScrollListItem* add(const std::string& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu @@ -134,7 +163,7 @@ public: BOOL setCurrentByIndex( S32 index ); S32 getCurrentIndex() const; - virtual void updateLayout(); + void createLineEditor(const Params&); //======================================================================== LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; @@ -170,26 +199,28 @@ public: void* getCurrentUserdata(); - void setPrearrangeCallback( void (*cb)(LLUICtrl*,void*) ) { mPrearrangeCallback = cb; } - void setTextEntryCallback( void (*cb)(LLLineEditor*, void*) ) { mTextEntryCallback = cb; } + void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; } + void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } + void setSelectionCallback( commit_callback_t cb ) { mSelectionCallback = cb; } void setButtonVisible(BOOL visible); - static void onButtonDown(void *userdata); - static void onItemSelected(LLUICtrl* item, void *userdata); - static void onTextEntry(LLLineEditor* line_editor, void* user_data); - static void onTextCommit(LLUICtrl* caller, void* user_data); + void onButtonDown(); + void onItemSelected(const LLSD& data); + void onTextCommit(const LLSD& data); void updateSelection(); virtual void showList(); virtual void hideList(); - + + void onTextEntry(LLLineEditor* line_editor); + protected: LLButton* mButton; LLScrollListCtrl* mList; EPreferredPosition mListPosition; LLPointer mArrowImage; - std::string mLabel; + LLUIString mLabel; private: S32 mButtonPadding; @@ -197,39 +228,16 @@ private: BOOL mAllowTextEntry; S32 mMaxChars; BOOL mTextEntryTentative; - void (*mPrearrangeCallback)(LLUICtrl*,void*); - void (*mTextEntryCallback)(LLLineEditor*, void*); + commit_callback_t mPrearrangeCallback; + commit_callback_t mTextEntryCallback; + commit_callback_t mSelectionCallback; }; -class LLFlyoutButton : public LLComboBox -{ -public: - LLFlyoutButton( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void *callback_userdata = NULL); - - virtual void updateLayout(); - virtual void draw(); - virtual void setEnabled(BOOL enabled); - - void setToggleState(BOOL state); - - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - static void onActionButtonClick(void *userdata); - static void onSelectAction(LLUICtrl* ctrl, void *userdata); - -protected: - LLButton* mActionButton; - LLPointer mActionButtonImage; - LLPointer mExpanderButtonImage; - LLPointer mActionButtonImageSelected; - LLPointer mExpanderButtonImageSelected; - LLPointer mActionButtonImageDisabled; - LLPointer mExpanderButtonImageDisabled; - BOOL mToggleState; -}; +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_COMBOBOX +#pragma warning (disable : 4231) +extern template LLComboBox* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif #endif diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp new file mode 100644 index 0000000000..f1fc3d8f43 --- /dev/null +++ b/indra/llui/llconsole.cpp @@ -0,0 +1,393 @@ +/** + * @file llconsole.cpp + * @brief a scrolling console output device + * + * $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 "linden_common.h" + +#include "llconsole.h" + +// linden library includes +#include "llmath.h" +//#include "llviewercontrol.h" +#include "llcriticaldamp.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llui.h" +#include "lluiimage.h" +//#include "llviewerimage.h" +//#include "llviewerimagelist.h" +//#include "llviewerwindow.h" +#include "llsd.h" +#include "llfontgl.h" +#include "llmath.h" + +//#include "llstartup.h" + +// Used for LCD display +extern void AddNewDebugConsoleToLCD(const LLWString &newLine); + +LLConsole* gConsole = NULL; // Created and destroyed in LLViewerWindow. + +const F32 FADE_DURATION = 2.f; +const S32 MIN_CONSOLE_WIDTH = 200; + +LLConsole::LLConsole(const LLConsole::Params& p) +: LLView(p), + LLFixedBuffer(p.max_lines), + mLinePersistTime(p.persist_time), // seconds + mFont(p.font) +{ + if (p.font_size_index.isProvided()) + { + setFontSize(p.font_size_index); + } + mFadeTime = mLinePersistTime - FADE_DURATION; + setMaxLines(LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")); +} + +void LLConsole::setLinePersistTime(F32 seconds) +{ + mLinePersistTime = seconds; + mFadeTime = mLinePersistTime - FADE_DURATION; +} + +void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + S32 new_width = llmax(50, llmin(getRect().getWidth(), width)); + S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height)); + + if ( mConsoleWidth == new_width + && mConsoleHeight == new_height ) + { + return; + } + + mConsoleWidth = new_width; + mConsoleHeight= new_height; + + LLView::reshape(new_width, new_height, called_from_parent); + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } +} + +void LLConsole::setFontSize(S32 size_index) +{ + if (-1 == size_index) + { + mFont = LLFontGL::getFontMonospace(); + } + else if (0 == size_index) + { + mFont = LLFontGL::getFontSansSerif(); + } + else if (1 == size_index) + { + mFont = LLFontGL::getFontSansSerifBig(); + } + else + { + mFont = LLFontGL::getFontSansSerifHuge(); + } + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } +} + +void LLConsole::draw() +{ + LLGLSUIDefault gls_ui; + + // skip lines added more than mLinePersistTime ago + F32 cur_time = mTimer.getElapsedTimeF32(); + + F32 skip_time = cur_time - mLinePersistTime; + F32 fade_time = cur_time - mFadeTime; + + if (mParagraphs.empty()) //No text to draw. + { + return; + } + + U32 num_lines=0; + + paragraph_t::reverse_iterator paragraph_it; + paragraph_it = mParagraphs.rbegin(); + U32 paragraph_num=mParagraphs.size(); + + while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) + { + num_lines += (*paragraph_it).mLines.size(); + if(num_lines > mMaxLines + || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) + { //All lines above here are done. Lose them. + for (U32 i=0;igetF32("ConsoleBackgroundOpacity"), 0.f, 1.f); +// LLColor4 color = gSavedSkinSettings.getColor("ConsoleBackground"); + LLColor4 color = LLUI::sSettingGroups["color"]->getColor("ConsoleBackground"); + color.mV[VALPHA] *= console_opacity; + + F32 line_height = mFont->getLineHeight(); + + for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) + { + S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8); + S32 target_width = llfloor( (*paragraph_it).mMaxWidth +15); + + y_pos += ((*paragraph_it).mLines.size()) * line_height; + imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); + + F32 y_off=0; + + F32 alpha; + + if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) + { + alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); + } + else + { + alpha = 1.0f; + } + + if( alpha > 0.f ) + { + for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); + line_it != (*paragraph_it).mLines.end(); + line_it ++) + { + for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); + seg_it != (*line_it).mLineColorSegments.end(); + seg_it++) + { + mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, + LLColor4( + (*seg_it).mColor.mV[VRED], + (*seg_it).mColor.mV[VGREEN], + (*seg_it).mColor.mV[VBLUE], + (*seg_it).mColor.mV[VALPHA]*alpha), + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::NORMAL, + LLFontGL::DROP_SHADOW, + S32_MAX, + target_width + ); + } + y_off += line_height; + } + } + y_pos += 8; + } +} + +void LLConsole::addLine(const std::string& utf8line) +{ + LLWString wline = utf8str_to_wstring(utf8line); + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); +} + +void LLConsole::addLine(const LLWString& wline) +{ + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); +} + +void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color) +{ + LLWString wline = utf8str_to_wstring(utf8line); + addLine(wline, size, color); +} + +//Generate highlight color segments for this paragraph. Pass in default color of paragraph. +void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) +{ + LLSD paragraph_color_segments; + LLColor4 lcolor=color; + + paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); + LLSD color_sd = color.getValue(); + paragraph_color_segments[0]["color"]=color_sd; + + for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray(); + color_segment_it != paragraph_color_segments.endArray(); + ++color_segment_it) + { + LLSD color_llsd = (*color_segment_it)["color"]; + std::string color_str = (*color_segment_it)["text"].asString(); + + ParagraphColorSegment color_segment; + + color_segment.mColor.setValue(color_llsd); + color_segment.mNumChars = color_str.length(); + + mParagraphColorSegments.push_back(color_segment); + } +} + +//Called when a paragraph is added to the console or window is resized. +void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, bool force_resize) +{ + if ( !force_resize ) + { + if ( mMaxWidth >= 0.0f + && mMaxWidth < screen_width ) + { + return; //No resize required. + } + } + + screen_width = screen_width - 30; //Margin for small windows. + + if ( mParagraphText.empty() + || mParagraphColorSegments.empty() + || font == NULL) + { + return; //Not enough info to complete. + } + + mLines.clear(); //Chuck everything. + mMaxWidth = 0.0f; + + paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin(); + U32 current_color_length = (*current_color).mNumChars; + + S32 paragraph_offset = 0; //Offset into the paragraph text. + + // Wrap lines that are longer than the view is wide. + while( paragraph_offset < (S32)mParagraphText.length() ) + { + S32 skip_chars; // skip '\n' + // Figure out if a word-wrapped line fits here. + LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('\n'), paragraph_offset); + if (line_end != LLWString::npos) + { + skip_chars = 1; // skip '\n' + } + else + { + line_end = mParagraphText.size(); + skip_chars = 0; + } + + U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, TRUE); + + if (drawable != 0) + { + F32 x_position = 0; //Screen X position of text. + + mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); + Line line; + + U32 left_to_draw = drawable; + U32 drawn = 0; + + while (left_to_draw >= current_color_length + && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + x_position += font->getWidth( color_text.c_str() ); //Set up next screen position. + + drawn += current_color_length; + left_to_draw -= current_color_length; + + current_color++; //Goto next paragraph color record. + + if (current_color != mParagraphColorSegments.end()) + { + current_color_length = (*current_color).mNumChars; + } + } + + if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); + + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + current_color_length -= left_to_draw; + } + mLines.push_back(line); //Append line to paragraph line list. + } + paragraph_offset += (drawable + skip_chars); + } +} + +//Pass in the string and the default color for this block of text. +LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width) + : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) +{ + makeParagraphColorSegments(color); + updateLines( screen_width, font ); +} + +void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) +{ + Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() ); + + mParagraphs.push_back ( paragraph ); + +#if LL_WINDOWS && LL_LCD_COMPILE + // add to LCD screen + AddNewDebugConsoleToLCD(wline); +#endif +} diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h new file mode 100644 index 0000000000..65149b217f --- /dev/null +++ b/indra/llui/llconsole.h @@ -0,0 +1,162 @@ +/** + * @file llconsole.h + * @brief a simple console-style output device + * + * $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_LLCONSOLE_H +#define LL_LLCONSOLE_H + +#include "llfixedbuffer.h" +#include "llview.h" +#include "v4color.h" +#include + +class LLFontGL; +class LLSD; + +class LLConsole : public LLFixedBuffer, public LLView +{ +public: + typedef enum e_font_size + { + MONOSPACE = -1, + SMALL = 0, + BIG = 1 + } EFontSize; + + struct Params : public LLInitParam::Block + { + Optional max_lines; + Optional persist_time; + Optional font_size_index; + Params() + : max_lines("max_lines", LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")), + persist_time("persist_time", 0.f) // forever + { + mouse_opaque(false); + } + }; +protected: + LLConsole(const Params&); + friend class LLUICtrlFactory; + +public: + //A paragraph color segment defines the color of text in a line + //of text that was received for console display. It has no + //notion of line wraps, screen position, or the text it contains. + //It is only the number of characters that are a color and the + //color. + struct ParagraphColorSegment + { + S32 mNumChars; + LLColor4 mColor; + }; + + //A line color segment is a chunk of text, the color associated + //with it, and the X Position it was calculated to begin at + //on the screen. X Positions are re-calculated if the + //screen changes size. + class LineColorSegment + { + public: + LineColorSegment(LLWString text, LLColor4 color, F32 xpos) : mText(text), mColor(color), mXPosition(xpos) {} + public: + LLWString mText; + LLColor4 mColor; + F32 mXPosition; + }; + + typedef std::list line_color_segments_t; + + //A line is composed of one or more color segments. + class Line + { + public: + line_color_segments_t mLineColorSegments; + }; + + typedef std::list lines_t; + typedef std::list paragraph_color_segments_t; + + //A paragraph is a processed element containing the entire text of the + //message (used for recalculating positions on screen resize) + //The time this message was added to the console output + //The visual screen width of the longest line in this block + //And a list of one or more lines which are used to display this message. + class Paragraph + { + public: + Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width); + void makeParagraphColorSegments ( const LLColor4 &color); + void updateLines ( F32 screen_width, const LLFontGL* font, bool force_resize=false ); + public: + LLWString mParagraphText; //The entire text of the paragraph + paragraph_color_segments_t mParagraphColorSegments; + F32 mAddTime; //Time this paragraph was added to the display. + F32 mMaxWidth; //Width of the widest line of text in this paragraph. + lines_t mLines; + + }; + + //The console contains a deque of paragraphs which represent the individual messages. + typedef std::deque paragraph_t; + paragraph_t mParagraphs; + + ~LLConsole(){}; + + // each line lasts this long after being added + void setLinePersistTime(F32 seconds); + + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + // -1 = monospace, 0 means small, font size = 1 means big + void setFontSize(S32 size_index); + + void addLine(const std::string& utf8line, F32 size, const LLColor4 &color); + void addLine(const LLWString& wline, F32 size, const LLColor4 &color); + + // Overrides + /*virtual*/ void draw(); + /*virtual*/ void addLine(const std::string& utf8line); + /*virtual*/ void addLine(const LLWString& line); +private: + F32 mLinePersistTime; // Age at which to stop drawing. + F32 mFadeTime; // Age at which to start fading + const LLFontGL* mFont; + S32 mLastBoxHeight; + S32 mLastBoxWidth; + S32 mConsoleWidth; + S32 mConsoleHeight; + +}; + +extern LLConsole* gConsole; + +#endif diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp new file mode 100644 index 0000000000..a63023e35c --- /dev/null +++ b/indra/llui/llcontainerview.cpp @@ -0,0 +1,301 @@ +/** + * @file llcontainerview.cpp + * @brief Container for all statistics info + * + * $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" + +#include "llcontainerview.h" + +#include "llerror.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llui.h" +#include "llstring.h" +#include "llscrollcontainer.h" +#include "lluictrlfactory.h" + +static LLRegisterWidget r("container_view"); + +LLContainerView::LLContainerView(const LLContainerView::Params& p) +: LLView(p), + mShowLabel(p.show_label), + mLabel(p.label), + mDisplayChildren(p.display_children) +{ + mCollapsible = TRUE; + mScrollContainer = NULL; +} + +LLContainerView::~LLContainerView() +{ + // Children all cleaned up by default view destructor. +} + +BOOL LLContainerView::postBuild() +{ + setDisplayChildren(mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + return TRUE; +} + +bool LLContainerView::addChild(LLView* child, S32 tab_group) +{ + bool res = LLView::addChild(child, tab_group); + if (res) + { + sendChildToBack(child); + } + return res; +} + +BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseDown(x, y, mask) != NULL); + } + if (!handled) + { + if( mCollapsible && mShowLabel && (y >= getRect().getHeight() - 10) ) + { + setDisplayChildren(!mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + handled = TRUE; + } + } + return handled; +} + +BOOL LLContainerView::handleMouseUp(S32 x, S32 y, MASK mask) +{ + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseUp(x, y, mask) != NULL); + } + return handled; +} + + +void LLContainerView::draw() +{ + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); + } + + // Draw the label + if (mShowLabel) + { + LLFontGL::getFontMonospace()->renderUTF8( + mLabel, 0, 2, getRect().getHeight() - 2, LLColor4(1,1,1,1), LLFontGL::LEFT, LLFontGL::TOP); + } + + LLView::draw(); +} + + +void LLContainerView::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + S32 desired_width = width; + S32 desired_height = height; + + if (mScrollContainer) + { + BOOL dum_bool; + mScrollContainer->calcVisibleSize(&desired_width, &desired_height, &dum_bool, &dum_bool); + } + else + { + // if we're uncontained - make height as small as possible + desired_height = 0; + } + + arrange(desired_width, desired_height, called_from_parent); + + // sometimes, after layout, our container will change size (scrollbars popping in and out) + // if so, attempt another layout + if (mScrollContainer) + { + S32 new_container_width; + S32 new_container_height; + BOOL dum_bool; + mScrollContainer->calcVisibleSize(&new_container_width, &new_container_height, &dum_bool, &dum_bool); + + if ((new_container_width != desired_width) || + (new_container_height != desired_height)) // the container size has changed, attempt to arrange again + { + arrange(new_container_width, new_container_height, called_from_parent); + } + } +} + +void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent) +{ + // Determine the sizes and locations of all contained views + S32 total_height = 0; + S32 top, left, right, bottom; + //LLView *childp; + + // These will be used for the children + left = 4; + top = getRect().getHeight() - 4; + right = width - 2; + bottom = top; + + // Leave some space for the top label/grab handle + if (mShowLabel) + { + total_height += 20; + } + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + if (!childp->getVisible()) + { + llwarns << "Incorrect visibility!" << llendl; + } + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + total_height += child_height; + } + + if (total_height < height) + total_height = height; + + if (followsTop()) + { + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mBottom = getRect().mTop - total_height; + } + else + { + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mTop = getRect().mBottom + total_height; + } + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mRight = getRect().mLeft + width; + + top = total_height; + if (mShowLabel) + { + top -= 20; + } + + bottom = top; + + if (mDisplayChildren) + { + // Iterate through all children, and put in container from top down. + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + bottom -= child_rect.getHeight(); + LLRect r(left, bottom + child_rect.getHeight(), right, bottom); + childp->setRect(r); + childp->reshape(right - left, top - bottom); + top = bottom - 2; + bottom = top; + } + } + + if (!called_from_parent) + { + if (getParent()) + { + getParent()->reshape(getParent()->getRect().getWidth(), getParent()->getRect().getHeight(), FALSE); + } + } + +} + +LLRect LLContainerView::getRequiredRect() +{ + LLRect req_rect; + //LLView *childp; + U32 total_height = 0; + + // Determine the sizes and locations of all contained views + + // Leave some space for the top label/grab handle + + if (mShowLabel) + { + total_height = 20; + } + + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + + total_height += child_height; + } + req_rect.mTop = total_height; + return req_rect; +} + +void LLContainerView::setLabel(const std::string& label) +{ + mLabel = label; +} + +void LLContainerView::setDisplayChildren(const BOOL displayChildren) +{ + mDisplayChildren = displayChildren; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + childp->setVisible(mDisplayChildren); + } +} diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h new file mode 100644 index 0000000000..9f3d1ac7ad --- /dev/null +++ b/indra/llui/llcontainerview.h @@ -0,0 +1,92 @@ +/** + * @file llcontainerview.h + * @brief Container for all statistics info. + * + * $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_LLCONTAINERVIEW_H +#define LL_LLCONTAINERVIEW_H + +#include "stdtypes.h" +#include "lltextbox.h" +#include "llstatbar.h" + +class LLScrollContainer; + +class LLContainerView : public LLView +{ +public: + struct Params : public LLInitParam::Block + { + Optional label; + Optional show_label; + Optional display_children; + Params() + : label("label"), + show_label("show_label", FALSE), + display_children("display_children", TRUE) + { + mouse_opaque(false); + } + }; +protected: + LLContainerView(const Params& p); + friend class LLUICtrlFactory; +public: + ~LLContainerView(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + + /*virtual*/ void draw(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. + + void setLabel(const std::string& label); + void showLabel(BOOL show) { mShowLabel = show; } + void setDisplayChildren(const BOOL displayChildren); + BOOL getDisplayChildren() { return mDisplayChildren; } + void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} + + private: + LLScrollContainer* mScrollContainer; + void arrange(S32 width, S32 height, BOOL called_from_parent = TRUE); + BOOL mShowLabel; + +protected: + BOOL mDisplayChildren; + std::string mLabel; +public: + BOOL mCollapsible; + +}; +#endif // LL_CONTAINERVIEW_ diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 6c92ea1ff7..8ecbdb98e1 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -43,10 +43,10 @@ #include "llmenugl.h" #include "lltextbox.h" #include "llcontrol.h" -#include "llresmgr.h" #include "llfontgl.h" #include "llwindow.h" #include "llfocusmgr.h" +#include "lluictrlfactory.h" const S32 LEADING_PAD = 5; const S32 TITLE_PAD = 8; @@ -56,21 +56,33 @@ const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize S32 LLDragHandle::sSnapMargin = 5; -LLDragHandle::LLDragHandle( const std::string& name, const LLRect& rect, const std::string& title ) -: LLView( name, rect, TRUE ), +LLDragHandle::LLDragHandle(const LLDragHandle::Params& p) +: LLView(p), mDragLastScreenX( 0 ), mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), - mDragHighlightColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ), - mDragShadowColor( LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ), mTitleBox( NULL ), mMaxTitleWidth( 0 ), - mForeground( TRUE ) + mForeground( TRUE ), + mDragHighlightColor(p.drag_highlight_color()), + mDragShadowColor(p.drag_shadow_color()) + { - sSnapMargin = LLUI::sConfigGroup->getS32("SnapMargin"); + static LLUICachedControl snap_margin ("SnapMargin", 0); + sSnapMargin = snap_margin; +} - setSaveToXML(false); +LLDragHandle::~LLDragHandle() +{ + removeChild(mTitleBox); + delete mTitleBox; +} + +void LLDragHandle::initFromParams(const LLDragHandle::Params& p) +{ + LLView::initFromParams(p); + setTitle( p.label ); } void LLDragHandle::setTitleVisible(BOOL visible) @@ -81,58 +93,47 @@ void LLDragHandle::setTitleVisible(BOOL visible) } } -void LLDragHandle::setTitleBox(LLTextBox* titlebox) -{ +void LLDragHandleTop::setTitle(const std::string& title) +{ + std::string trimmed_title = title; + LLStringUtil::trim(trimmed_title); + if( mTitleBox ) { - removeChild(mTitleBox); - delete mTitleBox; + mTitleBox->setText(trimmed_title); } - mTitleBox = titlebox; - if(mTitleBox) + else { + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLTextBox::Params params; + params.name("Drag Handle Title"); + params.rect(getRect()); + params.text(trimmed_title); + params.font(font); + params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); + params.font_shadow(LLFontGL::DROP_SHADOW_SOFT); + mTitleBox = LLUICtrlFactory::create (params); addChild( mTitleBox ); } -} - -LLDragHandleTop::LLDragHandleTop(const std::string& name, const LLRect &rect, const std::string& title) -: LLDragHandle(name, rect, title) -{ - setFollowsAll(); - setTitle( title ); -} - -LLDragHandleLeft::LLDragHandleLeft(const std::string& name, const LLRect &rect, const std::string& title) -: LLDragHandle(name, rect, title) -{ - setFollowsAll(); - setTitle( title ); -} - -void LLDragHandleTop::setTitle(const std::string& title) -{ - std::string trimmed_title = title; - LLStringUtil::trim(trimmed_title); - - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); - LLTextBox* titlebox = new LLTextBox( std::string("Drag Handle Title"), getRect(), trimmed_title, font ); - titlebox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); - titlebox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT); - setTitleBox(titlebox); reshapeTitleBox(); } const std::string& LLDragHandleTop::getTitle() const { - return getTitleBox() == NULL ? LLStringUtil::null : getTitleBox()->getText(); + return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText(); } void LLDragHandleLeft::setTitle(const std::string& ) { - setTitleBox(NULL); + if( mTitleBox ) + { + removeChild(mTitleBox); + delete mTitleBox; + mTitleBox = NULL; + } /* no title on left edge */ } @@ -184,9 +185,9 @@ void LLDragHandleTop::draw() */ // Colorize the text to match the frontmost state - if (getTitleBox()) + if (mTitleBox) { - getTitleBox()->setEnabled(getForeground()); + mTitleBox->setEnabled(getForeground()); } LLView::draw(); @@ -229,9 +230,9 @@ void LLDragHandleLeft::draw() */ // Colorize the text to match the frontmost state - if (getTitleBox()) + if (mTitleBox) { - getTitleBox()->setEnabled(getForeground()); + mTitleBox->setEnabled(getForeground()); } LLView::draw(); @@ -239,12 +240,12 @@ void LLDragHandleLeft::draw() void LLDragHandleTop::reshapeTitleBox() { - if( ! getTitleBox()) + if( ! mTitleBox) { return; } - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); - S32 title_width = font->getWidth( getTitleBox()->getText() ) + TITLE_PAD; + const LLFontGL* font = LLFontGL::getFontSansSerif(); + S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD; if (getMaxTitleWidth() > 0) title_width = llmin(title_width, getMaxTitleWidth()); S32 title_height = llround(font->getLineHeight()); @@ -255,7 +256,7 @@ void LLDragHandleTop::reshapeTitleBox() getRect().getWidth() - LEFT_PAD - RIGHT_PAD, title_height); - getTitleBox()->setRect( title_rect ); + mTitleBox->setRect( title_rect ); } void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -337,14 +338,14 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin); - getParent()->snappedTo(snap_view); + getParent()->setSnappedTo(snap_view); delta_x = new_rect.mLeft - pre_snap_x; delta_y = new_rect.mBottom - pre_snap_y; translated_rect.translate(delta_x, delta_y); // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc getParent()->setRect(original_rect); - getParent()->userSetShape(translated_rect); + getParent()->setShape(translated_rect, true); mDragLastScreenX += delta_x; mDragLastScreenY += delta_y; diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 9eb3e55a6c..8b53c46ae9 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -45,8 +45,24 @@ class LLTextBox; class LLDragHandle : public LLView { public: - LLDragHandle(const std::string& name, const LLRect& rect, const std::string& title ); - virtual ~LLDragHandle() { setTitleBox(NULL); } + struct Params + : public LLInitParam::Block + { + Optional label; + Optional drag_highlight_color; + Optional drag_shadow_color; + + Params() + : drag_highlight_color("", LLUI::getCachedColorFunctor("DefaultHighlightLight")), + drag_shadow_color("", LLUI::getCachedColorFunctor("DefaultShadowDark")) + { + mouse_opaque(true); + follows.flags(FOLLOWS_ALL); + } + }; + void initFromParams(const Params&); + + virtual ~LLDragHandle(); virtual void setValue(const LLSD& value); @@ -64,18 +80,20 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); protected: - LLTextBox* getTitleBox() const { return mTitleBox; } - void setTitleBox(LLTextBox*); - + LLDragHandle(const Params&); + friend class LLUICtrlFactory; + +protected: + LLTextBox* mTitleBox; + private: S32 mDragLastScreenX; S32 mDragLastScreenY; S32 mLastMouseScreenX; S32 mLastMouseScreenY; LLCoordGL mLastMouseDir; - LLColor4 mDragHighlightColor; - LLColor4 mDragShadowColor; - LLTextBox* mTitleBox; + LLUIColor mDragHighlightColor; + LLUIColor mDragShadowColor; S32 mMaxTitleWidth; BOOL mForeground; @@ -88,9 +106,10 @@ private: class LLDragHandleTop : public LLDragHandle { +protected: + LLDragHandleTop(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - LLDragHandleTop(const std::string& name, const LLRect& rect, const std::string& title ); - virtual void setTitle( const std::string& title ); virtual const std::string& getTitle() const; virtual void draw(); @@ -105,9 +124,10 @@ private: class LLDragHandleLeft : public LLDragHandle { +protected: + LLDragHandleLeft(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - LLDragHandleLeft(const std::string& name, const LLRect& rect, const std::string& title ); - virtual void setTitle( const std::string& title ); virtual const std::string& getTitle() const; virtual void draw(); diff --git a/indra/llui/llf32uictrl.cpp b/indra/llui/llf32uictrl.cpp new file mode 100644 index 0000000000..0978005b78 --- /dev/null +++ b/indra/llui/llf32uictrl.cpp @@ -0,0 +1,57 @@ +/** + * @file llf32uictrl.cpp + * @author Nat Goodspeed + * @date 2008-09-08 + * @brief Implementation for llf32uictrl. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llf32uictrl.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLF32UICtrl::LLF32UICtrl(const Params& p) +: LLUICtrl(p), + mInitialValue(p.initial_value().asReal()), + mMinValue(p.min_value), + mMaxValue(p.max_value), + mIncrement(p.increment) +{ + mViewModel->setValue(p.initial_value); +} + +F32 LLF32UICtrl::getValueF32() const +{ + return mViewModel->getValue().asReal(); +} diff --git a/indra/llui/llf32uictrl.h b/indra/llui/llf32uictrl.h new file mode 100644 index 0000000000..0a54fe761b --- /dev/null +++ b/indra/llui/llf32uictrl.h @@ -0,0 +1,83 @@ +/** + * @file llf32uictrl.h + * @author Nat Goodspeed + * @date 2008-09-08 + * @brief Base class for float-valued LLUICtrl widgets + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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$ + */ + +#if ! defined(LL_LLF32UICTRL_H) +#define LL_LLF32UICTRL_H + +#include "lluictrl.h" + +class LLF32UICtrl: public LLUICtrl +{ +public: + struct Params: public LLInitParam::Block + { + Optional min_value, + max_value, + increment; + + Params() + : min_value("min_val", 0.f), + max_value("max_val", 1.f), + increment("increment", 0.1f) + {} + }; + +protected: + LLF32UICtrl(const Params& p); + +public: + virtual F32 getValueF32() const; + + virtual void setValue(const LLSD& value ) { mViewModel->setValue(value); } + virtual LLSD getValue() const { return LLSD(getValueF32()); } + + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } + + virtual F32 getInitialValue() const { return mInitialValue; } + virtual F32 getMinValue() const { return mMinValue; } + virtual F32 getMaxValue() const { return mMaxValue; } + virtual F32 getIncrement() const { return mIncrement; } + virtual void setMinValue(F32 min_value) { mMinValue = min_value; } + virtual void setMaxValue(F32 max_value) { mMaxValue = max_value; } + virtual void setIncrement(F32 increment) { mIncrement = increment;} + +protected: + F32 mInitialValue; + F32 mMinValue; + F32 mMaxValue; + F32 mIncrement; +}; + +#endif /* ! defined(LL_LLF32UICTRL_H) */ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 21f8f6e5f7..be7e050b58 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -43,11 +43,13 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "lldraghandle.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llresizebar.h" #include "llresizehandle.h" #include "llkeyboard.h" #include "llmenugl.h" // MENU_BAR_HEIGHT +#include "llmodaldialog.h" #include "lltextbox.h" #include "llresmgr.h" #include "llui.h" @@ -56,37 +58,37 @@ #include "llcontrol.h" #include "lltabcontainer.h" #include "v2math.h" +#include "lltrans.h" +#include "llmultifloater.h" -const S32 MINIMIZED_WIDTH = 160; -const S32 CLOSE_BOX_FROM_TOP = 1; // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; std::string LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = { - "UIImgBtnCloseActiveUUID", //BUTTON_CLOSE - "UIImgBtnRestoreActiveUUID", //BUTTON_RESTORE - "UIImgBtnMinimizeActiveUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffActiveUUID", //BUTTON_TEAR_OFF - "UIImgBtnCloseActiveUUID", //BUTTON_EDIT + "closebox.tga", //BUTTON_CLOSE + "restore.tga", //BUTTON_RESTORE + "minimize.tga", //BUTTON_MINIMIZE + "tearoffbox.tga", //BUTTON_TEAR_OFF + "closebox.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] = { - "UIImgBtnCloseInactiveUUID", //BUTTON_CLOSE - "UIImgBtnRestoreInactiveUUID", //BUTTON_RESTORE - "UIImgBtnMinimizeInactiveUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffInactiveUUID", //BUTTON_TEAR_OFF - "UIImgBtnCloseInactiveUUID", //BUTTON_EDIT + "close_inactive_blue.tga", //BUTTON_CLOSE + "restore_inactive.tga", //BUTTON_RESTORE + "minimize_inactive.tga", //BUTTON_MINIMIZE + "tearoffbox.tga", //BUTTON_TEAR_OFF + "close_inactive_blue.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] = { - "UIImgBtnClosePressedUUID", //BUTTON_CLOSE - "UIImgBtnRestorePressedUUID", //BUTTON_RESTORE - "UIImgBtnMinimizePressedUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffPressedUUID", //BUTTON_TEAR_OFF - "UIImgBtnClosePressedUUID", //BUTTON_EDIT + "close_in_blue.tga", //BUTTON_CLOSE + "restore_pressed.tga", //BUTTON_RESTORE + "minimize_pressed.tga", //BUTTON_MINIMIZE + "tearoff_pressed.tga", //BUTTON_TEAR_OFF + "close_in_blue.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonNames[BUTTON_COUNT] = @@ -98,17 +100,20 @@ std::string LLFloater::sButtonNames[BUTTON_COUNT] = "llfloater_edit_btn", //BUTTON_EDIT }; -std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = +std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = {}; + + +std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]= { #ifdef LL_DARWIN - "Close (Cmd-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_DARWIN",//LLTrans::getString("BUTTON_CLOSE_DARWIN"), //"Close (Cmd-W)", //BUTTON_CLOSE #else - "Close (Ctrl-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_WIN", //LLTrans::getString("BUTTON_CLOSE_WIN"), //"Close (Ctrl-W)", //BUTTON_CLOSE #endif - "Restore", //BUTTON_RESTORE - "Minimize", //BUTTON_MINIMIZE - "Tear Off", //BUTTON_TEAR_OFF - "Edit", //BUTTON_EDIT + "BUTTON_RESTORE",//LLTrans::getString("BUTTON_RESTORE"), //"Restore", //BUTTON_RESTORE + "BUTTON_MINIMIZE",//LLTrans::getString("BUTTON_MINIMIZE"), //"Minimize", //BUTTON_MINIMIZE + "BUTTON_TEAR_OFF",//LLTrans::getString("BUTTON_TEAR_OFF"), //"Tear Off", //BUTTON_TEAR_OFF + "BUTTON_EDIT", //LLTrans::getString("BUTTON_EDIT"), // "Edit", //BUTTON_EDIT }; LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = @@ -126,59 +131,118 @@ LLFloater::handle_map_t LLFloater::sFloaterMap; LLFloaterView* gFloaterView = NULL; -LLFloater::LLFloater() : - //FIXME: we should initialize *all* member variables here - LLPanel(), mAutoFocus(TRUE), - mResizable(FALSE), - mDragOnLeft(FALSE), - mMinWidth(0), - mMinHeight(0) -{ - // automatically take focus when opened - mAutoFocus = TRUE; +//static +bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b) +{ + if (a.type() != b.type()) + { + //llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl; + return false; + } + else if (a.isUndefined()) + return false; + else if (a.isInteger()) + return a.asInteger() < b.asInteger(); + else if (a.isReal()) + return a.asReal() < b.asReal(); + else if (a.isString()) + return a.asString() < b.asString(); + else if (a.isUUID()) + return a.asUUID() < b.asUUID(); + else if (a.isDate()) + return a.asDate() < b.asDate(); + else if (a.isURI()) + return a.asString() < b.asString(); // compare URIs as strings + else if (a.isBoolean()) + return a.asBoolean() < b.asBoolean(); + else + return false; // no valid operation for Binary +} + +bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b) +{ + if (a.type() != b.type()) + { + //llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl; + return false; + } + else if (a.isUndefined()) + return true; + else if (a.isInteger()) + return a.asInteger() == b.asInteger(); + else if (a.isReal()) + return a.asReal() == b.asReal(); + else if (a.isString()) + return a.asString() == b.asString(); + else if (a.isUUID()) + return a.asUUID() == b.asUUID(); + else if (a.isDate()) + return a.asDate() == b.asDate(); + else if (a.isURI()) + return a.asString() == b.asString(); // compare URIs as strings + else if (a.isBoolean()) + return a.asBoolean() == b.asBoolean(); + else + return false; // no valid operation for Binary +} + +//************************************ + +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 + mHasBeenDraggedWhileMinimized(FALSE), + mPreviousMinimizedBottom(0), + mPreviousMinimizedLeft(0), + mNotificationContext(NULL) +{ + static LLUICachedControl default_background_color ("FloaterDefaultBackgroundColor", *(new LLColor4)); + static LLUICachedControl focus_background_color ("FloaterFocusBackgroundColor", *(new LLColor4)); + for (S32 i = 0; i < BUTTON_COUNT; i++) { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } - for (S32 i = 0; i < 4; i++) - { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; + sButtonToolTips[i] =LLTrans::getString( sButtonToolTipsIndex[i]); } - mDragHandle = NULL; + mHandle.bind(this); mNotificationContext = new LLFloaterNotificationContext(getHandle()); -} + mBgColorAlpha = default_background_color; + mBgColorOpaque = focus_background_color; -LLFloater::LLFloater(const std::string& name) -: LLPanel(name), mAutoFocus(TRUE) // automatically take focus when opened -{ - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } for (S32 i = 0; i < 4; i++) { - mResizeBar[i] = NULL; + mResizeBar[i] = NULL; mResizeHandle[i] = NULL; } - std::string title; // null string - initFloater(title, FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, TRUE, TRUE); // defaults -} + // Clicks stop here. + setMouseOpaque(TRUE); + + // Floaters always draw their background, unlike every other panel. + setBackgroundVisible(TRUE); -LLFloater::LLFloater(const std::string& name, const LLRect& rect, const std::string& title, - BOOL resizable, - S32 min_width, - S32 min_height, - BOOL drag_on_left, - BOOL minimizable, - BOOL close_btn, - BOOL bordered) -: LLPanel(name, rect, bordered), mAutoFocus(TRUE) // automatically take focus when opened -{ + // Floaters start not minimized. When minimized, they save their + // prior rectangle to be used on restore. + mExpandedRect.set(0,0,0,0); + for (S32 i = 0; i < BUTTON_COUNT; i++) { mButtonsEnabled[i] = FALSE; @@ -189,259 +253,176 @@ LLFloater::LLFloater(const std::string& name, const LLRect& rect, const std::str mResizeBar[i] = NULL; mResizeHandle[i] = NULL; } - initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn); -} + + initFromParams(p); + + // chrome floaters don't take focus at all + setFocusRoot(!getIsChrome()); -LLFloater::LLFloater(const std::string& name, const std::string& rect_control, const std::string& title, - BOOL resizable, - S32 min_width, - S32 min_height, - BOOL drag_on_left, - BOOL minimizable, - BOOL close_btn, - BOOL bordered) -: LLPanel(name, rect_control, bordered), mAutoFocus(TRUE) // automatically take focus when opened -{ - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } - for (S32 i = 0; i < 4; i++) - { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; - } - initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn); + initFloater(); } - // Note: Floaters constructed from XML call init() twice! -void LLFloater::initFloater(const std::string& title, - BOOL resizable, S32 min_width, S32 min_height, - BOOL drag_on_left, BOOL minimizable, BOOL close_btn) +void LLFloater::initFloater() { - mHandle.bind(this); - mNotificationContext = new LLFloaterNotificationContext(getHandle()); - - // Init function can be called more than once, so clear out old data. - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - if (mButtons[i] != NULL) - { - removeChild(mButtons[i]); - delete mButtons[i]; - mButtons[i] = NULL; - } - } - mButtonScale = 1.f; + addDragHandle(); + + addResizeCtrls(); - //sjb: Thia is a bit of a hack: - BOOL need_border = hasBorder(); - // remove the border since deleteAllChildren() will also delete the border (but not clear mBorder) - removeBorder(); - // this will delete mBorder too - deleteAllChildren(); - // add the border back if we want it - if (need_border) + // Close button. + if (mCanClose) { - addBorder(); + mButtonsEnabled[BUTTON_CLOSE] = TRUE; } - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); - - // Reset cached pointers - mDragHandle = NULL; - for (S32 i = 0; i < 4; i++) + // Minimize button only for top draggers + if ( !mDragOnLeft && mCanMinimize ) { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; + mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; } - mCanTearOff = TRUE; - mEditing = FALSE; - // Clicks stop here. - setMouseOpaque(TRUE); + buildButtons(); - mFirstLook = TRUE; - mForeground = FALSE; - mDragOnLeft = drag_on_left == TRUE; + // Floaters are created in the invisible state + setVisible(FALSE); - // Floaters always draw their background, unlike every other panel. - setBackgroundVisible(TRUE); + // add self to handle->floater map + sFloaterMap[mHandle] = this; - // Floaters start not minimized. When minimized, they save their - // prior rectangle to be used on restore. - mMinimized = FALSE; - mExpandedRect.set(0,0,0,0); - - S32 close_pad; // space to the right of close box - S32 close_box_size; // For layout purposes, how big is the close box? - if (close_btn) - { - close_box_size = LLFLOATER_CLOSE_BOX_SIZE; - close_pad = 0; - } - else + if (!getParent()) { - close_box_size = 0; - close_pad = 0; + gFloaterView->addChild(this); } +} - S32 minimize_box_size; - S32 minimize_pad; - if (minimizable && !drag_on_left) - { - minimize_box_size = LLFLOATER_CLOSE_BOX_SIZE; - minimize_pad = 0; - } - else +void LLFloater::addDragHandle() +{ + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + S32 close_box_size = mCanClose ? floater_close_box_size : 0; + + if (!mDragHandle) { - minimize_box_size = 0; - minimize_pad = 0; + if (mDragOnLeft) + { + LLDragHandleLeft::Params p; + p.name("drag"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + else // drag on top + { + LLDragHandleTop::Params p; + p.name("Drag Handle"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + addChild(mDragHandle); } - - // Drag Handle - // Add first so it's in the background. -// const S32 drag_pad = 2; - if (drag_on_left) + LLRect rect; + if (mDragOnLeft) { - LLRect drag_handle_rect; - drag_handle_rect.setOriginAndSize( - 0, 0, - DRAG_HANDLE_WIDTH, - getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); - mDragHandle = new LLDragHandleLeft(std::string("drag"), drag_handle_rect, title ); + rect.setLeftTopAndSize(0, 0, DRAG_HANDLE_WIDTH, getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); } else // drag on top { - LLRect drag_handle_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mDragHandle = new LLDragHandleTop( std::string("Drag Handle"), drag_handle_rect, title ); - } - addChild(mDragHandle); - - // Resize Handle - mResizable = resizable; - mMinWidth = min_width; - mMinHeight = min_height; - - if( mResizable ) - { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[LLResizeBar::LEFT] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - min_width, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[LLResizeBar::TOP] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - min_height, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - min_width, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - min_height, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - min_width, - min_height, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( - std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - min_width, - min_height, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - min_width, - min_height, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - min_width, - min_height, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); + rect = getLocalRect(); } + mDragHandle->setRect(rect); + updateButtons(); + applyTitle(); +} - // Close button. - if (close_btn) +void LLFloater::addResizeCtrls() +{ + for (S32 i = 0; i < 4; i++) { - mButtonsEnabled[BUTTON_CLOSE] = TRUE; + if (mResizeBar[i]) + { + removeChild(mResizeBar[i]); + delete mResizeBar[i]; + mResizeBar[i] = NULL; + } + if (mResizeHandle[i]) + { + removeChild(mResizeHandle[i]); + delete mResizeHandle[i]; + mResizeHandle[i] = NULL; + } } - - // Minimize button only for top draggers - if ( !drag_on_left && minimizable ) + if( !mResizable ) { - mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; + return; } + + // Resize bars (sides) + const S32 RESIZE_BAR_THICKNESS = 3; + LLResizeBar::Params p; + p.name("resizebar_left"); + p.resizing_view(this); + p.rect(LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0)); + p.min_size(mMinWidth); + p.side(LLResizeBar::LEFT); + mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::LEFT] ); + + p.name("resizebar_top"); + p.rect(LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS)); + p.min_size(mMinHeight); + p.side(LLResizeBar::TOP); + + mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::TOP] ); + + p.name("resizebar_right"); + p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0)); + p.min_size(mMinWidth); + p.side(LLResizeBar::RIGHT); + + mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::RIGHT] ); + + p.name("resizebar_bottom"); + p.rect(LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0)); + p.min_size(mMinHeight); + p.side(LLResizeBar::BOTTOM); + mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::BOTTOM] ); + + // Resize handles (corners) + LLResizeHandle::Params handle_p; + handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0)); + handle_p.min_width(mMinWidth); + handle_p.min_height(mMinHeight); + handle_p.corner(LLResizeHandle::RIGHT_BOTTOM); + mResizeHandle[0] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[0]); + + handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT)); + handle_p.corner(LLResizeHandle::RIGHT_TOP); + mResizeHandle[1] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[1]); + + handle_p.rect(LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 )); + handle_p.corner(LLResizeHandle::LEFT_BOTTOM); + mResizeHandle[2] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[2]); - // Keep track of whether this window has ever been dragged while it - // was minimized. If it has, we'll remember its position for the - // next time it's minimized. - mHasBeenDraggedWhileMinimized = FALSE; - mPreviousMinimizedLeft = 0; - mPreviousMinimizedBottom = 0; - - buildButtons(); - - // JC - Don't do this here, because many floaters first construct themselves, - // then show themselves. Put it in setVisibleAndFrontmost. - // make_ui_sound("UISndWindowOpen"); - - // RN: floaters are created in the invisible state - setVisible(FALSE); - - // add self to handle->floater map - sFloaterMap[mHandle] = this; - - if (!getParent()) - { - gFloaterView->addChild(this); - } + handle_p.rect(LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT )); + handle_p.corner(LLResizeHandle::LEFT_TOP); + mResizeHandle[3] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[3]); } // virtual LLFloater::~LLFloater() { + LLFloaterReg::removeInstance(mInstanceName, mKey); + delete mNotificationContext; mNotificationContext = NULL; - control_map_t::iterator itor; - for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor) - { - delete itor->second; - } - mFloaterControls.clear(); - //// am I not hosted by another floater? //if (mHostHandle.isDead()) //{ @@ -469,8 +450,27 @@ LLFloater::~LLFloater() delete mResizeBar[i]; delete mResizeHandle[i]; } + + storeRectControl(); + setVisible(false); // We're not visible if we're destroyed + storeVisibilityControl(); +} + +void LLFloater::storeRectControl() +{ + if( mRectControl.size() > 1 ) + { + LLUI::sSettingGroups["floater"]->setRect( mRectControl, getRect() ); + } } +void LLFloater::storeVisibilityControl() +{ + if( mVisibilityControl.size() > 1 ) + { + LLUI::sSettingGroups["floater"]->setBOOL( mVisibilityControl, getVisible() ); + } +} void LLFloater::setVisible( BOOL visible ) { @@ -504,10 +504,25 @@ void LLFloater::setVisible( BOOL visible ) } ++dependent_it; } + + storeVisibilityControl(); +} + +// virtual +void LLFloater::onVisibilityChange ( BOOL new_visibility ) +{ + if (new_visibility) + { + if (getHost()) + getHost()->setFloaterFlashing(this, FALSE); + } + LLPanel::onVisibilityChange ( new_visibility ); } -void LLFloater::open() /* Flawfinder: ignore */ +void LLFloater::openFloater(const LLSD& key) { + mKey = key; // in case we need to open ourselves again + if (getSoundFlags() != SILENT // don't play open sound for hosted (tabbed) windows && !getHost() @@ -525,9 +540,11 @@ void LLFloater::open() /* Flawfinder: ignore */ // only select tabs if window they are hosted in is visible getFloaterHost()->addFloater(this, getFloaterHost()->getVisible()); } - else if (getHost() != NULL) + + if (getHost() != NULL) { - // already hosted + getHost()->setMinimized(FALSE); + getHost()->setVisibleAndFrontmost(mAutoFocus); getHost()->showFloater(this); } else @@ -536,10 +553,10 @@ void LLFloater::open() /* Flawfinder: ignore */ setVisibleAndFrontmost(mAutoFocus); } - onOpen(); + onOpen(key); } -void LLFloater::close(bool app_quitting) +void LLFloater::closeFloater(bool app_quitting) { // Always unminimize before trying to close. // Most of the time the user will never see this state. @@ -570,7 +587,7 @@ void LLFloater::close(bool app_quitting) if (floaterp) { ++dependent_it; - floaterp->close(); + floaterp->closeFloater(app_quitting); } else { @@ -597,7 +614,7 @@ void LLFloater::close(bool app_quitting) } } } - + // Let floater do cleanup. onClose(app_quitting); } @@ -607,6 +624,7 @@ void LLFloater::close(bool app_quitting) void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) { LLPanel::reshape(width, height, called_from_parent); + storeRectControl(); } void LLFloater::releaseFocus() @@ -664,15 +682,23 @@ void LLFloater::center() centerWithin(gFloaterView->getRect()); } +LLMultiFloater* LLFloater::getHost() +{ + return (LLMultiFloater*)mHostHandle.get(); +} + void LLFloater::applyRectControl() { - if (!getRectControl().empty()) + if (mRectControl.size() > 1) { - const LLRect& rect = LLUI::sConfigGroup->getRect(getRectControl()); - translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom); - if (mResizable) + const LLRect& rect = LLUI::sSettingGroups["floater"]->getRect(mRectControl); + if (rect.getWidth() > 0 && rect.getHeight() > 0) { - reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom); + if (mResizable) + { + reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } } } } @@ -763,7 +789,7 @@ BOOL LLFloater::canSnapTo(const LLView* other_view) return LLPanel::canSnapTo(other_view); } -void LLFloater::snappedTo(const LLView* snap_view) +void LLFloater::setSnappedTo(const LLView* snap_view) { if (!snap_view || snap_view == getParent()) { @@ -778,10 +804,10 @@ void LLFloater::snappedTo(const LLView* snap_view) } } -void LLFloater::userSetShape(const LLRect& new_rect) +void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) { const LLRect old_rect = getRect(); - LLView::userSetShape(new_rect); + LLView::handleReshape(new_rect, by_user); // if not minimized, adjust all snapped dependents to new shape if (!isMinimized()) @@ -816,7 +842,7 @@ void LLFloater::userSetShape(const LLRect& new_rect) delta_y += new_rect.mBottom - old_rect.mBottom; dependent_rect.translate(delta_x, delta_y); - floaterp->userSetShape(dependent_rect); + floaterp->setShape(dependent_rect, by_user); } } } @@ -834,6 +860,9 @@ void LLFloater::userSetShape(const LLRect& new_rect) void LLFloater::setMinimized(BOOL minimize) { + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); + if (minimize == mMinimized) return; if (minimize) @@ -902,7 +931,7 @@ void LLFloater::setMinimized(BOOL minimize) mMinimized = TRUE; // Reshape *after* setting mMinimized - reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE); + reshape( minimized_width, floater_header_size, TRUE); } else { @@ -995,6 +1024,13 @@ void LLFloater::setFocus( BOOL b ) } } +// virtual +void LLFloater::setRect(const LLRect &rect) +{ + LLPanel::setRect(rect); + addDragHandle(); // re-add drag handle, sized based on rect +} + // virtual void LLFloater::setIsChrome(BOOL is_chrome) { @@ -1276,19 +1312,18 @@ void LLFloater::setEditModeEnabled(BOOL enable) // static -void LLFloater::onClickMinimize(void *userdata) +void LLFloater::onClickMinimize(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + if (!self) + return; self->setMinimized( !self->isMinimized() ); } -void LLFloater::onClickTearOff(void *userdata) +void LLFloater::onClickTearOff(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + if (!self) + return; LLMultiFloater* host_floater = self->getHost(); if (host_floater) //Tear off { @@ -1297,12 +1332,12 @@ void LLFloater::onClickTearOff(void *userdata) // reparent to floater view gFloaterView->addChild(self); - self->open(); /* Flawfinder: ignore */ + self->openFloater(self->getKey()); // only force position for floaters that don't have that data saved - if (self->getRectControl().empty()) + if (self->mRectControl.size() <= 1) { - new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->getRect().getWidth(), self->getRect().getHeight()); + new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); self->setRect(new_rect); } gFloaterView->adjustToFitScreen(self, FALSE); @@ -1317,17 +1352,16 @@ void LLFloater::onClickTearOff(void *userdata) self->setMinimized(FALSE); // to reenable minimize button if it was minimized new_host->showFloater(self); // make sure host is visible - new_host->open(); + new_host->openFloater(new_host->getKey()); } } } // static -void LLFloater::onClickEdit(void *userdata) +void LLFloater::onClickEdit(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + if (!self) + return; self->mEditing = self->mEditing ? FALSE : TRUE; } @@ -1373,7 +1407,7 @@ void LLFloater::closeFocusedFloater() LLFloater* floater_to_close = LLFloater::getClosableFloaterFromFocus(); if(floater_to_close) { - floater_to_close->close(); + floater_to_close->closeFloater(); } // if nothing took focus after closing focused floater @@ -1388,12 +1422,11 @@ void LLFloater::closeFocusedFloater() // static -void LLFloater::onClickClose( void* userdata ) +void LLFloater::onClickClose( LLFloater* self ) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - - self->close(); + if (!self) + return; + self->closeFloater(false); } @@ -1408,8 +1441,11 @@ void LLFloater::draw() S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH; S32 bottom = LLPANEL_BORDER_WIDTH; - LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow"); - F32 shadow_offset = (F32)LLUI::sConfigGroup->getS32("DropShadowFloater"); + static LLUICachedControl shadow_offset_S32 ("DropShadowFloater", 0); + static LLUICachedControl shadow_color_cached ("ColorDropShadow", *(new LLColor4)); + LLColor4 shadow_color = shadow_color_cached; + F32 shadow_offset = (F32)shadow_offset_S32; + if (!isBackgroundOpaque()) { shadow_offset *= 0.2f; @@ -1422,20 +1458,21 @@ void LLFloater::draw() // No transparent windows in simple UI if (isBackgroundOpaque()) { - gl_rect_2d( left, top, right, bottom, getBackgroundColor() ); + gl_rect_2d( left, top, right, bottom, mBgColorOpaque ); } else { - gl_rect_2d( left, top, right, bottom, getTransparentColor() ); + gl_rect_2d( left, top, right, bottom, mBgColorAlpha ); } if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty()) { + static LLUICachedControl titlebar_focus_color ("TitleBarFocusColor", *(new LLColor4)); // draw highlight on title bar to indicate focus. RDW - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); + const LLFontGL* font = LLFontGL::getFontSansSerif(); LLRect r = getRect(); gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, - LLUI::sColorsGroup->getColor("TitleBarFocusColor"), 0, TRUE); + titlebar_focus_color, 0, TRUE); } } @@ -1489,8 +1526,10 @@ void LLFloater::draw() { // add in a border to improve spacialized visual aclarity ;) // use lines instead of gl_rect_2d so we can round the edges as per james' recommendation + static LLUICachedControl focus_border_color ("FloaterFocusBorderColor", *(new LLColor4)); + static LLUICachedControl unfocus_border_color ("FloaterUnfocusBorderColor", *(new LLColor4)); LLUI::setLineWidth(1.5f); - LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? LLUI::sColorsGroup->getColor("FloaterFocusBorderColor") : LLUI::sColorsGroup->getColor("FloaterUnfocusBorderColor"); + 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); LLUI::setLineWidth(1.f); } @@ -1511,6 +1550,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) { // if removing minimize/restore button programmatically, // go ahead and unminimize floater + mCanMinimize = can_minimize; if (!can_minimize) { setMinimized(FALSE); @@ -1524,6 +1564,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) void LLFloater::setCanClose(BOOL can_close) { + mCanClose = can_close; mButtonsEnabled[BUTTON_CLOSE] = can_close; updateButtons(); @@ -1538,83 +1579,10 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) } -void LLFloater::setCanResize(BOOL can_resize) +void LLFloater::setCanResize(BOOL can_resize) { - if (mResizable && !can_resize) - { - for (S32 i = 0; i < 4; i++) - { - removeChild(mResizeBar[i], TRUE); - mResizeBar[i] = NULL; - - removeChild(mResizeHandle[i], TRUE); - mResizeHandle[i] = NULL; - } - } - else if (!mResizable && can_resize) - { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[0] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - mMinWidth, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[1] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - mMinHeight, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[2] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - mMinWidth, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[3] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - mMinHeight, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); - } mResizable = can_resize; + addResizeCtrls(); } void LLFloater::setCanDrag(BOOL can_drag) @@ -1633,6 +1601,8 @@ void LLFloater::setCanDrag(BOOL can_drag) void LLFloater::updateButtons() { + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); S32 button_count = 0; for (S32 i = 0; i < BUTTON_COUNT; i++) { @@ -1652,17 +1622,17 @@ void LLFloater::updateButtons() { btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH, - getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count, - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * button_count, + llround((F32)floater_close_box_size * mButtonScale), + llround((F32)floater_close_box_size * mButtonScale)); } else { btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count, - getRect().getHeight() - CLOSE_BOX_FROM_TOP, - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * button_count, + getRect().getHeight() - close_box_from_top, + llround((F32)floater_close_box_size * mButtonScale), + llround((F32)floater_close_box_size * mButtonScale)); } mButtons[i]->setRect(btn_rect); @@ -1676,50 +1646,56 @@ void LLFloater::updateButtons() } } if (mDragHandle) - mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1))); + mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); } void LLFloater::buildButtons() { + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); for (S32 i = 0; i < BUTTON_COUNT; i++) { + if (mButtons[i]) + { + removeChild(mButtons[i]); + delete mButtons[i]; + mButtons[i] = NULL; + } + LLRect btn_rect; if (mDragOnLeft) { btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH, - getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * (i + 1), + llround(floater_close_box_size * mButtonScale), + llround(floater_close_box_size * mButtonScale)); } else { btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1), - getRect().getHeight() - CLOSE_BOX_FROM_TOP, - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); - } - - LLButton* buttonp = new LLButton( - sButtonNames[i], - btn_rect, - sButtonActiveImageNames[i], - sButtonPressedImageNames[i], - LLStringUtil::null, - sButtonCallbacks[i], - this, - LLFontGL::getFontSansSerif()); - - buttonp->setTabStop(FALSE); - buttonp->setFollowsTop(); - buttonp->setFollowsRight(); - buttonp->setToolTip( sButtonToolTips[i] ); - buttonp->setImageColor(LLUI::sColorsGroup->getColor("FloaterButtonImageColor")); - buttonp->setHoverImages(sButtonPressedImageNames[i], - sButtonPressedImageNames[i]); - buttonp->setScaleImage(TRUE); - buttonp->setSaveToXML(false); + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * (i + 1), + getRect().getHeight() - close_box_from_top, + llround(floater_close_box_size * mButtonScale), + llround(floater_close_box_size * mButtonScale)); + } + + LLButton::Params p; + p.name(sButtonNames[i]); + p.rect(btn_rect); + p.label(""); + p.image_unselected.name(sButtonActiveImageNames[i]); + p.image_selected.name(sButtonPressedImageNames[i]); + p.image_hover_selected.name(sButtonPressedImageNames[i]); + p.image_hover_unselected.name(sButtonPressedImageNames[i]); + p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); + p.tab_stop(false); + p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); + p.tool_tip(sButtonToolTips[i]); + p.image_color(LLUI::getCachedColorFunctor("FloaterButtonImageColor")); + p.scale_image(true); + + LLButton* buttonp = LLUICtrlFactory::create(p); addChild(buttonp); mButtons[i] = buttonp; } @@ -1730,13 +1706,11 @@ void LLFloater::buildButtons() ///////////////////////////////////////////////////// // LLFloaterView -LLFloaterView::LLFloaterView( const std::string& name, const LLRect& rect ) -: LLUICtrl( name, rect, FALSE, NULL, NULL, FOLLOWS_ALL ), +LLFloaterView::LLFloaterView (const Params& p) +: LLUICtrl (p), mFocusCycleMode(FALSE), mSnapOffsetBottom(0) { - setTabStop(FALSE); - resetStartingFloaterPosition(); } // By default, adjust vertical. @@ -1830,69 +1804,6 @@ void LLFloaterView::restoreAll() } -void LLFloaterView::getNewFloaterPosition(S32* left,S32* top) -{ - // Workaround: mRect may change between when this object is created and the first time it is used. - static BOOL first = TRUE; - if( first ) - { - resetStartingFloaterPosition(); - first = FALSE; - } - - const S32 FLOATER_PAD = 16; - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - LLRect full_window(0, window_size.mY, window_size.mX, 0); - LLRect floater_creation_rect( - 160, - full_window.getHeight() - 2 * MENU_BAR_HEIGHT, - full_window.getWidth() * 2 / 3, - 130 ); - floater_creation_rect.stretch( -FLOATER_PAD ); - - *left = mNextLeft; - *top = mNextTop; - - const S32 STEP = 25; - S32 bottom = floater_creation_rect.mBottom + 2 * STEP; - S32 right = floater_creation_rect.mRight - 4 * STEP; - - mNextTop -= STEP; - mNextLeft += STEP; - - if( (mNextTop < bottom ) || (mNextLeft > right) ) - { - mColumn++; - mNextTop = floater_creation_rect.mTop; - mNextLeft = STEP * mColumn; - - if( (mNextTop < bottom) || (mNextLeft > right) ) - { - // Advancing the column didn't work, so start back at the beginning - resetStartingFloaterPosition(); - } - } -} - -void LLFloaterView::resetStartingFloaterPosition() -{ - const S32 FLOATER_PAD = 16; - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - LLRect full_window(0, window_size.mY, window_size.mX, 0); - LLRect floater_creation_rect( - 160, - full_window.getHeight() - 2 * MENU_BAR_HEIGHT, - full_window.getWidth() * 2 / 3, - 130 ); - floater_creation_rect.stretch( -FLOATER_PAD ); - - mNextLeft = floater_creation_rect.mLeft; - mNextTop = floater_creation_rect.mTop; - mColumn = 0; -} - LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ) { LLRect base_rect = reference_floater->getRect(); @@ -2104,15 +2015,17 @@ void LLFloaterView::focusFrontFloater() void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) { + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); S32 col = 0; LLRect snap_rect_local = getLocalSnapRect(); for(S32 row = snap_rect_local.mBottom; - row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE; - row += LLFLOATER_HEADER_SIZE ) //loop rows + row < snap_rect_local.getHeight() - floater_header_size; + row += floater_header_size ) //loop rows { for(col = snap_rect_local.mLeft; - col < snap_rect_local.getWidth() - MINIMIZED_WIDTH; - col += MINIMIZED_WIDTH) + col < snap_rect_local.getWidth() - minimized_width; + col += minimized_width) { bool foundGap = TRUE; for(child_list_const_iter_t child_it = getChildList()->begin(); @@ -2124,10 +2037,10 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) if(floater->isMinimized()) { LLRect r = floater->getRect(); - if((r.mBottom < (row + LLFLOATER_HEADER_SIZE)) - && (r.mBottom > (row - LLFLOATER_HEADER_SIZE)) - && (r.mLeft < (col + MINIMIZED_WIDTH)) - && (r.mLeft > (col - MINIMIZED_WIDTH))) + if((r.mBottom < (row + floater_header_size)) + && (r.mBottom > (row - floater_header_size)) + && (r.mLeft < (col + minimized_width)) + && (r.mLeft > (col - minimized_width))) { // needs the check for off grid. can't drag, // but window resize makes them off @@ -2179,7 +2092,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting) // dialogs to appear. if (floaterp->canClose() && !floaterp->isDead()) { - floaterp->close(app_quitting); + floaterp->closeFloater(app_quitting); } } } @@ -2202,14 +2115,13 @@ BOOL LLFloaterView::allChildrenClosed() return true; } - void LLFloaterView::refresh() { // Constrain children to be entirely on the screen for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; - if( floaterp->getVisible() ) + LLFloater* floaterp = dynamic_cast(*child_it); + if (floaterp && floaterp->getVisible() ) { // minimized floaters are kept fully onscreen adjustToFitScreen(floaterp, !floaterp->isMinimized()); @@ -2306,7 +2218,7 @@ LLRect LLFloaterView::getSnapRect() const return snap_rect; } -LLFloater *LLFloaterView::getFocusedFloater() +LLFloater *LLFloaterView::getFocusedFloater() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2319,7 +2231,7 @@ LLFloater *LLFloaterView::getFocusedFloater() return NULL; } -LLFloater *LLFloaterView::getFrontmost() +LLFloater *LLFloaterView::getFrontmost() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2332,7 +2244,7 @@ LLFloater *LLFloaterView::getFrontmost() return NULL; } -LLFloater *LLFloaterView::getBackmost() +LLFloater *LLFloaterView::getBackmost() const { LLFloater* back_most = NULL; for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) @@ -2348,18 +2260,51 @@ LLFloater *LLFloaterView::getBackmost() void LLFloaterView::syncFloaterTabOrder() { - // bring focused floater to front - for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) + // look for a visible modal dialog, starting from first (should be only one) + LLModalDialog* modal_dialog = NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; - if (gFocusMgr.childHasKeyboardFocus(floaterp)) + LLModalDialog* dialog = dynamic_cast(*child_it); + if (dialog && dialog->isModal() && dialog->getVisible()) { - bringToFront(floaterp, FALSE); + modal_dialog = dialog; break; } } - // then sync draw order to tab order + if (modal_dialog) + { + // If we have a visible modal dialog, make sure that it has focus + if( gFocusMgr.getTopCtrl() != modal_dialog ) + { + gFocusMgr.setTopCtrl( modal_dialog ); + } + + if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) ) + { + modal_dialog->setFocus(TRUE); + } + + if( !gFocusMgr.childHasMouseCapture( modal_dialog ) ) + { + gFocusMgr.setMouseCapture( modal_dialog ); + } + } + else + { + // otherwise, make sure the focused floater is in the front of the child list + for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) + { + LLFloater* floaterp = (LLFloater*)*child_it; + if (gFocusMgr.childHasKeyboardFocus(floaterp)) + { + bringToFront(floaterp, FALSE); + break; + } + } + } + + // sync draw order to tab order for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) { LLFloater* floaterp = (LLFloater*)*child_it; @@ -2367,7 +2312,7 @@ void LLFloaterView::syncFloaterTabOrder() } } -LLFloater* LLFloaterView::getParentFloater(LLView* viewp) +LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const { LLView* parentp = viewp->getParent(); @@ -2426,641 +2371,137 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) } } -// -// LLMultiFloater -// - -LLMultiFloater::LLMultiFloater() : - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(TRUE), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - -} - -LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) : - mTabContainer(NULL), - mTabPos(tab_pos), - mAutoResize(TRUE), - mOrigMinWidth(0), - mOrigMinHeight(0) +void LLFloater::setInstanceName(const std::string& name) { - -} - -LLMultiFloater::LLMultiFloater(const std::string &name) : - LLFloater(name), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(FALSE), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ -} - -LLMultiFloater::LLMultiFloater( - const std::string& name, - const LLRect& rect, - LLTabContainer::TabPosition tab_pos, - BOOL auto_resize) : - LLFloater(name, rect, name), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(auto_resize), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - mTabContainer = new LLTabContainer(std::string("Preview Tabs"), - LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0), - mTabPos, - FALSE, - FALSE); - mTabContainer->setFollowsAll(); - if (isResizable()) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - - addChild(mTabContainer); -} - -LLMultiFloater::LLMultiFloater( - const std::string& name, - const std::string& rect_control, - LLTabContainer::TabPosition tab_pos, - BOOL auto_resize) : - LLFloater(name, rect_control, name), - mTabContainer(NULL), - mTabPos(tab_pos), - mAutoResize(auto_resize), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - mTabContainer = new LLTabContainer(std::string("Preview Tabs"), - LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0), - mTabPos, - FALSE, - FALSE); - mTabContainer->setFollowsAll(); - if (isResizable() && mTabPos == LLTabContainer::BOTTOM) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - - addChild(mTabContainer); - -} - - -void LLMultiFloater::open() /* Flawfinder: ignore */ -{ - if (mTabContainer->getTabCount() > 0) - { - LLFloater::open(); /* Flawfinder: ignore */ - } - else - { - // for now, don't allow multifloaters - // without any child floaters - close(); - } -} - -void LLMultiFloater::onClose(bool app_quitting) -{ - if(closeAllFloaters() == TRUE) - { - LLFloater::onClose(app_quitting); - }//else not all tabs could be closed... -} - -void LLMultiFloater::draw() -{ - if (mTabContainer->getTabCount() == 0) - { - //RN: could this potentially crash in draw hierarchy? - close(); - } - else + if (name == mInstanceName) + return; + llassert_always(mInstanceName.empty()); + mInstanceName = name; + if (!mInstanceName.empty()) { - for (S32 i = 0; i < mTabContainer->getTabCount(); i++) + // save_rect and save_visibility only apply to registered floaters + if (!mRectControl.empty()) { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i); - if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i)) - { - mTabContainer->setPanelTitle(i, floaterp->getShortTitle()); - } + mRectControl = LLFloaterReg::declareRectControl(mInstanceName); } - LLFloater::draw(); - } -} - -BOOL LLMultiFloater::closeAllFloaters() -{ - S32 tabToClose = 0; - S32 lastTabCount = mTabContainer->getTabCount(); - while (tabToClose < mTabContainer->getTabCount()) - { - LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose); - first_floater->close(); - if(lastTabCount == mTabContainer->getTabCount()) + if (!mVisibilityControl.empty()) { - //Tab did not actually close, possibly due to a pending Save Confirmation dialog.. - //so try and close the next one in the list... - tabToClose++; - }else - { - //Tab closed ok. - lastTabCount = mTabContainer->getTabCount(); + mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName); } } - if( mTabContainer->getTabCount() != 0 ) - return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE. - return TRUE; //else all tabs were successfully closed... } -void LLMultiFloater::growToFit(S32 content_width, S32 content_height) +void LLFloater::setKey(const LLSD& newkey) { - S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2); - S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); - - if (isMinimized()) - { - LLRect newrect; - newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height); - setExpandedRect(newrect); - } - else - { - S32 old_height = getRect().getHeight(); - reshape(new_width, new_height); - // keep top left corner in same position - translate(0, old_height - new_height); - } + // Note: We don't have to do anything special with registration when we change keys + mKey = newkey; } -/** - void addFloater(LLFloater* floaterp, BOOL select_added_floater) - - Adds the LLFloater pointed to by floaterp to this. - If floaterp is already hosted by this, then it is re-added to get - new titles, etc. - If select_added_floater is true, the LLFloater pointed to by floaterp will - become the selected tab in this - - Affects: mTabContainer, floaterp -**/ -void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) +void LLFloater::initFromParams(const LLFloater::Params& p) { - if (!floaterp) - { - return; - } - - if (!mTabContainer) - { - llerrs << "Tab Container used without having been initialized." << llendl; - return; - } - - if (floaterp->getHost() == this) - { - // already hosted by me, remove - // do this so we get updated title, etc. - mFloaterDataMap.erase(floaterp->getHandle()); - mTabContainer->removeTabPanel(floaterp); - } - else if (floaterp->getHost()) - { - // floaterp is hosted by somebody else and - // this is adding it, so remove it from it's old host - floaterp->getHost()->removeFloater(floaterp); - } - else if (floaterp->getParent() == gFloaterView) - { - // rehost preview floater as child panel - gFloaterView->removeChild(floaterp); - } - - // store original configuration - LLFloaterData floater_data; - floater_data.mWidth = floaterp->getRect().getWidth(); - floater_data.mHeight = floaterp->getRect().getHeight(); - floater_data.mCanMinimize = floaterp->isMinimizeable(); - floater_data.mCanResize = floaterp->isResizable(); - - // remove minimize and close buttons - floaterp->setCanMinimize(FALSE); - floaterp->setCanResize(FALSE); - floaterp->setCanDrag(FALSE); - floaterp->storeRectControl(); - // avoid double rendering of floater background (makes it more opaque) - floaterp->setBackgroundVisible(FALSE); - - if (mAutoResize) - { - growToFit(floater_data.mWidth, floater_data.mHeight); - } + // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible + LLPanel::initFromParams(p); - //add the panel, add it to proper maps - mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point); - mFloaterDataMap[floaterp->getHandle()] = floater_data; + mTitle = p.title; + mShortTitle = p.short_title; + applyTitle(); - updateResizeLimits(); + setCanTearOff(p.can_tear_off); + setCanMinimize(p.can_minimize); + setCanClose(p.can_close); + + mDragOnLeft = p.can_drag_on_left; + mResizable = p.can_resize; + mMinWidth = p.min_width; + mMinHeight = p.min_height; + mSingleInstance = p.single_instance; + mAutoTile = p.auto_tile; - if ( select_added_floater ) + if (p.save_rect) { - mTabContainer->selectTabPanel(floaterp); + mRectControl = "t"; // flag to build mRectControl name once mInstanceName is set } - else + if (p.save_visibility) { - // reassert visible tab (hiding new floater if necessary) - mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); + mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set } - - floaterp->setHost(this); - if (isMinimized()) - { - floaterp->setVisible(FALSE); - } -} - -/** - BOOL selectFloater(LLFloater* floaterp) - - If the LLFloater pointed to by floaterp is hosted by this, - then its tab is selected and returns true. Otherwise returns false. - - Affects: mTabContainer -**/ -BOOL LLMultiFloater::selectFloater(LLFloater* floaterp) -{ - return mTabContainer->selectTabPanel(floaterp); -} - -// virtual -void LLMultiFloater::selectNextFloater() -{ - mTabContainer->selectNextTab(); } -// virtual -void LLMultiFloater::selectPrevFloater() +void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floater, LLXMLNodePtr output_node) { - mTabContainer->selectPrevTab(); -} + Params params(LLUICtrlFactory::getDefaultParams()); + LLXUIParser::instance().readXUI(node, params); -void LLMultiFloater::showFloater(LLFloater* floaterp) -{ - // we won't select a panel that already is selected - // it is hard to do this internally to tab container - // as tab selection is handled via index and the tab at a given - // index might have changed - if (floaterp != mTabContainer->getCurrentPanel() && - !mTabContainer->selectTabPanel(floaterp)) + if (output_node) { - addFloater(floaterp, TRUE); + Params output_params(params); + setupParamsForExport(output_params, parent); + Params default_params(LLUICtrlFactory::getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); } -} -void LLMultiFloater::removeFloater(LLFloater* floaterp) -{ - if ( floaterp->getHost() != this ) - return; - - floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle()); - if (found_data_it != mFloaterDataMap.end()) + setupParams(params, parent); + initFromParams(params); + + initFloater(); + + LLMultiFloater* last_host = LLFloater::getFloaterHost(); + if (node->hasName("multi_floater")) { - LLFloaterData& floater_data = found_data_it->second; - floaterp->setCanMinimize(floater_data.mCanMinimize); - if (!floater_data.mCanResize) - { - // restore original size - floaterp->reshape(floater_data.mWidth, floater_data.mHeight); - } - floaterp->setCanResize(floater_data.mCanResize); - mFloaterDataMap.erase(found_data_it); + LLFloater::setFloaterHost((LLMultiFloater*) this); } - mTabContainer->removeTabPanel(floaterp); - floaterp->setBackgroundVisible(TRUE); - floaterp->setCanDrag(TRUE); - floaterp->setHost(NULL); - floaterp->applyRectControl(); - - updateResizeLimits(); - - tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); -} -void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click) -{ - // default implementation does nothing -} + addChildren(node, output_node); -void LLMultiFloater::tabClose() -{ - if (mTabContainer->getTabCount() == 0) + if (node->hasName("multi_floater")) { - // no more children, close myself - close(); + LLFloater::setFloaterHost(last_host); } -} - -void LLMultiFloater::setVisible(BOOL visible) -{ - // *FIX: shouldn't have to do this, fix adding to minimized multifloater - LLFloater::setVisible(visible); - if (mTabContainer) - { - LLPanel* cur_floaterp = mTabContainer->getCurrentPanel(); - - if (cur_floaterp) - { - cur_floaterp->setVisible(visible); - } - - // if no tab selected, and we're being shown, - // select last tab to be added - if (visible && !cur_floaterp) - { - mTabContainer->selectLastTab(); - } - } -} + BOOL result = postBuild(); -BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask) -{ - if (key == 'W' && mask == MASK_CONTROL) + if (!result) { - LLFloater* floater = getActiveFloater(); - // is user closeable and is system closeable - if (floater && floater->canClose() && floater->isCloseable()) - { - floater->close(); - } - return TRUE; + llerrs << "Failed to construct floater " << getName() << llendl; } - return LLFloater::handleKeyHere(key, mask); -} - -LLFloater* LLMultiFloater::getActiveFloater() -{ - return (LLFloater*)mTabContainer->getCurrentPanel(); -} - -S32 LLMultiFloater::getFloaterCount() -{ - return mTabContainer->getTabCount(); -} - -/** - BOOL isFloaterFlashing(LLFloater* floaterp) - - Returns true if the LLFloater pointed to by floaterp - is currently in a flashing state and is hosted by this. - False otherwise. - - Requires: floaterp != NULL -**/ -BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp) -{ - if ( floaterp && floaterp->getHost() == this ) - return mTabContainer->getTabPanelFlashing(floaterp); - - return FALSE; -} - -/** - BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing) - - Sets the current flashing state of the LLFloater pointed - to by floaterp to be the BOOL flashing if the LLFloater pointed - to by floaterp is hosted by this. - - Requires: floaterp != NULL -**/ -void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing) -{ - if ( floaterp && floaterp->getHost() == this ) - mTabContainer->setTabPanelFlashing(floaterp, flashing); -} - -//static -void LLMultiFloater::onTabSelected(void* userdata, bool from_click) -{ - LLMultiFloater* floaterp = (LLMultiFloater*)userdata; - - floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click); -} + applyRectControl(); // If we have a saved rect control, apply it + gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen -void LLMultiFloater::setCanResize(BOOL can_resize) -{ - LLFloater::setCanResize(can_resize); - if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM) + if (open_floater) { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - else - { - mTabContainer->setRightTabBtnOffset(0); + this->openFloater(getKey()); } + + moveResizeHandlesToFront(); } -BOOL LLMultiFloater::postBuild() +// visibility methods +bool VisibilityPolicy::visible(LLFloater* instance, const LLSD& key) { - // remember any original xml minimum size - getResizeLimits(&mOrigMinWidth, &mOrigMinHeight); - - if (mTabContainer) - { - return TRUE; - } - - requires("Preview Tabs"); - if (checkRequirements()) + if (instance) { - mTabContainer = getChild("Preview Tabs"); - return TRUE; + return !instance->isMinimized() && instance->isInVisibleChain(); } - return FALSE; } -void LLMultiFloater::updateResizeLimits() +void VisibilityPolicy::show(LLFloater* instance, const LLSD& key) { - // initialize minimum size constraint to the original xml values. - S32 new_min_width = mOrigMinWidth; - S32 new_min_height = mOrigMinHeight; - // possibly increase minimum size constraint due to children's minimums. - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + if (instance) { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); - if (floaterp) + instance->openFloater(key); + if (instance->getHost()) { - new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); - new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); + instance->getHost()->openFloater(key); } } - setResizeLimits(new_min_width, new_min_height); - - S32 cur_height = getRect().getHeight(); - S32 new_width = llmax(getRect().getWidth(), new_min_width); - S32 new_height = llmax(getRect().getHeight(), new_min_height); - - if (isMinimized()) - { - const LLRect& expanded = getExpandedRect(); - LLRect newrect; - newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height)); - setExpandedRect(newrect); - } - else - { - reshape(new_width, new_height); - - // make sure upper left corner doesn't move - translate(0, cur_height - getRect().getHeight()); - - // make sure this window is visible on screen when it has been modified - // (tab added, etc) - gFloaterView->adjustToFitScreen(this, TRUE); - } -} - -// virtual -LLXMLNodePtr LLFloater::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLPanel::getXML(); - - node->createChild("title", TRUE)->setStringValue(getCurrentTitle()); - - node->createChild("can_resize", TRUE)->setBoolValue(isResizable()); - - node->createChild("can_minimize", TRUE)->setBoolValue(isMinimizeable()); - - node->createChild("can_close", TRUE)->setBoolValue(isCloseable()); - - node->createChild("can_drag_on_left", TRUE)->setBoolValue(isDragOnLeft()); - - node->createChild("min_width", TRUE)->setIntValue(getMinWidth()); - - node->createChild("min_height", TRUE)->setIntValue(getMinHeight()); - - node->createChild("can_tear_off", TRUE)->setBoolValue(mCanTearOff); - - return node; } -// static -LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +void VisibilityPolicy::hide(LLFloater* instance, const LLSD& key) { - std::string name("floater"); - node->getAttributeString("name", name); - - LLFloater *floaterp = new LLFloater(name); - - std::string filename; - node->getAttributeString("filename", filename); - - if (filename.empty()) - { - // Load from node - floaterp->initFloaterXML(node, parent, factory); - } - else - { - // Load from file - factory->buildFloater(floaterp, filename); - } - - return floaterp; + if (instance) instance->closeFloater(); } -void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */ -{ - std::string name(getName()); - std::string title(getCurrentTitle()); - std::string short_title(getShortTitle()); - std::string rect_control(""); - BOOL resizable = isResizable(); - S32 min_width = getMinWidth(); - S32 min_height = getMinHeight(); - BOOL drag_on_left = isDragOnLeft(); - BOOL minimizable = isMinimizeable(); - BOOL close_btn = isCloseable(); - LLRect rect; - - node->getAttributeString("name", name); - node->getAttributeString("title", title); - node->getAttributeString("short_title", short_title); - node->getAttributeString("rect_control", rect_control); - node->getAttributeBOOL("can_resize", resizable); - node->getAttributeBOOL("can_minimize", minimizable); - node->getAttributeBOOL("can_close", close_btn); - node->getAttributeBOOL("can_drag_on_left", drag_on_left); - node->getAttributeS32("min_width", min_width); - node->getAttributeS32("min_height", min_height); - - if (! rect_control.empty()) - { - setRectControl(rect_control); - } - - createRect(node, rect, parent, LLRect()); - - setRect(rect); - setName(name); - - initFloater(title, - resizable, - min_width, - min_height, - drag_on_left, - minimizable, - close_btn); - - setTitle(title); - applyTitle (); - - setShortTitle(short_title); - - BOOL can_tear_off; - if (node->getAttributeBOOL("can_tear_off", can_tear_off)) - { - setCanTearOff(can_tear_off); - } - - initFromXML(node, parent); - - LLMultiFloater* last_host = LLFloater::getFloaterHost(); - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost((LLMultiFloater*) this); - } - - initChildrenXML(node, factory); - - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost(last_host); - } - - BOOL result = postBuild(); - - if (!result) - { - llerrs << "Failed to construct floater " << name << llendl; - } - - applyRectControl(); - if (open) /* Flawfinder: ignore */ - { - this->open(); /* Flawfinder: ignore */ - } - - moveResizeHandlesToFront(); -} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 0e3d148b09..f6c783b0bf 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -39,7 +39,6 @@ #include "llpanel.h" #include "lluuid.h" -#include "lltabcontainer.h" #include "llnotifications.h" #include @@ -50,17 +49,10 @@ class LLButton; class LLMultiFloater; class LLFloater; -const S32 LLFLOATER_VPAD = 6; -const S32 LLFLOATER_HPAD = 6; -const S32 LLFLOATER_CLOSE_BOX_SIZE = 16; -const S32 LLFLOATER_HEADER_SIZE = 18; const BOOL RESIZE_YES = TRUE; const BOOL RESIZE_NO = FALSE; -const S32 DEFAULT_MIN_WIDTH = 100; -const S32 DEFAULT_MIN_HEIGHT = 100; - const BOOL DRAG_ON_TOP = FALSE; const BOOL DRAG_ON_LEFT = TRUE; @@ -87,11 +79,22 @@ private: LLHandle mFloaterHandle; }; - class LLFloater : public LLPanel { friend class LLFloaterView; +friend class LLFloaterReg; +friend class LLMultiFloater; public: + struct KeyCompare + { + static bool compare(const LLSD& a, const LLSD& b); + static bool equate(const LLSD& a, const LLSD& b); + bool operator()(const LLSD& a, const LLSD& b) const + { + return compare(a, b); + } + }; + enum EFloaterButtons { BUTTON_CLOSE, @@ -102,49 +105,63 @@ public: BUTTON_COUNT }; - LLFloater(); - LLFloater(const std::string& name); //simple constructor for data-driven initialization - LLFloater( const std::string& name, const LLRect& rect, const std::string& title, - BOOL resizable = FALSE, - S32 min_width = DEFAULT_MIN_WIDTH, - S32 min_height = DEFAULT_MIN_HEIGHT, - BOOL drag_on_left = FALSE, - BOOL minimizable = TRUE, - BOOL close_btn = TRUE, - BOOL bordered = BORDER_NO); - - LLFloater( const std::string& name, const std::string& rect_control, const std::string& title, - BOOL resizable = FALSE, - S32 min_width = DEFAULT_MIN_WIDTH, - S32 min_height = DEFAULT_MIN_HEIGHT, - BOOL drag_on_left = FALSE, - BOOL minimizable = TRUE, - BOOL close_btn = TRUE, - BOOL bordered = BORDER_NO); + struct Params + : public LLInitParam::Block + { + Optional title, + short_title; + + Optional single_instance, + auto_tile, + can_resize, + can_minimize, + can_close, + can_drag_on_left, + can_tear_off, + save_rect, + save_visibility; + + Params() : + title("title"), + short_title("short_title"), + single_instance("single_instance", false), + auto_tile("auto_tile", false), + can_resize("can_resize", false), + can_minimize("can_minimize", true), + can_close("can_close", true), + can_drag_on_left("can_drag_on_left", false), + can_tear_off("can_tear_off", true), + save_rect("save_rect", false), + save_visibility("save_visibility", false) + { + name = "floater"; + // defaults that differ from LLPanel: + background_visible = true; + visible = false; + } + }; + + LLFloater(const LLSD& key = LLSD(), const LLFloater::Params& params = LLFloater::Params()); virtual ~LLFloater(); - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open = TRUE); + void initFromParams(const LLFloater::Params& p); + void initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floater = TRUE, LLXMLNodePtr output_node = NULL); - /*virtual*/ void userSetShape(const LLRect& new_rect); + /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); /*virtual*/ BOOL canSnapTo(const LLView* other_view); - /*virtual*/ void snappedTo(const LLView* snap_view); + /*virtual*/ void setSnappedTo(const LLView* snap_view); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); + /*virtual*/ void setRect(const LLRect &rect); - // Can be called multiple times to reset floater parameters. - // Deletes all children of the floater. - virtual void initFloater(const std::string& title, BOOL resizable, - S32 min_width, S32 min_height, BOOL drag_on_left, - BOOL minimizable, BOOL close_btn); + void initFloater(); - virtual void open(); /* Flawfinder: ignore */ + void openFloater(const LLSD& key = LLSD()); // If allowed, close the floater cleanly, releasing focus. // app_quitting is passed to onClose() below. - virtual void close(bool app_quitting = false); + void closeFloater(bool app_quitting = false); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -153,11 +170,8 @@ public: // moves to center of gFloaterView void center(); - // applies rectangle stored in mRectControl, if any - void applyRectControl(); - - LLMultiFloater* getHost() { return (LLMultiFloater*)mHostHandle.get(); } + LLMultiFloater* getHost(); void applyTitle(); const std::string& getCurrentTitle() const; @@ -185,9 +199,8 @@ public: void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } - bool isMinimizeable() const{ return mButtonsEnabled[BUTTON_MINIMIZE]; } - // Does this window have a close button, NOT can we close it right now. - bool isCloseable() const{ return (mButtonsEnabled[BUTTON_CLOSE]); } + bool isMinimizeable() const{ return mCanMinimize; } + bool isCloseable() const{ return mCanClose; } bool isDragOnLeft() const{ return mDragOnLeft; } S32 getMinWidth() const{ return mMinWidth; } S32 getMinHeight() const{ return mMinHeight; } @@ -198,7 +211,7 @@ public: virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); virtual void draw(); - virtual void onOpen() {} + virtual void onOpen(const LLSD& key) {} // Call destroy() to free memory, or setVisible(FALSE) to keep it // If app_quitting, you might not want to save your visibility. @@ -210,8 +223,10 @@ public: virtual BOOL canClose() { return TRUE; } virtual void setVisible(BOOL visible); + virtual void onVisibilityChange ( BOOL curVisibilityIn ); + void setFrontmost(BOOL take_focus = TRUE); - + // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } @@ -222,6 +237,8 @@ public: LLHandle getSnapTarget() const { return mSnappedTo; } LLHandle getHandle() const { return mHandle; } + const LLSD& getKey() { return mKey; } + BOOL matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); @@ -235,22 +252,30 @@ public: return LLNotification::Params(name).context(mNotificationContext); } - static void onClickClose(void *userdata); - static void onClickMinimize(void *userdata); - static void onClickTearOff(void *userdata); - static void onClickEdit(void *userdata); + static void onClickClose(LLFloater* floater); + static void onClickMinimize(LLFloater* floater); + static void onClickTearOff(LLFloater* floater); + static void onClickEdit(LLFloater* floater); static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } static void setEditModeEnabled(BOOL enable); static BOOL getEditModeEnabled() { return sEditModeEnabled; } - static LLMultiFloater* getFloaterHost() {return sHostp; } - + static LLMultiFloater* getFloaterHost() {return sHostp; } + protected: + void setRectControl(const std::string& rectname) { mRectControl = rectname; }; + void applyRectControl(); + void storeRectControl(); + void storeVisibilityControl(); + + void setKey(const LLSD& key); + void setInstanceName(const std::string& name); + virtual void bringToFront(S32 x, S32 y); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); - void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized + void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened @@ -266,31 +291,48 @@ private: void updateButtons(); void buildButtons(); BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); - + void addResizeCtrls(); + void addDragHandle(); + +protected: + std::string mRectControl; + std::string mVisibilityControl; + + LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg + +private: LLRect mExpandedRect; LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; LLResizeHandle* mResizeHandle[4]; - LLButton *mMinimizeButton; + + LLUIString mTitle; + LLUIString mShortTitle; + + BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater + std::string mInstanceName; // Store the instance name so we can remove ourselves from the list + BOOL mAutoTile; // TRUE if placement of new instances tiles + BOOL mCanTearOff; + BOOL mCanMinimize; + BOOL mCanClose; + BOOL mDragOnLeft; + BOOL mResizable; + + S32 mMinWidth; + S32 mMinHeight; + BOOL mMinimized; BOOL mForeground; LLHandle mDependeeHandle; - std::string mTitle; - std::string mShortTitle; + BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. - - BOOL mResizable; - S32 mMinWidth; - S32 mMinHeight; - BOOL mEditing; typedef std::set > handle_set_t; typedef std::set >::iterator handle_set_iter_t; handle_set_t mDependents; - bool mDragOnLeft; BOOL mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; @@ -308,7 +350,9 @@ private: static std::string sButtonPressedImageNames[BUTTON_COUNT]; static std::string sButtonNames[BUTTON_COUNT]; static std::string sButtonToolTips[BUTTON_COUNT]; - typedef void (*click_callback)(void *); + static std::string sButtonToolTipsIndex[BUTTON_COUNT]; + + typedef void(*click_callback)(LLFloater*); static click_callback sButtonCallbacks[BUTTON_COUNT]; typedef std::map, LLFloater*> handle_map_t; @@ -320,7 +364,10 @@ private: BOOL mHasBeenDraggedWhileMinimized; S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; - + + LLColor4 mBgColorAlpha; + LLColor4 mBgColorOpaque; + LLFloaterNotificationContext* mNotificationContext; LLRootHandle mHandle; }; @@ -331,18 +378,18 @@ private: class LLFloaterView : public LLUICtrl { -public: - LLFloaterView( const std::string& name, const LLRect& rect ); +protected: + LLFloaterView (const Params& p); + friend class LLUICtrlFactory; +public: /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); void reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical); /*virtual*/ void draw(); /*virtual*/ LLRect getSnapRect() const; - void refresh(); + /*virtual*/ void refresh(); - void getNewFloaterPosition( S32* left, S32* top ); - void resetStartingFloaterPosition(); LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); // Given a child of gFloaterView, make sure this view can fit entirely onscreen. @@ -365,10 +412,10 @@ public: void closeAllChildren(bool app_quitting); BOOL allChildrenClosed(); - LLFloater* getFrontmost(); - LLFloater* getBackmost(); - LLFloater* getParentFloater(LLView* viewp); - LLFloater* getFocusedFloater(); + LLFloater* getFrontmost() const; + LLFloater* getBackmost() const; + LLFloater* getParentFloater(LLView* viewp) const; + LLFloater* getFocusedFloater() const; void syncFloaterTabOrder(); // Returns z order of child provided. 0 is closest, larger numbers @@ -386,99 +433,23 @@ private: S32 mSnapOffsetBottom; }; -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376 -class LLMultiFloater : public LLFloater -{ -public: - LLMultiFloater(); - LLMultiFloater(LLTabContainer::TabPosition tab_pos); - LLMultiFloater(const std::string& name); - LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); - LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); - virtual ~LLMultiFloater() {}; - - virtual BOOL postBuild(); - /*virtual*/ void open(); /* Flawfinder: ignore */ - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - - virtual void setCanResize(BOOL can_resize); - virtual void growToFit(S32 content_width, S32 content_height); - virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - - virtual void showFloater(LLFloater* floaterp); - virtual void removeFloater(LLFloater* floaterp); - - virtual void tabOpen(LLFloater* opened_floater, bool from_click); - virtual void tabClose(); - - virtual BOOL selectFloater(LLFloater* floaterp); - virtual void selectNextFloater(); - virtual void selectPrevFloater(); - - virtual LLFloater* getActiveFloater(); - virtual BOOL isFloaterFlashing(LLFloater* floaterp); - virtual S32 getFloaterCount(); - - virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); - virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs - void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } - static void onTabSelected(void* userdata, bool); - - virtual void updateResizeLimits(); - -protected: - struct LLFloaterData - { - S32 mWidth; - S32 mHeight; - BOOL mCanMinimize; - BOOL mCanResize; - }; - - LLTabContainer* mTabContainer; - - typedef std::map, LLFloaterData> floater_data_map_t; - floater_data_map_t mFloaterDataMap; - - LLTabContainer::TabPosition mTabPos; - BOOL mAutoResize; - S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late -}; +// singleton implementation for floaters +// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 +//******************************************************* +//* TO BE DEPRECATED +//******************************************************* // visibility policy specialized for floaters template<> class VisibilityPolicy { public: // visibility methods - static bool visible(LLFloater* instance, const LLSD& key) - { - if (instance) - { - return !instance->isMinimized() && instance->isInVisibleChain(); - } - return FALSE; - } + static bool visible(LLFloater* instance, const LLSD& key); - static void show(LLFloater* instance, const LLSD& key) - { - if (instance) - { - instance->open(); - if (instance->getHost()) - { - instance->getHost()->open(); - } - } - } + static void show(LLFloater* instance, const LLSD& key); - static void hide(LLFloater* instance, const LLSD& key) - { - if (instance) instance->close(); - } + static void hide(LLFloater* instance, const LLSD& key); }; @@ -489,6 +460,10 @@ template class LLFloaterSingleton : public LLUISingleton LLFloaterReg::sGroupMap; + +//******************************************************* + +//static +void LLFloaterReg::add(const std::string& name, const std::string& filename, const LLFloaterBuildFunc& func, const std::string& groupname) +{ + sBuildMap[name].mFunc = func; + sBuildMap[name].mFile = filename; + sGroupMap[name] = groupname.empty() ? name : groupname; + sGroupMap[groupname] = groupname; // for referencing directly by group name +} + +//static +LLRect LLFloaterReg::getFloaterRect(const std::string& name) +{ + LLRect rect; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + if (!list.empty()) + { + static LLUICachedControl floater_offset ("UIFloaterOffset", 16); + LLFloater* last_floater = list.back(); + if (last_floater->getHost()) + { + rect = last_floater->getHost()->getRect(); + } + else + { + rect = last_floater->getRect(); + } + rect.translate(floater_offset, -floater_offset); + } + } + return rect; +} + +//static +LLFloater* LLFloaterReg::findInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + break; + } + } + } + return res; +} + +//static +LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = findInstance(name, key); + if (!res) + { + const LLFloaterBuildFunc& build_func = sBuildMap[name].mFunc; + const std::string& xui_file = sBuildMap[name].mFile; + if (build_func) + { + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + int index = list.size(); + + res = build_func(key); + + const bool DONT_OPEN_FLOATER = false; + LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, DONT_OPEN_FLOATER); + + // Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe + res->mKey = key; + res->setInstanceName(name); + res->applyRectControl(); // Can't apply rect control until setting instance name + if (res->mAutoTile && !res->getHost() && index > 0) + { + const LLRect& cur_rect = res->getRect(); + LLRect next_rect = getFloaterRect(groupname); + next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, cur_rect.getWidth(), cur_rect.getHeight()); + res->setRect(next_rect); + res->setRectControl(LLStringUtil::null); // don't save rect of tiled floaters + gFloaterView->adjustToFitScreen(res, true); + } + else + { + gFloaterView->adjustToFitScreen(res, false); + } + list.push_back(res); + } + } + if (!res) + { + llwarns << "Floater type: '" << name << "' not registered." << llendl; + } + } + return res; +} + +//static +LLFloater* LLFloaterReg::removeInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + list.erase(iter); + break; + } + } + } + return res; +} + +//static +// returns true if the instance existed +bool LLFloaterReg::destroyInstance(const std::string& name, const LLSD& key) +{ + LLFloater* inst = removeInstance(name, key); + if (inst) + { + delete inst; + return true; + } + else + { + return false; + } +} + +// Iterators +//static +LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::string& name) +{ + instance_map_t::iterator iter = sInstanceMap.find(name); + if (iter != sInstanceMap.end()) + { + return iter->second; + } + else + { + return sNullInstanceList; + } +} + +// Visibility Management + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) +{ + LLFloater* instance = getInstance(name, key); + if (instance) + { + instance->openFloater(key); + if (focus) + instance->setFocus(TRUE); + } + return instance; +} + +//static +// returns true if the instance exists +bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance) + { + // When toggling *visibility*, close the host instead of the floater when hosted + if (instance->getHost()) + instance->getHost()->closeFloater(); + else + instance->closeFloater(); + return true; + } + else + { + return false; + } +} + +//static +// returns true if the instance is visible when completed +bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance && !instance->isMinimized() && instance->isInVisibleChain()) + { + // When toggling *visibility*, close the host instead of the floater when hosted + if (instance->getHost()) + instance->getHost()->closeFloater(); + else + instance->closeFloater(); + return false; + } + else + { + return showInstance(name, key, TRUE) ? true : false; + } +} + +//static +// returns true if the instance exists and is visible +bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance && !instance->isMinimized() && instance->isInVisibleChain()) + { + return true; + } + else + { + return false; + } +} + +//static +void LLFloaterReg::showInitialVisibleInstances() +{ + // Iterate through alll registered instance names and show any with a save visible state + for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) + { + const std::string& name = iter->first; + std::string controlname = getVisibilityControlName(name); + if (LLUI::sSettingGroups["floater"]->controlExists(controlname)) + { + BOOL isvis = LLUI::sSettingGroups["floater"]->getBOOL(controlname); + if (isvis) + { + showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true + } + } + } +} + +//static +void LLFloaterReg::hideVisibleInstances(const std::set& exceptions) +{ + // Iterate through alll active instances and hide them + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + const std::string& name = iter->first; + if (exceptions.find(name) != exceptions.end()) + continue; + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->pushVisible(FALSE); + } + } +} + +//static +void LLFloaterReg::restoreVisibleInstances() +{ + // Iterate through all active instances and restore visibility + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->popVisible(); + } + } +} + +//static +std::string LLFloaterReg::getRectControlName(const std::string& name) +{ + std::string res = std::string("floater_rect_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; +} + +//static +std::string LLFloaterReg::declareRectControl(const std::string& name) +{ + std::string controlname = getRectControlName(name); + LLUI::sSettingGroups["floater"]->declareRect(controlname, LLRect(), + llformat("Window Position and Size for %s", name.c_str()), + TRUE); + return controlname; +} + +//static +std::string LLFloaterReg::getVisibilityControlName(const std::string& name) +{ + std::string res = std::string("floater_vis_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; +} + +//static +std::string LLFloaterReg::declareVisibilityControl(const std::string& name) +{ + std::string controlname = getVisibilityControlName(name); + LLUI::sSettingGroups["floater"]->declareBOOL(controlname, FALSE, + llformat("Window Visibility for %s", name.c_str()), + TRUE); + return controlname; +} + +// Callbacks + +// static +// Call once (i.e use for init callbacks) +void LLFloaterReg::initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname) +{ + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the control value to the floater visibility control (Sets the value as well) + ctrl->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name)); +} + +// callback args may use "floatername.key" format +static void parse_name_key(std::string& name, LLSD& key) +{ + std::string instname = name; + std::size_t dotpos = instname.find("."); + if (dotpos != std::string::npos) + { + name = instname.substr(0, dotpos); + key = LLSD(instname.substr(dotpos+1, std::string::npos)); + } +} + +//static +void LLFloaterReg::showFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + showInstance(name, key, TRUE); +} +//static +void LLFloaterReg::hideFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + hideInstance(name, key); +} +//static +void LLFloaterReg::toggleFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + toggleInstance(name, key); +} + +//static +bool LLFloaterReg::floaterInstanceVisible(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + return instanceVisible(name, key); +} + diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h new file mode 100644 index 0000000000..af1bfc5ec1 --- /dev/null +++ b/indra/llui/llfloaterreg.h @@ -0,0 +1,149 @@ +/** + * @file llfloaterreg.h + * @brief LLFloaterReg Floater Registration Class + * + * $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$ + */ + +/// llcommon +#include "llboost.h" +#include "llrect.h" +#include "llstl.h" +#include "llsd.h" + +/// llui +#include "lluictrl.h" + +#include + +//******************************************************* +// +// Floater Class Registry +// + +class LLFloater; + +typedef boost::function LLFloaterBuildFunc; + +class LLFloaterReg +{ +public: + // We use a list of LLFloater's instead of a set for two reasons: + // 1) With a list we have a predictable ordering, useful for finding the last opened floater of a given type. + // 2) We can change the key of a floater without altering the list. + typedef std::list instance_list_t; + typedef const instance_list_t const_instance_list_t; + typedef std::map instance_map_t; + + struct BuildData + { + LLFloaterBuildFunc mFunc; + std::string mFile; + }; + typedef std::map build_map_t; + +private: + static instance_list_t sNullInstanceList; + static instance_map_t sInstanceMap; + static build_map_t sBuildMap; + static std::map sGroupMap; + +public: + // Registration + + // usage: LLFloaterClassRegistry::add("foo", (LLFloaterBuildFunc)&LLFloaterClassRegistry::build); + template + static LLFloater* build(const LLSD& key) + { + T* floater = new T(key); + return floater; + } + + static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func, + const std::string& groupname = LLStringUtil::null); + + // Helpers + static LLRect getFloaterRect(const std::string& name); + + // Find / get (create) / remove / destroy + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); + + // Iterators + static const_instance_list_t& getFloaterList(const std::string& name); + + // Visibility Management + // return NULL if instance not found or can't create instance (no builder) + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); + // Close a floater (may destroy or set invisible) + // return false if can't find instance + static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); + // return true if instance is visible: + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); + + static void showInitialVisibleInstances(); + static void hideVisibleInstances(const std::set& exceptions = std::set()); + static void restoreVisibleInstances(); + + // Control Variables + static std::string getRectControlName(const std::string& name); + static std::string declareRectControl(const std::string& name); + static std::string getVisibilityControlName(const std::string& name); + static std::string declareVisibilityControl(const std::string& name); + + // Callback wrappers + static void initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname); + static void showFloaterInstance(const LLSD& sdname); + static void hideFloaterInstance(const LLSD& sdname); + static void toggleFloaterInstance(const LLSD& sdname); + static bool floaterInstanceVisible(const LLSD& sdname); + + // Typed find / get / show + template + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(findInstance(name, key)); + } + + template + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(getInstance(name, key)); + } + + template + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) + { + return dynamic_cast(showInstance(name, key, focus)); + } + +}; + diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp new file mode 100644 index 0000000000..6b7c174726 --- /dev/null +++ b/indra/llui/llflyoutbutton.cpp @@ -0,0 +1,94 @@ +/** + * @file llflyoutbutton.cpp + * @brief LLFlyoutButton base class + * + * $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" + +// file includes +#include "llflyoutbutton.h" + +static LLRegisterWidget r2("flyout_button"); + +const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; + +LLFlyoutButton::LLFlyoutButton(const Params& p) +: LLComboBox(p), + mToggleState(FALSE), + mActionButton(NULL) +{ + // Always use text box + // Text label button + LLButton::Params bp(p.action_button); + bp.name(p.label); + bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight()); + bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2)); + bp.follows.flags(FOLLOWS_ALL); + + mActionButton = LLUICtrlFactory::create(bp); + addChild(mActionButton); + + mButton->setOrigin(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0); + mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); + mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT); +} + +void LLFlyoutButton::onActionButtonClick(const LLSD& data) +{ + // remember last list selection? + mList->deselect(); + onCommit(); +} + +void LLFlyoutButton::draw() +{ + mActionButton->setToggleState(mToggleState); + mButton->setToggleState(mToggleState); + + //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or + // the label reflects the last selected item, for now we have to manually remove the label + mButton->setLabel(LLStringUtil::null); + LLComboBox::draw(); +} + +void LLFlyoutButton::setEnabled(BOOL enabled) +{ + mActionButton->setEnabled(enabled); + LLComboBox::setEnabled(enabled); +} + + +void LLFlyoutButton::setToggleState(BOOL state) +{ + mToggleState = state; +} + + diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h new file mode 100644 index 0000000000..f60fe1eb35 --- /dev/null +++ b/indra/llui/llflyoutbutton.h @@ -0,0 +1,71 @@ +/** + * @file llflyoutbutton.h + * @brief LLFlyoutButton base class + * + * $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$ + */ + +// A control that displays the name of the chosen item, which when clicked +// shows a scrolling box of choices. + +#ifndef LL_LLFLYOUTBUTTON_H +#define LL_LLFLYOUTBUTTON_H + +#include "llcombobox.h" + +// Classes + +class LLFlyoutButton : public LLComboBox +{ +public: + struct Params : public LLInitParam::Block + { + Optional action_button; + + Params() + : action_button("action_button") + {} + + }; +protected: + LLFlyoutButton(const Params&); + friend class LLUICtrlFactory; +public: + virtual void draw(); + virtual void setEnabled(BOOL enabled); + + void setToggleState(BOOL state); + + void onActionButtonClick(const LLSD& data); + +protected: + LLButton* mActionButton; + BOOL mToggleState; +}; + +#endif // LL_LLFLYOUTBUTTON_H diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 661ffdd467..9a4ec7627e 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -220,24 +220,19 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor ) { LLMouseHandler* old_captor = mMouseCaptor; mMouseCaptor = new_captor; - /* - if (new_captor) + + if (LLView::sDebugMouseHandling) { - if ( new_captor->getName() == "Stickto") + if (new_captor) { llinfos << "New mouse captor: " << new_captor->getName() << llendl; } else { - llinfos << "New mouse captor: " << new_captor->getName() << llendl; + llinfos << "New mouse captor: NULL" << llendl; } } - else - { - llinfos << "New mouse captor: NULL" << llendl; - } - */ - + if( old_captor ) { old_captor->onMouseCaptureLost(); @@ -295,7 +290,7 @@ void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) if (old_top) { - old_top->onLostTop(); + old_top->onTopLost(); } } } @@ -328,7 +323,8 @@ F32 LLFocusMgr::getFocusFlashAmt() const LLColor4 LLFocusMgr::getFocusColor() const { - LLColor4 focus_color = lerp(LLUI::sColorsGroup->getColor( "FocusColor" ), LLColor4::white, getFocusFlashAmt()); + static LLUICachedControl focus_color_cached ("FocusColor", *(new LLColor4)); + LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt()); // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem) if (!mAppHasFocus) { diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 8864f7af15..2c0bcc6012 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -40,7 +40,7 @@ #include #include "llsd.h" -#include "llmemory.h" +#include "llsingleton.h" /** * @class LLFunctorRegistry diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index cb3b2a3a62..d01679cd1c 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -40,65 +40,33 @@ #include "llcontrol.h" #include "llui.h" #include "lluictrlfactory.h" - -const F32 RESOLUTION_BUMP = 1.f; +#include "lluiimage.h" static LLRegisterWidget r("icon"); -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id) -: LLUICtrl(name, - rect, - FALSE, // mouse opaque - NULL, NULL, - FOLLOWS_LEFT | FOLLOWS_TOP), - mColor( LLColor4::white ) -{ - setImage( image_id ); - setTabStop(FALSE); -} - -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name) -: LLUICtrl(name, - rect, - FALSE, // mouse opaque - NULL, NULL, - FOLLOWS_LEFT | FOLLOWS_TOP), - mColor( LLColor4::white ), - mImageName(image_name) -{ - setImage( image_name ); - setTabStop(FALSE); -} - - -LLIconCtrl::~LLIconCtrl() +LLIconCtrl::Params::Params() +: image("image_name"), + color("color"), + scale_image("scale_image") { - mImagep = NULL; + tab_stop = false; + mouse_opaque = false; } - -void LLIconCtrl::setImage(const std::string& image_name) +LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) +: LLUICtrl(p), + mColor(p.color()), + mImagep(p.image) { - //RN: support UUIDs masquerading as strings - if (LLUUID::validate(image_name)) - { - mImageID = LLUUID(image_name); - - setImage(mImageID); - } - else + if (mImagep.notNull()) { - mImageName = image_name; - mImagep = LLUI::sImageProvider->getUIImage(image_name); - mImageID.setNull(); + LLUICtrl::setValue(mImagep->getName()); } } -void LLIconCtrl::setImage(const LLUUID& image_id) +LLIconCtrl::~LLIconCtrl() { - mImageName.clear(); - mImagep = LLUI::sImageProvider->getUIImageByID(image_id); - mImageID = image_id; + mImagep = NULL; } @@ -106,69 +74,37 @@ void LLIconCtrl::draw() { if( mImagep.notNull() ) { - mImagep->draw(getLocalRect(), mColor ); + mImagep->draw(getLocalRect(), mColor.get() ); } LLUICtrl::draw(); } // virtual +// value might be a string or a UUID void LLIconCtrl::setValue(const LLSD& value ) { - if (value.isUUID()) + LLSD tvalue(value); + if (value.isString() && LLUUID::validate(value.asString())) { - setImage(value.asUUID()); + //RN: support UUIDs masquerading as strings + tvalue = LLSD(LLUUID(value.asString())); } - else + LLUICtrl::setValue(tvalue); + if (tvalue.isUUID()) { - setImage(value.asString()); + mImagep = LLUI::getUIImageByID(tvalue.asUUID()); } -} - -// virtual -LLSD LLIconCtrl::getValue() const -{ - LLSD ret = getImage(); - return ret; -} - -// virtual -LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - if (mImageName != "") + else { - node->createChild("image_name", TRUE)->setStringValue(mImageName); + mImagep = LLUI::getUIImage(tvalue.asString()); } - - node->createChild("color", TRUE)->setFloatValue(4, mColor.mV); - - return node; } -LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +std::string LLIconCtrl::getImageName() const { - std::string name("icon"); - node->getAttributeString("name", name); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - std::string image_name; - if (node->hasAttribute("image_name")) - { - node->getAttributeString("image_name", image_name); - } - - LLColor4 color(LLColor4::white); - LLUICtrlFactory::getAttributeColor(node,"color", color); - - LLIconCtrl* icon = new LLIconCtrl(name, rect, image_name); - - icon->setColor(color); - - icon->initFromXML(node, parent); - - return icon; + if (getValue().isString()) + return getValue().asString(); + else + return std::string(); } diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 50778cf226..ad0f6f563f 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -45,35 +45,37 @@ class LLUICtrlFactory; // // Classes // + +// class LLIconCtrl : public LLUICtrl { public: - LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id); - LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name); + struct Params : public LLInitParam::Block + { + Optional image; + Optional color; + Deprecated scale_image; + Params(); + }; +protected: + LLIconCtrl(const Params&); + friend class LLUICtrlFactory; +public: virtual ~LLIconCtrl(); // llview overrides virtual void draw(); - void setImage(const std::string& image_name); - void setImage(const LLUUID& image_name); - const LLUUID &getImage() const { return mImageID; } - std::string getImageName() const { return mImageName; } - - // Takes a UUID, wraps get/setImage + // lluictrl overrides virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; - void setColor(const LLColor4& color) { mColor = color; } + std::string getImageName() const; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + void setColor(const LLColor4& color) { mColor = color; } private: - LLColor4 mColor; - std::string mImageName; - LLUUID mImageID; + LLUIColor mColor; LLPointer mImagep; }; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 51ef3dbacf..30796a5ab9 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -223,8 +223,8 @@ LLColor3 LLKeywords::readColor( const std::string& s ) { F32 r, g, b; r = g = b = 0.0f; - S32 read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); - if( read != 3 ) /* Flawfinder: ignore */ + S32 values_read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); + if( values_read != 3 ) { llinfos << " poorly formed color in keyword file" << llendl; } diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp new file mode 100644 index 0000000000..483c1358ae --- /dev/null +++ b/indra/llui/lllayoutstack.cpp @@ -0,0 +1,718 @@ +/** + * @file lllayoutstack.cpp + * @brief LLLayout class - dynamic stacking of UI elements + * + * $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$ + */ + +// Opaque view with a background and a border. Can contain LLUICtrls. + +#include "linden_common.h" + +#include "lllayoutstack.h" +#include "llresizebar.h" +#include "llcriticaldamp.h" + +// +// LLLayoutStack +// +struct LLLayoutStack::LLEmbeddedPanel +{ + LLEmbeddedPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp), + mMinWidth(min_width), + mMinHeight(min_height), + mAutoResize(auto_resize), + mUserResize(user_resize), + mOrientation(orientation), + mCollapsed(FALSE), + mCollapseAmt(0.f), + mVisibleAmt(1.f), // default to fully visible + mResizeBar(NULL) + { + LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; + LLRect resize_bar_rect = panelp->getRect(); + + S32 min_dim; + if (orientation == HORIZONTAL) + { + min_dim = mMinHeight; + } + else + { + min_dim = mMinWidth; + } + LLResizeBar::Params p; + p.name("resize"); + p.resizing_view(mPanel); + p.min_size(min_dim); + p.side(side); + p.snapping_enabled(false); + mResizeBar = LLUICtrlFactory::create(p); + // panels initialized as hidden should not start out partially visible + if (!mPanel->getVisible()) + { + mVisibleAmt = 0.f; + } + } + + ~LLEmbeddedPanel() + { + // probably not necessary, but... + delete mResizeBar; + mResizeBar = NULL; + } + + F32 getCollapseFactor() + { + if (mOrientation == HORIZONTAL) + { + F32 collapse_amt = + clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth())); + return mVisibleAmt * collapse_amt; + } + else + { + F32 collapse_amt = + clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight()))); + return mVisibleAmt * collapse_amt; + } + } + + LLPanel* mPanel; + S32 mMinWidth; + S32 mMinHeight; + BOOL mAutoResize; + BOOL mUserResize; + BOOL mCollapsed; + LLResizeBar* mResizeBar; + ELayoutOrientation mOrientation; + F32 mVisibleAmt; + F32 mCollapseAmt; +}; + +static LLRegisterWidget r2("layout_stack", &LLLayoutStack::fromXML); + +LLLayoutStack::Params::Params() +: orientation("orientation", std::string("vertical")), + border_size("border_size", LLCachedControl(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) +{ + name="stack"; +} + +LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) +: LLView(p), + mMinWidth(0), + mMinHeight(0), + mPanelSpacing(p.border_size), + mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL) +{} + +LLLayoutStack::~LLLayoutStack() +{ + e_panel_list_t panels = mPanels; // copy list of panel pointers + mPanels.clear(); // clear so that removeChild() calls don't cause trouble + std::for_each(panels.begin(), panels.end(), DeletePointer()); +} + +void LLLayoutStack::draw() +{ + updateLayout(); + + e_panel_list_t::iterator panel_it; + for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + { + // clip to layout rectangle, not bounding rectangle + LLRect clip_rect = (*panel_it)->mPanel->getRect(); + // scale clipping rectangle by visible amount + if (mOrientation == HORIZONTAL) + { + clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor()); + } + else + { + clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); + } + + LLPanel* panelp = (*panel_it)->mPanel; + + LLLocalClipRect clip(clip_rect); + // only force drawing invisible children if visible amount is non-zero + drawChild(panelp, 0, 0, !clip_rect.isNull()); + } +} + +void LLLayoutStack::removeChild(LLView* view) +{ + LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast(view)); + + if (embedded_panelp) + { + mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); + delete embedded_panelp; + } + + // need to update resizebars + + calcMinExtents(); + + LLView::removeChild(view); +} + +BOOL LLLayoutStack::postBuild() +{ + updateLayout(); + return TRUE; +} + +static void get_attribute_s32_and_write(LLXMLNodePtr node, + const char* name, + S32 *value, + S32 default_value, + LLXMLNodePtr output_child) +{ + BOOL has_attr = node->getAttributeS32(name, *value); + if (has_attr && *value != default_value && output_child) + { + // create an attribute child node + LLXMLNodePtr child_attr = output_child->createChild(name, TRUE); + child_attr->setIntValue(*value); + } +} + +static void get_attribute_bool_and_write(LLXMLNodePtr node, + const char* name, + BOOL *value, + BOOL default_value, + LLXMLNodePtr output_child) +{ + BOOL has_attr = node->getAttributeBOOL(name, *value); + if (has_attr && *value != default_value && output_child) + { + LLXMLNodePtr child_attr = output_child->createChild(name, TRUE); + child_attr->setBoolValue(*value); + } +} +//static +LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) +{ + LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams()); + LLXUIParser::instance().readXUI(node, p); + setupParams(p, parent); + LLLayoutStack* layout_stackp = LLUICtrlFactory::create(p); + + if (parent && layout_stackp) + { + S32 tab_group = p.tab_group.isProvided() ? p.tab_group() : parent->getLastTabGroup(); + + parent->addChild(layout_stackp, tab_group); + } + + if (output_node) + { + Params output_params(p); + setupParamsForExport(output_params, parent); + LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); + } + + for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling()) + { + const S32 DEFAULT_MIN_WIDTH = 0; + const S32 DEFAULT_MIN_HEIGHT = 0; + const BOOL DEFAULT_AUTO_RESIZE = TRUE; + + S32 min_width = DEFAULT_MIN_WIDTH; + S32 min_height = DEFAULT_MIN_HEIGHT; + BOOL auto_resize = DEFAULT_AUTO_RESIZE; + + LLXMLNodePtr output_child; + if (output_node) + { + output_child = output_node->createChild("", FALSE); + } + + // Layout stack allows child nodes to acquire additional attributes, + // such as "min_width" in: " + // which equates to the following nesting: + // button + // param + // nested_param1 + // nested_param2 + // nested_param3 + for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();) + { + std::string child_name(childp->getName()->mString); + S32 num_tokens_pushed = 0; + + // for non "dotted" child nodes check to see if child node maps to another widget type + // and if not, treat as a child element of the current node + // e.g. will interpret as "button.rect" + // since there is no widget named "rect" + if (child_name.find(".") == std::string::npos) { - continue; + // skip over children with registered names + if (LLWidgetCreatorRegistry::instance().exists(child_name)) + { + childp = childp->getNextSibling(); + continue; + } + + mNameStack.push_back(std::make_pair(child_name, newParseGeneration())); + num_tokens_pushed++; } - llinfos << "Rebuilding UI panel " << panelp->getName() - << " from " << filename - << llendl; - BOOL visible = panelp->getVisible(); - panelp->setVisible(FALSE); - panelp->setFocus(FALSE); - panelp->deleteAllChildren(); + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + childp = childp->getNextSibling(); + continue; + } - buildPanel(panelp, filename.c_str(), &panelp->getFactoryMap()); - panelp->setVisible(visible); + // check for proper nesting + if(!scope.empty() && *name_token_it != scope) + { + childp = childp->getNextSibling(); + continue; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); + num_tokens_pushed++; + } + } + + // recurse and visit children XML nodes + if(readXUIImpl(childp, mNameStack.empty() ? scope : mNameStack.back().first, block)) + { + // child node successfully parsed, remove from DOM + + values_parsed = true; + LLXMLNodePtr node_to_remove = childp; + childp = childp->getNextSibling(); + + nodep->deleteChild(node_to_remove); + } + else + { + childp = childp->getNextSibling(); + } + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } } + return values_parsed; +} + +bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); - built_floater_t::iterator built_floater_it; - for (built_floater_it = mBuiltFloaters.begin(); - built_floater_it != mBuiltFloaters.end(); - ++built_floater_it) + bool any_parsed = false; + + for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); + attribute_it != nodep->mAttributes.end(); + ++attribute_it) { - LLFloater* floaterp = built_floater_it->first.get(); - if (!floaterp) + S32 num_tokens_pushed = 0; + std::string attribute_name(attribute_it->first->mString); + mCurReadNode = attribute_it->second; + + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) { - continue; + mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); + num_tokens_pushed++; } - std::string filename = built_floater_it->second; - llinfos << "Rebuilding UI floater " << floaterp->getName() - << " from " << filename - << llendl; - BOOL visible = floaterp->getVisible(); - floaterp->setVisible(FALSE); - floaterp->setFocus(FALSE); - floaterp->deleteAllChildren(); - gFloaterView->removeChild(floaterp); - buildFloater(floaterp, filename, &floaterp->getFactoryMap()); - floaterp->setVisible(visible); + any_parsed |= block.submitValue(mNameStack, *this); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } } + + return any_parsed; } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- +bool LLXUIParser::readBoolValue(void* val_ptr) +{ + S32 value; + bool success = mCurReadNode->getBoolValue(1, &value); + *((bool*)val_ptr) = (value != FALSE); + return success; +} -LLView *LLUICtrlFactory::createCtrlWidget(LLPanel *parent, LLXMLNodePtr node) +bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack) { - std::string ctrl_type = node->getName()->mString; - LLStringUtil::toLower(ctrl_type); - - LLWidgetClassRegistry::factory_func_t func = LLWidgetClassRegistry::getInstance()->getCreatorFunc(ctrl_type); + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setBoolValue(*((bool*)val_ptr)); + return true; + } + return false; +} - if (func == NULL) +bool LLXUIParser::readStringValue(void* val_ptr) +{ + *((std::string*)val_ptr) = mCurReadNode->getSanitizedValue(); + return true; +} + +bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - llwarns << "Unknown control type " << ctrl_type << llendl; - return NULL; + node->setStringValue(*((std::string*)val_ptr)); + return true; } + return false; +} - if (parent == NULL) +bool LLXUIParser::readU8Value(void* val_ptr) +{ + return mCurReadNode->getByteValue(1, (U8*)val_ptr); +} + +bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - if (mDummyPanel == NULL) - { - mDummyPanel = new LLPanel; - } - parent = mDummyPanel; + node->setUnsignedValue(*((U8*)val_ptr)); + return true; } - LLView *ctrl = func(node, parent, this); + return false; +} - return ctrl; +bool LLXUIParser::readS8Value(void* val_ptr) +{ + S32 value; + if(mCurReadNode->getIntValue(1, &value)) + { + *((S8*)val_ptr) = value; + return true; + } + return false; } -LLView* LLUICtrlFactory::createWidget(LLPanel *parent, LLXMLNodePtr node) +bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack) { - LLView* view = createCtrlWidget(parent, node); + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S8*)val_ptr)); + return true; + } + return false; +} - S32 tab_group = parent->getLastTabGroup(); - node->getAttributeS32("tab_group", tab_group); +bool LLXUIParser::readU16Value(void* val_ptr) +{ + U32 value; + if(mCurReadNode->getUnsignedValue(1, &value)) + { + *((U16*)val_ptr) = value; + return true; + } + return false; +} - if (view) +bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - parent->addChild(view, tab_group); + node->setUnsignedValue(*((U16*)val_ptr)); + return true; } + return false; +} - return view; +bool LLXUIParser::readS16Value(void* val_ptr) +{ + S32 value; + if(mCurReadNode->getIntValue(1, &value)) + { + *((S16*)val_ptr) = value; + return true; + } + return false; } -//----------------------------------------------------------------------------- -// createFactoryPanel() -//----------------------------------------------------------------------------- -LLPanel* LLUICtrlFactory::createFactoryPanel(const std::string& name) +bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack) { - std::deque::iterator itor; - for (itor = mFactoryStack.begin(); itor != mFactoryStack.end(); ++itor) + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - const LLCallbackMap::map_t* factory_map = *itor; + node->setIntValue(*((S16*)val_ptr)); + return true; + } + return false; +} - // Look up this panel's name in the map. - LLCallbackMap::map_const_iter_t iter = factory_map->find( name ); - if (iter != factory_map->end()) - { - // Use the factory to create the panel, instead of using a default LLPanel. - LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData ); - return ret; - } +bool LLXUIParser::readU32Value(void* val_ptr) +{ + return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); +} + +bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U32*)val_ptr)); + return true; } - return NULL; + return false; } -//----------------------------------------------------------------------------- +bool LLXUIParser::readS32Value(void* val_ptr) +{ + return mCurReadNode->getIntValue(1, (S32*)val_ptr); +} -//static -BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color) +bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack) { - std::string colorstring; - BOOL res = node->getAttributeString(name.c_str(), colorstring); - if (res && LLUI::sColorsGroup) + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - if (LLUI::sColorsGroup->controlExists(colorstring)) - { - color.setVec(LLUI::sColorsGroup->getColor(colorstring)); - } - else - { - res = FALSE; - } + node->setIntValue(*((S32*)val_ptr)); + return true; } - if (!res) + return false; +} + +bool LLXUIParser::readF32Value(void* val_ptr) +{ + return mCurReadNode->getFloatValue(1, (F32*)val_ptr); +} + +bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - res = LLColor4::parseColor(colorstring, &color); - } - if (!res) + node->setFloatValue(*((F32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF64Value(void* val_ptr) +{ + return mCurReadNode->getDoubleValue(1, (F64*)val_ptr); +} + +bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - res = node->getAttributeColor(name.c_str(), color); + node->setDoubleValue(*((F64*)val_ptr)); + return true; } - return res; + return false; } +bool LLXUIParser::readColor4Value(void* val_ptr) +{ + LLColor4* colorp = (LLColor4*)val_ptr; + if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + LLColor4 color = *((LLColor4*)val_ptr); + node->setFloatValue(4, color.mV); + return true; + } + return false; +} + +bool LLXUIParser::readUIColorValue(void* val_ptr) +{ + LLUIColor* param = (LLUIColor*)val_ptr; + LLColor4 color; + bool success = mCurReadNode->getFloatValue(4, color.mV) >= 3; + if (success) + { + param->set(color); + return true; + } + return false; +} + +bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + LLUIColor color = *((LLUIColor*)val_ptr); + node->setFloatValue(4, color.get().mV); + return true; + } + return false; +} + +bool LLXUIParser::readUUIDValue(void* val_ptr) +{ + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(mCurReadNode->getSanitizedValue())) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLUUID*)val_ptr)->asString()); + return true; + } + return false; +} + +bool LLXUIParser::readSDValue(void* val_ptr) +{ + *((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue()); + return true; +} + +bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLSD*)val_ptr)->asString()); + return true; + } + return false; +} + +/*virtual*/ std::string LLXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studo friendly formatting of output message for easy access to originating xml + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserWarning(message); +#endif +} + +void LLXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserError(message); +#endif +} diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 5e7c24efc0..5b04557368 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -33,68 +33,326 @@ #ifndef LLUICTRLFACTORY_H #define LLUICTRLFACTORY_H +#include "llcallbackmap.h" +#include "llinitparam.h" +#include "llxmlnode.h" + +#include #include #include -#include "llcallbackmap.h" -#include "llfloater.h" - -class LLView; class LLPanel; +class LLFloater; +class LLView; -class LLUICtrlFactory : public LLSingleton +class LLXUIParser : public LLInitParam::Parser, public LLSingleton { +LOG_CLASS(LLXUIParser); + +protected: + LLXUIParser(); + friend class LLSingleton; public: + typedef LLInitParam::Parser::name_stack_t name_stack_t; + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent=false); + void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); + +private: + typedef std::list > token_list_t; + + bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block); + bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); + + //reader helper functions + bool readBoolValue(void* val_ptr); + bool readStringValue(void* val_ptr); + bool readU8Value(void* val_ptr); + bool readS8Value(void* val_ptr); + bool readU16Value(void* val_ptr); + bool readS16Value(void* val_ptr); + bool readU32Value(void* val_ptr); + bool readS32Value(void* val_ptr); + bool readF32Value(void* val_ptr); + bool readF64Value(void* val_ptr); + bool readColor4Value(void* val_ptr); + bool readUIColorValue(void* val_ptr); + bool readUUIDValue(void* val_ptr); + bool readSDValue(void* val_ptr); + + //writer helper functions + bool writeBoolValue(const void* val_ptr, const name_stack_t&); + bool writeStringValue(const void* val_ptr, const name_stack_t&); + bool writeU8Value(const void* val_ptr, const name_stack_t&); + bool writeS8Value(const void* val_ptr, const name_stack_t&); + bool writeU16Value(const void* val_ptr, const name_stack_t&); + bool writeS16Value(const void* val_ptr, const name_stack_t&); + bool writeU32Value(const void* val_ptr, const name_stack_t&); + bool writeS32Value(const void* val_ptr, const name_stack_t&); + bool writeF32Value(const void* val_ptr, const name_stack_t&); + bool writeF64Value(const void* val_ptr, const name_stack_t&); + bool writeColor4Value(const void* val_ptr, const name_stack_t&); + bool writeUIColorValue(const void* val_ptr, const name_stack_t&); + bool writeUUIDValue(const void* val_ptr, const name_stack_t&); + bool writeSDValue(const void* val_ptr, const name_stack_t&); + + LLXMLNodePtr getNode(const name_stack_t& stack); + +private: + Parser::name_stack_t mNameStack; + LLXMLNodePtr mCurReadNode; + // Root of the widget XML sub-tree, for example, "line_editor" + LLXMLNodePtr mWriteRootNode; + S32 mLastWriteGeneration; + LLXMLNodePtr mLastWrittenChild; +}; + +// global static instance for registering all widget types +typedef boost::function LLWidgetCreatorFunc; + +class LLWidgetCreatorRegistry : public LLRegistrySingleton +{ +protected: + LLWidgetCreatorRegistry() {} + +private: + friend class LLSingleton; +}; + +struct LLCompareTypeID +{ + bool operator()(const std::type_info* lhs, const std::type_info* rhs) const + { + return lhs->before(*rhs); + } +}; + + +class LLWidgetTemplateRegistry +: public LLRegistrySingleton +{ + +}; + +// local static instance for registering a particular widget +template +class LLRegisterWidget +: public LLWidgetCreatorRegistry::StaticRegistrar +{ +public: + // register with either the provided builder, or the generic templated builder + LLRegisterWidget(const char* tag, LLWidgetCreatorFunc func = NULL); +}; + +class LLUICtrlFactory : public LLSingleton +{ +private: + friend class LLSingleton; LLUICtrlFactory(); - // do not call! needs to be public so run-time can clean up the singleton - virtual ~LLUICtrlFactory(); + ~LLUICtrlFactory(); + + // only partial specialization allowed in inner classes, so use extra dummy parameter + template + class ParamDefaults : public LLSingleton > + { + public: + ParamDefaults() + { + // recursively initialize from base class param block + ((typename T::base_block_t&)mPrototype).fillFrom(ParamDefaults::instance().get()); + // after initializing base classes, look up template file for this param block + std::string* param_block_tag = LLWidgetTemplateRegistry::instance().getValue(&typeid(T)); + if (param_block_tag) + { + LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype); + } + } - void setupPaths(); + const T& get() { return mPrototype; } - void buildFloater(LLFloater* floaterp, const std::string &filename, - const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE); - BOOL buildPanel(LLPanel* panelp, const std::string &filename, - const LLCallbackMap::map_t* factory_map = NULL); + private: + T mPrototype; + }; - void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); } - void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); } + // base case for recursion, there are NO base classes of LLInitParam::BaseBlock + template + class ParamDefaults : public LLSingleton > + { + public: + const LLInitParam::BaseBlock& get() { return mBaseBlock; } + private: + LLInitParam::BaseBlock mBaseBlock; + }; - class LLMenuGL *buildMenu(const std::string &filename, LLView* parentp); - class LLPieMenu *buildPieMenu(const std::string &filename, LLView* parentp); +public: + + template + static const T& getDefaultParams() + { + //#pragma message("Generating ParamDefaults") + return ParamDefaults::instance().get(); + } + + void buildFloater(LLFloater* floaterp, const std::string &filename, BOOL open_floater = TRUE, LLXMLNodePtr output_node = NULL); + LLFloater* buildFloaterFromXML(const std::string& filename, BOOL open_floater = TRUE); + BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL); // Does what you want for LLFloaters and LLPanels // Returns 0 on success S32 saveToXML(LLView* viewp, const std::string& filename); - // Rebuilds all currently built panels. - void rebuild(); + std::string getCurFileName() { return mFileNames.empty() ? "" : mFileNames.back(); } static BOOL getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color); LLPanel* createFactoryPanel(const std::string& name); - virtual LLView* createCtrlWidget(LLPanel *parent, LLXMLNodePtr node); - virtual LLView* createWidget(LLPanel *parent, LLXMLNodePtr node); + void pushFactoryFunctions(const LLCallbackMap::map_t* map); + void popFactoryFunctions(); - static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); + template + static T* create(typename T::Params& params, LLView* parent = NULL) + { + //#pragma message("Generating LLUICtrlFactory::create") + params.fillFrom(ParamDefaults::instance().get()); + //S32 foo = "test"; - static const std::vector& getXUIPaths(); + if (!params.validateBlock()) + { + llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; + } + T* widget = new T(params); + widget->initFromParams(params); + if (parent) + widget->setParent(parent); + return widget; + } -private: - bool getLayeredXMLNodeImpl(const std::string &filename, LLXMLNodePtr& root); + LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename = LLStringUtil::null, LLXMLNodePtr output_node = NULL); + + template + static T* createFromFile(const std::string &filename, LLView *parent) + { + //#pragma message("Generating LLUICtrlFactory::createFromFile") + T* widget = NULL; + + std::string skinned_filename = findSkinnedFilename(filename); + getInstance()->mFileNames.push_back(skinned_filename); + { + LLXMLNodePtr root_node; + + if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) + { + LLView* view = getInstance()->createFromXML(root_node, parent, filename); + if (view) + { + widget = dynamic_cast(view); + // not of right type, so delete it + if (!widget) + { + delete view; + view = NULL; + } + + } + } + else + { + llwarns << "Couldn't parse XUI file: " << skinned_filename << llendl; + } + } + getInstance()->mFileNames.pop_back(); - typedef std::map, std::string> built_panel_t; - built_panel_t mBuiltPanels; + return widget; + } - typedef std::map, std::string> built_floater_t; - built_floater_t mBuiltFloaters; + template + static T* createDummyWidget(const std::string& name) + { + //#pragma message("Generating LLUICtrlFactory::createDummyWidget") + typename T::Params params; + params.name(name); + + return create(params); + } - std::deque mFactoryStack; + template + static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) + { + //#pragma message("Generating LLUICtrlFactory::defaultBuilder") + PARAM_BLOCK params(getDefaultParams()); - static std::vector sXUIPaths; + LLXUIParser::instance().readXUI(node, params); - LLPanel* mDummyPanel; + if (output_node) + { + // We always want to output top-left coordinates + PARAM_BLOCK output_params(params); + T::setupParamsForExport(output_params, parent); + // Export only the differences between this any default params + PARAM_BLOCK default_params(getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); + } + + // Apply layout transformations, usually munging rect + T::setupParams(params, parent); + + if (!params.validateBlock()) + { + llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; + } + T* widget = new T(params); + widget->initFromParams(params); + + if (parent) + { + S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; + setCtrlParent(widget, parent, tab_group); + } + + widget->addChildren(node, output_node); + + if (!widget->postBuild()) + { + delete widget; + return NULL; + } + + return widget; + } + + static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); + + static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); + +private: + //static void setCtrlValue(LLView* view, LLXMLNodePtr node); + static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); + + // Avoid directly using LLUI and LLDir in the template code + static std::string findSkinnedFilename(const std::string& filename); + + typedef std::deque factory_stack_t; + factory_stack_t mFactoryStack; + + LLPanel* mDummyPanel; + std::vector mFileNames; }; +// this is here to make gcc happy with reference to LLUICtrlFactory +template +LLRegisterWidget::LLRegisterWidget(const char* tag, LLWidgetCreatorFunc func) +: LLWidgetCreatorRegistry::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder : func) +{ + //FIXME: inventory_panel will register itself with LLPanel::Params but it does have its own params...:( + LLWidgetTemplateRegistry::instance().defaultRegistrar().add(&typeid(PARAM_BLOCK), tag); +} + #endif //LLUICTRLFACTORY_H diff --git a/indra/llui/lluifwd.h b/indra/llui/lluifwd.h index 32d5c9b44f..f99bb39fdd 100644 --- a/indra/llui/lluifwd.h +++ b/indra/llui/lluifwd.h @@ -53,7 +53,6 @@ class LLSlider; class LLSliderCtrl; class LLSpinCtrl; class LLTabContainer; -class LLTabContainerVertical; class LLTextBox; class LLTextEditor; class LLTextureCtrl; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp new file mode 100644 index 0000000000..0ed2283742 --- /dev/null +++ b/indra/llui/lluiimage.cpp @@ -0,0 +1,158 @@ +/** + * @file lluiimage.cpp + * @brief UI implementation + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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$ + */ + +// Utilities functions the user interface needs + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +// Project includes +#include "lluiimage.h" +#include "llui.h" + +LLUIImage::LLUIImage(const std::string& name, LLPointer image) : + mName(name), + mImage(image), + mScaleRegion(0.f, 1.f, 1.f, 0.f), + mClipRegion(0.f, 1.f, 1.f, 0.f), + mUniformScaling(TRUE), + mNoClip(TRUE) +{ +} + +void LLUIImage::setClipRegion(const LLRectf& region) +{ + mClipRegion = region; + mNoClip = mClipRegion.mLeft == 0.f + && mClipRegion.mRight == 1.f + && mClipRegion.mBottom == 0.f + && mClipRegion.mTop == 1.f; +} + +void LLUIImage::setScaleRegion(const LLRectf& region) +{ + mScaleRegion = region; + mUniformScaling = mScaleRegion.mLeft == 0.f + && mScaleRegion.mRight == 1.f + && mScaleRegion.mBottom == 0.f + && mScaleRegion.mTop == 1.f; +} + +//TODO: move drawing implementation inside class +void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const +{ + gl_draw_image(x, y, mImage, color, mClipRegion); +} + +void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + if (mUniformScaling) + { + gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); + } + else + { + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + FALSE, + mClipRegion, + mScaleRegion); + } +} + +void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + TRUE, + mClipRegion, + mScaleRegion); +} + +void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const +{ + LLRect border_rect; + border_rect.setOriginAndSize(x, y, width, height); + border_rect.stretch(border_width, border_width); + drawSolid(border_rect, color); +} + +S32 LLUIImage::getWidth() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); +} + +S32 LLUIImage::getHeight() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); +} + +S32 LLUIImage::getTextureWidth() const +{ + return mImage->getWidth(0); +} + +S32 LLUIImage::getTextureHeight() const +{ + return mImage->getHeight(0); +} + +namespace LLInitParam +{ + LLUIImage* TypedParam::getValueFromBlock() const + { + LLUIImage* imagep = LLUI::getUIImage(name()); + if (!imagep) + { + // default to current value + imagep = mData.mValue; + } + return imagep; + } + + template<> + bool ParamCompare::equals( + LLUIImage* const &a, + LLUIImage* const &b) + { + // force all LLUIImages for XML UI export to be "non-default" + return false; + } +} diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h new file mode 100644 index 0000000000..cd660a0954 --- /dev/null +++ b/indra/llui/lluiimage.h @@ -0,0 +1,113 @@ +/** + * @file lluiimage.h + * @brief wrapper for images used in the UI that handles smart scaling, etc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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_LLUIIMAGE_H +#define LL_LLUIIMAGE_H + +#include "llgl.h" +#include "llimagegl.h" +#include "llrefcount.h" +#include "llrect.h" +#include +#include "llinitparam.h" + +extern const LLColor4 UI_VERTEX_COLOR; + +class LLUIImage : public LLRefCount +{ +public: + LLUIImage(const std::string& name, LLPointer image); + + void setClipRegion(const LLRectf& region); + void setScaleRegion(const LLRectf& region); + + LLPointer getImage() { return mImage; } + const LLPointer& getImage() const { return mImage; } + + void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + + void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; + void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, mImage->getWidth(0), mImage->getHeight(0), color); } + + void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; + void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } + void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, mImage->getWidth(0), mImage->getHeight(0), color, border_width); } + + const std::string& getName() const { return mName; } + + S32 getWidth() const; + S32 getHeight() const; + + // returns dimensions of underlying textures, which might not be equal to ui image portion + S32 getTextureWidth() const; + S32 getTextureHeight() const; + +protected: + std::string mName; + LLRectf mScaleRegion; + LLRectf mClipRegion; + LLPointer mImage; + BOOL mUniformScaling; + BOOL mNoClip; +}; + +namespace LLInitParam +{ + template<> + class TypedParam, false> + : public BlockValue + { + typedef boost::add_reference::type>::type T_const_ref; + typedef BlockValue super_t; + public: + Optional name; + + TypedParam(BlockDescriptor& descriptor, const std::string& name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func) + : super_t(descriptor, name, value, func) + { + } + + LLUIImage* getValueFromBlock() const; + }; + + // Need custom comparison function for our test app, which only loads + // LLUIImage* as NULL. + template<> + bool ParamCompare::equals( + LLUIImage* const &a, LLUIImage* const &b); +} + +typedef LLPointer LLUIImagePtr; +#endif diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 0b76b8e814..ce73990d27 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -33,6 +33,7 @@ #include "linden_common.h" #include "lluistring.h" #include "llsd.h" +#include "lltrans.h" const LLStringUtil::format_map_t LLUIString::sNullArgs; @@ -112,6 +113,10 @@ void LLUIString::clear() void LLUIString::format() { mResult = mOrig; - LLStringUtil::format(mResult, mArgs); + + // get the defailt args + local args + LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); + combined_args.insert(mArgs.begin(), mArgs.end()); + LLStringUtil::format(mResult, combined_args); mWResult = utf8str_to_wstring(mResult); } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 2350ea6050..462fd16b60 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -56,17 +56,18 @@ #include "lltexteditor.h" #include "lltextbox.h" -//HACK: this allows you to instantiate LLView from xml with "" which we don't want -static LLRegisterWidget r("view"); - BOOL LLView::sDebugRects = FALSE; BOOL LLView::sDebugKeys = FALSE; S32 LLView::sDepth = 0; BOOL LLView::sDebugMouseHandling = FALSE; std::string LLView::sMouseHandlerMessage; -BOOL LLView::sEditingUI = FALSE; +//BOOL LLView::sEditingUI = FALSE; BOOL LLView::sForceReshape = FALSE; -LLView* LLView::sEditingUIView = NULL; +//LLView* LLView::sEditingUIView = NULL; +std::set LLView::sPreviewHighlightedElements; +BOOL LLView::sHighlightingDiffs = FALSE; +LLView* LLView::sPreviewClickedElement = NULL; +BOOL LLView::sDrawPreviewHighlights = FALSE; S32 LLView::sLastLeftXML = S32_MIN; S32 LLView::sLastBottomXML = S32_MIN; @@ -74,77 +75,76 @@ S32 LLView::sLastBottomXML = S32_MIN; BOOL LLView::sIsDrawing = FALSE; #endif -LLView::LLView() : - mParentView(NULL), - mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(TRUE), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) -{ -} - -LLView::LLView(const std::string& name, BOOL mouse_opaque) : +LLView::Params::Params() +: name("name", std::string("unnamed")), + enabled("enabled", true), + visible("visible", true), + mouse_opaque("mouse_opaque", true), + follows("follows"), + hover_cursor("hover_cursor", "UI_CURSOR_ARROW"), + use_bounding_rect("use_bounding_rect", false), + tab_group("tab_group", 0), + default_tab_group("default_tab_group"), + tool_tip("tool_tip"), + sound_flags("sound_flags", MOUSE_UP), + font("font", LLFontGL::getFontSansSerif()), + font_halign("halign"), + font_valign("valign"), + layout("layout"), + rect("rect"), + bottom_delta("bottom_delta", S32_MAX), + left_delta("left_delta", S32_MAX), + top_delta("top_delta"), + right_delta("right_delta"), + center_horiz("center_horiz", false), + center_vert("center_vert", false), + serializable("", false), + user_resize("user_resize"), + auto_resize("auto_resize"), + needs_translate("translate") +{ + addSynonym(rect, ""); +} + +LLView::LLView(const LLView::Params& p) +: mName(p.name), mParentView(NULL), - mName(name), mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) -{ -} - - -LLView::LLView( - const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) : - mParentView(NULL), - mName(name), - mRect(rect), - mBoundingRect(rect), - mReshapeFlags(reshape), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), + mSaveToXML(p.serializable), mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), + mLastVisible(FALSE), mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) + mHoverCursor(getCursorFromString(p.hover_cursor)), + mEnabled(p.enabled), + mVisible(p.visible), + mMouseOpaque(p.mouse_opaque), + mSoundFlags(p.sound_flags), + mUseBoundingRect(p.use_bounding_rect), + mDefaultTabGroup(p.default_tab_group), + mLastTabGroup(0), + mToolTipMsg((LLStringExplicit)p.tool_tip()) { + // create rect first, as this will supply initial follows flags + setShape(p.rect); + parseFollowsFlags(p); } - LLView::~LLView() { //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; // llassert(LLView::sIsDrawing == FALSE); + +// llassert_always(sDepth == 0); // avoid deleting views while drawing! It can subtly break list iterators + if( gFocusMgr.getKeyboardFocus() == this ) { - llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; + //llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; gFocusMgr.removeKeyboardFocusWithoutCallback( this ); } if( hasMouseCapture() ) { - llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; + //llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; gFocusMgr.removeMouseCaptureWithoutCallback( this ); } @@ -155,14 +155,6 @@ LLView::~LLView() mParentView->removeChild(this); } - dispatch_list_t::iterator itor; - for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor) - { - (*itor).second->clearDispatchers(); - } - - std::for_each(mFloaterControls.begin(), mFloaterControls.end(), - DeletePairedPointer()); std::for_each(mDummyWidgets.begin(), mDummyWidgets.end(), DeletePairedPointer()); } @@ -185,7 +177,6 @@ BOOL LLView::isPanel() const return FALSE; } -// virtual void LLView::setToolTip(const LLStringExplicit& msg) { mToolTipMsg = msg; @@ -232,19 +223,31 @@ const std::string& LLView::getName() const void LLView::sendChildToFront(LLView* child) { +// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child && child->getParent() == this) { - mChildList.remove( child ); - mChildList.push_front(child); + // minor optimization, but more importantly, + // won't temporarily create an empty list + if (child != mChildList.front()) + { + mChildList.remove( child ); + mChildList.push_front(child); + } } } void LLView::sendChildToBack(LLView* child) { +// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child && child->getParent() == this) { - mChildList.remove( child ); - mChildList.push_back(child); + // minor optimization, but more importantly, + // won't temporarily create an empty list + if (child != mChildList.back()) + { + mChildList.remove( child ); + mChildList.push_back(child); + } } } @@ -264,12 +267,46 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) } } -void LLView::addChild(LLView* child, S32 tab_group) +void LLView::addChildren(LLXMLNodePtr node, LLXMLNodePtr output_node) +{ + if (node.isNull()) return; + + for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling()) + { + LLXMLNodePtr outputChild; + if (output_node) + { + outputChild = output_node->createChild("", FALSE); + } + + if (!LLUICtrlFactory::getInstance()->createFromXML(child_node, this, LLStringUtil::null, outputChild)) + { + std::string child_name = std::string(child_node->getName()->mString); + if (child_name.find(".") == std::string::npos) + { + llwarns << "Could not create widget named " << child_node->getName()->mString << llendl; + } + } + + if (outputChild && !outputChild->mChildren && outputChild->mAttributes.empty() && outputChild->getValue().empty()) + { + output_node->deleteChild(outputChild); + } + } +} + +// virtual +bool LLView::addChild(LLView* child, S32 tab_group) { + if (!child) + { + return false; + } if (mParentView == child) { llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; } + // remove from current parent if (child->mParentView) { @@ -282,55 +319,46 @@ void LLView::addChild(LLView* child, S32 tab_group) // add to ctrl list if is LLUICtrl if (child->isCtrl()) { - // controls are stored in reverse order from render order - addCtrlAtEnd((LLUICtrl*) child, tab_group); + LLUICtrl* ctrl = static_cast(child); + mCtrlOrder.insert(tab_order_pair_t(ctrl, + tab_order_t(tab_group, mNextInsertionOrdinal))); + + mNextInsertionOrdinal++; } child->mParentView = this; updateBoundingRect(); + mLastTabGroup = tab_group; + return true; } -void LLView::addChildAtEnd(LLView* child, S32 tab_group) +bool LLView::addChildInBack(LLView* child, S32 tab_group) { - if (mParentView == child) - { - llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; - } - // remove from current parent - if (child->mParentView) + if(addChild(child, tab_group)) { - child->mParentView->removeChild(child); + sendChildToBack(child); + return true; } - // add to back of child list - mChildList.push_back(child); - - // add to ctrl list if is LLUICtrl - if (child->isCtrl()) - { - // controls are stored in reverse order from render order - addCtrl((LLUICtrl*) child, tab_group); - } - - child->mParentView = this; - updateBoundingRect(); + return false; } // remove the specified child from the view, and set it's parent to NULL. -void LLView::removeChild(LLView* child, BOOL deleteIt) +void LLView::removeChild(LLView* child) { + //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { mChildList.remove( child ); child->mParentView = NULL; if (child->isCtrl()) { - removeCtrl((LLUICtrl*)child); - } - if (deleteIt) - { - delete child; + child_tab_order_t::iterator found = mCtrlOrder.find(static_cast(child)); + if(found != mCtrlOrder.end()) + { + mCtrlOrder.erase(found); + } } } else @@ -340,28 +368,6 @@ void LLView::removeChild(LLView* child, BOOL deleteIt) updateBoundingRect(); } -void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group) -{ - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, mNextInsertionOrdinal++))); -} - -void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group) -{ - // add to front of list by using negative ordinal, which monotonically increases - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, -1 * mNextInsertionOrdinal++))); -} - -void LLView::removeCtrl(LLUICtrl* ctrl) -{ - child_tab_order_t::iterator found = mCtrlOrder.find(ctrl); - if(found != mCtrlOrder.end()) - { - mCtrlOrder.erase(found); - } -} - LLView::ctrl_list_t LLView::getCtrlList() const { ctrl_list_t controls; @@ -651,7 +657,7 @@ BOOL LLView::canSnapTo(const LLView* other_view) } // virtual -void LLView::snappedTo(const LLView* snap_view) +void LLView::setSnappedTo(const LLView* snap_view) { } @@ -669,6 +675,17 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask) return handled; } +void LLView::onMouseEnter(S32 x, S32 y, MASK mask) +{ + //llinfos << "Mouse entered " << getName() << llendl; +} + +void LLView::onMouseLeave(S32 x, S32 y, MASK mask) +{ + //llinfos << "Mouse left " << getName() << llendl; +} + + std::string LLView::getShowNamesToolTip() { LLView* view = getParent(); @@ -729,23 +746,14 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s // get our own tooltip tool_tip = mToolTipMsg.getString(); - if ( - LLUI::sShowXUINames + + if (LLUI::sShowXUINames && (tool_tip.find(".xml", 0) == std::string::npos) && (mName.find("Drag", 0) == std::string::npos)) { tool_tip = getShowNamesToolTip(); } - BOOL show_names_text_box = LLUI::sShowXUINames && dynamic_cast(this) != NULL; - - // don't allow any siblings to handle this event - // even if we don't have a tooltip - if (getMouseOpaque() || show_names_text_box) - { - handled = TRUE; - } - if(!tool_tip.empty()) { msg = tool_tip; @@ -757,7 +765,13 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s localPointToScreen( mRect.getWidth(), mRect.getHeight(), &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); - + } + // 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(this)))) + { handled = TRUE; } @@ -923,22 +937,22 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask) handled_view = this; } - // HACK If we're editing UI, select the leaf view that ate the click. - if (sEditingUI && handled_view) - { - // need to find leaf views, big hack - LLButton* buttonp = dynamic_cast(handled_view); - LLLineEditor* line_editorp = dynamic_cast(handled_view); - LLTextEditor* text_editorp = dynamic_cast(handled_view); - LLTextBox* text_boxp = dynamic_cast(handled_view); - if (buttonp - || line_editorp - || text_editorp - || text_boxp) - { - sEditingUIView = handled_view; - } - } + //// HACK If we're editing UI, select the leaf view that ate the click. + //if (sEditingUI && handled_view) + //{ + // // need to find leaf views, big hack + // LLButton* buttonp = dynamic_cast(handled_view); + // LLLineEditor* line_editorp = dynamic_cast(handled_view); + // LLTextEditor* text_editorp = dynamic_cast(handled_view); + // LLTextBox* text_boxp = dynamic_cast(handled_view); + // if (buttonp + // || line_editorp + // || text_editorp + // || text_boxp) + // { + // sEditingUIView = handled_view; + // } + //} return handled; } @@ -1164,6 +1178,7 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask) { sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; } + handled_view = viewp; break; } @@ -1326,55 +1341,58 @@ void LLView::draw() } } - LLRect rootRect = getRootView()->getRect(); - LLRect screenRect; - - // draw focused control on top of everything else - LLView* focus_view = gFocusMgr.getKeyboardFocus(); - if (focus_view && focus_view->getParent() != this) + if (!mChildList.empty()) { - focus_view = NULL; - } + LLRect rootRect = getRootView()->getRect(); + LLRect screenRect; - ++sDepth; - for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) - { - LLView *viewp = *child_iter; + // draw focused control on top of everything else + LLView* focus_view = gFocusMgr.getKeyboardFocus(); + if (focus_view && focus_view->getParent() != this) + { + focus_view = NULL; + } + + ++sDepth; - if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) + for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter) { - // Only draw views that are within the root view - localRectToScreen(viewp->getRect(),&screenRect); - if ( rootRect.rectInRect(&screenRect) ) + child_list_reverse_iter_t child = child_iter++; + LLView *viewp = *child; + + if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) { - glMatrixMode(GL_MODELVIEW); - LLUI::pushMatrix(); + // Only draw views that are within the root view + localRectToScreen(viewp->getRect(),&screenRect); + if ( rootRect.rectInRect(&screenRect) ) { - LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); - viewp->draw(); + glMatrixMode(GL_MODELVIEW); + LLUI::pushMatrix(); + { + LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); + viewp->draw(); + } + LLUI::popMatrix(); } - LLUI::popMatrix(); } - } - } - --sDepth; + } + --sDepth; - if (focus_view && focus_view->getVisible()) - { - drawChild(focus_view); + if (focus_view && focus_view->getVisible()) + { + drawChild(focus_view); + } } - // HACK - if (sEditingUI && this == sEditingUIView) - { - drawDebugRect(); - } + gGL.getTexUnit(0)->disable(); } //Draw a box for debugging. void LLView::drawDebugRect() { + std::set::iterator preview_iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this); // figure out if it's a previewed element + LLUI::pushMatrix(); { // drawing solids requires texturing be disabled @@ -1389,9 +1407,21 @@ void LLView::drawDebugRect() // draw red rectangle for the border LLColor4 border_color(0.f, 0.f, 0.f, 1.f); - if (sEditingUI) + //if (sEditingUI) + //{ + // border_color.mV[0] = 1.f; + //} + if(preview_iter != sPreviewHighlightedElements.end()) { - border_color.mV[0] = 1.f; + if(LLView::sPreviewClickedElement && this == sPreviewClickedElement) + { + border_color = LLColor4::red; + } + else + { + static LLUICachedControl scroll_highlighted_color ("ScrollHighlightedColor", *(new LLColor4)); + border_color = scroll_highlighted_color; + } } else { @@ -1414,8 +1444,8 @@ void LLView::drawDebugRect() gGL.vertex2i(0, debug_rect.getHeight() - 1); gGL.end(); - // Draw the name if it's not a leaf node - if (mChildList.size() && !sEditingUI) + // Draw the name if it's not a leaf node or not in editing or preview mode + if (mChildList.size() && preview_iter == sPreviewHighlightedElements.end()) { //char temp[256]; S32 x, y; @@ -1425,7 +1455,7 @@ void LLView::drawDebugRect() std::string debug_text = llformat("%s (%d x %d)", getName().c_str(), debug_rect.getWidth(), debug_rect.getHeight()); LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, - LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, + LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); } } @@ -1581,15 +1611,28 @@ void LLView::updateBoundingRect() } } -LLRect LLView::getScreenRect() const +LLRect LLView::calcScreenRect() const { - // *FIX: check for one-off error LLRect screen_rect; localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom); localPointToScreen(getRect().getWidth(), getRect().getHeight(), &screen_rect.mRight, &screen_rect.mTop); return screen_rect; } +LLRect LLView::calcScreenBoundingRect() const +{ + LLRect screen_rect; + // get bounding rect, if used + LLRect bounding_rect = mUseBoundingRect ? mBoundingRect : mRect; + + // convert to local coordinates, as defined by mRect + bounding_rect.translate(-mRect.mLeft, -mRect.mBottom); + + localPointToScreen(bounding_rect.mLeft, bounding_rect.mBottom, &screen_rect.mLeft, &screen_rect.mBottom); + localPointToScreen(bounding_rect.mRight, bounding_rect.mTop, &screen_rect.mRight, &screen_rect.mTop); + return screen_rect; +} + LLRect LLView::getLocalBoundingRect() const { LLRect local_bounding_rect = getBoundingRect(); @@ -1688,7 +1731,12 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ if (create_if_missing) { - return createDummyWidget(name); + LLView* view = getDummyWidget(name); + if (!view) + { + view = LLUICtrlFactory::createDummyWidget(name); + } + return view; } return NULL; } @@ -1777,12 +1825,32 @@ LLView* LLView::getRootView() return view; } -BOOL LLView::deleteViewByHandle(LLHandle handle) +LLView* LLView::findPrevSibling(LLView* child) +{ + child_list_t::iterator prev_it = std::find(mChildList.begin(), mChildList.end(), child); + if (prev_it != mChildList.end() && prev_it != mChildList.begin()) + { + return *(--prev_it); + } + return NULL; +} + +LLView* LLView::findNextSibling(LLView* child) +{ + child_list_t::iterator next_it = std::find(mChildList.begin(), mChildList.end(), child); + if (next_it != mChildList.end()) + { + next_it++; + } + + return (next_it != mChildList.end()) ? *next_it : NULL; +} + +void LLView::deleteViewByHandle(LLHandle handle) { LLView* viewp = handle.get(); delete viewp; - return viewp != NULL; } @@ -1943,132 +2011,6 @@ BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* o return FALSE; } -// virtual -LLXMLNodePtr LLView::getXML(bool save_children) const -{ - //FIXME: need to provide actual derived type tag, probably outside this method - LLXMLNodePtr node = new LLXMLNode("view", FALSE); - - node->createChild("name", TRUE)->setStringValue(getName()); - node->createChild("width", TRUE)->setIntValue(getRect().getWidth()); - node->createChild("height", TRUE)->setIntValue(getRect().getHeight()); - - LLView* parent = getParent(); - S32 left = getRect().mLeft; - S32 bottom = getRect().mBottom; - if (parent) bottom -= parent->getRect().getHeight(); - - node->createChild("left", TRUE)->setIntValue(left); - node->createChild("bottom", TRUE)->setIntValue(bottom); - - U32 follows_flags = getFollows(); - if (follows_flags) - { - std::stringstream buffer; - bool pipe = false; - if (followsLeft()) - { - buffer << "left"; - pipe = true; - } - if (followsTop()) - { - if (pipe) buffer << "|"; - buffer << "top"; - pipe = true; - } - if (followsRight()) - { - if (pipe) buffer << "|"; - buffer << "right"; - pipe = true; - } - if (followsBottom()) - { - if (pipe) buffer << "|"; - buffer << "bottom"; - } - node->createChild("follows", TRUE)->setStringValue(buffer.str()); - } - // Export all widgets as enabled and visible - code must disable. - node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque ); - if (!mToolTipMsg.getString().empty()) - { - node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg.getString()); - } - if (mSoundFlags != MOUSE_UP) - { - node->createChild("sound_flags", TRUE)->setIntValue((S32)mSoundFlags); - } - - node->createChild("enabled", TRUE)->setBoolValue(getEnabled()); - - if (!mControlName.empty()) - { - node->createChild("control_name", TRUE)->setStringValue(mControlName); - } - return node; -} - -//static -LLView* LLView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - LLView* viewp = new LLView(); - viewp->initFromXML(node, parent); - return viewp; -} - -// static -void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color, - const char* xml_name, const char* control_name) -{ - if (color != LLUI::sColorsGroup->getColor(ll_safe_string(control_name))) - { - node->createChild(xml_name, TRUE)->setFloatValue(4, color.mV); - } -} - -//static -std::string LLView::escapeXML(const std::string& xml, std::string& indent) -{ - std::string ret = indent + "\"" + LLXMLNode::escapeXML(xml); - - //replace every newline with a close quote, new line, indent, open quote - size_t index = ret.size()-1; - size_t fnd; - - while ((fnd = ret.rfind("\n", index)) != std::string::npos) - { - ret.replace(fnd, 1, "\"\n" + indent + "\""); - index = fnd-1; - } - - //append close quote - ret.append("\""); - - return ret; -} - -// static -LLWString LLView::escapeXML(const LLWString& xml) -{ - LLWString out; - for (LLWString::size_type i = 0; i < xml.size(); ++i) - { - llwchar c = xml[i]; - switch(c) - { - case '"': out.append(utf8string_to_wstring(""")); break; - case '\'': out.append(utf8string_to_wstring("'")); break; - case '&': out.append(utf8string_to_wstring("&")); break; - case '<': out.append(utf8string_to_wstring("<")); break; - case '>': out.append(utf8string_to_wstring(">")); break; - default: out.push_back(c); break; - } - } - return out; -} - // static const LLCtrlQuery & LLView::getTabOrderQuery() { @@ -2105,7 +2047,12 @@ const LLCtrlQuery & LLView::getFocusRootsQuery() } -void LLView::userSetShape(const LLRect& new_rect) +void LLView::setShape(const LLRect& new_rect, bool by_user) +{ + handleReshape(new_rect, by_user); +} + +void LLView::handleReshape(const LLRect& new_rect, bool by_user) { reshape(new_rect.getWidth(), new_rect.getHeight()); translate(new_rect.mLeft - getRect().mLeft, new_rect.mBottom - getRect().mBottom); @@ -2353,306 +2300,52 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna // Listener dispatch functions //----------------------------------------------------------------------------- -void LLView::registerEventListener(std::string name, LLSimpleListener* function) -{ - mDispatchList.insert(std::pair(name, function)); -} - -void LLView::deregisterEventListener(std::string name) -{ - dispatch_list_t::iterator itor = mDispatchList.find(name); - if (itor != mDispatchList.end()) - { - mDispatchList.erase(itor); - } -} - -std::string LLView::findEventListener(LLSimpleListener *listener) const -{ - dispatch_list_t::const_iterator itor; - for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor) - { - if (itor->second == listener) - { - return itor->first; - } - } - if (mParentView) - { - return mParentView->findEventListener(listener); - } - return LLStringUtil::null; -} - -LLSimpleListener* LLView::getListenerByName(const std::string& callback_name) -{ - LLSimpleListener* callback = NULL; - dispatch_list_t::iterator itor = mDispatchList.find(callback_name); - if (itor != mDispatchList.end()) - { - callback = itor->second; - } - else if (mParentView) - { - callback = mParentView->getListenerByName(callback_name); - } - return callback; -} LLControlVariable *LLView::findControl(const std::string& name) { - control_map_t::iterator itor = mFloaterControls.find(name); - if (itor != mFloaterControls.end()) + LLControlVariable* control; + control = LLUI::sSettingGroups["color"]->getControl(name); + if (control) { - return itor->second; + return control; } - if (mParentView) - { - return mParentView->findControl(name); - } - return LLUI::sConfigGroup->getControl(name); + + return LLUI::sSettingGroups["config"]->getControl(name); } const S32 FLOATER_H_MARGIN = 15; const S32 MIN_WIDGET_HEIGHT = 10; const S32 VPAD = 4; -// static -U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect) -{ - U32 follows = 0; - S32 x = rect.mLeft; - S32 y = rect.mBottom; - S32 w = rect.getWidth(); - S32 h = rect.getHeight(); - - U32 last_x = 0; - U32 last_y = 0; - if (parent_view) - { - last_y = parent_view->getRect().getHeight(); - child_list_t::const_iterator itor = parent_view->getChildList()->begin(); - if (itor != parent_view->getChildList()->end()) - { - LLView *last_view = (*itor); - if (last_view->getSaveToXML()) - { - last_x = last_view->getRect().mLeft; - last_y = last_view->getRect().mBottom; - } - } - } - - std::string rect_control; - node->getAttributeString("rect_control", rect_control); - if (! rect_control.empty()) - { - LLRect rect = LLUI::sConfigGroup->getRect(rect_control); - x = rect.mLeft; - y = rect.mBottom; - w = rect.getWidth(); - h = rect.getHeight(); - } - - if (node->hasAttribute("left")) - { - node->getAttributeS32("left", x); - } - if (node->hasAttribute("bottom")) - { - node->getAttributeS32("bottom", y); - } - - // Make your width the width of the containing - // view if you don't specify a width. - if (parent_view) - { - if(w == 0) - { - w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x); - } - - if(h == 0) - { - h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight()); - } - } - - if (node->hasAttribute("width")) - { - node->getAttributeS32("width", w); - } - if (node->hasAttribute("height")) - { - node->getAttributeS32("height", h); - } - - if (parent_view) - { - if (node->hasAttribute("left_delta")) - { - S32 left_delta = 0; - node->getAttributeS32("left_delta", left_delta); - x = last_x + left_delta; - } - else if (node->hasAttribute("left") && node->hasAttribute("right")) - { - // compute width based on left and right - S32 right = 0; - node->getAttributeS32("right", right); - if (right < 0) - { - right = parent_view->getRect().getWidth() + right; - } - w = right - x; - } - else if (node->hasAttribute("left")) - { - if (x < 0) - { - x = parent_view->getRect().getWidth() + x; - follows |= FOLLOWS_RIGHT; - } - else - { - follows |= FOLLOWS_LEFT; - } - } - else if (node->hasAttribute("width") && node->hasAttribute("right")) - { - S32 right = 0; - node->getAttributeS32("right", right); - if (right < 0) - { - right = parent_view->getRect().getWidth() + right; - } - x = right - w; - } - else - { - // left not specified, same as last - x = last_x; - } - - if (node->hasAttribute("bottom_delta")) - { - S32 bottom_delta = 0; - node->getAttributeS32("bottom_delta", bottom_delta); - y = last_y + bottom_delta; - } - else if (node->hasAttribute("top")) - { - // compute height based on top - S32 top = 0; - node->getAttributeS32("top", top); - if (top < 0) - { - top = parent_view->getRect().getHeight() + top; - } - h = top - y; - } - else if (node->hasAttribute("bottom")) - { - if (y < 0) - { - y = parent_view->getRect().getHeight() + y; - follows |= FOLLOWS_TOP; - } - else - { - follows |= FOLLOWS_BOTTOM; - } - } - else - { - // if bottom not specified, generate automatically - if (last_y == 0) - { - // treat first child as "bottom" - y = parent_view->getRect().getHeight() - (h + VPAD); - follows |= FOLLOWS_TOP; - } - else - { - // treat subsequent children as "bottom_delta" - y = last_y - (h + VPAD); - } - } - } - else - { - x = llmax(x, 0); - y = llmax(y, 0); - follows = FOLLOWS_LEFT | FOLLOWS_TOP; - } - rect.setOriginAndSize(x, y, w, h); - - return follows; -} - -void LLView::initFromXML(LLXMLNodePtr node, LLView* parent) +void LLView::initFromParams(const LLView::Params& params) { - // create rect first, as this will supply initial follows flags - LLRect view_rect; - U32 follows_flags = createRect(node, view_rect, parent, getRequiredRect()); - // call reshape in case there are any child elements that need to be layed out - reshape(view_rect.getWidth(), view_rect.getHeight()); - setRect(view_rect); - setFollows(follows_flags); - - parseFollowsFlags(node); + LLRect required_rect = getRequiredRect(); - if (node->hasAttribute("control_name")) - { - std::string control_name; - node->getAttributeString("control_name", control_name); - setControlName(control_name, NULL); - } + S32 width = llmax(getRect().getWidth(), required_rect.getWidth()); + S32 height = llmax(getRect().getHeight(), required_rect.getHeight()); - if (node->hasAttribute("tool_tip")) - { - std::string tool_tip_msg; - node->getAttributeString("tool_tip", tool_tip_msg); - setToolTip(tool_tip_msg); - } + reshape(width, height); - if (node->hasAttribute("enabled")) - { - BOOL enabled; - node->getAttributeBOOL("enabled", enabled); - setEnabled(enabled); - } - - if (node->hasAttribute("visible")) - { - BOOL visible; - node->getAttributeBOOL("visible", visible); - setVisible(visible); - } + // call virtual methods with most recent data + // use getters because these values might not come through parameter block + setEnabled(getEnabled()); + setVisible(getVisible()); - if (node->hasAttribute("hover_cursor")) + if (!params.name().empty()) { - std::string cursor_string; - node->getAttributeString("hover_cursor", cursor_string); - mHoverCursor = getCursorFromString(cursor_string); + setName(params.name()); } - - node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect); - node->getAttributeBOOL("mouse_opaque", mMouseOpaque); - node->getAttributeS32("default_tab_group", mDefaultTabGroup); - - reshape(view_rect.getWidth(), view_rect.getHeight()); + mLayout = params.layout(); } -void LLView::parseFollowsFlags(LLXMLNodePtr node) +void LLView::parseFollowsFlags(const LLView::Params& params) { - if (node->hasAttribute("follows")) + if (params.follows.string.isProvided()) { - setFollowsNone(); + setFollows(FOLLOWS_NONE); - std::string follows; - node->getAttributeString("follows", follows); + std::string follows = params.follows.string; typedef boost::tokenizer > tokenizer; boost::char_separator sep("|"); @@ -2685,45 +2378,13 @@ void LLView::parseFollowsFlags(LLXMLNodePtr node) ++token_iter; } } -} - -// static -LLFontGL* LLView::selectFont(LLXMLNodePtr node) -{ - std::string font_name, font_size, font_style; - U8 style = 0; - - if (node->hasAttribute("font")) - { - node->getAttributeString("font", font_name); - } - - if (node->hasAttribute("font_size")) - { - node->getAttributeString("font_size", font_size); - } - - if (node->hasAttribute("font_style")) - { - node->getAttributeString("font_style", font_style); - style = LLFontGL::getStyleFromString(font_style); - } - - if (node->hasAttribute("font-style")) + else if (params.follows.flags.isProvided()) { - node->getAttributeString("font-style", font_style); - style = LLFontGL::getStyleFromString(font_style); + setFollows(params.follows.flags); } - - if (font_name.empty()) - return NULL; - - LLFontDescriptor desc(font_name, font_size, style); - LLFontGL* gl_font = LLFontGL::getFont(desc); - - return gl_font; } + // static LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node) { @@ -2738,175 +2399,216 @@ LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node) return gl_hfont_align; } -// static -LLFontGL::VAlign LLView::selectFontVAlign(LLXMLNodePtr node) +//static +void LLView::setupParams(LLView::Params& p, LLView* parent) { - LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; + const S32 VPAD = 4; + const S32 MIN_WIDGET_HEIGHT = 10; + + p.serializable(true); + + // *NOTE: Do not inherit layout from parent until we re-export + // all nodes and make topleft the default. JC + //if (p.layout().empty() && parent) + // p.layout = parent->getLayout(); - if (node->hasAttribute("valign")) + if (parent) { - std::string vert_align_name; - node->getAttributeString("valign", vert_align_name); - gl_vfont_align = LLFontGL::vAlignFromName(vert_align_name); - } - return gl_vfont_align; -} + LLRect parent_rect = parent->getLocalRect(); + // overwrite uninitialized rect params, using context + LLRect last_rect = parent->getLocalRect(); -// static -LLFontGL::StyleFlags LLView::selectFontStyle(LLXMLNodePtr node) -{ - LLFontGL::StyleFlags gl_font_style = LLFontGL::NORMAL; + bool layout_topleft = (p.layout() == "topleft"); + if (layout_topleft) + { + //invert top to bottom + if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; + if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom; + } - if (node->hasAttribute("style")) - { - std::string style_flags_name; - node->getAttributeString("style", style_flags_name); + // convert negative or centered coordinates to parent relative values + // Note: some of this logic matches the logic in TypedParam::getValueFromBlock() - if (style_flags_name == "normal") + if (p.center_horiz) { - gl_font_style = LLFontGL::NORMAL; + if (p.rect.left.isProvided() && p.rect.right.isProvided()) + { + S32 width = p.rect.right - p.rect.left; + width = llmax(width, 0); + S32 offset = parent_rect.getWidth()/2 - width/2; + p.rect.left = p.rect.left + offset; + p.rect.right = p.rect.right + offset; + } + else + { + p.rect.left = p.rect.left + parent_rect.getWidth()/2 - p.rect.width/2; + } } - else if (style_flags_name == "bold") + else { - gl_font_style = LLFontGL::BOLD; + if (p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); + if (p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); } - else if (style_flags_name == "italic") + if (p.center_vert) { - gl_font_style = LLFontGL::ITALIC; + if (p.rect.bottom.isProvided() && p.rect.top.isProvided()) + { + S32 height = p.rect.top - p.rect.bottom; + height = llmax(height, 0); + S32 offset = parent_rect.getHeight()/2 - height/2; + p.rect.bottom = p.rect.bottom + offset; + p.rect.top = p.rect.top + offset; + } + else + { + p.rect.bottom = p.rect.bottom + parent_rect.getHeight()/2 - p.rect.height/2; + } } - else if (style_flags_name == "underline") + else { - gl_font_style = LLFontGL::UNDERLINE; + if (p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); + if (p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); } - //else leave left - } - return gl_font_style; -} - -bool LLView::setControlValue(const LLSD& value) -{ - std::string ctrlname = getControlName(); - if (!ctrlname.empty()) - { - LLUI::sConfigGroup->setValue(ctrlname, value); - return true; - } - return false; -} -//virtual -void LLView::setControlName(const std::string& control_name, LLView *context) -{ - if (context == NULL) - { - context = this; - } - if (!mControlName.empty()) - { - llwarns << "setControlName called twice on same control!" << llendl; - mControlConnection.disconnect(); // disconnect current signal - mControlName.clear(); - } - - // Register new listener - if (!control_name.empty()) - { - LLControlVariable *control = context->findControl(control_name); - if (control) + // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels + if (!p.rect.height.isProvided() && !p.rect.top.isProvided()) { - mControlName = control_name; - mControlConnection = control->getSignal()->connect(boost::bind(&controlListener, _1, getHandle(), std::string("value"))); - setValue(control->getValue()); + p.rect.height = MIN_WIDGET_HEIGHT; } - } -} -// static -bool LLView::controlListener(const LLSD& newvalue, LLHandle handle, std::string type) -{ - LLView* view = handle.get(); - if (view) - { - if (type == "value") + last_rect.translate(0, last_rect.getHeight()); + + LLView::child_list_t::const_iterator itor = parent->getChildList()->begin(); + for (;itor != parent->getChildList()->end(); ++itor) { - view->setValue(newvalue); - return true; + LLView *last_view = (*itor); + if (last_view->getSaveToXML()) + { + last_rect = last_view->getRect(); + break; + } } - else if (type == "enabled") + + if (layout_topleft) { - view->setEnabled(newvalue.asBoolean()); - return true; + S32 left_delta = 0; + p.bottom_delta.setIfNotProvided(0, false); + + // Invert the sense of bottom_delta for topleft layout + if (p.bottom_delta.isProvided()) + { + p.bottom_delta = -p.bottom_delta; + } + else if (p.top_delta.isProvided()) + { + p.bottom_delta = -(p.rect.height + p.top_delta); + } + else if (!p.left_delta.isProvided() && !p.right_delta.isProvided() && !p.top_delta.isProvided()) + { + // set default position is just below last rect + p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false); + } + + // *TODO: Add left_pad for padding off the last widget's right edge + // if (p.left_pad.isProvided()) + //{ + // left_delta = p.left_pad + last_rect.getWidth(); + //} + //else if ... + if (p.left_delta.isProvided()) + { + left_delta = p.left_delta; + } + else if (p.right_delta.isProvided()) + { + left_delta = -(p.right_delta + p.rect.width); + } + + last_rect.translate(left_delta, p.bottom_delta); } - else if (type == "visible") - { - view->setVisible(newvalue.asBoolean()); - return true; + else + { + // set default position is just below last rect + p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false); + p.left_delta.setIfNotProvided(0, false); + last_rect.translate(p.left_delta, p.bottom_delta); } - } - return false; -} -void LLView::addBoolControl(const std::string& name, bool initial_value) -{ - mFloaterControls[name] = new LLControlVariable(name, TYPE_BOOLEAN, initial_value, std::string("Internal floater control")); -} + // this handles case where *both* x and x_delta are provided + // ignore x in favor of default x + x_delta + if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); + if (p.left_delta.isProvided()) p.rect.left.set(0, false); -LLControlVariable *LLView::getControl(const std::string& name) -{ - control_map_t::iterator itor = mFloaterControls.find(name); - if (itor != mFloaterControls.end()) - { - return itor->second; + // selectively apply rectangle defaults, making sure that + // params are not flagged as having been "provided" + // as rect params are overconstrained and rely on provided flags + p.rect.left.setIfNotProvided(last_rect.mLeft, false); + p.rect.bottom.setIfNotProvided(last_rect.mBottom, false); + p.rect.top.setIfNotProvided(last_rect.mTop, false); + p.rect.right.setIfNotProvided(last_rect.mRight, false); + p.rect.width.setIfNotProvided(last_rect.getWidth(), false); + p.rect.height.setIfNotProvided(last_rect.getHeight(), false); } - return NULL; -} - -//virtual -void LLView::setValue(const LLSD& value) -{ } -//virtual -LLSD LLView::getValue() const +static S32 invert_vertical(S32 y, LLView* parent) { - return LLSD(); + if (y < 0) + { + // already based on top-left, just invert + return -y; + } + else if (parent) + { + // use parent to flip coordinate + S32 parent_height = parent->getRect().getHeight(); + return parent_height - y; + } + else + { + llwarns << "Attempting to convert layout to top-left with no parent" << llendl; + return y; + } } -LLView* LLView::createWidget(LLXMLNodePtr xml_node) const +//static +void LLView::setupParamsForExport(Params& p, LLView* parent) { - // forward requests to ui ctrl factory - return LLUICtrlFactory::getInstance()->createCtrlWidget(NULL, xml_node); -} - -// -// LLWidgetClassRegistry -// - -LLWidgetClassRegistry::LLWidgetClassRegistry() -{ -} + // Don't convert if already top-left based + if (p.layout() == "topleft") + { + return; + } -void LLWidgetClassRegistry::registerCtrl(const std::string& tag, LLWidgetClassRegistry::factory_func_t function) -{ - std::string lower_case_tag = tag; - LLStringUtil::toLower(lower_case_tag); - - mCreatorFunctions[lower_case_tag] = function; + if (p.rect.top.isProvided()) + { + p.rect.top = invert_vertical(p.rect.top, parent); + } + if (p.top_delta.isProvided()) + { + p.top_delta = -p.top_delta; + } + if (p.rect.bottom.isProvided()) + { + p.rect.bottom = invert_vertical(p.rect.bottom, parent); + } + if (p.bottom_delta.isProvided()) + { + p.bottom_delta = -p.bottom_delta; + } + p.layout = "topleft"; } -BOOL LLWidgetClassRegistry::isTagRegistered(const std::string &tag) +LLView::tree_iterator_t LLView::beginTree() { - return mCreatorFunctions.find(tag) != mCreatorFunctions.end(); + return tree_iterator_t(this, + boost::bind(boost::mem_fn(&LLView::beginChild), _1), + boost::bind(boost::mem_fn(&LLView::endChild), _1)); } -LLWidgetClassRegistry::factory_func_t LLWidgetClassRegistry::getCreatorFunc(const std::string& ctrl_type) +LLView::tree_iterator_t LLView::endTree() { - factory_map_t::const_iterator found_it = mCreatorFunctions.find(ctrl_type); - if (found_it == mCreatorFunctions.end()) - { - return NULL; - } - return found_it->second; + // an empty iterator is an "end" iterator + return tree_iterator_t(); } - diff --git a/indra/llui/llview.h b/indra/llui/llview.h index e0e0f6ba47..69ae7dd993 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -47,12 +47,15 @@ #include "llrect.h" #include "llui.h" #include "lluistring.h" -#include "lluixmltags.h" #include "llviewquery.h" #include "llxmlnode.h" #include "stdenums.h" #include "lluistring.h" #include "llcursortypes.h" +#include "lluictrlfactory.h" +#include "lltreeiterators.h" + +#include const U32 FOLLOWS_NONE = 0x00; const U32 FOLLOWS_LEFT = 0x01; @@ -75,9 +78,6 @@ virtual BOOL isPanel(); LLPanel virtual void setRect(const LLRect &rect); LLLineEditor -virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); -virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); -virtual void removeCtrl( LLUICtrl* ctrl); LLPanel virtual BOOL canFocusChildren() const { return TRUE; } LLFolderView @@ -103,7 +103,7 @@ 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 userSetShape(const LLRect& new_rect); +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); @@ -121,10 +121,6 @@ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropTy virtual void draw(); * - * -virtual LLXMLNodePtr getXML(bool save_children = true) const; - * -virtual void initFromXML(LLXMLNodePtr node, LLView* parent); * virtual void onFocusLost() {} LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox @@ -132,14 +128,8 @@ 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 void setControlName(const std::string& control, LLView *context); - LLSliderCtrl, LLCheckBoxCtrl -virtual std::string getControlName() const { return mControlName; } - LLSliderCtrl, LLCheckBoxCtrl virtual bool handleEvent(LLPointer event, const LLSD& userdata); LLMenuItem -virtual void setValue(const LLSD& value); - * protected: virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -148,67 +138,65 @@ virtual BOOL handleUnicodeCharHere(llwchar uni_char); * */ -class LLUICtrlFactory; - -// maps xml strings to widget classes -class LLWidgetClassRegistry : public LLSingleton +class LLView : public LLMouseHandler, public LLMortician { - friend class LLSingleton; public: - typedef LLView* (*factory_func_t)(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - typedef std::map factory_map_t; - - void registerCtrl(const std::string& xml_tag, factory_func_t function); - BOOL isTagRegistered(const std::string& xml_tag); - factory_func_t getCreatorFunc(const std::string& xml_tag); - - // get (first) xml tag for a given class - template std::string getTag() + struct Follows : public LLInitParam::Choice { - factory_map_t::iterator it; - for(it = mCreatorFunctions.begin(); it != mCreatorFunctions.end(); ++it) - { - if (it->second == T::fromXML) - { - return it->first; - } - } - - return ""; - } - -private: - LLWidgetClassRegistry(); - virtual ~LLWidgetClassRegistry() {}; - - typedef std::set ctrl_name_set_t; - ctrl_name_set_t mUICtrlNames; + Option string; + Option flags; - // map of xml tags to widget creator functions - factory_map_t mCreatorFunctions; -}; + Follows() + : string(""), + flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP) + {} + }; -template -class LLRegisterWidget -{ -public: - LLRegisterWidget(const std::string& tag) + struct Params : public LLInitParam::Block { - LLWidgetClassRegistry* registry = LLWidgetClassRegistry::getInstance(); - if (registry->isTagRegistered(tag)) - { - //error! - llerrs << "Widget named " << tag << " already registered!" << llendl; - } - else - { - registry->registerCtrl(tag, T::fromXML); - } - } -}; + Mandatory name; + + Optional enabled, + visible; + Optional mouse_opaque; + Optional use_bounding_rect; + Optional tab_group, + default_tab_group; + Optional tool_tip; + + Optional sound_flags; + Optional serializable; + Optional follows; + Optional hover_cursor; + + // font params + Optional font; + Optional font_halign; + Optional font_valign; + + Optional layout; + Optional rect; + Optional top_delta, + bottom_delta, + right_delta, + left_delta; + + Optional center_horiz, + center_vert; + + // these are nested attributes for LLLayoutPanel + //FIXME: get parent context involved in parsing traversal + Deprecated user_resize, + auto_resize, + needs_translate; + + Params(); + }; + void initFromParams(const LLView::Params&); -class LLView : public LLMouseHandler, public LLMortician -{ +protected: + LLView(const LLView::Params&); + friend class LLUICtrlFactory; public: #if LL_DEBUG @@ -253,10 +241,6 @@ public: typedef child_tab_order_t::reverse_iterator child_tab_order_reverse_iter_t; typedef child_tab_order_t::const_reverse_iterator child_tab_order_const_reverse_iter_t; - LLView(); - LLView(const std::string& name, BOOL mouse_opaque); - LLView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows=FOLLOWS_NONE); - virtual ~LLView(); // Hack to support LLFocusMgr (from LLMouseHandler) @@ -300,15 +284,21 @@ public: void sendChildToBack(LLView* child); void moveChildToFrontOfTabGroup(LLUICtrl* child); void moveChildToBackOfTabGroup(LLUICtrl* child); + + void addChildren(LLXMLNodePtr node, LLXMLNodePtr output_node = NULL); + + virtual bool addChild(LLView* view, S32 tab_group = 0); + + // implemented in terms of addChild() + bool addChildInBack(LLView* view, S32 tab_group = 0); - void addChild(LLView* view, S32 tab_group = 0); - void addChildAtEnd(LLView* view, S32 tab_group = 0); // remove the specified child from the view, and set it's parent to NULL. - void removeChild(LLView* view, BOOL deleteIt = FALSE); + virtual void removeChild(LLView* view); + + // helper function for lluictrlfactory.h create<> template + void setParent(LLView* parent) { if (parent) parent->addChild(this); } - virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); - virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); - virtual void removeCtrl( LLUICtrl* ctrl); + virtual BOOL postBuild() { return TRUE; } child_tab_order_t getCtrlOrder() const { return mCtrlOrder; } ctrl_list_t getCtrlList() const; @@ -316,6 +306,7 @@ public: void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; } S32 getDefaultTabGroup() const { return mDefaultTabGroup; } + S32 getLastTabGroup() { return mLastTabGroup; } BOOL isInVisibleChain() const; BOOL isInEnabledChain() const; @@ -347,7 +338,7 @@ public: virtual void onVisibilityChange ( BOOL curVisibilityIn ); void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); } - void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; } + void popVisible() { setVisible(mLastVisible); } LLHandle getHandle() { mHandle.bind(this); return mHandle; } @@ -361,11 +352,14 @@ public: const LLRect& getRect() const { return mRect; } const LLRect& getBoundingRect() const { return mBoundingRect; } LLRect getLocalBoundingRect() const; - LLRect getScreenRect() const; + LLRect calcScreenRect() const; + LLRect calcScreenBoundingRect() const; LLRect getLocalRect() const; virtual LLRect getSnapRect() const; LLRect getLocalSnapRect() const; + std::string getLayout() { return mLayout; } + // Override and return required size for this object. 0 for width/height means don't care. virtual LLRect getRequiredRect(); void updateBoundingRect(); @@ -373,12 +367,17 @@ public: LLView* getRootView(); LLView* getParent() const { return mParentView; } LLView* getFirstChild() const { return (mChildList.empty()) ? NULL : *(mChildList.begin()); } + LLView* findPrevSibling(LLView* child); + LLView* findNextSibling(LLView* child); S32 getChildCount() const { return (S32)mChildList.size(); } template void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); } BOOL hasAncestor(const LLView* parentp) const; BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const; BOOL childHasKeyboardFocus( const std::string& childname ) const; - + + typedef LLTreeDFSIter tree_iterator_t; + tree_iterator_t beginTree(); + tree_iterator_t endTree(); // // UTILITIES @@ -391,13 +390,11 @@ public: BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); void centerWithin(const LLRect& bounds); - virtual void userSetShape(const LLRect& new_rect); + void setShape(const LLRect& new_rect, bool by_user = false); 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); - virtual BOOL canSnapTo(const LLView* other_view); - - virtual void snappedTo(const LLView* snap_view); + virtual void setSnappedTo(const LLView* snap_view); virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); @@ -407,15 +404,11 @@ public: EAcceptance* accept, std::string& tooltip_msg); - std::string getShowNamesToolTip(); + virtual std::string getShowNamesToolTip(); virtual void draw(); - virtual LLXMLNodePtr getXML(bool save_children = true) const; - //FIXME: make LLView non-instantiable from XML - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); - virtual void initFromXML(LLXMLNodePtr node, LLView* parent); - void parseFollowsFlags(LLXMLNodePtr node); + void parseFollowsFlags(const LLView::Params& params); // Some widgets, like close box buttons, don't need to be saved BOOL getSaveToXML() const { return mSaveToXML; } @@ -440,25 +433,16 @@ public: void screenRectToLocal( const LLRect& screen, LLRect* local ) const; void localRectToScreen( const LLRect& local, LLRect* screen ) const; - // Listener dispatching functions (Dispatcher deletes pointers to listeners on deregistration or destruction) - LLSimpleListener* getListenerByName(const std::string& callback_name); - void registerEventListener(std::string name, LLSimpleListener* function); - void deregisterEventListener(std::string name); - std::string findEventListener(LLSimpleListener *listener) const; - void addListenerToControl(LLEventDispatcher *observer, const std::string& name, LLSD filter, LLSD userdata); - - void addBoolControl(const std::string& name, bool initial_value); - LLControlVariable *getControl(const std::string& name); LLControlVariable *findControl(const std::string& name); - bool setControlValue(const LLSD& value); - virtual void setControlName(const std::string& control, LLView *context); - virtual std::string getControlName() const { return mControlName; } + // Moved setValue(), getValue(), setControlValue(), setControlName(), + // controlListener() to LLUICtrl because an LLView is NOT assumed to + // contain a value. If that's what you want, use LLUICtrl instead. // virtual bool handleEvent(LLPointer event, const LLSD& userdata); - virtual void setValue(const LLSD& value); - virtual LLSD getValue() const; const child_list_t* getChildList() const { return &mChildList; } + const child_list_const_iter_t beginChild() { return mChildList.begin(); } + const child_list_const_iter_t endChild() { return mChildList.end(); } // LLMouseHandler functions // Default behavior is to pass events to children @@ -479,26 +463,20 @@ public: /*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; - template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const + // view-specific handlers + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + + template T* findChild(const std::string& name, BOOL recurse = TRUE) const { LLView* child = getChildView(name, recurse, FALSE); T* result = dynamic_cast(child); - if (!result) - { - // 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; - } - if (create_if_missing) - { - // create dummy widget instance here - result = createDummyWidget(name); - } - } return result; } + template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + template T& getChildRef(const std::string& name, BOOL recurse = TRUE) const { return *getChild(name, recurse, TRUE); @@ -506,39 +484,6 @@ public: virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; - template T* createDummyWidget(const std::string& name) const - { - T* widget = getDummyWidget(name); - if (!widget) - { - // get xml tag name corresponding to requested widget type (e.g. "button") - std::string xml_tag = LLWidgetClassRegistry::getInstance()->getTag(); - if (xml_tag.empty()) - { - llwarns << "No xml tag registered for this class " << llendl; - return NULL; - } - // create dummy xml node (