summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/integration_tests/llui_libtest/llwidgetreg.cpp2
-rw-r--r--indra/llcommon/llpreprocessor.h2
-rw-r--r--indra/llcommon/llsafehandle.h1
-rw-r--r--indra/llcommon/llsecondlifeurls.cpp2
-rw-r--r--indra/llcommon/llstringtable.cpp17
-rw-r--r--indra/llcommon/llstringtable.h18
-rw-r--r--indra/llcommon/llversionviewer.h2
-rw-r--r--indra/llrender/llfontgl.cpp3
-rw-r--r--indra/llui/CMakeLists.txt4
-rw-r--r--indra/llui/llbutton.cpp6
-rw-r--r--indra/llui/llbutton.h3
-rw-r--r--indra/llui/llcheckboxctrl.cpp2
-rw-r--r--indra/llui/llcombobox.cpp6
-rw-r--r--indra/llui/llcombobox.h2
-rw-r--r--indra/llui/llconsole.cpp4
-rw-r--r--indra/llui/llconsole.h7
-rw-r--r--indra/llui/lldraghandle.cpp9
-rw-r--r--indra/llui/lldraghandle.h6
-rw-r--r--indra/llui/llfloater.cpp2
-rw-r--r--indra/llui/llfloater.h2
-rw-r--r--indra/llui/llfocusmgr.cpp2
-rw-r--r--indra/llui/lllayoutstack.cpp2
-rw-r--r--indra/llui/lllayoutstack.h4
-rw-r--r--indra/llui/lllineeditor.cpp16
-rw-r--r--indra/llui/lllineeditor.h6
-rw-r--r--indra/llui/llmenubutton.cpp135
-rw-r--r--indra/llui/llmenubutton.h68
-rw-r--r--indra/llui/llmenugl.cpp96
-rw-r--r--indra/llui/llmenugl.h12
-rw-r--r--indra/llui/llmultisliderctrl.cpp2
-rw-r--r--indra/llui/llpanel.cpp9
-rw-r--r--indra/llui/llpanel.h6
-rw-r--r--indra/llui/llradiogroup.cpp2
-rw-r--r--indra/llui/llradiogroup.h13
-rw-r--r--indra/llui/llscrollbar.cpp13
-rw-r--r--indra/llui/llscrollbar.h3
-rw-r--r--indra/llui/llscrollcontainer.cpp50
-rw-r--r--indra/llui/llscrollcontainer.h4
-rw-r--r--indra/llui/llscrolllistcell.cpp7
-rw-r--r--indra/llui/llscrolllistcell.h13
-rw-r--r--indra/llui/llscrolllistctrl.cpp64
-rw-r--r--indra/llui/llscrolllistctrl.h6
-rw-r--r--indra/llui/llscrolllistitem.cpp1
-rw-r--r--indra/llui/llscrolllistitem.h2
-rw-r--r--indra/llui/llsliderctrl.cpp2
-rw-r--r--indra/llui/llspinctrl.cpp2
-rw-r--r--indra/llui/llstatview.cpp2
-rw-r--r--indra/llui/llstyle.cpp2
-rw-r--r--indra/llui/llstyle.h16
-rw-r--r--indra/llui/lltabcontainer.cpp8
-rw-r--r--indra/llui/lltabcontainer.h2
-rw-r--r--indra/llui/lltextbase.cpp2273
-rw-r--r--indra/llui/lltextbase.h382
-rw-r--r--indra/llui/lltextbox.cpp636
-rw-r--r--indra/llui/lltextbox.h95
-rw-r--r--indra/llui/lltexteditor.cpp1981
-rw-r--r--indra/llui/lltexteditor.h293
-rw-r--r--indra/llui/lltextparser.cpp4
-rw-r--r--indra/llui/lltextparser.h12
-rw-r--r--indra/llui/lltoggleablemenu.cpp82
-rw-r--r--indra/llui/lltoggleablemenu.h65
-rw-r--r--indra/llui/lltooltip.cpp334
-rw-r--r--indra/llui/lltooltip.h90
-rw-r--r--indra/llui/llui.cpp49
-rw-r--r--indra/llui/llui.h5
-rw-r--r--indra/llui/lluictrl.cpp30
-rw-r--r--indra/llui/lluictrl.h34
-rw-r--r--indra/llui/lluictrlfactory.cpp14
-rw-r--r--indra/llui/llurlentry.cpp10
-rw-r--r--indra/llui/llurlentry.h20
-rw-r--r--indra/llui/llurlmatch.cpp5
-rw-r--r--indra/llui/llurlmatch.h20
-rw-r--r--indra/llui/llurlregistry.cpp8
-rw-r--r--indra/llui/llview.cpp377
-rw-r--r--indra/llui/llview.h25
-rw-r--r--indra/llui/tests/llurlentry_test.cpp13
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp34
-rw-r--r--indra/llwindow/llmousehandler.h7
-rw-r--r--indra/llwindow/llpreeditor.h2
-rw-r--r--indra/llwindow/llwindowmacosx.cpp12
-rw-r--r--indra/llwindow/llwindowwin32.cpp6
-rw-r--r--indra/llxml/llxmlnode.h2
-rw-r--r--indra/llxml/llxmlparser.h2
-rw-r--r--indra/llxuixml/llinitparam.h23
-rw-r--r--indra/llxuixml/lltrans.cpp65
-rw-r--r--indra/llxuixml/lltrans.h6
-rw-r--r--indra/newview/CMakeLists.txt9
-rw-r--r--indra/newview/app_settings/settings.xml83
-rw-r--r--indra/newview/installers/windows/installer_template.nsi2
-rw-r--r--indra/newview/llappviewer.cpp7
-rw-r--r--indra/newview/llavataractions.cpp29
-rw-r--r--indra/newview/llavataractions.h6
-rw-r--r--indra/newview/llavatarlistitem.cpp2
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp103
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h9
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp4
-rw-r--r--indra/newview/llchatmsgbox.cpp110
-rw-r--r--indra/newview/llchatmsgbox.h8
-rw-r--r--indra/newview/llchiclet.cpp2
-rw-r--r--indra/newview/llcolorswatch.cpp2
-rw-r--r--indra/newview/lldateutil.cpp140
-rw-r--r--indra/newview/lldateutil.h49
-rw-r--r--indra/newview/lldebugmessagebox.cpp2
-rw-r--r--indra/newview/llexpandabletextbox.cpp19
-rw-r--r--indra/newview/llexpandabletextbox.h22
-rw-r--r--indra/newview/llfasttimerview.cpp4
-rw-r--r--indra/newview/llfasttimerview.h2
-rw-r--r--indra/newview/llfavoritesbar.cpp4
-rw-r--r--indra/newview/llfloaterabout.cpp9
-rw-r--r--indra/newview/llfloaterbuy.cpp7
-rw-r--r--indra/newview/llfloaterbuy.h1
-rw-r--r--indra/newview/llfloaterbuyland.cpp51
-rw-r--r--indra/newview/llfloaterchat.cpp15
-rw-r--r--indra/newview/llfloaterfriends.cpp4
-rw-r--r--indra/newview/llfloatergesture.cpp16
-rw-r--r--indra/newview/llfloatergroups.cpp4
-rw-r--r--indra/newview/llfloaterland.cpp27
-rw-r--r--indra/newview/llfloaterregioninfo.cpp35
-rw-r--r--indra/newview/llfloaterregioninfo.h12
-rw-r--r--indra/newview/llfloaterreporter.cpp32
-rw-r--r--indra/newview/llfloaterreporter.h2
-rw-r--r--indra/newview/llfloaterscriptdebug.cpp3
-rw-r--r--indra/newview/llfloatersellland.cpp5
-rw-r--r--indra/newview/llfloatertestinspectors.cpp9
-rw-r--r--indra/newview/llfloatertestinspectors.h1
-rw-r--r--indra/newview/llfloatertools.cpp2
-rw-r--r--indra/newview/llfloateruipreview.cpp29
-rw-r--r--indra/newview/llfolderviewitem.cpp14
-rw-r--r--indra/newview/llfolderviewitem.h2
-rw-r--r--indra/newview/llgrouplist.cpp13
-rw-r--r--indra/newview/llimfloater.cpp11
-rw-r--r--indra/newview/llimpanel.cpp14
-rw-r--r--indra/newview/llinspectavatar.cpp335
-rw-r--r--indra/newview/llinspectavatar.h61
-rw-r--r--indra/newview/llinspectobject.cpp563
-rw-r--r--indra/newview/llinspectobject.h40
-rw-r--r--indra/newview/lljoystickbutton.cpp24
-rw-r--r--indra/newview/lllistview.cpp2
-rw-r--r--indra/newview/lllocationinputctrl.cpp4
-rw-r--r--indra/newview/lllocationinputctrl.h2
-rw-r--r--indra/newview/llmenucommands.cpp6
-rw-r--r--indra/newview/llmenucommands.h1
-rw-r--r--indra/newview/llnamelistctrl.cpp60
-rw-r--r--indra/newview/llnamelistctrl.h7
-rw-r--r--indra/newview/llnearbychat.cpp35
-rw-r--r--indra/newview/llnetmap.cpp6
-rw-r--r--indra/newview/llnetmap.h2
-rw-r--r--indra/newview/llpanelavatar.cpp3
-rw-r--r--indra/newview/llpanelavatartag.cpp24
-rw-r--r--indra/newview/llpanelblockedlist.h1
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp3
-rw-r--r--indra/newview/llpanelgrouproles.cpp1
-rw-r--r--indra/newview/llpanellogin.cpp4
-rw-r--r--indra/newview/llpanelpeople.cpp2
-rw-r--r--indra/newview/llpanelpeople.h2
-rw-r--r--indra/newview/llpanelpermissions.cpp32
-rw-r--r--indra/newview/llpanelpermissions.h15
-rw-r--r--indra/newview/llpanelpick.cpp20
-rw-r--r--indra/newview/llpanelprofile.cpp13
-rw-r--r--indra/newview/llpreviewgesture.cpp4
-rw-r--r--indra/newview/llpreviewnotecard.cpp8
-rw-r--r--indra/newview/llprogressview.cpp4
-rw-r--r--indra/newview/llselectmgr.cpp57
-rw-r--r--indra/newview/llselectmgr.h56
-rw-r--r--indra/newview/llslurl.cpp8
-rw-r--r--indra/newview/llslurl.h3
-rw-r--r--indra/newview/llstartup.cpp10
-rw-r--r--indra/newview/llstylemap.cpp7
-rw-r--r--indra/newview/lltexturectrl.cpp2
-rw-r--r--indra/newview/lltoastalertpanel.cpp3
-rw-r--r--indra/newview/lltoastnotifypanel.cpp9
-rw-r--r--indra/newview/lltoastpanel.cpp2
-rw-r--r--indra/newview/lltool.cpp2
-rw-r--r--indra/newview/lltool.h4
-rw-r--r--indra/newview/lltoolbar.cpp3
-rw-r--r--indra/newview/lltooldraganddrop.cpp4
-rw-r--r--indra/newview/lltooldraganddrop.h2
-rw-r--r--indra/newview/lltoolpie.cpp272
-rw-r--r--indra/newview/lltoolpie.h5
-rw-r--r--indra/newview/lltoolpipette.cpp4
-rw-r--r--indra/newview/lltoolpipette.h2
-rw-r--r--indra/newview/lluploaddialog.cpp2
-rw-r--r--indra/newview/llviewchildren.cpp11
-rw-r--r--indra/newview/llviewchildren.h2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp5
-rw-r--r--indra/newview/llviewerjoystick.cpp2
-rw-r--r--indra/newview/llviewerjoystick.h3
-rw-r--r--indra/newview/llviewermedia.h5
-rw-r--r--indra/newview/llviewermenu.cpp533
-rw-r--r--indra/newview/llviewermenu.h34
-rw-r--r--indra/newview/llviewermessage.cpp43
-rw-r--r--indra/newview/llviewerparcelmgr.h3
-rw-r--r--indra/newview/llviewertexteditor.cpp95
-rw-r--r--indra/newview/llviewertexteditor.h6
-rw-r--r--indra/newview/llviewerwindow.cpp33
-rw-r--r--indra/newview/llworldmapview.cpp5
-rw-r--r--indra/newview/llworldmapview.h2
-rw-r--r--indra/newview/skins/default/colors.xml4
-rw-r--r--indra/newview/skins/default/textures/icons/Info_Small.pngbin0 -> 371 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_land.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_inspect.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_map.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_debug_panel.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_telehub.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_inspectors.xml31
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_widgets.xml57
-rw-r--r--indra/newview/skins/default/xui/en/floater_ui_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml216
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml162
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml114
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml129
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_audio_device.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_profile.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_land_money.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_progress.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_ed.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_world_map.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml44
-rw-r--r--indra/newview/skins/default/xui/en/widgets/line_editor.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text.xml14
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text_editor.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/textbase.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_telehub.xml2
-rw-r--r--indra/newview/tests/lldateutil_test.cpp159
-rw-r--r--indra/test/test.cpp17
241 files changed, 6881 insertions, 5329 deletions
diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
index 5a97f2aefd..316fd810c0 100644
--- a/indra/integration_tests/llui_libtest/llwidgetreg.cpp
+++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
@@ -37,6 +37,7 @@
#include "llcombobox.h"
#include "llcontainerview.h"
#include "lliconctrl.h"
+#include "llmenubutton.h"
#include "llmenugl.h"
#include "llmultislider.h"
#include "llmultisliderctrl.h"
@@ -64,6 +65,7 @@ void LLWidgetReg::initClass(bool register_widgets)
if (register_widgets)
{
LLDefaultChildRegistry::Register<LLButton> button("button");
+ LLDefaultChildRegistry::Register<LLMenuButton> menu_button("menu_button");
LLDefaultChildRegistry::Register<LLCheckBoxCtrl> check_box("check_box");
LLDefaultChildRegistry::Register<LLComboBox> combo_box("combo_box");
LLDefaultChildRegistry::Register<LLFilterEditor> filter_editor("filter_editor");
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 4401be1679..bb598a2be1 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -117,7 +117,9 @@ using snprintf_hack::snprintf;
#if defined(LL_WINDOWS)
#define BOOST_REGEX_NO_LIB 1
#define CURL_STATICLIB 1
+#ifndef XML_STATIC
#define XML_STATIC
+#endif
#endif // LL_WINDOWS
diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h
index 1f7c682fd1..5862f1a341 100644
--- a/indra/llcommon/llsafehandle.h
+++ b/indra/llcommon/llsafehandle.h
@@ -77,6 +77,7 @@ public:
Type* operator->() { return nonNull(mPointer); }
Type* get() const { return mPointer; }
+ void clear() { assign(NULL); }
// 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); }
diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp
index 6323d9d36b..9e67872ffd 100644
--- a/indra/llcommon/llsecondlifeurls.cpp
+++ b/indra/llcommon/llsecondlifeurls.cpp
@@ -34,7 +34,7 @@
#include "llsecondlifeurls.h"
/*
const std::string CREATE_ACCOUNT_URL (
- "http://secondlife.com/registration/");
+ "http://join.secondlife.com/");
const std::string MANAGE_ACCOUNT (
"http://secondlife.com/account/"); // *TODO: NOT USED
diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp
index 27f9036b8b..2f3a994d8f 100644
--- a/indra/llcommon/llstringtable.cpp
+++ b/indra/llcommon/llstringtable.cpp
@@ -38,6 +38,23 @@
LLStringTable gStringTable(32768);
+LLStringTableEntry::LLStringTableEntry(const char *str)
+: mString(NULL), mCount(1)
+{
+ // Copy string
+ U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
+ length = llmin(length, MAX_STRINGS_LENGTH);
+ mString = new char[length];
+ strncpy(mString, str, length); /*Flawfinder: ignore*/
+ mString[length - 1] = 0;
+}
+
+LLStringTableEntry::~LLStringTableEntry()
+{
+ delete [] mString;
+ mCount = 0;
+}
+
LLStringTable::LLStringTable(int tablesize)
: mUniqueEntries(0)
{
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 4492063275..888361b0b9 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -59,21 +59,9 @@ const U32 MAX_STRINGS_LENGTH = 256;
class LLStringTableEntry
{
public:
- LLStringTableEntry(const char *str)
- : mString(NULL), mCount(1)
- {
- // Copy string
- U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
- length = llmin(length, MAX_STRINGS_LENGTH);
- mString = new char[length];
- strncpy(mString, str, length); /*Flawfinder: ignore*/
- mString[length - 1] = 0;
- }
- ~LLStringTableEntry()
- {
- delete [] mString;
- mCount = 0;
- }
+ LLStringTableEntry(const char *str);
+ ~LLStringTableEntry();
+
void incCount() { mCount++; }
BOOL decCount() { return --mCount; }
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 45810a101d..2c3e9c7333 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -38,6 +38,6 @@ const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 0;
const S32 LL_VERSION_BUILD = 0;
-const char * const LL_CHANNEL = "Second Life 2009";
+const char * const LL_CHANNEL = "Second Life Developer";
#endif
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index d76b23248d..8f943182b8 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -484,7 +484,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
S32 start_of_last_word = 0;
BOOL in_word = FALSE;
- F32 scaled_max_pixels = (F32)llceil(max_pixels * sScaleX);
+ // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
+ F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
S32 i;
for (i=0; (i < max_chars); i++)
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 0a284f0088..d9169f57f9 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -51,6 +51,7 @@ set(llui_SOURCE_FILES
lllayoutstack.cpp
lllineeditor.cpp
lllocalcliprect.cpp
+ llmenubutton.cpp
llmenugl.cpp
llmodaldialog.cpp
llmultifloater.cpp
@@ -87,6 +88,7 @@ set(llui_SOURCE_FILES
lltextparser.cpp
lltransientfloatermgr.cpp
lltransutil.cpp
+ lltoggleablemenu.cpp
lltooltip.cpp
llui.cpp
lluicolortable.cpp
@@ -137,6 +139,7 @@ set(llui_HEADER_FILES
lllazyvalue.h
lllineeditor.h
lllocalcliprect.h
+ llmenubutton.h
llmenugl.h
llmodaldialog.h
llmultifloater.h
@@ -171,6 +174,7 @@ set(llui_HEADER_FILES
lltextbox.h
lltexteditor.h
lltextparser.h
+ lltoggleablemenu.h
lltooltip.h
lltransientfloatermgr.h
lltransutil.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index b9613b502c..219c2ee254 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -145,7 +145,8 @@ LLButton::LLButton(const LLButton::Params& p)
mRightHPad(p.pad_right),
mHoverGlowStrength(p.hover_glow_amount),
mCommitOnReturn(p.commit_on_return),
- mFadeWhenDisabled(FALSE)
+ mFadeWhenDisabled(FALSE),
+ mForcePressedState(FALSE)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@@ -536,7 +537,8 @@ void LLButton::draw()
bool enabled = isInEnabledChain();
bool pressed = pressed_by_keyboard
- || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y));
+ || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
+ || mForcePressedState;
bool selected = getToggleState();
bool use_glow_effect = FALSE;
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 04716d605b..73ba457d34 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -233,6 +233,8 @@ public:
static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname);
static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
static void showHelp(LLUICtrl* ctrl, const LLSD& sdname);
+
+ void setForcePressedState(BOOL b) { mForcePressedState = b; }
protected:
const LLPointer<LLUIImage>& getImageUnselected() const { return mImageUnselected; }
@@ -310,6 +312,7 @@ private:
BOOL mNeedsHighlight;
BOOL mCommitOnReturn;
BOOL mFadeWhenDisabled;
+ BOOL mForcePressedState;
LLFrameTimer mFlashingTimer;
};
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index 455b17ffc7..7f0f9751db 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -97,7 +97,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
LLTextBox::Params tbparams = p.label_text;
tbparams.rect(label_rect);
- tbparams.text(local_label);
+ tbparams.initial_value(local_label);
if (p.font.isProvided())
{
tbparams.font(p.font);
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 0170ac0c6a..36e309d639 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -714,11 +714,11 @@ void LLComboBox::onItemSelected(const LLSD& data)
}
}
-BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLComboBox::handleToolTip(S32 x, S32 y, MASK mask)
{
std::string tool_tip;
- if(LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen))
+ if(LLUICtrl::handleToolTip(x, y, mask))
{
return TRUE;
}
@@ -731,7 +731,7 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_re
if( !tool_tip.empty() )
{
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tool_tip)
.sticky_rect(calcScreenRect()));
}
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 68cbfeeeeb..6285ca5170 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -113,7 +113,7 @@ public:
// LLView interface
virtual void onFocusLost();
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 1e8b8a5537..285ce82d2d 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -61,7 +61,7 @@ const F32 FADE_DURATION = 2.f;
const S32 MIN_CONSOLE_WIDTH = 200;
LLConsole::LLConsole(const LLConsole::Params& p)
-: LLView(p),
+: LLUICtrl(p),
LLFixedBuffer(p.max_lines),
mLinePersistTime(p.persist_time), // seconds
mFont(p.font)
@@ -94,7 +94,7 @@ void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent)
mConsoleWidth = new_width;
mConsoleHeight= new_height;
- LLView::reshape(new_width, new_height, called_from_parent);
+ LLUICtrl::reshape(new_width, new_height, called_from_parent);
for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
{
diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h
index 56e1614948..5800a82922 100644
--- a/indra/llui/llconsole.h
+++ b/indra/llui/llconsole.h
@@ -34,14 +34,13 @@
#define LL_LLCONSOLE_H
#include "llfixedbuffer.h"
-#include "llview.h"
+#include "lluictrl.h"
#include "v4color.h"
#include <deque>
-class LLFontGL;
class LLSD;
-class LLConsole : public LLFixedBuffer, public LLView
+class LLConsole : public LLFixedBuffer, public LLUICtrl
{
public:
typedef enum e_font_size
@@ -51,7 +50,7 @@ public:
BIG = 1
} EFontSize;
- struct Params : public LLInitParam::Block<Params, LLView::Params>
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<U32> max_lines;
Optional<F32> persist_time;
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 6e8e37ded3..8eccd709ce 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -108,7 +108,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
LLTextBox::Params params;
params.name("Drag Handle Title");
params.rect(getRect());
- params.text(trimmed_title);
+ params.initial_value(trimmed_title);
params.font(font);
params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
@@ -120,7 +120,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
}
-const std::string& LLDragHandleTop::getTitle() const
+std::string LLDragHandleTop::getTitle() const
{
return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText();
}
@@ -138,7 +138,7 @@ void LLDragHandleLeft::setTitle(const std::string& )
}
-const std::string& LLDragHandleLeft::getTitle() const
+std::string LLDragHandleLeft::getTitle() const
{
return LLStringUtil::null;
}
@@ -256,7 +256,8 @@ void LLDragHandleTop::reshapeTitleBox()
getRect().getWidth() - LEFT_PAD - RIGHT_PAD,
title_height);
- mTitleBox->setRect( title_rect );
+ // calls reshape on mTitleBox
+ mTitleBox->setShape( title_rect );
}
void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent)
diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h
index 88ec1d21f8..dc5410787b 100644
--- a/indra/llui/lldraghandle.h
+++ b/indra/llui/lldraghandle.h
@@ -74,7 +74,7 @@ public:
void setTitleVisible(BOOL visible);
virtual void setTitle( const std::string& title ) = 0;
- virtual const std::string& getTitle() const = 0;
+ virtual std::string getTitle() const = 0;
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -112,7 +112,7 @@ protected:
friend class LLUICtrlFactory;
public:
virtual void setTitle( const std::string& title );
- virtual const std::string& getTitle() const;
+ virtual std::string getTitle() const;
virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -130,7 +130,7 @@ protected:
friend class LLUICtrlFactory;
public:
virtual void setTitle( const std::string& title );
- virtual const std::string& getTitle() const;
+ virtual std::string getTitle() const;
virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index ff0288a32f..564e4d748f 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -785,7 +785,7 @@ void LLFloater::applyTitle()
}
}
-const std::string& LLFloater::getCurrentTitle() const
+std::string LLFloater::getCurrentTitle() const
{
return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null;
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 2a31ba4e8f..1dc5177f81 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -171,7 +171,7 @@ public:
LLMultiFloater* getHost();
void applyTitle();
- const std::string& getCurrentTitle() const;
+ std::string getCurrentTitle() const;
void setTitle( const std::string& title);
std::string getTitle() const;
void setShortTitle( const std::string& short_title );
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 279cbaa923..00a80478cf 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -274,7 +274,7 @@ BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const
// Returns TRUE is parent or any descedent of parent is the mouse captor.
BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const
{
- if( mMouseCaptor && mMouseCaptor->isView() )
+ if( mMouseCaptor && dynamic_cast<LLView*>(mMouseCaptor) != NULL )
{
LLView* captor_view = (LLView*)mMouseCaptor;
while( captor_view )
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 2d582c0568..5eade72b61 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -35,7 +35,9 @@
#include "linden_common.h"
#include "lllayoutstack.h"
+
#include "lllocalcliprect.h"
+#include "llpanel.h"
#include "llresizebar.h"
#include "llcriticaldamp.h"
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 9459b9990c..49cbe7270f 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -34,7 +34,9 @@
#ifndef LL_LLLAYOUTSTACK_H
#define LL_LLLAYOUTSTACK_H
-#include "llpanel.h"
+#include "llview.h"
+
+class LLPanel;
class LLLayoutStack : public LLView
{
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index ede67ad17d..693ea5bb45 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -107,9 +107,6 @@ LLLineEditor::Params::Params()
highlight_color("highlight_color"),
preedit_bg_color("preedit_bg_color"),
border(""),
- is_unicode("is_unicode"),
- drop_shadow_visible("drop_shadow_visible"),
- border_drop_shadow_visible("border_drop_shadow_visible"),
bg_visible("bg_visible"),
text_pad_left("text_pad_left"),
text_pad_right("text_pad_right"),
@@ -544,18 +541,13 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
return TRUE;
}
- if (mSelectAllonFocusReceived
- && gFocusMgr.getKeyboardFocus() != this)
- {
- setFocus( TRUE );
- }
- else
+
+ if (!mSelectAllonFocusReceived
+ || gFocusMgr.getKeyboardFocus() == this)
{
mLastSelectionStart = -1;
mLastSelectionStart = -1;
- setFocus( TRUE );
-
if (mask & MASK_SHIFT)
{
// Handle selection extension
@@ -621,6 +613,8 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
gFocusMgr.setMouseCapture( this );
}
+ setFocus(TRUE);
+
// delay cursor flashing
mKeystrokeTimer.reset();
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 339aad30fb..48d68b9935 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -105,10 +105,7 @@ public:
Optional<S32> text_pad_left,
text_pad_right;
- Ignored is_unicode,
- drop_shadow_visible,
- border_drop_shadow_visible,
- bg_visible;
+ Ignored bg_visible;
Params();
};
@@ -280,6 +277,7 @@ private:
virtual void getPreeditRange(S32 *position, S32 *length) const;
virtual BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
+ virtual LLWString getPreeditString() const { return getWText(); }
protected:
LLUIString mText; // The string being edited.
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
new file mode 100644
index 0000000000..2bb6749c83
--- /dev/null
+++ b/indra/llui/llmenubutton.cpp
@@ -0,0 +1,135 @@
+/**
+ * @file llbutton.cpp
+ * @brief LLButton 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"
+
+#include "llmenubutton.h"
+
+// Linden library includes
+#include "llmenugl.h"
+#include "llstring.h"
+#include "v4color.h"
+
+static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button");
+
+
+LLMenuButton::Params::Params()
+: menu_filename("menu_filename")
+{
+}
+
+
+LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
+: LLButton(p),
+ mMenu(NULL),
+ mMenuVisibleLastFrame(false)
+{
+ std::string menu_filename = p.menu_filename;
+
+ if (!menu_filename.empty())
+ {
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!mMenu)
+ {
+ llwarns << "Error loading menu_button menu" << llendl;
+ }
+ }
+}
+
+void LLMenuButton::toggleMenu()
+{
+ if(!mMenu)
+ return;
+
+ if (mMenu->getVisible() || mMenuVisibleLastFrame)
+ {
+ mMenu->setVisible(FALSE);
+ }
+ else
+ {
+ LLRect rect = getRect();
+ //mMenu->needsArrange(); //so it recalculates the visible elements
+ LLMenuGL::showPopup(getParent(), mMenu, rect.mLeft, rect.mBottom);
+ }
+}
+
+
+BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
+{
+ if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
+ {
+ toggleMenu();
+ return TRUE;
+ }
+
+ if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
+ {
+ mMenu->setVisible(FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (hasTabStop() && !getIsChrome())
+ {
+ setFocus(TRUE);
+ }
+
+ toggleMenu();
+
+ if (getSoundFlags() & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+
+ return TRUE;
+}
+
+void LLMenuButton::draw()
+{
+ //we save this off so next frame when we try to close it by
+ //button click, and it hides menus before we get to it, we know
+ mMenuVisibleLastFrame = mMenu && mMenu->getVisible();
+
+ if (mMenuVisibleLastFrame)
+ {
+ setForcePressedState(TRUE);
+ }
+
+ LLButton::draw();
+
+ setForcePressedState(FALSE);
+}
+
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
new file mode 100644
index 0000000000..94b0e4355d
--- /dev/null
+++ b/indra/llui/llmenubutton.h
@@ -0,0 +1,68 @@
+/**
+ * @file llbutton.h
+ * @brief Header for buttons
+ *
+ * $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_LLMENUBUTTON_H
+#define LL_LLMENUBUTTON_H
+
+#include "llbutton.h"
+
+class LLMenuGL;
+
+class LLMenuButton
+: public LLButton
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ // filename for it's toggleable menu
+ Optional<std::string> menu_filename;
+
+ Params();
+ };
+
+ void toggleMenu();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
+
+protected:
+ friend class LLUICtrlFactory;
+ LLMenuButton(const Params&);
+
+private:
+ LLMenuGL* mMenu;
+ bool mMenuVisibleLastFrame;
+};
+
+
+#endif // LL_LLMENUBUTTON_H
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index f2d147ac39..14bee0465c 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -781,6 +781,10 @@ LLMenuItemCallGL::LLMenuItemCallGL(const LLMenuItemCallGL::Params& p)
void LLMenuItemCallGL::initFromParams(const Params& p)
{
+ if (p.on_visible.isProvided())
+ {
+ initVisibleCallback(p.on_visible, mVisibleSignal);
+ }
if (p.on_enable.isProvided())
{
initEnableCallback(p.on_enable, mEnableSignal);
@@ -823,9 +827,19 @@ void LLMenuItemCallGL::updateEnabled( void )
}
}
+void LLMenuItemCallGL::updateVisible( void )
+{
+ if (mVisibleSignal.num_slots() > 0)
+ {
+ bool visible = mVisibleSignal(this, LLSD());
+ setVisible(visible);
+ }
+}
+
void LLMenuItemCallGL::buildDrawLabel( void )
{
updateEnabled();
+ updateVisible();
LLMenuItemGL::buildDrawLabel();
}
@@ -1224,23 +1238,7 @@ void LLMenuItemBranchGL::openMenu()
rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
}
branch->setRect( rect );
- S32 x = 0;
- S32 y = 0;
- branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() );
- S32 delta_x = 0;
- S32 delta_y = 0;
- if( y < menu_region_rect.mBottom )
- {
- delta_y = menu_region_rect.mBottom - y;
- }
-
- S32 menu_region_width = menu_region_rect.getWidth();
- if( x - menu_region_rect.mLeft > menu_region_width - rect.getWidth() )
- {
- // move sub-menu over to left side
- delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth())));
- }
- branch->translate( delta_x, delta_y );
+ branch->translateIntoRectWithExclusion( menu_region_rect, getMenu()->getRect(), FALSE );
branch->setVisible( TRUE );
branch->getParent()->sendChildToFront(branch);
@@ -1935,6 +1933,9 @@ void LLMenuGL::arrange( void )
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
+ // do first so LLMenuGLItemCall can call on_visible to determine if visible
+ (*item_iter)->buildDrawLabel();
+
if ((*item_iter)->getVisible())
{
if (!getTornOff()
@@ -1976,6 +1977,9 @@ void LLMenuGL::arrange( void )
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
+ // do first so LLMenuGLItemCall can call on_visible to determine if visible
+ (*item_iter)->buildDrawLabel();
+
if ((*item_iter)->getVisible())
{
if (!getTornOff()
@@ -2162,7 +2166,7 @@ void LLMenuGL::arrange( void )
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
+ {
if ((*item_iter)->getVisible())
{
if (mScrollable)
@@ -2193,7 +2197,6 @@ void LLMenuGL::arrange( void )
}
}
(*item_iter)->setRect( rect );
- (*item_iter)->buildDrawLabel();
}
}
}
@@ -2936,11 +2939,27 @@ void hide_top_view( LLView* view )
// static
void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
{
+ const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
+ const S32 CURSOR_WIDTH = 12;
+
// Save click point for detecting cursor moves before mouse-up.
// Must be in local coords to compare with mouseUp events.
// If the mouse doesn't move, the menu will stay open ala the Mac.
// See also LLContextMenu::show()
S32 mouse_x, mouse_y;
+
+ // Resetting scrolling position
+ if (menu->isScrollable())
+ {
+ menu->mFirstVisibleItem = NULL;
+ }
+
+ menu->setVisible( TRUE );
+
+ // Fix menu rect if needed.
+ menu->needsArrange();
+ menu->arrangeAndClear();
+
LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y);
@@ -2948,7 +2967,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
const S32 HPAD = 2;
LLRect rect = menu->getRect();
- //LLView* cur_view = spawning_view;
S32 left = x + HPAD;
S32 top = y;
spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent());
@@ -2956,37 +2974,19 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
rect.getWidth(), rect.getHeight() );
menu->setRect( rect );
- // Resetting scrolling position
- if (menu->isScrollable())
- {
- menu->mFirstVisibleItem = NULL;
- menu->needsArrange();
- }
- menu->arrangeAndClear(); // Fix menu rect if needed.
- rect = menu->getRect();
// Adjust context menu to fit onscreen
- S32 bottom;
- left = rect.mLeft;
- bottom = rect.mBottom;
- S32 delta_x = 0;
- S32 delta_y = 0;
- if( bottom < menu_region_rect.mBottom )
- {
- // At this point, we need to move the context menu to the
- // other side of the mouse.
- delta_y = (rect.getHeight() + 2 * HPAD);
- }
-
- if( left > menu_region_rect.mRight - rect.getWidth() )
- {
- // At this point, we need to move the context menu to the
- // other side of the mouse.
- delta_x = -(rect.getWidth() + 2 * HPAD);
- }
- menu->translate( delta_x, delta_y );
- menu->setVisible( TRUE );
+ LLRect mouse_rect;
+ const S32 MOUSE_CURSOR_PADDING = 5;
+ mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING,
+ mouse_y + MOUSE_CURSOR_PADDING,
+ CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
+ CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
+ menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE );
menu->getParent()->sendChildToFront(menu);
+
+
+
}
///============================================================================
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 8309fedf7f..48887ec352 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -268,15 +268,18 @@ public:
{
Optional<EnableCallbackParam > on_enable;
Optional<CommitCallbackParam > on_click;
+ Optional<VisibleCallbackParam > on_visible;
Params()
: on_enable("on_enable"),
- on_click("on_click")
+ on_click("on_click"),
+ on_visible("on_visible")
{}
};
protected:
LLMenuItemCallGL(const Params&);
friend class LLUICtrlFactory;
void updateEnabled( void );
+ void updateVisible( void );
public:
void initFromParams(const Params& p);
@@ -300,10 +303,15 @@ public:
{
return mEnableSignal.connect(cb);
}
-
+
+ boost::signals2::connection setVisibleCallback( const visible_signal_t::slot_type& cb )
+ {
+ return mVisibleSignal.connect(cb);
+ }
private:
enable_signal_t mEnableSignal;
+ visible_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp
index 0fbb7ced54..a9f462173d 100644
--- a/indra/llui/llmultisliderctrl.cpp
+++ b/indra/llui/llmultisliderctrl.cpp
@@ -98,7 +98,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
LLTextBox::Params params;
params.name("MultiSliderCtrl Label");
params.rect(label_rect);
- params.text(p.label);
+ params.initial_value(p.label());
params.font(p.font);
mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox);
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b9bbb4db22..1695aee2b8 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -819,15 +819,6 @@ void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWS
}
}
-void LLPanel::childSetWrappedText(const std::string& id, const std::string& text, bool visible)
-{
- LLTextBox* child = findChild<LLTextBox>(id);
- if (child)
- {
- child->setVisible(visible);
- child->setWrappedText(text);
- }
-}
void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)
{
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 8b23ea7030..0594762333 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -209,9 +209,6 @@ public:
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
LLPanel *childGetVisibleTab(const std::string& id) const;
- // LLTextBox
- void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true);
-
// LLTextBox/LLTextEditor/LLLineEditor
void childSetText(const std::string& id, const LLStringExplicit& text) { childSetValue(id, LLSD(text)); }
@@ -243,7 +240,8 @@ protected:
LLCallbackMap::map_t mFactoryMap;
CommitCallbackRegistry::ScopedRegistrar mCommitCallbackRegistrar;
EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
-
+ VisibleCallbackRegistry::ScopedRegistrar mVisibleCallbackRegistrar;
+
commit_signal_t mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
std::string mHelpTopic; // the name of this panel's help topic to display in the Help Viewer
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index d1ea5843eb..f9f0307d17 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -55,6 +55,8 @@ LLRadioGroup::Params::Params()
name = "radio_group";
mouse_opaque = true;
follows.flags = FOLLOWS_LEFT | FOLLOWS_TOP;
+ // radio items are not tabbable until they are selected
+ tab_stop = false;
}
LLRadioGroup::LLRadioGroup(const LLRadioGroup::Params& p)
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index 914548b6aa..1e9b5115f8 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -47,18 +47,7 @@ class LLRadioCtrl : public LLCheckBoxCtrl
{
public:
struct Params : public LLInitParam::Block<Params, LLCheckBoxCtrl::Params>
- {
- Ignored length;
- Ignored type;
-
- Params()
- : length("length"),
- type("type")
- {
- // radio items are not tabbable until they are selected
- tab_stop = false;
- }
- };
+ {};
/*virtual*/ ~LLRadioCtrl();
/*virtual*/ void setValue(const LLSD& value);
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index ed150ac50c..7db34a0608 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -88,8 +88,6 @@ LLScrollbar::LLScrollbar(const Params & p)
mCurGlowStrength(0.f),
mTrackColor( p.track_color() ),
mThumbColor ( p.thumb_color() ),
- mOnScrollEndCallback( NULL ),
- mOnScrollEndData( NULL ),
mThumbImageV(p.thumb_image_vertical),
mThumbImageH(p.thumb_image_horizontal),
mTrackImageV(p.track_image_vertical),
@@ -243,11 +241,6 @@ void LLScrollbar::updateThumbRect()
mThumbRect.mRight = thumb_start + thumb_length;
mThumbRect.mBottom = 0;
}
-
- if (mOnScrollEndCallback && mOnScrollEndData && (mDocPos == getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
}
BOOL LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -568,12 +561,6 @@ void LLScrollbar::draw()
}
}
- BOOL was_scrolled_to_bottom = (getDocPos() == getDocPosMax());
- if (mOnScrollEndCallback && was_scrolled_to_bottom)
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
-
// Draw children
LLView::draw();
} // end draw
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index 7e88b16561..e4c5712fb7 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -164,9 +164,6 @@ private:
LLUIImagePtr mTrackImageH;
S32 mThickness;
-
- void (*mOnScrollEndCallback)(void*);
- void *mOnScrollEndData;
};
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index cd5926fb6b..5597d494fe 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -76,6 +76,7 @@ LLScrollContainer::Params::Params()
: is_opaque("opaque"),
bg_color("color"),
border_visible("border_visible"),
+ hide_scrollbar("hide_scrollbar"),
min_auto_scroll_rate("min_auto_scroll_rate", 100),
max_auto_scroll_rate("max_auto_scroll_rate", 1000),
reserve_scroll_corner("reserve_scroll_corner", false)
@@ -93,6 +94,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
mAutoScrollRate( 0.f ),
mBackgroundColor(p.bg_color()),
mIsOpaque(p.is_opaque),
+ mHideScrollbar(p.hide_scrollbar),
mReserveScrollCorner(p.reserve_scroll_corner),
mMinAutoScrollRate(p.min_auto_scroll_rate),
mMaxAutoScrollRate(p.max_auto_scroll_rate),
@@ -349,28 +351,33 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height
S32 doc_width = doc_rect.getWidth();
S32 doc_height = doc_rect.getHeight();
- *visible_width = getRect().getWidth() - 2 * mBorder->getBorderWidth();
- *visible_height = getRect().getHeight() - 2 * mBorder->getBorderWidth();
+ S32 border_width = (mBorder->getVisible() ? 2 * mBorder->getBorderWidth() : 0);
+ *visible_width = getRect().getWidth() - border_width;
+ *visible_height = getRect().getHeight() - border_width;
*show_v_scrollbar = FALSE;
- if( *visible_height < doc_height )
- {
- *show_v_scrollbar = TRUE;
- *visible_width -= scrollbar_size;
- }
-
*show_h_scrollbar = FALSE;
- if( *visible_width < doc_width )
- {
- *show_h_scrollbar = TRUE;
- *visible_height -= scrollbar_size;
- // Must retest now that visible_height has changed
- if( !*show_v_scrollbar && (*visible_height < doc_height) )
+ if (!mHideScrollbar)
+ {
+ if( *visible_height < doc_height )
{
*show_v_scrollbar = TRUE;
*visible_width -= scrollbar_size;
}
+
+ if( *visible_width < doc_width )
+ {
+ *show_h_scrollbar = TRUE;
+ *visible_height -= scrollbar_size;
+
+ // Must retest now that visible_height has changed
+ if( !*show_v_scrollbar && (*visible_height < doc_height) )
+ {
+ *show_v_scrollbar = TRUE;
+ *visible_width -= scrollbar_size;
+ }
+ }
}
}
@@ -457,19 +464,6 @@ void LLScrollContainer::draw()
sDepth--;
}
}
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
-
} // end draw
bool LLScrollContainer::addChild(LLView* view, S32 tab_group)
@@ -598,7 +592,7 @@ LLRect LLScrollContainer::getContentWindowRect() const
BOOL show_h_scrollbar = FALSE;
BOOL show_v_scrollbar = FALSE;
calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
- S32 border_width = mBorder->getBorderWidth();
+ S32 border_width = mBorder->getVisible() ? mBorder->getBorderWidth() : 0;
scroller_view_rect.setOriginAndSize(border_width,
show_h_scrollbar ? mScrollbar[HORIZONTAL]->getRect().mTop : border_width,
visible_width,
diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h
index 8385bca02f..ac8ffe5258 100644
--- a/indra/llui/llscrollcontainer.h
+++ b/indra/llui/llscrollcontainer.h
@@ -68,7 +68,8 @@ public:
{
Optional<bool> is_opaque,
reserve_scroll_corner,
- border_visible;
+ border_visible,
+ hide_scrollbar;
Optional<F32> min_auto_scroll_rate,
max_auto_scroll_rate;
Optional<LLUIColor> bg_color;
@@ -139,6 +140,7 @@ private:
F32 mAutoScrollRate;
F32 mMinAutoScrollRate;
F32 mMaxAutoScrollRate;
+ bool mHideScrollbar;
};
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index e28da91305..a7c268758a 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -204,6 +204,13 @@ BOOL LLScrollListText::isText() const
return TRUE;
}
+BOOL LLScrollListText::needsToolTip() const
+{
+ // show tooltips for truncated text
+ return mFont->getWidth(mText.getString()) > getWidth();
+}
+
+
//virtual
BOOL LLScrollListText::getVisible() const
{
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index 9d3fa65f64..758623f121 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -94,16 +94,18 @@ public:
LLScrollListCell(const LLScrollListCell::Params&);
virtual ~LLScrollListCell() {};
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible
+
+ virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const {}; // truncate to given width, if possible
virtual S32 getWidth() const {return mWidth;}
virtual S32 getContentWidth() const { return 0; }
- virtual S32 getHeight() const = 0;
+ virtual S32 getHeight() const { return 0; }
virtual const LLSD getValue() const;
virtual void setValue(const LLSD& value) { }
virtual BOOL getVisible() const { return TRUE; }
virtual void setWidth(S32 width) { mWidth = width; }
virtual void highlightText(S32 offset, S32 num_chars) {}
- virtual BOOL isText() const = 0;
+ virtual BOOL isText() const { return FALSE; }
+ virtual BOOL needsToolTip() const { return FALSE; }
virtual void setColor(const LLColor4&) {}
virtual void onCommit() {};
@@ -120,8 +122,6 @@ public:
LLScrollListSpacer(const LLScrollListCell::Params& p) : LLScrollListCell(p) {}
/*virtual*/ ~LLScrollListSpacer() {};
/*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const {}
- /*virtual*/ S32 getHeight() const { return 0; }
- /*virtual*/ BOOL isText() const { return FALSE; }
};
/*
@@ -143,6 +143,7 @@ public:
/*virtual*/ void setColor(const LLColor4&);
/*virtual*/ BOOL isText() const;
+ /*virtual*/ BOOL needsToolTip() const;
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
@@ -175,7 +176,6 @@ public:
/*virtual*/ S32 getHeight() const;
/*virtual*/ const LLSD getValue() const;
/*virtual*/ void setColor(const LLColor4&);
- /*virtual*/ BOOL isText()const { return FALSE; }
/*virtual*/ void setValue(const LLSD& value);
private:
@@ -202,7 +202,6 @@ public:
/*virtual*/ void setEnabled(BOOL enable);
LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
- /*virtual*/ BOOL isText() const { return FALSE; }
private:
LLCheckBoxCtrl* mCheckBox;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 54e42bf642..af05686c70 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -218,7 +218,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
sbparams.orientation(LLScrollbar::VERTICAL);
sbparams.doc_size(getItemCount());
sbparams.doc_pos(mScrollLines);
- sbparams.page_size( mPageLines ? mPageLines : getItemCount() );
+ sbparams.page_size( getLinesPerPage() );
sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2));
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.visible(false);
@@ -475,10 +475,7 @@ void LLScrollListCtrl::updateLayout()
getChildView("comment_text")->setShape(mItemListRect);
// how many lines of content in a single "page"
- S32 page_lines = mLineHeight? mItemListRect.getHeight() / mLineHeight : getItemCount();
- //if mPageLines is NOT provided display all item
- if(mPageLines)
- page_lines = mPageLines;
+ S32 page_lines = getLinesPerPage();
BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight();
if (scrollbar_visible)
@@ -1386,7 +1383,7 @@ void LLScrollListCtrl::drawItems()
S32 y = mItemListRect.mTop - mLineHeight;
// allow for partial line at bottom
- S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
+ S32 num_page_lines = getLinesPerPage();
LLRect item_rect;
@@ -1529,7 +1526,19 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
-BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+// *NOTE: Requires a valid row_index and column_index
+LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)
+{
+ LLRect cell_rect;
+ S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
+ S32 rect_bottom = getRowOffsetFromIndex(row_index);
+ LLScrollListColumn* columnp = getColumn(column_index);
+ cell_rect.setOriginAndSize(rect_left, rect_bottom,
+ rect_left + columnp->getWidth(), mLineHeight);
+ return cell_rect;
+}
+
+BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
{
S32 column_index = getColumnIndexFromOffset(x);
LLScrollListColumn* columnp = getColumn(column_index);
@@ -1543,20 +1552,23 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sti
{
LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
if (!hit_cell) return FALSE;
- //S32 cell_required_width = hit_cell->getContentWidth();
if (hit_cell
- && hit_cell->isText())
+ && hit_cell->isText()
+ && hit_cell->needsToolTip())
{
- S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
- S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item));
- LLRect cell_rect;
- cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight);
+ S32 row_index = getItemIndex(hit_item);
+ LLRect cell_rect = getCellRect(row_index, column_index);
// Convert rect local to screen coordinates
LLRect sticky_rect;
localRectToScreen(cell_rect, &sticky_rect);
- LLToolTipMgr::instance().show(LLToolTipParams()
- .message(hit_cell->getValue().asString())
- .sticky_rect(sticky_rect));
+
+ // display tooltip exactly over original cell, in same font
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(hit_cell->getValue().asString())
+ .font(LLFontGL::getFontSansSerifSmall())
+ .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 4))
+ .delay_time(0.2f)
+ .sticky_rect(sticky_rect));
}
handled = TRUE;
}
@@ -1565,7 +1577,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sti
LLScrollColumnHeader* headerp = columnp->mHeader;
if (headerp && !handled)
{
- handled = headerp->handleToolTip(x, y, msg, sticky_rect_screen);
+ handled = headerp->handleToolTip(x, y, mask);
}
return handled;
@@ -1877,7 +1889,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mLineHeight );
// allow for partial line at bottom
- S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
+ S32 num_page_lines = getLinesPerPage();
S32 line = 0;
item_list::iterator iter;
@@ -2336,6 +2348,20 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
}
}
+S32 LLScrollListCtrl::getLinesPerPage()
+{
+ //if mPageLines is NOT provided display all item
+ if(mPageLines)
+ {
+ return mPageLines;
+ }
+ else
+ {
+ return mLineHeight ? mItemListRect.getHeight() / mLineHeight : getItemCount();
+ }
+}
+
+
// Called by scrollbar
void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar )
{
@@ -2442,7 +2468,7 @@ void LLScrollListCtrl::scrollToShowSelected()
}
S32 lowest = mScrollLines;
- S32 page_lines = (mPageLines)? mPageLines : getItemCount();
+ S32 page_lines = getLinesPerPage();
S32 highest = mScrollLines + page_lines;
if (index < lowest)
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 83b2f71037..78bc60db6e 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -288,7 +288,7 @@ public:
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ void setEnabled(BOOL enabled);
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void onFocusReceived();
@@ -307,6 +307,9 @@ public:
LLRect getItemListRect() { return mItemListRect; }
+ /// Returns rect, in local coords, of a given row/column
+ LLRect getCellRect(S32 row_index, S32 column_index);
+
// Used "internally" by the scroll bar.
void onScrollChange( S32 new_pos, LLScrollbar* src );
@@ -390,6 +393,7 @@ private:
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
+ S32 getLinesPerPage();
static void showNameDetails(std::string id, bool is_group);
static void copyNameToClipboard(std::string id, bool is_group);
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index 2ac6925c78..2c5e0d24cd 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -36,7 +36,6 @@
#include "llscrolllistitem.h"
#include "llrect.h"
-#include "llresmgr.h" // LLFONT_SANSSERIF_SMALL
#include "llui.h"
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index c2b7effbc7..0ec7fbcc2c 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -34,10 +34,8 @@
#ifndef LLSCROLLLISTITEM_H
#define LLSCROLLLISTITEM_H
-#include "llfontgl.h" // LLFontGL::HAlign
#include "llpointer.h" // LLPointer<>
#include "llsd.h"
-#include "lluistring.h"
#include "v4color.h"
#include "llinitparam.h"
#include "llscrolllistcell.h"
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index fb71b60725..3ecf629082 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -83,7 +83,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
LLTextBox::Params params(p.slider_label);
params.rect.setIfNotProvided(label_rect);
params.font.setIfNotProvided(p.font);
- params.text(p.label);
+ params.initial_value(p.label());
mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox);
}
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 83d71006aa..bedf16a397 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -90,7 +90,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
LLTextBox::Params params;
params.name("SpinCtrl Label");
params.rect(label_rect);
- params.text(p.label);
+ params.initial_value(p.label());
if (p.font.isProvided())
{
params.font(p.font);
diff --git a/indra/llui/llstatview.cpp b/indra/llui/llstatview.cpp
index 4ba01eb441..9580c76e2a 100644
--- a/indra/llui/llstatview.cpp
+++ b/indra/llui/llstatview.cpp
@@ -67,5 +67,7 @@ LLStatView::~LLStatView()
static StatViewRegistry::Register<LLStatBar> r1("stat_bar");
static StatViewRegistry::Register<LLStatView> r2("stat_view");
+// stat_view can be a child of panels/etc.
+static LLDefaultChildRegistry::Register<LLStatView> r3("stat_view");
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index c16ac08014..fd3f88d1f6 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -40,7 +40,7 @@
LLStyle::Params::Params()
: visible("visible", true),
- drop_shadow("drop_shadow", false),
+ drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),
color("color", LLColor4::black),
font("font", LLFontGL::getFontMonospace()),
image("image"),
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 5e8883afd7..c769964136 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -44,12 +44,12 @@ class LLStyle : public LLRefCount
public:
struct Params : public LLInitParam::Block<Params>
{
- Optional<bool> visible,
- drop_shadow;
- Optional<LLUIColor> color;
- Optional<const LLFontGL*> font;
- Optional<LLUIImage*> image;
- Optional<std::string> link_href;
+ Optional<bool> visible;
+ Optional<LLFontGL::ShadowType> drop_shadow;
+ Optional<LLUIColor> color;
+ Optional<const LLFontGL*> font;
+ Optional<LLUIImage*> image;
+ Optional<std::string> link_href;
Params();
};
LLStyle(const Params& p = Params());
@@ -60,6 +60,8 @@ public:
BOOL isVisible() const;
void setVisible(BOOL is_visible);
+ LLFontGL::ShadowType getShadowType() { return mDropShadow; }
+
void setFont(const LLFontGL* font);
const LLFontGL* getFont() const;
@@ -94,7 +96,7 @@ public:
BOOL mItalic;
BOOL mBold;
BOOL mUnderline;
- BOOL mDropShadow;
+ LLFontGL::ShadowType mDropShadow;
protected:
~LLStyle() { }
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index b6eed3ef18..b1067ad6f3 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -596,10 +596,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
// virtual
-BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect )
+BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
{
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
- BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
+ BOOL handled = LLPanel::handleToolTip( x, y, mask);
if (!handled && getTabCount() > 0)
{
LLTabTuple* firsttuple = getTab(0);
@@ -629,7 +629,7 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& stic
tuple->mButton->setVisible( TRUE );
S32 local_x = x - tuple->mButton->getRect().mLeft;
S32 local_y = y - tuple->mButton->getRect().mBottom;
- handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
+ handled = tuple->mButton->handleToolTip( local_x, local_y, mask);
if( handled )
{
break;
@@ -906,7 +906,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLTextBox::Params params;
params.name(trimmed_label);
params.rect(btn_rect);
- params.text(trimmed_label);
+ params.initial_value(trimmed_label);
params.font(font);
textbox = LLUICtrlFactory::create<LLTextBox> (params);
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 89a0346896..7bbecc1abc 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -99,7 +99,7 @@ public:
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect );
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType type, void* cargo_data,
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0fd6a14187..6c048aa908 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -34,25 +34,2011 @@
#include "linden_common.h"
#include "lltextbase.h"
-#include "llstl.h"
-#include "llview.h"
-#include "llwindow.h"
+
+#include "lllocalcliprect.h"
#include "llmenugl.h"
+#include "llscrollcontainer.h"
+#include "llstl.h"
+#include "lltextparser.h"
#include "lltooltip.h"
#include "lluictrl.h"
#include "llurlaction.h"
#include "llurlregistry.h"
-
+#include "llview.h"
+#include "llwindow.h"
#include <boost/bind.hpp>
-// global state for all text fields
-LLUIColor LLTextBase::mLinkColor = LLColor4::blue;
+const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
+const S32 CURSOR_THICKNESS = 2;
+
+LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num)
+: mDocIndexStart(index_start),
+ mDocIndexEnd(index_end),
+ mRect(rect),
+ mLineNum(line_num)
+{}
bool LLTextBase::compare_segment_end::operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const
{
return a->getEnd() < b->getEnd();
}
+
+// helper functors
+struct LLTextBase::compare_bottom
+{
+ bool operator()(const S32& a, const LLTextBase::line_info& b) const
+ {
+ return a > b.mRect.mBottom; // bottom of a is higher than bottom of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const S32& b) const
+ {
+ return a.mRect.mBottom > b; // bottom of a is higher than bottom of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return a.mRect.mBottom > b.mRect.mBottom; // bottom of a is higher than bottom of b
+ }
+
+};
+
+// helper functors
+struct LLTextBase::compare_top
+{
+ bool operator()(const S32& a, const LLTextBase::line_info& b) const
+ {
+ return a > b.mRect.mTop; // top of a is higher than top of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const S32& b) const
+ {
+ return a.mRect.mTop > b; // top of a is higher than top of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return a.mRect.mTop > b.mRect.mTop; // top of a is higher than top of b
+ }
+};
+
+struct LLTextBase::line_end_compare
+{
+ bool operator()(const S32& pos, const LLTextBase::line_info& info) const
+ {
+ return (pos < info.mDocIndexEnd);
+ }
+
+ bool operator()(const LLTextBase::line_info& info, const S32& pos) const
+ {
+ return (info.mDocIndexEnd < pos);
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return (a.mDocIndexEnd < b.mDocIndexEnd);
+ }
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LLTextBase::DocumentPanel
+//
+
+
+LLTextBase::DocumentPanel::DocumentPanel(const Params& p)
+: LLPanel(p)
+{}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LLTextBase
+//
+
+// register LLTextBase::Params under name "textbase"
+static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(&typeid(LLTextBase::Params), "textbase");
+
+LLTextBase::LineSpacingParams::LineSpacingParams()
+: multiple("multiple", 1.f),
+ pixels("pixels", 0)
+{
+}
+
+
+LLTextBase::Params::Params()
+: cursor_color("cursor_color"),
+ text_color("text_color"),
+ text_readonly_color("text_readonly_color"),
+ bg_visible("bg_visible", false),
+ border_visible("border_visible", false),
+ bg_readonly_color("bg_readonly_color"),
+ bg_writeable_color("bg_writeable_color"),
+ bg_focus_color("bg_focus_color"),
+ hide_scrollbar("hide_scrollbar"),
+ clip_to_rect("clip_to_rect", true),
+ track_end("track_end", false),
+ read_only("read_only", false),
+ v_pad("v_pad", 0),
+ h_pad("h_pad", 0),
+ line_spacing("line_spacing"),
+ max_text_length("max_length", 255),
+ font_shadow("font_shadow"),
+ wrap("wrap"),
+ use_ellipses("use_ellipses", false),
+ allow_html("allow_html", false),
+ parse_highlights("parse_highlights", false)
+{
+ addSynonym(track_end, "track_bottom");
+ addSynonym(wrap, "word_wrap");
+}
+
+
+LLTextBase::LLTextBase(const LLTextBase::Params &p)
+: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
+ mURLClickSignal(),
+ mMaxTextByteLength( p.max_text_length ),
+ mDefaultFont(p.font),
+ mFontShadow(p.font_shadow),
+ mPopupMenu(NULL),
+ mReadOnly(p.read_only),
+ mCursorColor(p.cursor_color),
+ mFgColor(p.text_color),
+ mBorderVisible( p.border_visible ),
+ mReadOnlyFgColor(p.text_readonly_color),
+ mWriteableBgColor(p.bg_writeable_color),
+ mReadOnlyBgColor(p.bg_readonly_color),
+ mFocusBgColor(p.bg_focus_color),
+ mReflowNeeded(FALSE),
+ mCursorPos( 0 ),
+ mScrollNeeded(FALSE),
+ mDesiredXPixel(-1),
+ mHPad(p.h_pad),
+ mVPad(p.v_pad),
+ mHAlign(p.font_halign),
+ mLineSpacingMult(p.line_spacing.multiple),
+ mLineSpacingPixels(p.line_spacing.pixels),
+ mTrackEnd( p.track_end ),
+ mScrollIndex(-1),
+ mSelectionStart( 0 ),
+ mSelectionEnd( 0 ),
+ mIsSelecting( FALSE ),
+ mClip(p.clip_to_rect),
+ mWordWrap(p.wrap),
+ mUseEllipses( p.use_ellipses ),
+ mParseHTML(p.allow_html),
+ mParseHighlights(p.parse_highlights)
+{
+ LLScrollContainer::Params scroll_params;
+ scroll_params.name = "text scroller";
+ scroll_params.rect = getLocalRect();
+ scroll_params.follows.flags = FOLLOWS_ALL;
+ scroll_params.is_opaque = false;
+ scroll_params.mouse_opaque = false;
+ scroll_params.min_auto_scroll_rate = 200;
+ scroll_params.max_auto_scroll_rate = 800;
+ scroll_params.hide_scrollbar = p.hide_scrollbar;
+ scroll_params.border_visible = p.border_visible;
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
+ addChild(mScroller);
+
+ LLPanel::Params panel_params;
+ panel_params.name = "text_contents";
+ panel_params.rect = LLRect(0, 500, 500, 0);
+ panel_params.background_visible = p.bg_visible;
+ panel_params.background_opaque = true;
+ panel_params.mouse_opaque = false;
+
+ mDocumentPanel = LLUICtrlFactory::create<DocumentPanel>(panel_params);
+ mScroller->addChild(mDocumentPanel);
+
+ createDefaultSegment();
+
+ updateTextRect();
+}
+
+LLTextBase::~LLTextBase()
+{
+ delete mPopupMenu;
+ clearSegments();
+}
+
+void LLTextBase::initFromParams(const LLTextBase::Params& p)
+{
+ LLUICtrl::initFromParams(p);
+ resetDirty(); // Update saved text state
+ updateSegments();
+
+ // HACK: work around enabled == readonly design bug -- RN
+ // setEnabled will modify our read only status, so do this after
+ // LLTextBase::initFromParams
+ if (p.read_only.isProvided())
+ {
+ mReadOnly = p.read_only;
+ }
+
+ // HACK: text editors always need to be enabled so that we can scroll
+ LLView::setEnabled(true);
+}
+
+bool LLTextBase::truncate()
+{
+ BOOL did_truncate = FALSE;
+
+ // First rough check - if we're less than 1/4th the size, we're OK
+ if (getLength() >= S32(mMaxTextByteLength / 4))
+ {
+ // Have to check actual byte size
+ LLWString text(getWText());
+ S32 utf8_byte_size = wstring_utf8_length(text);
+ if ( utf8_byte_size > mMaxTextByteLength )
+ {
+ // Truncate safely in UTF-8
+ std::string temp_utf8_text = wstring_to_utf8str(text);
+ temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
+ getViewModel()->setDisplay(utf8str_to_wstring( temp_utf8_text ));
+ did_truncate = TRUE;
+ }
+ }
+
+ return did_truncate;
+}
+
+LLStyle::Params LLTextBase::getDefaultStyle()
+{
+ LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() );
+ return LLStyle::Params().color(text_color).font(mDefaultFont).drop_shadow(mFontShadow);
+}
+
+void LLTextBase::onValueChange(S32 start, S32 end)
+{
+}
+
+
+// Draws the black box behind the selected text
+void LLTextBase::drawSelectionBackground()
+{
+ // Draw selection even if we don't have keyboard focus for search/replace
+ if( hasSelection() && !mLineInfoList.empty())
+ {
+ LLWString text = getWText();
+ std::vector<LLRect> selection_rects;
+
+ S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
+ S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
+ LLRect selection_rect = mTextRect;
+
+ // Skip through the lines we aren't drawing.
+ LLRect content_display_rect = mScroller->getVisibleContentRect();
+
+ // binary search for line that starts before top of visible buffer
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
+ line_list_t::const_iterator end_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
+
+ bool done = false;
+
+ // Find the coordinates of the selected area
+ for (;line_iter != end_iter && !done; ++line_iter)
+ {
+ // is selection visible on this line?
+ if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
+ {
+ segment_set_t::iterator segment_iter;
+ S32 segment_offset;
+ getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
+
+ LLRect selection_rect;
+ selection_rect.mLeft = line_iter->mRect.mLeft;
+ selection_rect.mRight = line_iter->mRect.mLeft;
+ selection_rect.mBottom = line_iter->mRect.mBottom;
+ selection_rect.mTop = line_iter->mRect.mTop;
+
+ for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
+ {
+ LLTextSegmentPtr segmentp = *segment_iter;
+
+ S32 segment_line_start = segmentp->getStart() + segment_offset;
+ S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+
+ // if selection after beginning of segment
+ if(selection_left >= segment_line_start)
+ {
+ S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
+ selection_rect.mLeft += segmentp->getWidth(segment_offset, num_chars);
+ }
+
+ // if selection spans end of current segment...
+ if (selection_right > segment_line_end)
+ {
+ // extend selection slightly beyond end of line
+ // to indicate selection of newline character (use "n" character to determine width)
+ selection_rect.mRight += segmentp->getWidth(segment_offset, segment_line_end - segment_line_start);
+ }
+ // else if selection ends on current segment...
+ else
+ {
+ S32 num_chars = selection_right - segment_line_start;
+ selection_rect.mRight += segmentp->getWidth(segment_offset, num_chars);
+
+ break;
+ }
+ }
+ selection_rects.push_back(selection_rect);
+ }
+ }
+
+ // Draw the selection box (we're using a box instead of reversing the colors on the selected text).
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ const LLColor4& color = mReadOnly ? mReadOnlyBgColor.get() : mWriteableBgColor.get();
+ F32 alpha = hasFocus() ? 0.7f : 0.3f;
+ alpha *= getDrawContext().mAlpha;
+ gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
+
+ for (std::vector<LLRect>::iterator rect_it = selection_rects.begin();
+ rect_it != selection_rects.end();
+ ++rect_it)
+ {
+ LLRect selection_rect = *rect_it;
+ selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom);
+ gl_rect_2d(selection_rect);
+ }
+ }
+}
+
+void LLTextBase::drawCursor()
+{
+ F32 alpha = getDrawContext().mAlpha;
+
+ if( hasFocus()
+ && gFocusMgr.getAppHasFocus()
+ && !mReadOnly)
+ {
+ LLWString wtext = getWText();
+ const llwchar* text = wtext.c_str();
+
+ LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+ cursor_rect.translate(-1, 0);
+ segment_set_t::iterator seg_it = getSegIterContaining(mCursorPos);
+
+ // take style from last segment
+ LLTextSegmentPtr segmentp;
+
+ if (seg_it != mSegments.end())
+ {
+ segmentp = *seg_it;
+ }
+ else
+ {
+ //segmentp = mSegments.back();
+ return;
+ }
+
+ // Draw the cursor
+ // (Flash the cursor every half second starting a fixed time after the last keystroke)
+ F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
+ if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )
+ {
+
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
+ {
+ S32 width = llmax(CURSOR_THICKNESS, segmentp->getWidth(mCursorPos - segmentp->getStart(), 1));
+ cursor_rect.mRight = cursor_rect.mLeft + width;
+ }
+ else
+ {
+ cursor_rect.mRight = cursor_rect.mLeft + CURSOR_THICKNESS;
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLColor4 cursor_color = mCursorColor.get() % alpha;
+ gGL.color4fv( cursor_color.mV );
+
+ gl_rect_2d(cursor_rect);
+
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n')
+ {
+ LLColor4 text_color;
+ const LLFontGL* fontp;
+ if (segmentp)
+ {
+ text_color = segmentp->getColor();
+ fontp = segmentp->getStyle()->getFont();
+ }
+ else if (mReadOnly)
+ {
+ text_color = mReadOnlyFgColor.get();
+ fontp = mDefaultFont;
+ }
+ else
+ {
+ text_color = mFgColor.get();
+ fontp = mDefaultFont;
+ }
+ fontp->render(text, mCursorPos, cursor_rect.mLeft, cursor_rect.mTop,
+ LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
+ LLFontGL::LEFT, LLFontGL::TOP,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ 1);
+ }
+
+ // Make sure the IME is in the right place
+ LLRect screen_pos = calcScreenRect();
+ LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) );
+
+ ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
+ ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
+ getWindow()->setLanguageTextInput( ime_pos );
+ }
+ }
+}
+
+void LLTextBase::drawText()
+{
+ LLWString text = getWText();
+ const S32 text_len = getLength();
+ if( text_len <= 0 )
+ {
+ return;
+ }
+ S32 selection_left = -1;
+ S32 selection_right = -1;
+ // Draw selection even if we don't have keyboard focus for search/replace
+ if( hasSelection())
+ {
+ selection_left = llmin( mSelectionStart, mSelectionEnd );
+ selection_right = llmax( mSelectionStart, mSelectionEnd );
+ }
+
+ LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
+ LLRect content_rect = mScroller->getContentWindowRect();
+ std::pair<S32, S32> line_range = getVisibleLines();
+ S32 first_line = line_range.first;
+ S32 last_line = line_range.second;
+ if (first_line >= last_line)
+ {
+ return;
+ }
+
+ S32 line_start = getLineStart(first_line);
+ // find first text segment that spans top of visible portion of text buffer
+ segment_set_t::iterator seg_iter = getSegIterContaining(line_start);
+ if (seg_iter == mSegments.end())
+ {
+ return;
+ }
+
+ LLTextSegmentPtr cur_segment = *seg_iter;
+
+ for (S32 cur_line = first_line; cur_line < last_line; cur_line++)
+ {
+ line_info& line = mLineInfoList[cur_line];
+
+ if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom)
+ {
+ break;
+ }
+
+ S32 next_start = -1;
+ S32 line_end = text_len;
+
+ if ((cur_line + 1) < getLineCount())
+ {
+ next_start = getLineStart(cur_line + 1);
+ line_end = next_start;
+ }
+ if ( text[line_end-1] == '\n' )
+ {
+ --line_end;
+ }
+
+ LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
+ line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
+ mDocumentPanel->getRect().getWidth() - scrolled_view_rect.mLeft,
+ line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom);
+
+ // draw a single line of text
+ S32 seg_start = line_start;
+ while( seg_start < line_end )
+ {
+ while( cur_segment->getEnd() <= seg_start )
+ {
+ seg_iter++;
+ if (seg_iter == mSegments.end())
+ {
+ llwarns << "Ran off the segmentation end!" << llendl;
+
+ return;
+ }
+ cur_segment = *seg_iter;
+ }
+
+ S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart();
+ text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect));
+
+ seg_start = clipped_end + cur_segment->getStart();
+ }
+
+ line_start = next_start;
+ }
+}
+
+///////////////////////////////////////////////////////////////////
+// Returns change in number of characters in mWText
+
+S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments )
+{
+ LLWString text(getWText());
+ S32 old_len = text.length(); // length() returns character length
+ S32 insert_len = wstr.length();
+
+ pos = getEditableIndex(pos, true);
+
+ segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+
+ LLTextSegmentPtr default_segment;
+
+ LLTextSegmentPtr segmentp;
+ if (seg_iter != mSegments.end())
+ {
+ segmentp = *seg_iter;
+ }
+ else
+ {
+ //segmentp = mSegments.back();
+ return pos;
+ }
+
+ if (segmentp->canEdit())
+ {
+ segmentp->setEnd(segmentp->getEnd() + insert_len);
+ if (seg_iter != mSegments.end())
+ {
+ ++seg_iter;
+ }
+ }
+ else
+ {
+ // create default editable segment to hold new text
+ default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), pos, pos + insert_len, *this);
+ }
+
+ // shift remaining segments to right
+ for(;seg_iter != mSegments.end(); ++seg_iter)
+ {
+ LLTextSegmentPtr segmentp = *seg_iter;
+ segmentp->setStart(segmentp->getStart() + insert_len);
+ segmentp->setEnd(segmentp->getEnd() + insert_len);
+ }
+
+ // insert new segments
+ if (segments)
+ {
+ if (default_segment.notNull())
+ {
+ // potentially overwritten by segments passed in
+ insertSegment(default_segment);
+ }
+ for (segment_vec_t::iterator seg_iter = segments->begin();
+ seg_iter != segments->end();
+ ++seg_iter)
+ {
+ LLTextSegment* segmentp = *seg_iter;
+ insertSegment(segmentp);
+ }
+ }
+
+ text.insert(pos, wstr);
+ getViewModel()->setDisplay(text);
+
+ if ( truncate() )
+ {
+ // The user's not getting everything he's hoping for
+ make_ui_sound("UISndBadKeystroke");
+ insert_len = getLength() - old_len;
+ }
+
+ onValueChange(pos, pos + insert_len);
+
+ return insert_len;
+}
+
+S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
+{
+ LLWString text(getWText());
+ segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+ while(seg_iter != mSegments.end())
+ {
+ LLTextSegmentPtr segmentp = *seg_iter;
+ S32 end = pos + length;
+ if (segmentp->getStart() < pos)
+ {
+ // deleting from middle of segment
+ if (segmentp->getEnd() > end)
+ {
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ // truncating segment
+ else
+ {
+ segmentp->setEnd(pos);
+ }
+ }
+ else if (segmentp->getStart() < end)
+ {
+ // deleting entire segment
+ if (segmentp->getEnd() <= end)
+ {
+ // remove segment
+ segmentp->unlinkFromDocument(this);
+ segment_set_t::iterator seg_to_erase(seg_iter++);
+ mSegments.erase(seg_to_erase);
+ continue;
+ }
+ // deleting head of segment
+ else
+ {
+ segmentp->setStart(pos);
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ }
+ else
+ {
+ // shifting segments backward to fill deleted portion
+ segmentp->setStart(segmentp->getStart() - length);
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ ++seg_iter;
+ }
+
+ text.erase(pos, length);
+ getViewModel()->setDisplay(text);
+
+ // recreate default segment in case we erased everything
+ createDefaultSegment();
+
+ onValueChange(pos, pos);
+
+ return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
+}
+
+S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
+{
+ if (pos > (S32)getLength())
+ {
+ return 0;
+ }
+ LLWString text(getWText());
+ text[pos] = wc;
+ getViewModel()->setDisplay(text);
+
+ onValueChange(pos, pos + 1);
+
+ return 1;
+}
+
+
+void LLTextBase::createDefaultSegment()
+{
+ // ensures that there is always at least one segment
+ if (mSegments.empty())
+ {
+ LLTextSegmentPtr default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
+ mSegments.insert(default_segment);
+ default_segment->linkToDocument(this);
+ }
+}
+
+void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
+{
+ if (segment_to_insert.isNull())
+ {
+ return;
+ }
+
+ segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
+
+ if (cur_seg_iter == mSegments.end())
+ {
+ mSegments.insert(segment_to_insert);
+ segment_to_insert->linkToDocument(this);
+ }
+ else
+ {
+ LLTextSegmentPtr cur_segmentp = *cur_seg_iter;
+ if (cur_segmentp->getStart() < segment_to_insert->getStart())
+ {
+ S32 old_segment_end = cur_segmentp->getEnd();
+ // split old at start point for new segment
+ cur_segmentp->setEnd(segment_to_insert->getStart());
+ // advance to next segment
+ ++cur_seg_iter;
+ // insert remainder of old segment
+ LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
+ cur_seg_iter = mSegments.insert(cur_seg_iter, remainder_segment);
+ remainder_segment->linkToDocument(this);
+ // insert new segment before remainder of old segment
+ cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
+
+ segment_to_insert->linkToDocument(this);
+ // move to "remanider" segment and start truncation there
+ ++cur_seg_iter;
+ }
+ else
+ {
+ cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
+ ++cur_seg_iter;
+ segment_to_insert->linkToDocument(this);
+ }
+
+ // now delete/truncate remaining segments as necessary
+ while(cur_seg_iter != mSegments.end())
+ {
+ cur_segmentp = *cur_seg_iter;
+ if (cur_segmentp->getEnd() <= segment_to_insert->getEnd())
+ {
+ cur_segmentp->unlinkFromDocument(this);
+ segment_set_t::iterator seg_to_erase(cur_seg_iter++);
+ mSegments.erase(seg_to_erase);
+ }
+ else
+ {
+ cur_segmentp->setStart(segment_to_insert->getEnd());
+ break;
+ }
+ }
+ }
+}
+
+BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMouseUp(x, y, mask))
+ {
+ // Did we just click on a link?
+ if (cur_segment->getStyle()
+ && cur_segment->getStyle()->isLink())
+ {
+ // *TODO: send URL here?
+ mURLClickSignal(this, LLSD() );
+ }
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMiddleMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMiddleMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMiddleMouseUp(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMiddleMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleRightMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleRightMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleRightMouseUp(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleRightMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleDoubleClick(x, y, mask);
+}
+
+BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleHover(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleHover(x, y, mask);
+}
+
+BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleScrollWheel(x, y, clicks))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleToolTip(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleToolTip(x, y, mask);
+}
+
+
+void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLUICtrl::reshape( width, height, called_from_parent );
+
+ // do this first after reshape, because other things depend on
+ // up-to-date mTextRect
+ updateTextRect();
+
+ needsReflow();
+}
+
+void LLTextBase::draw()
+{
+ // reflow if needed, on demand
+ reflow();
+
+ // then update scroll position, as cursor may have moved
+ updateScrollFromCursor();
+
+ LLColor4 bg_color = mReadOnly
+ ? mReadOnlyBgColor.get()
+ : hasFocus()
+ ? mFocusBgColor.get()
+ : mWriteableBgColor.get();
+
+ mDocumentPanel->setBackgroundColor(bg_color);
+
+ LLUICtrl::draw();
+ {
+ LLLocalClipRect clip(mTextRect, mClip);
+ drawSelectionBackground();
+ drawText();
+ drawCursor();
+ }
+}
+
+//virtual
+void LLTextBase::clear()
+{
+ getViewModel()->setDisplay(LLWStringUtil::null);
+ clearSegments();
+}
+
+//virtual
+void LLTextBase::setColor( const LLColor4& c )
+{
+ mFgColor = c;
+}
+
+//virtual
+void LLTextBase::setValue(const LLSD& value )
+{
+ setText(value.asString());
+}
+
+//virtual
+void LLTextBase::deselect()
+{
+ mSelectionStart = 0;
+ mSelectionEnd = 0;
+ mIsSelecting = FALSE;
+}
+
+
+// Sets the scrollbar from the cursor position
+void LLTextBase::updateScrollFromCursor()
+{
+ // Update scroll position even in read-only mode (when there's no cursor displayed)
+ // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
+
+ if (!mScrollNeeded)
+ {
+ return;
+ }
+ mScrollNeeded = FALSE;
+
+ // scroll so that the cursor is at the top of the page
+ LLRect scroller_doc_window = mScroller->getVisibleContentRect();
+ LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
+ cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
+ mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
+}
+
+S32 LLTextBase::getLeftOffset(S32 width)
+{
+ switch (mHAlign)
+ {
+ case LLFontGL::LEFT:
+ return 0;
+ case LLFontGL::HCENTER:
+ return (mTextRect.getWidth() - width) / 2;
+ case LLFontGL::RIGHT:
+ return mTextRect.getWidth() - width;
+ default:
+ return 0;
+ }
+}
+
+
+static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
+void LLTextBase::reflow(S32 start_index)
+{
+ if (!mReflowNeeded) return;
+
+ LLFastTimer ft(FTM_TEXT_REFLOW);
+
+ updateSegments();
+
+ while(mReflowNeeded)
+ {
+ mReflowNeeded = FALSE;
+
+ bool scrolled_to_bottom = mScroller->isAtBottom();
+
+ LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+ bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible
+ S32 first_line = getFirstVisibleLine();
+
+ // if scroll anchor not on first line, update it to first character of first line
+ if (!mLineInfoList.empty()
+ && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart
+ || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd))
+ {
+ mScrollIndex = mLineInfoList[first_line].mDocIndexStart;
+ }
+ LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
+
+ S32 cur_top = 0;
+
+ if (getLength())
+ {
+ segment_set_t::iterator seg_iter = mSegments.begin();
+ S32 seg_offset = 0;
+ S32 line_start_index = 0;
+ const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
+ S32 remaining_pixels = text_width;
+ LLWString text(getWText());
+ S32 line_count = 0;
+
+ // find and erase line info structs starting at start_index and going to end of document
+ if (!mLineInfoList.empty())
+ {
+ // find first element whose end comes after start_index
+ line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
+ line_start_index = iter->mDocIndexStart;
+ line_count = iter->mLineNum;
+ getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
+ mLineInfoList.erase(iter, mLineInfoList.end());
+ }
+
+ S32 line_height = 0;
+
+ while(seg_iter != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *seg_iter;
+
+ // track maximum height of any segment on this line
+ line_height = llmax(line_height, segment->getMaxHeight());
+ S32 cur_index = segment->getStart() + seg_offset;
+ // find run of text from this segment that we can display on one line
+ S32 end_index = cur_index;
+ while(end_index < segment->getEnd() && text[end_index] != '\n')
+ {
+ ++end_index;
+ }
+
+ // ask segment how many character fit in remaining space
+ S32 max_characters = end_index - cur_index;
+ S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
+ seg_offset,
+ cur_index - line_start_index,
+ max_characters);
+
+
+ S32 segment_width = segment->getWidth(seg_offset, character_count);
+ remaining_pixels -= segment_width;
+ S32 text_left = getLeftOffset(text_width - remaining_pixels);
+
+ seg_offset += character_count;
+
+ S32 last_segment_char_on_line = segment->getStart() + seg_offset;
+
+ // if we didn't finish the current segment...
+ if (last_segment_char_on_line < segment->getEnd())
+ {
+ // set up index for next line
+ // ...skip newline, we don't want to draw
+ S32 next_line_count = line_count;
+ if (text[last_segment_char_on_line] == '\n')
+ {
+ seg_offset++;
+ last_segment_char_on_line++;
+ next_line_count++;
+ }
+
+ // add line info and keep going
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ LLRect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height),
+ line_count));
+
+ line_start_index = segment->getStart() + seg_offset;
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ remaining_pixels = text_width;
+ line_height = 0;
+ line_count = next_line_count;
+ }
+ // ...just consumed last segment..
+ else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
+ {
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ LLRect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height),
+ line_count));
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ break;
+ }
+ // finished a segment and there are segments remaining on this line
+ else
+ {
+ // subtract pixels used and increment segment
+ ++seg_iter;
+ seg_offset = 0;
+ }
+ }
+ }
+
+ if (mLineInfoList.empty())
+ {
+ mContentsRect = LLRect(0, mVPad, mHPad, 0);
+ }
+ else
+ {
+
+ mContentsRect = mLineInfoList.begin()->mRect;
+ for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
+ line_iter != mLineInfoList.end();
+ ++line_iter)
+ {
+ mContentsRect.unionWith(line_iter->mRect);
+ }
+
+ mContentsRect.mRight += mHPad;
+ mContentsRect.mTop += mVPad;
+ // get around rounding errors when clipping text against rectangle
+ mContentsRect.stretch(1);
+ }
+
+ // change mDocumentPanel document size to accomodate reflowed text
+ LLRect document_rect;
+ document_rect.setOriginAndSize(1, 1,
+ mScroller->getContentWindowRect().getWidth(),
+ llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
+ mDocumentPanel->setShape(document_rect);
+
+ // after making document big enough to hold all the text, move the text to fit in the document
+ if (!mLineInfoList.empty())
+ {
+ S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
+ // move line segments to fit new document rect
+ for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
+ {
+ it->mRect.translate(0, delta_pos);
+ }
+ mContentsRect.translate(0, delta_pos);
+ }
+
+ // calculate visible region for diplaying text
+ updateTextRect();
+
+ for (segment_set_t::iterator segment_it = mSegments.begin();
+ segment_it != mSegments.end();
+ ++segment_it)
+ {
+ LLTextSegmentPtr segmentp = *segment_it;
+ segmentp->updateLayout(*this);
+
+ }
+
+ // apply scroll constraints after reflowing text
+ if (!hasMouseCapture())
+ {
+ LLRect visible_content_rect = mScroller->getVisibleContentRect();
+ if (scrolled_to_bottom && mTrackEnd)
+ {
+ // keep bottom of text buffer visible
+ endOfDoc();
+ }
+ else if (hasSelection() && follow_selection)
+ {
+ // keep cursor in same vertical position on screen when selecting text
+ LLRect new_cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
+ new_cursor_rect_doc.translate(visible_content_rect.mLeft, visible_content_rect.mBottom);
+ mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
+ //llassert_always(getLocalRectFromDocIndex(mCursorPos).mBottom == old_cursor_rect.mBottom);
+ }
+ else
+ {
+ // keep first line of text visible
+ LLRect new_first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
+ new_first_char_rect.translate(visible_content_rect.mLeft, visible_content_rect.mBottom);
+ mScroller->scrollToShowRect(new_first_char_rect, first_char_rect);
+ //llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom);
+ }
+ }
+ }
+
+
+ // reset desired x cursor position
+ updateCursorXPos();
+}
+
+LLRect LLTextBase::getContentsRect()
+{
+ reflow();
+ return mContentsRect;
+}
+
+
+void LLTextBase::clearSegments()
+{
+ mSegments.clear();
+ createDefaultSegment();
+}
+
+S32 LLTextBase::getLineStart( S32 line ) const
+{
+ S32 num_lines = getLineCount();
+ if (num_lines == 0)
+ {
+ return 0;
+ }
+
+ line = llclamp(line, 0, num_lines-1);
+ return mLineInfoList[line].mDocIndexStart;
+}
+
+
+S32 LLTextBase::getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap) const
+{
+ if (mLineInfoList.empty())
+ {
+ return 0;
+ }
+ else
+ {
+ line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), doc_index, line_end_compare());
+ if (include_wordwrap)
+ {
+ return iter - mLineInfoList.begin();
+ }
+ else
+ {
+ if (iter == mLineInfoList.end())
+ {
+ return mLineInfoList.back().mLineNum;
+ }
+ else
+ {
+ return iter->mLineNum;
+ }
+ }
+ }
+}
+
+// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line.
+S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap) const
+{
+ if (mLineInfoList.empty())
+ {
+ return startpos;
+ }
+ else
+ {
+ line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), startpos, line_end_compare());
+ return startpos - iter->mDocIndexStart;
+ }
+}
+
+S32 LLTextBase::getFirstVisibleLine() const
+{
+ LLRect visible_region = mScroller->getVisibleContentRect();
+
+ // binary search for line that starts before top of visible buffer
+ line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
+
+ return iter - mLineInfoList.begin();
+}
+
+std::pair<S32, S32> LLTextBase::getVisibleLines() const
+{
+ LLRect visible_region = mScroller->getVisibleContentRect();
+
+ // binary search for line that starts before top of visible buffer and starts before end of visible buffer
+ line_list_t::const_iterator first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
+ line_list_t::const_iterator last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top());
+
+ return std::pair<S32, S32>(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin());
+}
+
+
+
+LLTextViewModel* LLTextBase::getViewModel() const
+{
+ return (LLTextViewModel*)mViewModel.get();
+}
+
+void LLTextBase::addDocumentChild(LLView* view)
+{
+ mDocumentPanel->addChild(view);
+}
+
+void LLTextBase::removeDocumentChild(LLView* view)
+{
+ mDocumentPanel->removeChild(view);
+}
+
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments");
+void LLTextBase::updateSegments()
+{
+ LLFastTimer ft(FTM_UPDATE_TEXT_SEGMENTS);
+ createDefaultSegment();
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp )
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
+{
+ segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const
+{
+ LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+// Finds the text segment (if any) at the give local screen position
+LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+{
+ // Find the cursor position at the requested local screen position
+ S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
+ segment_set_t::iterator seg_iter = getSegIterContaining(offset);
+ if (seg_iter != mSegments.end())
+ {
+ return *seg_iter;
+ }
+ else
+ {
+ return LLTextSegmentPtr();
+ }
+}
+
+void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
+{
+ // work out the XUI menu file to use for this url
+ LLUrlMatch match;
+ std::string url = in_url;
+ if (! LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return;
+ }
+
+ std::string xui_file = match.getMenuName();
+ if (xui_file.empty())
+ {
+ return;
+ }
+
+ // set up the callbacks for all of the potential menu items, N.B. we
+ // don't use const ref strings in callbacks in case url goes out of scope
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.Open", boost::bind(&LLUrlAction::openURL, url));
+ registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));
+ registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
+ registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
+ registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
+ registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
+ registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
+
+ // create and return the context menu from the XUI file
+ delete mPopupMenu;
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+ if (mPopupMenu)
+ {
+ mPopupMenu->show(x, y);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+}
+
+void LLTextBase::setText(const LLStringExplicit &utf8str)
+{
+ // clear out the existing text and segments
+ clear();
+
+ truncate();
+
+ createDefaultSegment();
+
+ startOfDoc();
+ deselect();
+
+ // append the new text (supports Url linking)
+ std::string text(utf8str);
+ LLStringUtil::removeCRLF(text);
+
+ appendText(text, false);
+
+ needsReflow();
+
+ //resetDirty();
+ onValueChange(0, getLength());
+}
+
+//virtual
+std::string LLTextBase::getText() const
+{
+ return getViewModel()->getValue().asString();
+}
+
+void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
+{
+ LLStyle::Params style_params(input_params);
+ style_params.fillFrom(getDefaultStyle());
+
+ if (!style_params.font.isProvided())
+ {
+ style_params.font = mDefaultFont;
+ }
+ if (!style_params.drop_shadow.isProvided())
+ {
+ style_params.drop_shadow = mFontShadow;
+ }
+
+ S32 part = (S32)LLTextParser::WHOLE;
+ if(mParseHTML)
+ {
+ S32 start=0,end=0;
+ LLUrlMatch match;
+ std::string text = new_text;
+ while ( LLUrlRegistry::instance().findUrl(text, match,
+ boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
+ {
+ start = match.getStart();
+ end = match.getEnd()+1;
+
+ LLStyle::Params link_params = style_params;
+ link_params.color = match.getColor();
+ // apply font name from requested style_params
+ std::string font_name = LLFontGL::nameFromFont(style_params.font());
+ link_params.font.name.setIfNotProvided(font_name);
+ link_params.font.style = "UNDERLINE";
+ link_params.link_href = match.getUrl();
+
+ // output the text before the Url
+ if (start > 0)
+ {
+ if (part == (S32)LLTextParser::WHOLE ||
+ part == (S32)LLTextParser::START)
+ {
+ part = (S32)LLTextParser::START;
+ }
+ else
+ {
+ part = (S32)LLTextParser::MIDDLE;
+ }
+ std::string subtext=text.substr(0,start);
+ appendAndHighlightText(subtext, prepend_newline, part, style_params);
+ prepend_newline = false;
+ }
+
+ // output an optional icon before the Url
+ if (! match.getIcon().empty())
+ {
+ LLUIImagePtr image = LLUI::getUIImage(match.getIcon());
+ if (image)
+ {
+ LLStyle::Params icon;
+ icon.image = image;
+ // HACK: fix spacing of images and remove the fixed char spacing
+ appendAndHighlightText(" ", prepend_newline, part, icon);
+ prepend_newline = false;
+ }
+ }
+ // output the styled Url
+ appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params);
+ prepend_newline = false;
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
+ {
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
+ }
+
+ // move on to the rest of the text after the Url
+ if (end < (S32)text.length())
+ {
+ text = text.substr(end,text.length() - end);
+ end=0;
+ part=(S32)LLTextParser::END;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
+ if (end < (S32)text.length()) appendAndHighlightText(text, prepend_newline, part, style_params);
+ }
+ else
+ {
+ appendAndHighlightText(new_text, prepend_newline, part, style_params);
+ }
+}
+
+void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep)
+{
+ if (new_text.empty()) return;
+
+ // Save old state
+ S32 selection_start = mSelectionStart;
+ S32 selection_end = mSelectionEnd;
+ BOOL was_selecting = mIsSelecting;
+ S32 cursor_pos = mCursorPos;
+ S32 old_length = getLength();
+ BOOL cursor_was_at_end = (mCursorPos == old_length);
+
+ deselect();
+
+ setCursorPos(old_length);
+
+ LLTextParser* highlight = LLTextParser::getInstance();
+
+ if (mParseHighlights && highlight)
+ {
+ LLStyle::Params highlight_params = stylep;
+
+ LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
+ for (S32 i = 0; i < pieces.size(); i++)
+ {
+ LLSD color_llsd = pieces[i]["color"];
+ LLColor4 lcolor;
+ lcolor.setValue(color_llsd);
+ highlight_params.color = lcolor;
+
+ LLWString wide_text;
+ if (prepend_newline && (i == 0 || pieces.size() <= 1 ))
+ {
+ wide_text = utf8str_to_wstring(std::string("\n") + pieces[i]["text"].asString());
+ }
+ else
+ {
+ wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
+ }
+ S32 cur_length = getLength();
+ LLTextSegmentPtr segmentp = new LLNormalTextSegment(new LLStyle(highlight_params), cur_length, cur_length + wide_text.size(), *this);
+ segment_vec_t segments;
+ segments.push_back(segmentp);
+ insertStringNoUndo(cur_length, wide_text, &segments);
+ }
+ }
+ else
+ {
+ LLWString wide_text;
+
+ // Add carriage return if not first line
+ if (getLength() != 0
+ && prepend_newline)
+ {
+ wide_text = utf8str_to_wstring(std::string("\n") + new_text);
+ }
+ else
+ {
+ wide_text = utf8str_to_wstring(new_text);
+ }
+
+ segment_vec_t segments;
+ S32 segment_start = old_length;
+ S32 segment_end = old_length + wide_text.size();
+ segments.push_back(new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this ));
+
+ insertStringNoUndo(getLength(), wide_text, &segments);
+ }
+
+ needsReflow();
+
+ // Set the cursor and scroll position
+ if( selection_start != selection_end )
+ {
+ mSelectionStart = selection_start;
+ mSelectionEnd = selection_end;
+
+ mIsSelecting = was_selecting;
+ setCursorPos(cursor_pos);
+ }
+ else if( cursor_was_at_end )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos(cursor_pos);
+ }
+
+ //if( !allow_undo )
+ //{
+ // blockUndo();
+ //}
+}
+
+
+void LLTextBase::replaceUrlLabel(const std::string &url,
+ const std::string &label)
+{
+ // get the full (wide) text for the editor so we can change it
+ LLWString text = getWText();
+ LLWString wlabel = utf8str_to_wstring(label);
+ bool modified = false;
+ S32 seg_start = 0;
+
+ // iterate through each segment looking for ones styled as links
+ segment_set_t::iterator it;
+ for (it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *seg = *it;
+ const LLStyleSP style = seg->getStyle();
+
+ // update segment start/end length in case we replaced text earlier
+ S32 seg_length = seg->getEnd() - seg->getStart();
+ seg->setStart(seg_start);
+ seg->setEnd(seg_start + seg_length);
+
+ // if we find a link with our Url, then replace the label
+ if (style->isLink() && style->getLinkHREF() == url)
+ {
+ S32 start = seg->getStart();
+ S32 end = seg->getEnd();
+ text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
+ seg->setEnd(start + wlabel.size());
+ modified = true;
+ }
+
+ // work out the character offset for the next segment
+ seg_start = seg->getEnd();
+ }
+
+ // update the editor with the new (wide) text string
+ if (modified)
+ {
+ getViewModel()->setDisplay(text);
+ deselect();
+ setCursorPos(mCursorPos);
+ needsReflow();
+ }
+}
+
+
+void LLTextBase::setWText(const LLWString& text)
+{
+ setText(wstring_to_utf8str(text));
+}
+
+LLWString LLTextBase::getWText() const
+{
+ return getViewModel()->getDisplay();
+}
+
+// If round is true, if the position is on the right half of a character, the cursor
+// will be put to its right. If round is false, the cursor will always be put to the
+// character's left.
+
+S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+{
+ // Figure out which line we're nearest to.
+ LLRect visible_region = mScroller->getVisibleContentRect();
+
+ // binary search for line that starts before local_y
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom());
+
+ if (line_iter == mLineInfoList.end())
+ {
+ return getLength(); // past the end
+ }
+
+ S32 pos = getLength();
+ S32 start_x = mTextRect.mLeft + line_iter->mRect.mLeft;
+
+ segment_set_t::iterator line_seg_iter;
+ S32 line_seg_offset;
+ for(getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
+ line_seg_iter != mSegments.end();
+ ++line_seg_iter, line_seg_offset = 0)
+ {
+ const LLTextSegmentPtr segmentp = *line_seg_iter;
+
+ S32 segment_line_start = segmentp->getStart() + line_seg_offset;
+ S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start;
+ S32 text_width = segmentp->getWidth(line_seg_offset, segment_line_length);
+ if (local_x < start_x + text_width // cursor to left of right edge of text
+ || segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line
+ {
+ // Figure out which character we're nearest to.
+ S32 offset;
+ if (!segmentp->canEdit())
+ {
+ S32 segment_width = segmentp->getWidth(0, segmentp->getEnd() - segmentp->getStart());
+ if (round && local_x - start_x > segment_width / 2)
+ {
+ offset = segment_line_length;
+ }
+ else
+ {
+ offset = 0;
+ }
+ }
+ else
+ {
+ offset = segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round);
+ }
+ pos = segment_line_start + offset;
+ break;
+ }
+ start_x += text_width;
+ }
+
+ return pos;
+}
+
+LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
+{
+ LLRect local_rect;
+ if (mLineInfoList.empty())
+ {
+ local_rect = mTextRect;
+ local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
+ return local_rect;
+ }
+
+ // clamp pos to valid values
+ pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1);
+
+
+ // find line that contains cursor
+ line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
+
+ LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
+ local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft;
+ local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom);
+ local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom);
+
+ segment_set_t::iterator line_seg_iter;
+ S32 line_seg_offset;
+ segment_set_t::iterator cursor_seg_iter;
+ S32 cursor_seg_offset;
+ getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
+ getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset);
+
+ while(line_seg_iter != mSegments.end())
+ {
+ const LLTextSegmentPtr segmentp = *line_seg_iter;
+
+ if (line_seg_iter == cursor_seg_iter)
+ {
+ // cursor advanced to right based on difference in offset of cursor to start of line
+ local_rect.mLeft += segmentp->getWidth(line_seg_offset, cursor_seg_offset - line_seg_offset);
+
+ break;
+ }
+ else
+ {
+ // add remainder of current text segment to cursor position
+ local_rect.mLeft += segmentp->getWidth(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset);
+ // offset will be 0 for all segments after the first
+ line_seg_offset = 0;
+ // go to next text segment on this line
+ ++line_seg_iter;
+ }
+ }
+
+ local_rect.mRight = local_rect.mLeft;
+
+ return local_rect;
+}
+
+void LLTextBase::updateCursorXPos()
+{
+ // reset desired x cursor position
+ mDesiredXPixel = getLocalRectFromDocIndex(mCursorPos).mLeft;
+}
+
+
+void LLTextBase::startOfLine()
+{
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ setCursorPos(mCursorPos - offset);
+}
+
+void LLTextBase::endOfLine()
+{
+ S32 line = getLineNumFromDocIndex(mCursorPos);
+ S32 num_lines = getLineCount();
+ if (line + 1 >= num_lines)
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos( getLineStart(line + 1) - 1 );
+ }
+}
+
+void LLTextBase::startOfDoc()
+{
+ setCursorPos(0);
+}
+
+void LLTextBase::endOfDoc()
+{
+ setCursorPos(getLength());
+}
+
+void LLTextBase::changePage( S32 delta )
+{
+ const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10;
+ if (delta == 0) return;
+
+ LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+
+ if( delta == -1 )
+ {
+ mScroller->pageUp(PIXEL_OVERLAP_ON_PAGE_CHANGE);
+ }
+ else
+ if( delta == 1 )
+ {
+ mScroller->pageDown(PIXEL_OVERLAP_ON_PAGE_CHANGE);
+ }
+
+ if (getLocalRectFromDocIndex(mCursorPos) == cursor_rect)
+ {
+ // cursor didn't change apparent position, so move to top or bottom of document, respectively
+ if (delta < 0)
+ {
+ startOfDoc();
+ }
+ else
+ {
+ endOfDoc();
+ }
+ }
+ else
+ {
+ setCursorAtLocalPos(cursor_rect.getCenterX(), cursor_rect.getCenterY(), true, false);
+ }
+}
+
+// Picks a new cursor position based on the screen size of text being drawn.
+void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset )
+{
+ setCursorPos(getDocIndexFromLocalCoord(local_x, local_y, round), keep_cursor_offset);
+}
+
+
+void LLTextBase::changeLine( S32 delta )
+{
+ S32 line = getLineNumFromDocIndex(mCursorPos);
+
+ S32 new_line = line;
+ if( (delta < 0) && (line > 0 ) )
+ {
+ new_line = line - 1;
+ }
+ else if( (delta > 0) && (line < (getLineCount() - 1)) )
+ {
+ new_line = line + 1;
+ }
+
+ LLRect visible_region = mScroller->getVisibleContentRect();
+
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE);
+ setCursorPos(new_cursor_pos, true);
+}
+
+
+bool LLTextBase::setCursor(S32 row, S32 column)
+{
+ if (0 <= row && row < (S32)mLineInfoList.size())
+ {
+ S32 doc_pos = mLineInfoList[row].mDocIndexStart;
+ column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1);
+ doc_pos += column;
+ updateCursorXPos();
+
+ return setCursorPos(doc_pos);
+ }
+ return false;
+}
+
+
+bool LLTextBase::setCursorPos(S32 cursor_pos, bool keep_cursor_offset)
+{
+ S32 new_cursor_pos = cursor_pos;
+ if (new_cursor_pos != mCursorPos)
+ {
+ new_cursor_pos = getEditableIndex(new_cursor_pos, new_cursor_pos >= mCursorPos);
+ }
+
+ mCursorPos = llclamp(new_cursor_pos, 0, (S32)getLength());
+ needsScroll();
+ if (!keep_cursor_offset)
+ updateCursorXPos();
+ // did we get requested position?
+ return new_cursor_pos == cursor_pos;
+}
+
+// constraint cursor to editable segments of document
+S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
+{
+ segment_set_t::iterator segment_iter;
+ S32 offset;
+ getSegmentAndOffset(index, &segment_iter, &offset);
+ if (segment_iter == mSegments.end())
+ {
+ return 0;
+ }
+
+ LLTextSegmentPtr segmentp = *segment_iter;
+
+ if (segmentp->canEdit())
+ {
+ return segmentp->getStart() + offset;
+ }
+ else if (segmentp->getStart() < index && index < segmentp->getEnd())
+ {
+ // bias towards document end
+ if (increasing_direction)
+ {
+ return segmentp->getEnd();
+ }
+ // bias towards document start
+ else
+ {
+ return segmentp->getStart();
+ }
+ }
+ else
+ {
+ return index;
+ }
+}
+
+void LLTextBase::updateTextRect()
+{
+ LLRect old_text_rect = mTextRect;
+ mTextRect = mScroller->getContentWindowRect();
+ //FIXME: replace border with image?
+ if (mBorderVisible)
+ {
+ mTextRect.stretch(-1);
+ }
+ mTextRect.mLeft += mHPad;
+ mTextRect.mTop -= mVPad;
+ if (mTextRect != old_text_rect)
+ {
+ needsReflow();
+ }
+}
+
+
+void LLTextBase::startSelection()
+{
+ if( !mIsSelecting )
+ {
+ mIsSelecting = TRUE;
+ mSelectionStart = mCursorPos;
+ mSelectionEnd = mCursorPos;
+ }
+}
+
+void LLTextBase::endSelection()
+{
+ if( mIsSelecting )
+ {
+ mIsSelecting = FALSE;
+ mSelectionEnd = mCursorPos;
+ }
+}
+
//
// LLTextSegment
//
@@ -69,17 +2055,29 @@ S32 LLTextSegment::getMaxHeight() const { return 0; }
bool LLTextSegment::canEdit() const { return false; }
void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
void LLTextSegment::linkToDocument(LLTextBase*) {}
-void LLTextSegment::setHasMouseHover(bool hover) {}
const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
void LLTextSegment::setColor(const LLColor4 &color) {}
const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
void LLTextSegment::setStyle(const LLStyleSP &style) {}
void LLTextSegment::setToken( LLKeywordToken* token ) {}
LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
-BOOL LLTextSegment::getToolTip( std::string& msg ) const { return FALSE; }
void LLTextSegment::setToolTip( const std::string &msg ) {}
void LLTextSegment::dump() const {}
-
+BOOL LLTextSegment::handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleHover(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
+BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
+std::string LLTextSegment::getName() const { return ""; }
+void LLTextSegment::onMouseCaptureLost() {}
+void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}
+void LLTextSegment::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}
+BOOL LLTextSegment::hasMouseCapture() { return FALSE; }
//
// LLNormalTextSegment
@@ -89,7 +2087,6 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32
: LLTextSegment(start, end),
mStyle( style ),
mToken(NULL),
- mHasMouseHover(false),
mEditor(editor)
{
mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
@@ -98,7 +2095,6 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32
LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
: LLTextSegment(start, end),
mToken(NULL),
- mHasMouseHover(false),
mEditor(editor)
{
mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
@@ -115,21 +2111,25 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
- image->draw(draw_rect.mLeft, draw_rect.mTop-style_image_height,
+ // Center the image vertically
+ S32 image_bottom = draw_rect.getCenterY() - (style_image_height/2);
+ image->draw(draw_rect.mLeft, image_bottom,
style_image_width, style_image_height);
}
- return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect.mLeft, draw_rect.mBottom);
+ return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);
}
return draw_rect.mLeft;
}
// Draws a single text segment, reversing the color for selection if needed.
-F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y)
+F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect)
{
+ F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha;
+
const LLWString &text = mEditor.getWText();
- F32 right_x = x;
+ F32 right_x = rect.mLeft;
if (!mStyle->isVisible())
{
return right_x;
@@ -137,7 +2137,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
const LLFontGL* font = mStyle->getFont();
- LLColor4 color = mStyle->getColor();
+ LLColor4 color = mStyle->getColor() % alpha;
font = mStyle->getFont();
@@ -147,9 +2147,9 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 start = seg_start;
S32 end = llmin( selection_start, seg_end );
S32 length = end - start;
- font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.getWidth(), &right_x, mEditor.getUseEllipses());
}
- x = right_x;
+ rect.mLeft = (S32)ceil(right_x);
if( (selection_start < seg_end) && (selection_end > seg_start) )
{
@@ -158,18 +2158,18 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = llmin( selection_end, seg_end );
S32 length = end - start;
- font->render(text, start, x, y,
+ font->render(text, start, rect.mLeft, rect.mTop,
LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
- LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, rect.mRight, &right_x, mEditor.getUseEllipses());
}
- x = right_x;
+ rect.mLeft = (S32)ceil(right_x);
if( selection_end < seg_end )
{
// Draw normally
S32 start = llmax( selection_end, seg_start );
S32 end = seg_end;
S32 length = end - start;
- font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems());
+ font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.mRight, &right_x, mEditor.getUseEllipses());
}
return right_x;
}
@@ -179,21 +2179,54 @@ S32 LLNormalTextSegment::getMaxHeight() const
return mMaxHeight;
}
-BOOL LLNormalTextSegment::getToolTip(std::string& msg) const
+BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask)
{
+ if (getStyle() && getStyle()->isLink())
+ {
+ LLUrlAction::clickAction(getStyle()->getLinkHREF());
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ std::string msg;
// do we have a tooltip for a loaded keyword (for script editor)?
if (mToken && !mToken->getToolTip().empty())
{
const LLWString& wmsg = mToken->getToolTip();
- msg = wstring_to_utf8str(wmsg);
+ LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg));
return TRUE;
}
// or do we have an explicitly set tooltip (e.g., for Urls)
- if (! mTooltip.empty())
+ if (!mTooltip.empty())
{
- msg = mTooltip;
+ LLToolTipMgr::instance().show(mTooltip);
return TRUE;
}
+
return FALSE;
}
@@ -258,201 +2291,69 @@ void LLNormalTextSegment::dump() const
llendl;
}
-//////////////////////////////////////////////////////////////////////////
+
//
-// LLTextBase
+// LLInlineViewSegment
//
-LLTextBase::LLTextBase(const LLUICtrl::Params &p) :
- mHoverSegment(NULL),
- mDefaultFont(p.font),
- mParseHTML(TRUE),
- mPopupMenu(NULL)
-{
-}
-
-LLTextBase::~LLTextBase()
+LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end)
+: LLTextSegment(start, end),
+ mView(view)
{
- clearSegments();
-}
+}
-void LLTextBase::clearSegments()
+LLInlineViewSegment::~LLInlineViewSegment()
{
- setHoverSegment(NULL);
- mSegments.clear();
+ mView->die();
}
-void LLTextBase::setHoverSegment(LLTextSegmentPtr segment)
+S32 LLInlineViewSegment::getWidth(S32 first_char, S32 num_chars) const
{
- if (mHoverSegment)
+ if (first_char == 0 && num_chars == 0)
{
- mHoverSegment->setHasMouseHover(false);
- }
- if (segment)
- {
- segment->setHasMouseHover(true);
- }
- mHoverSegment = segment;
-}
-
-void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const
-{
- *seg_iter = getSegIterContaining(startpos);
- if (*seg_iter == mSegments.end())
- {
- *offsetp = 0;
+ return 0;
}
else
{
- *offsetp = startpos - (**seg_iter)->getStart();
+ return mView->getRect().getWidth();
}
}
-void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp )
+S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
- *seg_iter = getSegIterContaining(startpos);
- if (*seg_iter == mSegments.end())
+ if (line_offset != 0 && num_pixels < mView->getRect().getWidth())
{
- *offsetp = 0;
+ return 0;
}
else
{
- *offsetp = startpos - (**seg_iter)->getStart();
+ return mEnd - mStart;
}
}
-LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
+void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
- segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
- return it;
+ LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
+ LLRect doc_rect = editor.getDocumentPanel()->getRect();
+ mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
}
-LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const
+F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
- LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
- return it;
+ return (F32)(draw_rect.mLeft + mView->getRect().getWidth());
}
-// Finds the text segment (if any) at the give local screen position
-LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+S32 LLInlineViewSegment::getMaxHeight() const
{
- // Find the cursor position at the requested local screen position
- S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
- segment_set_t::iterator seg_iter = getSegIterContaining(offset);
- if (seg_iter != mSegments.end())
- {
- return *seg_iter;
- }
- else
- {
- return LLTextSegmentPtr();
- }
+ return mView->getRect().getHeight();
}
-BOOL LLTextBase::handleHoverOverUrl(S32 x, S32 y)
+void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
{
- setHoverSegment(NULL);
-
- // Check to see if we're over an HTML-style link
- LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if (cur_segment)
- {
- setHoverSegment(cur_segment);
-
- LLStyleSP style = cur_segment->getStyle();
- if (style && style->isLink())
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-BOOL LLTextBase::handleMouseUpOverUrl(S32 x, S32 y)
-{
- if (mParseHTML && mHoverSegment)
- {
- LLStyleSP style = mHoverSegment->getStyle();
- if (style && style->isLink())
- {
- LLUrlAction::clickAction(style->getLinkHREF());
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-BOOL LLTextBase::handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y)
-{
- // pop up a context menu for any Url under the cursor
- const LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
- if (cur_segment && cur_segment->getStyle() && cur_segment->getStyle()->isLink())
- {
- delete mPopupMenu;
- mPopupMenu = createUrlContextMenu(cur_segment->getStyle()->getLinkHREF());
- if (mPopupMenu)
- {
- mPopupMenu->show(x, y);
- LLMenuGL::showPopup(view, mPopupMenu, x, y);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
-{
- std::string tooltip_msg;
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if (cur_segment && cur_segment->getToolTip( tooltip_msg ) && view)
- {
- // Use a slop area around the cursor
- const S32 SLOP = 8;
- // Convert rect local to screen coordinates
- view->localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect_screen.mLeft),
- &(sticky_rect_screen.mBottom));
- sticky_rect_screen.mRight = sticky_rect_screen.mLeft + 2 * SLOP;
- sticky_rect_screen.mTop = sticky_rect_screen.mBottom + 2 * SLOP;
-
- LLToolTipMgr::instance().show(LLToolTipParams()
- .message(tooltip_msg)
- .sticky_rect(sticky_rect_screen));
- return TRUE;
- }
- return FALSE;
+ editor->removeDocumentChild(mView);
}
-LLContextMenu *LLTextBase::createUrlContextMenu(const std::string &in_url)
+void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
{
- // work out the XUI menu file to use for this url
- LLUrlMatch match;
- std::string url = in_url;
- if (! LLUrlRegistry::instance().findUrl(url, match))
- {
- return NULL;
- }
-
- std::string xui_file = match.getMenuName();
- if (xui_file.empty())
- {
- return NULL;
- }
-
- // set up the callbacks for all of the potential menu items, N.B. we
- // don't use const ref strings in callbacks in case url goes out of scope
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- registrar.add("Url.Open", boost::bind(&LLUrlAction::openURL, url));
- registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));
- registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
- registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
- registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
- registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
- registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
-
- // create and return the context menu from the XUI file
- return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
+ editor->addDocumentChild(mView);
}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 82b9f6a43f..d0287a99ca 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -35,13 +35,16 @@
#define LL_LLTEXTBASE_H
#include "v4color.h"
+#include "lleditmenuhandler.h"
#include "llstyle.h"
#include "llkeywords.h"
-#include "lluictrl.h"
+#include "llpanel.h"
#include <string>
#include <set>
+#include <boost/signals2.hpp>
+
class LLContextMenu;
class LLTextSegment;
@@ -52,64 +55,307 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
/// as LLTextEditor and LLTextBox. It implements shared functionality
/// such as Url highlighting and opening.
///
-class LLTextBase
+class LLTextBase
+: public LLUICtrl,
+ protected LLEditMenuHandler
{
public:
- LLTextBase(const LLUICtrl::Params &p);
- virtual ~LLTextBase();
+ struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
+ {
+ Alternative<F32> multiple;
+ Alternative<S32> pixels;
+ LineSpacingParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> cursor_color,
+ text_color,
+ text_readonly_color,
+ bg_readonly_color,
+ bg_writeable_color,
+ bg_focus_color;
+
+ Optional<bool> bg_visible,
+ border_visible,
+ track_end,
+ read_only,
+ hide_scrollbar,
+ clip_to_rect,
+ wrap,
+ use_ellipses,
+ allow_html,
+ parse_highlights;
+
+ Optional<S32> v_pad,
+ h_pad;
+
+ Optional<LineSpacingParams>
+ line_spacing;
+
+ Optional<S32> max_text_length;
+
+ Optional<LLFontGL::ShadowType> font_shadow;
+
+ Params();
+ };
+
+ // LLMouseHandler interface
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
+ // LLView interface
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ void draw();
+
+ // LLUICtrl interface
+ /*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
+ /*virtual*/ void clear();
+ /*virtual*/ void setColor( const LLColor4& c );
+ /*virtual*/ void setValue(const LLSD& value );
+ /*virtual*/ LLTextViewModel* getViewModel() const;
+
+ // LLEditMenuHandler interface
+ /*virtual*/ void deselect();
- /// specify the color to display Url hyperlinks in the text
- static void setLinkColor(LLColor4 color) { mLinkColor = color; }
+ // used by LLTextSegment layout code
+ bool getWordWrap() { return mWordWrap; }
+ bool getUseEllipses() { return mUseEllipses; }
+ bool truncate(); // returns true of truncation occurred
- /// enable/disable the automatic hyperlinking of Urls in the text
- void setParseHTML(BOOL parsing) { mParseHTML=parsing; }
+ // TODO: move into LLTextSegment?
+ void createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
- // public text editing virtual methods
- virtual LLWString getWText() const = 0;
- virtual BOOL allowsEmbeddedItems() const { return FALSE; }
- virtual BOOL getWordWrap() { return mWordWrap; }
- virtual S32 getLength() const = 0;
+
+ // Text accessors
+ // TODO: add optional style parameter
+ virtual void setText(const LLStringExplicit &utf8str); // uses default style
+ virtual std::string getText() const;
+
+ // wide-char versions
+ void setWText(const LLWString& text);
+ LLWString getWText() const;
+
+ void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
+
+ S32 getLength() const { return getWText().length(); }
+ S32 getLineCount() const { return mLineInfoList.size(); }
+
+ class DocumentPanel : public LLPanel
+ {
+ public:
+ DocumentPanel(const Params&);
+ };
+ void addDocumentChild(LLView* view);
+ void removeDocumentChild(LLView* view);
+ const DocumentPanel* getDocumentPanel() const { return mDocumentPanel; }
+ LLRect getTextRect() { return mTextRect; }
+ LLRect getContentsRect();
+
+ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+ LLRect getLocalRectFromDocIndex(S32 pos) const;
+
+ void setReadOnly(bool read_only) { mReadOnly = read_only; }
+ bool getReadOnly() { return mReadOnly; }
+
+ // cursor manipulation
+ bool setCursor(S32 row, S32 column);
+ bool setCursorPos(S32 cursor_pos, bool keep_cursor_offset = false);
+ void startOfLine();
+ void endOfLine();
+ void startOfDoc();
+ void endOfDoc();
+ void changePage( S32 delta );
+ void changeLine( S32 delta );
+
+ const LLFontGL* getDefaultFont() const { return mDefaultFont; }
+
+public:
+ // Fired when a URL link is clicked
+ commit_signal_t mURLClickSignal;
protected:
+ // helper structs
+ struct compare_bottom;
+ struct compare_top;
+ struct line_end_compare;
+ typedef std::vector<LLTextSegmentPtr> segment_vec_t;
+
+ // Abstract inner base class representing an undoable editor command.
+ // Concrete sub-classes can be defined for operations such as insert, remove, etc.
+ // Used as arguments to the execute() method below.
+ class TextCmd
+ {
+ public:
+ TextCmd( S32 pos, BOOL group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() )
+ : mPos(pos),
+ mGroupWithNext(group_with_next)
+ {
+ if (segment.notNull())
+ {
+ mSegments.push_back(segment);
+ }
+ }
+ virtual ~TextCmd() {}
+ virtual BOOL execute(LLTextBase* editor, S32* delta) = 0;
+ virtual S32 undo(LLTextBase* editor) = 0;
+ virtual S32 redo(LLTextBase* editor) = 0;
+ virtual BOOL canExtend(S32 pos) const { return FALSE; }
+ virtual void blockExtensions() {}
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; }
+ virtual BOOL hasExtCharValue( llwchar value ) const { return FALSE; }
+
+ // Defined here so they can access protected LLTextEditor editing methods
+ S32 insert(LLTextBase* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); }
+ S32 remove(LLTextBase* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); }
+ S32 overwrite(LLTextBase* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); }
+
+ S32 getPosition() const { return mPos; }
+ BOOL groupWithNext() const { return mGroupWithNext; }
+
+ protected:
+ const S32 mPos;
+ BOOL mGroupWithNext;
+ segment_vec_t mSegments;
+ };
+
struct compare_segment_end
{
bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const;
};
typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
- // routines to manage segments
- void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
- void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
- LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
+ // protected member variables
+ // List of offsets and segment index of the start of each line. Always has at least one node (0).
+ struct line_info
+ {
+ line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num);
+ S32 mDocIndexStart;
+ S32 mDocIndexEnd;
+ LLRect mRect;
+ S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
+ };
+ typedef std::vector<line_info> line_list_t;
+
+ // member functions
+ LLTextBase(const Params &p);
+ virtual ~LLTextBase();
+ void initFromParams(const Params& p);
+ LLStyle::Params getDefaultStyle();
+ virtual void onValueChange(S32 start, S32 end);
+
+ // draw methods
+ void drawSelectionBackground(); // draws the black box behind the selected text
+ void drawCursor();
+ void drawText();
+
+ // modify contents
+ S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
+ S32 removeStringNoUndo(S32 pos, S32 length);
+ S32 overwriteCharNoUndo(S32 pos, llwchar wc);
+ void appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep);
+
+
+ // manage segments
+ void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
+ void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
+ LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
segment_set_t::iterator getSegIterContaining(S32 index);
segment_set_t::const_iterator getSegIterContaining(S32 index) const;
- void clearSegments();
- void setHoverSegment(LLTextSegmentPtr segment);
+ void clearSegments();
+ void createDefaultSegment();
+ virtual void updateSegments();
+ void insertSegment(LLTextSegmentPtr segment_to_insert);
+
+ // manage lines
+ S32 getLineStart( S32 line ) const;
+ S32 getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getLineOffsetFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getFirstVisibleLine() const;
+ std::pair<S32, S32> getVisibleLines() const;
+ S32 getLeftOffset(S32 width);
+ void reflow(S32 start_index = 0);
- // event handling for Urls within the text field
- BOOL handleHoverOverUrl(S32 x, S32 y);
- BOOL handleMouseUpOverUrl(S32 x, S32 y);
- BOOL handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y);
- BOOL handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ // cursor
+ void updateCursorXPos();
+ void setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset=false );
+ S32 getEditableIndex(S32 index, bool increasing_direction); // constraint cursor to editable segments of document
+ void resetCursorBlink() { mCursorBlinkTimer.reset(); }
+ void updateScrollFromCursor();
- // pure virtuals that have to be implemented by any subclasses
- virtual S32 getLineCount() const = 0;
- virtual S32 getLineStart( S32 line ) const = 0;
- virtual S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const = 0;
+ // text selection
+ bool hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
+ void startSelection();
+ void endSelection();
- // protected member variables
- static LLUIColor mLinkColor;
- const LLFontGL *mDefaultFont;
- segment_set_t mSegments;
- LLTextSegmentPtr mHoverSegment;
- BOOL mParseHTML;
- BOOL mWordWrap;
+ // misc
+ void updateTextRect();
+ void needsReflow() { mReflowNeeded = TRUE; }
+ void needsScroll() { mScrollNeeded = TRUE; }
+ void replaceUrlLabel(const std::string &url, const std::string &label);
-private:
- // create a popup context menu for the given Url
- static LLContextMenu *createUrlContextMenu(const std::string &url);
+protected:
+ // text segmentation and flow
+ segment_set_t mSegments;
+ line_list_t mLineInfoList;
+ LLRect mTextRect; // The rect in which text is drawn. Excludes borders.
+ LLRect mContentsRect;
+
+ // colors
+ LLUIColor mCursorColor;
+ LLUIColor mFgColor;
+ LLUIColor mReadOnlyFgColor;
+ LLUIColor mWriteableBgColor;
+ LLUIColor mReadOnlyBgColor;
+ LLUIColor mFocusBgColor;
+
+ // cursor
+ S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
+ S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be
+ LLFrameTimer mCursorBlinkTimer; // timer that controls cursor blinking
+
+ // selection
+ S32 mSelectionStart;
+ S32 mSelectionEnd;
+
+ BOOL mIsSelecting; // Are we in the middle of a drag-select?
+
+ // configuration
+ S32 mHPad; // padding on left of text
+ S32 mVPad; // padding above text
+ LLFontGL::HAlign mHAlign;
+ F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding)
+ S32 mLineSpacingPixels; // padding between lines
+ const LLFontGL* mDefaultFont; // font that is used when none specified
+ LLFontGL::ShadowType mFontShadow;
+ bool mBorderVisible;
+ bool mParseHTML; // make URLs interactive
+ bool mParseHighlights; // highlight user-defined keywords
+ bool mWordWrap;
+ bool mUseEllipses;
+ bool mTrackEnd; // if true, keeps scroll position at end of document during resize
+ bool mReadOnly;
+ bool mClip;
+ S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
+
+ // support widgets
+ LLContextMenu* mPopupMenu;
+ DocumentPanel* mDocumentPanel;
+ class LLScrollContainer* mScroller;
+
+ // transient state
+ bool mReflowNeeded; // need to reflow text because of change to text contents or display region
+ bool mScrollNeeded; // need to change scroll region because of change to cursor position
+ S32 mScrollIndex; // index of first character to keep visible in scroll region
- LLContextMenu *mPopupMenu;
};
///
@@ -118,7 +364,7 @@ private:
/// includes a start/end offset from the start of the string, a
/// style to render with, an optional tooltip, etc.
///
-class LLTextSegment : public LLRefCount
+class LLTextSegment : public LLRefCount, public LLMouseHandler
{
public:
LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
@@ -134,17 +380,32 @@ public:
virtual void unlinkFromDocument(class LLTextBase* editor);
virtual void linkToDocument(class LLTextBase* editor);
- virtual void setHasMouseHover(bool hover);
virtual const LLColor4& getColor() const;
virtual void setColor(const LLColor4 &color);
virtual const LLStyleSP getStyle() const;
virtual void setStyle(const LLStyleSP &style);
virtual void setToken( LLKeywordToken* token );
virtual LLKeywordToken* getToken() const;
- virtual BOOL getToolTip( std::string& msg ) const;
virtual void setToolTip(const std::string& tooltip);
virtual void dump() const;
+ // LLMouseHandler interface
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ /*virtual*/ std::string getName() const;
+ /*virtual*/ void onMouseCaptureLost();
+ /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
+ /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
+ /*virtual*/ BOOL hasMouseCapture();
+
S32 getStart() const { return mStart; }
void setStart(S32 start) { mStart = start; }
S32 getEnd() const { return mEnd; }
@@ -167,7 +428,6 @@ public:
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
/*virtual*/ S32 getMaxHeight() const;
/*virtual*/ bool canEdit() const { return true; }
- /*virtual*/ void setHasMouseHover(bool hover) { mHasMouseHover = hover; }
/*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
/*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
/*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
@@ -178,15 +438,20 @@ public:
/*virtual*/ void setToolTip(const std::string& tooltip);
/*virtual*/ void dump() const;
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
protected:
- F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y);
+ F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect);
+protected:
class LLTextBase& mEditor;
- LLStyleSP mStyle;
- S32 mMaxHeight;
- LLKeywordToken* mToken;
- bool mHasMouseHover;
- std::string mTooltip;
+ LLStyleSP mStyle;
+ S32 mMaxHeight;
+ LLKeywordToken* mToken;
+ std::string mTooltip;
};
class LLIndexSegment : public LLTextSegment
@@ -195,4 +460,23 @@ public:
LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {}
};
+class LLInlineViewSegment : public LLTextSegment
+{
+public:
+ LLInlineViewSegment(LLView* widget, S32 start, S32 end);
+ ~LLInlineViewSegment();
+ /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ /*virtual*/ void updateLayout(const class LLTextBase& editor);
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtuaL*/ S32 getMaxHeight() const;
+ /*virtual*/ bool canEdit() const { return false; }
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor);
+ /*virtual*/ void linkToDocument(class LLTextBase* editor);
+
+private:
+ LLView* mView;
+};
+
+
#endif
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 132bef0296..3feca136be 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -40,47 +40,10 @@
static LLDefaultChildRegistry::Register<LLTextBox> r("text");
-LLTextBox::Params::Params()
-: text_color("text_color"),
- length("length"),
- type("type"),
- border_visible("border_visible", false),
- border_drop_shadow_visible("border_drop_shadow_visible", false),
- bg_visible("bg_visible", false),
- use_ellipses("use_ellipses"),
- word_wrap("word_wrap", false),
- drop_shadow_visible("drop_shadow_visible"),
- disabled_color("disabled_color"),
- background_color("background_color"),
- v_pad("v_pad", 0),
- h_pad("h_pad", 0),
- line_spacing("line_spacing", 0),
- text("text"),
- font_shadow("font_shadow", LLFontGL::NO_SHADOW)
-{}
-
LLTextBox::LLTextBox(const LLTextBox::Params& p)
-: LLUICtrl(p),
- LLTextBase(p),
- mBackgroundVisible( p.bg_visible ),
- mBorderVisible( p.border_visible ),
- mShadowType( p.font_shadow ),
- mBorderDropShadowVisible( p.border_drop_shadow_visible ),
- mUseEllipses( p.use_ellipses ),
- mHPad(p.h_pad),
- mVPad(p.v_pad),
- mVAlign( LLFontGL::TOP ),
- mClickedCallback(NULL),
- mTextColor(p.text_color()),
- mDisabledColor(p.disabled_color()),
- mBackgroundColor(p.background_color()),
- mHAlign(p.font_halign),
- mLineSpacing(p.line_spacing),
- mDidWordWrap(FALSE)
-{
- mWordWrap = p.word_wrap;
- setText( p.text() );
-}
+: LLTextBase(p),
+ mClickedCallback(NULL)
+{}
BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -101,6 +64,11 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
}
}
+ if (!handled)
+ {
+ handled = LLTextBase::handleMouseDown(x, y, mask);
+ }
+
return handled;
}
@@ -125,528 +93,60 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
}
// handle clicks on Urls in the textbox first
- if (! handleMouseUpOverUrl(x, y))
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+
+ // DO THIS AT THE VERY END to allow the button to be destroyed
+ // as a result of being clicked. If mouseup in the widget,
+ // it's been clicked
+ if (mClickedCallback && !handled)
{
- // DO THIS AT THE VERY END to allow the button to be destroyed
- // as a result of being clicked. If mouseup in the widget,
- // it's been clicked
- if (mClickedCallback && ! handled)
- {
- mClickedCallback();
- }
+ mClickedCallback();
}
}
return handled;
}
-BOOL LLTextBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- // pop up a context menu for any Url under the cursor
- return handleRightMouseDownOverUrl(this, x, y);
-}
-
-BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
-{
- // Check to see if we're over an HTML-style link
- if (handleHoverOverUrl(x, y))
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- return TRUE;
- }
-
- return LLView::handleHover(x,y,mask);
-}
-
-BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
-{
- if (handleToolTipForUrl(this, x, y, msg, sticky_rect_screen))
- {
- return TRUE;
- }
-
- return LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen);
-}
-
void LLTextBox::setText(const LLStringExplicit& text)
{
- if(mWordWrap && !mDidWordWrap)
- {
- setWrappedText(text);
- }
- else
- {
- mText.assign(text);
- updateDisplayTextAndSegments();
- }
-}
-
-void LLTextBox::setLineLengths()
-{
- mLineLengthList.clear();
+ // does string argument insertion
+ mText.assign(text);
- std::string::size_type cur = 0;
- std::string::size_type len = mDisplayText.size();
-
- while (cur < len)
- {
- std::string::size_type end = mDisplayText.find('\n', cur);
- std::string::size_type runLen;
-
- if (end == std::string::npos)
- {
- runLen = len - cur;
- cur = len;
- }
- else
- {
- runLen = end - cur;
- cur = end + 1; // skip the new line character
- }
-
- mLineLengthList.push_back( (S32)runLen );
- }
-}
-
-LLWString LLTextBox::wrapText(const LLWString &wtext, S32 &hoffset, S32 &line_num, F32 max_width)
-{
- LLWString final_wtext;
-
- LLWString::size_type cur = 0;
- LLWString::size_type len = wtext.size();
- while (cur < len)
- {
- LLWString::size_type end = wtext.find('\n', cur);
- if (end == LLWString::npos)
- {
- end = len;
- }
-
- bool charsRemaining = true;
- LLWString::size_type runLen = end - cur;
- if (runLen > 0)
- {
- // work out how many chars can fit onto the current line
- LLWString run(wtext, cur, runLen);
- LLWString::size_type useLen =
- mDefaultFont->maxDrawableChars(run.c_str(), max_width-hoffset, runLen, TRUE);
- charsRemaining = (cur + useLen < len);
-
- // try to break lines on word boundaries
- if (useLen < run.size())
- {
- LLWString::size_type prev_use_len = useLen;
- while (useLen > 0 && ! isspace(run[useLen-1]) && ! ispunct(run[useLen-1]))
- {
- --useLen;
- }
- if (useLen == 0)
- {
- useLen = prev_use_len;
- }
- }
-
- // add the chars that could fit onto one line to our result
- final_wtext.append(wtext, cur, useLen);
- cur += useLen;
- hoffset += mDefaultFont->getWidth(run.substr(0, useLen).c_str());
-
- // abort if not enough room to add any more characters
- if (useLen == 0)
- {
- break;
- }
- }
-
- if (charsRemaining)
- {
- if (wtext[cur] == '\n')
- {
- cur += 1;
- }
- final_wtext += '\n';
- hoffset = 0;
- line_num += 1;
- }
- }
-
- return final_wtext;
-}
-
-void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
-{
- mDidWordWrap = TRUE;
- setText(wstring_to_utf8str(getWrappedText(in_text, max_width)));
-}
-
-LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_width)
-{
- //
- // we don't want to wrap Urls otherwise we won't be able to detect their
- // presence for hyperlinking. So we look for all Urls, and then word wrap
- // the text before and after, but never break a Url in the middle. We
- // also need to consider that the Url will be displayed as a label (not
- // necessary the actual Url string).
- //
-
- if (max_width < 0.0f)
- {
- max_width = (F32)getRect().getWidth();
- }
-
- LLWString wtext = utf8str_to_wstring(in_text);
- LLWString final_wtext;
- S32 line_num = 1;
- S32 hoffset = 0;
-
- // find the next Url in the text string
- LLUrlMatch match;
- while ( LLUrlRegistry::instance().findUrl(wtext, match))
- {
- S32 start = match.getStart();
- S32 end = match.getEnd() + 1;
-
- // perform word wrap on the text before the Url
- final_wtext += wrapText(wtext.substr(0, start), hoffset, line_num, max_width);
-
- // add the Url (but compute width based on its label)
- S32 label_width = mDefaultFont->getWidth(match.getLabel());
- if (hoffset > 0 && hoffset + label_width > max_width)
- {
- final_wtext += '\n';
- line_num++;
- hoffset = 0;
- }
- final_wtext += wtext.substr(start, end-start);
- hoffset += label_width;
- if (hoffset > max_width)
- {
- final_wtext += '\n';
- line_num++;
- hoffset = 0;
- // eat any leading whitespace on the next line
- while (isspace(wtext[end]) && end < (S32)wtext.size())
- {
- end++;
- }
- }
-
- // move on to the rest of the text after the Url
- wtext = wtext.substr(end, wtext.size() - end + 1);
- }
-
- final_wtext += wrapText(wtext, hoffset, line_num, max_width);
- return final_wtext;
+ LLTextBase::setText(mText.getString());
}
S32 LLTextBox::getTextPixelWidth()
{
- S32 max_line_width = 0;
- if( mLineLengthList.size() > 0 )
- {
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = mLineLengthList.begin();
- iter != mLineLengthList.end(); ++iter)
- {
- S32 line_length = *iter;
- S32 line_width = mDefaultFont->getWidth( mDisplayText.c_str(), cur_pos, line_length );
- if( line_width > max_line_width )
- {
- max_line_width = line_width;
- }
- cur_pos += line_length+1;
- }
- }
- else
- {
- max_line_width = mDefaultFont->getWidth(mDisplayText.c_str());
- }
- return max_line_width;
+ return getContentsRect().getWidth();
}
S32 LLTextBox::getTextPixelHeight()
{
- S32 num_lines = mLineLengthList.size();
- if( num_lines < 1 )
- {
- num_lines = 1;
- }
- return (S32)(num_lines * mDefaultFont->getLineHeight());
-}
-
-void LLTextBox::setValue(const LLSD& value )
-{
- mDidWordWrap = FALSE;
- setText(value.asString());
+ return getContentsRect().getHeight();
}
BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
{
mText.setArg(key, text);
- updateDisplayTextAndSegments();
- return TRUE;
-}
-
-void LLTextBox::draw()
-{
- F32 alpha = getDrawContext().mAlpha;
+ LLTextBase::setText(mText.getString());
- if (mBorderVisible)
- {
- gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
- }
-
- if( mBorderDropShadowVisible )
- {
- static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
- static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
- gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- color_drop_shadow % alpha, drop_shadow_tooltip);
- }
-
- if (mBackgroundVisible)
- {
- LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- gl_rect_2d( r, mBackgroundColor.get() % alpha );
- }
-
- S32 text_x = 0;
- switch( mHAlign )
- {
- case LLFontGL::LEFT:
- text_x = mHPad;
- break;
- case LLFontGL::HCENTER:
- text_x = getRect().getWidth() / 2;
- break;
- case LLFontGL::RIGHT:
- text_x = getRect().getWidth() - mHPad;
- break;
- }
-
- S32 text_y = getRect().getHeight() - mVPad;
-
- if ( getEnabled() )
- {
- drawText( text_x, text_y, mDisplayText, mTextColor.get() );
- }
- else
- {
- drawText( text_x, text_y, mDisplayText, mDisabledColor.get() );
- }
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
+ return TRUE;
}
-void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- // reparse line lengths (don't need to recalculate the display text)
- setLineLengths();
- LLView::reshape(width, height, called_from_parent);
-}
-
-void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color )
-{
- F32 alpha = getDrawContext().mAlpha;
- if (mSegments.size() > 1)
- {
- // we have Urls (or other multi-styled segments)
- drawTextSegments(x, y, text);
- }
- else if( mLineLengthList.empty() )
- {
- // simple case of 1 line of text in one style
- mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha,
- mHAlign, mVAlign,
- 0,
- mShadowType,
- S32_MAX, getRect().getWidth(), NULL, mUseEllipses);
- }
- else
- {
- // simple case of multiple lines of text, all in the same style
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = mLineLengthList.begin();
- iter != mLineLengthList.end(); ++iter)
- {
- S32 line_length = *iter;
- mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha,
- mHAlign, mVAlign,
- 0,
- mShadowType,
- line_length, getRect().getWidth(), NULL, mUseEllipses );
- cur_pos += line_length + 1;
- S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing;
- y -= line_height;
- if(y < line_height)
- break;
- }
- }
-}
void LLTextBox::reshapeToFitText()
{
- // wrap remaining lines that did not fit on call to setWrappedText()
- setLineLengths();
+ reflow();
S32 width = getTextPixelWidth();
S32 height = getTextPixelHeight();
- reshape( width + 2 * mHPad, height + 2 * mVPad );
-}
-
-S32 LLTextBox::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
-{
- // Returns the character offset for the character under the local (x, y) coordinate.
- // When round is true, if the position is on the right half of a character, the cursor
- // will be put to its right. If round is false, the cursor will always be put to the
- // character's left.
-
- LLRect rect = getLocalRect();
- rect.mLeft += mHPad;
- rect.mRight -= mHPad;
- rect.mTop += mVPad;
- rect.mBottom -= mVPad;
-
- // Figure out which line we're nearest to.
- S32 total_lines = getLineCount();
- S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing;
- S32 line = (rect.mTop - 1 - local_y) / line_height;
- if (line >= total_lines)
- {
- return getLength(); // past the end
- }
-
- line = llclamp( line, 0, total_lines );
- S32 line_start = getLineStart(line);
- S32 next_start = getLineStart(line+1);
- S32 line_end = (next_start != line_start) ? next_start - 1 : getLength();
- if (line_start == -1)
- {
- return 0;
- }
-
- S32 line_len = line_end - line_start;
- S32 pos = mDefaultFont->charFromPixelOffset(mDisplayText.c_str(), line_start,
- (F32)(local_x - rect.mLeft),
- (F32)rect.getWidth(),
- line_len, round);
-
- return line_start + pos;
+ reshape( width + 2 * mHPad, height + 2 * mVPad, FALSE );
}
-S32 LLTextBox::getLineStart( S32 line ) const
-{
- line = llclamp(line, 0, getLineCount()-1);
-
- S32 result = 0;
- for (int i = 0; i < line; i++)
- {
- result += mLineLengthList[i] + 1 /* add newline */;
- }
-
- return result;
-}
-
-void LLTextBox::updateDisplayTextAndSegments()
-{
- // remove any previous segment list
- clearSegments();
-
- // if URL parsing is turned off, then not much to bo
- if (! mParseHTML)
- {
- mDisplayText = mText.getWString();
- setLineLengths();
- return;
- }
-
- // create unique text segments for Urls
- mDisplayText.clear();
- S32 end = 0;
- LLUrlMatch match;
- LLWString text = mText.getWString();
-
- // find the next Url in the text string
- while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) )
- {
- // work out the char offset for the start/end of the url
- S32 url_start = match.getStart();
- S32 url_end = match.getEnd();
-
- // and the char offset for the label in the display text
- S32 seg_start = mDisplayText.size();
- S32 start = seg_start + url_start;
- S32 end = start + match.getLabel().size();
-
- // create a segment for the text before the Url
- mSegments.insert(new LLNormalTextSegment(new LLStyle(), seg_start, start, *this));
- mDisplayText += text.substr(0, url_start);
-
- // create a segment for the Url text
- LLStyleSP html(new LLStyle);
- html->setVisible(true);
- html->setColor(mLinkColor);
- html->mUnderline = TRUE;
- html->setLinkHREF(match.getUrl());
-
- LLNormalTextSegment *html_seg = new LLNormalTextSegment(html, start, end, *this);
- html_seg->setToolTip(match.getTooltip());
-
- mSegments.insert(html_seg);
- mDisplayText += utf8str_to_wstring(match.getLabel());
-
- // move on to the rest of the text after the Url
- text = text.substr(url_end+1, text.size() - url_end);
- }
-
- // output a segment for the remaining text
- if (text.size() > 0)
- {
- mSegments.insert(new LLNormalTextSegment(new LLStyle(), end, end + text.size(), *this));
- mDisplayText += text;
- }
-
- // strip whitespace from the end of the text
- while (mDisplayText.size() > 0 && isspace(mDisplayText[mDisplayText.size()-1]))
- {
- mDisplayText = mDisplayText.substr(0, mDisplayText.size() - 1);
-
- segment_set_t::iterator it = getSegIterContaining(mDisplayText.size());
- if (it != mSegments.end())
- {
- LLTextSegmentPtr seg = *it;
- seg->setEnd(seg->getEnd()-1);
- }
- }
-
- // we may have changed the line lengths, so recalculate them
- setLineLengths();
-}
void LLTextBox::onUrlLabelUpdated(const std::string &url, const std::string &label)
{
- if (mDidWordWrap)
- {
- // re-word wrap as the url label lengths may have changed
- setWrappedText(mText.getString());
- }
- else
- {
- // or just update the display text with the latest Url labels
- updateDisplayTextAndSegments();
- }
+ needsReflow();
}
bool LLTextBox::isClickable() const
@@ -676,89 +176,3 @@ bool LLTextBox::isClickable() const
return false;
}
-void LLTextBox::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text)
-{
- F32 alpha = getDrawContext().mAlpha;
-
- const S32 text_len = text.length();
- if (text_len <= 0)
- {
- return;
- }
-
- S32 cur_line = 0;
- S32 num_lines = getLineCount();
- S32 line_start = getLineStart(cur_line);
- S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing;
- F32 text_y = (F32) init_y;
- segment_set_t::iterator cur_seg = mSegments.begin();
-
- // render a line of text at a time
- const LLRect textRect = getLocalRect();
- while((textRect.mBottom <= text_y) && (cur_line < num_lines))
- {
- S32 next_start = -1;
- S32 line_end = text_len;
-
- if ((cur_line + 1) < num_lines)
- {
- next_start = getLineStart(cur_line + 1);
- line_end = next_start;
- }
- if ( text[line_end-1] == '\n' )
- {
- --line_end;
- }
-
- // render all segments on this line
- F32 text_x = init_x;
- S32 seg_start = line_start;
- while (seg_start < line_end && cur_seg != mSegments.end())
- {
- // move to the next segment (or continue the previous one)
- LLTextSegment *cur_segment = *cur_seg;
- while (cur_segment->getEnd() <= seg_start)
- {
- if (++cur_seg == mSegments.end())
- {
- return;
- }
- cur_segment = *cur_seg;
- }
-
- // Draw a segment within the line
- S32 clipped_end = llmin( line_end, cur_segment->getEnd() );
- S32 clipped_len = clipped_end - seg_start;
- if( clipped_len > 0 )
- {
- LLStyleSP style = cur_segment->getStyle();
- if (style && style->isVisible())
- {
- // work out the color for the segment
- LLColor4 color ;
- if (getEnabled())
- {
- color = style->isLink() ? mLinkColor.get() : mTextColor.get();
- }
- else
- {
- color = mDisabledColor.get();
- }
- color = color % alpha;
-
- // render a single line worth for this segment
- mDefaultFont->render(text, seg_start, text_x, text_y, color,
- mHAlign, mVAlign, 0, mShadowType, clipped_len,
- textRect.getWidth(), &text_x, mUseEllipses);
- }
-
- seg_start += clipped_len;
- }
- }
-
- // move down one line
- text_y -= (F32)line_height;
- line_start = next_start;
- cur_line++;
- }
-}
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index 0517325e70..f8c4447b62 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -33,47 +33,21 @@
#ifndef LL_LLTEXTBOX_H
#define LL_LLTEXTBOX_H
-#include "lluictrl.h"
#include "v4color.h"
#include "llstring.h"
#include "lluistring.h"
#include "lltextbase.h"
class LLTextBox :
- public LLTextBase,
- public LLUICtrl
+ public LLTextBase
{
public:
// *TODO: Add callback to Params
typedef boost::function<void (void)> callback_t;
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
- {
- Optional<std::string> text;
-
- Optional<bool> border_visible,
- border_drop_shadow_visible,
- bg_visible,
- use_ellipses,
- word_wrap;
-
- Optional<LLFontGL::ShadowType> font_shadow;
-
- Ignored drop_shadow_visible,
- type,
- length;
-
- Optional<LLUIColor> text_color,
- disabled_color,
- background_color;
-
- Optional<S32> v_pad,
- h_pad,
- line_spacing;
-
- Params();
- };
+ struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
+ {};
protected:
LLTextBox(const Params&);
@@ -82,84 +56,33 @@ protected:
public:
virtual ~LLTextBox() {}
- virtual void draw();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
-
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
- void setColor( const LLColor4& c ) { mTextColor = c; }
- void setDisabledColor( const LLColor4& c) { mDisabledColor = c; }
- void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; }
-
- void setText( const LLStringExplicit& text );
- void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.f); // -1 means use existing control width
- void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
+ /*virtual*/ void setText( const LLStringExplicit& text );
- void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
- void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
- void setBorderDropshadowVisible(BOOL visible){ mBorderDropShadowVisible = visible; }
- void setHPad(S32 pixels) { mHPad = pixels; }
- void setVPad(S32 pixels) { mVPad = pixels; }
void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button
- const LLFontGL* getFont() const { return mDefaultFont; }
- void setFont(const LLFontGL* font) { mDefaultFont = font; }
+ //const LLFontGL* getFont() const { return mDefaultFont; }
+ //void setFont(const LLFontGL* font) { mDefaultFont = font; }
void reshapeToFitText();
- const std::string& getText() const { return mText.getString(); }
- LLWString getWText() const { return mDisplayText; }
+ //const std::string& getText() const { return mText.getString(); }
S32 getTextPixelWidth();
S32 getTextPixelHeight();
- S32 getLength() const { return mDisplayText.length(); }
- virtual void setValue(const LLSD& value );
virtual LLSD getValue() const { return LLSD(getText()); }
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
protected:
- S32 getLineCount() const { return mLineLengthList.size(); }
- S32 getLineStart( S32 line ) const;
- S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
- LLWString getWrappedText(const LLStringExplicit& in_text, F32 max_width = -1.f);
- void setLineLengths();
- void updateDisplayTextAndSegments();
- virtual void drawText(S32 x, S32 y, const LLWString &text, const LLColor4& color );
void onUrlLabelUpdated(const std::string &url, const std::string &label);
bool isClickable() const;
- LLWString wrapText(const LLWString &wtext, S32 &hoffset, S32 &line_num, F32 max_width);
- void drawTextSegments(S32 x, S32 y, const LLWString &text);
-
- LLUIString mText;
- LLWString mDisplayText;
- LLUIColor mTextColor;
- LLUIColor mDisabledColor;
- LLUIColor mBackgroundColor;
- LLUIColor mBorderColor;
-
- BOOL mBackgroundVisible;
- BOOL mBorderVisible;
- BOOL mDidWordWrap;
-
- LLFontGL::ShadowType mShadowType;
- BOOL mBorderDropShadowVisible;
- BOOL mUseEllipses;
-
- S32 mLineSpacing;
-
- S32 mHPad;
- S32 mVPad;
- LLFontGL::HAlign mHAlign;
- LLFontGL::VAlign mVAlign;
- std::vector<S32> mLineLengthList;
- callback_t mClickedCallback;
+ LLUIString mText;
+ callback_t mClickedCallback;
};
#endif
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 39f09b297f..997c5b8fa8 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -77,106 +77,31 @@ static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor");
//
const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32;
const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4;
-const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
-const S32 CURSOR_THICKNESS = 2;
const S32 SPACES_PER_TAB = 4;
-
-// helper functors
-struct LLTextEditor::compare_bottom
-{
- bool operator()(const S32& a, const LLTextEditor::line_info& b) const
- {
- return a > b.mBottom; // bottom of a is higher than bottom of b
- }
-
- bool operator()(const LLTextEditor::line_info& a, const S32& b) const
- {
- return a.mBottom > b; // bottom of a is higher than bottom of b
- }
-
- bool operator()(const LLTextEditor::line_info& a, const LLTextEditor::line_info& b) const
- {
- return a.mBottom > b.mBottom; // bottom of a is higher than bottom of b
- }
-
-};
-
-// helper functors
-struct LLTextEditor::compare_top
-{
- bool operator()(const S32& a, const LLTextEditor::line_info& b) const
- {
- return a > b.mTop; // top of a is higher than top of b
- }
-
- bool operator()(const LLTextEditor::line_info& a, const S32& b) const
- {
- return a.mTop > b; // top of a is higher than top of b
- }
-
- bool operator()(const LLTextEditor::line_info& a, const LLTextEditor::line_info& b) const
- {
- return a.mTop > b.mTop; // top of a is higher than top of b
- }
-};
-
-struct LLTextEditor::line_end_compare
-{
- bool operator()(const S32& pos, const LLTextEditor::line_info& info) const
- {
- return (pos < info.mDocIndexEnd);
- }
-
- bool operator()(const LLTextEditor::line_info& info, const S32& pos) const
- {
- return (info.mDocIndexEnd < pos);
- }
-
- bool operator()(const LLTextEditor::line_info& a, const LLTextEditor::line_info& b) const
- {
- return (a.mDocIndexEnd < b.mDocIndexEnd);
- }
-
-};
-
-//
-// DocumentPanel
-//
-
-class DocumentPanel : public LLPanel
-{
-public:
- DocumentPanel(const Params&);
-};
-
-DocumentPanel::DocumentPanel(const Params& p)
-: LLPanel(p)
-{}
-
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdInsert : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdInsert : public LLTextBase::TextCmd
{
public:
- LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
- : LLTextCmd(pos, group_with_next, segment), mWString(ws)
+ TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(ws)
{
}
- virtual ~LLTextCmdInsert() {}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual ~TextCmdInsert() {}
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
*delta = insert(editor, getPosition(), mWString );
LLWStringUtil::truncate(mWString, *delta);
//mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), mWString.length() );
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
insert(editor, getPosition(), mWString );
return getPosition() + mWString.length();
@@ -187,11 +112,11 @@ private:
};
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdAddChar : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdAddChar : public LLTextBase::TextCmd
{
public:
- LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
- : LLTextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
+ TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
{
}
virtual void blockExtensions()
@@ -205,14 +130,14 @@ public:
return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
*delta = insert(editor, getPosition(), mWString);
LLWStringUtil::truncate(mWString, *delta);
//mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
- virtual BOOL extendAndExecute( LLTextEditor* editor, S32 pos, llwchar wc, S32* delta )
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
{
LLWString ws;
ws += wc;
@@ -224,12 +149,12 @@ public:
}
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), mWString.length() );
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
insert(editor, getPosition(), mWString );
return getPosition() + mWString.length();
@@ -243,25 +168,25 @@ private:
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdOverwriteChar : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd
{
public:
- LLTextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
- : LLTextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
+ TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
+ : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
- mOldChar = editor->getWChar(getPosition());
+ mOldChar = editor->getWText()[getPosition()];
overwrite(editor, getPosition(), mChar);
*delta = 0;
return TRUE;
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
overwrite(editor, getPosition(), mOldChar);
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
overwrite(editor, getPosition(), mChar);
return getPosition()+1;
@@ -274,26 +199,26 @@ private:
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdRemove : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd
{
public:
- LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
- LLTextCmd(pos, group_with_next), mLen(len)
+ TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
+ TextCmd(pos, group_with_next), mLen(len)
{
std::swap(mSegments, segments);
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
- mWString = editor->getWSubString(getPosition(), mLen);
+ mWString = editor->getWText().substr(getPosition(), mLen);
*delta = remove(editor, getPosition(), mLen );
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
insert(editor, getPosition(), mWString);
return getPosition() + mWString.length();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
remove(editor, getPosition(), mLen );
return getPosition();
@@ -307,138 +232,61 @@ private:
///////////////////////////////////////////////////////////////////
LLTextEditor::Params::Params()
: default_text("default_text"),
- max_text_length("max_length", 255),
- read_only("read_only", false),
embedded_items("embedded_items", false),
- hide_scrollbar("hide_scrollbar"),
- hide_border("hide_border", false),
- word_wrap("word_wrap", false),
ignore_tab("ignore_tab", true),
- track_bottom("track_bottom", false),
handle_edit_keys_directly("handle_edit_keys_directly", false),
show_line_numbers("show_line_numbers", false),
- cursor_color("cursor_color"),
default_color("default_color"),
- text_color("text_color"),
- text_readonly_color("text_readonly_color"),
- bg_readonly_color("bg_readonly_color"),
- bg_writeable_color("bg_writeable_color"),
- bg_focus_color("bg_focus_color"),
- link_color("link_color"),
- commit_on_focus_lost("commit_on_focus_lost", false),
- length("length"), // ignored
- type("type"), // ignored
- is_unicode("is_unicode")// ignored
+ commit_on_focus_lost("commit_on_focus_lost", false)
{}
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
- LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
LLTextBase(p),
- mMaxTextByteLength( p.max_text_length ),
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
mLastCmd( NULL ),
- mCursorPos( 0 ),
- mIsSelecting( FALSE ),
- mSelectionStart( 0 ),
- mSelectionEnd( 0 ),
- mOnScrollEndData( NULL ),
- mCursorColor( p.cursor_color() ),
- mFgColor( p.text_color() ),
mDefaultColor( p.default_color() ),
- mReadOnlyFgColor( p.text_readonly_color() ),
- mWriteableBgColor( p.bg_writeable_color() ),
- mReadOnlyBgColor( p.bg_readonly_color() ),
- mFocusBgColor( p.bg_focus_color() ),
- mLinkColor( p.link_color() ),
- mReadOnly(p.read_only),
mShowLineNumbers ( p.show_line_numbers ),
mCommitOnFocusLost( p.commit_on_focus_lost),
- mTrackBottom( p.track_bottom ),
mAllowEmbeddedItems( p.embedded_items ),
mHandleEditKeysDirectly( p.handle_edit_keys_directly ),
mMouseDownX(0),
mMouseDownY(0),
- mLastSelectionX(-1),
- mReflowNeeded(FALSE),
- mScrollNeeded(FALSE),
- mLastSelectionY(-1),
- mParseHighlights(FALSE),
- mTabsToNextField(p.ignore_tab),
- mScrollIndex(-1)
+ mTabsToNextField(p.ignore_tab)
{
- static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
-
- mWordWrap = p.word_wrap;
mDefaultFont = p.font;
- mParseHTML = FALSE;
mSourceID.generate();
- // reset desired x cursor position
- mDesiredXPixel = -1;
-
- LLScrollContainer::Params scroll_params;
- scroll_params.name = "text scroller";
- scroll_params.rect = getLocalRect();
- scroll_params.follows.flags = FOLLOWS_ALL;
- scroll_params.is_opaque = false;
- scroll_params.mouse_opaque = false;
- scroll_params.min_auto_scroll_rate = 200;
- scroll_params.max_auto_scroll_rate = 800;
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
- addChild(mScroller);
-
- LLPanel::Params panel_params;
- panel_params.name = "text_contents";
- panel_params.rect = LLRect(0, 500, 500, 0);
- panel_params.background_visible = true;
- panel_params.background_opaque = true;
- panel_params.mouse_opaque = false;
-
- mDocumentPanel = LLUICtrlFactory::create<DocumentPanel>(panel_params);
- mScroller->addChild(mDocumentPanel);
-
- updateTextRect();
-
- static LLUICachedControl<S32> text_editor_border ("UITextEditorBorder", 0);
+ //FIXME: use image?
LLViewBorder::Params params;
params.name = "text ed border";
params.rect = getLocalRect();
params.bevel_style = LLViewBorder::BEVEL_IN;
- params.border_thickness = text_editor_border;
+ params.border_thickness = 1;
+ params.visible = p.border_visible;
mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
addChild( mBorder );
- mBorder->setVisible(!p.hide_border);
-
- createDefaultSegment();
- appendText(p.default_text, FALSE, FALSE);
+ setText(p.default_text());
+ if (mShowLineNumbers)
+ {
+ mHPad += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
+ updateTextRect();
+ }
}
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
{
- resetDirty(); // Update saved text state
- LLUICtrl::initFromParams(p);
- // HACK: work around enabled == readonly design bug -- RN
- // setEnabled will modify our read only status, so do this after
- // LLUICtrl::initFromParams
- if (p.read_only.isProvided())
- {
- mReadOnly = p.read_only;
- }
-
+ LLTextBase::initFromParams(p);
+
if (p.commit_on_focus_lost.isProvided())
{
mCommitOnFocusLost = p.commit_on_focus_lost;
}
- updateSegments();
updateAllowingLanguageInput();
-
- // HACK: text editors always need to be enabled so that we can scroll
- LLView::setEnabled(true);
}
LLTextEditor::~LLTextEditor()
@@ -455,282 +303,18 @@ LLTextEditor::~LLTextEditor()
std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
}
-LLTextViewModel* LLTextEditor::getViewModel() const
-{
- return (LLTextViewModel*)mViewModel.get();
-}
-
-static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
-void LLTextEditor::reflow(S32 start_index)
-{
- if (!mReflowNeeded) return;
-
- LLFastTimer ft(FTM_TEXT_REFLOW);
- static LLUICachedControl<S32> texteditor_vpad_top ("UITextEditorVPadTop", 0);
-
- updateSegments();
-
- while(mReflowNeeded)
- {
- bool scrolled_to_bottom = mScroller->isAtBottom();
- mReflowNeeded = FALSE;
-
- LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
- bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible
- S32 first_line = getFirstVisibleLine();
- // if scroll anchor not on first line, update it to first character of first line
- if (!mLineInfoList.empty()
- && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart
- || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd))
- {
- mScrollIndex = mLineInfoList[first_line].mDocIndexStart;
- }
- LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
- //first_char_rect.intersectWith(mTextRect);
-
- S32 cur_top = -texteditor_vpad_top;
-
- if (getLength())
- {
- segment_set_t::iterator seg_iter = mSegments.begin();
- S32 seg_offset = 0;
- S32 line_start_index = 0;
- S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
- S32 remaining_pixels = text_width;
- LLWString text(getWText());
- S32 line_count = 0;
-
- // find and erase line info structs starting at start_index and going to end of document
- if (!mLineInfoList.empty())
- {
- // find first element whose end comes after start_index
- line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
- line_start_index = iter->mDocIndexStart;
- line_count = iter->mLineNum;
- getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
- mLineInfoList.erase(iter, mLineInfoList.end());
- }
-
- // reserve enough space for line numbers
- S32 line_height = mShowLineNumbers ? (S32)(LLFontGL::getFontMonospace()->getLineHeight()) : 0;
-
- while(seg_iter != mSegments.end())
- {
- LLTextSegmentPtr segment = *seg_iter;
-
- // track maximum height of any segment on this line
- line_height = llmax(line_height, segment->getMaxHeight());
- S32 cur_index = segment->getStart() + seg_offset;
- // find run of text from this segment that we can display on one line
- S32 end_index = cur_index;
- while(end_index < segment->getEnd() && text[end_index] != '\n')
- {
- ++end_index;
- }
-
- // ask segment how many character fit in remaining space
- S32 max_characters = end_index - cur_index;
- S32 character_count = segment->getNumChars(llmax(0, remaining_pixels), seg_offset, cur_index - line_start_index, max_characters);
-
- seg_offset += character_count;
-
- S32 last_segment_char_on_line = segment->getStart() + seg_offset;
-
- // if we didn't finish the current segment...
- if (last_segment_char_on_line < segment->getEnd())
- {
- // set up index for next line
- // ...skip newline, we don't want to draw
- S32 next_line_count = line_count;
- if (text[last_segment_char_on_line] == '\n')
- {
- seg_offset++;
- last_segment_char_on_line++;
- next_line_count++;
- }
-
- // add line info and keep going
- mLineInfoList.push_back(line_info(line_start_index, last_segment_char_on_line, cur_top, cur_top - line_height, line_count));
-
- line_start_index = segment->getStart() + seg_offset;
- cur_top -= line_height;
- remaining_pixels = text_width;
- line_height = 0;
- line_count = next_line_count;
- }
- // ...just consumed last segment..
- else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
- {
- mLineInfoList.push_back(line_info(line_start_index, last_segment_char_on_line, cur_top, cur_top - line_height, line_count));
- cur_top -= line_height;
- break;
- }
- // finished a segment and there are segments remaining on this line
- else
- {
- // subtract pixels used and increment segment
- remaining_pixels -= segment->getWidth(seg_offset, character_count);
- ++seg_iter;
- seg_offset = 0;
- }
- }
- }
-
- // change mDocumentPanel document size to accomodate reflowed text
- LLRect document_rect;
- document_rect.setOriginAndSize(1, 1,
- mScroller->getContentWindowRect().getWidth(),
- llmax(mScroller->getContentWindowRect().getHeight(), -cur_top));
- mDocumentPanel->setShape(document_rect);
-
- // after making document big enough to hold all the text, move the text to fit in the document
- if (!mLineInfoList.empty())
- {
- S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mTop - texteditor_vpad_top;
- // move line segments to fit new document rect
- for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
- {
- it->mTop += delta_pos;
- it->mBottom += delta_pos;
- }
- }
-
- // calculate visible region for diplaying text
- updateTextRect();
-
- for (segment_set_t::iterator segment_it = mSegments.begin();
- segment_it != mSegments.end();
- ++segment_it)
- {
- LLTextSegmentPtr segmentp = *segment_it;
- segmentp->updateLayout(*this);
-
- }
-
- // apply scroll constraints after reflowing text
- if (!hasMouseCapture())
- {
- LLRect visible_content_rect = mScroller->getVisibleContentRect();
- if (scrolled_to_bottom && mTrackBottom)
- {
- // keep bottom of text buffer visible
- endOfDoc();
- }
- else if (hasSelection() && follow_selection)
- {
- // keep cursor in same vertical position on screen when selecting text
- LLRect new_cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
- new_cursor_rect_doc.translate(visible_content_rect.mLeft, visible_content_rect.mBottom);
- mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
- //llassert_always(getLocalRectFromDocIndex(mCursorPos).mBottom == old_cursor_rect.mBottom);
- }
- else
- {
- // keep first line of text visible
- LLRect new_first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
- new_first_char_rect.translate(visible_content_rect.mLeft, visible_content_rect.mBottom);
- mScroller->scrollToShowRect(new_first_char_rect, first_char_rect);
- //llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom);
- }
- }
- }
-
- // reset desired x cursor position
- updateCursorXPos();
-}
-
////////////////////////////////////////////////////////////
// LLTextEditor
// Public methods
-BOOL LLTextEditor::truncate()
-{
- BOOL did_truncate = FALSE;
-
- // First rough check - if we're less than 1/4th the size, we're OK
- if (getLength() >= S32(mMaxTextByteLength / 4))
- {
- // Have to check actual byte size
- LLWString text(getWText());
- S32 utf8_byte_size = wstring_utf8_length(text);
- if ( utf8_byte_size > mMaxTextByteLength )
- {
- // Truncate safely in UTF-8
- std::string temp_utf8_text = wstring_to_utf8str(text);
- temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
- getViewModel()->setDisplay(utf8str_to_wstring( temp_utf8_text ));
- did_truncate = TRUE;
- }
- }
-
- return did_truncate;
-}
-
void LLTextEditor::setText(const LLStringExplicit &utf8str)
{
- // clear out the existing text and segments
- clearSegments();
-
- getViewModel()->setValue("");
-
- truncate();
- blockUndo();
-
- createDefaultSegment();
-
- startOfDoc();
- deselect();
-
- // append the new text (supports Url linking)
- std::string text(utf8str);
- LLStringUtil::removeCRLF(text);
- appendStyledText(text, false, false, LLStyle::Params());
-
- needsReflow();
-
- resetDirty();
-
- onValueChange(0, getLength());
-}
-
-void LLTextEditor::setWText(const LLWString &wtext)
-{
- // clear out the existing text and segments
- clearSegments();
-
- getViewModel()->setDisplay(LLWString());
-
- truncate();
blockUndo();
-
- createDefaultSegment();
-
- startOfDoc();
deselect();
- // append the new text (supports Url linking)
- appendStyledText(wstring_to_utf8str(wtext), false, false, LLStyle::Params());
-
- needsReflow();
+ LLTextBase::setText(utf8str);
resetDirty();
-
- onValueChange(0, getLength());
-}
-
-// virtual
-void LLTextEditor::setValue(const LLSD& value)
-{
- setText(value.asString());
-}
-
-std::string LLTextEditor::getText() const
-{
- if (mAllowEmbeddedItems)
- {
- llwarns << "getText() called on text with embedded items (not supported)" << llendl;
- }
- return getViewModel()->getValue().asString();
}
void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap)
@@ -828,12 +412,6 @@ void LLTextEditor::replaceTextAll(const std::string& search_text, const std::str
}
}
-// Picks a new cursor position based on the screen size of text being drawn.
-void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset )
-{
- setCursorPos(getDocIndexFromLocalCoord(local_x, local_y, round), keep_cursor_offset);
-}
-
S32 LLTextEditor::prevWordPos(S32 cursorPos) const
{
LLWString wtext(getWText());
@@ -862,60 +440,6 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
return cursorPos;
}
-S32 LLTextEditor::getLineStart( S32 line ) const
-{
- S32 num_lines = getLineCount();
- if (num_lines == 0)
- {
- return 0;
- }
-
- line = llclamp(line, 0, num_lines-1);
- return mLineInfoList[line].mDocIndexStart;
-}
-
-S32 LLTextEditor::getLineHeight( S32 line ) const
-{
- S32 num_lines = getLineCount();
- if (num_lines == 0)
- {
- return 0;
- }
-
- line = llclamp(line, 0, num_lines-1);
- return mLineInfoList[line].mTop - mLineInfoList[line].mBottom;
-}
-
-// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line.
-void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp, bool include_wordwrap) const
-{
- if (mLineInfoList.empty())
- {
- *linep = 0;
- *offsetp = startpos;
- }
- else
- {
- line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), startpos, line_end_compare());
- if (include_wordwrap)
- {
- *linep = iter - mLineInfoList.begin();
- }
- else
- {
- if (iter == mLineInfoList.end())
- {
- *linep = mLineInfoList.back().mLineNum;
- }
- else
- {
- *linep = iter->mLineNum;
- }
- }
- *offsetp = startpos - iter->mDocIndexStart;
- }
-}
-
const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
// find segment index at character to left of cursor (or rightmost edge of selection)
@@ -957,201 +481,6 @@ void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out,
}
}
-// If round is true, if the position is on the right half of a character, the cursor
-// will be put to its right. If round is false, the cursor will always be put to the
-// character's left.
-
-S32 LLTextEditor::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
-{
- // Figure out which line we're nearest to.
- LLRect visible_region = mScroller->getVisibleContentRect();
-
- // binary search for line that starts before local_y
- line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom());
-
- if (line_iter == mLineInfoList.end())
- {
- return getLength(); // past the end
- }
-
- S32 pos = getLength();
- S32 start_x = mTextRect.mLeft;
-
- segment_set_t::iterator line_seg_iter;
- S32 line_seg_offset;
- for(getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
- line_seg_iter != mSegments.end();
- ++line_seg_iter, line_seg_offset = 0)
- {
- const LLTextSegmentPtr segmentp = *line_seg_iter;
-
- S32 segment_line_start = segmentp->getStart() + line_seg_offset;
- S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start;
- S32 text_width = segmentp->getWidth(line_seg_offset, segment_line_length);
- if (local_x < start_x + text_width // cursor to left of right edge of text
- || segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line
- {
- // Figure out which character we're nearest to.
- S32 offset;
- if (!segmentp->canEdit())
- {
- S32 segment_width = segmentp->getWidth(0, segmentp->getEnd() - segmentp->getStart());
- if (round && local_x - start_x > segment_width / 2)
- {
- offset = segment_line_length;
- }
- else
- {
- offset = 0;
- }
- }
- else
- {
- offset = segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round);
- }
- pos = segment_line_start + offset;
- break;
- }
- start_x += text_width;
- }
-
- return pos;
-}
-
-LLRect LLTextEditor::getLocalRectFromDocIndex(S32 pos) const
-{
- LLRect local_rect(mTextRect);
- local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
- if (mLineInfoList.empty())
- {
- return local_rect;
- }
-
- // clamp pos to valid values
- pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1);
-
-
- // find line that contains cursor
- line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
-
- LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
- local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft;
- local_rect.mBottom = mTextRect.mBottom + (line_iter->mBottom - scrolled_view_rect.mBottom);
- local_rect.mTop = mTextRect.mBottom + (line_iter->mTop - scrolled_view_rect.mBottom);
-
- segment_set_t::iterator line_seg_iter;
- S32 line_seg_offset;
- segment_set_t::iterator cursor_seg_iter;
- S32 cursor_seg_offset;
- getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
- getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset);
-
- while(line_seg_iter != mSegments.end())
- {
- const LLTextSegmentPtr segmentp = *line_seg_iter;
-
- if (line_seg_iter == cursor_seg_iter)
- {
- // cursor advanced to right based on difference in offset of cursor to start of line
- local_rect.mLeft += segmentp->getWidth(line_seg_offset, cursor_seg_offset - line_seg_offset);
-
- break;
- }
- else
- {
- // add remainder of current text segment to cursor position
- local_rect.mLeft += segmentp->getWidth(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset);
- // offset will be 0 for all segments after the first
- line_seg_offset = 0;
- // go to next text segment on this line
- ++line_seg_iter;
- }
- }
-
- local_rect.mRight = local_rect.mLeft;
-
- return local_rect;
-}
-
-void LLTextEditor::addDocumentChild(LLView* view)
-{
- mDocumentPanel->addChild(view);
-}
-
-void LLTextEditor::removeDocumentChild(LLView* view)
-{
- mDocumentPanel->removeChild(view);
-}
-
-bool LLTextEditor::setCursor(S32 row, S32 column)
-{
- if (0 <= row && row < (S32)mLineInfoList.size())
- {
- S32 doc_pos = mLineInfoList[row].mDocIndexStart;
- column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1);
- doc_pos += column;
- updateCursorXPos();
-
- return setCursorPos(doc_pos);
- }
- return false;
-}
-
-bool LLTextEditor::setCursorPos(S32 cursor_pos, bool keep_cursor_offset)
-{
- S32 new_cursor_pos = cursor_pos;
- if (new_cursor_pos != mCursorPos)
- {
- new_cursor_pos = getEditableIndex(new_cursor_pos, new_cursor_pos >= mCursorPos);
- }
-
- mCursorPos = llclamp(new_cursor_pos, 0, (S32)getLength());
- needsScroll();
- if (!keep_cursor_offset)
- updateCursorXPos();
- // did we get requested position?
- return new_cursor_pos == cursor_pos;
-}
-
-void LLTextEditor::updateCursorXPos()
-{
- // reset desired x cursor position
- mDesiredXPixel = getLocalRectFromDocIndex(mCursorPos).mLeft;
-}
-
-// constraint cursor to editable segments of document
-// NOTE: index must be within document range
-S32 LLTextEditor::getEditableIndex(S32 index, bool increasing_direction)
-{
- segment_set_t::iterator segment_iter;
- S32 offset;
- getSegmentAndOffset(index, &segment_iter, &offset);
-
- LLTextSegmentPtr segmentp = *segment_iter;
-
- if (segmentp->canEdit())
- {
- return segmentp->getStart() + offset;
- }
- else if (segmentp->getStart() < index && index < segmentp->getEnd())
- {
- // bias towards document end
- if (increasing_direction)
- {
- return segmentp->getEnd();
- }
- // bias towards document start
- else
- {
- return segmentp->getStart();
- }
- }
- else
- {
- return index;
- }
-}
-
// virtual
BOOL LLTextEditor::canDeselect() const
{
@@ -1167,25 +496,6 @@ void LLTextEditor::deselect()
}
-void LLTextEditor::startSelection()
-{
- if( !mIsSelecting )
- {
- mIsSelecting = TRUE;
- mSelectionStart = mCursorPos;
- mSelectionEnd = mCursorPos;
- }
-}
-
-void LLTextEditor::endSelection()
-{
- if( mIsSelecting )
- {
- mIsSelecting = FALSE;
- mSelectionEnd = mCursorPos;
- }
-}
-
BOOL LLTextEditor::selectionContainsLineBreaks()
{
if (hasSelection())
@@ -1334,23 +644,12 @@ void LLTextEditor::selectAll()
setCursorPos(mSelectionEnd);
}
-
-BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
-{
- if (childrenHandleToolTip(x, y, msg, sticky_rect_screen))
- {
- return TRUE;
- }
-
- return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
-}
-
BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
// Let scrollbar have first dibs
- handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
+ handled = LLTextBase::handleMouseDown(x, y, mask);
if( !handled )
{
@@ -1398,7 +697,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
}
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
return handled;
}
@@ -1407,7 +706,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- handled = childrenHandleMiddleMouseDown(x, y, mask) != NULL;
+ handled = LLTextBase::handleMouseDown(x, y, mask);
if (!handled)
{
@@ -1424,19 +723,12 @@ BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
- static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
BOOL handled = FALSE;
if(hasMouseCapture() )
{
if( mIsSelecting )
{
- if (x != mLastSelectionX || y != mLastSelectionY)
- {
- mLastSelectionX = x;
- mLastSelectionY = y;
- }
-
mScroller->autoScroll(x, y);
S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight);
@@ -1453,32 +745,19 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
if( !handled )
{
// Pass to children
- handled = LLView::childrenHandleHover(x, y, mask) != NULL;
+ handled = LLTextBase::handleHover(x, y, mask);
}
if( handled )
{
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
}
- // Opaque
if( !handled )
{
- // Check to see if we're over an HTML-style link
- handled = handleHoverOverUrl(x, y);
- if( handled )
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- }
-
- if( !handled )
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- handled = TRUE;
- }
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
}
return handled;
@@ -1489,8 +768,12 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // let scrollbar have first dibs
- handled = LLView::childrenHandleMouseUp(x, y, mask) != NULL;
+ // if I'm not currently selecting text
+ if (!(hasSelection() && hasMouseCapture()))
+ {
+ // let text segments handle mouse event
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
if( !handled )
{
@@ -1503,11 +786,6 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
endSelection();
}
- if( !hasSelection() && hasMouseCapture() )
- {
- handleMouseUpOverUrl(x, y);
- }
-
// take selection to 'primary' clipboard
updatePrimary();
@@ -1515,7 +793,7 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
}
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
if( hasMouseCapture() )
{
@@ -1532,8 +810,8 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // let scrollbar have first dibs
- handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL;
+ // let scrollbar and text segments have first dibs
+ handled = LLTextBase::handleDoubleClick(x, y, mask);
if( !handled )
{
@@ -1571,7 +849,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
mIsSelecting = FALSE;
// delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
// take selection to 'primary' clipboard
updatePrimary();
@@ -1583,35 +861,18 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
}
-// Allow calling cards to be dropped onto text fields. Append the name and
-// a carriage return.
-// virtual
-BOOL LLTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg)
-{
- *accept = ACCEPT_NO;
-
- return TRUE;
-}
-
//----------------------------------------------------------------------------
// Returns change in number of characters in mText
-S32 LLTextEditor::execute( LLTextCmd* cmd )
+S32 LLTextEditor::execute( TextCmd* cmd )
{
S32 delta = 0;
if( cmd->execute(this, &delta) )
{
// Delete top of undo stack
undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (enditer != mUndoStack.begin())
- {
- --enditer;
- std::for_each(mUndoStack.begin(), enditer, DeletePointer());
- mUndoStack.erase(mUndoStack.begin(), enditer);
- }
+ std::for_each(mUndoStack.begin(), enditer, DeletePointer());
+ mUndoStack.erase(mUndoStack.begin(), enditer);
// Push the new command is now on the top (front) of the undo stack.
mUndoStack.push_front(cmd);
mLastCmd = cmd;
@@ -1627,7 +888,7 @@ S32 LLTextEditor::execute( LLTextCmd* cmd )
S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment)
{
- return execute( new LLTextCmdInsert( pos, group_with_next_op, wstr, segment ) );
+ return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
}
S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
@@ -1638,12 +899,7 @@ S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
// store text segments
getSegmentsInRange(segments_to_remove, pos, pos + length, false);
- return execute( new LLTextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
-}
-
-S32 LLTextEditor::append(const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment)
-{
- return insert(getLength(), wstr, group_with_next_op, segment);
+ return execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
}
S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
@@ -1654,7 +910,7 @@ S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
}
else
{
- return execute(new LLTextCmdOverwriteChar(pos, FALSE, wc));
+ return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
}
}
@@ -1674,8 +930,7 @@ void LLTextEditor::removeCharOrTab()
if (text[mCursorPos - 1] == ' ')
{
// Try to remove a "tab"
- S32 line, offset;
- getLineAndOffset(mCursorPos, &line, &offset);
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
if (offset > 0)
{
chars_to_remove = offset % SPACES_PER_TAB;
@@ -1749,7 +1004,7 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
}
else
{
- return execute(new LLTextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
+ return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
}
}
@@ -2349,8 +1604,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return
deleteSelection(FALSE);
}
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
for( S32 i=0; i < spaces_needed; i++ )
@@ -2481,7 +1735,7 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
if( handled )
{
- resetKeystrokeTimer();
+ resetCursorBlink();
// Most keystrokes will make the selection box go away, but not all will.
if( !selection_modified &&
@@ -2534,7 +1788,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
if( handled )
{
- resetKeystrokeTimer();
+ resetCursorBlink();
// Most keystrokes will make the selection box go away, but not all will.
deselect();
@@ -2573,8 +1827,7 @@ void LLTextEditor::doDelete()
if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
{
// Try to remove a full tab's worth of spaces
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
if( chars_to_remove == 0 )
{
@@ -2694,7 +1947,7 @@ void LLTextEditor::redo()
void LLTextEditor::onFocusReceived()
{
- LLUICtrl::onFocusReceived();
+ LLTextBase::onFocusReceived();
updateAllowingLanguageInput();
}
@@ -2717,19 +1970,19 @@ void LLTextEditor::onFocusLost()
// Make sure cursor is shown again
getWindow()->showCursorFromMouseMove();
- LLUICtrl::onFocusLost();
+ LLTextBase::onFocusLost();
}
void LLTextEditor::onCommit()
{
setControlValue(getValue());
- LLUICtrl::onCommit();
+ LLTextBase::onCommit();
}
void LLTextEditor::setEnabled(BOOL enabled)
{
// just treat enabled as read-only flag
- BOOL read_only = !enabled;
+ bool read_only = !enabled;
if (read_only != mReadOnly)
{
mReadOnly = read_only;
@@ -2738,195 +1991,6 @@ void LLTextEditor::setEnabled(BOOL enabled)
}
}
-void LLTextEditor::drawBackground()
-{
- S32 left = 0;
- S32 top = getRect().getHeight();
- S32 bottom = 0;
-
- LLColor4 bg_color = mReadOnly ? mReadOnlyBgColor.get()
- : hasFocus() ? mFocusBgColor.get() : mWriteableBgColor.get();
- if( mShowLineNumbers ) {
- gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor.get() ); // line number area always read-only
- gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator
- }
-}
-
-// Draws the black box behind the selected text
-void LLTextEditor::drawSelectionBackground()
-{
- // Draw selection even if we don't have keyboard focus for search/replace
- if( hasSelection() && !mLineInfoList.empty())
- {
- LLWString text = getWText();
- std::vector<LLRect> selection_rects;
-
- S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
- S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
- LLRect selection_rect = mTextRect;
-
- // Skip through the lines we aren't drawing.
- LLRect content_display_rect = mScroller->getVisibleContentRect();
-
- // binary search for line that starts before top of visible buffer
- line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
- line_list_t::const_iterator end_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
-
- bool done = false;
-
- // Find the coordinates of the selected area
- for (;line_iter != end_iter && !done; ++line_iter)
- {
- // is selection visible on this line?
- if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
- {
- segment_set_t::iterator segment_iter;
- S32 segment_offset;
- getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
-
- LLRect selection_rect;
- selection_rect.mLeft = 0;
- selection_rect.mRight = 0;
- selection_rect.mBottom = line_iter->mBottom;
- selection_rect.mTop = line_iter->mTop;
-
- for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
- {
- LLTextSegmentPtr segmentp = *segment_iter;
-
- S32 segment_line_start = segmentp->getStart() + segment_offset;
- S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
-
- // if selection after beginning of segment
- if(selection_left >= segment_line_start)
- {
- S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
- selection_rect.mLeft += segmentp->getWidth(segment_offset, num_chars);
- }
-
- // if selection spans end of current segment...
- if (selection_right > segment_line_end)
- {
- // extend selection slightly beyond end of line
- // to indicate selection of newline character (use "n" character to determine width)
- selection_rect.mRight += segmentp->getWidth(segment_offset, segment_line_end - segment_line_start);
- }
- // else if selection ends on current segment...
- else
- {
- S32 num_chars = selection_right - segment_line_start;
- selection_rect.mRight += segmentp->getWidth(segment_offset, num_chars);
-
- break;
- }
- }
- selection_rects.push_back(selection_rect);
- }
- }
-
- // Draw the selection box (we're using a box instead of reversing the colors on the selected text).
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- const LLColor4& color = mReadOnly ? mReadOnlyBgColor.get() : mWriteableBgColor.get();
- F32 alpha = hasFocus() ? 0.7f : 0.3f;
- gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
-
- for (std::vector<LLRect>::iterator rect_it = selection_rects.begin();
- rect_it != selection_rects.end();
- ++rect_it)
- {
- LLRect selection_rect = *rect_it;
- selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom);
- gl_rect_2d(selection_rect);
- }
- }
-}
-
-void LLTextEditor::drawCursor()
-{
- if( hasFocus()
- && gFocusMgr.getAppHasFocus()
- && !mReadOnly)
- {
- LLWString wtext = getWText();
- const llwchar* text = wtext.c_str();
-
- LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
- cursor_rect.translate(-1, 0);
- segment_set_t::iterator seg_it = getSegIterContaining(mCursorPos);
-
- // take style from last segment
- LLTextSegmentPtr segmentp;
-
- if (seg_it != mSegments.end())
- {
- segmentp = *seg_it;
- }
- else
- {
- //segmentp = mSegments.back();
- return;
- }
-
- // Draw the cursor
- // (Flash the cursor every half second starting a fixed time after the last keystroke)
- F32 elapsed = mKeystrokeTimer.getElapsedTimeF32();
- if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )
- {
-
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
- {
- S32 width = llmax(CURSOR_THICKNESS, segmentp->getWidth(mCursorPos - segmentp->getStart(), 1));
- cursor_rect.mRight = cursor_rect.mLeft + width;
- }
- else
- {
- cursor_rect.mRight = cursor_rect.mLeft + CURSOR_THICKNESS;
- }
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.color4fv( mCursorColor.get().mV );
-
- gl_rect_2d(cursor_rect);
-
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n')
- {
- LLColor4 text_color;
- const LLFontGL* fontp;
- if (segmentp)
- {
- text_color = segmentp->getColor();
- fontp = segmentp->getStyle()->getFont();
- }
- else if (mReadOnly)
- {
- text_color = mReadOnlyFgColor.get();
- fontp = mDefaultFont;
- }
- else
- {
- text_color = mFgColor.get();
- fontp = mDefaultFont;
- }
- fontp->render(text, mCursorPos, cursor_rect.mLeft, cursor_rect.mBottom,
- LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f),
- LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
- LLFontGL::NO_SHADOW,
- 1);
- }
-
- // Make sure the IME is in the right place
- LLRect screen_pos = calcScreenRect();
- LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) );
-
- ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
- ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
- getWindow()->setLanguageTextInput( ime_pos );
- }
- }
-}
-
void LLTextEditor::drawPreeditMarker()
{
static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
@@ -3032,96 +2096,6 @@ void LLTextEditor::drawPreeditMarker()
}
-void LLTextEditor::drawText()
-{
- LLWString text = getWText();
- const S32 text_len = getLength();
- if( text_len <= 0 )
- {
- return;
- }
- S32 selection_left = -1;
- S32 selection_right = -1;
- // Draw selection even if we don't have keyboard focus for search/replace
- if( hasSelection())
- {
- selection_left = llmin( mSelectionStart, mSelectionEnd );
- selection_right = llmax( mSelectionStart, mSelectionEnd );
- }
-
- LLGLSUIDefault gls_ui;
- LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
- LLRect content_rect = mScroller->getContentWindowRect();
- S32 first_line = getFirstVisibleLine();
- S32 num_lines = getLineCount();
- if (first_line >= num_lines)
- {
- return;
- }
-
- S32 line_start = getLineStart(first_line);
- // find first text segment that spans top of visible portion of text buffer
- segment_set_t::iterator seg_iter = getSegIterContaining(line_start);
- if (seg_iter == mSegments.end())
- {
- return;
- }
-
- LLTextSegmentPtr cur_segment = *seg_iter;
-
- for (S32 cur_line = first_line; cur_line < num_lines; cur_line++)
- {
- line_info& line = mLineInfoList[cur_line];
-
- if ((line.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom)
- {
- break;
- }
-
- S32 next_start = -1;
- S32 line_end = text_len;
-
- if ((cur_line + 1) < num_lines)
- {
- next_start = getLineStart(cur_line + 1);
- line_end = next_start;
- }
- if ( text[line_end-1] == '\n' )
- {
- --line_end;
- }
-
- LLRect text_rect(mTextRect.mLeft - scrolled_view_rect.mLeft,
- line.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
- mTextRect.getWidth() - scrolled_view_rect.mLeft,
- line.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom);
-
- // draw a single line of text
- S32 seg_start = line_start;
- while( seg_start < line_end )
- {
- while( cur_segment->getEnd() <= seg_start )
- {
- seg_iter++;
- if (seg_iter == mSegments.end())
- {
- llwarns << "Ran off the segmentation end!" << llendl;
-
- return;
- }
- cur_segment = *seg_iter;
- }
-
- S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart();
- text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect));
-
- seg_start = clipped_end + cur_segment->getStart();
- }
-
- line_start = next_start;
- }
-}
-
void LLTextEditor::drawLineNumbers()
{
LLGLSUIDefault gls_ui;
@@ -3136,24 +2110,31 @@ void LLTextEditor::drawLineNumbers()
return;
}
- S32 cursor_line = getCurrentLine();
+ S32 cursor_line = getLineNumFromDocIndex(mCursorPos);
if (mShowLineNumbers)
{
+ S32 left = 0;
+ S32 top = getRect().getHeight();
+ S32 bottom = 0;
+
+ gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor.get() ); // line number area always read-only
+ gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator
+
S32 last_line_num = -1;
for (S32 cur_line = first_line; cur_line < num_lines; cur_line++)
{
line_info& line = mLineInfoList[cur_line];
- if ((line.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom)
+ if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom)
{
break;
}
- S32 line_bottom = line.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom;
+ S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom;
// draw the line numbers
- if(line.mLineNum != last_line_num && line.mTop <= scrolled_view_rect.mTop)
+ if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop)
{
const LLFontGL *num_font = LLFontGL::getFontMonospace();
const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum ));
@@ -3180,58 +2161,23 @@ void LLTextEditor::drawLineNumbers()
void LLTextEditor::draw()
{
- // reflow if needed, on demand
- reflow();
-
- // then update scroll position, as cursor may have moved
- updateScrollFromCursor();
-
- LLColor4 bg_color = mReadOnly
- ? mReadOnlyBgColor.get()
- : hasFocus()
- ? mFocusBgColor.get()
- : mWriteableBgColor.get();
-
- mDocumentPanel->setBackgroundColor(bg_color);
-
- LLView::draw();
- drawBackground(); //overlays scrolling panel bg
- drawLineNumbers();
-
{
// pad clipping rectangle so that cursor can draw at full width
// when at left edge of mTextRect
LLRect clip_rect(mTextRect);
clip_rect.stretch(1);
LLLocalClipRect clip(clip_rect);
- drawSelectionBackground();
drawPreeditMarker();
- drawText();
- drawCursor();
}
+ LLTextBase::draw();
+ drawLineNumbers();
+
//RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
// when in readonly mode
mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
}
-
-S32 LLTextEditor::getFirstVisibleLine() const
-{
- LLRect visible_region = mScroller->getVisibleContentRect();
-
- // binary search for line that starts before top of visible buffer
- line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
-
- return iter - mLineInfoList.begin();
-}
-
-// virtual
-void LLTextEditor::clear()
-{
- setText(LLStringUtil::null);
-}
-
// Start or stop the editor from accepting text-editing keystrokes
// see also LLLineEditor
void LLTextEditor::setFocus( BOOL new_state )
@@ -3247,7 +2193,7 @@ void LLTextEditor::setFocus( BOOL new_state )
getWindow()->allowLanguageTextInput(this, FALSE);
}
- LLUICtrl::setFocus( new_state );
+ LLTextBase::setFocus( new_state );
if( new_state )
{
@@ -3255,7 +2201,7 @@ void LLTextEditor::setFocus( BOOL new_state )
gEditMenuHandler = this;
// Don't start the cursor flashing right away
- resetKeystrokeTimer();
+ resetCursorBlink();
}
else
{
@@ -3269,96 +2215,6 @@ void LLTextEditor::setFocus( BOOL new_state )
}
}
-// virtual
-BOOL LLTextEditor::acceptsTextInput() const
-{
- return !mReadOnly;
-}
-
-// Given a line (from the start of the doc) and an offset into the line, find the offset (pos) into text.
-S32 LLTextEditor::getPos( S32 line, S32 offset )
-{
- S32 line_start = getLineStart(line);
- S32 next_start = getLineStart(line+1);
- if (next_start == line_start)
- {
- next_start = getLength() + 1;
- }
- S32 line_length = next_start - line_start - 1;
- line_length = llmax(line_length, 0);
- return line_start + llmin( offset, line_length );
-}
-
-
-void LLTextEditor::changePage( S32 delta )
-{
- const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10;
- if (delta == 0) return;
-
- //RN: use pixel heights
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
-
- if( delta == -1 )
- {
- mScroller->pageUp(PIXEL_OVERLAP_ON_PAGE_CHANGE);
- }
- else
- if( delta == 1 )
- {
- mScroller->pageDown(PIXEL_OVERLAP_ON_PAGE_CHANGE);
- }
-
- if (getLocalRectFromDocIndex(mCursorPos) == cursor_rect)
- {
- // cursor didn't change apparent position, so move to top or bottom of document, respectively
- if (delta < 0)
- {
- startOfDoc();
- }
- else
- {
- endOfDoc();
- }
- }
- else
- {
- setCursorAtLocalPos(cursor_rect.getCenterX(), cursor_rect.getCenterY(), true, false);
- }
-}
-
-void LLTextEditor::changeLine( S32 delta )
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- S32 new_line = line;
- if( (delta < 0) && (line > 0 ) )
- {
- new_line = line - 1;
- }
- else if( (delta > 0) && (line < (getLineCount() - 1)) )
- {
- new_line = line + 1;
- }
-
- LLRect visible_region = mScroller->getVisibleContentRect();
-
- S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE);
- setCursorPos(new_cursor_pos, true);
-}
-
-
-void LLTextEditor::startOfLine()
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
- setCursorPos(mCursorPos - offset);
-}
-
-
// public
void LLTextEditor::setCursorAndScrollToEnd()
{
@@ -3366,92 +2222,16 @@ void LLTextEditor::setCursorAndScrollToEnd()
endOfDoc();
}
-void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap )
-{
- getLineAndOffset( mCursorPos, line, col, include_wordwrap );
-}
-
void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
{
- getLineAndColumnForPosition(mCursorPos, line, col, include_wordwrap);
-}
-
-S32 LLTextEditor::getCurrentLine()
-{
- return getLineForPosition(mCursorPos);
-}
-
-S32 LLTextEditor::getLineForPosition(S32 position)
-{
- S32 line, col;
- getLineAndColumnForPosition(position, &line, &col, FALSE);
- return line;
-}
-
-
-void LLTextEditor::endOfLine()
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
- S32 num_lines = getLineCount();
- if (line + 1 >= num_lines)
- {
- setCursorPos(getLength());
- }
- else
- {
- setCursorPos( getLineStart(line + 1) - 1 );
- }
-}
-
-void LLTextEditor::startOfDoc()
-{
- setCursorPos(0);
-}
-
-void LLTextEditor::endOfDoc()
-{
- setCursorPos(getLength());
-}
-
-// Sets the scrollbar from the cursor position
-void LLTextEditor::updateScrollFromCursor()
-{
- // Update scroll position even in read-only mode (when there's no cursor displayed)
- // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
-
- if (!mScrollNeeded)
- {
- return;
- }
- mScrollNeeded = FALSE;
-
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- // scroll so that the cursor is at the top of the page
- LLRect scroller_doc_window = mScroller->getVisibleContentRect();
- LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
- cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
- mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
-}
-
-void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLView::reshape( width, height, called_from_parent );
-
- // do this first after reshape, because other things depend on
- // up-to-date mTextRect
- updateTextRect();
-
- needsReflow();
+ *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
+ *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
}
void LLTextEditor::autoIndent()
{
// Count the number of spaces in the current line
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 line = getLineNumFromDocIndex(mCursorPos);
S32 line_start = getLineStart(line);
S32 space_count = 0;
S32 i;
@@ -3496,221 +2276,6 @@ void LLTextEditor::insertText(const std::string &new_text)
setEnabled( enabled );
}
-
-void LLTextEditor::appendColoredText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- const LLColor4 &color,
- const std::string& font_name)
-{
- LLColor4 lcolor=color;
- if (mParseHighlights)
- {
- LLTextParser* highlight = LLTextParser::getInstance();
- highlight->parseFullLineHighlights(new_text, &lcolor);
- }
-
- LLStyle::Params style_params;
- style_params.color = lcolor;
- if (font_name.empty())
- {
- style_params.font = mDefaultFont;
- }
- else
- {
- style_params.font.name = font_name;
- }
- appendStyledText(new_text, allow_undo, prepend_newline, style_params);
-}
-
-void LLTextEditor::appendStyledText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- const LLStyle::Params& style_params)
-{
- S32 part = (S32)LLTextParser::WHOLE;
- if(mParseHTML)
- {
-
- S32 start=0,end=0;
- LLUrlMatch match;
- std::string text = new_text;
- while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextEditor::onUrlLabelUpdated, this, _1, _2)) )
- {
- start = match.getStart();
- end = match.getEnd()+1;
-
- LLStyle::Params link_params = style_params;
- link_params.color = mLinkColor;
- link_params.font.style = "UNDERLINE";
- link_params.link_href = match.getUrl();
-
- // output the text before the Url
- if (start > 0)
- {
- if (part == (S32)LLTextParser::WHOLE ||
- part == (S32)LLTextParser::START)
- {
- part = (S32)LLTextParser::START;
- }
- else
- {
- part = (S32)LLTextParser::MIDDLE;
- }
- std::string subtext=text.substr(0,start);
- appendHighlightedText(subtext,allow_undo, prepend_newline, part, style_params);
- prepend_newline = false;
- }
-
- // output the styled Url
- appendText(match.getLabel(),allow_undo, prepend_newline, link_params);
- prepend_newline = false;
-
- // set the tooltip for the Url label
- if (! match.getTooltip().empty())
- {
- segment_set_t::iterator it = getSegIterContaining(getLength()-1);
- if (it != mSegments.end())
- {
- LLTextSegmentPtr segment = *it;
- segment->setToolTip(match.getTooltip());
- }
- }
-
- // output an optional icon after the Url
- if (! match.getIcon().empty())
- {
- LLUIImagePtr image = LLUI::getUIImage(match.getIcon());
- if (image)
- {
- LLStyle::Params icon;
- icon.image = image;
- // TODO: fix spacing of images and remove the fixed char spacing
- appendText(" ", allow_undo, prepend_newline, icon);
- }
- }
-
- // move on to the rest of the text after the Url
- if (end < (S32)text.length())
- {
- text = text.substr(end,text.length() - end);
- end=0;
- part=(S32)LLTextParser::END;
- }
- else
- {
- break;
- }
- }
- if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
- if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, style_params);
- }
- else
- {
- appendHighlightedText(new_text, allow_undo, prepend_newline, part, style_params);
- }
-}
-
-void LLTextEditor::appendHighlightedText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- S32 highlight_part,
- const LLStyle::Params& style_params)
-{
- if (mParseHighlights)
- {
- LLTextParser* highlight = LLTextParser::getInstance();
-
- if (highlight && !style_params.isDefault())
- {
- LLStyle::Params highlight_params = style_params;
-
- LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), highlight_part);
- bool lprepend=prepend_newline;
- for (S32 i=0;i<pieces.size();i++)
- {
- LLSD color_llsd = pieces[i]["color"];
- LLColor4 lcolor;
- lcolor.setValue(color_llsd);
- highlight_params.color = lcolor;
- if (i != 0 && (pieces.size() > 1) ) lprepend=FALSE;
- appendText((std::string)pieces[i]["text"], allow_undo, lprepend, highlight_params);
- }
- return;
- }
- }
- appendText(new_text, allow_undo, prepend_newline, style_params);
-}
-
-// Appends new text to end of document
-void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline,
- const LLStyle::Params& stylep)
-{
- if (new_text.empty()) return;
-
- // Save old state
- S32 selection_start = mSelectionStart;
- S32 selection_end = mSelectionEnd;
- BOOL was_selecting = mIsSelecting;
- S32 cursor_pos = mCursorPos;
- S32 old_length = getLength();
- BOOL cursor_was_at_end = (mCursorPos == old_length);
-
- deselect();
-
- setCursorPos(old_length);
-
- LLWString wide_text;
-
- // Add carriage return if not first line
- if (getLength() != 0
- && prepend_newline)
- {
- wide_text = utf8str_to_wstring(std::string("\n") + new_text);
- }
- else
- {
- wide_text = utf8str_to_wstring(new_text);
- }
-
- LLTextSegmentPtr segmentp;
- if (!stylep.isDefault())
- {
- S32 segment_start = old_length;
- S32 segment_end = old_length + wide_text.size();
- segmentp = new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this );
- }
-
- append(wide_text, TRUE, segmentp);
-
- needsReflow();
-
- // Set the cursor and scroll position
- if( selection_start != selection_end )
- {
- mSelectionStart = selection_start;
- mSelectionEnd = selection_end;
-
- mIsSelecting = was_selecting;
- setCursorPos(cursor_pos);
- }
- else if( cursor_was_at_end )
- {
- setCursorPos(getLength());
- }
- else
- {
- setCursorPos(cursor_pos);
- }
-
- if( !allow_undo )
- {
- blockUndo();
- }
-}
-
-
void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline)
{
// Save old state
@@ -3739,7 +2304,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
}
LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size());
- append(widget_wide_text, FALSE, segment);
+ insert(getLength(), widget_wide_text, FALSE, segment);
needsReflow();
@@ -3767,12 +2332,6 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
}
}
-void LLTextEditor::onUrlLabelUpdated(const std::string &url,
- const std::string &label)
-{
- // LLUrlRegistry has given us a new label for one of our Urls
- replaceUrlLabel(url, label);
-}
void LLTextEditor::replaceUrlLabel(const std::string &url,
const std::string &label)
@@ -3830,164 +2389,10 @@ void LLTextEditor::removeTextFromEnd(S32 num_chars)
mSelectionStart = llclamp(mSelectionStart, 0, len);
mSelectionEnd = llclamp(mSelectionEnd, 0, len);
- reflow();
+ needsReflow();
needsScroll();
}
-///////////////////////////////////////////////////////////////////
-// Returns change in number of characters in mWText
-
-S32 LLTextEditor::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextEditor::segment_vec_t* segments )
-{
- LLWString text(getWText());
- S32 old_len = text.length(); // length() returns character length
- S32 insert_len = wstr.length();
-
- pos = getEditableIndex(pos, true);
-
- segment_set_t::iterator seg_iter = getSegIterContaining(pos);
-
- LLTextSegmentPtr default_segment;
-
- LLTextSegmentPtr segmentp;
- if (seg_iter != mSegments.end())
- {
- segmentp = *seg_iter;
- }
- else
- {
- //segmentp = mSegments.back();
- return pos;
- }
-
- if (segmentp->canEdit())
- {
- segmentp->setEnd(segmentp->getEnd() + insert_len);
- if (seg_iter != mSegments.end())
- {
- ++seg_iter;
- }
- }
- else
- {
- // create default editable segment to hold new text
- default_segment = new LLNormalTextSegment( getDefaultStyle(), pos, pos + insert_len, *this);
- }
-
- // shift remaining segments to right
- for(;seg_iter != mSegments.end(); ++seg_iter)
- {
- LLTextSegmentPtr segmentp = *seg_iter;
- segmentp->setStart(segmentp->getStart() + insert_len);
- segmentp->setEnd(segmentp->getEnd() + insert_len);
- }
-
- // insert new segments
- if (segments)
- {
- if (default_segment.notNull())
- {
- // potentially overwritten by segments passed in
- insertSegment(default_segment);
- }
- for (segment_vec_t::iterator seg_iter = segments->begin();
- seg_iter != segments->end();
- ++seg_iter)
- {
- LLTextSegment* segmentp = *seg_iter;
- insertSegment(segmentp);
- }
- }
-
- text.insert(pos, wstr);
- getViewModel()->setDisplay(text);
-
- if ( truncate() )
- {
- // The user's not getting everything he's hoping for
- make_ui_sound("UISndBadKeystroke");
- insert_len = getLength() - old_len;
- }
-
- onValueChange(pos, pos + insert_len);
-
- return insert_len;
-}
-
-S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length)
-{
- LLWString text(getWText());
- segment_set_t::iterator seg_iter = getSegIterContaining(pos);
- while(seg_iter != mSegments.end())
- {
- LLTextSegmentPtr segmentp = *seg_iter;
- S32 end = pos + length;
- if (segmentp->getStart() < pos)
- {
- // deleting from middle of segment
- if (segmentp->getEnd() > end)
- {
- segmentp->setEnd(segmentp->getEnd() - length);
- }
- // truncating segment
- else
- {
- segmentp->setEnd(pos);
- }
- }
- else if (segmentp->getStart() < end)
- {
- // deleting entire segment
- if (segmentp->getEnd() <= end)
- {
- // remove segment
- segmentp->unlinkFromDocument(this);
- segment_set_t::iterator seg_to_erase(seg_iter++);
- mSegments.erase(seg_to_erase);
- continue;
- }
- // deleting head of segment
- else
- {
- segmentp->setStart(pos);
- segmentp->setEnd(segmentp->getEnd() - length);
- }
- }
- else
- {
- // shifting segments backward to fill deleted portion
- segmentp->setStart(segmentp->getStart() - length);
- segmentp->setEnd(segmentp->getEnd() - length);
- }
- ++seg_iter;
- }
-
- text.erase(pos, length);
- getViewModel()->setDisplay(text);
-
- // recreate default segment in case we erased everything
- createDefaultSegment();
-
- onValueChange(pos, pos);
-
- return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
-}
-
-S32 LLTextEditor::overwriteCharNoUndo(S32 pos, llwchar wc)
-{
- if (pos > (S32)getLength())
- {
- return 0;
- }
- LLWString text(getWText());
- text[pos] = wc;
- getViewModel()->setDisplay(text);
-
- onValueChange(pos, pos + 1);
-
- return 1;
-}
-
//----------------------------------------------------------------------------
void LLTextEditor::makePristine()
@@ -4051,29 +2456,13 @@ BOOL LLTextEditor::tryToRevertToPristineState()
}
-void LLTextEditor::updateTextRect()
-{
- static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0);
- static LLUICachedControl<S32> texteditor_h_pad ("UITextEditorHPad", 0);
-
- LLRect old_text_rect = mTextRect;
- mTextRect = mScroller->getContentWindowRect();
- mTextRect.stretch(texteditor_border * -1);
- mTextRect.mLeft += texteditor_h_pad;
- mTextRect.mLeft += mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0;
- if (mTextRect != old_text_rect)
- {
- needsReflow();
- }
-}
-
-LLFastTimer::DeclareTimer FTM_TEXT_EDITOR_LOAD_KEYWORD("Text Editor Load Keywords");
+static LLFastTimer::DeclareTimer FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting");
void LLTextEditor::loadKeywords(const std::string& filename,
const std::vector<std::string>& funcs,
const std::vector<std::string>& tooltips,
const LLColor3& color)
{
- LLFastTimer ft(FTM_TEXT_EDITOR_LOAD_KEYWORD);
+ LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
if(mKeywords.loadFromFile(filename))
{
S32 count = llmin(funcs.size(), tooltips.size());
@@ -4094,27 +2483,9 @@ void LLTextEditor::loadKeywords(const std::string& filename,
}
}
-void LLTextEditor::createDefaultSegment()
-{
- // ensures that there is always at least one segment
- if (mSegments.empty())
- {
- LLTextSegmentPtr default_segment = new LLNormalTextSegment( getDefaultStyle(), 0, getLength() + 1, *this);
- mSegments.insert(default_segment);
- default_segment->linkToDocument(this);
- }
-}
-
-LLStyleSP LLTextEditor::getDefaultStyle()
-{
- LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() );
- return LLStyleSP(new LLStyle(LLStyle::Params().color(text_color).font(mDefaultFont)));
-}
-
-LLFastTimer::DeclareTimer FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments");
void LLTextEditor::updateSegments()
{
- LLFastTimer ft(FTM_UPDATE_TEXT_SEGMENTS);
+ LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
if (mKeywords.isLoaded())
{
// HACK: No non-ascii keywords for now
@@ -4125,11 +2496,11 @@ void LLTextEditor::updateSegments()
segment_set_t::iterator insert_it = mSegments.begin();
for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{
- insert_it = mSegments.insert(insert_it, *list_it);
+ insertSegment(*list_it);
}
}
- createDefaultSegment();
+ LLTextBase::updateSegments();
}
void LLTextEditor::updateLinkSegments()
@@ -4155,66 +2526,7 @@ void LLTextEditor::updateLinkSegments()
}
}
-void LLTextEditor::insertSegment(LLTextSegmentPtr segment_to_insert)
-{
- if (segment_to_insert.isNull())
- {
- return;
- }
-
- segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
- if (cur_seg_iter == mSegments.end())
- {
- mSegments.insert(segment_to_insert);
- segment_to_insert->linkToDocument(this);
- }
- else
- {
- LLTextSegmentPtr cur_segmentp = *cur_seg_iter;
- if (cur_segmentp->getStart() < segment_to_insert->getStart())
- {
- S32 old_segment_end = cur_segmentp->getEnd();
- // split old at start point for new segment
- cur_segmentp->setEnd(segment_to_insert->getStart());
- // advance to next segment
- ++cur_seg_iter;
- // insert remainder of old segment
- LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
- cur_seg_iter = mSegments.insert(cur_seg_iter, remainder_segment);
- remainder_segment->linkToDocument(this);
- // insert new segment before remainder of old segment
- cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
-
- segment_to_insert->linkToDocument(this);
- // move to "remanider" segment and start truncation there
- ++cur_seg_iter;
- }
- else
- {
- cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
- ++cur_seg_iter;
- segment_to_insert->linkToDocument(this);
- }
-
- // now delete/truncate remaining segments as necessary
- while(cur_seg_iter != mSegments.end())
- {
- cur_segmentp = *cur_seg_iter;
- if (cur_segmentp->getEnd() <= segment_to_insert->getEnd())
- {
- cur_segmentp->unlinkFromDocument(this);
- segment_set_t::iterator seg_to_erase(cur_seg_iter++);
- mSegments.erase(seg_to_erase);
- }
- else
- {
- cur_segmentp->setStart(segment_to_insert->getEnd());
- break;
- }
- }
- }
-}
void LLTextEditor::onMouseCaptureLost()
{
@@ -4400,7 +2712,7 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
{
- mPreeditOverwrittenWString = getWSubString(insert_preedit_at, mPreeditWString.length());
+ mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
}
else
@@ -4415,7 +2727,7 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
setCursorPos(insert_preedit_at + caret_position);
// Update of the preedit should be caused by some key strokes.
- mKeystrokeTimer.reset();
+ resetCursorBlink();
onKeyStroke();
}
@@ -4578,93 +2890,6 @@ S32 LLTextEditor::getPreeditFontSize() const
return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
}
-LLWString LLTextEditor::getWText() const
-{
- return getViewModel()->getDisplay();
-}
-
-void LLTextEditor::onValueChange(S32 start, S32 end)
-{
-}
-
-//
-// LLInlineViewSegment
-//
-
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end)
-: LLTextSegment(start, end),
- mView(view)
-{
-}
-
-LLInlineViewSegment::~LLInlineViewSegment()
-{
- mView->die();
-}
-
-S32 LLInlineViewSegment::getWidth(S32 first_char, S32 num_chars) const
-{
- if (first_char == 0 && num_chars == 0)
- {
- return 0;
- }
- else
- {
- return mView->getRect().getWidth();
- }
-}
-
-S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
-{
- if (line_offset != 0 && num_pixels < mView->getRect().getWidth())
- {
- return 0;
- }
- else
- {
- return mEnd - mStart;
- }
-}
-
-void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
-{
- const LLTextEditor *ed = dynamic_cast<const LLTextEditor *>(&editor);
- if (ed)
- {
- LLRect start_rect = ed->getLocalRectFromDocIndex(mStart);
- LLRect doc_rect = ed->getDocumentPanel()->getRect();
- mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
- }
-}
-
-F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
-{
- return (F32)(draw_rect.mLeft + mView->getRect().getWidth());
-}
-
-S32 LLInlineViewSegment::getMaxHeight() const
-{
- return mView->getRect().getHeight();
-}
-
-void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
-{
- LLTextEditor *ed = dynamic_cast<LLTextEditor *>(editor);
- if (ed)
- {
- ed->removeDocumentChild(mView);
- }
-}
-
-void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
-{
- LLTextEditor *ed = dynamic_cast<LLTextEditor *>(editor);
- if (ed)
- {
- ed->addDocumentChild(mView);
- }
-}
-
BOOL LLTextEditor::isDirty() const
{
if(mReadOnly)
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index a04261c4be..0e5707a3a6 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -37,7 +37,6 @@
#include "llrect.h"
#include "llkeywords.h"
-#include "lluictrl.h"
#include "llframetimer.h"
#include "lldarray.h"
#include "llstyle.h"
@@ -52,66 +51,27 @@
class LLFontGL;
class LLScrollbar;
class LLKeywordToken;
-class LLTextCmd;
+class TextCmd;
class LLUICtrlFactory;
class LLScrollContainer;
-class LLInlineViewSegment : public LLTextSegment
-{
-public:
- LLInlineViewSegment(LLView* widget, S32 start, S32 end);
- ~LLInlineViewSegment();
- /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
- /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
- /*virtual*/ void updateLayout(const class LLTextBase& editor);
- /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
- /*virtuaL*/ S32 getMaxHeight() const;
- /*virtual*/ bool canEdit() const { return false; }
- /*virtual*/ void unlinkFromDocument(class LLTextBase* editor);
- /*virtual*/ void linkToDocument(class LLTextBase* editor);
-
-private:
- LLView* mView;
-};
-
class LLTextEditor :
public LLTextBase,
- public LLUICtrl,
- private LLEditMenuHandler,
protected LLPreeditor
{
public:
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
{
Optional<std::string> default_text;
- Optional<S32> max_text_length;
- Optional<bool> read_only,
- embedded_items,
- word_wrap,
+ Optional<bool> embedded_items,
ignore_tab,
- hide_border,
- track_bottom,
handle_edit_keys_directly,
show_line_numbers,
commit_on_focus_lost;
//colors
- Optional<LLUIColor> cursor_color,
- default_color,
- text_color,
- text_readonly_color,
- bg_readonly_color,
- bg_writeable_color,
- bg_focus_color,
- link_color;
-
- Optional<LLViewBorder::Params> border;
-
- Ignored type,
- length,
- is_unicode,
- hide_scrollbar;
+ Optional<LLUIColor> default_color;
Params();
};
@@ -128,15 +88,6 @@ public:
static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff;
static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
-
- struct compare_segment_end
- {
- bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const
- {
- return a->getEnd() < b->getEnd();
- }
- };
-
virtual ~LLTextEditor();
typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t;
@@ -155,14 +106,9 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask );
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept, std::string& tooltip_msg);
virtual void onMouseCaptureLost();
// view overrides
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void draw();
virtual void onFocusReceived();
virtual void onFocusLost();
@@ -170,11 +116,8 @@ public:
virtual void setEnabled(BOOL enabled);
// uictrl overrides
- virtual void clear();
virtual void setFocus( BOOL b );
- virtual BOOL acceptsTextInput() const;
virtual BOOL isDirty() const;
- virtual void setValue(const LLSD& value);
// LLEditMenuHandler interface
virtual void undo();
@@ -201,12 +144,9 @@ public:
virtual void deselect();
virtual BOOL canDeselect() const;
- virtual void onValueChange(S32 start, S32 end);
-
void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
- BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
void replaceUrlLabel(const std::string &url, const std::string &label);
// Undo/redo stack
@@ -216,9 +156,6 @@ public:
virtual void makePristine();
BOOL isPristine() const;
BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
- S32 getLength() const { return getWText().length(); }
- void setReadOnly(bool read_only) { mReadOnly = read_only; }
- bool getReadOnly() { return mReadOnly; }
//
// Text manipulation
@@ -226,25 +163,10 @@ public:
// inserts text at cursor
void insertText(const std::string &text);
- // appends text at end
- void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline,
- const LLStyle::Params& style = LLStyle::Params());
-
- void appendColoredText(const std::string &wtext, bool allow_undo,
- bool prepend_newline,
- const LLColor4 &color,
- const std::string& font_name = LLStringUtil::null);
- // if styled text starts a line, you need to prepend a newline.
- void appendStyledText(const std::string &new_text, bool allow_undo,
- bool prepend_newline,
- const LLStyle::Params& style);
- void appendHighlightedText(const std::string &new_text, bool allow_undo,
- bool prepend_newline, S32 highlight_part,
- const LLStyle::Params& style);
+
void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline);
// Non-undoable
void setText(const LLStringExplicit &utf8str);
- void setWText(const LLWString &wtext);
// Removes text from the end of document
@@ -253,14 +175,9 @@ public:
BOOL tryToRevertToPristineState();
- bool setCursor(S32 row, S32 column);
- bool setCursorPos(S32 offset, bool keep_cursor_offset = false);
void setCursorAndScrollToEnd();
- void getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap );
void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
- S32 getLineForPosition(S32 position);
- S32 getCurrentLine();
void loadKeywords(const std::string& filename,
const std::vector<std::string>& funcs,
@@ -277,55 +194,17 @@ public:
virtual BOOL importBuffer(const char* buffer, S32 length );
virtual BOOL exportBuffer(std::string& buffer );
- const class DocumentPanel* getDocumentPanel() const { return mDocumentPanel; }
-
const LLUUID& getSourceID() const { return mSourceID; }
- // Callbacks
- std::string getText() const;
-
- // Callback for when a Url has been resolved by the server
- void onUrlLabelUpdated(const std::string &url, const std::string &label);
-
- // Getters
- LLWString getWText() const;
- llwchar getWChar(S32 pos) const { return getWText()[pos]; }
- LLWString getWSubString(S32 pos, S32 len) const { return getWText().substr(pos, len); }
-
- typedef std::vector<LLTextSegmentPtr> segment_vec_t;
-
const LLTextSegmentPtr getPreviousSegment() const;
void getSelectedSegments(segment_vec_t& segments) const;
- void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
- LLRect getLocalRectFromDocIndex(S32 index) const;
-
- void addDocumentChild(LLView* view);
- void removeDocumentChild(LLView* view);
-
protected:
- // Change cursor
- void startOfLine();
- void endOfLine();
- void startOfDoc();
- void endOfDoc();
-
void drawPreeditMarker();
- void needsReflow() { mReflowNeeded = TRUE; }
- void needsScroll() { mScrollNeeded = TRUE; }
- void updateCursorXPos();
-
- void updateScrollFromCursor();
- void updateTextRect();
- const LLRect& getTextRect() const { return mTextRect; }
-
void assignEmbedded(const std::string &s);
- BOOL truncate(); // Returns true if truncation occurs
void removeCharOrTab();
- void setCursorAtLocalPos(S32 x, S32 y, bool round, bool keep_cursor_offset = false);
- /*virtual*/ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
void indentSelectedLines( S32 spaces );
S32 indentLine( S32 pos, S32 spaces );
@@ -340,68 +219,21 @@ protected:
BOOL handleEditKey(const KEY key, const MASK mask);
BOOL selectionContainsLineBreaks();
- void startSelection();
- void endSelection();
void deleteSelection(BOOL transient_operation);
S32 prevWordPos(S32 cursorPos) const;
S32 nextWordPos(S32 cursorPos) const;
- S32 getLineCount() const { return mLineInfoList.size(); }
- S32 getLineStart( S32 line ) const;
- S32 getLineHeight( S32 line ) const;
- void getLineAndOffset(S32 pos, S32* linep, S32* offsetp, bool include_wordwrap = true) const;
- S32 getPos(S32 line, S32 offset);
-
- void changePage(S32 delta);
- void changeLine(S32 delta);
-
void autoIndent();
void findEmbeddedItemSegments(S32 start, S32 end);
- void insertSegment(LLTextSegmentPtr segment_to_insert);
-
+ void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
+
virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
- // Abstract inner base class representing an undoable editor command.
- // Concrete sub-classes can be defined for operations such as insert, remove, etc.
- // Used as arguments to the execute() method below.
- class LLTextCmd
- {
- public:
- LLTextCmd( S32 pos, BOOL group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() )
- : mPos(pos),
- mGroupWithNext(group_with_next)
- {
- if (segment.notNull())
- {
- mSegments.push_back(segment);
- }
- }
- virtual ~LLTextCmd() {}
- virtual BOOL execute(LLTextEditor* editor, S32* delta) = 0;
- virtual S32 undo(LLTextEditor* editor) = 0;
- virtual S32 redo(LLTextEditor* editor) = 0;
- virtual BOOL canExtend(S32 pos) const { return FALSE; }
- virtual void blockExtensions() {}
- virtual BOOL extendAndExecute( LLTextEditor* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; }
- virtual BOOL hasExtCharValue( llwchar value ) const { return FALSE; }
-
- // Defined here so they can access protected LLTextEditor editing methods
- S32 insert(LLTextEditor* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); }
- S32 remove(LLTextEditor* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); }
- S32 overwrite(LLTextEditor* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); }
-
- S32 getPosition() const { return mPos; }
- BOOL groupWithNext() const { return mGroupWithNext; }
-
- protected:
- const S32 mPos;
- BOOL mGroupWithNext;
- segment_vec_t mSegments;
- };
+
// Here's the method that takes and applies text commands.
- S32 execute(LLTextCmd* cmd);
+ S32 execute(TextCmd* cmd);
// Undoable operations
void addChar(llwchar c); // at mCursorPos
@@ -411,15 +243,7 @@ protected:
S32 removeChar(S32 pos);
S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
S32 remove(S32 pos, S32 length, bool group_with_next_op);
- S32 append(const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
- // Direct operations
- S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
- S32 removeStringNoUndo(S32 pos, S32 length);
- S32 overwriteCharNoUndo(S32 pos, llwchar wc);
-
- void resetKeystrokeTimer() { mKeystrokeTimer.reset(); }
-
void updateAllowingLanguageInput();
BOOL hasPreeditString() const;
@@ -432,6 +256,7 @@ protected:
virtual void getSelectionRange(S32 *position, S32 *length) const;
virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
+ virtual LLWString getPreeditString() const { return getWText(); }
//
// Protected data
//
@@ -439,74 +264,31 @@ protected:
// as possible behind protected accessor methods.
//
- // I-beam is just after the mCursorPos-th character.
- S32 mCursorPos;
-
// Use these to determine if a click on an embedded item is a drag or not.
S32 mMouseDownX;
S32 mMouseDownY;
- // Are we in the middle of a drag-select? To figure out if there is a current
- // selection, call hasSelection().
- BOOL mIsSelecting;
- S32 mSelectionStart;
- S32 mSelectionEnd;
- S32 mLastSelectionX;
- S32 mLastSelectionY;
-
- BOOL mParseHighlights;
-
- // Scrollbar data
- class DocumentPanel* mDocumentPanel;
- LLScrollContainer* mScroller;
-
- void *mOnScrollEndData;
-
LLWString mPreeditWString;
LLWString mPreeditOverwrittenWString;
std::vector<S32> mPreeditPositions;
std::vector<BOOL> mPreeditStandouts;
- S32 mScrollIndex; // index into document that controls default scroll position
-
protected:
- LLUIColor mCursorColor;
- LLUIColor mFgColor;
- LLUIColor mDefaultColor;
- LLUIColor mReadOnlyFgColor;
- LLUIColor mWriteableBgColor;
- LLUIColor mReadOnlyBgColor;
- LLUIColor mFocusBgColor;
- LLUIColor mLinkColor;
+ LLUIColor mDefaultColor;
- BOOL mReadOnly;
- BOOL mShowLineNumbers;
+ BOOL mShowLineNumbers;
- void updateSegments();
- void updateLinkSegments();
+ /*virtual*/ void updateSegments();
+ void updateLinkSegments();
private:
-
//
// Methods
//
void pasteHelper(bool is_primary);
- virtual LLTextViewModel* getViewModel() const;
- void reflow(S32 startpos = 0);
-
- void createDefaultSegment();
- LLStyleSP getDefaultStyle();
- S32 getEditableIndex(S32 index, bool increasing_direction);
-
- void drawBackground();
- void drawSelectionBackground();
- void drawCursor();
- void drawText();
void drawLineNumbers();
- S32 getFirstVisibleLine() const;
-
void onKeyStroke();
//
@@ -514,56 +296,25 @@ private:
//
LLKeywords mKeywords;
- // Concrete LLTextCmd sub-classes used by the LLTextEditor base class
- class LLTextCmdInsert;
- class LLTextCmdAddChar;
- class LLTextCmdOverwriteChar;
- class LLTextCmdRemove;
-
- S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
+ // Concrete TextCmd sub-classes used by the LLTextEditor base class
+ class TextCmdInsert;
+ class TextCmdAddChar;
+ class TextCmdOverwriteChar;
+ class TextCmdRemove;
class LLViewBorder* mBorder;
BOOL mBaseDocIsPristine;
- LLTextCmd* mPristineCmd;
+ TextCmd* mPristineCmd;
- LLTextCmd* mLastCmd;
+ TextCmd* mLastCmd;
- typedef std::deque<LLTextCmd*> undo_stack_t;
+ typedef std::deque<TextCmd*> undo_stack_t;
undo_stack_t mUndoStack;
- S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be
- LLRect mTextRect; // The rect in which text is drawn. Excludes borders.
- // List of offsets and segment index of the start of each line. Always has at least one node (0).
- struct line_info
- {
- line_info(S32 index_start, S32 index_end, S32 top, S32 bottom, S32 line_num)
- : mDocIndexStart(index_start),
- mDocIndexEnd(index_end),
- mTop(top),
- mBottom(bottom),
- mLineNum(line_num)
- {}
- S32 mDocIndexStart;
- S32 mDocIndexEnd;
- S32 mTop;
- S32 mBottom;
- S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
- };
- struct compare_bottom;
- struct compare_top;
- struct line_end_compare;
- typedef std::vector<line_info> line_list_t;
- line_list_t mLineInfoList;
- BOOL mReflowNeeded;
- BOOL mScrollNeeded;
-
- LLFrameTimer mKeystrokeTimer;
-
BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces
BOOL mCommitOnFocusLost;
BOOL mTakesFocus;
- BOOL mTrackBottom; // if true, keeps scroll position at bottom during resize
BOOL mAllowEmbeddedItems;
diff --git a/indra/llui/lltextparser.cpp b/indra/llui/lltextparser.cpp
index 707dd0afdd..76a39e3094 100644
--- a/indra/llui/lltextparser.cpp
+++ b/indra/llui/lltextparser.cpp
@@ -103,7 +103,7 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
return found;
}
-LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, S32 part, S32 index)
+LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
{
//evil recursive string atomizer.
LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
@@ -122,7 +122,7 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC
{
S32 end = std::string(mHighlights[i]["pattern"]).length();
S32 len = text.length();
- S32 newpart;
+ EHighlightPosition newpart;
if (start==0)
{
start_llsd[0]["text"] =text.substr(0,end);
diff --git a/indra/llui/lltextparser.h b/indra/llui/lltextparser.h
index fb1a7758b7..072ac0f300 100644
--- a/indra/llui/lltextparser.h
+++ b/indra/llui/lltextparser.h
@@ -34,8 +34,6 @@
#ifndef LL_LLTEXTPARSER_H
#define LL_LLTEXTPARSER_H
-#include "lltextparser.h"
-
#include "llsd.h"
class LLUUID;
@@ -45,17 +43,17 @@ class LLColor4;
class LLTextParser
{
public:
- enum ConditionType { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH };
- enum HighlightType { PART, ALL };
- enum HighlightPosition { WHOLE, START, MIDDLE, END };
- enum DialogAction { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE };
+ typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;
+ typedef enum e_highlight_type { PART, ALL } EHighlightType;
+ typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;
+ typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction;
static LLTextParser* getInstance();
LLTextParser(){};
~LLTextParser();
S32 findPattern(const std::string &text, LLSD highlight);
- LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0);
+ LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
std::string getFileName();
diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp
new file mode 100644
index 0000000000..717e135412
--- /dev/null
+++ b/indra/llui/lltoggleablemenu.cpp
@@ -0,0 +1,82 @@
+/**
+ * @file lltoggleablemenu.cpp
+ * @brief Menu toggled by a button press
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+
+#include "lltoggleablemenu.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLToggleableMenu> r("toggleable_menu");
+
+LLToggleableMenu::LLToggleableMenu(const LLToggleableMenu::Params& p)
+: LLMenuGL(p),
+ mClosedByButtonClick(false)
+{
+}
+
+// virtual
+void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
+{
+ S32 x,y;
+ LLUI::getMousePositionLocal(LLUI::getRootView(), &x, &y);
+
+ if (!curVisibilityIn && mButtonRect.pointInRect(x, y))
+ {
+ mClosedByButtonClick = true;
+ }
+}
+
+void LLToggleableMenu::setButtonRect(const LLRect& rect, LLView* current_view)
+{
+ LLRect screen;
+ current_view->localRectToScreen(rect, &screen);
+ mButtonRect = screen;
+}
+
+bool LLToggleableMenu::toggleVisibility()
+{
+ if (mClosedByButtonClick)
+ {
+ mClosedByButtonClick = false;
+ return false;
+ }
+
+ if (getVisible())
+ {
+ setVisible(FALSE);
+ mClosedByButtonClick = false;
+ return false;
+ }
+
+ return true;
+}
diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h
new file mode 100644
index 0000000000..3cd66e04a8
--- /dev/null
+++ b/indra/llui/lltoggleablemenu.h
@@ -0,0 +1,65 @@
+/**
+ * @file lltoggleablemenu.h
+ * @brief Menu toggled by a button press
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOGGLEABLEMENU_H
+#define LL_LLTOGGLEABLEMENU_H
+
+#include "llmenugl.h"
+
+class LLToggleableMenu : public LLMenuGL
+{
+public:
+ //adding blank params to work around registration issue
+ //where LLToggleableMenu was owning the LLMenuGL param
+ //and menu.xml was never loaded
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {};
+protected:
+ LLToggleableMenu(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual void handleVisibilityChange (BOOL curVisibilityIn);
+
+ // Converts the given local button rect to a screen rect
+ void setButtonRect(const LLRect& rect, LLView* current_view);
+
+ // Returns "true" if menu was not closed by button click
+ // and is not still visible. If menu is visible toggles
+ // its visibility off.
+ bool toggleVisibility();
+
+protected:
+ bool mClosedByButtonClick;
+ LLRect mButtonRect;
+};
+
+#endif // LL_LLTOGGLEABLEMENU_H
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 5c017dabd7..8f5c029816 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -36,7 +36,6 @@
#include "lltooltip.h"
// Library includes
-#include "llpanel.h"
#include "lltextbox.h"
#include "lliconctrl.h"
#include "llui.h" // positionViewNearMouse()
@@ -45,7 +44,6 @@
//
// Constants
//
-const F32 DELAY_BEFORE_SHOW_TIP = 0.35f;
//
// Local globals
@@ -57,6 +55,11 @@ LLToolTipView *gToolTipView = NULL;
// Member functions
//
+LLToolTipView::Params::Params()
+{
+ mouse_opaque = false;
+}
+
LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
: LLView(p)
{
@@ -64,10 +67,7 @@ LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
void LLToolTipView::draw()
{
- if (LLUI::getWindow()->isCursorHidden() )
- {
- LLToolTipMgr::instance().hideToolTips();
- }
+ LLToolTipMgr::instance().updateToolTipVisibility();
// do the usual thing
LLView::draw();
@@ -80,17 +80,10 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
- // hide existing tooltips when mouse moves out of sticky rect
- if (tooltip_mgr.toolTipVisible()
- && !tooltip_mgr.getStickyRect().pointInRect(x, y))
- {
- tooltip_mgr.hideToolTips();
- }
-
- // allow new tooltips whenever mouse moves
if (x != last_x && y != last_y)
{
- tooltip_mgr.enableToolTips();
+ // allow new tooltips because mouse moved
+ tooltip_mgr.unblockToolTips();
}
last_x = x;
@@ -100,96 +93,84 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
return LLView::handleMouseDown(x, y, mask);
}
BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
return LLView::handleMiddleMouseDown(x, y, mask);
}
BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
return LLView::handleRightMouseDown(x, y, mask);
}
BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
{
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
return FALSE;
}
void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
}
void LLToolTipView::drawStickyRect()
{
- gl_rect_2d(LLToolTipMgr::instance().getStickyRect(), LLColor4::white, false);
+ gl_rect_2d(LLToolTipMgr::instance().getMouseNearRect(), LLColor4::white, false);
}
//
// LLToolTip
//
-class LLToolTip : public LLPanel
-{
-public:
- struct Params : public LLInitParam::Block<Params, LLPanel::Params>
- {
- Mandatory<F32> visible_time;
-
- Optional<LLToolTipParams::click_callback_t> click_callback;
- Optional<LLUIImage*> image;
-
- Params()
- {
- //use_bounding_rect = true;
- }
- };
- /*virtual*/ void draw();
- /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
-
- /*virtual*/ void setValue(const LLSD& value);
- /*virtual*/ void setVisible(BOOL visible);
- bool isFading() { return mFadeTimer.getStarted(); }
-
- LLToolTip(const Params& p);
-
-private:
- LLTextBox* mTextBox;
- LLFrameTimer mFadeTimer;
- F32 mVisibleTime;
- bool mHasClickCallback;
-};
static LLDefaultChildRegistry::Register<LLToolTip> r("tool_tip");
-const S32 TOOLTIP_PADDING = 4;
+
+LLToolTip::Params::Params()
+: max_width("max_width", 200),
+ padding("padding", 4),
+ pos("pos"),
+ message("message"),
+ delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
+ visible_time_over("visible_time_over", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeOver" )),
+ visible_time_near("visible_time_near", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeNear" )),
+ visible_time_far("visible_time_far", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeFar" )),
+ sticky_rect("sticky_rect"),
+ image("image")
+{
+ name = "tooltip";
+ font = LLFontGL::getFontSansSerif();
+ bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
+ background_visible = true;
+}
LLToolTip::LLToolTip(const LLToolTip::Params& p)
: LLPanel(p),
- mVisibleTime(p.visible_time),
- mHasClickCallback(p.click_callback.isProvided())
+ mMaxWidth(p.max_width),
+ mHasClickCallback(p.click_callback.isProvided()),
+ mPadding(p.padding)
{
LLTextBox::Params params;
- params.text = "tip_text";
- params.name = params.text;
+ params.initial_value = "tip_text";
+ params.name = params.initial_value().asString();
// bake textbox padding into initial rect
- params.rect = LLRect (TOOLTIP_PADDING, TOOLTIP_PADDING + 1, TOOLTIP_PADDING + 1, TOOLTIP_PADDING);
+ params.rect = LLRect (mPadding, mPadding + 1, mPadding + 1, mPadding);
params.follows.flags = FOLLOWS_ALL;
- params.h_pad = 4;
- params.v_pad = 2;
+ params.h_pad = 0;
+ params.v_pad = 0;
params.mouse_opaque = false;
params.text_color = LLUIColorTable::instance().getColor( "ToolTipTextColor" );
params.bg_visible = false;
- params.font.style = "NORMAL";
- //params.border_drop_shadow_visible = true;
+ params.font = p.font;
+ params.use_ellipses = true;
mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mTextBox);
@@ -198,8 +179,9 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
LLIconCtrl::Params icon_params;
icon_params.name = "tooltip_icon";
LLRect icon_rect;
- const S32 TOOLTIP_ICON_SIZE = 18;
- icon_rect.setOriginAndSize(TOOLTIP_PADDING, TOOLTIP_PADDING, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+ LLUIImage* imagep = p.image;
+ const S32 TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
+ icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
icon_params.rect = icon_rect;
icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
icon_params.image = p.image;
@@ -218,13 +200,20 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
void LLToolTip::setValue(const LLSD& value)
{
- mTextBox->setWrappedText(value.asString());
- mTextBox->reshapeToFitText();
+ const S32 REALLY_LARGE_HEIGHT = 10000;
+ reshape(mMaxWidth, REALLY_LARGE_HEIGHT);
+
+ mTextBox->setValue(value);
+
+ LLRect text_contents_rect = mTextBox->getContentsRect();
+ S32 text_width = llmin(mMaxWidth, text_contents_rect.getWidth());
+ S32 text_height = text_contents_rect.getHeight();
+ mTextBox->reshape(text_width, text_height);
// reshape tooltip panel to fit text box
LLRect tooltip_rect = calcBoundingRect();
- tooltip_rect.mTop += TOOLTIP_PADDING;
- tooltip_rect.mRight += TOOLTIP_PADDING;
+ tooltip_rect.mTop += mPadding;
+ tooltip_rect.mRight += mPadding;
tooltip_rect.mBottom = 0;
tooltip_rect.mLeft = 0;
@@ -234,19 +223,21 @@ void LLToolTip::setValue(const LLSD& value)
void LLToolTip::setVisible(BOOL visible)
{
// fade out tooltip over time
- if (!visible)
+ if (visible)
+ {
+ mVisibleTimer.start();
+ mFadeTimer.stop();
+ LLPanel::setVisible(TRUE);
+ }
+ else
{
+ mVisibleTimer.stop();
// don't actually change mVisible state, start fade out transition instead
if (!mFadeTimer.getStarted())
{
mFadeTimer.start();
}
}
- else
- {
- mFadeTimer.stop();
- LLPanel::setVisible(TRUE);
- }
}
BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
@@ -263,11 +254,6 @@ void LLToolTip::draw()
{
F32 alpha = 1.f;
- if (LLUI::getMouseIdleTime() > mVisibleTime)
- {
- LLToolTipMgr::instance().hideToolTips();
- }
-
if (mFadeTimer.getStarted())
{
F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime");
@@ -287,94 +273,90 @@ void LLToolTip::draw()
}
}
+bool LLToolTip::isFading()
+{
+ return mFadeTimer.getStarted();
+}
+
+F32 LLToolTip::getVisibleTime()
+{
+ return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f;
+}
+
+bool LLToolTip::hasClickCallback()
+{
+ return mHasClickCallback;
+}
//
// LLToolTipMgr
//
-LLToolTipParams::LLToolTipParams()
-: pos("pos"),
- message("message"),
- delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
- visible_time("visible_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTime" )),
- sticky_rect("sticky_rect"),
- width("width", 200),
- image("image")
-{}
LLToolTipMgr::LLToolTipMgr()
-: mToolTip(NULL)
-{
-}
+: mToolTip(NULL),
+ mNeedsToolTip(false)
+{}
-LLToolTip* LLToolTipMgr::createToolTip(const LLToolTipParams& params)
+void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
{
- S32 mouse_x;
- S32 mouse_y;
- LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
+ // block all other tooltips until tooltips re-enabled (e.g. mouse moved)
+ blockToolTips();
+ delete mToolTip;
- LLToolTip::Params tooltip_params;
- tooltip_params.name = "tooltip";
- tooltip_params.mouse_opaque = true;
+ LLToolTip::Params tooltip_params(params);
+ // block mouse events if there is a click handler registered (specifically, hover)
+ tooltip_params.mouse_opaque = params.click_callback.isProvided();
tooltip_params.rect = LLRect (0, 1, 1, 0);
- tooltip_params.bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
- tooltip_params.background_visible = true;
- tooltip_params.visible_time = params.visible_time;
- if (params.image.isProvided())
- {
- tooltip_params.image = params.image;
- }
- if (params.click_callback.isProvided())
- {
- tooltip_params.click_callback = params.click_callback;
- }
-
- LLToolTip* tooltip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
- // make tooltip fixed width and tall enough to fit text
- tooltip->reshape(params.width, 2000);
- tooltip->setValue(params.message());
- gToolTipView->addChild(tooltip);
+ mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
+ mToolTip->setValue(params.message());
+ gToolTipView->addChild(mToolTip);
if (params.pos.isProvided())
{
+ LLCoordGL pos = params.pos;
// try to spawn at requested position
- LLUI::positionViewNearMouse(tooltip, params.pos.x, params.pos.y);
+ LLUI::positionViewNearMouse(mToolTip, pos.mX, pos.mY);
}
else
{
// just spawn at mouse location
- LLUI::positionViewNearMouse(tooltip);
+ LLUI::positionViewNearMouse(mToolTip);
}
//...update "sticky" rect and tooltip position
if (params.sticky_rect.isProvided())
{
- mToolTipStickyRect = params.sticky_rect;
+ mMouseNearRect = params.sticky_rect;
}
else
{
- // otherwise just use one pixel rect around mouse cursor
- mToolTipStickyRect.setOriginAndSize(mouse_x, mouse_y, 1, 1);
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
+
+ // allow mouse a little bit of slop before changing tooltips
+ mMouseNearRect.setCenterAndSize(mouse_x, mouse_y, 3, 3);
}
-
- if (params.click_callback.isProvided())
+
+ // allow mouse to move all the way to the tooltip without changing tooltips
+ // (tooltip can still time out)
+ if (mToolTip->hasClickCallback())
{
// keep tooltip up when we mouse over it
- mToolTipStickyRect.unionWith(tooltip->getRect());
+ mMouseNearRect.unionWith(mToolTip->getRect());
}
-
- return tooltip;
}
void LLToolTipMgr::show(const std::string& msg)
{
- show(LLToolTipParams().message(msg));
+ show(LLToolTip::Params().message(msg));
}
-void LLToolTipMgr::show(const LLToolTipParams& params)
+void LLToolTipMgr::show(const LLToolTip::Params& params)
{
if (!params.validateBlock())
{
@@ -382,38 +364,42 @@ void LLToolTipMgr::show(const LLToolTipParams& params)
return;
}
- bool tooltip_shown = mToolTip
- && mToolTip->getVisible()
- && !mToolTip->isFading();
-
- // if tooltip contents change, hide existing tooltip
- if (tooltip_shown && mLastToolTipMessage != params.message())
- {
- hideToolTips();
- }
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
+ // are we ready to show the tooltip?
if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc.
- && LLUI::getMouseIdleTime() > params.delay_time // the mouse has been still long enough
- && !tooltip_shown) // tooltip not visible
+ && LLUI::getMouseIdleTime() > params.delay_time) // the mouse has been still long enough
{
- // create new tooltip at mouse cursor position
- delete mToolTip;
- mToolTip = createToolTip(params);
+ bool tooltip_changed = mLastToolTipParams.message() != params.message()
+ || mLastToolTipParams.pos() != params.pos();
+
+ bool tooltip_shown = mToolTip
+ && mToolTip->getVisible()
+ && !mToolTip->isFading();
- // remember this tooltip so we know when it changes
- mLastToolTipMessage = params.message();
+ mNeedsToolTip = tooltip_changed || !tooltip_shown;
+ // store description of tooltip for later creation
+ mNextToolTipParams = params;
}
}
// allow new tooltips to be created, e.g. after mouse has moved
-void LLToolTipMgr::enableToolTips()
+void LLToolTipMgr::unblockToolTips()
{
mToolTipsBlocked = false;
}
+// disallow new tooltips until unblockTooltips called
+void LLToolTipMgr::blockToolTips()
+{
+ hideToolTips();
+ mToolTipsBlocked = true;
+}
+
void LLToolTipMgr::hideToolTips()
{
- mToolTipsBlocked = true;
if (mToolTip)
{
mToolTip->setVisible(FALSE);
@@ -422,7 +408,7 @@ void LLToolTipMgr::hideToolTips()
bool LLToolTipMgr::toolTipVisible()
{
- return mToolTip ? mToolTip->getVisible() : false;
+ return mToolTip ? mToolTip->isInVisibleChain() : false;
}
LLRect LLToolTipMgr::getToolTipRect()
@@ -435,11 +421,63 @@ LLRect LLToolTipMgr::getToolTipRect()
}
-LLRect LLToolTipMgr::getStickyRect()
+LLRect LLToolTipMgr::getMouseNearRect()
{
- if (!mToolTip) return LLRect();
+ return toolTipVisible() ? mMouseNearRect : LLRect();
+}
+
+// every frame, determine if current tooltip should be hidden
+void LLToolTipMgr::updateToolTipVisibility()
+{
+ // create new tooltip if we have one ready to go
+ if (mNeedsToolTip)
+ {
+ mNeedsToolTip = false;
+ createToolTip(mNextToolTipParams);
+ mLastToolTipParams = mNextToolTipParams;
+
+ return;
+ }
- return mToolTip->isInVisibleChain() ? mToolTipStickyRect : LLRect();
+ // hide tooltips when mouse cursor is hidden
+ if (LLUI::getWindow()->isCursorHidden())
+ {
+ blockToolTips();
+ return;
+ }
+
+ // hide existing tooltips if they have timed out
+ S32 mouse_x, mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
+
+ F32 tooltip_timeout = 0.f;
+ if (toolTipVisible())
+ {
+ // mouse far away from tooltip
+ tooltip_timeout = mLastToolTipParams.visible_time_far;
+ // mouse near rect will only include the tooltip if the
+ // tooltip is clickable
+ if (mMouseNearRect.pointInRect(mouse_x, mouse_y))
+ {
+ // mouse "close" to tooltip
+ tooltip_timeout = mLastToolTipParams.visible_time_near;
+
+ // if tooltip is clickable (has large mMouseNearRect)
+ // than having cursor over tooltip keeps it up indefinitely
+ if (mToolTip->parentPointInView(mouse_x, mouse_y))
+ {
+ // mouse over tooltip itself, don't time out
+ tooltip_timeout = mLastToolTipParams.visible_time_over;
+ }
+ }
+
+ if (mToolTip->getVisibleTime() > tooltip_timeout)
+ {
+ hideToolTips();
+ }
+ }
}
+
+
// EOF
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index fb7f942099..6715da1611 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -36,7 +36,7 @@
// Library includes
#include "llsingleton.h"
#include "llinitparam.h"
-#include "llview.h"
+#include "llpanel.h"
//
// Classes
@@ -46,10 +46,7 @@ class LLToolTipView : public LLView
public:
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- Params()
- {
- mouse_opaque = false;
- }
+ Params();
};
LLToolTipView(const LLToolTipView::Params&);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
@@ -65,57 +62,82 @@ public:
/*virtual*/ void draw();
};
-struct LLToolTipPosParams : public LLInitParam::Block<LLToolTipPosParams>
+class LLToolTip : public LLPanel
{
- Mandatory<S32> x,
- y;
- LLToolTipPosParams()
- : x("x"),
- y("y")
- {}
-};
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ typedef boost::function<void(void)> click_callback_t;
-struct LLToolTipParams : public LLInitParam::Block<LLToolTipParams>
-{
- typedef boost::function<void(void)> click_callback_t;
+ Mandatory<std::string> message;
+
+ Optional<LLCoordGL> pos;
+ Optional<F32> delay_time,
+ visible_time_over, // time for which tooltip is visible while mouse on it
+ visible_time_near, // time for which tooltip is visible while mouse near it
+ visible_time_far; // time for which tooltip is visible while mouse moved away
+ Optional<LLRect> sticky_rect;
+ Optional<const LLFontGL*> font;
- Mandatory<std::string> message;
-
- Optional<LLToolTipPosParams> pos;
- Optional<F32> delay_time,
- visible_time;
- Optional<LLRect> sticky_rect;
- Optional<S32> width;
- Optional<LLUIImage*> image;
+ Optional<click_callback_t> click_callback;
+ Optional<LLUIImage*> image;
+ Optional<S32> max_width;
+ Optional<S32> padding;
+
+ Params();
+ };
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- Optional<click_callback_t> click_callback;
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ void setVisible(BOOL visible);
- LLToolTipParams();
- LLToolTipParams(const std::string& message);
+ bool isFading();
+ F32 getVisibleTime();
+ bool hasClickCallback();
+
+ LLToolTip(const Params& p);
+
+private:
+ class LLTextBox* mTextBox;
+ LLFrameTimer mFadeTimer;
+ LLFrameTimer mVisibleTimer;
+ S32 mMaxWidth;
+ bool mHasClickCallback;
+ S32 mPadding; // pixels
};
+
class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
{
LOG_CLASS(LLToolTipMgr);
public:
LLToolTipMgr();
- void show(const LLToolTipParams& params);
+ void show(const LLToolTip::Params& params);
void show(const std::string& message);
- void enableToolTips();
+ void unblockToolTips();
+ void blockToolTips();
+
void hideToolTips();
bool toolTipVisible();
LLRect getToolTipRect();
-
- LLRect getStickyRect();
+ LLRect getMouseNearRect();
+ void updateToolTipVisibility();
private:
- class LLToolTip* createToolTip(const LLToolTipParams& params);
+ void createToolTip(const LLToolTip::Params& params);
bool mToolTipsBlocked;
class LLToolTip* mToolTip;
- std::string mLastToolTipMessage;
- LLRect mToolTipStickyRect;
+
+ // tooltip creation is deferred until the UI is drawn every frame
+ // so the last tooltip to be created in a given frame will win
+ LLToolTip::Params mLastToolTipParams; // description of last tooltip we showed
+ LLToolTip::Params mNextToolTipParams; // description of next tooltip we want to show
+ bool mNeedsToolTip; // do we want to show a tooltip
+
+ LLRect mMouseNearRect;
};
//
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index d5b67f53b7..c89e5944fa 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -55,6 +55,7 @@
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llmenugl.h"
+#include "llmenubutton.h"
#include "llwindow.h"
// for registration
@@ -90,6 +91,7 @@ std::list<std::string> gUntranslated;
static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button");
static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor");
+static LLDefaultChildRegistry::Register<LLMenuButton> register_menu_button("menu_button");
//
@@ -1644,6 +1646,17 @@ void LLUI::setMousePositionScreen(S32 x, S32 y)
}
//static
+void LLUI::getMousePositionScreen(S32 *x, S32 *y)
+{
+ LLCoordWindow cursor_pos_window;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+ LLCoordGL cursor_pos_gl;
+ getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+ *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);
+ *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);
+}
+
+//static
void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
{
S32 screen_x, screen_y;
@@ -1655,15 +1668,12 @@ void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
//static
void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y)
{
- LLCoordWindow cursor_pos_window;
- LLView::getWindow()->getCursorPosition(&cursor_pos_window);
- LLCoordGL cursor_pos_gl;
- LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
- cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]);
- cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
- viewp->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, x, y);
+ S32 screen_x, screen_y;
+ getMousePositionScreen(&screen_x, &screen_y);
+ viewp->screenPointToLocal(screen_x, screen_y, x, y);
}
+
// On Windows, the user typically sets the language when they install the
// app (by running it with a shortcut that sets InstallLanguage). On Mac,
// or on Windows if the SecondLife.exe executable is run directly, the
@@ -1835,14 +1845,14 @@ LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
// spawn_x and spawn_y are top left corner of view in screen GL coordinates
void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
{
- const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
- const S32 CURSOR_WIDTH = 12;
+ const S32 CURSOR_HEIGHT = 18; // Approximate "normal" cursor size
+ const S32 CURSOR_WIDTH = 9;
LLView* parent = view->getParent();
S32 mouse_x;
S32 mouse_y;
- LLUI::getMousePositionLocal(parent, &mouse_x, &mouse_y);
+ LLUI::getMousePositionScreen(&mouse_x, &mouse_y);
// If no spawn location provided, use mouse position
if (spawn_x == S32_MAX || spawn_y == S32_MAX)
@@ -1856,12 +1866,13 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
LLRect mouse_rect;
const S32 MOUSE_CURSOR_PADDING = 5;
mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING,
- mouse_y + MOUSE_CURSOR_PADDING,
- CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
- CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
+ mouse_y + MOUSE_CURSOR_PADDING,
+ CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
+ CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
S32 local_x, local_y;
- view->getParent()->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y);
+ // convert screen coordinates to tooltipview-local coordinates
+ parent->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y);
// Start at spawn position (using left/top)
view->setOrigin( local_x, local_y - view->getRect().getHeight());
@@ -1915,12 +1926,14 @@ namespace LLInitParam
}
};
- TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
- : super_t(descriptor, name, value, func, min_count, max_count),
- name(""),
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count),
+ name("name"),
size("size"),
style("style")
- {}
+ {
+ addSynonym(name, "");
+ }
const LLFontGL* TypedParam<const LLFontGL*>::getValueFromBlock() const
{
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 86cb516500..f071e8dc47 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -190,6 +190,7 @@ public:
static void setRootView(LLView* view) { sRootView = view; }
static std::string locateSkin(const std::string& filename);
static void setMousePositionScreen(S32 x, S32 y);
+ static void getMousePositionScreen(S32 *x, S32 *y);
static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y);
static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
static void setScaleFactor(const LLVector2& scale_factor);
@@ -409,8 +410,8 @@ namespace LLInitParam
{
typedef BlockValue<const LLFontGL*> super_t;
public:
- Optional<std::string> name,
- size,
+ Mandatory<std::string> name;
+ Optional<std::string> size,
style;
TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index fe99d9c267..5b72f87a78 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -49,7 +49,12 @@ LLUICtrl::Params::Params()
validate_callback("validate_callback"),
mouseenter_callback("mouseenter_callback"),
mouseleave_callback("mouseleave_callback"),
- control_name("control_name")
+ control_name("control_name"),
+ font("font", LLFontGL::getFontSansSerif()),
+ font_halign("halign"),
+ font_valign("valign"),
+ length("length"), // ignore LLXMLNode cruft
+ type("type") // ignore LLXMLNode cruft
{
addSynonym(initial_value, "initial_value");
}
@@ -212,6 +217,29 @@ void LLUICtrl::initEnableCallback(const EnableCallbackParam& cb, enable_signal_t
}
}
+void LLUICtrl::initVisibleCallback(const VisibleCallbackParam& cb, visible_signal_t& sig)
+{
+ // Set the callback function
+ if (cb.function.isProvided())
+ {
+ if (cb.parameter.isProvided())
+ sig.connect(boost::bind(cb.function(), this, cb.parameter));
+ else
+ sig.connect(cb.function());
+ }
+ else
+ {
+ visible_callback_t* func = (VisibleCallbackRegistry::getValue(cb.function_name));
+ if (func)
+ {
+ if (cb.parameter.isProvided())
+ sig.connect(boost::bind((*func), this, cb.parameter));
+ else
+ sig.connect(*func);
+ }
+ }
+}
+
// virtual
void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index c2502732f3..69207eb8ea 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -34,14 +34,15 @@
#ifndef LL_LLUICTRL_H
#define LL_LLUICTRL_H
-#include "llboost.h"
+//#include "llboost.h"
#include "llrect.h"
#include "llsd.h"
#include <boost/function.hpp>
+#include <boost/signals2.hpp>
#include "llinitparam.h"
#include "llview.h"
-#include "llviewmodel.h"
+#include "llviewmodel.h" // *TODO move dependency to .cpp file
const BOOL TAKE_FOCUS_YES = TRUE;
const BOOL TAKE_FOCUS_NO = FALSE;
@@ -62,6 +63,9 @@ public:
typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
+ typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> visible_callback_t;
+ typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> visible_signal_t;
+
struct CallbackParam : public LLInitParam::Block<CallbackParam>
{
Ignored name;
@@ -91,6 +95,11 @@ public:
Optional<enable_callback_t> function;
};
+ struct VisibleCallbackParam : public LLInitParam::Block<VisibleCallbackParam, CallbackParam >
+ {
+ Optional<visible_callback_t> function;
+ };
+
struct EnableControls : public LLInitParam::Choice<EnableControls>
{
Alternative<std::string> enabled;
@@ -107,9 +116,12 @@ public:
Alternative<std::string> invisible;
ControlVisibility()
- : visible("visiblity_control"),
- invisible("invisiblity_control")
- {}
+ : visible("visibility_control"),
+ invisible("invisibility_control")
+ {
+ addSynonym(visible, "visiblity_control");
+ addSynonym(invisible, "invisiblity_control");
+ }
};
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
@@ -128,6 +140,15 @@ public:
Optional<EnableControls> enabled_controls;
Optional<ControlVisibility> controls_visibility;
+ // font params
+ Optional<const LLFontGL*> font;
+ Optional<LLFontGL::HAlign> font_halign;
+ Optional<LLFontGL::VAlign> font_valign;
+
+ // cruft from LLXMLNode implementation
+ Ignored type,
+ length;
+
Params();
};
@@ -142,6 +163,7 @@ protected:
void initCommitCallback(const CommitCallbackParam& cb, commit_signal_t& sig);
void initEnableCallback(const EnableCallbackParam& cb, enable_signal_t& sig);
+ void initVisibleCallback(const VisibleCallbackParam& cb, visible_signal_t& sig);
// We need this virtual so we can override it with derived versions
virtual LLViewModel* getViewModel() const;
@@ -259,6 +281,8 @@ public:
class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
+ class VisibleCallbackRegistry : public CallbackRegistry<visible_callback_t, VisibleCallbackRegistry>{};
+
protected:
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 538e1ec492..4ce6677294 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -113,8 +113,20 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const wid
if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, registry, outputChild))
{
+ // child_node is not a valid child for the current parent
std::string child_name = std::string(child_node->getName()->mString);
- llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
+ if (LLDefaultChildRegistry::instance().getValue(child_name))
+ {
+ // This means that the registry assocaited with the parent widget does not have an entry
+ // for the child widget
+ // You might need to add something like:
+ // static ParentWidgetRegistry::Register<ChildWidgetType> register("child_widget_name");
+ llwarns << child_name << " is not a valid child of " << node->getName()->mString << llendl;
+ }
+ else
+ {
+ llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
+ }
}
if (outputChild && !outputChild->mChildren && outputChild->mAttributes.empty() && outputChild->getValue().empty())
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index c20212c375..c1da73fa83 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -36,8 +36,10 @@
#include "lluri.h"
#include "llcachename.h"
#include "lltrans.h"
+#include "lluicolortable.h"
LLUrlEntryBase::LLUrlEntryBase()
+: mColor(LLUIColorTable::instance().getColor("HTMLLinkColor"))
{
}
@@ -260,10 +262,11 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
//
LLUrlEntryAgent::LLUrlEntryAgent()
{
- mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/about",
+ mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_agent.xml";
- mTooltip = LLTrans::getString("TooltipAgentUrl");
+ mIcon = "Generic_Person";
+ mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}
void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
@@ -293,7 +296,7 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
}
- return unescapeUrl(url);
+ return LLTrans::getString("LoadingData");//unescapeUrl(url);
}
//
@@ -305,6 +308,7 @@ LLUrlEntryGroup::LLUrlEntryGroup()
mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/about",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_group.xml";
+ mIcon = "Generic_Group";
mTooltip = LLTrans::getString("TooltipGroupUrl");
}
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 54053872df..afb2fdcde9 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -35,7 +35,7 @@
#define LL_LLURLENTRY_H
#include "lluuid.h"
-
+#include "lluicolor.h"
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
@@ -77,13 +77,16 @@ public:
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
- const std::string &getIcon() const { return mIcon; }
+ std::string getIcon() const { return mIcon; }
+
+ /// Return the color to render the displayed text
+ LLUIColor getColor() const { return mColor; }
/// Given a matched Url, return a tooltip string for the hyperlink
std::string getTooltip() const { return mTooltip; }
/// Return the name of a XUI file containing the context menu items
- const std::string getMenuName() const { return mMenuName; }
+ std::string getMenuName() const { return mMenuName; }
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
@@ -102,11 +105,12 @@ protected:
LLUrlLabelSignal *signal;
} LLUrlEntryObserver;
- boost::regex mPattern;
- std::string mIcon;
- std::string mMenuName;
- std::string mTooltip;
- std::multimap<std::string, LLUrlEntryObserver> mObservers;
+ boost::regex mPattern;
+ std::string mIcon;
+ std::string mMenuName;
+ std::string mTooltip;
+ LLUIColor mColor;
+ std::multimap<std::string, LLUrlEntryObserver> mObservers;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index 7eec4c4a65..3b47145a22 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -47,8 +47,8 @@ LLUrlMatch::LLUrlMatch() :
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
- const std::string &icon, const std::string &menu,
- const std::string &location)
+ const std::string &icon, const LLUIColor& color,
+ const std::string &menu, const std::string &location)
{
mStart = start;
mEnd = end;
@@ -56,6 +56,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
+ mColor = color;
mMenuName = menu;
mLocation = location;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 0711e41443..7f5767923a 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -38,6 +38,7 @@
#include <string>
#include <vector>
+#include "lluicolor.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
@@ -62,27 +63,31 @@ public:
U32 getEnd() const { return mEnd; }
/// return the Url that has been matched in the input string
- const std::string &getUrl() const { return mUrl; }
+ std::string getUrl() const { return mUrl; }
/// return a label that can be used for the display of this Url
- const std::string &getLabel() const { return mLabel; }
+ std::string getLabel() const { return mLabel; }
/// return a message that could be displayed in a tooltip or status bar
- const std::string &getTooltip() const { return mTooltip; }
+ std::string getTooltip() const { return mTooltip; }
/// return the filename for an icon that can be displayed next to this Url
- const std::string &getIcon() const { return mIcon; }
+ std::string getIcon() const { return mIcon; }
+
+ /// Return the color to render the displayed text
+ LLUIColor getColor() const { return mColor; }
/// Return the name of a XUI file containing the context menu items
- const std::string getMenuName() const { return mMenuName; }
+ std::string getMenuName() const { return mMenuName; }
/// return the SL location that this Url describes, or "" if none.
- const std::string &getLocation() const { return mLocation; }
+ std::string getLocation() const { return mLocation; }
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
- const std::string &menu, const std::string &location);
+ const LLUIColor& color, const std::string &menu,
+ const std::string &location);
private:
U32 mStart;
@@ -93,6 +98,7 @@ private:
std::string mIcon;
std::string mMenuName;
std::string mLocation;
+ LLUIColor mColor;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 6f5c694b1b..8413de0837 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -155,6 +155,7 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getLabel(url, cb),
match_entry->getTooltip(),
match_entry->getIcon(),
+ match_entry->getColor(),
match_entry->getMenuName(),
match_entry->getLocation(url));
return true;
@@ -183,9 +184,10 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
}
S32 end = start + wurl.size() - 1;
- match.setValues(start, end, match.getUrl(), match.getLabel(),
- match.getTooltip(), match.getIcon(),
- match.getMenuName(), match.getLocation());
+ match.setValues(start, end, match.getUrl(),
+ match.getLabel(), match.getTooltip(),
+ match.getIcon(), match.getColor(),
+ match.getMenuName(), match.getLocation());
return true;
}
return false;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 10cb3fb377..1df8838738 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -92,9 +92,6 @@ LLView::Params::Params()
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),
@@ -172,12 +169,6 @@ LLView::~LLView()
}
// virtual
-BOOL LLView::isView() const
-{
- return TRUE;
-}
-
-// virtual
BOOL LLView::isCtrl() const
{
return FALSE;
@@ -227,10 +218,9 @@ BOOL LLView::getUseBoundingRect()
}
// virtual
-const std::string& LLView::getName() const
+std::string LLView::getName() const
{
- static const std::string unnamed("(no name)");
- return mName.empty() ? unnamed : mName;
+ return mName.empty() ? std::string("(no name)") : mName;
}
void LLView::sendChildToFront(LLView* child)
@@ -634,16 +624,7 @@ void LLView::setSnappedTo(const LLView* snap_view)
BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleHover( x, y, mask ) != NULL;
- if( !handled
- && blockMouseEvent(x, y) )
- {
- LLUI::sWindow->setCursor(mHoverCursor);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- handled = TRUE;
- }
-
- return handled;
+ return childrenHandleHover( x, y, mask ) != NULL;
}
void LLView::onMouseEnter(S32 x, S32 y, MASK mask)
@@ -657,7 +638,7 @@ void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
}
-LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
{
LLView* handled_view = NULL;
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
@@ -665,13 +646,13 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if(!viewp->pointInView(local_x, local_y) ||
- !viewp->getVisible())
+ if(!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible())
{
continue;
}
- if(viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) )
+ if (viewp->handleToolTip(local_x, local_y, mask) )
{
if (sDebugMouseHandling)
{
@@ -682,20 +663,22 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st
break;
}
- if( viewp->blockMouseEvent(x, y) )
+ if (viewp->blockMouseEvent(local_x, local_y))
{
handled_view = viewp;
+ break;
}
}
return handled_view;
}
-BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+
+BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
// parents provide tooltips first, which are optionally
- // overridden by children
+ // overridden by children, in case child is mouse_opaque
if (!mToolTipMsg.empty())
{
// allow "scrubbing" over ui by showing next tooltip immediately
@@ -703,7 +686,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_s
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
? 0.f
: LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" );
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(mToolTipMsg)
.sticky_rect(calcScreenRect())
.delay_time(timeout));
@@ -712,7 +695,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_s
}
// child tooltips will override our own
- LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen);
+ LLView* child_handler = childrenHandleToolTip(x, y, mask);
if (child_handler)
{
handled = TRUE;
@@ -720,7 +703,6 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_s
return handled;
}
-
BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
@@ -801,20 +783,7 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EAcceptance* accept,
std::string& tooltip_msg)
{
- // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent
- BOOL handled = childrenHandleDragAndDrop( x, y, mask, drop,
- cargo_type,
- cargo_data,
- accept,
- tooltip_msg) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- *accept = ACCEPT_NO;
- handled = TRUE;
- lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLView " << getName() << llendl;
- }
-
- return handled;
+ return childrenHandleDragAndDrop( x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL;
}
LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
@@ -824,28 +793,33 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
EAcceptance* accept,
std::string& tooltip_msg)
{
- LLView* handled_view = FALSE;
- // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent
- if( getVisible() )
-// if( getVisible() && getEnabled() )
+ LLView* handled_view = NULL;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if( !viewp->pointInView(local_x, local_y) ||
+ !viewp->getVisible() ||
+ !viewp->getEnabled())
{
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleDragAndDrop(local_x, local_y, mask, drop,
- cargo_type,
- cargo_data,
- accept,
- tooltip_msg))
- {
- handled_view = viewp;
- break;
- }
+ continue;
+ }
+ if (viewp->handleDragAndDrop(local_x, local_y, mask, drop,
+ cargo_type,
+ cargo_data,
+ accept,
+ tooltip_msg))
+ {
+ handled_view = viewp;
+ break;
+ }
+
+ if (viewp->blockMouseEvent(x, y))
+ {
+ *accept = ACCEPT_NO;
+ handled_view = viewp;
+ break;
}
}
return handled_view;
@@ -862,105 +836,42 @@ BOOL LLView::hasMouseCapture()
BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleMouseUp( x, y, mask ) != NULL;
}
BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = childrenHandleMouseDown( x, y, mask );
- BOOL handled = (handled_view != NULL);
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- 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<LLButton*>(handled_view);
- // LLLineEditor* line_editorp = dynamic_cast<LLLineEditor*>(handled_view);
- // LLTextEditor* text_editorp = dynamic_cast<LLTextEditor*>(handled_view);
- // LLTextBox* text_boxp = dynamic_cast<LLTextBox*>(handled_view);
- // if (buttonp
- // || line_editorp
- // || text_editorp
- // || text_boxp)
- // {
- // sEditingUIView = handled_view;
- // }
- //}
-
- return handled;
+ return childrenHandleMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handleMouseDown(x, y, mask);
- handled = TRUE;
- }
- return handled;
+ return childrenHandleDoubleClick( x, y, mask ) != NULL;
}
BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- if( getVisible() && getEnabled() )
- {
- return childrenHandleScrollWheel( x, y, clicks ) != NULL;
- }
- return FALSE;
+ return childrenHandleScrollWheel( x, y, clicks ) != NULL;
}
BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleRightMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleRightMouseUp( x, y, mask ) != NULL;
}
BOOL LLView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = childrenHandleMiddleMouseDown( x, y, mask );
- BOOL handled = (handled_view != NULL);
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- handled_view = this;
- }
-
- return handled;
+ return childrenHandleMiddleMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleMiddleMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleMiddleMouseUp( x, y, mask ) != NULL;
}
@@ -974,10 +885,14 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y)
- && viewp->getVisible()
- && viewp->getEnabled()
- && viewp->handleScrollWheel( local_x, local_y, clicks ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleScrollWheel( local_x, local_y, clicks ))
{
if (sDebugMouseHandling)
{
@@ -987,6 +902,12 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1002,10 +923,14 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if(viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleHover(local_x, local_y, mask) )
+ if(!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleHover(local_x, local_y, mask) )
{
if (sDebugMouseHandling)
{
@@ -1015,6 +940,14 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ LLUI::sWindow->setCursor(viewp->getHoverCursor());
+
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1080,10 +1013,14 @@ LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMouseDown( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1092,6 +1029,12 @@ LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if(viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
return handled_view;
}
@@ -1107,10 +1050,15 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleRightMouseDown( local_x, local_y, mask ))
+
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleRightMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1120,6 +1068,12 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1136,10 +1090,14 @@ LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMiddleMouseDown( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMiddleMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1148,6 +1106,12 @@ LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1164,10 +1128,15 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleDoubleClick( local_x, local_y, mask ))
+
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleDoubleClick( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1176,6 +1145,12 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1191,12 +1166,13 @@ LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y))
- continue;
- if (!viewp->getVisible())
- continue;
- if (!viewp->getEnabled())
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
continue;
+ }
+
if (viewp->handleMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
@@ -1206,6 +1182,12 @@ LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1221,10 +1203,14 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleRightMouseUp( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled() )
+ {
+ continue;
+ }
+
+ if(viewp->handleRightMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1233,6 +1219,12 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if(viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1248,10 +1240,14 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMiddleMouseUp( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMiddleMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
@@ -1260,6 +1256,12 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1272,18 +1274,6 @@ void LLView::draw()
void LLView::drawChildren()
{
- if (sDebugRects)
- {
- drawDebugRect();
-
- // Check for bogus rectangle
- if (getRect().mRight <= getRect().mLeft
- || getRect().mTop <= getRect().mBottom)
- {
- llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
- }
- }
-
if (!mChildList.empty())
{
LLRect rootRect = getRootView()->getRect();
@@ -1307,6 +1297,17 @@ void LLView::drawChildren()
{
LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
viewp->draw();
+
+ if (sDebugRects)
+ {
+ viewp->drawDebugRect();
+
+ // Check for bogus rectangle
+ if (!getRect().isValid())
+ {
+ llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
+ }
+ }
}
LLUI::popMatrix();
}
@@ -1353,10 +1354,6 @@ void LLView::drawDebugRect()
// draw red rectangle for the border
LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
- //if (sEditingUI)
- //{
- // border_color.mV[0] = 1.f;
- //}
if(preview_iter != sPreviewHighlightedElements.end())
{
if(LLView::sPreviewClickedElement && this == sPreviewClickedElement)
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 7a37d6f430..7ddff2bd9e 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -42,8 +42,6 @@
#include "llfontgl.h"
#include "llmortician.h"
#include "llmousehandler.h"
-#include "llnametable.h"
-#include "llsd.h"
#include "llstring.h"
#include "llrect.h"
#include "llui.h"
@@ -58,6 +56,8 @@
#include <list>
+class LLSD;
+
const U32 FOLLOWS_NONE = 0x00;
const U32 FOLLOWS_LEFT = 0x01;
const U32 FOLLOWS_RIGHT = 0x02;
@@ -124,21 +124,16 @@ public:
Optional<bool> enabled,
visible,
mouse_opaque,
- use_bounding_rect;
+ use_bounding_rect,
+ from_xui;
Optional<S32> tab_group,
default_tab_group;
Optional<std::string> tool_tip;
Optional<S32> sound_flags;
- Optional<bool> from_xui;
Optional<Follows> follows;
Optional<std::string> hover_cursor;
-
- // font params
- Optional<const LLFontGL*> font;
- Optional<LLFontGL::HAlign> font_halign;
- Optional<LLFontGL::VAlign> font_valign;
Optional<std::string> layout;
Optional<LLRect> rect;
@@ -223,9 +218,6 @@ public:
virtual ~LLView();
- // Hack to support LLFocusMgr (from LLMouseHandler)
- /*virtual*/ BOOL isView() const;
-
// Some UI widgets need to be added as controls. Others need to
// be added as regular view children. isCtrl should return TRUE
// if a widget needs to be added as a ctrl
@@ -258,6 +250,8 @@ public:
void setUseBoundingRect( BOOL use_bounding_rect );
BOOL getUseBoundingRect();
+ ECursorType getHoverCursor() { return mHoverCursor; }
+
const std::string& getToolTip() const { return mToolTipMsg.getString(); }
void sendChildToFront(LLView* child);
@@ -443,12 +437,11 @@ public:
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); // Display mToolTipMsg if no child handles it.
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
- /*virtual*/ const std::string& getName() const;
+ /*virtual*/ std::string getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ BOOL hasMouseCapture();
- /*virtual*/ BOOL isView(); // Hack to support LLFocusMgr
/*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;
@@ -545,7 +538,7 @@ protected:
LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
- LLView* childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
+ LLView* childrenHandleToolTip(S32 x, S32 y, MASK mask);
ECursorType mHoverCursor;
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 1e7a0f7f2c..468fae2ec5 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -24,9 +24,17 @@
#include "../llurlentry.h"
#include "llurlentry_stub.cpp"
#include "lltut.h"
+#include "../lluicolortable.h"
#include <boost/regex.hpp>
+LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& default_color) const
+{
+ return LLUIColor();
+}
+
+LLUIColor::LLUIColor() {}
+
namespace tut
{
struct LLUrlEntryData
@@ -276,6 +284,11 @@ namespace tut
testRegex("Agent Url multicase", r,
"XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About XXX",
"secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About");
+
+ testRegex("Agent Url alternate command", r,
+ "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar",
+ "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar");
+
}
template<> template<>
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 4dae49db90..e8cf135346 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -23,6 +23,10 @@
#include "../llurlmatch.h"
#include "lltut.h"
+// link seam
+LLUIColor::LLUIColor()
+{}
+
namespace tut
{
struct LLUrlMatchData
@@ -49,7 +53,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
- match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", "", "");
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "");
ensure("! empty()", ! match.empty());
}
@@ -62,7 +66,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@@ -75,7 +79,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@@ -88,10 +92,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
- match.setValues(10, 20, "http://slurl.com/", "", "", "", "", "");
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "");
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@@ -104,10 +108,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
- match.setValues(10, 20, "", "Label", "", "", "", "");
+ match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "");
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@@ -120,10 +124,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
- match.setValues(10, 20, "", "", "Info", "", "", "");
+ match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "");
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@@ -136,10 +140,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
- match.setValues(10, 20, "", "", "", "Icon", "", "");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "");
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@@ -152,10 +156,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
- match.setValues(10, 20, "", "", "", "Icon", "xui_file.xml", "");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "");
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@@ -168,10 +172,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
- match.setValues(10, 20, "", "", "", "Icon", "xui_file.xml", "Paris");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris");
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
- match.setValues(10, 20, "", "", "", "", "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}
diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h
index b5dbbc53fb..d758a1638a 100644
--- a/indra/llwindow/llmousehandler.h
+++ b/indra/llwindow/llmousehandler.h
@@ -70,14 +70,11 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) = 0;
- virtual const std::string& getName() const = 0;
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) = 0;
+ virtual std::string getName() const = 0;
virtual void onMouseCaptureLost() = 0;
- // Hack to support LLFocusMgr
- virtual BOOL isView() const = 0;
-
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const = 0;
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const = 0;
diff --git a/indra/llwindow/llpreeditor.h b/indra/llwindow/llpreeditor.h
index dd63a98606..fcb39515e7 100644
--- a/indra/llwindow/llpreeditor.h
+++ b/indra/llwindow/llpreeditor.h
@@ -94,7 +94,7 @@ public:
// Get the contents of this preeditor as a LLWString. If there is an active preedit,
// the returned LLWString contains it.
- virtual LLWString getWText() const = 0;
+ virtual LLWString getPreeditString() const = 0;
// Handle a UTF-32 char on this preeditor, i.e., add the character
// to the contents.
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 82dc5e4a13..d2760e3d59 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -2016,7 +2016,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// Although the spec. is unclear, replace range should
// not present when there is an active preedit. We just
// ignore the case. markAsPreedit will detect the case and warn it.
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location);
const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length);
mPreeditor->markAsPreedit(location, length);
@@ -2214,7 +2214,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
LLCoordGL caret_coord;
LLRect preedit_bounds;
@@ -2251,7 +2251,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
mPreeditor->getSelectionRange(&selection, &selection_length);
if (selection_length)
{
- const LLWString text = mPreeditor->getWText().substr(selection, selection_length);
+ const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length);
const llutf16string text_utf16 = wstring_to_utf16str(text);
result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText,
text_utf16.length() * sizeof(U16), text_utf16.c_str());
@@ -2637,7 +2637,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
const CFIndex length = wstring_utf16_length(text, 0, preedit)
+ wstring_utf16_length(text, preedit + preedit_length, text.length());
result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length);
@@ -2654,7 +2654,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
CFRange range;
if (preedit_length)
@@ -2688,7 +2688,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
// The GetCharacters event of TSMDA has a fundamental flaw;
// An input method need to decide the starting offset and length
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 9936b24292..0faa3e93ff 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -3544,7 +3544,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
// number to getPreeditLocation.
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
LLCoordGL caret_coord;
@@ -3571,7 +3571,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
case IMR_RECONVERTSTRING:
{
mPreeditor->resetPreedit();
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 select, select_length;
mPreeditor->getSelectionRange(&select, &select_length);
@@ -3613,7 +3613,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
}
case IMR_DOCUMENTFEED:
{
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index 818d774f73..7823607c3b 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -34,7 +34,7 @@
#define LL_LLXMLNODE_H
#ifndef XML_STATIC
-#define XML_STATIC 1
+#define XML_STATIC
#endif
#ifdef LL_STANDALONE
#include <expat.h>
diff --git a/indra/llxml/llxmlparser.h b/indra/llxml/llxmlparser.h
index d7595f6a68..fa9e8175e2 100644
--- a/indra/llxml/llxmlparser.h
+++ b/indra/llxml/llxmlparser.h
@@ -34,7 +34,7 @@
#define LL_LLXMLPARSER_H
#ifndef XML_STATIC
-#define XML_STATIC 1
+#define XML_STATIC
#endif
#ifdef LL_STANDALONE
#include <expat.h>
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index baa782916e..88bc430504 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -1568,11 +1568,11 @@ namespace LLInitParam
public Param
{
public:
- typedef BlockValue<T> self_t;
- typedef Block<TypedParam<T, TypeValues<T>, false> > block_t;
- typedef const T& value_const_ref_t;
- typedef value_const_ref_t value_assignment_t;
- typedef typename TypeValues<T>::KeyCache key_cache_t;
+ typedef BlockValue<T> self_t;
+ typedef Block<TypedParam<T, TypeValues<T>, false> > block_t;
+ typedef const T& value_const_ref_t;
+ typedef value_const_ref_t value_assignment_t;
+ typedef typename TypeValues<T>::KeyCache key_cache_t;
BlockValue(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
: Param(block_descriptor.mCurrentBlockPtr),
@@ -1754,11 +1754,16 @@ namespace LLInitParam
protected:
value_assignment_t get() const
{
- if (mData.mLastParamVersion < BaseBlock::getLastChangeVersion() && block_t::validateBlock(true))
+ // if some parameters were provided, issue warnings on invalid blocks
+ if (Param::getProvided() && (mData.mLastParamVersion < BaseBlock::getLastChangeVersion()))
{
- mData.mValue = static_cast<const DERIVED*>(this)->getValueFromBlock();
- mData.clearKey();
- mData.mLastParamVersion = BaseBlock::getLastChangeVersion();
+ // go ahead and issue warnings at this point if any param is invalid
+ if(block_t::validateBlock(false))
+ {
+ mData.mValue = static_cast<const DERIVED*>(this)->getValueFromBlock();
+ mData.clearKey();
+ mData.mLastParamVersion = BaseBlock::getLastChangeVersion();
+ }
}
return mData.mValue;
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
index 2efc475f57..e974dbd0ba 100644
--- a/indra/llxuixml/lltrans.cpp
+++ b/indra/llxuixml/lltrans.cpp
@@ -194,3 +194,68 @@ bool LLTrans::findString(std::string &result, const std::string &xml_desc, const
return false;
}
}
+
+//static
+std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+{
+ // Compute which string identifier to use
+ const char* form = "";
+ if (language == "ru") // Russian
+ {
+ // From GNU ngettext()
+ // Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ if (count % 10 == 1
+ && count % 100 != 11)
+ {
+ // singular, "1 item"
+ form = "A";
+ }
+ else if (count % 10 >= 2
+ && count % 10 <= 4
+ && (count % 100 < 10 || count % 100 >= 20) )
+ {
+ // special case "2 items", "23 items", but not "13 items"
+ form = "B";
+ }
+ else
+ {
+ // English-style plural, "5 items"
+ form = "C";
+ }
+ }
+ else if (language == "fr" || language == "pt") // French, Brazilian Portuguese
+ {
+ // French and Portuguese treat zero as a singular "0 item" not "0 items"
+ if (count == 0 || count == 1)
+ {
+ form = "A";
+ }
+ else
+ {
+ // English-style plural
+ form = "B";
+ }
+ }
+ else // default
+ {
+ // languages like English with 2 forms, singular and plural
+ if (count == 1)
+ {
+ // "1 item"
+ form = "A";
+ }
+ else
+ {
+ // "2 items", also use plural for "0 items"
+ form = "B";
+ }
+ }
+
+ // Translate that string
+ LLStringUtil::format_map_t args;
+ args["[COUNT]"] = llformat("%d", count);
+
+ // Look up "AgeYearsB" or "AgeWeeksC" including the "form"
+ std::string key = llformat("%s%s", xml_desc.c_str(), form);
+ return getString(key, args);
+}
diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h
index 340d70e434..79df5802e5 100644
--- a/indra/llxuixml/lltrans.h
+++ b/indra/llxuixml/lltrans.h
@@ -80,6 +80,12 @@ public:
static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+ // Returns translated string with [COUNT] replaced with a number, following
+ // special per-language logic for plural nouns. For example, some languages
+ // may have different plurals for 0, 1, 2 and > 2.
+ // See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples.
+ static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count);
+
/**
* @brief Returns a translated string
* @param xml_desc String's description
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b217a5b781..14a37981a6 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -106,6 +106,7 @@ set(viewer_SOURCE_FILES
llconfirmationmanager.cpp
llcurrencyuimanager.cpp
llcylinder.cpp
+ lldateutil.cpp
lldebugmessagebox.cpp
lldebugview.cpp
lldelayedgestureerror.cpp
@@ -241,6 +242,7 @@ set(viewer_SOURCE_FILES
llimview.cpp
llimcontrolpanel.cpp
llinspectavatar.cpp
+ llinspectobject.cpp
llinventorybridge.cpp
llinventoryclipboard.cpp
llinventoryfilter.cpp
@@ -395,7 +397,6 @@ set(viewer_SOURCE_FILES
lltoastimpanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
- lltoggleablemenu.cpp
lltoolbar.cpp
lltoolbrush.cpp
lltoolcomp.cpp
@@ -576,6 +577,7 @@ set(viewer_HEADER_FILES
llconfirmationmanager.h
llcurrencyuimanager.h
llcylinder.h
+ lldateutil.h
lldebugmessagebox.h
lldebugview.h
lldelayedgestureerror.h
@@ -711,6 +713,7 @@ set(viewer_HEADER_FILES
llimview.h
llimcontrolpanel.h
llinspectavatar.h
+ llinspectobject.h
llinventorybridge.h
llinventoryclipboard.h
llinventoryfilter.h
@@ -865,7 +868,6 @@ set(viewer_HEADER_FILES
lltoastimpanel.h
lltoastnotifypanel.h
lltoastpanel.h
- lltoggleablemenu.h
lltool.h
lltoolbar.h
lltoolbrush.h
@@ -1538,9 +1540,12 @@ if (INSTALL)
include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
endif (INSTALL)
+# To add a viewer unit test, just add the test .cpp file below
+# This creates a separate test project per file listed.
include(LLAddBuildTest)
SET(viewer_TEST_SOURCE_FILES
llagentaccess.cpp
+ lldateutil.cpp
llviewerhelputil.cpp
)
set_source_files_properties(
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 99b662a63f..94a5f5c52b 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3673,7 +3673,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <string>0.1</string>
+ <real>0.15</real>
</map>
<key>InstallLanguage</key>
<map>
@@ -7585,7 +7585,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>ShowCameraButton</key>
<map>
@@ -8456,18 +8456,40 @@
<key>Value</key>
<real>0.2</real>
</map>
- <key>ToolTipVisibleTime</key>
- <map>
- <key>Comment</key>
- <string>Fade tooltip after mouse is idle for this long</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>10.0</real>
- </map>
- <key>ToolboxAutoMove</key>
+ <key>ToolTipVisibleTimeFar</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade tooltip after after time passes (seconds) while mouse not near tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+ <key>ToolTipVisibleTimeNear</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade tooltip after after time passes (seconds) while mouse near tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>5.0</real>
+ </map>
+ <key>ToolTipVisibleTimeOver</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade tooltip after after time passes (seconds) while mouse over tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1000.0</real>
+ </map>
+ <key>ToolboxAutoMove</key>
<map>
<key>Comment</key>
<string>[NOT USED]</string>
@@ -9655,39 +9677,6 @@
<key>Value</key>
<integer>15</integer>
</map>
- <key>UITextEditorBorder</key>
- <map>
- <key>Comment</key>
- <string>UI Text Editor Border</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>UITextEditorHPad</key>
- <map>
- <key>Comment</key>
- <string>UI Text Horizontal Pad</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>4</integer>
- </map>
- <key>UITextEditorVPadTop</key>
- <map>
- <key>Comment</key>
- <string>UI Text Vertical Pad Top</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>4</integer>
- </map>
<key>UploadBakedTexOld</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 73a548cdc6..a7322749ca 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -758,7 +758,7 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
"InternetShortcut" "URL" \
- "http://www.secondlife.com/registration/"
+ "http://join.secondlife.com/"
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Your Account.url" \
"InternetShortcut" "URL" \
"http://www.secondlife.com/account/"
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 30e0a5770c..41cbc21fe9 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -696,9 +696,6 @@ bool LLAppViewer::init()
// Let code in llui access the viewer help floater
LLUI::sHelpImpl = LLViewerHelp::getInstance();
- // Set the link color for any Urls in text fields
- LLTextBase::setLinkColor( LLUIColorTable::instance().getColor("HTMLLinkColor") );
-
// Load translations for tooltips
LLFloater::initClass();
@@ -1424,6 +1421,9 @@ bool LLAppViewer::cleanup()
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
}
+ // Turn off Space Navigator and similar devices
+ LLViewerJoystick::getInstance()->terminate();
+
removeMarkerFile(); // Any crashes from here on we'll just have to ignore
writeDebugInfo();
@@ -2379,7 +2379,6 @@ void LLAppViewer::cleanupSavedSettings()
}
gSavedSettings.setF32("MapScale", gMapScale );
- gSavedSettings.setBOOL("ShowHoverTips", gToolTipView->getVisible());
// Some things are cached in LLAgent.
if (gAgent.mInitialized)
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 1676bb1d44..92b2768f39 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -39,16 +39,22 @@
#include "lldarray.h"
#include "llnotifications.h"
+#include "roles_constants.h" // for GP_MEMBER_INVITE
+
#include "llagent.h"
#include "llappviewer.h" // for gLastVersionChannel
#include "llcachename.h"
#include "llcallingcard.h" // for LLAvatarTracker
-#include "llgivemoney.h" // foe LLFloaterPay
+#include "llfloatergroupinvite.h"
+#include "llfloatergroups.h"
+#include "llfloaterreg.h"
+#include "llgivemoney.h"
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
#include "llimview.h" // for gIMMgr
#include "llmutelist.h"
#include "llrecentpeople.h"
#include "llsidetray.h"
+#include "llviewerobjectlist.h"
#include "llviewermessage.h" // for handle_lure
#include "llviewerregion.h"
@@ -244,6 +250,17 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)
}
}
+void LLAvatarActions::inviteToGroup(const LLUUID& id)
+{
+ LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(id));
+ if (widget)
+ {
+ widget->center();
+ widget->setPowersMask(GP_MEMBER_INVITE);
+ widget->setSelectGroupCallback(boost::bind(callback_invite_to_group, _1, id));
+ }
+}
+
//== private methods ========================================================================================
// static
@@ -294,6 +311,16 @@ bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response,
}
// static
+void LLAvatarActions::callback_invite_to_group(LLUUID group_id, LLUUID id)
+{
+ std::vector<LLUUID> agent_ids;
+ agent_ids.push_back(id);
+
+ LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
+}
+
+
+// static
bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index e911715c70..512f673b43 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -96,11 +96,17 @@ public:
*/
static bool isBlocked(const LLUUID& id);
+ /**
+ * Invite avatar to a group.
+ */
+ static void inviteToGroup(const LLUUID& id);
+
private:
static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
+ static void callback_invite_to_group(LLUUID group_id, LLUUID id);
// Just request friendship, no dialog.
static void requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message);
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 665dffc8c6..51545bcc07 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -148,7 +148,7 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id)
void LLAvatarListItem::onInfoBtnClick()
{
- LLFloaterReg::showInstance("inspect_avatar", mAvatarId);
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarId));
/* TODO fix positioning of inspector
localPointToScreen(mXPos, mYPos, &mXPos, &mYPos);
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index e568b9c526..5c68ac8cdb 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -42,12 +42,18 @@
#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
#include "lldate.h"
#include "lltrans.h"
+#include "llui.h" // LLUI::getLanguage()
#include "message.h"
LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor()
{
}
+LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor()
+{
+ llinfos << "JAMESDEBUG cleanup avatar properties processor" << llendl;
+}
+
void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
{
// Check if that observer is already in mObservers for that avatar_id
@@ -172,103 +178,6 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData*
gAgent.sendReliableMessage();
}
-//static
-std::string LLAvatarPropertiesProcessor::ageFromDate(const std::string& date_string)
-{
- // Convert string date to malleable representation
- S32 month, day, year;
- S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &month, &day, &year);
- if (matched != 3) return "???";
-
- // Create ISO-8601 date string
- std::string iso8601_date_string =
- llformat("%04d-%02d-%02dT00:00:00Z", year, month, day);
- LLDate date(iso8601_date_string);
-
- // Correct for the fact that account creation dates are in Pacific time,
- // == UTC - 8
- F64 date_secs_since_epoch = date.secondsSinceEpoch();
- date_secs_since_epoch += 8.0 * 60.0 * 60.0;
-
- // Convert seconds from epoch to seconds from now
- F64 now_secs_since_epoch = LLDate::now().secondsSinceEpoch();
- F64 age_secs = now_secs_since_epoch - date_secs_since_epoch;
-
- // We don't care about sub-day times
- const F64 SEC_PER_DAY = 24.0 * 60.0 * 60.0;
- S32 age_days = lltrunc(age_secs / SEC_PER_DAY);
-
- // Assume most values won't be used to fill in the format string:
- // "[AGEYEARS][AGEMONTHS][AGEWEEKS][AGEDAYS]old"
- LLStringUtil::format_map_t final_args;
- final_args["[AGEYEARS]"] = "";
- final_args["[AGEMONTHS]"] = "";
- final_args["[AGEWEEKS]"] = "";
- final_args["[AGEDAYS]"] = "";
-
- // Try for age in round number of years
- LLStringUtil::format_map_t args;
- S32 age_years = age_days / 365;
- age_days = age_days % 365;
- if (age_years > 1)
- {
- args["[YEARS]"] = llformat("%d", age_years);
- final_args["[AGEYEARS]"] = LLTrans::getString("AgeYears", args);
- }
- else if (age_years == 1)
- {
- final_args["[AGEYEARS]"] = LLTrans::getString("Age1Year");
- }
- // fall through because we show years + months for ages > 1 year
-
- S32 age_months = age_days / 30;
- age_days = age_days % 30;
- if (age_months > 1)
- {
- args["[MONTHS]"] = llformat("%d", age_months);
- final_args["[AGEMONTHS]"] = LLTrans::getString("AgeMonths", args);
- // Either N years M months, or just M months,
- // so we can exit.
- return LLTrans::getString("YearsMonthsOld", final_args);
- }
- else if (age_months == 1)
- {
- final_args["[AGEMONTHS]"] = LLTrans::getString("Age1Month");
- return LLTrans::getString("YearsMonthsOld", final_args);
- }
-
- // Now for age in weeks
- S32 age_weeks = age_days / 7;
- age_days = age_days % 7;
- if (age_weeks > 1)
- {
- args["[WEEKS]"] = llformat("%d", age_weeks);
- final_args["[AGEWEEKS]"] = LLTrans::getString("AgeWeeks", args);
- return LLTrans::getString("WeeksOld", final_args);
- }
- else if (age_weeks == 1)
- {
- final_args["[AGEWEEKS]"] = LLTrans::getString("Age1Week");
- return LLTrans::getString("WeeksOld", final_args);
- }
-
- // Down to days now
- if (age_days > 1)
- {
- args["[DAYS]"] = llformat("%d", age_days);
- final_args["[AGEDAYS]"] = LLTrans::getString("AgeDays", args);
- return LLTrans::getString("DaysOld", final_args);
- }
- else if (age_days == 1)
- {
- final_args["[AGEDAYS]"] = LLTrans::getString("Age1Day");
- return LLTrans::getString("DaysOld", final_args);
- }
- else
- {
- return LLTrans::getString("TodayOld");
- }
-}
//static
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 79d109f1db..ea80c3d4f8 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -36,6 +36,7 @@
#include "lluuid.h"
#include "llsingleton.h"
#include "v3dmath.h" // LLVector3d
+#include <list>
#include <map>
/*
@@ -147,8 +148,7 @@ class LLAvatarPropertiesProcessor
public:
LLAvatarPropertiesProcessor();
- virtual ~LLAvatarPropertiesProcessor()
- {}
+ virtual ~LLAvatarPropertiesProcessor();
void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
@@ -174,11 +174,6 @@ public:
void sendPickDelete(const LLUUID& pick_id);
- // Convert a date provided by the server (MM/DD/YYYY) into a localized,
- // human-readable age (1 year, 2 months) using translation strings from
- // the XML file.
- static std::string ageFromDate(const std::string& date_string);
-
// Returns translated, human readable string for account type, such
// as "Resident" or "Linden Employee". Used for profiles, inspectors.
static std::string accountType(const LLAvatarData* avatar_data);
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index c2d7e0d935..25620c2aed 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -236,7 +236,7 @@ BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask)
S32 local_y = y - msg_inspector->getRect().mBottom - caption->getRect().mBottom;
if(msg_inspector->pointInView(local_x, local_y))
{
- LLFloaterReg::showInstance("inspect_avatar", mFromID);
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mFromID));
}
else
{
@@ -262,7 +262,7 @@ bool LLNearbyChatToastPanel::canAddText ()
LLChatMsgBox* msg_text = findChild<LLChatMsgBox>("msg_text");
if(!msg_text)
return false;
- return msg_text->getTextLinesNum()<10;
+ return msg_text->getLineCount()<10;
}
BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp
index bd0c36b44a..6eaafc9059 100644
--- a/indra/newview/llchatmsgbox.cpp
+++ b/indra/newview/llchatmsgbox.cpp
@@ -39,88 +39,60 @@
static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
-LLChatMsgBox::Params::Params() :
- block_spacing("block_spacing", 10)
+class ChatSeparator : public LLTextSegment
{
- line_spacing = 4;
-}
+public:
+ ChatSeparator(S32 start, S32 end)
+ : LLTextSegment(start, end),
+ mEditor(NULL)
+ {}
-LLChatMsgBox::LLChatMsgBox(const Params& p) :
- LLTextBox(p),
- mBlockSpacing(p.block_spacing)
-{}
+ /*virtual*/ void linkToDocument(class LLTextBase* editor)
+ {
+ mEditor = editor;
+ }
-void LLChatMsgBox::addText( const LLStringExplicit& text )
-{
- LLWString t = mText.getWString();
- if (! t.empty())
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor)
{
- t += '\n';
+ mEditor = NULL;
}
- t += getWrappedText(text);
- LLTextBox::setText(wstring_to_utf8str(t));
- mSeparatorOffset.push_back(getLength());
-}
-void LLChatMsgBox::setText(const LLStringExplicit& text)
-{
- mSeparatorOffset.clear();
- mText.clear();
- addText(text);
-}
+ /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const
+ {
+ return mEditor->getDocumentPanel()->getRect().getWidth();
+ }
-void LLChatMsgBox::setValue(const LLSD& value )
-{
- setText(value.asString());
-}
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+ {
+ gl_line_2d(draw_rect.mLeft + 5, draw_rect.getCenterY(), draw_rect.mRight - 5, draw_rect.getCenterY(), LLColor4::grey);
+ return draw_rect.getWidth();
+ }
+
+private:
+ LLTextBase* mEditor;
+};
-S32 LLChatMsgBox::getTextPixelHeight()
-{
- S32 num_blocks = mSeparatorOffset.size();
- S32 num_lines = getTextLinesNum();
- return (S32)(num_lines * mDefaultFont->getLineHeight() + \
- (num_lines-1) * mLineSpacing + \
- (num_blocks-1) * mBlockSpacing + \
- 2 * mLineSpacing);
-}
-S32 LLChatMsgBox::getTextLinesNum()
+LLChatMsgBox::Params::Params() :
+ block_spacing("block_spacing", 10)
{
- S32 num_lines = getLineCount();
- if (num_lines < 1)
- {
- num_lines = 1;
- }
-
- return num_lines;
+ line_spacing.pixels = 4;
}
-void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4 &color)
-{
- S32 start = 0;
- S32 width = getRect().getWidth()-10;
+LLChatMsgBox::LLChatMsgBox(const Params& p) :
+ LLTextBox(p),
+ mBlockSpacing(p.block_spacing)
+{}
- // iterate through each block of text that has been added
- y -= mLineSpacing;
- for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); it != mSeparatorOffset.end() ;)
+void LLChatMsgBox::addText( const LLStringExplicit& text )
+{
+ S32 length = getLength();
+ // if there is existing text, add a separator
+ if (length > 0)
{
- // display the text for this block
- S32 num_chars = *it - start;
- LLWString text = mDisplayText.substr(start, num_chars);
- LLTextBox::drawText(x, y, text, color);
-
- // exit the loop if this is the last text block
- start += num_chars + 1; // skip the newline
- if (++it == mSeparatorOffset.end())
- {
- break;
- }
-
- // output a separator line between blocks
- S32 num_lines = std::count(text.begin(), text.end(), '\n') + 1;
- y -= num_lines * (llfloor(mDefaultFont->getLineHeight()) + mLineSpacing);
- S32 sep_y = y - mBlockSpacing/2 + mLineSpacing/2;
- gl_line_2d(5, sep_y, width, sep_y, LLColor4::grey);
- y -= mBlockSpacing;
+ // chat separator exists right before the null terminator
+ insertSegment(new ChatSeparator(length - 1, length - 1));
}
+ // prepend newline only if there is some existing text
+ appendText(text, length > 0);
}
diff --git a/indra/newview/llchatmsgbox.h b/indra/newview/llchatmsgbox.h
index b81b740bdc..df29db58c3 100644
--- a/indra/newview/llchatmsgbox.h
+++ b/indra/newview/llchatmsgbox.h
@@ -61,18 +61,10 @@ protected:
friend class LLUICtrlFactory;
public:
- void setText(const LLStringExplicit &text);
void addText(const LLStringExplicit &text);
- S32 getTextPixelHeight();
- S32 getTextLinesNum();
-
- /*virtual*/ void setValue(const LLSD &value);
- /*virtual*/ void drawText(S32 x, S32 y, const LLWString &text, const LLColor4 &color);
-
private:
S32 mBlockSpacing;
- std::vector<S32> mSeparatorOffset;
};
#endif
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 98e492cada..23664fa6d6 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1305,7 +1305,7 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter)
LLRect LLChicletNotificationCounterCtrl::getRequiredRect()
{
LLRect rc;
- S32 text_width = getFont()->getWidth(getText());
+ S32 text_width = getContentsRect().getWidth();
rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth);
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 113f4c2c54..7b75c77a1e 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -87,7 +87,7 @@ LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
tp.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
}
- tp.text(p.label);
+ tp.initial_value(p.label());
mCaption = LLUICtrlFactory::create<LLTextBox>(tp);
addChild( mCaption );
diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp
new file mode 100644
index 0000000000..040fad3c4a
--- /dev/null
+++ b/indra/newview/lldateutil.cpp
@@ -0,0 +1,140 @@
+/**
+* @file lldateutil.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldateutil.h"
+
+// Linden libraries
+#include "lltrans.h"
+#include "llui.h"
+
+static S32 age_days_from_date(const std::string& date_string,
+ const LLDate& now)
+{
+ // Convert string date to malleable representation
+ S32 month, day, year;
+ S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &month, &day, &year);
+ if (matched != 3) return S32_MIN;
+
+ // Create ISO-8601 date string
+ std::string iso8601_date_string =
+ llformat("%04d-%02d-%02dT00:00:00Z", year, month, day);
+ LLDate date(iso8601_date_string);
+
+ // Correct for the fact that account creation dates are in Pacific time,
+ // == UTC - 8
+ F64 date_secs_since_epoch = date.secondsSinceEpoch();
+ date_secs_since_epoch += 8.0 * 60.0 * 60.0;
+
+ // Convert seconds from epoch to seconds from now
+ F64 now_secs_since_epoch = now.secondsSinceEpoch();
+ F64 age_secs = now_secs_since_epoch - date_secs_since_epoch;
+
+ // We don't care about sub-day times
+ const F64 SEC_PER_DAY = 24.0 * 60.0 * 60.0;
+ S32 age_days = lltrunc(age_secs / SEC_PER_DAY);
+
+ return age_days;
+}
+
+std::string LLDateUtil::ageFromDate(const std::string& date_string,
+ const LLDate& now)
+{
+ S32 age_days = age_days_from_date(date_string, now);
+ if (age_days == S32_MIN) return "???";
+
+ // Noun pluralization depends on language
+ std::string lang = LLUI::getLanguage();
+
+ // Try for age in round number of years
+ LLStringUtil::format_map_t args;
+ S32 age_years = age_days / 365;
+ age_days = age_days % 365;
+ // *NOTE: This is wrong. Not all months have 30 days, but we don't have a library
+ // for relative date arithmetic. :-( JC
+ S32 age_months = age_days / 30;
+ age_days = age_days % 30;
+
+ if (age_months > 0 || age_years > 0)
+ {
+ args["[AGEYEARS]"] =
+ LLTrans::getCountString(lang, "AgeYears", age_years);
+ args["[AGEMONTHS]"] =
+ LLTrans::getCountString(lang, "AgeMonths", age_months);
+
+ // We want to display times like:
+ // 2 year 2 months
+ // 2 years (implicitly 0 months)
+ // 11 months
+ if (age_years > 0)
+ {
+ if (age_months > 0)
+ {
+ return LLTrans::getString("YearsMonthsOld", args);
+ }
+ else
+ {
+ return LLTrans::getString("YearsOld", args);
+ }
+ }
+ else // age_years == 0
+ {
+ return LLTrans::getString("MonthsOld", args);
+ }
+ }
+ // you're 0 months old, display in weeks or days
+
+ // Now for age in weeks
+ S32 age_weeks = age_days / 7;
+ age_days = age_days % 7;
+ if (age_weeks > 0)
+ {
+ args["[AGEWEEKS]"] =
+ LLTrans::getCountString(lang, "AgeWeeks", age_weeks);
+ return LLTrans::getString("WeeksOld", args);
+ }
+
+ // Down to days now
+ if (age_days > 0)
+ {
+ args["[AGEDAYS]"] =
+ LLTrans::getCountString(lang, "AgeDays", age_days);
+ return LLTrans::getString("DaysOld", args);
+ }
+
+ return LLTrans::getString("TodayOld");
+}
+
+std::string LLDateUtil::ageFromDate(const std::string& date_string)
+{
+ return ageFromDate(date_string, LLDate::now());
+}
diff --git a/indra/newview/lldateutil.h b/indra/newview/lldateutil.h
new file mode 100644
index 0000000000..041be07f12
--- /dev/null
+++ b/indra/newview/lldateutil.h
@@ -0,0 +1,49 @@
+/**
+* @file lldateutil.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LLDATEUTIL_H
+#define LLDATEUTIL_H
+
+class LLDate;
+
+namespace LLDateUtil
+{
+ // Convert a date provided by the server (MM/DD/YYYY) into a localized,
+ // human-readable age (1 year, 2 months) using translation strings.
+ // Pass LLDate::now() for now.
+ // Used for avatar inspectors and profiles.
+ std::string ageFromDate(const std::string& date_string, const LLDate& now);
+
+ // Calls the above with LLDate::now()
+ std::string ageFromDate(const std::string& date_string);
+}
+
+#endif
diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp
index 786473eb9b..29e375c9fa 100644
--- a/indra/newview/lldebugmessagebox.cpp
+++ b/indra/newview/lldebugmessagebox.cpp
@@ -131,7 +131,7 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy
LLTextBox::Params params;
params.name("value");
- params.text(params.name);
+ params.initial_value(params.name());
params.rect(LLRect(20,20,190,0));
mText = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mText);
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 131f9ceaf0..f8f5db9d7e 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -78,6 +78,9 @@ void LLExpandableTextBox::LLTextBoxEx::draw()
LLUICtrl::draw();
}
+/* LLTextBox has been rewritten, the variables referenced in this code
+no longer exist.
+
void LLExpandableTextBox::LLTextBoxEx::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color )
{
// *NOTE:dzaporozhan:
@@ -141,6 +144,7 @@ void LLExpandableTextBox::LLTextBoxEx::drawText( S32 x, S32 y, const LLWString &
}
}
}
+*/
void LLExpandableTextBox::LLTextBoxEx::showExpandText(S32 y)
{
@@ -161,8 +165,14 @@ S32 LLExpandableTextBox::LLTextBoxEx::getCropTextWidth()
return mExpandTextBox->getRect().mLeft - getHPad() * 2;
}
+/*
+// *NOTE:James:
+// LLTextBox::drawText() has been completely rewritten, as it now handles
+// arbitrarily styled segments of text. This needs to be rebuilt.
+
void LLExpandableTextBox::LLTextBoxEx::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text)
{
+
// *NOTE:dzaporozhan:
// Copy/paste from LLTextBox::drawTextSegments in order to modify last
// line width if needed and who "More" link
@@ -270,6 +280,7 @@ void LLExpandableTextBox::LLTextBoxEx::drawTextSegments(S32 init_x, S32 init_y,
}
}
}
+*/
S32 LLExpandableTextBox::LLTextBoxEx::getVerticalTextDelta()
{
@@ -422,8 +433,11 @@ void LLExpandableTextBox::expandTextBox()
// disable horizontal scrollbar
text_box_rect.mRight -= scrollbar_size;
+
// text box size has changed - redo text wrap
- mTextBox->setWrappedText(mText, text_box_rect.getWidth());
+ // Should be handled automatically in reshape() below. JC
+ //mTextBox->setWrappedText(mText, text_box_rect.getWidth());
+
// recalculate text delta since text wrap changed text height
text_delta = mTextBox->getVerticalTextDelta() + mTextBox->getVPad() * 2;
}
@@ -460,7 +474,8 @@ void LLExpandableTextBox::collapseTextBox()
updateTextBoxRect();
- mTextBox->setWrappedText(mText);
+ // Should be handled automatically in reshape above. JC
+ //mTextBox->setWrappedText(mText);
if(gFocusMgr.getTopCtrl() == this)
{
gFocusMgr.setTopCtrl(NULL);
diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h
index 0a5a4c8b75..0b9c3f7258 100644
--- a/indra/newview/llexpandabletextbox.h
+++ b/indra/newview/llexpandabletextbox.h
@@ -64,17 +64,17 @@ protected:
*/
/*virtual*/ void draw();
- /**
- * Draws simple text(no urls) line by line, will show or hide "More" link
- * if needed.
- */
- /*virtual*/ void drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color );
-
- /**
- * Draws segmented text(with urls) line by line. Will show or hide "More" link
- * if needed
- */
- void drawTextSegments(S32 x, S32 y, const LLWString &text);
+// /**
+// * Draws simple text(no urls) line by line, will show or hide "More" link
+// * if needed.
+// */
+// /*virtual*/ void drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color );
+//
+// /**
+// * Draws segmented text(with urls) line by line. Will show or hide "More" link
+// * if needed
+// */
+// void drawTextSegments(S32 x, S32 y, const LLWString &text);
/**
* Returns difference between text box height and text height.
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 8af3a8b539..0bd4389b50 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -244,7 +244,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
}
-BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
{
if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
{
@@ -254,7 +254,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& stic
LLRect screen_rect;
localRectToScreen(mToolTipRect, &screen_rect);
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex))
.sticky_rect(screen_rect));
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index 97e4e94460..2bb023ab14 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -57,7 +57,7 @@ public:
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual void draw();
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index ea947a5565..48fcb6b6de 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -123,7 +123,7 @@ class LLFavoriteLandmarkButton : public LLButton
{
public:
- BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect)
+ BOOL handleToolTip(S32 x, S32 y, MASK mask)
{
LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
return TRUE;
@@ -201,7 +201,7 @@ private:
class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL
{
public:
- BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect)
+ BOOL handleToolTip(S32 x, S32 y, MASK mask)
{
LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
return TRUE;
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index e28d223a10..a4c38d03aa 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -115,9 +115,6 @@ BOOL LLFloaterAbout::postBuild()
getChild<LLUICtrl>("copy_btn")->setCommitCallback(
boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
- // make sure that we handle hyperlinks in the About text
- support_widget->setParseHTML(TRUE);
-
// Version string
std::string version = LLTrans::getString("APP_NAME")
+ llformat(" %d.%d.%d (%d) %s %s (%s)\n",
@@ -241,7 +238,11 @@ BOOL LLFloaterAbout::postBuild()
support.append(getString ("PacketsLost", args) + "\n");
}
- support_widget->appendColoredText(support, FALSE, FALSE, LLUIColorTable::instance().getColor("TextFgReadOnlyColor"));
+ support_widget->appendText(support,
+ FALSE,
+ LLStyle::Params()
+ .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+ support_widget->blockUndo();
// Fix views
support_widget->setCursorPos(0);
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index a7aaf71ef6..473d5ce827 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -73,6 +73,8 @@ BOOL LLFloaterBuy::postBuild()
// This also avoids problems where the user resizes the application window
// mid-session and the saved rect is off-center.
center();
+
+ mCloseSignal.connect(boost::bind(&LLFloaterBuy::onClose, this));
return TRUE;
}
@@ -307,3 +309,8 @@ void LLFloaterBuy::onClickCancel()
{
closeFloater();
}
+
+void LLFloaterBuy::onClose()
+{
+ mObjectSelection.clear();
+}
diff --git a/indra/newview/llfloaterbuy.h b/indra/newview/llfloaterbuy.h
index ee54303267..2ec66136b2 100644
--- a/indra/newview/llfloaterbuy.h
+++ b/indra/newview/llfloaterbuy.h
@@ -70,6 +70,7 @@ protected:
void onClickBuy();
void onClickCancel();
+ void onClose();
private:
LLSafeHandle<LLObjectSelection> mObjectSelection;
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 7075719299..2c2a5107f5 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -50,6 +50,7 @@
#include "lllineeditor.h"
#include "llnotify.h"
#include "llparcel.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
@@ -71,7 +72,7 @@
const F32 GROUP_LAND_BONUS_FACTOR = 1.1f;
const F64 CURRENCY_ESTIMATE_FREQUENCY = 0.5;
// how long of a pause in typing a currency buy amount before an
- // esimate is fetched from the server
+ // estimate is fetched from the server
class LLFloaterBuyLandUI
: public LLFloater
@@ -177,6 +178,11 @@ public:
void sendBuyLand();
void updateNames();
+ // Name cache callback
+ void updateGroupName(const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group);
void refreshUI();
@@ -201,16 +207,6 @@ public:
};
-static void cacheNameUpdateRefreshesBuyLand(const LLUUID&,
- const std::string&, const std::string&, BOOL)
-{
- LLFloaterBuyLandUI* ui = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (ui)
- {
- ui->updateNames();
- }
-}
-
// static
void LLFloaterBuyLand::buyLand(
LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
@@ -296,13 +292,6 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
mChildren(*this), mCurrency(*this), mTransaction(0),
mParcelBuyInfo(0)
{
- static bool observingCacheName = false;
- if (!observingCacheName)
- {
- gCacheName->addObserver(&cacheNameUpdateRefreshesBuyLand);
- observingCacheName = true;
- }
-
LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
// LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_buy_land.xml");
@@ -788,14 +777,30 @@ void LLFloaterBuyLandUI::updateNames()
}
else if (parcelp->getIsGroupOwned())
{
- gCacheName->getGroupName(parcelp->getGroupID(), mParcelSellerName);
+ gCacheName->get(parcelp->getGroupID(), TRUE,
+ boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
+ _1, _2, _3, _4));
}
else
{
- gCacheName->getFullName(parcelp->getOwnerID(), mParcelSellerName);
+ mParcelSellerName =
+ LLSLURL::buildCommand("agent", parcelp->getOwnerID(), "inspect");
}
}
+void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group)
+{
+ LLParcel* parcelp = mParcel->getParcel();
+ if (parcelp
+ && parcelp->getGroupID() == id)
+ {
+ // request is current
+ mParcelSellerName = first_name;
+ }
+}
void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
{
@@ -1036,9 +1041,7 @@ void LLFloaterBuyLandUI::refreshUI()
if (message)
{
message->setVisible(true);
- message->setWrappedText(
- !mCanBuy ? mCannotBuyReason : "(waiting for data)"
- );
+ message->setValue(LLSD(!mCanBuy ? mCannotBuyReason : "(waiting for data)"));
}
childSetVisible("error_web",
@@ -1148,7 +1151,7 @@ void LLFloaterBuyLandUI::refreshUI()
}
}
- childSetWrappedText("land_use_reason", message);
+ childSetValue("land_use_reason", message);
childShow("step_2");
childShow("land_use_action");
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index ca43f41d05..6d2e959352 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -56,6 +56,7 @@
#include "llchatbar.h"
#include "llrecentpeople.h"
#include "llpanelblockedlist.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
@@ -162,7 +163,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
if (chat.mSourceType == CHAT_SOURCE_AGENT &&
chat.mFromID != LLUUID::null)
{
- chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
+ chat.mURL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
}
// If the chat line has an associated url, link it up to the name.
@@ -171,10 +172,12 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
{
std::string start_line = line.substr(0, chat.mFromName.length() + 1);
line = line.substr(chat.mFromName.length() + 1);
- edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL));
+ edit->appendText(start_line, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL));
+ edit->blockUndo();
prepend_newline = false;
}
- edit->appendColoredText(line, false, prepend_newline, color);
+ edit->appendText(line, prepend_newline, LLStyle::Params().color(color));
+ edit->blockUndo();
}
void log_chat_text(const LLChat& chat)
@@ -216,12 +219,6 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
LLViewerTextEditor* history_editor = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor");
LLViewerTextEditor* history_editor_with_mute = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
- history_editor->setParseHTML(TRUE);
- history_editor_with_mute->setParseHTML(TRUE);
-
- history_editor->setParseHighlights(TRUE);
- history_editor_with_mute->setParseHighlights(TRUE);
-
if (!chat.mMuted)
{
add_timestamped_line(history_editor, chat, color);
diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp
index 0c77d88efb..2c66ab502d 100644
--- a/indra/newview/llfloaterfriends.cpp
+++ b/indra/newview/llfloaterfriends.cpp
@@ -237,7 +237,7 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
LLSD& friend_column = element["columns"][LIST_FRIEND_NAME];
friend_column["column"] = "friend_name";
friend_column["value"] = fullname;
- friend_column["font"] = "SANSSERIF";
+ friend_column["font"]["name"] = "SANSSERIF";
friend_column["font"]["style"] = "NORMAL";
LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
@@ -614,7 +614,7 @@ void LLPanelFriends::onClickPay(void* user_data)
std::vector<LLUUID> ids = panelp->getSelectedIDs();
if(ids.size() == 1)
{
- handle_pay_by_id(ids[0]);
+ LLAvatarActions::pay(ids[0]);
}
}
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 431bc09d86..e0fe87f9ae 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -205,7 +205,7 @@ void LLFloaterGesture::buildGestureList()
element["columns"][0]["column"] = "trigger";
element["columns"][0]["value"] = gesture->mTrigger;
- element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = font_style;
std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
@@ -232,13 +232,13 @@ void LLFloaterGesture::buildGestureList()
}
element["columns"][1]["column"] = "shortcut";
element["columns"][1]["value"] = buffer;
- element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][1]["font"]["name"] = "SANSSERIF";
element["columns"][1]["font"]["style"] = font_style;
// hidden column for sorting
element["columns"][2]["column"] = "key";
element["columns"][2]["value"] = key_string;
- element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
element["columns"][2]["font"]["style"] = font_style;
// Only add "playing" if we've got the name, less confusing. JC
@@ -248,26 +248,26 @@ void LLFloaterGesture::buildGestureList()
}
element["columns"][3]["column"] = "name";
element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"] = "SANSSERIF";
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
element["columns"][3]["font"]["style"] = font_style;
}
else
{
element["columns"][0]["column"] = "trigger";
element["columns"][0]["value"] = "";
- element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = font_style;
element["columns"][0]["column"] = "trigger";
element["columns"][0]["value"] = "---";
- element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = font_style;
element["columns"][2]["column"] = "key";
element["columns"][2]["value"] = "~~~";
- element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
element["columns"][2]["font"]["style"] = font_style;
element["columns"][3]["column"] = "name";
element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"] = "SANSSERIF";
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
element["columns"][3]["font"]["style"] = font_style;
}
list->addElement(element, ADD_BOTTOM);
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index b1f40d9d1d..3648898f28 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -372,7 +372,7 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
element["id"] = id;
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = group_datap->mName;
- element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = style;
group_list->addElement(element, ADD_SORTED);
@@ -390,7 +390,7 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
element["id"] = LLUUID::null;
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = LLTrans::getString("GroupsNone");
- element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = style;
group_list->addElement(element, ADD_TOP);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3fe7d8d9da..a378a511b5 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -62,6 +62,7 @@
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
#include "llselectmgr.h"
+#include "llslurl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
@@ -754,7 +755,7 @@ void LLPanelLandGeneral::refreshNames()
else
{
// Figure out the owner's name
- gCacheName->getFullName(parcel->getOwnerID(), owner);
+ owner = LLSLURL::buildCommand("agent", parcel->getOwnerID(), "inspect");
}
if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
@@ -763,18 +764,11 @@ void LLPanelLandGeneral::refreshNames()
}
mTextOwner->setText(owner);
- std::string group;
- if(!parcel->getGroupID().isNull())
- {
- gCacheName->getGroupName(parcel->getGroupID(), group);
- }
- mTextGroup->setText(group);
-
const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
if(auth_buyer_id.notNull())
{
std::string name;
- gCacheName->getFullName(auth_buyer_id, name);
+ name = LLSLURL::buildCommand("agent", auth_buyer_id, "inspect");
mSaleInfoForSale2->setTextArg("[BUYER]", name);
}
else
@@ -787,7 +781,20 @@ void LLPanelLandGeneral::refreshNames()
// virtual
void LLPanelLandGeneral::draw()
{
- refreshNames();
+ LLParcel *parcel = mParcel->getParcel();
+ if (parcel)
+ {
+ std::string group;
+ if (!parcel->getGroupID().isNull())
+ {
+ // *TODO: Change to "inspect" when we have group inspectors and
+ // move into refreshNames() above
+ // group = LLSLURL::buildCommand("group", parcel->getGroupID(), "inspect");
+ gCacheName->getGroupName(parcel->getGroupID(), group);
+ }
+ mTextGroup->setText(group);
+ }
+
LLPanel::draw();
}
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 10276ba36d..0330a8c692 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -37,7 +37,6 @@
#include <algorithm>
#include <functional>
-#include "llcachename.h"
#include "lldir.h"
#include "lldispatcher.h"
#include "llglheaders.h"
@@ -67,6 +66,7 @@
#include "llnamelistctrl.h"
#include "llscrolllistitem.h"
#include "llsliderctrl.h"
+#include "llslurl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
@@ -2560,30 +2560,6 @@ void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent,
}
}
-// static
-void LLPanelEstateInfo::callbackCacheName(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
-{
- LLPanelEstateInfo* self = LLFloaterRegionInfo::getPanelEstate();
- if (!self) return;
-
- std::string name;
-
- if (id.isNull())
- {
- name = "(none)";
- }
- else
- {
- name = first + " " + last;
- }
-
- self->setOwnerName(name);
-}
-
void LLPanelEstateInfo::clearAccessLists()
{
LLNameListCtrl* name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
@@ -2960,7 +2936,7 @@ BOOL LLPanelEstateCovenant::sendUpdate()
return TRUE;
}
-const std::string& LLPanelEstateCovenant::getEstateName() const
+std::string LLPanelEstateCovenant::getEstateName() const
{
return mEstateNameText->getText();
}
@@ -3011,7 +2987,7 @@ void LLPanelEstateCovenant::updateEstateOwnerName(const std::string& name)
}
}
-const std::string& LLPanelEstateCovenant::getOwnerName() const
+std::string LLPanelEstateCovenant::getOwnerName() const
{
return mEstateOwnerText->getText();
}
@@ -3069,8 +3045,9 @@ bool LLDispatchEstateUpdateInfo::operator()(
LLUUID owner_id(strings[1]);
regionp->setOwner(owner_id);
// Update estate owner name in UI
- const BOOL is_group = FALSE;
- gCacheName->get(owner_id, is_group, &LLPanelEstateInfo::callbackCacheName);
+ std::string owner_name =
+ LLSLURL::buildCommand("agent", owner_id, "inspect");
+ panel->setOwnerName(owner_name);
U32 estate_id = strtoul(strings[2].c_str(), NULL, 10);
panel->setEstateID(estate_id);
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index be4becf7e7..68ed4e0c89 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -338,14 +338,6 @@ public:
// are ignored, so must disable UI.
void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban);
- // this must have the same function signature as
- // llmessage/llcachename.h:LLCacheNameCallback
- static void callbackCacheName(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group);
-
protected:
virtual BOOL sendUpdate();
// confirmation dialog callback
@@ -400,9 +392,9 @@ public:
const LLUUID& getCovenantID() const { return mCovenantID; }
void setCovenantID(const LLUUID& id) { mCovenantID = id; }
- const std::string& getEstateName() const;
+ std::string getEstateName() const;
void setEstateName(const std::string& name);
- const std::string& getOwnerName() const;
+ std::string getOwnerName() const;
void setOwnerName(const std::string& name);
void setCovenantTextEditor(const std::string& text);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 3dcdc2f56e..1ec869da73 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -32,14 +32,13 @@
#include "llviewerprecompiledheaders.h"
-#include <sstream>
-
// self include
#include "llfloaterreporter.h"
+#include <sstream>
+
// linden library includes
#include "llassetstorage.h"
-#include "llcachename.h"
#include "llfontgl.h"
#include "llgl.h" // for renderer
#include "llinventory.h"
@@ -48,18 +47,14 @@
#include "llversionviewer.h"
#include "message.h"
#include "v3math.h"
-#include "lltexteditor.h"
// viewer project includes
#include "llagent.h"
#include "llbutton.h"
-#include "llcheckboxctrl.h"
#include "llfloaterreg.h"
-#include "lllineeditor.h"
#include "lltexturectrl.h"
#include "llscrolllistctrl.h"
#include "llimview.h"
-#include "lltextbox.h"
#include "lldispatcher.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@@ -72,6 +67,7 @@
#include "lltoolobjpicker.h"
#include "lltoolmgr.h"
#include "llresourcedata.h" // for LLResourceData
+#include "llslurl.h"
#include "llviewerwindow.h"
#include "llviewertexturelist.h"
#include "llworldmap.h"
@@ -103,6 +99,7 @@ LLFloaterReporter::LLFloaterReporter(const LLSD& key)
mObjectID(),
mScreenID(),
mAbuserID(),
+ mOwnerName(),
mDeselectOnClose( FALSE ),
mPicking( FALSE),
mPosition(),
@@ -158,6 +155,7 @@ BOOL LLFloaterReporter::postBuild()
// Default text to be blank
childSetText("object_name", LLStringUtil::null);
childSetText("owner_name", LLStringUtil::null);
+ mOwnerName = LLStringUtil::null;
childSetFocus("summary_edit");
@@ -174,8 +172,8 @@ BOOL LLFloaterReporter::postBuild()
// abuser name is selected from a list
- LLLineEditor* le = getChild<LLLineEditor>("abuser_name_edit");
- le->setEnabled( FALSE );
+ LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit");
+ le->setEnabled( false );
setPosBox((LLVector3d)mPosition.getValue());
LLButton* pick_btn = getChild<LLButton>("pick_btn");
@@ -299,9 +297,12 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
object_owner.append("Unknown");
}
childSetText("object_name", object_owner);
- childSetText("owner_name", object_owner);
+ std::string owner_link =
+ LLSLURL::buildCommand("agent", mObjectID, "inspect");
+ childSetText("owner_name", owner_link);
childSetText("abuser_name_edit", object_owner);
mAbuserID = object_id;
+ mOwnerName = object_owner;
}
else
{
@@ -445,6 +446,7 @@ void LLFloaterReporter::onClickObjPicker(void *userdata)
self->mPicking = TRUE;
self->childSetText("object_name", LLStringUtil::null);
self->childSetText("owner_name", LLStringUtil::null);
+ self->mOwnerName = LLStringUtil::null;
LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
if (pick_btn) pick_btn->setToggleState(TRUE);
}
@@ -505,9 +507,12 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
{
childSetText("object_name", object_name);
- childSetText("owner_name", owner_name);
+ std::string owner_link =
+ LLSLURL::buildCommand("agent", owner_id, "inspect");
+ childSetText("owner_name", owner_link);
childSetText("abuser_name_edit", owner_name);
mAbuserID = owner_id;
+ mOwnerName = owner_name;
}
@@ -608,11 +613,10 @@ LLSD LLFloaterReporter::gatherReport()
<< LL_VIEWER_BUILD << std::endl << std::endl;
std::string object_name = childGetText("object_name");
- std::string owner_name = childGetText("owner_name");
- if (!object_name.empty() && !owner_name.empty())
+ if (!object_name.empty() && !mOwnerName.empty())
{
details << "Object: " << object_name << "\n";
- details << "Owner: " << owner_name << "\n";
+ details << "Owner: " << mOwnerName << "\n";
}
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index 7e8f05e3fc..917f513641 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -128,6 +128,8 @@ private:
LLUUID mObjectID;
LLUUID mScreenID;
LLUUID mAbuserID;
+ // Store the real name, not the link, for upstream reporting
+ std::string mOwnerName;
BOOL mDeselectOnClose;
BOOL mPicking;
LLVector3 mPosition;
diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp
index 328fb6450e..3bf1848efb 100644
--- a/indra/newview/llfloaterscriptdebug.cpp
+++ b/indra/newview/llfloaterscriptdebug.cpp
@@ -167,6 +167,7 @@ void LLFloaterScriptDebugOutput::addLine(const std::string &utf8mesg, const std:
setShortTitle(user_name);
}
- mHistoryEditor->appendColoredText(utf8mesg, false, true, color);
+ mHistoryEditor->appendText(utf8mesg, true, LLStyle::Params().color(color));
+ mHistoryEditor->blockUndo();
}
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index fe98c84301..9e203c4269 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -131,7 +131,6 @@ LLFloaterSellLandUI::LLFloaterSellLandUI(const LLSD& key)
mRegion(0)
{
LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
-// LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_sell_land.xml");
mCloseSignal.connect(boost::bind(&LLFloaterSellLandUI::onClose, this));
}
@@ -153,7 +152,7 @@ void LLFloaterSellLandUI::SelectionObserver::changed()
{
mFloater->closeFloater();
}
- else
+ else if (mFloater->getVisible()) // only update selection if sell land ui in use
{
mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
LLViewerParcelMgr::getInstance()->getParcelSelection());
@@ -176,7 +175,7 @@ BOOL LLFloaterSellLandUI::postBuild()
bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
{
- if (!parcel->getParcel()) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS
+ if (!parcel->getParcel())
{
return false;
}
diff --git a/indra/newview/llfloatertestinspectors.cpp b/indra/newview/llfloatertestinspectors.cpp
index c56586cb95..8af011c17a 100644
--- a/indra/newview/llfloatertestinspectors.cpp
+++ b/indra/newview/llfloatertestinspectors.cpp
@@ -44,6 +44,8 @@ LLFloaterTestInspectors::LLFloaterTestInspectors(const LLSD& seed)
{
mCommitCallbackRegistrar.add("ShowAvatarInspector",
boost::bind(&LLFloaterTestInspectors::showAvatarInspector, this, _1, _2));
+ mCommitCallbackRegistrar.add("ShowObjectInspector",
+ boost::bind(&LLFloaterTestInspectors::showObjectInspector, this, _1, _2));
}
LLFloaterTestInspectors::~LLFloaterTestInspectors()
@@ -77,7 +79,12 @@ void LLFloaterTestInspectors::showAvatarInspector(LLUICtrl*, const LLSD& avatar_
id = avatar_id.asUUID();
}
// spawns off mouse position automatically
- LLFloaterReg::showInstance("inspect_avatar", id);
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", id));
+}
+
+void LLFloaterTestInspectors::showObjectInspector(LLUICtrl*, const LLSD& object_id)
+{
+ LLFloaterReg::showInstance("inspect_object", LLSD().insert("object_id", object_id));
}
void LLFloaterTestInspectors::onClickAvatar2D()
diff --git a/indra/newview/llfloatertestinspectors.h b/indra/newview/llfloatertestinspectors.h
index d2dc2248bb..6555aad4e8 100644
--- a/indra/newview/llfloatertestinspectors.h
+++ b/indra/newview/llfloatertestinspectors.h
@@ -50,6 +50,7 @@ private:
// Button callback to show
void showAvatarInspector(LLUICtrl*, const LLSD& avatar_id);
+ void showObjectInspector(LLUICtrl*, const LLSD& avatar_id);
// Debug function hookups for buttons
void onClickAvatar2D();
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 7dc29379e4..c08996cc26 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -36,7 +36,7 @@
#include "llfontgl.h"
#include "llcoord.h"
-#include "llgl.h"
+//#include "llgl.h"
#include "llagent.h"
#include "llbutton.h"
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 2eb4e7580e..266252efea 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -500,6 +500,14 @@ void LLFloaterUIPreview::refreshList()
}
}
found = TRUE;
+ while(found) // for every inspector file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+ found = TRUE;
while(found) // for every menu file that matches the pattern
{
if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name, FALSE))) // get next file matching pattern
@@ -596,20 +604,12 @@ void LLFloaterUIPreview::addFloaterEntry(const std::string& path)
void LLFloaterUIPreview::onClickDisplayFloater(S32 caller_id)
{
displayFloater(TRUE, caller_id);
- if(caller_id == PRIMARY_FLOATER)
- {
- mDisplayedFloater->center(); // move displayed floater to the center of the screen
- }
}
// Saves the current floater/panel
void LLFloaterUIPreview::onClickSaveFloater(S32 caller_id)
{
displayFloater(TRUE, caller_id, true);
- if(caller_id == PRIMARY_FLOATER)
- {
- mDisplayedFloater->center(); // move displayed floater to the center of the screen
- }
}
// Saves all floater/panels
@@ -672,7 +672,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
*floaterp = new LLPreviewedFloater(this);
- if(!strncmp(path.c_str(),"floater_",8)) // if it's a floater
+ if(!strncmp(path.c_str(),"floater_",8)
+ || !strncmp(path.c_str(), "inspect_", 8)) // if it's a floater
{
if (save)
{
@@ -774,13 +775,6 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
mCloseOtherButton_2->setEnabled(TRUE);
}
- // *TODO: Make the secondary floater pop up next to the primary one. Doesn't seem to always work if secondary was up first...
- if((mDisplayedFloater && ID == 2) || (mDisplayedFloater_2 && ID == 1))
- {
- mDisplayedFloater_2->setSnapTarget(mDisplayedFloater->getHandle());
- mDisplayedFloater->addDependentFloater(mDisplayedFloater_2);
- }
-
// Add localization to title so user knows whether it's localized or defaulted to en
std::string full_path = getLocalizedDirectory() + path;
std::string floater_lang = "EN";
@@ -793,6 +787,9 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
(ID == 1 ? " - Primary" : " - Secondary") + std::string("]");
(*floaterp)->setTitle(new_title);
+ (*floaterp)->center();
+ addDependentFloater(*floaterp);
+
if(click && ID == 1 && !save)
{
// set up live file to track it
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 490929e5a6..ef54ee7d4a 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -563,7 +563,7 @@ const std::string& LLFolderViewItem::getSearchableLabel() const
return mSearchableLabel;
}
-const std::string& LLFolderViewItem::getName( void ) const
+std::string LLFolderViewItem::getName( void ) const
{
if(mListener)
{
@@ -947,18 +947,6 @@ void LLFolderViewItem::draw()
}
}
}
-
- if( sDebugRects )
- {
- drawDebugRect();
- }
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
}
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index eec885fd29..32134670c8 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -255,7 +255,7 @@ public:
// This method returns the actual name of the thing being
// viewed. This method will ask the viewed object itself.
- const std::string& getName( void ) const;
+ std::string getName( void ) const;
const std::string& getSearchableLabel( void ) const;
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 905857f393..4caef8e000 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -301,13 +301,22 @@ void LLGroupListItem::setGroupIconVisible(bool visible)
void LLGroupListItem::setActive(bool active)
{
// Active group should be bold.
- LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc());
+ LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc());
// *NOTE dzaporozhan
// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
// is predefined as bold (SansSerifSmallBold, for example)
new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
- mGroupNameBox->setFont(LLFontGL::getFont(new_desc));
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+ LLStyle::Params style_params;
+ style_params.font = new_font;
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ std::string text = mGroupNameBox->getText();
+ mGroupNameBox->clear();
+ mGroupNameBox->appendText(text, false, style_params);
}
void LLGroupListItem::onInfoBtnClick()
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index d0be581f6d..dde36ac25b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -200,7 +200,6 @@ BOOL LLIMFloater::postBuild()
childSetCommitCallback("chat_editor", onSendMsg, this);
mHistoryEditor = getChild<LLViewerTextEditor>("im_text");
- mHistoryEditor->setParseHTML(TRUE);
setTitle(LLIMModel::instance().getName(mSessionID));
setDocked(true);
@@ -361,19 +360,21 @@ void LLIMFloater::updateMessages()
if (mLastFromName != from)
{
message << from << " ----- " << msg["time"].asString();
- mHistoryEditor->appendColoredText(message.str(), false,
- prepend_newline, divider_color);
+ mHistoryEditor->appendText(message.str(),
+ prepend_newline, LLStyle::Params().color(divider_color) );
message.str("");
mLastFromName = from;
}
message << msg["message"].asString();
- mHistoryEditor->appendColoredText(message.str(), false,
- prepend_newline, chat_color);
+ mHistoryEditor->appendText(message.str(),
+ prepend_newline,
+ LLStyle::Params().color(chat_color) );
message.str("");
mLastMessageIndex = msg["index"].asInteger();
}
+ mHistoryEditor->blockUndo();
mHistoryEditor->setCursorAndScrollToEnd();
}
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index abd3cd4def..89a885090c 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -1078,8 +1078,6 @@ BOOL LLFloaterIMPanel::postBuild()
//close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this);
mHistoryEditor = getChild<LLViewerTextEditor>("im_history");
- mHistoryEditor->setParseHTML(TRUE);
- mHistoryEditor->setParseHighlights(TRUE);
if ( IM_SESSION_GROUP_START == mDialog )
{
@@ -1334,16 +1332,18 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
if (name == SYSTEM_FROM)
{
- mHistoryEditor->appendColoredText(name + separator_string, false, prepend_newline, color);
+ mHistoryEditor->appendText(name + separator_string, prepend_newline, LLStyle::Params().color(color));
}
else
{
// Convert the name to a hotlink and add to message.
- mHistoryEditor->appendStyledText(name + separator_string, false, prepend_newline, LLStyleMap::instance().lookupAgent(source));
+ mHistoryEditor->appendText(name + separator_string, prepend_newline, LLStyleMap::instance().lookupAgent(source));
}
prepend_newline = false;
}
- mHistoryEditor->appendColoredText(utf8msg, false, prepend_newline, color);
+ mHistoryEditor->appendText(utf8msg, prepend_newline, LLStyle::Params().color(color));
+ mHistoryEditor->blockUndo();
+
S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
if (log_to_file && (im_log_option!=LOG_CHAT))
{
@@ -1859,7 +1859,8 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
}
//self->addHistoryLine(line, LLColor4::grey, FALSE);
- self->mHistoryEditor->appendColoredText(message, false, true, LLUIColorTable::instance().getColor("ChatHistoryTextColor"));
+ self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
+ self->mHistoryEditor->blockUndo();
}
void LLFloaterIMPanel::showSessionStartError(
@@ -1934,4 +1935,3 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const
}
return false;
}
-
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 72f89d2e72..a08d9e1163 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -34,15 +34,106 @@
#include "llinspectavatar.h"
// viewer files
+#include "llagent.h"
#include "llagentdata.h"
#include "llavataractions.h"
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
-
-// linden libraries
+#include "lldateutil.h" // ageFromDate()
+#include "llfloaterreporter.h"
+#include "llfloaterworldmap.h"
+#include "llmutelist.h"
+#include "llpanelblockedlist.h"
+#include "llviewermenu.h"
+#include "llvoiceclient.h"
+
+// Linden libraries
+#include "llcontrol.h" // LLCachedControl
+#include "llfloater.h"
+#include "llfloaterreg.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lluictrl.h"
+class LLFetchAvatarData;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectAvatar
+//////////////////////////////////////////////////////////////////////////////
+
+// Avatar Inspector, a small information window used when clicking
+// on avatar names in the 2D UI and in the ambient inspector widget for
+// the 3D world.
+class LLInspectAvatar : public LLFloater
+{
+ friend class LLFloaterReg;
+
+public:
+ // avatar_id - Avatar ID for which to show information
+ // Inspector will be positioned relative to current mouse position
+ LLInspectAvatar(const LLSD& avatar_id);
+ virtual ~LLInspectAvatar();
+
+ /*virtual*/ BOOL postBuild(void);
+ /*virtual*/ void draw();
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same avatar but in different position)
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ // Inspectors close themselves when they lose focus
+ /*virtual*/ void onFocusLost();
+
+ // Update view based on information from avatar properties processor
+ void processAvatarData(LLAvatarData* data);
+
+private:
+ // Make network requests for all the data to display in this view.
+ // Used on construction and if avatar id changes.
+ void requestUpdate();
+
+ // Set the volume slider to this user's current client-side volume setting,
+ // hiding/disabling if the user is not nearby.
+ void updateVolumeSlider();
+
+ // Button callbacks
+ void onClickAddFriend();
+ void onClickViewProfile();
+ void onClickIM();
+ void onClickTeleport();
+ void onClickInviteToGroup();
+ void onClickPay();
+ void onClickBlock();
+ void onClickReport();
+ bool onVisibleFindOnMap();
+ bool onVisibleGodMode();
+ void onClickMuteVolume();
+ void onFindOnMap();
+ void onVolumeChange(const LLSD& data);
+
+ // Callback for gCacheName to look up avatar name
+ void nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group);
+
+private:
+ LLUUID mAvatarID;
+ // Need avatar name information to spawn friend add request
+ std::string mAvatarName;
+ LLUUID mPartnerID;
+ // an in-flight request for avatar properties from LLAvatarPropertiesProcessor
+ // is represented by this object
+ LLFetchAvatarData* mPropertiesRequest;
+ LLFrameTimer mCloseTimer;
+ LLFrameTimer mOpenTimer;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// LLFetchAvatarData
+//////////////////////////////////////////////////////////////////////////////
+
// This object represents a pending request for avatar properties information
class LLFetchAvatarData : public LLAvatarPropertiesObserver
{
@@ -50,8 +141,8 @@ public:
// If the inspector closes it will delete the pending request object, so the
// inspector pointer will be valid for the lifetime of this object
LLFetchAvatarData(const LLUUID& avatar_id, LLInspectAvatar* inspector)
- : mAvatarID(avatar_id),
- mInspector(inspector)
+ : mAvatarID(avatar_id),
+ mInspector(inspector)
{
LLAvatarPropertiesProcessor* processor =
LLAvatarPropertiesProcessor::getInstance();
@@ -61,14 +152,14 @@ public:
// properties processor)
processor->sendAvatarPropertiesRequest(mAvatarID);
}
-
+
~LLFetchAvatarData()
{
// remove ourselves as an observer
LLAvatarPropertiesProcessor::getInstance()->
- removeObserver(mAvatarID, this);
+ removeObserver(mAvatarID, this);
}
-
+
void processProperties(void* data, EAvatarProcessorType type)
{
// route the data to the inspector
@@ -79,7 +170,7 @@ public:
mInspector->processAvatarData(avatar_data);
}
}
-
+
// Store avatar ID so we can un-register the observer on destruction
LLUUID mAvatarID;
LLInspectAvatar* mInspector;
@@ -88,10 +179,24 @@ public:
LLInspectAvatar::LLInspectAvatar(const LLSD& sd)
: LLFloater( LLSD() ), // single_instance, doesn't really need key
mAvatarID(), // set in onOpen()
- mFirstName(),
- mLastName(),
- mPropertiesRequest(NULL)
+ mPartnerID(),
+ mAvatarName(),
+ mPropertiesRequest(NULL),
+ mCloseTimer()
{
+ mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile", boost::bind(&LLInspectAvatar::onClickViewProfile, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.AddFriend", boost::bind(&LLInspectAvatar::onClickAddFriend, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.IM", boost::bind(&LLInspectAvatar::onClickIM, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Teleport", boost::bind(&LLInspectAvatar::onClickTeleport, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup", boost::bind(&LLInspectAvatar::onClickInviteToGroup, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Block", boost::bind(&LLInspectAvatar::onClickBlock, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Report", boost::bind(&LLInspectAvatar::onClickReport, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap", boost::bind(&LLInspectAvatar::onFindOnMap, this));
+ mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));
+ mVisibleCallbackRegistrar.add("InspectAvatar.VisibleGodMode", boost::bind(&LLInspectAvatar::onVisibleGodMode, this));
+
+
// can't make the properties request until the widgets are constructed
// as it might return immediately, so do it in postBuild.
}
@@ -100,6 +205,7 @@ LLInspectAvatar::~LLInspectAvatar()
{
// clean up any pending requests so they don't call back into a deleted
// view
+ llinfos << "JAMESDEBUG cleanup inspect avatar" << llendl;
delete mPropertiesRequest;
mPropertiesRequest = NULL;
}
@@ -113,18 +219,35 @@ BOOL LLInspectAvatar::postBuild(void)
getChild<LLUICtrl>("view_profile_btn")->setCommitCallback(
boost::bind(&LLInspectAvatar::onClickViewProfile, this) );
+ getChild<LLUICtrl>("mute_btn")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onClickMuteVolume, this) );
+
+ getChild<LLUICtrl>("volume_slider")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onVolumeChange, this, _2));
+
return TRUE;
}
void LLInspectAvatar::draw()
{
- static LLCachedControl<F32> FADE_OUT_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
- if (mCloseTimer.getStarted())
+ static LLCachedControl<F32> FADE_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
+ if (mOpenTimer.getStarted())
{
- F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 1.f, 0.f);
+ F32 alpha = clamp_rescale(mOpenTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 0.f, 1.f);
LLViewDrawContext context(alpha);
LLFloater::draw();
- if (mCloseTimer.getElapsedTimeF32() > FADE_OUT_TIME)
+ if (alpha == 1.f)
+ {
+ mOpenTimer.stop();
+ }
+
+ }
+ else if (mCloseTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ if (mCloseTimer.getElapsedTimeF32() > FADE_TIME)
{
closeFloater(false);
}
@@ -142,9 +265,11 @@ void LLInspectAvatar::draw()
void LLInspectAvatar::onOpen(const LLSD& data)
{
mCloseTimer.stop();
+ mOpenTimer.start();
// Extract appropriate avatar id
- mAvatarID = data.isUUID() ? data : data["avatar_id"];
+ mAvatarID = data["avatar_id"];
+ mPartnerID = LLUUID::null;
// Position the inspector relative to the mouse cursor
// Similar to how tooltips are positioned
@@ -160,6 +285,8 @@ void LLInspectAvatar::onOpen(const LLSD& data)
// can't call from constructor as widgets are not built yet
requestUpdate();
+
+ updateVolumeSlider();
}
//virtual
@@ -167,6 +294,7 @@ void LLInspectAvatar::onFocusLost()
{
// Start closing when we lose focus
mCloseTimer.start();
+ mOpenTimer.stop();
}
void LLInspectAvatar::requestUpdate()
@@ -178,7 +306,9 @@ void LLInspectAvatar::requestUpdate()
getChild<LLUICtrl>("user_subtitle")->
setValue("Test subtitle");
getChild<LLUICtrl>("user_details")->
- setValue("Test details\nTest line 2");
+ setValue("Test details");
+ getChild<LLUICtrl>("user_partner")->
+ setValue("Test partner");
return;
}
@@ -186,6 +316,7 @@ void LLInspectAvatar::requestUpdate()
getChild<LLUICtrl>("user_name")->setValue("");
getChild<LLUICtrl>("user_subtitle")->setValue("");
getChild<LLUICtrl>("user_details")->setValue("");
+ getChild<LLUICtrl>("user_partner")->setValue("");
// Make a new request for properties
delete mPropertiesRequest;
@@ -212,49 +343,187 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
{
LLStringUtil::format_map_t args;
args["[BORN_ON]"] = data->born_on;
- args["[AGE]"] = LLAvatarPropertiesProcessor::ageFromDate(data->born_on);
+ args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on);
args["[SL_PROFILE]"] = data->about_text;
args["[RW_PROFILE"] = data->fl_about_text;
args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);
- args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(data);
+ std::string payment_info = LLAvatarPropertiesProcessor::paymentInfo(data);
+ args["[PAYMENTINFO]"] = payment_info;
+ args["[COMMA]"] = (payment_info.empty() ? "" : ",");
std::string subtitle = getString("Subtitle", args);
getChild<LLUICtrl>("user_subtitle")->setValue( LLSD(subtitle) );
std::string details = getString("Details", args);
getChild<LLUICtrl>("user_details")->setValue( LLSD(details) );
+ // Look up partner name, if there is one
+ mPartnerID = data->partner_id;
+ if (mPartnerID.notNull())
+ {
+ gCacheName->get(mPartnerID, FALSE,
+ boost::bind(&LLInspectAvatar::nameUpdatedCallback,
+ this, _1, _2, _3, _4));
+ }
+
// Delete the request object as it has been satisfied
delete mPropertiesRequest;
mPropertiesRequest = NULL;
}
+void LLInspectAvatar::updateVolumeSlider()
+{
+ // By convention, we only display and toggle voice mutes, not all mutes
+ bool is_muted = LLMuteList::getInstance()->
+ isMuted(mAvatarID, LLMute::flagVoiceChat);
+ bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID);
+
+ LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
+ mute_btn->setEnabled( voice_enabled );
+ mute_btn->setValue( is_muted );
+
+ LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
+ volume_slider->setEnabled( voice_enabled && !is_muted );
+ const F32 DEFAULT_VOLUME = 0.5f;
+ F32 volume;
+ if (is_muted)
+ {
+ // it's clearer to display their volume as zero
+ volume = 0.f;
+ }
+ else if (!voice_enabled)
+ {
+ // use nominal value rather than 0
+ volume = DEFAULT_VOLUME;
+ }
+ else
+ {
+ // actual volume
+ volume = gVoiceClient->getUserVolume(mAvatarID);
+
+ // *HACK: Voice client doesn't have any data until user actually
+ // says something.
+ if (volume == 0.f)
+ {
+ volume = DEFAULT_VOLUME;
+ }
+ }
+ volume_slider->setValue( (F64)volume );
+}
+
+void LLInspectAvatar::onClickMuteVolume()
+{
+ // By convention, we only display and toggle voice mutes, not all mutes
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+ if (!is_muted)
+ {
+ mute_list->add(mute, LLMute::flagVoiceChat);
+ }
+ else
+ {
+ mute_list->remove(mute, LLMute::flagVoiceChat);
+ }
+
+ updateVolumeSlider();
+}
+
+void LLInspectAvatar::onVolumeChange(const LLSD& data)
+{
+ F32 volume = (F32)data.asReal();
+ gVoiceClient->setUserVolume(mAvatarID, volume);
+}
+
void LLInspectAvatar::nameUpdatedCallback(
const LLUUID& id,
const std::string& first,
const std::string& last,
BOOL is_group)
{
- // Possibly a request for an older inspector
- if (id != mAvatarID) return;
-
- mFirstName = first;
- mLastName = last;
- std::string name = first + " " + last;
-
- childSetValue("user_name", LLSD(name) );
+ if (id == mAvatarID)
+ {
+ mAvatarName = first + " " + last;
+ childSetValue("user_name", LLSD(mAvatarName) );
+ }
+
+ if (id == mPartnerID)
+ {
+ LLStringUtil::format_map_t args;
+ args["[PARTNER]"] = first + " " + last;
+ std::string partner = getString("Partner", args);
+ getChild<LLUICtrl>("user_partner")->setValue(partner);
+ }
+ // Otherwise possibly a request for an older inspector, ignore it
}
void LLInspectAvatar::onClickAddFriend()
{
- std::string name;
- name.assign(mFirstName);
- name.append(" ");
- name.append(mLastName);
-
- LLAvatarActions::requestFriendshipDialog(mAvatarID, name);
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
}
void LLInspectAvatar::onClickViewProfile()
{
+ // hide inspector when showing profile
+ setFocus(FALSE);
LLAvatarActions::showProfile(mAvatarID);
+
+}
+
+bool LLInspectAvatar::onVisibleFindOnMap()
+{
+ return gAgent.isGodlike() || is_agent_mappable(mAvatarID);
+}
+
+bool LLInspectAvatar::onVisibleGodMode()
+{
+ return gAgent.isGodlike();
+}
+
+void LLInspectAvatar::onClickIM()
+{
+ LLAvatarActions::startIM(mAvatarID);
+}
+
+void LLInspectAvatar::onClickTeleport()
+{
+ LLAvatarActions::offerTeleport(mAvatarID);
+}
+
+void LLInspectAvatar::onClickInviteToGroup()
+{
+ LLAvatarActions::inviteToGroup(mAvatarID);
+}
+
+void LLInspectAvatar::onClickPay()
+{
+ LLAvatarActions::pay(mAvatarID);
+}
+
+void LLInspectAvatar::onClickBlock()
+{
+ LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+}
+
+void LLInspectAvatar::onClickReport()
+{
+ LLFloaterReporter::showFromObject(mAvatarID);
+}
+
+
+void LLInspectAvatar::onFindOnMap()
+{
+ gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName);
+ LLFloaterReg::showInstance("world_map");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectAvatarUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectAvatarUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_avatar", "inspect_avatar.xml",
+ &LLFloaterReg::build<LLInspectAvatar>);
}
diff --git a/indra/newview/llinspectavatar.h b/indra/newview/llinspectavatar.h
index 8d490382d2..179ad1ffe1 100644
--- a/indra/newview/llinspectavatar.h
+++ b/indra/newview/llinspectavatar.h
@@ -32,63 +32,10 @@
#ifndef LLINSPECTAVATAR_H
#define LLINSPECTAVATAR_H
-#include "llfloater.h"
-
-struct LLAvatarData;
-class LLFetchAvatarData;
-
-// Avatar Inspector, a small information window used when clicking
-// on avatar names in the 2D UI and in the ambient inspector widget for
-// the 3D world.
-class LLInspectAvatar : public LLFloater
+namespace LLInspectAvatarUtil
{
- friend class LLFloaterReg;
-
-public:
- // avatar_id - Avatar ID for which to show information
- // Inspector will be positioned relative to current mouse position
- LLInspectAvatar(const LLSD& avatar_id);
- virtual ~LLInspectAvatar();
-
- /*virtual*/ BOOL postBuild(void);
- /*virtual*/ void draw();
-
- // Because floater is single instance, need to re-parse data on each spawn
- // (for example, inspector about same avatar but in different position)
- /*virtual*/ void onOpen(const LLSD& avatar_id);
-
- // Inspectors close themselves when they lose focus
- /*virtual*/ void onFocusLost();
-
- // Update view based on information from avatar properties processor
- void processAvatarData(LLAvatarData* data);
-
-private:
- // Make network requests for all the data to display in this view.
- // Used on construction and if avatar id changes.
- void requestUpdate();
-
- // Button callbacks
- void onClickAddFriend();
- void onClickViewProfile();
-
- // Callback for gCacheName to look up avatar name
- void nameUpdatedCallback(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group);
-
-private:
- LLUUID mAvatarID;
- // Need avatar name information to spawn friend add request
- std::string mFirstName;
- std::string mLastName;
- // an in-flight request for avatar properties from LLAvatarPropertiesProcessor
- // is represented by this object
- LLFetchAvatarData* mPropertiesRequest;
- LLFrameTimer mCloseTimer;
-};
-
+ // Register with LLFloaterReg
+ void registerFloater();
+}
#endif
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
new file mode 100644
index 0000000000..b0e6273c41
--- /dev/null
+++ b/indra/newview/llinspectobject.cpp
@@ -0,0 +1,563 @@
+/**
+ * @file llinspectobject.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspectobject.h"
+
+// Viewer
+#include "llnotifications.h" // *TODO: Eliminate, add LLNotificationsUtil wrapper
+#include "llselectmgr.h"
+#include "llslurl.h"
+#include "llviewermenu.h" // handle_object_touch(), handle_buy()
+#include "llviewerobjectlist.h" // to select the requested object
+
+// Linden libraries
+#include "llbutton.h" // setLabel(), not virtual!
+#include "llclickaction.h"
+#include "llcontrol.h" // LLCachedControl
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llresmgr.h" // getMonetaryString
+#include "llsafehandle.h"
+#include "lltextbox.h" // for description truncation
+#include "lltrans.h"
+#include "llui.h" // positionViewNearMouse()
+#include "lluictrl.h"
+
+class LLViewerObject;
+
+// *TODO: Abstract out base class for LLInspectObject and LLInspectObject
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectObject
+//////////////////////////////////////////////////////////////////////////////
+
+// Object Inspector, a small information window used when clicking
+// in the ambient inspector widget for objects in the 3D world.
+class LLInspectObject : public LLFloater
+{
+ friend class LLFloaterReg;
+
+public:
+ // object_id - Root object ID for which to show information
+ // Inspector will be positioned relative to current mouse position
+ LLInspectObject(const LLSD& object_id);
+ virtual ~LLInspectObject();
+
+ /*virtual*/ BOOL postBuild(void);
+ /*virtual*/ void draw();
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same avatar but in different position)
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ // Release the selection and do other cleanup
+ void onClose();
+
+ // Inspectors close themselves when they lose focus
+ /*virtual*/ void onFocusLost();
+
+private:
+ // Refresh displayed data with information from selection manager
+ void update();
+
+ void hideButtons();
+ void updateButtons(LLSelectNode* nodep);
+ void updateSitLabel(LLSelectNode* nodep);
+ void updateTouchLabel(LLSelectNode* nodep);
+
+ void updateName(LLSelectNode* nodep);
+ void updateDescription(LLSelectNode* nodep);
+ void updatePrice(LLSelectNode* nodep);
+
+ void updateCreator(LLSelectNode* nodep);
+
+ void onClickBuy();
+ void onClickPay();
+ void onClickTakeFreeCopy();
+ void onClickTouch();
+ void onClickSit();
+ void onClickOpen();
+ void onClickMoreInfo();
+
+private:
+ LLUUID mObjectID;
+ LLFrameTimer mOpenTimer;
+ LLFrameTimer mCloseTimer;
+ LLSafeHandle<LLObjectSelection> mObjectSelection;
+};
+
+LLInspectObject::LLInspectObject(const LLSD& sd)
+: LLFloater( LLSD() ), // single_instance, doesn't really need key
+ mObjectID(), // set in onOpen()
+ mCloseTimer(),
+ mOpenTimer()
+{
+ // can't make the properties request until the widgets are constructed
+ // as it might return immediately, so do it in postBuild.
+ mCommitCallbackRegistrar.add("InspectObject.Buy", boost::bind(&LLInspectObject::onClickBuy, this));
+ mCommitCallbackRegistrar.add("InspectObject.Pay", boost::bind(&LLInspectObject::onClickPay, this));
+ mCommitCallbackRegistrar.add("InspectObject.TakeFreeCopy", boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
+ mCommitCallbackRegistrar.add("InspectObject.Touch", boost::bind(&LLInspectObject::onClickTouch, this));
+ mCommitCallbackRegistrar.add("InspectObject.Sit", boost::bind(&LLInspectObject::onClickSit, this));
+ mCommitCallbackRegistrar.add("InspectObject.Open", boost::bind(&LLInspectObject::onClickOpen, this));
+ mCommitCallbackRegistrar.add("InspectObject.MoreInfo", boost::bind(&LLInspectObject::onClickMoreInfo, this));
+}
+
+
+LLInspectObject::~LLInspectObject()
+{
+}
+
+/*virtual*/
+BOOL LLInspectObject::postBuild(void)
+{
+ // The XML file has sample data in it. Clear that out so we don't
+ // flicker when data arrives off network.
+ getChild<LLUICtrl>("object_name")->setValue("");
+ getChild<LLUICtrl>("object_creator")->setValue("");
+ getChild<LLUICtrl>("object_description")->setValue("");
+
+ // Set buttons invisible until we know what this object can do
+ hideButtons();
+
+ // Hide floater when name links clicked
+ LLTextBox* textbox = getChild<LLTextBox>("object_creator");
+ textbox->mURLClickSignal.connect(
+ boost::bind(&LLInspectObject::closeFloater, this, false) );
+
+ // Hook up functionality
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickBuy, this));
+ getChild<LLUICtrl>("pay_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickPay, this));
+ getChild<LLUICtrl>("take_free_copy_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
+ getChild<LLUICtrl>("touch_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickTouch, this));
+ getChild<LLUICtrl>("sit_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickSit, this));
+ getChild<LLUICtrl>("open_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickOpen, this));
+ getChild<LLUICtrl>("more_info_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickMoreInfo, this));
+
+ // Watch for updates to selection properties off the network
+ LLSelectMgr::getInstance()->mUpdateSignal.connect(
+ boost::bind(&LLInspectObject::update, this) );
+
+ mCloseSignal.connect( boost::bind(&LLInspectObject::onClose, this) );
+
+ return TRUE;
+}
+
+void LLInspectObject::draw()
+{
+ static LLCachedControl<F32> FADE_OUT_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
+ if (mOpenTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mOpenTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 0.f, 1.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ }
+ else if (mCloseTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ if (mCloseTimer.getElapsedTimeF32() > FADE_OUT_TIME)
+ {
+ closeFloater(false);
+ }
+ }
+ else
+ {
+ LLFloater::draw();
+ }
+}
+
+
+// Multiple calls to showInstance("inspect_avatar", foo) will provide different
+// LLSD for foo, which we will catch here.
+//virtual
+void LLInspectObject::onOpen(const LLSD& data)
+{
+ mCloseTimer.stop();
+ mOpenTimer.start();
+
+ // Extract appropriate avatar id
+ mObjectID = data["object_id"];
+
+ // Position the inspector relative to the mouse cursor
+ // Similar to how tooltips are positioned
+ // See LLToolTipMgr::createToolTip
+ if (data.has("pos"))
+ {
+ LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
+ }
+ else
+ {
+ LLUI::positionViewNearMouse(this);
+ }
+
+ // Promote hovered object to a complete selection, which will also force
+ // a request for selected object data off the network
+ LLViewerObject* obj = gObjectList.findObject( mObjectID );
+ if (obj)
+ {
+ LLSelectMgr::instance().deselectAll();
+ mObjectSelection = LLSelectMgr::instance().selectObjectAndFamily(obj);
+
+ // Mark this as a transient selection
+ struct SetTransient : public LLSelectedNodeFunctor
+ {
+ bool apply(LLSelectNode* node)
+ {
+ node->setTransient(TRUE);
+ return true;
+ }
+ } functor;
+ mObjectSelection->applyToNodes(&functor);
+ }
+}
+
+void LLInspectObject::onClose()
+{
+ // Release selection to deselect
+ mObjectSelection = NULL;
+}
+
+//virtual
+void LLInspectObject::onFocusLost()
+{
+ // Start closing when we lose focus
+ mCloseTimer.start();
+ mOpenTimer.stop();
+}
+
+
+void LLInspectObject::update()
+{
+ // Performance optimization, because we listen to updates from select mgr
+ // but we're never destroyed.
+ if (!getVisible()) return;
+
+ LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
+ if (!selection) return;
+
+ LLSelectNode* nodep = selection->getFirstRootNode();
+ if (!nodep) return;
+
+ updateButtons(nodep);
+ updateName(nodep);
+ updateDescription(nodep);
+ updateCreator(nodep);
+ updatePrice(nodep);
+}
+
+void LLInspectObject::hideButtons()
+{
+ getChild<LLUICtrl>("buy_btn")->setVisible(false);
+ getChild<LLUICtrl>("pay_btn")->setVisible(false);
+ getChild<LLUICtrl>("take_free_copy_btn")->setVisible(false);
+ getChild<LLUICtrl>("touch_btn")->setVisible(false);
+ getChild<LLUICtrl>("sit_btn")->setVisible(false);
+ getChild<LLUICtrl>("open_btn")->setVisible(false);
+}
+
+// *TODO: Extract this method from lltoolpie.cpp and put somewhere shared
+extern U8 final_click_action(LLViewerObject*);
+
+// Choose the "most relevant" operation for this object, and show a button for
+// that operation as the left-most button in the inspector.
+void LLInspectObject::updateButtons(LLSelectNode* nodep)
+{
+ // We'll start with everyone hidden and show the ones we need
+ hideButtons();
+
+ LLViewerObject* object = nodep->getObject();
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ bool for_copy = anyone_copy_selection(nodep);
+ bool for_sale = enable_buy_object();
+ S32 price = nodep->mSaleInfo.getSalePrice();
+ U8 click_action = final_click_action(object);
+
+ if (for_copy
+ || (for_sale && price == 0))
+ {
+ // Free copies have priority over other operations
+ getChild<LLUICtrl>("take_free_copy_btn")->setVisible(true);
+ }
+ else if (for_sale)
+ {
+ getChild<LLUICtrl>("buy_btn")->setVisible(true);
+ }
+ else if ( enable_pay_object() )
+ {
+ getChild<LLUICtrl>("pay_btn")->setVisible(true);
+ }
+ else if (click_action == CLICK_ACTION_SIT)
+ {
+ // Click-action sit must come before "open" because many objects on
+ // which you can sit have scripts, and hence can be opened
+ getChild<LLUICtrl>("sit_btn")->setVisible(true);
+ updateSitLabel(nodep);
+ }
+ else if (object->flagHandleTouch()
+ || (parent && parent->flagHandleTouch()))
+ {
+ getChild<LLUICtrl>("touch_btn")->setVisible(true);
+ updateTouchLabel(nodep);
+ }
+ else if ( enable_object_open() )
+ {
+ // Open is last because anything with a script in it can be opened
+ getChild<LLUICtrl>("open_btn")->setVisible(true);
+ }
+ else
+ {
+ // By default, we can sit on anything
+ getChild<LLUICtrl>("sit_btn")->setVisible(true);
+ updateSitLabel(nodep);
+ }
+
+ // No flash
+ focusFirstItem(FALSE, FALSE);
+}
+
+void LLInspectObject::updateSitLabel(LLSelectNode* nodep)
+{
+ LLButton* sit_btn = getChild<LLButton>("sit_btn");
+ if (!nodep->mSitName.empty())
+ {
+ sit_btn->setLabel( nodep->mSitName );
+ }
+ else
+ {
+ sit_btn->setLabel( getString("Sit") );
+ }
+}
+
+void LLInspectObject::updateTouchLabel(LLSelectNode* nodep)
+{
+ LLButton* sit_btn = getChild<LLButton>("touch_btn");
+ if (!nodep->mTouchName.empty())
+ {
+ sit_btn->setLabel( nodep->mTouchName );
+ }
+ else
+ {
+ sit_btn->setLabel( getString("Touch") );
+ }
+}
+
+void LLInspectObject::updateName(LLSelectNode* nodep)
+{
+ std::string name;
+ if (!nodep->mName.empty())
+ {
+ name = nodep->mName;
+ }
+ else
+ {
+ name = LLTrans::getString("TooltipNoName");
+ }
+ getChild<LLUICtrl>("object_name")->setValue(name);
+}
+
+void LLInspectObject::updateDescription(LLSelectNode* nodep)
+{
+ const char* const DEFAULT_DESC = "(No Description)";
+ std::string desc;
+ if (!nodep->mDescription.empty()
+ && nodep->mDescription != DEFAULT_DESC)
+ {
+ desc = nodep->mDescription;
+ }
+
+ LLTextBox* textbox = getChild<LLTextBox>("object_description");
+ textbox->setValue(desc);
+
+ // Truncate description text to fit in widget
+ // *HACK: OMG, use lower-left corner to truncate text
+ // Don't round the position, we want the left of the character
+ S32 corner_index = textbox->getDocIndexFromLocalCoord( 0, 0, FALSE);
+ LLWString desc_wide = textbox->getWText();
+ // index == length if position is past last character
+ if (corner_index < (S32)desc_wide.length())
+ {
+ desc_wide = desc_wide.substr(0, corner_index);
+ textbox->setWText(desc_wide);
+ }
+}
+
+void LLInspectObject::updateCreator(LLSelectNode* nodep)
+{
+ // final information for display
+ LLStringUtil::format_map_t args;
+ std::string text;
+
+ // Leave text blank until data loaded
+ if (nodep->mValid)
+ {
+ // Utilize automatic translation of SLURL into name to display
+ // a clickable link
+ // Objects cannot be created by a group, so use agent URL format
+ LLUUID creator_id = nodep->mPermissions->getCreator();
+ std::string creator_url =
+ LLSLURL::buildCommand("agent", creator_id, "about");
+ args["[CREATOR]"] = creator_url;
+
+ // created by one user but owned by another
+ std::string owner_url;
+ LLUUID owner_id;
+ bool group_owned = nodep->mPermissions->isGroupOwned();
+ if (group_owned)
+ {
+ owner_id = nodep->mPermissions->getGroup();
+ owner_url = LLSLURL::buildCommand("group", owner_id, "about");
+ }
+ else
+ {
+ owner_id = nodep->mPermissions->getOwner();
+ owner_url = LLSLURL::buildCommand("agent", owner_id, "about");
+ }
+ args["[OWNER]"] = owner_url;
+
+ if (creator_id == owner_id)
+ {
+ // common case, created and owned by one user
+ text = getString("Creator", args);
+ }
+ else
+ {
+ text = getString("CreatorAndOwner", args);
+ }
+ }
+ getChild<LLUICtrl>("object_creator")->setValue(text);
+}
+
+void LLInspectObject::updatePrice(LLSelectNode* nodep)
+{
+ // *TODO: Only look these up once and use for both updateButtons and here
+ bool for_copy = anyone_copy_selection(nodep);
+ bool for_sale = enable_buy_object();
+ S32 price = nodep->mSaleInfo.getSalePrice();
+
+ bool show_price_icon = false;
+ std::string line;
+ if (for_copy
+ || (for_sale && price == 0))
+ {
+ line = getString("PriceFree");
+ show_price_icon = true;
+ }
+ else if (for_sale)
+ {
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = LLResMgr::getInstance()->getMonetaryString(price);
+ line = getString("Price", args);
+ show_price_icon = true;
+ }
+ getChild<LLUICtrl>("price_text")->setValue(line);
+ getChild<LLUICtrl>("price_icon")->setVisible(show_price_icon);
+}
+
+void LLInspectObject::onClickBuy()
+{
+ handle_buy();
+ closeFloater();
+}
+
+void LLInspectObject::onClickPay()
+{
+ handle_give_money_dialog();
+ closeFloater();
+}
+
+void LLInspectObject::onClickTakeFreeCopy()
+{
+ LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
+ if (!selection) return;
+
+ LLSelectNode* nodep = selection->getFirstRootNode();
+ if (!nodep) return;
+
+ // Figure out if this is a "free buy" or a "take copy"
+ bool for_copy = anyone_copy_selection(nodep);
+ // Prefer to just take a free copy
+ if (for_copy)
+ {
+ handle_take_copy();
+ }
+ else
+ {
+ // Buy for free (confusing, but that's how it is)
+ handle_buy();
+ }
+ closeFloater();
+}
+
+void LLInspectObject::onClickTouch()
+{
+ handle_object_touch();
+ closeFloater();
+}
+
+void LLInspectObject::onClickSit()
+{
+ handle_object_sit_or_stand();
+ closeFloater();
+}
+
+void LLInspectObject::onClickOpen()
+{
+ LLFloaterReg::showInstance("openobject");
+ closeFloater();
+}
+
+void LLInspectObject::onClickMoreInfo()
+{
+ // *TODO: Show object info side panel, once that is implemented.
+ LLNotifications::instance().add("ClickUnimplemented");
+ closeFloater();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectObjectUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectObjectUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_object", "inspect_object.xml",
+ &LLFloaterReg::build<LLInspectObject>);
+}
+
diff --git a/indra/newview/llinspectobject.h b/indra/newview/llinspectobject.h
new file mode 100644
index 0000000000..aa45f401c0
--- /dev/null
+++ b/indra/newview/llinspectobject.h
@@ -0,0 +1,40 @@
+/**
+ * @file llinspectobject.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECTOBJECT_H
+#define LLINSPECTOBJECT_H
+
+namespace LLInspectObjectUtil
+{
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index efc03b3d88..4fd3b7bddc 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -537,18 +537,6 @@ void LLJoystickCameraRotate::draw()
{
drawRotatedImage( getImageSelected()->getImage(), 3 );
}
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
}
// Draws image rotated by multiples of 90 degrees
@@ -723,18 +711,6 @@ void LLJoystickCameraZoom::draw()
{
getImageUnselected()->draw( 0, 0 );
}
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
}
void LLJoystickCameraZoom::updateSlop()
diff --git a/indra/newview/lllistview.cpp b/indra/newview/lllistview.cpp
index 3019d5d3d5..f4f3b1df78 100644
--- a/indra/newview/lllistview.cpp
+++ b/indra/newview/lllistview.cpp
@@ -57,7 +57,7 @@ LLListView::LLListView(const Params& p)
LLRect label_rect(0, 20, 300, 0);
LLTextBox::Params text_box_params;
text_box_params.rect(label_rect);
- text_box_params.text("This is a list-view");
+ text_box_params.initial_value("This is a list-view");
mLabel = LLUICtrlFactory::create<LLTextBox>(text_box_params);
addChild(mLabel);
}
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 68dc3854db..16a10dc502 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -290,10 +290,10 @@ void LLLocationInputCtrl::hideList()
focusTextEntry();
}
-BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, MASK mask)
{
// Let the buttons show their tooltips.
- if (LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen) && !msg.empty())
+ if (LLUICtrl::handleToolTip(x, y, mask))
{
if (mList->getRect().pointInRect(x, y))
{
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index 6edae9a9e2..c74a294ca3 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -71,7 +71,7 @@ public:
// LLView interface
/*virtual*/ void setEnabled(BOOL enabled);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp
index 1666ec1336..f61177d581 100644
--- a/indra/newview/llmenucommands.cpp
+++ b/indra/newview/llmenucommands.cpp
@@ -49,7 +49,6 @@
#include "llfloaterchat.h"
#include "llfloaterdirectory.h"
#include "llfloaterworldmap.h"
-#include "llgivemoney.h"
#include "lllineeditor.h"
#include "llnotify.h"
#include "llstatusbar.h"
@@ -68,11 +67,6 @@
#include "llfocusmgr.h"
#include "llnearbychatbar.h"
-void handle_pay_by_id(const LLUUID& agent_id)
-{
- const BOOL is_group = FALSE;
- LLFloaterPay::payDirectly(&give_money, agent_id, is_group);
-}
void handle_mouselook(void*)
{
diff --git a/indra/newview/llmenucommands.h b/indra/newview/llmenucommands.h
index 368c6fe752..a3611ef6d1 100644
--- a/indra/newview/llmenucommands.h
+++ b/indra/newview/llmenucommands.h
@@ -35,7 +35,6 @@
class LLUUID;
-void handle_pay_by_id(const LLUUID& agent_id);
void handle_mouselook(void*);
void handle_chat(void*);
void handle_return_key(void*);
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 8ef6b25c50..541db0ca6e 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -32,16 +32,18 @@
#include "llviewerprecompiledheaders.h"
-#include <boost/tokenizer.hpp>
-
#include "llnamelistctrl.h"
+#include <boost/tokenizer.hpp>
+
#include "llcachename.h"
+#include "llfloaterreg.h"
#include "llinventory.h"
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
#include "llscrolllistcolumn.h"
#include "llsdparam.h"
+#include "lltooltip.h"
static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list");
@@ -128,6 +130,60 @@ BOOL LLNameListCtrl::handleDragAndDrop(
return handled;
}
+void LLNameListCtrl::showAvatarInspector(const LLUUID& avatar_id)
+{
+ LLSD key;
+ key["avatar_id"] = avatar_id;
+ LLFloaterReg::showInstance("inspect_avatar", key);
+}
+
+//virtual
+BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+ S32 column_index = getColumnIndexFromOffset(x);
+ LLScrollListItem* hit_item = hitItem(x, y);
+ if (hit_item)
+ {
+ if (column_index == mNameColumnIndex)
+ {
+ // ...this is the column with the avatar name
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (hit_cell)
+ {
+ S32 row_index = getItemIndex(hit_item);
+ LLRect cell_rect = getCellRect(row_index, column_index);
+ // Convert rect local to screen coordinates
+ LLRect sticky_rect;
+ localRectToScreen(cell_rect, &sticky_rect);
+
+ // Spawn at right side of cell
+ LLCoordGL pos( sticky_rect.mRight - 16, sticky_rect.mTop );
+ LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small");
+ LLUUID avatar_id = hit_item->getValue().asUUID();
+
+ LLToolTip::Params params;
+ params.background_visible( false );
+ params.click_callback( boost::bind(&LLNameListCtrl::showAvatarInspector, this, avatar_id) );
+ params.delay_time(0.0f); // spawn instantly on hover
+ params.image( icon );
+ params.message("");
+ params.padding(0);
+ params.pos(pos);
+ params.sticky_rect(sticky_rect);
+
+ LLToolTipMgr::getInstance()->show(params);
+ handled = TRUE;
+ }
+ }
+ }
+ if (!handled)
+ {
+ handled = LLScrollListCtrl::handleToolTip(x, y, mask);
+ }
+ return handled;
+}
+
// public
void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos,
BOOL enabled)
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 070b6c4f4f..d0f0ec4d21 100644
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -110,15 +110,20 @@ public:
static void refreshAll(const LLUUID& id, const std::string& firstname,
const std::string& lastname, BOOL is_group);
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ // LLView interface
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
void setAllowCallingCardDrop(BOOL b) { mAllowCallingCardDrop = b; }
/*virtual*/ void updateColumns();
private:
+ void showAvatarInspector(const LLUUID& avatar_id);
+
+private:
S32 mNameColumnIndex;
std::string mNameColumn;
BOOL mAllowCallingCardDrop;
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 8430937933..cc5f37b903 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -51,6 +51,7 @@
//for LLViewerTextEditor support
#include "llagent.h" // gAgent
#include "llfloaterscriptdebug.h"
+#include "llslurl.h"
#include "llviewertexteditor.h"
#include "llstylemap.h"
@@ -207,7 +208,7 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
if (chat.mSourceType == CHAT_SOURCE_AGENT &&
chat.mFromID != LLUUID::null)
{
- str_URL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
+ str_URL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
}
// If the chat line has an associated url, link it up to the name.
@@ -216,20 +217,31 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
{
std::string start_line = line.substr(0, chat.mFromName.length() + 1);
line = line.substr(chat.mFromName.length() + 1);
- mChatHistoryEditor->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,str_URL));
+ mChatHistoryEditor->appendText(start_line, prepend_newline,
+ LLStyleMap::instance().lookup(chat.mFromID,str_URL));
+ mChatHistoryEditor->blockUndo();
prepend_newline = false;
}
S32 font_size = gSavedSettings.getS32("ChatFontSize");
- std::string font_name = "";
-
- if (0 == font_size)
- font_name = "small";
- else if (2 == font_size)
- font_name = "sansserifbig";
+ const LLFontGL* fontp = NULL;
+ switch(font_size)
+ {
+ case 0:
+ fontp = LLFontGL::getFontSansSerifSmall();
+ break;
+ default:
+ case 1:
+ fontp = LLFontGL::getFontSansSerif();
+ break;
+ case 2:
+ fontp = LLFontGL::getFontSansSerifBig();
+ break;
+ }
- mChatHistoryEditor->appendColoredText(line, false, prepend_newline, color, font_name);
+ mChatHistoryEditor->appendText(line, prepend_newline, LLStyle::Params().color(color).font(fontp));
+ mChatHistoryEditor->blockUndo();
}
void LLNearbyChat::addMessage(const LLChat& chat)
@@ -250,11 +262,6 @@ void LLNearbyChat::addMessage(const LLChat& chat)
}
// could flash the chat button in the status bar here. JC
-
-
- mChatHistoryEditor->setParseHTML(TRUE);
- mChatHistoryEditor->setParseHighlights(TRUE);
-
if (!chat.mMuted)
add_timestamped_line(chat, color);
}
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 5e65f2244d..bd6e6cd0cb 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -500,7 +500,7 @@ BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
-BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen )
+BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
{
if (gDisconnected)
{
@@ -530,7 +530,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rec
args["[REGION]"] = "";
}
- msg = mToolTipMsg;
+ std::string msg = mToolTipMsg;
LLStringUtil::format(msg, args);
LLRect sticky_rect;
@@ -545,7 +545,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rec
sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP;
}
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(msg)
.sticky_rect(sticky_rect));
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 7598154480..821c348835 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -67,7 +67,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen );
+ /*virtual*/ BOOL handleToolTip( S32 x, S32 y, MASK mask);
void setScale( F32 scale );
void setRotateMap( BOOL b ) { mRotateMap = b; }
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 7ccff73080..c543f85f22 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -38,6 +38,7 @@
#include "llavatarconstants.h" // AVATAR_ONLINE
#include "llcallingcard.h"
#include "llcombobox.h"
+#include "lldateutil.h"
#include "llimview.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
@@ -447,7 +448,7 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
- childSetValue("register_date", LLAvatarPropertiesProcessor::ageFromDate(avatar_data->born_on));
+ childSetValue("register_date", LLDateUtil::ageFromDate(avatar_data->born_on));
childSetValue("sl_description_edit", avatar_data->about_text);
childSetValue("fl_description_edit",avatar_data->fl_about_text);
childSetValue("2nd_life_pic", avatar_data->image_id);
diff --git a/indra/newview/llpanelavatartag.cpp b/indra/newview/llpanelavatartag.cpp
index e66c36287b..03ad19f911 100644
--- a/indra/newview/llpanelavatartag.cpp
+++ b/indra/newview/llpanelavatartag.cpp
@@ -64,29 +64,7 @@ BOOL LLPanelAvatarTag::postBuild()
void LLPanelAvatarTag::draw()
{
-
- ///TODO: ANGELA do something similar to fade the panel out
-/* // HACK: assuming tooltip background is in ToolTipBGColor, perform fade out
- LLColor4 bg_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
- if (tooltip_vis)
- {
- mToolTipFadeTimer.stop();
- mToolTip->setBackgroundColor(bg_color);
- }
- else
- {
- if (!mToolTipFadeTimer.getStarted())
- {
- mToolTipFadeTimer.start();
- }
- F32 tool_tip_fade_time = gSavedSettings.getF32("ToolTipFadeTime");
- bg_color.mV[VALPHA] = clamp_rescale(mToolTipFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, bg_color.mV[VALPHA], 0.f);
- mToolTip->setBackgroundColor(bg_color);
- }
-
- // above interpolation of bg_color alpha is guaranteed to reach 0.f exactly
- mToolTip->setVisible( bg_color.mV[VALPHA] != 0.f );
- */
+
}
void LLPanelAvatarTag::setName(const std::string& name)
{
diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h
index 52b74a184b..0993f46f79 100644
--- a/indra/newview/llpanelblockedlist.h
+++ b/indra/newview/llpanelblockedlist.h
@@ -35,6 +35,7 @@
#include "llpanel.h"
#include "llmutelist.h"
+#include "llfloater.h"
// #include <vector>
// class LLButton;
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 2e1d971995..0331fad60c 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -721,15 +721,18 @@ void LLPanelGroupGeneral::updateMembers()
row["id"] = member->getID();
row["columns"][0]["column"] = "name";
+ row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
row["columns"][0]["font"]["style"] = style;
// value is filled in by name list control
row["columns"][1]["column"] = "title";
row["columns"][1]["value"] = member->getTitle();
+ row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
row["columns"][1]["font"]["style"] = style;
row["columns"][2]["column"] = "online";
row["columns"][2]["value"] = member->getOnlineStatus();
+ row["columns"][2]["font"]["name"] = "SANSSERIF_SMALL";
row["columns"][2]["font"]["style"] = style;
sSDTime += sd_timer.getElapsedTimeF32();
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 99bb760b61..1521c1113a 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -634,6 +634,7 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
row["columns"][1]["column"] = "action";
row["columns"][1]["value"] = action_set->mActionSetData->mName;
+ row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
row["columns"][1]["font"]["style"] = "BOLD";
LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index a7f66f3293..24e76e2c6e 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -178,10 +178,10 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
if (LLPanelLogin::sInstance)
{
llwarns << "Duplicate instance of login view deleted" << llendl;
- delete LLPanelLogin::sInstance;
-
// Don't leave bad pointer in gFocusMgr
gFocusMgr.setDefaultKeyboardFocus(NULL);
+
+ delete LLPanelLogin::sInstance;
}
LLPanelLogin::sInstance = this;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index b2a0a01005..c94c38983d 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -621,7 +621,7 @@ void LLPanelPeople::updateButtons()
buttonSetEnabled("chat_btn", item_selected);
}
-const std::string& LLPanelPeople::getActiveTabName() const
+std::string LLPanelPeople::getActiveTabName() const
{
return mTabContainer->getCurrentPanel()->getName();
}
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index de27814388..03802015ce 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -63,7 +63,7 @@ private:
void updateRecentList();
void updateButtons();
- const std::string& getActiveTabName() const;
+ std::string getActiveTabName() const;
LLUUID getCurrentItemID() const;
void buttonSetVisible(std::string btn_name, BOOL visible);
void buttonSetEnabled(const std::string& btn_name, bool enabled);
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 42f9906409..2d3f901370 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -85,9 +85,6 @@ BOOL LLPanelPermissions::postBuild()
childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe);
- childSetAction("button owner profile",LLPanelPermissions::onClickOwner,this);
- childSetAction("button creator profile",LLPanelPermissions::onClickCreator,this);
-
getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickGroup,this));
childSetCommitCallback("checkbox share with group",LLPanelPermissions::onCommitGroupShare,this);
@@ -162,12 +159,10 @@ void LLPanelPermissions::refresh()
childSetEnabled("Creator:",false);
childSetText("Creator Name",LLStringUtil::null);
childSetEnabled("Creator Name",false);
- childSetEnabled("button creator profile",false);
childSetEnabled("Owner:",false);
childSetText("Owner Name",LLStringUtil::null);
childSetEnabled("Owner Name",false);
- childSetEnabled("button owner profile",false);
childSetEnabled("Group:",false);
childSetText("Group Name",LLStringUtil::null);
@@ -275,7 +270,6 @@ void LLPanelPermissions::refresh()
childSetText("Creator Name",creator_name);
childSetEnabled("Creator Name",TRUE);
- childSetEnabled("button creator profile", creators_identical && mCreatorID.notNull() );
// Update owner text field
childSetEnabled("Owner:",true);
@@ -310,7 +304,6 @@ void LLPanelPermissions::refresh()
childSetText("Owner Name",owner_name);
childSetEnabled("Owner Name",TRUE);
- childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
// update group text field
childSetEnabled("Group:",true);
@@ -803,31 +796,6 @@ void LLPanelPermissions::onClickRelease(void*)
LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null);
}
-// static
-void LLPanelPermissions::onClickCreator(void *data)
-{
- LLPanelPermissions *self = (LLPanelPermissions *)data;
-
- LLAvatarActions::showProfile(self->mCreatorID);
-}
-
-// static
-void LLPanelPermissions::onClickOwner(void *data)
-{
- LLPanelPermissions *self = (LLPanelPermissions *)data;
-
- if (LLSelectMgr::getInstance()->selectIsGroupOwned())
- {
- LLUUID group_id;
- LLSelectMgr::getInstance()->selectGetGroup(group_id);
- LLGroupActions::show(group_id);
- }
- else
- {
- LLAvatarActions::showProfile(self->mOwnerID);
- }
-}
-
void LLPanelPermissions::onClickGroup()
{
LLUUID owner_id;
diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h
index 481efe178e..805a4dbe97 100644
--- a/indra/newview/llpanelpermissions.h
+++ b/indra/newview/llpanelpermissions.h
@@ -42,12 +42,6 @@
// Panel for permissions of an object.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLCheckBoxCtrl;
-class LLTextBox;
-class LLButton;
-class LLLineEditor;
-class LLRadioGroup;
-class LLComboBox;
class LLNameBox;
class LLPanelPermissions : public LLPanel
@@ -56,31 +50,24 @@ public:
LLPanelPermissions();
virtual ~LLPanelPermissions();
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
- // MANIPULATORS
void refresh(); // refresh all labels as needed
protected:
// statics
static void onClickClaim(void*);
static void onClickRelease(void*);
- static void onClickCreator(void*);
- static void onClickOwner(void*);
void onClickGroup();
void cbGroupID(LLUUID group_id);
static void onClickDeedToGroup(void*);
static void onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm);
-// static void onCommitGroupMove(LLUICtrl *ctrl, void *data);
-// static void onCommitGroupCopy(LLUICtrl *ctrl, void *data);
-// static void onCommitGroupModify(LLUICtrl *ctrl, void *data);
static void onCommitGroupShare(LLUICtrl *ctrl, void *data);
static void onCommitEveryoneMove(LLUICtrl *ctrl, void *data);
static void onCommitEveryoneCopy(LLUICtrl *ctrl, void *data);
- //static void onCommitEveryoneModify(LLUICtrl *ctrl, void *data);
static void onCommitNextOwnerModify(LLUICtrl* ctrl, void* data);
static void onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data);
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 5df3d4f1d6..424e453a2f 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -356,14 +356,7 @@ std::string LLPanelPick::createLocationText(const std::string& owner_name, const
void LLPanelPick::setPickName(std::string name)
{
- if (mEditMode)
- {
- childSetValue(XML_NAME, name);
- }
- else
- {
- childSetWrappedText(XML_NAME, name);
- }
+ childSetValue(XML_NAME, name);
//preserving non-wrapped text for info/edit modes switching
mName = name;
@@ -371,14 +364,7 @@ void LLPanelPick::setPickName(std::string name)
void LLPanelPick::setPickDesc(std::string desc)
{
- if (mEditMode)
- {
- childSetValue(XML_DESC, desc);
- }
- else
- {
- childSetWrappedText(XML_DESC, desc);
- }
+ childSetValue(XML_DESC, desc);
//preserving non-wrapped text for info/edit modes switching
mDesc = desc;
@@ -386,7 +372,7 @@ void LLPanelPick::setPickDesc(std::string desc)
void LLPanelPick::setPickLocation(const std::string& location)
{
- childSetWrappedText(XML_LOCATION, location);
+ childSetValue(XML_LOCATION, location);
//preserving non-wrapped text for info/edit modes switching
mLocation = location;
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index be28129451..3bd2645be3 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -35,6 +35,7 @@
#include "llagent.h"
#include "llavataractions.h"
+#include "llfloaterreg.h"
#include "llcommandhandler.h"
#include "llpanelpicks.h"
#include "lltabcontainer.h"
@@ -52,15 +53,21 @@ public:
LLMediaCtrl* web)
{
if (params.size() < 2) return false;
- LLUUID agent_id;
- if (!agent_id.set(params[0], FALSE))
+ LLUUID avatar_id;
+ if (!avatar_id.set(params[0], FALSE))
{
return false;
}
if (params[1].asString() == "about")
{
- LLAvatarActions::showProfile(agent_id);
+ LLAvatarActions::showProfile(avatar_id);
+ return true;
+ }
+
+ if (params[1].asString() == "inspect")
+ {
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", avatar_id));
return true;
}
return false;
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 04827e3a78..faca950963 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -421,9 +421,7 @@ BOOL LLPreviewGesture::postBuild()
mStepList = list;
// Options
- text = getChild<LLTextBox>("options_text");
- text->setBorderVisible(TRUE);
- mOptionsText = text;
+ mOptionsText = getChild<LLTextBox>("options_text");
combo = getChild<LLComboBox>( "animation_list");
combo->setVisible(FALSE);
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 29320522d9..ab9cfbf850 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -85,12 +85,8 @@ LLPreviewNotecard::~LLPreviewNotecard()
BOOL LLPreviewNotecard::postBuild()
{
LLViewerTextEditor *ed = getChild<LLViewerTextEditor>("Notecard Editor");
- if (ed)
- {
- ed->setParseHTML(TRUE);
- ed->setNotecardInfo(mItemUUID, mObjectID, getKey());
- ed->makePristine();
- }
+ ed->setNotecardInfo(mItemUUID, mObjectID, getKey());
+ ed->makePristine();
childSetAction("Save", onClickSave, this);
childSetVisible("lock", FALSE);
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 3c6645f116..5f6b210767 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -196,7 +196,7 @@ void LLProgressView::draw()
void LLProgressView::setText(const std::string& text)
{
- getChild<LLTextBox>("progress_text")->setWrappedText(LLStringExplicit(text));
+ getChild<LLUICtrl>("progress_text")->setValue(text);
}
void LLProgressView::setPercent(const F32 percent)
@@ -207,7 +207,7 @@ void LLProgressView::setPercent(const F32 percent)
void LLProgressView::setMessage(const std::string& msg)
{
mMessage = msg;
- getChild<LLTextBox>("message_text")->setWrappedText(LLStringExplicit(mMessage));
+ getChild<LLUICtrl>("message_text")->setValue(mMessage);
}
void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ae8c9f770b..d163ceb30e 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -43,6 +43,7 @@
#include "llrender.h"
#include "llpermissions.h"
#include "llpermissionsflags.h"
+#include "lltrans.h"
#include "llundo.h"
#include "lluuid.h"
#include "llvolume.h"
@@ -66,6 +67,7 @@
#include "llinventorymodel.h"
#include "llmenugl.h"
#include "llmutelist.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "lltool.h"
@@ -805,11 +807,13 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32
// NOTE: there is only ever one linked set in mHoverObjects
if (mHoverObjects->getFirstRootObject() != objectp)
{
+
// Collect all of the objects
std::vector<LLViewerObject*> objects;
objectp = objectp->getRootEdit();
objectp->addThisAndNonJointChildren(objects);
+ mHoverObjects->deleteAllNodes();
for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
iter != objects.end(); ++iter)
{
@@ -818,7 +822,7 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32
nodep->selectTE(face, TRUE);
mHoverObjects->addNodeAtEnd(nodep);
}
-
+
requestObjectPropertiesFamily(objectp);
}
@@ -2389,6 +2393,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
}
if (first_id.isNull())
{
+ name = LLTrans::getString("AvatarNameNobody");
return FALSE;
}
@@ -2396,11 +2401,11 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
if (identical)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2455,20 +2460,21 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull() && !first_group_owned);
if (first_group_owned)
{
- name.assign( "(Group Owned)");
+ // *TODO: We don't have group inspectors yet
+ name = LLSLURL::buildCommand("group", first_id, "about");
}
else if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
- name.assign("Public");
+ name = LLTrans::getString("AvatarNameNobody");
}
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2519,7 +2525,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull());
if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
@@ -5449,15 +5455,17 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
// Utility Functions
//
-// Update everyone who cares about the selection list
+// *DEPRECATED: See header comment.
void dialog_refresh_all()
{
- if (gNoRender)
- {
- return;
- }
+ // This is the easiest place to fire the update signal, as it will
+ // make cleaning up the functions below easier. Also, sometimes entities
+ // outside the selection manager change properties of selected objects
+ // and call into this function. Yuck.
+ LLSelectMgr::getInstance()->mUpdateSignal();
- //could refresh selected object info in toolbar here
+ // *TODO: Eliminate all calls into outside classes below, make those
+ // objects register with the update signal.
gFloaterTools->dirty();
@@ -5853,6 +5861,27 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
gAgent.mHUDCurZoom = current_zoom;
}
+/////////////////////////////////////////////////////////////////////////////
+// Object selection iterator helpers
+/////////////////////////////////////////////////////////////////////////////
+bool LLObjectSelection::is_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && (object->isRootEdit() || object->isJointChild());
+}
+
LLObjectSelection::LLObjectSelection() :
LLRefCount(),
mSelectType(SELECT_TYPE_WORLD)
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 9e02170d74..26ac95060f 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -35,7 +35,6 @@
#include "llcharacter.h"
#include "lleditmenuhandler.h"
-#include "llstring.h"
#include "llundo.h"
#include "lluuid.h"
#include "llpointer.h"
@@ -48,14 +47,15 @@
#include "llframetimer.h"
#include "llbbox.h"
#include "llpermissions.h"
-#include "llviewerobject.h"
#include "llcontrol.h"
+#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template
+
#include <deque>
-#include "boost/iterator/filter_iterator.hpp"
+#include <boost/iterator/filter_iterator.hpp>
+#include <boost/signals2.hpp>
class LLMessageSystem;
class LLViewerTexture;
-class LLViewerObject;
class LLColor4;
class LLVector3;
class LLSelectNode;
@@ -203,13 +203,9 @@ class LLObjectSelection : public LLRefCount
protected:
~LLObjectSelection();
- // List
public:
typedef std::list<LLSelectNode*> list_t;
-private:
- list_t mList;
-public:
// Iterators
struct is_non_null
{
@@ -235,11 +231,7 @@ public:
struct is_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root, list_t::iterator > root_iterator;
root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); }
@@ -247,11 +239,7 @@ public:
struct is_valid_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root, list_t::iterator > valid_root_iterator;
valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); }
@@ -259,11 +247,7 @@ public:
struct is_root_object
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root_object, list_t::iterator > root_object_iterator;
root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); }
@@ -326,6 +310,7 @@ public:
ESelectType getSelectType() const { return mSelectType; }
private:
+ list_t mList;
const LLObjectSelection &operator=(const LLObjectSelection &);
LLPointer<LLViewerObject> mPrimaryObject;
@@ -398,13 +383,16 @@ public:
// Add
////////////////////////////////////////////////////////////////
- // For when you want just a child object.
- LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
-
// This method is meant to select an object, and then select all
- // of the ancestors and descendents. This should be the normal behavior.
+ // of the ancestors and descendants. This should be the normal behavior.
+ //
+ // *NOTE: You must hold on to the object selection handle, otherwise
+ // the objects will be automatically deselected in 1 frame.
LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
+ // For when you want just a child object.
+ LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
+
// Same as above, but takes a list of objects. Used by rectangle select.
LLObjectSelectionHandle selectObjectAndFamily(const std::vector<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE);
@@ -691,7 +679,13 @@ private:
static void packPermissionsHead(void* user_data);
static void packGodlikeHead(void* user_data);
static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle);
-
+
+public:
+ // Observer/callback support for when object selection changes or
+ // properties are received/updated
+ typedef boost::signals2::signal< void ()> update_signal_t;
+ update_signal_t mUpdateSignal;
+
private:
LLPointer<LLViewerTexture> mSilhouetteImagep;
LLObjectSelectionHandle mSelectedObjects;
@@ -723,8 +717,10 @@ private:
LLAnimPauseRequest mPauseRequest;
};
-// Utilities
-void dialog_refresh_all(); // Update subscribers to the selection list
+// *DEPRECATED: For callbacks or observers, use
+// LLSelectMgr::getInstance()->mUpdateSignal.connect( callback )
+// Update subscribers to the selection list
+void dialog_refresh_all();
// Templates
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp
index 836fe9729d..37e268ad34 100644
--- a/indra/newview/llslurl.cpp
+++ b/indra/newview/llslurl.cpp
@@ -106,6 +106,14 @@ std::string LLSLURL::buildSLURL(const std::string& regionname, S32 x, S32 y, S32
}
// static
+std::string LLSLURL::buildCommand(const char* noun, const LLUUID& id, const char* verb)
+{
+ std::string slurl = llformat("secondlife:///app/%s/%s/%s",
+ noun, id.asString().c_str(), verb);
+ return slurl;
+}
+
+// static
std::string LLSLURL::buildUnescapedSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
{
std::string unescapedslurl = PREFIX_SLURL + regionname + llformat("/%d/%d/%d",x,y,z);
diff --git a/indra/newview/llslurl.h b/indra/newview/llslurl.h
index 8af2bdfb83..05b0143e72 100644
--- a/indra/newview/llslurl.h
+++ b/indra/newview/llslurl.h
@@ -73,6 +73,9 @@ public:
*/
static std::string buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
+ /// Build a SLURL like secondlife:///app/agent/<uuid>/inspect
+ static std::string buildCommand(const char* noun, const LLUUID& id, const char* verb);
+
/**
* builds: http://slurl.com/secondlife/Region Name/x/y/z/ without escaping result url.
*/
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 053b863b6d..62435c6288 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -195,6 +195,10 @@
#include "lldxhardware.h"
#endif
+#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#include <glib/gspawn.h>
+#endif
+
//
// exported globals
//
@@ -1824,9 +1828,9 @@ bool idle_startup()
{
gCacheName = new LLCacheName(gMessageSystem);
gCacheName->addObserver(&callback_cache_name);
- gCacheName->LocalizeCacheName("waiting", LLTrans::getString("CacheWaiting"));
- gCacheName->LocalizeCacheName("nobody", LLTrans::getString("CacheNobody"));
- gCacheName->LocalizeCacheName("none", LLTrans::getString("CacheNone"));
+ gCacheName->LocalizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
+ gCacheName->LocalizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
+ gCacheName->LocalizeCacheName("none", LLTrans::getString("GroupNameNone"));
// Load stored cache if possible
LLAppViewer::instance()->loadNameCache();
}
diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp
index fc125dcf9c..2485563cbc 100644
--- a/indra/newview/llstylemap.cpp
+++ b/indra/newview/llstylemap.cpp
@@ -33,8 +33,10 @@
#include "llviewerprecompiledheaders.h"
#include "llstylemap.h"
+
#include "llstring.h"
#include "llui.h"
+#include "llslurl.h"
#include "llviewercontrol.h"
#include "llagent.h"
@@ -47,7 +49,8 @@ const LLStyle::Params &LLStyleMap::lookupAgent(const LLUUID &source)
if (source != LLUUID::null && source != gAgent.getID() )
{
style_params.color.control = "HTMLLinkColor";
- style_params.link_href = llformat("secondlife:///app/agent/%s/about",source.asString().c_str());
+ style_params.link_href =
+ LLSLURL::buildCommand("agent", source, "inspect");
}
else
{
@@ -55,7 +58,7 @@ const LLStyle::Params &LLStyleMap::lookupAgent(const LLUUID &source)
style_params.color = LLColor4::white;
}
- mMap[source] = LLStyle::Params();
+ mMap[source] = style_params;
}
return mMap[source];
}
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 1b47fa43c7..9fc91e2971 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -882,7 +882,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
LLTextBox::Params params(p.caption_text);
params.name(p.label);
params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
- params.text(p.label);
+ params.initial_value(p.label());
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
mCaption = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mCaption );
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 4309f56710..d9be6b172c 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -168,6 +168,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
params.name("Alert message");
params.font(font);
params.tab_stop(false);
+ params.wrap(true);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);
@@ -178,7 +179,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
- LINE_HEIGHT // title bar
- 3*VPAD - BTN_HEIGHT;
msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );
- msg_box->setWrappedText(msg, (F32)MAX_ALLOWED_MSG_WIDTH);
+ msg_box->setValue(msg);
msg_box->reshapeToFitText();
const LLRect& text_rect = msg_box->getRect();
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 9761a45d83..86b162247a 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -144,10 +144,11 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas
params.mouse_opaque(false);
params.font.style("BOLD");
params.text_color(LLUIColorTable::instance().getColor("NotifyCautionWarnColor"));
- params.background_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ params.bg_readonly_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
params.border_visible(false);
+ params.wrap(true);
caution_box = LLUICtrlFactory::create<LLTextBox> (params);
- caution_box->setWrappedText(notification->getMessage());
+ caution_box->setValue(notification->getMessage());
addChild(caution_box);
@@ -175,13 +176,13 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas
params.default_text(mMessage);
params.font(sFont);
params.embedded_items(false);
- params.word_wrap(true);
+ params.wrap(true);
params.tab_stop(false);
params.mouse_opaque(false);
params.bg_readonly_color(LLColor4::transparent);
params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor"));
params.enabled(false);
- params.hide_border(true);
+ params.border_visible(false);
text = LLUICtrlFactory::create<LLTextEditor> (params);
addChild(text);
}
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index e884d89ce4..68ad043129 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -56,7 +56,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
if (message->getVisible())
{
S32 heightDelta = 0;
- S32 maxTextHeight = (S32)(message->getFont()->getLineHeight() * maxLineCount);
+ S32 maxTextHeight = (S32)(message->getDefaultFont()->getLineHeight() * maxLineCount);
LLRect messageRect = message->getRect();
S32 oldTextHeight = messageRect.getHeight();
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 880d5d5e12..669a62a238 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -155,7 +155,7 @@ BOOL LLTool::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLTool::handleToolTip(S32 x, S32 y, MASK mask)
{
// by default, didn't handle it
// llinfos << "LLTool::handleToolTip" << llendl;
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index bef4a2e1fd..c3573cd38c 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -66,7 +66,7 @@ public:
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// Return FALSE to allow context menu to be shown.
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const
@@ -74,7 +74,7 @@ public:
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const
{ *screen_x = local_x; *screen_y = local_y; }
- virtual const std::string& getName() const { return mName; }
+ virtual std::string getName() const { return mName; }
// New virtual functions
virtual LLViewerObject* getEditingObject() { return NULL; }
diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
index c7c9f07504..0572f9a698 100644
--- a/indra/newview/lltoolbar.cpp
+++ b/indra/newview/lltoolbar.cpp
@@ -271,6 +271,7 @@ void LLToolBar::updateCommunicateList()
contact_sd["columns"][0]["value"] = LLFloaterMyFriends::getInstance()->getShortTitle();
if (LLFloaterMyFriends::getInstance() == frontmost_floater)
{
+ contact_sd["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
contact_sd["columns"][0]["font"]["style"] = "BOLD";
// make sure current tab is selected in list
if (selected.isUndefined())
@@ -286,6 +287,7 @@ void LLToolBar::updateCommunicateList()
if (LLFloaterChat::getInstance() == frontmost_floater)
{
+ communicate_sd["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
communicate_sd["columns"][0]["font"]["style"] = "BOLD";
if (selected.isUndefined())
{
@@ -318,6 +320,7 @@ void LLToolBar::updateCommunicateList()
im_sd["columns"][0]["value"] = floater_title;
if (im_floaterp == frontmost_floater)
{
+ im_sd["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
im_sd["columns"][0]["font"]["style"] = "BOLD";
if (selected.isUndefined())
{
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index c3064ffa43..bc0a654eb9 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -762,11 +762,11 @@ BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
return FALSE;
}
-BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
{
if (!mToolTipMsg.empty())
{
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(mToolTipMsg)
.delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
return TRUE;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index acf01869e7..e1536acf75 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -59,7 +59,7 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleKey(KEY key, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual void onMouseCaptureLost();
virtual void handleDeselect();
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index d5db224143..5525c359fc 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -70,9 +70,6 @@
#include "llworld.h"
#include "llui.h"
#include "llweb.h"
-#include "llinspectavatar.h"
-
-extern void handle_buy(void*);
extern BOOL gDebugClicks;
@@ -212,7 +209,7 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
case CLICK_ACTION_SIT:
if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // agent not already sitting
{
- handle_sit_or_stand();
+ handle_object_sit_or_stand();
// put focus in world when sitting on an object
gFocusMgr.setKeyboardFocus(NULL);
return TRUE;
@@ -456,7 +453,7 @@ void LLToolPie::selectionPropertiesReceived()
switch (click_action)
{
case CLICK_ACTION_BUY:
- handle_buy(NULL);
+ handle_buy();
break;
case CLICK_ACTION_PAY:
handle_give_money_dialog();
@@ -586,10 +583,39 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
return FALSE;
}
-//FIXME - RN: get this in LLToolSelectLand too or share some other way?
-const char* DEFAULT_DESC = "(No Description)";
+static bool needs_tooltip(LLSelectNode* nodep)
+{
+ LLViewerObject* object = nodep->getObject();
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+ if (object->flagHandleTouch()
+ || (parent && parent->flagHandleTouch())
+ || object->flagTakesMoney()
+ || (parent && parent->flagTakesMoney())
+ || object->flagAllowInventoryAdd()
+ )
+ {
+ return true;
+ }
+
+ U8 click_action = final_click_action(object);
+ if (click_action != 0)
+ {
+ return true;
+ }
+
+ if (nodep->mValid)
+ {
+ bool anyone_copy = anyone_copy_selection(nodep);
+ bool for_sale = for_sale_selection(nodep);
+ if (anyone_copy || for_sale)
+ {
+ return true;
+ }
+ }
+ return false;
+}
-BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect& sticky_rect_screen)
+BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
{
if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
if (!mHoverPick.isValid()) return TRUE;
@@ -636,8 +662,11 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect
line.clear();
if (hover_object->isAvatar())
{
- // only show tooltip if inspector not already open
- if (!LLFloaterReg::instanceVisible("inspect_avatar"))
+ // only show tooltip if same inspector not already open
+ LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
+ if (!existing_inspector
+ || !existing_inspector->getVisible()
+ || existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
{
std::string avatar_name;
LLNameValue* firstname = hover_object->getNVPair("FirstName");
@@ -650,12 +679,15 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect
{
avatar_name = LLTrans::getString("TooltipPerson");
}
- LLToolTipParams params;
- params.message(avatar_name);
- params.image.name("Info");
- params.sticky_rect(gViewerWindow->getVirtualWorldViewRect());
- params.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
- LLToolTipMgr::instance().show(params);
+
+ // *HACK: We may select this object, so pretend it was clicked
+ mPick = mHoverPick;
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(avatar_name)
+ .image(LLUI::getUIImage("Info"))
+ .click_callback(boost::bind(showAvatarInspector, hover_object->getID()))
+ .visible_time_near(6.f)
+ .visible_time_far(3.f));
}
}
else
@@ -667,177 +699,38 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect
//
// Default prefs will suppress display unless the object is interactive
//
- BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip");
-
+ bool show_all_object_tips =
+ (bool)gSavedSettings.getBOOL("ShowAllObjectHoverTip");
LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
- if (nodep)
+
+ // only show tooltip if same inspector not already open
+ LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_object");
+ if (nodep &&
+ (!existing_inspector
+ || !existing_inspector->getVisible()
+ || existing_inspector->getKey()["object_id"].asUUID() != hover_object->getID()))
{
- line.clear();
if (nodep->mName.empty())
{
- line.append(LLTrans::getString("TooltipNoName"));
- }
- else
- {
- line.append( nodep->mName );
- }
- tooltip_msg.append(line);
- tooltip_msg.push_back('\n');
-
- if (!nodep->mDescription.empty()
- && nodep->mDescription != DEFAULT_DESC)
- {
- tooltip_msg.append( nodep->mDescription );
- tooltip_msg.push_back('\n');
- }
-
- // Line: "Owner: James Linden"
- line.clear();
- line.append(LLTrans::getString("TooltipOwner") + " ");
-
- if (nodep->mValid)
- {
- LLUUID owner;
- std::string name;
- if (!nodep->mPermissions->isGroupOwned())
- {
- owner = nodep->mPermissions->getOwner();
- if (LLUUID::null == owner)
- {
- line.append(LLTrans::getString("TooltipPublic"));
- }
- else if(gCacheName->getFullName(owner, name))
- {
- line.append(name);
- }
- else
- {
- line.append(LLTrans::getString("RetrievingData"));
- }
- }
- else
- {
- std::string name;
- owner = nodep->mPermissions->getGroup();
- if (gCacheName->getGroupName(owner, name))
- {
- line.append(name);
- line.append(LLTrans::getString("TooltipIsGroup"));
- }
- else
- {
- line.append(LLTrans::getString("RetrievingData"));
- }
- }
+ tooltip_msg.append(LLTrans::getString("TooltipNoName"));
}
else
{
- line.append(LLTrans::getString("RetrievingData"));
+ tooltip_msg.append( nodep->mName );
}
- tooltip_msg.append(line);
- tooltip_msg.push_back('\n');
- // Build a line describing any special properties of this object.
- LLViewerObject *object = hover_object;
- LLViewerObject *parent = (LLViewerObject *)object->getParent();
-
- if (object &&
- (object->usePhysics() ||
- object->flagScripted() ||
- object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ||
- object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ||
- object->flagAllowInventoryAdd() ||
- object->flagTemporary() ||
- object->flagPhantom()) )
- {
- line.clear();
- if (object->flagScripted())
- {
- line.append(LLTrans::getString("TooltipFlagScript") + " ");
- }
-
- if (object->usePhysics())
- {
- line.append(LLTrans::getString("TooltipFlagPhysics") + " ");
- }
-
- if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) )
- {
- line.append(LLTrans::getString("TooltipFlagTouch") + " ");
- suppressObjectHoverDisplay = FALSE; // Show tip
- }
-
- if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) )
- {
- line.append(LLTrans::getString("TooltipFlagL$") + " ");
- suppressObjectHoverDisplay = FALSE; // Show tip
- }
-
- if (object->flagAllowInventoryAdd())
- {
- line.append(LLTrans::getString("TooltipFlagDropInventory") + " ");
- suppressObjectHoverDisplay = FALSE; // Show tip
- }
-
- if (object->flagPhantom())
- {
- line.append(LLTrans::getString("TooltipFlagPhantom") + " ");
- }
-
- if (object->flagTemporary())
- {
- line.append(LLTrans::getString("TooltipFlagTemporary") + " ");
- }
-
- if (object->usePhysics() ||
- object->flagHandleTouch() ||
- (parent && parent->flagHandleTouch()) )
- {
- line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " ");
- }
- tooltip_msg.append(line);
- tooltip_msg.push_back('\n');
- }
-
- // Free to copy / For Sale: L$
- line.clear();
- if (nodep->mValid)
- {
- BOOL for_copy = nodep->mPermissions->getMaskEveryone() & PERM_COPY && object->permCopy();
- BOOL for_sale = nodep->mSaleInfo.isForSale() &&
- nodep->mPermissions->getMaskOwner() & PERM_TRANSFER &&
- (nodep->mPermissions->getMaskOwner() & PERM_COPY ||
- nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
- if (for_copy)
- {
- line.append(LLTrans::getString("TooltipFreeToCopy"));
- suppressObjectHoverDisplay = FALSE; // Show tip
- }
- else if (for_sale)
- {
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice());
- line.append(LLTrans::getString("TooltipForSaleL$", args));
- suppressObjectHoverDisplay = FALSE; // Show tip
- }
- else
- {
- // Nothing if not for sale
- // line.append("Not for sale");
- }
- }
- else
- {
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = LLTrans::getString("RetrievingData");
- line.append(LLTrans::getString("TooltipForSaleMsg", args));
- }
- tooltip_msg.append(line);
- tooltip_msg.push_back('\n');
+ bool needs_tip = needs_tooltip(nodep);
- if (!suppressObjectHoverDisplay)
+ if (show_all_object_tips || needs_tip)
{
- LLToolTipMgr::instance().show(tooltip_msg);
+ // We may select this object, so pretend it was clicked
+ mPick = mHoverPick;
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(tooltip_msg)
+ .image(LLUI::getUIImage("Info"))
+ .click_callback(boost::bind(showObjectInspector, hover_object->getID()))
+ .visible_time_near(6.f)
+ .visible_time_far(3.f));
}
}
}
@@ -990,18 +883,23 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
}
- LLToolTipMgr::instance().show(tooltip_msg);
+
+ // trim last newlines
+ if (!tooltip_msg.empty())
+ {
+ tooltip_msg.erase(tooltip_msg.size() - 1);
+ LLToolTipMgr::instance().show(tooltip_msg);
+ }
}
return TRUE;
}
-// static
-void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
+static void show_inspector(const char* inspector, const char* param, const LLUUID& source_id)
{
LLSD params;
- params["avatar_id"] = avatar_id;
+ params[param] = source_id;
if (LLToolTipMgr::instance().toolTipVisible())
{
LLRect rect = LLToolTipMgr::instance().getToolTipRect();
@@ -1009,7 +907,19 @@ void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
params["pos"]["y"] = rect.mTop;
}
- LLFloaterReg::showInstance("inspect_avatar", params);
+ LLFloaterReg::showInstance(inspector, params);
+}
+
+// static
+void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
+{
+ show_inspector("inspect_avatar", "avatar_id", avatar_id);
+}
+
+// static
+void LLToolPie::showObjectInspector(const LLUUID& object_id)
+{
+ show_inspector("inspect_object", "object_id", object_id);
}
void LLToolPie::handleDeselect()
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index f6a67c13b1..5faedbec5a 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -55,7 +55,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual void render();
@@ -76,7 +76,8 @@ public:
static void selectionPropertiesReceived();
- static void showAvatarInspector(const LLUUID& id);
+ static void showAvatarInspector(const LLUUID& avatar_id);
+ static void showObjectInspector(const LLUUID& object_id);
private:
BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y);
BOOL pickLeftMouseDownCallback();
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 9a92f2ae3f..beebb47537 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -93,7 +93,7 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect &sticky_rect_screen)
+BOOL LLToolPipette::handleToolTip(S32 x, S32 y, MASK mask)
{
if (mTooltipMsg.empty())
{
@@ -102,7 +102,7 @@ BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect &sticky
LLRect sticky_rect;
sticky_rect.setCenterAndSize(x, y, 20, 20);
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(mTooltipMsg)
.sticky_rect(sticky_rect));
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index cce5b6ce54..f86939cfeb 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -56,7 +56,7 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp
index 153e3e7382..577b5952e5 100644
--- a/indra/newview/lluploaddialog.cpp
+++ b/indra/newview/lluploaddialog.cpp
@@ -82,7 +82,7 @@ LLUploadDialog::LLUploadDialog( const std::string& msg)
LLTextBox::Params params;
params.name("Filename");
params.rect(msg_rect);
- params.text("Filename");
+ params.initial_value("Filename");
params.font(font);
mLabelBox[line_num] = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox[line_num]);
diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp
index 842ffc7f9a..41eafa871d 100644
--- a/indra/newview/llviewchildren.cpp
+++ b/indra/newview/llviewchildren.cpp
@@ -74,17 +74,6 @@ void LLViewChildren::setText(
}
}
-void LLViewChildren::setWrappedText(
- const std::string& id, const std::string& text, bool visible)
-{
- LLTextBox* child = mParent.getChild<LLTextBox>(id);
- if (child)
- {
- child->setVisible(visible);
- child->setWrappedText(text);
- }
-}
-
void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible)
{
LLIconCtrl* child = mParent.getChild<LLIconCtrl>(id);
diff --git a/indra/newview/llviewchildren.h b/indra/newview/llviewchildren.h
index 9263d77bdc..6cfa535a94 100644
--- a/indra/newview/llviewchildren.h
+++ b/indra/newview/llviewchildren.h
@@ -53,8 +53,6 @@ public:
// LLTextBox
void setText(const std::string& id,
const std::string& text, bool visible = true);
- void setWrappedText(const std::string& id,
- const std::string& text, bool visible = true);
// LLIconCtrl
enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 2f656479f6..0b21f3565d 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -110,6 +110,7 @@
#include "llfloaterwindlight.h"
#include "llfloaterworldmap.h"
#include "llinspectavatar.h"
+#include "llinspectobject.h"
#include "llmediaremotectrl.h"
#include "llmoveview.h"
#include "llnearbychat.h"
@@ -172,8 +173,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);
LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>);
LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
- LLFloaterReg::add("inspect_avatar", "inspect_avatar.xml",
- &LLFloaterReg::build<LLInspectAvatar>);
+ LLInspectAvatarUtil::registerFloater();
+ LLInspectObjectUtil::registerFloater();
LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index 9f7e4d338b..b919e3d1c1 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -282,7 +282,7 @@ void LLViewerJoystick::terminate()
ndof_libcleanup();
llinfos << "Terminated connection with NDOF device." << llendl;
-
+ mDriverState = JDS_UNINITIALIZED;
#endif
}
diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h
index 6be9db3313..b565ed5696 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -56,6 +56,8 @@ public:
virtual ~LLViewerJoystick();
void init(bool autoenable);
+ void terminate();
+
void updateStatus();
void scanJoystick();
void moveObjects(bool reset = false);
@@ -76,7 +78,6 @@ public:
protected:
void updateEnabled(bool autoenable);
- void terminate();
void handleRun(F32 inc);
void agentSlide(F32 inc);
void agentPush(F32 inc);
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 775f72d56f..c9ba5841e9 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -193,12 +193,11 @@ public:
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { return FALSE; };
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; };
- /*virtual*/ const std::string& getName() const { return LLStringUtil::null; };
+ /*virtual*/ std::string getName() const { return LLStringUtil::null; };
- /*virtual*/ BOOL isView() const { return FALSE; };
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {};
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {};
/*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; };
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 12253455a3..d95992412f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -80,6 +80,7 @@
#include "lldrawpoolalpha.h"
#include "lldrawpooltree.h"
#include "llface.h"
+#include "llfilepicker.h"
#include "llfirstuse.h"
#include "llfirsttimetipmanager.h"
#include "llfloater.h"
@@ -295,8 +296,7 @@ S32 selection_price();
BOOL enable_take();
void handle_take();
bool confirm_take(const LLSD& notification, const LLSD& response);
-BOOL enable_buy(void*);
-void handle_buy(void *);
+
void handle_buy_object(LLSaleInfo sale_info);
void handle_buy_contents(LLSaleInfo sale_info);
@@ -2490,12 +2490,10 @@ class LLObjectEnableReportAbuse : public view_listener_t
}
};
-class LLObjectTouch : public view_listener_t
+void handle_object_touch()
{
- bool handleEvent(const LLSD& userdata)
- {
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return true;
+ if (!object) return;
LLPickInfo pick = LLToolPie::getInstance()->getPick();
@@ -2534,19 +2532,20 @@ class LLObjectTouch : public view_listener_t
msg->addVector3("Normal", pick.mNormal);
msg->addVector3("Binormal", pick.mBinormal);
msg->sendMessage(object->getRegion()->getHost());
+}
- return true;
- }
-};
-
+bool enable_object_touch()
+{
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ return obj && obj->flagHandleTouch();
+}
// One object must have touch sensor
class LLObjectEnableTouch : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = obj && obj->flagHandleTouch();
+ bool new_value = enable_object_touch();
// Update label based on the node touch name if available.
std::string touch_text;
@@ -2596,23 +2595,18 @@ class LLObjectOpen : public view_listener_t
}
};
*/
-class LLObjectEnableOpen : public view_listener_t
+bool enable_object_open()
{
- bool handleEvent(const LLSD& userdata)
- {
- // Look for contents in root object, which is all the LLFloaterOpenObject
- // understands.
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = (obj != NULL);
- if (new_value)
- {
- LLViewerObject* root = obj->getRootEdit();
- if (!root) new_value = false;
- else new_value = root->allowOpen();
- }
- return new_value;
- }
-};
+ // Look for contents in root object, which is all the LLFloaterOpenObject
+ // understands.
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!obj) return false;
+
+ LLViewerObject* root = obj->getRootEdit();
+ if (!root) return false;
+
+ return root->allowOpen();
+}
class LLViewJoystickFlycam : public view_listener_t
@@ -2666,52 +2660,50 @@ class LLObjectBuild : public view_listener_t
}
};
-class LLObjectEdit : public view_listener_t
+
+void handle_object_edit()
{
- bool handleEvent(const LLSD& userdata)
+ LLViewerParcelMgr::getInstance()->deselectLand();
+
+ if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
{
- LLViewerParcelMgr::getInstance()->deselectLand();
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
+ if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
{
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
- if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
- {
- // always freeze camera in space, even if camera doesn't move
- // so, for example, follow cam scripts can't affect you when in build mode
- gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- }
- else
+ // always freeze camera in space, even if camera doesn't move
+ // so, for example, follow cam scripts can't affect you when in build mode
+ gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ }
+ else
+ {
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ LLViewerObject* selected_objectp = selection->getFirstRootObject();
+ if (selected_objectp)
{
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- LLViewerObject* selected_objectp = selection->getFirstRootObject();
- if (selected_objectp)
- {
- // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
- gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
- gAgent.cameraZoomIn(0.666f);
- gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
- gViewerWindow->moveCursorToCenter();
+ // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
+ gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+ gAgent.cameraZoomIn(0.666f);
+ gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
+ gViewerWindow->moveCursorToCenter();
}
}
- }
-
- LLFloaterReg::showInstance("build");
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
-
- LLViewerJoystick::getInstance()->moveObjects(true);
- LLViewerJoystick::getInstance()->setNeedsReset(true);
-
- // Could be first use
- LLFirstUse::useBuild();
- return true;
}
-};
-
+
+ LLFloaterReg::showInstance("build");
+
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
+
+ LLViewerJoystick::getInstance()->moveObjects(true);
+ LLViewerJoystick::getInstance()->setNeedsReset(true);
+
+ // Could be first use
+ LLFirstUse::useBuild();
+ return;
+
+}
//---------------------------------------------------------------------------
// Land pie menu
//---------------------------------------------------------------------------
@@ -2795,24 +2787,21 @@ BOOL enable_object_build(void*)
return can_build;
}
-class LLEnableEdit : public view_listener_t
+bool enable_object_edit()
{
- bool handleEvent(const LLSD& userdata)
+ // *HACK: The new "prelude" Help Islands have a build sandbox area,
+ // so users need the Edit and Create pie menu options when they are
+ // there. Eventually this needs to be replaced with code that only
+ // lets you edit objects if you have permission to do so (edit perms,
+ // group edit, god). See also lltoolbar.cpp. JC
+ bool enable = true;
+ if (gAgent.inPrelude())
{
- // *HACK: The new "prelude" Help Islands have a build sandbox area,
- // so users need the Edit and Create pie menu options when they are
- // there. Eventually this needs to be replaced with code that only
- // lets you edit objects if you have permission to do so (edit perms,
- // group edit, god). See also lltoolbar.cpp. JC
- bool enable = true;
- if (gAgent.inPrelude())
- {
- enable = LLViewerParcelMgr::getInstance()->agentCanBuild()
- || LLSelectMgr::getInstance()->getSelection()->isAttachment();
- }
- return enable;
+ enable = LLViewerParcelMgr::getInstance()->agentCanBuild()
+ || LLSelectMgr::getInstance()->getSelection()->isAttachment();
}
-};
+ return enable;
+}
class LLSelfRemoveAllAttachments : public view_listener_t
{
@@ -2866,27 +2855,24 @@ BOOL enable_has_attachments(void*)
// }
//}
-class LLObjectEnableMute : public view_listener_t
+bool enable_object_mute()
{
- bool handleEvent(const LLSD& userdata)
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ bool new_value = (object != NULL);
+ if (new_value)
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = (object != NULL);
- if (new_value)
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (avatar)
{
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (avatar)
- {
- // It's an avatar
- LLNameValue *lastname = avatar->getNVPair("LastName");
- BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
- BOOL is_self = avatar->isSelf();
- new_value = !is_linden && !is_self;
- }
+ // It's an avatar
+ LLNameValue *lastname = avatar->getNVPair("LastName");
+ BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+ BOOL is_self = avatar->isSelf();
+ new_value = !is_linden && !is_self;
}
- return new_value;
}
-};
+ return new_value;
+}
class LLObjectMute : public view_listener_t
{
@@ -3345,36 +3331,29 @@ void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm
string.append(buffer);
}
-BOOL enable_buy(void*)
+bool enable_buy_object()
{
// In order to buy, there must only be 1 purchaseable object in
// the selection manger.
- if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return FALSE;
+ if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
LLViewerObject* obj = NULL;
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if(node)
{
obj = node->getObject();
- if(!obj) return FALSE;
+ if(!obj) return false;
- if(node->mSaleInfo.isForSale() && node->mPermissions->getMaskOwner() & PERM_TRANSFER &&
- (node->mPermissions->getMaskOwner() & PERM_COPY || node->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY))
+ if( for_sale_selection(node) )
{
- if(obj->permAnyOwner()) return TRUE;
+ // *NOTE: Is this needed? This checks to see if anyone owns the
+ // object, dating back to when we had "public" objects owned by
+ // no one. JC
+ if(obj->permAnyOwner()) return true;
}
}
- return FALSE;
+ return false;
}
-class LLObjectEnableBuy : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = enable_buy(NULL);
- return new_value;
- }
-};
-
// Note: This will only work if the selected object's data has been
// received by the viewer and cached in the selection manager.
void handle_buy_object(LLSaleInfo sale_info)
@@ -3717,20 +3696,35 @@ class LLEditEnableCustomizeAvatar : public view_listener_t
}
};
+bool enable_sit_object()
+{
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
// only works on pie menu
-bool handle_sit_or_stand()
+void handle_object_sit_or_stand()
{
LLPickInfo pick = LLToolPie::getInstance()->getPick();
LLViewerObject *object = pick.getObject();;
if (!object || pick.mPickType == LLPickInfo::PICK_FLORA)
{
- return true;
+ return;
}
if (sitting_on_selection())
{
gAgent.standUp();
- return true;
+ return;
}
// get object selection offset
@@ -3748,17 +3742,8 @@ bool handle_sit_or_stand()
object->getRegion()->sendReliableMessage();
}
- return true;
}
-class LLObjectSitOrStand : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- return handle_sit_or_stand();
- }
-};
-
void near_sit_down_point(BOOL success, void *)
{
if (success)
@@ -4228,18 +4213,14 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
}
}
-class LLToolsTakeCopy : public view_listener_t
+void handle_take_copy()
{
- bool handleEvent(const LLSD& userdata)
- {
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
-
- const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
- derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- return true;
- }
-};
+ LLUUID category_id =
+ gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
+ derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+}
// You can return an object to its owner if it is on your land.
@@ -4485,43 +4466,50 @@ BOOL enable_take()
return FALSE;
}
-class LLToolsBuyOrTake : public view_listener_t
+
+void handle_buy_or_take()
{
- bool handleEvent(const LLSD& userdata)
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- return true;
- }
+ return;
+ }
- if (is_selection_buy_not_take())
- {
- S32 total_price = selection_price();
+ if (is_selection_buy_not_take())
+ {
+ S32 total_price = selection_price();
- if (total_price <= gStatusBar->getBalance() || total_price == 0)
- {
- handle_buy(NULL);
- }
- else
- {
- LLFloaterBuyCurrency::buyCurrency(
- "Buying this costs", total_price);
- }
+ if (total_price <= gStatusBar->getBalance() || total_price == 0)
+ {
+ handle_buy();
}
else
{
- handle_take();
+ LLFloaterBuyCurrency::buyCurrency(
+ "Buying this costs", total_price);
}
- return true;
}
-};
+ else
+ {
+ handle_take();
+ }
+}
+
+bool visible_buy_object()
+{
+ return is_selection_buy_not_take() && enable_buy_object();
+}
+
+bool visible_take_object()
+{
+ return !is_selection_buy_not_take() && enable_take();
+}
class LLToolsEnableBuyOrTake : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
bool is_buy = is_selection_buy_not_take();
- bool new_value = is_buy ? enable_buy(NULL) : enable_take();
+ bool new_value = is_buy ? enable_buy_object() : enable_take();
// Update label
std::string label;
@@ -4632,7 +4620,7 @@ void show_buy_currency(const char* extra)
LLNotifications::instance().add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
}
-void handle_buy(void*)
+void handle_buy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
@@ -4650,14 +4638,20 @@ void handle_buy(void*)
}
}
-class LLObjectBuy : public view_listener_t
+bool anyone_copy_selection(LLSelectNode* nodep)
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_buy(NULL);
- return true;
- }
-};
+ bool perm_copy = (bool)(nodep->getObject()->permCopy());
+ bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
+ return perm_copy && all_copy;
+}
+
+bool for_sale_selection(LLSelectNode* nodep)
+{
+ return nodep->mSaleInfo.isForSale()
+ && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
+ && (nodep->mPermissions->getMaskOwner() & PERM_COPY
+ || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
+}
BOOL sitting_on_selection()
{
@@ -4985,28 +4979,24 @@ class LLEditDelete : public view_listener_t
}
};
-class LLObjectEnableDelete : public view_listener_t
+bool enable_object_delete()
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value =
+ bool new_value =
#ifdef HACKED_GODLIKE_VIEWER
- TRUE;
+ TRUE;
#else
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- (!LLViewerLogin::getInstance()->isInProductionGrid()
- && gAgent.isGodlike()) ||
+ (!LLViewerLogin::getInstance()->isInProductionGrid()
+ && gAgent.isGodlike()) ||
# endif
- LLSelectMgr::getInstance()->canDoDelete();
+ LLSelectMgr::getInstance()->canDoDelete();
#endif
- return new_value;
- }
-};
+ return new_value;
+}
-class LLObjectDelete : public view_listener_t
+void handle_object_delete()
{
- bool handleEvent(const LLSD& userdata)
- {
+
if (LLSelectMgr::getInstance())
{
LLSelectMgr::getInstance()->doDelete();
@@ -5018,9 +5008,8 @@ class LLObjectDelete : public view_listener_t
// When deleting an object we may not actually be done
// Keep selection so we know what to delete when confirmation is needed about the delete
gPieObject->hide();
- return true;
- }
-};
+ return;
+}
void handle_force_delete(void*)
{
@@ -5377,29 +5366,6 @@ class LLToolsLookAtSelection : public view_listener_t
}
};
-void callback_invite_to_group(LLUUID group_id, LLUUID dest_id)
-{
- std::vector<LLUUID> agent_ids;
- agent_ids.push_back(dest_id);
-
- LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
-}
-
-void invite_to_group(const LLUUID& dest_id)
-{
- LLViewerObject* dest = gObjectList.findObject(dest_id);
- if(dest && dest->isAvatar())
- {
- LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
- if (widget)
- {
- widget->center();
- widget->setPowersMask(GP_MEMBER_INVITE);
- widget->setSelectGroupCallback(boost::bind(callback_invite_to_group, _1, dest_id));
- }
- }
-}
-
class LLAvatarInviteToGroup : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -5407,7 +5373,7 @@ class LLAvatarInviteToGroup : public view_listener_t
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if(avatar)
{
- invite_to_group(avatar->getID());
+ LLAvatarActions::inviteToGroup(avatar->getID());
}
return true;
}
@@ -5475,7 +5441,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec
return false;
}
-bool handle_give_money_dialog()
+void handle_give_money_dialog()
{
LLNotification::Params params("BusyModePay");
params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
@@ -5489,38 +5455,28 @@ bool handle_give_money_dialog()
{
LLNotifications::instance().forceResponse(params, 1);
}
- return true;
}
-class LLPayObject : public view_listener_t
+bool enable_pay_avatar()
{
- bool handleEvent(const LLSD& userdata)
- {
- return handle_give_money_dialog();
- }
-};
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ LLVOAvatar* avatar = find_avatar_from_object(obj);
+ return (avatar != NULL);
+}
-class LLEnablePayObject : public view_listener_t
+bool enable_pay_object()
{
- bool handleEvent(const LLSD& userdata)
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if( object )
{
- LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- bool new_value = (avatar != NULL);
- if (!new_value)
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+ if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if( object )
- {
- LLViewerObject *parent = (LLViewerObject *)object->getParent();
- if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
- {
- new_value = true;
- }
- }
+ return true;
}
- return new_value;
}
-};
+ return false;
+}
class LLObjectEnableSitOrStand : public view_listener_t
{
@@ -6157,7 +6113,7 @@ class LLAttachmentEnableDetach : public view_listener_t
};
// Used to tell if the selected object can be attached to your avatar.
-BOOL object_selected_and_point_valid(const LLSD&)
+BOOL object_selected_and_point_valid()
{
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
for (LLObjectSelection::root_iterator iter = selection->root_begin();
@@ -6187,7 +6143,7 @@ BOOL object_selected_and_point_valid(const LLSD&)
BOOL object_is_wearable()
{
- if (!object_selected_and_point_valid(LLSD()))
+ if (!object_selected_and_point_valid())
{
return FALSE;
}
@@ -6209,15 +6165,6 @@ BOOL object_is_wearable()
}
-// Also for seeing if object can be attached. See above.
-class LLObjectEnableWear : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- return object_selected_and_point_valid(LLSD());
- }
-};
-
class LLAttachmentPointFilled : public view_listener_t
{
bool handleEvent(const LLSD& user_data)
@@ -6564,40 +6511,37 @@ class LLEditableSelectedMono : public view_listener_t
}
};
-class LLToolsEnableTakeCopy : public view_listener_t
+bool enable_object_take_copy()
{
- bool handleEvent(const LLSD& userdata)
+ bool all_valid = false;
+ if (LLSelectMgr::getInstance())
{
- bool all_valid = false;
- if (LLSelectMgr::getInstance())
+ if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- all_valid = true;
+ all_valid = true;
#ifndef HACKED_GODLIKE_VIEWER
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- if (LLViewerLogin::getInstance()->isInProductionGrid()
- || !gAgent.isGodlike())
+ if (LLViewerLogin::getInstance()->isInProductionGrid()
+ || !gAgent.isGodlike())
# endif
+ {
+ struct f : public LLSelectedObjectFunctor
{
- struct f : public LLSelectedObjectFunctor
+ virtual bool apply(LLViewerObject* obj)
{
- virtual bool apply(LLViewerObject* obj)
- {
- return (!obj->permCopy() || obj->isAttachment());
- }
- } func;
- const bool firstonly = true;
- bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- all_valid = !any_invalid;
- }
-#endif // HACKED_GODLIKE_VIEWER
+ return (!obj->permCopy() || obj->isAttachment());
+ }
+ } func;
+ const bool firstonly = true;
+ bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+ all_valid = !any_invalid;
}
+#endif // HACKED_GODLIKE_VIEWER
}
-
- return all_valid;
}
-};
+
+ return all_valid;
+}
class LLHasAsset : public LLInventoryCollectFunctor
@@ -7701,13 +7645,14 @@ void initialize_menus()
LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+ LLUICtrl::VisibleCallbackRegistry::Registrar& visible = LLUICtrl::VisibleCallbackRegistry::currentRegistrar();
// Enable God Mode
view_listener_t::addMenu(new LLEnableGodCustomerService(), "EnableGodCustomerService");
// Agent
commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
- enable.add("Agent.emableFlying", boost::bind(&LLAgent::enableFlying));
+ enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying));
// File menu
init_menu_file();
@@ -7801,8 +7746,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
view_listener_t::addMenu(new LLToolsLookAtSelection(), "Tools.LookAtSelection");
- view_listener_t::addMenu(new LLToolsBuyOrTake(), "Tools.BuyOrTake");
- view_listener_t::addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy");
+ commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
+ commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
view_listener_t::addMenu(new LLToolsSaveToInventory(), "Tools.SaveToInventory");
view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
@@ -7811,7 +7756,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsEnableLink(), "Tools.EnableLink");
view_listener_t::addMenu(new LLToolsEnableUnlink(), "Tools.EnableUnlink");
view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
- view_listener_t::addMenu(new LLToolsEnableTakeCopy(), "Tools.EnableTakeCopy");
+ visible.add("Tools.VisibleTakeCopy", boost::bind(&enable_object_take_copy));
+ enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
view_listener_t::addMenu(new LLToolsEnableSaveToInventory(), "Tools.EnableSaveToInventory");
view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
@@ -8012,31 +7958,51 @@ void initialize_menus()
view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
- view_listener_t::addMenu(new LLObjectEnableMute(), "Avatar.EnableMute");
view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
view_listener_t::addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject");
// Object pie menu
view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
- view_listener_t::addMenu(new LLObjectTouch(), "Object.Touch");
- view_listener_t::addMenu(new LLObjectSitOrStand(), "Object.SitOrStand");
- view_listener_t::addMenu(new LLObjectDelete(), "Object.Delete");
+ commit.add("Object.Touch", boost::bind(&handle_object_touch));
+ commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
+ visible.add("Object.EnableSit", boost::bind(&enable_sit_object));
+ commit.add("Object.Delete", boost::bind(&handle_object_delete));
view_listener_t::addMenu(new LLObjectAttachToAvatar(), "Object.AttachToAvatar");
view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
- view_listener_t::addMenu(new LLObjectBuy(), "Object.Buy");
- view_listener_t::addMenu(new LLObjectEdit(), "Object.Edit");
- view_listener_t::addMenu(new LLObjectEnableOpen(), "Object.EnableOpen");
+ visible.add("Object.VisibleTake", boost::bind(&visible_take_object));
+ visible.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
+
+ commit.add("Object.Buy", boost::bind(&handle_buy));
+ commit.add("Object.Edit", boost::bind(&handle_object_edit));
+
+ commit.add("Object.Take", boost::bind(&handle_take));
+
+ enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
+ visible.add("Object.VisibleOpen", boost::bind(&enable_object_open));
+
+ enable.add("Object.EnableTouch", boost::bind(&enable_object_touch));
+ visible.add("Object.VisibleTouch", boost::bind(&enable_object_touch));
+
view_listener_t::addMenu(new LLObjectEnableTouch(), "Object.EnableTouch");
view_listener_t::addMenu(new LLObjectEnableSitOrStand(), "Object.EnableSitOrStand");
- view_listener_t::addMenu(new LLObjectEnableDelete(), "Object.EnableDelete");
- view_listener_t::addMenu(new LLObjectEnableWear(), "Object.EnableWear");
+
+ enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
+ visible.add("Object.VisibleDelete", boost::bind(&enable_object_delete));
+
+ enable.add("Object.EnableWear", boost::bind(&object_selected_and_point_valid));
+ visible.add("Object.VisibleWear", boost::bind(&object_selected_and_point_valid));
+
view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
- view_listener_t::addMenu(new LLObjectEnableMute(), "Object.EnableMute");
- view_listener_t::addMenu(new LLObjectEnableBuy(), "Object.EnableBuy");
+
+ enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
+ enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
+ visible.add("Object.VisibleMute", boost::bind(&enable_object_mute));
+
+ enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
/*view_listener_t::addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch");
view_listener_t::addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch");
@@ -8068,10 +8034,13 @@ void initialize_menus()
view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
- view_listener_t::addMenu(new LLPayObject(), "PayObject");
+ commit.add("PayObject", boost::bind(&handle_give_money_dialog));
- view_listener_t::addMenu(new LLEnablePayObject(), "EnablePayObject");
- view_listener_t::addMenu(new LLEnableEdit(), "EnableEdit");
+ enable.add("EnablePayObject", boost::bind(&enable_pay_object));
+ visible.add("VisiblePayObject", boost::bind(&enable_pay_object));
+ enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
+ enable.add("EnableEdit", boost::bind(&enable_object_edit));
+ visible.add("Object.VisibleEdit", boost::bind(&enable_object_edit));
view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index dd6aac2dd3..75f4f08bde 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -36,14 +36,12 @@
#include "llmenugl.h"
#include "llsafehandle.h"
-//newview includes
-#include "llfilepicker.h"
-
+class LLSD;
class LLUICtrl;
class LLView;
class LLParcelSelection;
class LLObjectSelection;
-
+class LLSelectNode;
void init_menus();
void cleanup_menus();
@@ -83,7 +81,6 @@ void confirm_replace_attachment(S32 option, void* user_data);
void handle_detach_from_avatar(const LLSD& user_data);
void attach_label(std::string& label, const LLSD&);
void detach_label(std::string& label, const LLSD&);
-BOOL object_selected_and_point_valid(const LLSD&);
void handle_detach(void*);
BOOL enable_god_full(void* user_data);
BOOL enable_god_liaison(void* user_data);
@@ -96,21 +93,34 @@ void exchange_callingcard(const LLUUID& dest_id);
void handle_gestures(void*);
void handle_sit_down(void*);
void handle_object_build(void*);
+void handle_object_touch();
+bool enable_object_open();
+
+// Buy either contents or object itself
+void handle_buy();
+
+void handle_take_copy();
+
+// Can anyone take a free copy of the object?
+// *TODO: Move to separate file
+bool anyone_copy_selection(LLSelectNode* nodep);
+
+// Is this selected object for sale?
+// *TODO: Move to separate file
+bool for_sale_selection(LLSelectNode* nodep);
+
void handle_save_snapshot(void *);
void handle_toggle_flycam();
-bool handle_sit_or_stand();
-bool handle_give_money_dialog();
+void handle_object_sit_or_stand();
+void handle_give_money_dialog();
+bool enable_pay_object();
+bool enable_buy_object();
bool handle_go_to();
// Export to XML or Collada
void handle_export_selected( void * );
-// Pass in an empty string and this function will build a string that
-// describes buyer permissions.
-class LLSaleInfo;
-class LLPermissions;
-
class LLViewerMenuHolderGL : public LLMenuHolderGL
{
public:
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 390e1fe032..2e8580907e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -103,6 +103,7 @@
#include "llsidetray.h"
#include "llstartup.h"
#include "llsky.h"
+#include "llslurl.h"
#include "llstatenums.h"
#include "llstatusbar.h"
#include "llimview.h"
@@ -168,9 +169,6 @@ extern BOOL gDebugClicks;
// function prototypes
void open_offer(const std::vector<LLUUID>& items, const std::string& from_name);
bool check_offer_throttle(const std::string& from_name, bool check_only);
-void callbackCacheEstateOwnerName(const LLUUID& id,
- const std::string& first, const std::string& last,
- BOOL is_group);
//inventory offer throttle globals
LLFrameTimer gThrottleTimer;
@@ -5576,10 +5574,17 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateEstateName(estate_name);
LLFloaterBuyLand::updateEstateName(estate_name);
+ std::string owner_name =
+ LLSLURL::buildCommand("agent", estate_owner_id, "inspect");
+ LLPanelEstateCovenant::updateEstateOwnerName(owner_name);
+ LLPanelLandCovenant::updateEstateOwnerName(owner_name);
+ LLFloaterBuyLand::updateEstateOwnerName(owner_name);
+
LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
if (panel)
{
panel->updateEstateName(estate_name);
+ panel->updateEstateOwnerName(owner_name);
}
// standard message, not from system
@@ -5607,8 +5612,6 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateLastModified(last_modified);
LLFloaterBuyLand::updateLastModified(last_modified);
- gCacheName->get(estate_owner_id, false, &callbackCacheEstateOwnerName);
-
// load the actual covenant asset data
const BOOL high_priority = TRUE;
if (covenant_id.notNull())
@@ -5638,32 +5641,10 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelEstateCovenant::updateCovenantText(covenant_text, covenant_id);
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, covenant_id);
- panel->updateCovenantText(covenant_text);
- }
-}
-
-void callbackCacheEstateOwnerName(const LLUUID& id,
- const std::string& first, const std::string& last,
- BOOL is_group)
-{
- std::string name;
-
- if (id.isNull())
- {
- name = LLTrans::getString("none_text");
- }
- else
- {
- name = first + " " + last;
- }
- LLPanelEstateCovenant::updateEstateOwnerName(name);
- LLPanelLandCovenant::updateEstateOwnerName(name);
- LLFloaterBuyLand::updateEstateOwnerName(name);
-
- LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
- if (panel)
- {
- panel->updateEstateOwnerName(name);
+ if (panel)
+ {
+ panel->updateCovenantText(covenant_text);
+ }
}
}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 275c79fd3b..3964a56bf6 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -71,6 +71,9 @@ const F32 PARCEL_POST_HEIGHT = 0.666f;
// Base class for people who want to "observe" changes in the viewer
// parcel selection.
+
+//FIXME: this should be done by grabbing a floating parcel selection and observing changes on it, not the parcel mgr
+//--RN
class LLParcelObserver
{
public:
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index ceb2698223..b853bcb46e 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -32,37 +32,37 @@
#include "llviewerprecompiledheaders.h"
+#include "llviewertexteditor.h"
+
+#include "llagent.h"
+#include "llaudioengine.h"
+#include "llavataractions.h"
+#include "llfloaterchat.h"
#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
-#include "llaudioengine.h"
-#include "llagent.h"
#include "llinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
-
-#include "llviewertexteditor.h"
-
-#include "llfloaterchat.h"
-#include "llfloaterworldmap.h"
+#include "llmemorystream.h"
+#include "llmenugl.h"
+#include "llnotecard.h"
#include "llnotify.h"
#include "llpanelplaces.h"
#include "llpreview.h"
-#include "llpreviewtexture.h"
#include "llpreviewnotecard.h"
+#include "llpreviewtexture.h"
#include "llscrollbar.h"
+#include "llscrollcontainer.h"
#include "llsidetray.h"
#include "lltooldraganddrop.h"
+#include "lltooltip.h"
#include "lltrans.h"
+#include "lluictrlfactory.h"
#include "llviewercontrol.h"
+#include "llviewerinventory.h"
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
-#include "llviewerinventory.h"
-#include "lluictrlfactory.h"
-#include "llnotecard.h"
-#include "llmemorystream.h"
-#include "llmenugl.h"
-#include "llscrollcontainer.h"
-#include "llavataractions.h"
#include "llappviewer.h" // for gPacificDaylightTime
@@ -142,8 +142,6 @@ public:
}
}
- //virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
- //virtual void updateLayout(const class LLTextEditor& editor);
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
@@ -167,7 +165,7 @@ public:
}
F32 right_x;
- mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mBottom, color, LLFontGL::LEFT, LLFontGL::BOTTOM, mHasMouseHover ? LLFontGL::UNDERLINE : 0, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x);
+ mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mBottom, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::UNDERLINE, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x);
return right_x;
}
@@ -176,20 +174,21 @@ public:
return llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight()));
}
/*virtual*/ bool canEdit() const { return false; }
- //virtual void unlinkFromDocument(class LLTextEditor* editor);
- //virtual void linkToDocument(class LLTextEditor* editor);
- virtual void setHasMouseHover(bool hover)
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
{
- mHasMouseHover = hover;
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
}
- //virtual const LLColor4& getColor() const;
- //virtual void setColor(const LLColor4 &color);
- //virtual void setStyle(const LLStyleSP &style);
- virtual BOOL getToolTip( std::string& msg ) const
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask )
{
- msg = mToolTip;
- return TRUE;
+ if (!mToolTip.empty())
+ {
+ LLToolTipMgr::instance().show(mToolTip);
+ return TRUE;
+ }
+ return FALSE;
}
/*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
@@ -562,17 +561,17 @@ void LLEmbeddedItems::markSaved()
///////////////////////////////////////////////////////////////////
-class LLViewerTextEditor::LLTextCmdInsertEmbeddedItem : public LLTextEditor::LLTextCmd
+class LLViewerTextEditor::TextCmdInsertEmbeddedItem : public LLTextBase::TextCmd
{
public:
- LLTextCmdInsertEmbeddedItem( S32 pos, LLInventoryItem* item )
- : LLTextCmd(pos, FALSE),
+ TextCmdInsertEmbeddedItem( S32 pos, LLInventoryItem* item )
+ : TextCmd(pos, FALSE),
mExtCharValue(0)
{
mItem = item;
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
LLViewerTextEditor* viewer_editor = (LLViewerTextEditor*)editor;
// Take this opportunity to remove any unused embedded items from this editor
@@ -587,13 +586,13 @@ public:
return FALSE;
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), 1);
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
LLWString ws;
ws += mExtCharValue;
@@ -635,7 +634,6 @@ LLViewerTextEditor::LLViewerTextEditor(const LLViewerTextEditor::Params& p)
mDragItemSaved(FALSE),
mInventoryCallback(new LLEmbeddedNotecardOpener)
{
- mParseHTML = p.allow_html;
mEmbeddedItemList = new LLEmbeddedItems(this);
mInventoryCallback->setEditor(this);
}
@@ -673,7 +671,7 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
llwchar wc = 0;
if (mCursorPos < getLength())
{
- wc = getWChar(mCursorPos);
+ wc = getWText()[mCursorPos];
}
LLInventoryItem* item_at_pos = LLEmbeddedItems::getEmbeddedItem(wc);
if (item_at_pos)
@@ -773,22 +771,6 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
return handled;
}
-BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- // pop up a context menu for any Url under the cursor
- if (handleRightMouseDownOverUrl(this, x, y))
- {
- return TRUE;
- }
-
- if (childrenHandleRightMouseDown(x, y, mask) != NULL)
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -955,7 +937,7 @@ std::string LLViewerTextEditor::getEmbeddedText()
LLWString outtextw;
for (S32 i=0; i<(S32)getWText().size(); i++)
{
- llwchar wch = getWChar(i);
+ llwchar wch = getWText()[i];
if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR )
{
S32 index = mEmbeddedItemList->getIndexFromEmbeddedChar(wch);
@@ -998,7 +980,8 @@ std::string LLViewerTextEditor::appendTime(bool prepend_newline)
substitution["datetime"] = (S32) utc_time;
LLStringUtil::format (timeStr, substitution);
- appendColoredText(timeStr, false, prepend_newline, LLColor4::grey);
+ appendText(timeStr, prepend_newline, LLStyle::Params().color(LLColor4::grey));
+ blockUndo();
return timeStr;
}
@@ -1057,7 +1040,7 @@ BOOL LLViewerTextEditor::openEmbeddedItemAtPos(S32 pos)
{
if( pos < getLength())
{
- llwchar wc = getWChar(pos);
+ llwchar wc = getWText()[pos];
LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem( wc );
if( item )
{
@@ -1227,7 +1210,7 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD&
// Returns change in number of characters in mWText
S32 LLViewerTextEditor::insertEmbeddedItem( S32 pos, LLInventoryItem* item )
{
- return execute( new LLTextCmdInsertEmbeddedItem( pos, item ) );
+ return execute( new TextCmdInsertEmbeddedItem( pos, item ) );
}
bool LLViewerTextEditor::importStream(std::istream& str)
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index 100fa343af..ba0c40cb2e 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -43,10 +43,7 @@ class LLViewerTextEditor : public LLTextEditor
public:
struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
{
- Optional<bool> allow_html;
-
Params()
- : allow_html("allow_html", false)
{
name = "text_editor";
}
@@ -64,7 +61,6 @@ public:
// mousehandler overrides
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
@@ -139,7 +135,7 @@ private:
// Inner classes
//
- class LLTextCmdInsertEmbeddedItem;
+ class TextCmdInsertEmbeddedItem;
};
#endif // LL_VIEWERTEXTEDITOR_H
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4a0efbaddc..24d00cba16 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -835,9 +835,13 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask
// Save mouse point for access during idle() and display()
LLCoordGL mouse_point(x, y);
- saveLastMouse(mouse_point);
- LLUI::resetMouseIdleTimer();
+ if (mouse_point != mCurrentMousePoint)
+ {
+ LLUI::resetMouseIdleTimer();
+ }
+
+ saveLastMouse(mouse_point);
mWindow->showCursorFromMouseMove();
@@ -1866,7 +1870,6 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
if(gStatusBar)
{
gStatusBar->setBackgroundColor( new_bg_color );
- gStatusBar->getChild<LLTextBox>("HealthText")->setBackgroundColor(new_bg_color);
}
}
@@ -2022,7 +2025,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
}
// hide tooltips on keypress
- LLToolTipMgr::instance().hideToolTips();
+ LLToolTipMgr::instance().blockToolTips();
// Explicit hack for debug menu.
if ((MASK_ALT & mask) &&
@@ -2609,16 +2612,16 @@ void LLViewerWindow::updateUI()
append_xui_tooltip(tooltip_view, tool_tip_msg);
screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tool_tip_msg)
.sticky_rect(screen_sticky_rect)
- .width(400));
+ .max_width(400));
}
// if there is a mouse captor, nothing else gets a tooltip
else if (mouse_captor)
{
mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
}
else
{
@@ -2626,20 +2629,20 @@ void LLViewerWindow::updateUI()
if (!tool_tip_handled && top_ctrl)
{
top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
}
if (!tool_tip_handled)
{
local_x = x; local_y = y;
- tool_tip_handled = mRootView->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
}
LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
if (!tool_tip_handled && current_tool)
{
current_tool->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = current_tool->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect );
+ tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
}
}
}
@@ -2687,7 +2690,7 @@ void LLViewerWindow::updateLayout()
&& !suppress_toolbox // not override in third person
&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
- && (!captor || captor->isView()))) // not dragging
+ && (!captor || dynamic_cast<LLView*>(captor) != NULL))) // not dragging
{
// Force floater tools to be visible (unless minimized)
if (!gFloaterTools->getVisible())
@@ -2787,6 +2790,14 @@ void LLViewerWindow::updateKeyboardFocus()
}
parent = parent->getParentUICtrl();
}
+
+ // if we didn't find a better place to put focus, just release it
+ // hasFocus() will return true if and only if we didn't touch focus since we
+ // are only moving focus higher in the hierarchy
+ if (cur_focus->hasFocus())
+ {
+ cur_focus->setFocus(FALSE);
+ }
}
else if (cur_focus->isFocusRoot())
{
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 79308f7e16..30736b1e03 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -1181,7 +1181,7 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
}
-BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen )
+BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask )
{
LLVector3d pos_global = viewPosToGlobal(x, y);
@@ -1236,9 +1236,10 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& stic
S32 screen_x, screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
+ LLRect sticky_rect_screen;
sticky_rect_screen.setCenterAndSize(screen_x, screen_y, SLOP, SLOP);
- LLToolTipMgr::instance().show(LLToolTipParams()
+ LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tooltip_msg)
.sticky_rect(sticky_rect_screen));
}
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index 8349d5399f..66793f0101 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -72,7 +72,7 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen );
+ virtual BOOL handleToolTip( S32 x, S32 y, MASK mask);
bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track);
void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id);
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 7e22e17188..eb62c442db 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -2,7 +2,6 @@
<colors>
<!-- Named Colors -->
-
<color
name="EmphasisColor"
value="0.38 0.694 0.573 1" />
@@ -90,6 +89,9 @@
name="AlertCautionTextColor"
reference="Black" />
<color
+ name="AgentLinkColor"
+ reference="White" />
+ <color
name="AlertTextColor"
value="0.58 0.66 0.84 1" />
<color
diff --git a/indra/newview/skins/default/textures/icons/Info_Small.png b/indra/newview/skins/default/textures/icons/Info_Small.png
new file mode 100644
index 0000000000..81078c32dc
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Info_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 8a6e9486a2..f106796cd9 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -137,6 +137,7 @@
<texture name="Icon_Undock_Press" file_name="windows/Icon_Undock_Press.png" preload="false" />
<texture name="Info" file_name="icons/Info.png" preload="false" />
+ <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
<texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
<texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index c9e143bf95..dc6af79db5 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -80,6 +80,7 @@
label="Support"
name="support_panel">
<text_editor
+ allow_html="true"
follows="top|left"
font="SansSerif"
height="350"
@@ -127,7 +128,7 @@ Thank you to the following residents for helping to ensure that this is the best
It is a rare mind indeed that can render the hitherto non-existent blindingly obvious. The cry 'I could have thought of that' is a very popular and misleading one, for the fact is that they didn't, and a very significant and revealing fact it is too.
--- Douglas Adams
+ -- Douglas Adams
</text_editor>
</panel>
<panel
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 5a285cdcb0..524495d83d 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -132,9 +132,6 @@ Go to World menu &gt; About Land or select another parcel to show its details.
Description:
</text>
<text_editor
- bevel_style="in"
- border_style="line"
- border_thickness="1"
follows="left|top|right"
height="52"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
index bd0dac5ca1..62d40bc45f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -483,7 +483,8 @@ sold with objects
name="error_message"
right="435"
top="208"
- width="215">
+ width="215"
+ word_wrap="true">
Something ain&apos;t right.
</text>
<button
@@ -583,7 +584,8 @@ sold with objects
left="72"
name="land_use_reason"
right="435"
- width="215">
+ width="215"
+ word_wrap="true">
You hold 1309 m² of land.
This parcel is 512 m² of land.
</text>
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index be1278e8cc..a233f7f0fa 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -56,6 +56,8 @@
layout="topleft"
max_length="2147483647"
name="im_text"
+ parse_highlights="true"
+ allow_html="true"
track_bottom="true"
width="195"
word_wrap="true">
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 8b271eb41e..bdce8fa4fc 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -33,7 +33,7 @@
<text_editor
font="SansSerif"
height="64"
- hide_border="true"
+ border_visible="false"
hide_scrollbar="true"
layout="topleft"
left="77"
diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml
index 00b9f850ad..339604e658 100644
--- a/indra/newview/skins/default/xui/en/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/en/floater_inspect.xml
@@ -55,7 +55,7 @@
top_pad="5"
width="150">
<button.commit_callback
- function="Inspect.OwnerProfilet" />
+ function="Inspect.OwnerProfile" />
</button>
<button
follows="left|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml
index 70f9c19658..dc6a02efe1 100644
--- a/indra/newview/skins/default/xui/en/floater_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_map.xml
@@ -81,7 +81,6 @@
left="0"
name="floater_map_east"
right="10"
- text="E"
text_color="1 1 1 0.7"
top="215">
E
@@ -95,7 +94,6 @@
left="0"
name="floater_map_west"
right="11"
- text="W"
text_color="1 1 1 0.7"
top="215">
W
@@ -109,7 +107,6 @@
left="0"
name="floater_map_south"
right="10"
- text="S"
text_color="1 1 1 0.7"
top="215">
S
@@ -123,7 +120,6 @@
left="0"
name="floater_map_southeast"
right="20"
- text="SE"
text_color="1 1 1 0.7"
top="215">
SE
@@ -137,7 +133,6 @@
left="0"
name="floater_map_northeast"
right="20"
- text="NE"
text_color="1 1 1 0.7"
top="215">
NE
@@ -151,7 +146,6 @@
left="0"
name="floater_map_southwest"
right="20"
- text="SW"
text_color="1 1 1 0.7"
top="215">
SW
@@ -165,7 +159,6 @@
left="0"
name="floater_map_northwest"
right="20"
- text="NW"
text_color="1 1 1 0.7"
top="215">
NW
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 78f795b0e2..e851710ad8 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -39,6 +39,7 @@
height="320"
max_length="2147483647"
name="Chat History Editor"
+ parse_highlights="true"
read_only="true"
text_color="ChatHistoryTextColor"
text_readonly_color="ChatHistoryTextColor"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index 1d7b7adca2..f90f2a81cf 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -74,6 +74,7 @@
left="4"
max_length="65536"
name="Notecard Editor"
+ allow_html="true"
handle_edit_keys_directly="true"
tab_group="1"
top="46"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index c7f5a1170f..abde4ba5fa 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -33,6 +33,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
@@ -58,6 +59,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
@@ -83,6 +85,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
@@ -130,6 +133,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
@@ -155,6 +159,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
@@ -345,6 +350,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -389,6 +395,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
@@ -413,6 +420,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -437,6 +445,7 @@
length="1"
follows="left|top"
height="16"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -473,6 +482,7 @@
height="50"
layout="topleft"
left="10"
+ font.name="SansSerif"
font.style="BOLD"
name="incomplete_title"
top_pad="5"
diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
index c8b8c34f85..2085b74a55 100644
--- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
@@ -16,6 +16,7 @@
layout="topleft"
max_length="10000"
name="Chat History Editor"
+ parse_highlights="true"
width="420"
word_wrap="true" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml
index b703b49b8b..95de27e0ea 100644
--- a/indra/newview/skins/default/xui/en/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/en/floater_telehub.xml
@@ -88,7 +88,6 @@
</text>
<scroll_list
follows="left|top"
- font="SansSerifSmall"
height="60"
layout="topleft"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
index a1a271d0eb..2011f57d8b 100644
--- a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
- can_resize="true"
+ can_resize="false"
height="400"
layout="topleft"
name="floater_test_inspectors"
@@ -15,7 +15,6 @@
width="300">
Click to spawn an inspector:
</text>
- <!-- James Tester, 4 years old -->
<button
name="avatar_2d_btn1"
label="Avatar 2D"
@@ -25,7 +24,7 @@
width="100"
commit_callback.function="ShowAvatarInspector"
commit_callback.parameter="22df1dcb-810a-4975-aab9-0159958fe155" />
- <!-- DonkeyPuncher 2008-10-1 -->
+ <!-- InspectorA Tester -->
<button
name="avatar_2d_btn5"
label="Avatar 2D"
@@ -34,8 +33,8 @@
height="20"
width="100"
commit_callback.function="ShowAvatarInspector"
- commit_callback.parameter="d5330e4e-391a-4f00-9352-b797ed2f9a97" />
- <!-- DonkeyPuncher 2009-01-15 -->
+ commit_callback.parameter="927e68e0-e52d-4bb8-b1a9-add97a57c86a" />
+ <!-- InspectorB Tester -->
<button
name="avatar_2d_btn2"
label="Avatar 2D"
@@ -44,8 +43,8 @@
height="20"
width="100"
commit_callback.function="ShowAvatarInspector"
- commit_callback.parameter="05511655-a58a-48b6-b645-966f69fc17a7" />
- <!-- 2009-06-14 -->
+ commit_callback.parameter="9a2300ca-e251-45dd-bb61-e33139f6e4eb" />
+ <!-- InspectorC Tester -->
<button
name="avatar_2d_btn3"
label="Avatar 2D"
@@ -54,7 +53,7 @@
height="20"
width="100"
commit_callback.function="ShowAvatarInspector"
- commit_callback.parameter="6a164b3d-7c2c-43eb-880a-0ebc0687b3ec" />
+ commit_callback.parameter="8024f082-34cc-48a3-a42e-c42f345efd74" />
<!-- jarvtest Bombastic 2009-10-3 -->
<button
name="avatar_2d_btn4"
@@ -85,7 +84,9 @@
top_pad="10"
left_delta="0"
height="20"
- width="100"/>
+ width="100"
+ commit_callback.function="ShowObjectInspector"
+ commit_callback.parameter="" />
<button
name="group_btn"
label="Group"
@@ -107,5 +108,17 @@
left_delta="0"
height="20"
width="100"/>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="0"
+ max_length="65536"
+ name="slurl"
+ top_pad="4"
+ width="100">
+ secondlife:///app/agent/00000000-0000-0000-0000-000000000000/inspect
+ </text>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 88c001b714..8305452c85 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -122,7 +122,6 @@
left="10"
name="floater_map_north"
right="30"
- text="N"
text_color="1 1 1 0.7"
top="370">
N
diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
index 6ddaa63c1d..5a29c6a319 100644
--- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
@@ -19,6 +19,8 @@
can_resize="true"
title="Test Floater"
height="500"
+ min_width="850"
+ min_height="500"
layout="topleft"
name="floater_test_widgets"
help_topic="floater_test_widgets"
@@ -39,6 +41,7 @@
<menu_bar
height="18"
layout="topleft"
+ follows="top|left"
tool_tip="menu"
left="2"
name="test_menu_bar"
@@ -74,7 +77,9 @@
<text
bottom="55"
layout="topleft"
- left="10">
+ follows="top|left"
+ left="10"
+ height="16">
For widget list see https://wiki.lindenlab.com/wiki/Viewer:UI/Widgets
</text>
@@ -82,6 +87,7 @@
<button
height="20"
+ follows="top|left"
label="Button"
layout="topleft"
left_delta="0"
@@ -91,7 +97,7 @@
width="100" />
<!-- "flyout_button" is a button that can spawn a menu -->
<flyout_button
- follows="right|bottom"
+ follows="top|left"
height="20"
label="Flyout"
layout="topleft"
@@ -121,6 +127,7 @@
provide input that is not a list item. -->
<combo_box
bottom_delta="35"
+ follows="top|left"
height="16"
width="150"
label="Combobox"
@@ -150,6 +157,7 @@
the text. -->
<line_editor
height="20"
+ follows="top|left"
layout="topleft"
left_delta="0"
name="test_line_editor"
@@ -161,7 +169,7 @@
<!-- "filter_editor" is a specialized line_editor that shows read-only
help text until the user clicks in the widget. -->
<filter_editor
- follows="left|top|right"
+ follows="left|top"
height="20"
label="Type here to search"
layout="topleft"
@@ -173,6 +181,7 @@
<!-- "progress_bar" percent completed gets set in C++ code -->
<progress_bar
height="16"
+ follows="top|left"
layout="topleft"
left_delta="0"
name="test_progress_bar"
@@ -227,6 +236,7 @@
<!-- "scroll_list" is a scrolling list of columnar data. -->
<scroll_list
bottom_delta="100"
+ follows="top|left"
height="80"
draw_heading="true"
tool_tip="scroll list"
@@ -239,10 +249,19 @@
dynamic_width="true"
name="second_column"
label="Column B"/>
+ <row>
+ <column column="first_column">short text</column>
+ <column column="second_column">more short text</column>
+ </row>
+ <row>
+ <column column="first_column">this is some longer text</column>
+ <column column="second_column">and here is some more long text</column>
+ </row>
</scroll_list>
<!-- "slider" is a horizontal input widget for numerical data. -->
<slider
bottom_delta="45"
+ follows="top|left"
layout="topleft"
min_val="0"
max_val="100"
@@ -255,22 +274,36 @@
change the value. -->
<spinner
bottom_delta="35"
+ follows="top|left"
label="Spinner"
layout="topleft"
name="test_spinner"
tool_tip="spinner"/>
<text
bottom_delta="50"
+ follows="top|left"
+ font.name="SansSerifSmall"
font.style = "UNDERLINE"
layout="topleft"
name="test_text"
tool_tip="text">
Text (underlined)
</text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ width="60"
+ use_ellipses="true"
+ name="test_text"
+ tool_tip="text">
+ Truncated text here
+ </text>
<!-- "text_editor" is a multi-line text input widget, similar to
textarea in HTML. -->
<text_editor
- height="80"
+ height="40"
+ follows="top|left|bottom"
layout="topleft"
left_delta="0"
name="test_text_editor"
@@ -279,7 +312,18 @@
width="200">
Text Editor
</text_editor>
-
+ <text
+ height="40"
+ follows="top|left|bottom"
+ layout="topleft"
+ name="test_text_editor"
+ tool_tip="text box"
+ top_pad="5"
+ width="200">
+ Text box
+with
+multiple lines
+ </text>
<!-- And a third column -->
<!-- "tab_container" is a holder for multiple panels of UI widgets.
@@ -309,7 +353,6 @@
color="0.3 0.6 0.9 1"
follows="left|top"
height="90"
- border="true"
layout="topleft"
left="10"
label="Color Swatch 1"
@@ -333,7 +376,7 @@
</panel>
<!-- panels can also refer to other floaters or panels -->
<panel
- border="true"
+ border="true"
filename="floater_test_checkbox.xml"
height="225"
label="Tab 2 - Checkbox"
diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
index 9a3d5aa183..4ed6787f53 100644
--- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
@@ -17,7 +17,7 @@
left="0"
mouse_opaque="false"
name="main_panel"
- right="650"
+ right="750"
top="0">
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index 2042ffedbc..b44acebbcf 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -1,102 +1,142 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<!-- All our XML is utf-8 encoded. -->
-
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<!--
Not can_close / no title to avoid window chrome
Single instance - only have one at a time, recycle it each spawn
-->
<floater
- background_opaque="false"
- background_visible="true"
- bevel_style="in"
- bg_alpha_color="PanelDefaultBackgroundColor"
- can_close="false"
- can_minimize="false"
- name="inspect_avatar"
- help_topic="inspect_avatar"
- single_instance="true"
- sound_flags="0"
- title=""
- visible="true"
- width="300"
- height="200"
- left="0"
- top="200"
- >
+ bevel_style="in"
+ bg_alpha_color="PanelDefaultBackgroundColor"
+ can_close="false"
+ can_minimize="false"
+ height="190"
+ layout="topleft"
+ name="inspect_avatar"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="300">
<!-- Allowed fields include:
[BORN_ON] ("12/3/2008")
[SL_PROFILE] (Second Life profile),
- [RW_PROFILE] (real world profile),
+ [RW_PROFILE] (real world profile),
[ACCTTYPE] ("Resident"),
[PAYMENTINFO] ("Payment Info on File"),
- [AGE] ("1 year 2 months") -->
- <string name="Subtitle">
+ [AGE] ("1 year 2 months")
+ -->
+ <string
+ name="Subtitle">
[AGE]
</string>
- <string name="Details">
-[ACCTTYPE], [PAYMENTINFO]
-Profile: [SL_PROFILE]
+ <string
+ name="Details">
+[ACCTTYPE][COMMA] [PAYMENTINFO]
+ </string>
+ <string
+ name="Partner">
+ Partner: [PARTNER]
</string>
<text
- top="180" left="10" width="280" height="70" follows="left|top|right|bottom"
- use_ellipses="true" word_wrap="true"
- font="SansSerifHugeBold" text_color="white"
- mouse_opaque="true" name="user_name" >
- Test Name
- </text>
- <!-- General purpose subtitle area, not sure yet what goes here -->
- <text
- top="155" left="10" width="150" height="20" follows="left|top|right|bottom"
- font="SansSerifBig"
- text_color="white"
- mouse_opaque="true"
- name="user_subtitle" />
- <!-- Leave text fields blank so it doesn't flash when data arrives off the network -->
- <text
- top="115" left="10" width="290" height="50" follows="left|top|right|bottom"
- font="SansSerifSmall" text_color="white" word_wrap="true"
- mouse_opaque="true" name="user_details" />
- <avatar_icon
- top="185" left="230" width="60" height="60" follows="left|top|right|bottom"
- color="1 1 1 1" enabled="true" mouse_opaque="true" name="avatar_icon"
- />
- <slider
- bottom="35" left="45" width="250" height="30" follows="top|left"
- name="volume_slider"
- tool_tip="Voice Volume"
- increment="0.05" initial_value="0.75" max_val="1" min_val="0"
- show_text="false"
- />
- <button
- bottom="40" left="10" width="32" height="16" follows="left|top|right|bottom"
- name="mute_btn"
- label=""
- image_unselected="icn_speaker_dark.tga"
- image_disabled="icn_speaker_dark.tga"
- image_selected="icn_speaker-muted_dark.tga"
- image_hover_selected="icn_speaker-muted_dark.tga"
- image_disabled_selected="icn_speaker-muted_dark.tga"
- halign="center"
- toggle="true"
- />
- <button
- bottom="10" left="10" width="110" height="20" follows="top|left"
- name="add_friend_btn"
- label="Add Friend"
- font="SansSerif"
- />
- <button
- bottom="10" left="120" width="110" height="20" follows="top|left"
- name="view_profile_btn"
- label="View Profile"
- font="SansSerif"
- />
- <button
- bottom="10" left="230" width="60" height="20" follows="top|left"
- name="gear_btn"
- label=""
- image_overlay="Icon_Gear_Foreground"
- image_overlay_alignment="center"
- scale_image="true"
- />
-</floater>
+ follows="left|top|right|bottom"
+ font="SansSerifHugeBold"
+ height="70"
+ left="10"
+ name="user_name"
+ text_color="white"
+ top="20"
+ use_ellipses="true"
+ value="Test Name"
+ width="280"
+ word_wrap="true" />
+ <text
+ follows="left|top|right|bottom"
+ font="SansSerifBig"
+ height="20"
+ left="10"
+ name="user_subtitle"
+ text_color="white"
+ top="45"
+ width="150" />
+ <!-- Leave text fields blank so it doesn't flash when data arrives off the network -->
+ <text
+ follows="left|top|right|bottom"
+ height="20"
+ left="10"
+ name="user_details"
+ text_color="white"
+ top="85"
+ width="290"
+ word_wrap="true" />
+ <text
+ follows="left|top|right|bottom"
+ height="20"
+ left="10"
+ name="user_partner"
+ text_color="white"
+ top="105"
+ width="290"
+ word_wrap="true" />
+ <avatar_icon
+ follows="left|top|right|bottom"
+ height="60"
+ left="230"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="15"
+ width="60" />
+ <slider
+ follows="top|left"
+ height="30"
+ increment="0.05"
+ left="20"
+ max_val="0.95"
+ min_val="0.05"
+ name="volume_slider"
+ show_text="false"
+ tool_tip="Voice Volume"
+ top="125"
+ value="0.5"
+ width="240" />
+ <button
+ follows="left|top|right|bottom"
+ height="16"
+ image_disabled="icn_speaker_dark.tga"
+ image_disabled_selected="icn_speaker-muted_dark.tga"
+ image_hover_selected="icn_speaker-muted_dark.tga"
+ image_selected="icn_speaker-muted_dark.tga"
+ image_unselected="icn_speaker_dark.tga"
+ is_toggle="true"
+ left="265"
+ name="mute_btn"
+ picture_style="true"
+ top="132"
+ width="32" />
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="20"
+ label="Add Friend"
+ left="10"
+ name="add_friend_btn"
+ top_pad="10"
+ width="105" />
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="20"
+ label="View Profile"
+ left_delta="110"
+ name="view_profile_btn"
+ top_delta="0"
+ width="105" />
+ <menu_button
+ follows="top|left"
+ height="20"
+ image_overlay="windows\Icon_Gear_Foreground.png"
+ image_overlay_alignment="center"
+ menu_filename="menu_inspect_avatar_gear.xml"
+ name="gear_btn"
+ picture_style="true"
+ top_delta="0"
+ left_delta="110"
+ width="60"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
new file mode 100644
index 0000000000..cc56f630b0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ bevel_style="in"
+ bg_opaque_color="MouseGray"
+ can_close="false"
+ can_minimize="false"
+ height="145"
+ layout="topleft"
+ name="inspect_object"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="300">
+ <string name="Creator">By [CREATOR]</string>
+ <string name="CreatorAndOwner">
+By [CREATOR]
+Owned by [OWNER]
+ </string>
+ <!-- *TODO: Might need to change to [AMOUNT] if icon contains "L$" -->
+ <string name="Price">L$[AMOUNT]</string>
+ <string name="PriceFree">Free!</string>
+ <string name="Touch">Touch</string>
+ <string name="Sit">Sit</string>
+ <text
+ follows="all"
+ font="SansSerifLargeBold"
+ height="20"
+ left="8"
+ name="object_name"
+ text_color="white"
+ top="8"
+ use_ellipses="true"
+ value="Test Object Name That Is Really Long"
+ width="268" />
+ <text
+ follows="all"
+ font="SansSerif"
+ height="30"
+ left="10"
+ name="object_creator"
+ top_pad="0"
+ width="280">
+By Longavatarname Johnsonlongstonnammer
+Owned by James Linden
+ </text>
+ <text
+ follows="all"
+ height="45"
+ left="100"
+ name="object_description"
+ top_pad="4"
+ width="200"
+ word_wrap="true">
+This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really?
+ </text>
+ <!-- *TODO: Replace this icon -->
+ <icon
+ name="price_icon"
+ image_name="Favorite_Star_Active"
+ left="5"
+ width="16"
+ height="16"
+ top="79"
+ follows="left|top"
+ />
+ <text
+ follows="all"
+ font="SansSerifSmallBold"
+ height="45"
+ left="22"
+ name="price_text"
+ text_color="white"
+ top="80"
+ font_shadow="none"
+ width="80">
+L$300,000
+ </text>
+ <!-- Overlapping buttons for all default actions. Show "Buy" if
+ for sale, "Sit" if can sit, etc. -->
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="23"
+ label="Buy"
+ left="10"
+ name="buy_btn"
+ top="116"
+ width="100" />
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="23"
+ label="Pay"
+ left_delta="0"
+ name="pay_btn"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="23"
+ label="Take Copy"
+ left_delta="0"
+ name="take_free_copy_btn"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="top|left"
+ font="SansSerifSmall"
+ height="23"
+ label="Touch"
+ left_delta="0"
+ name="touch_btn"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="top|left"
+ font="SansSerif"
+ height="23"
+ label="Sit"
+ left_delta="0"
+ name="sit_btn"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="top|left"
+ font="SansSerifSmall"
+ height="23"
+ label="Open"
+ left_delta="0"
+ name="open_btn"
+ top_delta="0"
+ width="100" />
+ <!-- non-overlapping buttons here -->
+ <menu_button
+ follows="top|left"
+ height="23"
+ image_overlay="Icon_Gear_Foreground"
+ image_overlay_alignment="center"
+ right="-8"
+ menu_filename="menu_inspect_object_gear.xml"
+ name="gear_btn"
+ picture_style="true"
+ top_delta="0"
+ width="30" />
+ <button
+ follows="top|left"
+ height="22"
+ image_overlay="TabIcon_Close_Off"
+ layout="topleft"
+ name="more_info_btn"
+ picture_style="true"
+ right="-8"
+ top="7"
+ left_delta="110"
+ tab_stop="false"
+ width="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..9f5b7f3813
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ enabled="true"
+ name="view_profile">
+ <menu_item_call.on_click
+ function="InspectAvatar.ViewProfile"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ layout="topleft"
+ name="add_friend">
+ <menu_item_call.on_click
+ function="InspectAvatar.AddFriend"/>
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="im">
+ <menu_item_call.on_click
+ function="InspectAvatar.IM"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ layout="topleft"
+ enabled="true"
+ name="call">
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="teleport">
+ <menu_item_call.on_click
+ function="InspectAvatar.Teleport"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Invite to Group"
+ layout="topleft"
+ name="invite_to_group">
+ <menu_item_call.on_click
+ function="InspectAvatar.InviteToGroup"/>
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call
+ label="Block"
+ layout="topleft"
+ name="block">
+ <menu_item_call.on_click
+ function="InspectAvatar.Block"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ layout="topleft"
+ name="report">
+ <menu_item_call.on_click
+ function="InspectAvatar.Report"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ layout="topleft"
+ name="freeze">
+ <menu_item_call.on_click
+ function="InspectAvatar.Freeze"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleGodMode"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ layout="topleft"
+ name="eject">
+ <menu_item_call.on_click
+ function="InspectAvatar.Eject"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleGodMode"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug"
+ layout="topleft"
+ name="debug">
+ <menu_item_call.on_click
+ function="InspectAvatar.Debug"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleGodMode"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Find On Map"
+ layout="topleft"
+ name="find_on_map">
+ <menu_item_call.on_click
+ function="InspectAvatar.FindOnMap"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFindOnMap"/>
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="pay">
+ <menu_item_call.on_click
+ function="InspectAvatar.Pay"/>
+ </menu_item_call>
+</menu> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..1bba8eb264
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="Touch"
+ layout="topleft"
+ enabled="true"
+ name="touch">
+ <menu_item_call.on_click
+ function="InspectObject.Touch"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleTouch" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sit"
+ layout="topleft"
+ name="sit">
+ <menu_item_call.on_click
+ function="InspectObject.Sit"/>
+ <menu_item_call.on_visible
+ function="Object.EnableSit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="pay">
+ <menu_item_call.on_click
+ function="InspectObject.Pay"/>
+ <menu_item_call.on_visible
+ function="VisiblePayObject" />
+ </menu_item_call>
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ enabled="true"
+ name="buy">
+ <menu_item_call.on_click
+ function="InspectObject.Buy"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleBuy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take"
+ layout="topleft"
+ name="take">
+ <menu_item_call.on_click
+ function="Object.Take" />
+ <menu_item_call.on_enable
+ function="Object.VisibleTake"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="take_copy">
+ <menu_item_call.on_click
+ function="InspectObject.TakeFreeCopy"/>
+ <menu_item_call.on_visible
+ function="Tools.VisibleTakeCopy"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="open">
+ <menu_item_call.on_click
+ function="InspectObject.Open"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleOpen" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="report">
+ <menu_item_call.on_click
+ function="Object.Edit" />
+ <menu_item_call.on_enable
+ function="Object.VisibleEdit"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Wear"
+ layout="topleft"
+ name="wear">
+ <menu_item_call.on_click
+ function="Object.AttachToAvatar" />
+ <menu_item_call.on_visible
+ function="Object.VisibleWear" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ layout="topleft"
+ name="report">
+ <menu_item_call.on_click
+ function="Object.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Block"
+ layout="topleft"
+ name="block">
+ <menu_item_call.on_click
+ function="Object.Mute" />
+ <menu_item_call.on_visible
+ function="Object.VisibleMute" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ </menu_item_call>
+ <menu_item_call
+ label="Remove"
+ layout="topleft"
+ name="remove">
+ <menu_item_call.on_click
+ function="Object.Delete" />
+ <menu_item_call.on_visible
+ function="Object.VisibleDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="More Info"
+ layout="topleft"
+ name="more_info">
+ <menu_item_call.on_click
+ function="InspectObject.MoreInfo"/>
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fe088b43be..829c2e02d8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -447,7 +447,7 @@ Your default permissions may not work in older regions.
icon="alertmodal.tga"
name="ClickUnimplemented"
type="alertmodal">
-This feature is yet to be implemented.
+Sorry, not implemented yet.
</notification>
<notification
@@ -761,7 +761,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now?
name="url"
openexternally = "1">
- http://secondlife.com/registration/
+ http://join/secondlife.com/
</url>
<usetemplate
name="okcancelbuttons"
diff --git a/indra/newview/skins/default/xui/en/panel_audio_device.xml b/indra/newview/skins/default/xui/en/panel_audio_device.xml
index 5f495ef8ce..4329982209 100644
--- a/indra/newview/skins/default/xui/en/panel_audio_device.xml
+++ b/indra/newview/skins/default/xui/en/panel_audio_device.xml
@@ -80,7 +80,7 @@
bg_readonly_color="0 0 0 0"
enabled="false"
height="60"
- hide_border="true"
+ border_visible="false"
hide_scrollbar="true"
layout="topleft"
left_delta="10"
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index d5ed0c986d..c3ae2d953a 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -62,7 +62,6 @@
auto_update="true"
follows="right"
draw_border="false"
- halign="left"
height="16"
layout="topleft"
left_pad="3"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index 0d6d8ba97d..b13058f40a 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -201,7 +201,7 @@
type="string"
follows="left|top"
font="SansSerifSmall"
- font.style="BOLD"
+ font.style="BOLD"
height="15"
layout="topleft"
left="10"
@@ -272,7 +272,7 @@
<text
follows="left|top"
font="SansSerifSmall"
- font.style="BOLD"
+ font.style="BOLD"
height="15"
layout="topleft"
left="10"
@@ -305,7 +305,7 @@
<text
follows="left|top"
font="SansSerifSmall"
- font.style="BOLD"
+ font.style="BOLD"
height="15"
layout="topleft"
left="10"
@@ -391,6 +391,7 @@
follows="left|top"
height="10"
layout="topleft"
+ font="SansSerifSmall"
font.style="BOLD"
left="12"
mouse_opaque="false"
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
index 069cf1d7bd..999aa814b1 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -55,7 +55,6 @@
<scroll_list
draw_heading="true"
follows="top"
- font="SansSerifSmall"
heading_height="14"
height="100"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index c96c296057..aeeb884036 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -9,7 +9,7 @@
width="800">
<panel.string
name="create_account_url">
- http://secondlife.com/registration/
+ http://join.secondlife.com/
</panel.string>
<panel.string
name="real_url">
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index 02d179d503..b4212aaa34 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -17,6 +17,10 @@
http://www.secondlife.com/account/billing.php?lang=en
</string>
<string
+ name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=en
+ </string>
+ <string
name="my_account_link_url"
value="http://secondlife.com/account" />
<string
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 9b2461db7c..9abaf29f57 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -82,7 +82,8 @@
name="progress_text"
text_color="LoginProgressBoxTextColor"
top_pad="5"
- width="593" />
+ width="593"
+ word_wrap="true"/>
<progress_bar
bottom="115"
color_bar="1 1 1 0.96"
@@ -100,11 +101,12 @@
height="100"
layout="topleft"
left="45"
- line_spacing="2"
+ line_spacing.pixels="2"
name="message_text"
text_color="LoginProgressBoxTextColor"
top="145"
- width="550" />
+ width="550"
+ word_wrap="true"/>
</layout_panel>
<layout_panel
height="200"
diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml
index a3c714ce72..765e2ae623 100644
--- a/indra/newview/skins/default/xui/en/panel_script_ed.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -32,8 +32,6 @@
<text_editor
type="string"
length="1"
- bevel_style="none"
- border_style="line"
bottom="393"
follows="left|top|right|bottom"
font="Monospace"
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index 418b88b7b5..d172154d49 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -21,7 +21,6 @@
filename="panel_sidetray_home_tab.xml"
label="home"
border="true"
- font="SansSerifBold"
/>
</sidetray_tab>
@@ -44,14 +43,12 @@
name="panel_people"
filename="panel_people.xml"
border="true"
- font="SansSerifBold"
/>
<panel
class="panel_profile_view"
name="panel_profile_view"
filename="panel_profile_view.xml"
border="true"
- font="SansSerifBold"
/>
<panel
class="panel_group_info_sidetray"
@@ -107,7 +104,6 @@
filename="panel_me_profile.xml"
label="Me"
border="true"
- font="SansSerifBold"
/>
</sidetray_tab>
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index f6ffd2e4ee..07f0806ccb 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -58,7 +58,7 @@
<text
type="string"
length="1"
- disabled_color="TimeTextColor"
+ text_readonly_color="TimeTextColor"
follows="right|bottom"
halign="right"
height="16"
@@ -100,9 +100,8 @@
visible="false"
width="16" />
<text
- type="string"
- length="1"
- disabled_color="HealthTextColor"
+ bg_visible="false"
+ text_readonly_color="HealthTextColor"
follows="rsight|bottom"
font_shadow="hard"
height="16"
diff --git a/indra/newview/skins/default/xui/en/panel_world_map.xml b/indra/newview/skins/default/xui/en/panel_world_map.xml
index ee355fa95c..9f08d3a817 100644
--- a/indra/newview/skins/default/xui/en/panel_world_map.xml
+++ b/indra/newview/skins/default/xui/en/panel_world_map.xml
@@ -51,7 +51,6 @@
label="N"
layout="topleft"
name="floater_map_north"
- text="N"
text_color="1 1 1 0.7">
N
</text>
@@ -61,7 +60,6 @@
label="E"
layout="topleft"
name="floater_map_east"
- text="E"
text_color="1 1 1 0.7">
E
</text>
@@ -71,7 +69,6 @@
label="W"
layout="topleft"
name="floater_map_west"
- text="W"
text_color="1 1 1 0.7">
W
</text>
@@ -81,7 +78,6 @@
label="S"
layout="topleft"
name="floater_map_south"
- text="S"
text_color="1 1 1 0.7">
S
</text>
@@ -91,7 +87,6 @@
label="SE"
layout="topleft"
name="floater_map_southeast"
- text="SE"
text_color="1 1 1 0.7">
SE
</text>
@@ -101,7 +96,6 @@
label="NE"
layout="topleft"
name="floater_map_northeast"
- text="NE"
text_color="1 1 1 0.7">
NE
</text>
@@ -111,7 +105,6 @@
label="SW"
layout="topleft"
name="floater_map_southwest"
- text="SW"
text_color="1 1 1 0.7">
SW
</text>
@@ -121,7 +114,6 @@
label="NW"
layout="topleft"
name="floater_map_northwest"
- text="NW"
text_color="1 1 1 0.7">
NW
</text>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index f398cc33b5..3a5347fe12 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -15,9 +15,6 @@
<string name="StartupDetectingHardware">Detecting hardware...</string>
<string name="StartupLoading">Loading</string>
<string name="Fullbright">Fullbright (Legacy)</string>
- <string name="CacheWaiting">(Loading...)</string>
- <string name="CacheNobody">(nobody)</string>
- <string name="CacheNone">(none)</string>
<!-- Login -->
<string name="LoginInProgress">Logging in. [APP_NAME] may appear frozen. Please wait.</string>
<string name="LoginInProgressNoFrozen">Logging in...</string>
@@ -40,13 +37,14 @@
<string name="LoginDownloadingClothing">Downloading clothing...</string>
<string name="LoginFailedNoNetwork">Network Error: Could not establish connection, please check your network connection.</string>
<string name="Quit">Quit</string>
- <string name="create_account_url">http://secondlife.com/registration/</string>
+ <string name="create_account_url">http://join.secondlife.com/</string>
<!-- Disconnection -->
<string name="AgentLostConnection">This region may be experiencing trouble. Please check your connection to the Internet.</string>
<!-- Tooltip, lltooltipview.cpp -->
+ <!-- *TODO: Most of these are now unused, eliminate them -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
<string name="TooltipOwner">Owner:</string> <!-- Owner name follows -->
@@ -118,7 +116,10 @@
<!-- Avatar name: text shown while fetching name -->
<string name="AvatarNameWaiting">(waiting)</string>
- <!-- Avatar name: text shown as an alternative to AvatarNameFetching, easter egg. -->
+ <!-- Avatar name: More than one avatar is selected/used here -->
+ <string name="AvatarNameMultiple">(multiple)</string>
+
+ <!-- Avatar name: text shown as an alternative to AvatarNameFetching, easter egg. -->
<string name="AvatarNameHippos">(hippos)</string>
<!-- Group name: text shown for LLUUID::null -->
@@ -1931,21 +1932,24 @@ this texture in your inventory
<string name="Left Pec">Left Pec</string>
<string name="Right Pec">Right Pec</string>
- <!-- Avatar age computation, see LLAvatarPropertiesProcessor::ageFromDate -->
- <string name="YearsMonthsOld">[AGEYEARS][AGEMONTHS]old</string>
- <string name="WeeksOld">[AGEWEEKS]old</string>
- <string name="DaysOld">[AGEDAYS]old</string>
+ <!-- Avatar age computation, see LLDateUtil::ageFromDate -->
+ <string name="YearsMonthsOld">[AGEYEARS] [AGEMONTHS] old</string>
+ <string name="YearsOld">[AGEYEARS] old</string>
+ <string name="MonthsOld">[AGEMONTHS] old</string>
+ <string name="WeeksOld">[AGEWEEKS] old</string>
+ <string name="DaysOld">[AGEDAYS] old</string>
<string name="TodayOld">Joined today</string>
- <!-- Use value="" because of trailing spaces -->
- <string name="AgeYears" value="[YEARS] years " />
- <string name="Age1Year" value="1 year "/>
- <string name="AgeMonths" value="[MONTHS] months "/>
- <string name="Age1Month" value="1 month "/>
- <string name="AgeWeeks" value="[WEEKS] weeks "/>
- <string name="Age1Week" value="1 week "/>
- <string name="AgeDays" value="[DAYS] days "/>
- <string name="Age1Day" value="1 day "/>
+ <!-- AgeYearsA = singular, AgeYearsB = plural, see logic in
+ LLTrans::getCountString() -->
+ <string name="AgeYearsA">[COUNT] year</string>
+ <string name="AgeYearsB">[COUNT] years</string>
+ <string name="AgeMonthsA">[COUNT] month</string>
+ <string name="AgeMonthsB">[COUNT] months</string>
+ <string name="AgeWeeksA">[COUNT] week</string>
+ <string name="AgeWeeksB">[COUNT] weeks</string>
+ <string name="AgeDaysA">[COUNT] day</string>
+ <string name="AgeDaysB">[COUNT] days</string>
<!-- Account types, see LLAvatarPropertiesProcessor -->
<string name="AcctTypeResident">Resident</string>
@@ -1995,8 +1999,8 @@ this texture in your inventory
<!-- groups -->
<string name="GroupsNone">none</string>
- <string name="Group" value=" (group)" />
- <string name="Unknown">(Unknown)</string>
+ <string name="Group" value=" (group)" />
+ <string name="Unknown">(Unknown)</string>
<string name="SummaryForTheWeek" value="Summary for this week, beginning on " />
<string name="NextStipendDay" value="The next stipend day is " />
<string name="GroupIndividualShare" value=" Group Individual Share" />
diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
index 8b4126952e..546fbd9b47 100644
--- a/indra/newview/skins/default/xui/en/widgets/line_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<line_editor
- background_image="TextField_Off"
- background_image_disabled="TextField_Disabled"
- background_image_focused="TextField_Active"
+<line_editor background_image="TextField_Off"
+ background_image_disabled="TextField_Disabled"
+ background_image_focused="TextField_Active"
select_on_focus="false"
handle_edit_keys_directly="false"
commit_on_focus_lost="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
index 4f2261c953..8ace7b96bc 100644
--- a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
@@ -1,22 +1,26 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<simple_text_editor
+ allow_html="false"
mouse_opaque="true"
font="SansSerifSmall"
max_length="255"
embedded_items="false"
hide_scrollbar="false"
- hide_border="true"
+ border_visible="false"
word_wrap="false"
ignore_tab="true"
+ line_spacing.pixels="1"
track_bottom="false"
cursor_color="TextCursorColor"
default_color="TextDefaultColor"
text_color="TextFgColor"
text_readonly_color="TextFgReadOnlyColor"
+ h_pad="5"
+ v_pad="3"
+ bg_visible="true"
bg_readonly_color="TextBgReadOnlyColor"
bg_writeable_color="TextBgWriteableColor"
- bg_focus_color="TextBgFocusColor"
- link_color="HTMLLinkColor">
+ bg_focus_color="TextBgFocusColor">
<simple_text_editor.border
bevel_style="in"
follows="all" />
diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml
index 3d98cd66f9..7d78a8fa20 100644
--- a/indra/newview/skins/default/xui/en/widgets/text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/text.xml
@@ -1,16 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<text name="text_box"
+<text allow_html="true"
+ clip_to_rect="false"
+ name="text_box"
font="SansSerifSmall"
font_shadow="soft"
tab_stop="false"
halign="left"
hover_color="LabelSelectedColor"
- disabled_color="LabelDisabledColor"
- background_color="FloaterDefaultBackgroundColor"
+ h_pad="-1"
+ hide_scrollbar="true"
+ text_readonly_color="LabelDisabledColor"
+ bg_writeable_color="FloaterDefaultBackgroundColor"
border_color="DefaultHighlightLight"
use_ellipses="false"
bg_visible="false"
- border_drop_shadow_visible="false"
border_visible="false"
hover="false"
- text_color="LabelTextColor"/>
+ text_color="LabelTextColor"
+ v_pad="-1"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/text_editor.xml b/indra/newview/skins/default/xui/en/widgets/text_editor.xml
index deaade04f8..23ca8ea338 100644
--- a/indra/newview/skins/default/xui/en/widgets/text_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/text_editor.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<!-- Core parameters are in simple_text_editor.xml -->
<text_editor
- allow_html="false" />
+ allow_html="false"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/textbase.xml b/indra/newview/skins/default/xui/en/widgets/textbase.xml
new file mode 100644
index 0000000000..c352abca3b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/textbase.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<textbase clip_to_rect="true"
+ h_pad="4"
+ v_pad="4"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_telehub.xml b/indra/newview/skins/default/xui/nl/floater_telehub.xml
index 5a8abc208a..8fe8e06c03 100644
--- a/indra/newview/skins/default/xui/nl/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/nl/floater_telehub.xml
@@ -17,7 +17,7 @@
<text name="spawn_points_text">
Spawnpunten (posities, niet objecten):
</text>
- <scroll_list bottom_delta="-44" draw_border="true" follows="left|top" font="SansSerifSmall"
+ <scroll_list bottom_delta="-44" draw_border="true" follows="left|top"
height="40" left="10" multi_select="false" name="spawn_points_list"
width="230" />
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
new file mode 100644
index 0000000000..30e39a3bcf
--- /dev/null
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -0,0 +1,159 @@
+/**
+ * @file lldateutil_test.cpp
+ *
+ * $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 "../test/lltut.h"
+
+#include "../lldateutil.h"
+
+#include "lldate.h"
+#include "llstring.h" // LLStringUtil::format()
+#include "lltrans.h"
+#include "llui.h"
+
+#include <map>
+
+
+// Baked-in return values for getString()
+std::map< std::string, std::string > gString;
+
+// Baked-in return values for getCountString()
+// map of pairs of input xml_desc and integer count
+typedef std::pair< std::string, int > count_string_t;
+std::map< count_string_t, std::string > gCountString;
+
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args)
+{
+ std::string text = gString[xml_desc];
+ LLStringUtil::format(text, args);
+ return text;
+}
+
+std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+{
+ return gCountString[ count_string_t(xml_desc, count) ];
+}
+
+std::string LLUI::getLanguage()
+{
+ return "en";
+}
+
+namespace tut
+{
+ struct dateutil
+ {
+ // Hard-code a "now" date so unit test doesn't change with
+ // current time. Because server strings are in Pacific time
+ // roll this forward 8 hours to compensate. This represents
+ // 2009-12-31T00:00:00Z UTC.
+ dateutil()
+ : mNow(std::string("2009-12-31T08:00:00Z"))
+ {
+ // copied from strings.xml
+ gString["YearsMonthsOld"] = "[AGEYEARS] [AGEMONTHS] old";
+ gString["YearsOld"] = "[AGEYEARS] old";
+ gString["MonthsOld"] = "[AGEMONTHS] old";
+ gString["WeeksOld"] = "[AGEWEEKS] old";
+ gString["DaysOld"] = "[AGEDAYS] old";
+ gString["TodayOld"] = "Joined today";
+
+ gCountString[ count_string_t("AgeYears", 1) ] = "1 year";
+ gCountString[ count_string_t("AgeYears", 2) ] = "2 years";
+ gCountString[ count_string_t("AgeMonths", 1) ] = "1 month";
+ gCountString[ count_string_t("AgeMonths", 2) ] = "2 months";
+ gCountString[ count_string_t("AgeWeeks", 1) ] = "1 week";
+ gCountString[ count_string_t("AgeWeeks", 2) ] = "2 weeks";
+ gCountString[ count_string_t("AgeDays", 1) ] = "1 day";
+ gCountString[ count_string_t("AgeDays", 2) ] = "2 days";
+ }
+ LLDate mNow;
+ };
+
+ typedef test_group<dateutil> dateutil_t;
+ typedef dateutil_t::object dateutil_object_t;
+ tut::dateutil_t tut_dateutil("dateutil");
+
+ template<> template<>
+ void dateutil_object_t::test<1>()
+ {
+ set_test_name("Years");
+ ensure_equals("years + months",
+ LLDateUtil::ageFromDate("10/30/2007", mNow),
+ "2 years 2 months old" );
+ ensure_equals("years",
+ LLDateUtil::ageFromDate("12/31/2007", mNow),
+ "2 years old" );
+ ensure_equals("single year",
+ LLDateUtil::ageFromDate("12/31/2008", mNow),
+ "1 year old" );
+ ensure_equals("single year + a bit",
+ LLDateUtil::ageFromDate("12/12/2008", mNow),
+ "1 year old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<2>()
+ {
+ set_test_name("Months");
+ ensure_equals("months",
+ LLDateUtil::ageFromDate("10/30/2009", mNow),
+ "2 months old" );
+ ensure_equals("single month",
+ LLDateUtil::ageFromDate("11/30/2009", mNow),
+ "1 month old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<3>()
+ {
+ set_test_name("Weeks");
+ ensure_equals("weeks",
+ LLDateUtil::ageFromDate("12/17/2009", mNow),
+ "2 weeks old" );
+ ensure_equals("single week",
+ LLDateUtil::ageFromDate("12/24/2009", mNow),
+ "1 week old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<4>()
+ {
+ set_test_name("Days");
+ ensure_equals("days",
+ LLDateUtil::ageFromDate("12/29/2009", mNow),
+ "2 days old" );
+ ensure_equals("single day",
+ LLDateUtil::ageFromDate("12/30/2009", mNow),
+ "1 day old" );
+ ensure_equals("today",
+ LLDateUtil::ageFromDate("12/31/2009", mNow),
+ "Joined today" );
+ }
+}
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index ba81c6e49e..2f50d872ee 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -136,12 +136,9 @@ public:
run_completed_(*mStream);
}
run_completed_(std::cout);
-
- if (mFailedTests > 0)
- {
- exit(1);
- }
}
+
+ int getFailedTests() const { return mFailedTests; }
private:
void run_completed_(std::ostream &stream)
@@ -340,9 +337,11 @@ int main(int argc, char **argv)
tut::runner.get().run_tests(test_group);
}
+ bool success = (callback.getFailedTests() == 0);
+
if (wait_at_exit)
{
- std::cerr << "Waiting for input before exiting..." << std::endl;
+ std::cerr << "Press return to exit..." << std::endl;
std::cin.get();
}
@@ -352,7 +351,7 @@ int main(int argc, char **argv)
delete output;
}
- if (touch)
+ if (touch && success)
{
std::ofstream s;
s.open(touch);
@@ -361,5 +360,7 @@ int main(int argc, char **argv)
}
apr_terminate();
- return 0;
+
+ int retval = (success ? 0 : 1);
+ return retval;
}