diff options
author | Monroe Linden <monroe@lindenlab.com> | 2009-10-05 15:50:24 -0700 |
---|---|---|
committer | Monroe Linden <monroe@lindenlab.com> | 2009-10-05 15:50:24 -0700 |
commit | 39ee2367a7e771890017fc3d663780437ea69bb2 (patch) | |
tree | b84c3ade59dba5ae032a3123afb9c3c5f78c9b68 /indra | |
parent | 374deb8da13c63f80dc1b245488eb254eb86f5d2 (diff) | |
parent | 6ef3f20933c5df684298bc1b8f338ce9dfd49070 (diff) |
Merging due to changes since my last pull.
Diffstat (limited to 'indra')
292 files changed, 9364 insertions, 6227 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 2a0c0d8d29..5c4831cc2b 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -61,21 +61,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 ccea101cd6..e69ca7eec5 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 = 2639; -const char * const LL_CHANNEL = "Second Life 2009"; +const char * const LL_CHANNEL = "Second Life Developer"; #endif diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp index 62504be3b0..8ca3c56022 100644 --- a/indra/llprimitive/tests/llmessagesystem_stub.cpp +++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp @@ -1,23 +1,11 @@ -/** +/** * @file llmessagesystem_stub.cpp - * @brief stub class to allow unit testing * - * $LicenseInfo:firstyear=2008&license=internal$ - * - * Copyright (c) 2008, Linden Research, Inc. - * - * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of - * this source code is governed by the Linden Lab Source Code Disclosure - * Agreement ("Agreement") { } - * Lab. By accessing, using, copying, modifying or distributing this - * software, you acknowledge that you have been informed of your - * obligations under the Agreement and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * Copyright (c) 2008-2009, Linden Research, Inc. + * $/LicenseInfo$ */ + #include "linden_common.h" char * _PREHASH_TextureEntry; 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/llrender/llfontgl.h b/indra/llrender/llfontgl.h index af8e0909af..ad84b6d641 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -72,11 +72,10 @@ public: enum StyleFlags { // text style to render. May be combined (these are bit flags) - // TODO:: Maybe change the value to 0x01 << 0 for 1 0x01 << 1 for 2, 0x01 << 2 for 4 - NORMAL = 0, - BOLD = 1, - ITALIC = 2, - UNDERLINE = 4 + NORMAL = 0x00, + BOLD = 0x01, + ITALIC = 0x02, + UNDERLINE = 0x04 }; enum ShadowType 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..d742281f30 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; @@ -207,7 +189,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params)); // move text over to fit image in - mTextBox->translate(TOOLTIP_ICON_SIZE,0); + mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0); } if (p.click_callback.isProvided()) @@ -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 4482a75405..50be55e9d0 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 @@ -262,8 +264,7 @@ set(viewer_SOURCE_FILES llmaniptranslate.cpp llmapresponders.cpp llmediactrl.cpp - llmediadataresponder.cpp - llmediadatafetcher.cpp + llmediadataclient.cpp llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp @@ -395,7 +396,6 @@ set(viewer_SOURCE_FILES lltoastimpanel.cpp lltoastnotifypanel.cpp lltoastpanel.cpp - lltoggleablemenu.cpp lltoolbar.cpp lltoolbrush.cpp lltoolcomp.cpp @@ -576,6 +576,7 @@ set(viewer_HEADER_FILES llconfirmationmanager.h llcurrencyuimanager.h llcylinder.h + lldateutil.h lldebugmessagebox.h lldebugview.h lldelayedgestureerror.h @@ -711,6 +712,7 @@ set(viewer_HEADER_FILES llimview.h llimcontrolpanel.h llinspectavatar.h + llinspectobject.h llinventorybridge.h llinventoryclipboard.h llinventoryfilter.h @@ -732,8 +734,7 @@ set(viewer_HEADER_FILES llmanipscale.h llmaniptranslate.h llmapresponders.h - llmediadataresponder.h - llmediadatafetcher.h + llmediadataclient.h llmediaremotectrl.h llmemoryview.h llmenucommands.h @@ -865,7 +866,6 @@ set(viewer_HEADER_FILES lltoastimpanel.h lltoastnotifypanel.h lltoastpanel.h - lltoggleablemenu.h lltool.h lltoolbar.h lltoolbrush.h @@ -1538,9 +1538,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/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index a49ccb77b4..d7bb64ce8a 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -40,7 +40,6 @@ </array> <key>tags</key> <array> - <string>ShaderLoading</string> </array> </map> </array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 99b662a63f..7f96e0761e 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> @@ -5294,7 +5294,7 @@ <key>Value</key> <integer>13</integer> </map> - <key>PrimMediaFetchQueueDelay</key> + <key>PrimMediaRequestQueueDelay</key> <map> <key>Comment</key> <string>Timer delay for fetching media from the queue (in seconds).</string> @@ -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..f58c85d8c5 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -42,12 +42,17 @@ #include "llavatarconstants.h" // AVATAR_TRANSACTED, etc. #include "lldate.h" #include "lltrans.h" +#include "llui.h" // LLUI::getLanguage() #include "message.h" LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor() { } +LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor() +{ +} + void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer) { // Check if that observer is already in mObservers for that avatar_id @@ -172,103 +177,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/llface.cpp b/indra/newview/llface.cpp index a5b0b05603..b0ae13348b 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -272,12 +272,12 @@ void LLFace::setTexture(LLViewerTexture* tex) removeAtlas() ; } - mTexture = tex ; - - if(mTexture.notNull()) + if(tex) { - mTexture->addFace(this) ; - } + tex->addFace(this) ; + } + + mTexture = tex ; } void LLFace::switchTexture(LLViewerTexture* new_texture) 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/llfolderview.cpp b/indra/newview/llfolderview.cpp index d149c8bbb5..3fd0875709 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -213,7 +213,7 @@ LLFolderView::LLFolderView(const Params& p) LLLineEditor::Params params; params.name("ren"); params.rect(getRect()); - params.font(sFont); + params.font(getLabelFontForStyle(LLFontGL::NORMAL)); params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN); params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); params.prevalidate_callback(&LLLineEditor::prevalidatePrintableNotPipe); @@ -832,6 +832,8 @@ void LLFolderView::draw() LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + // if cursor has moved off of me during drag and drop // close all auto opened folders if (!mDragAndDropThisFrame) @@ -873,12 +875,12 @@ void LLFolderView::draw() if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) { mStatusText = LLTrans::getString("Searching"); - sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } else { mStatusText = LLTrans::getString("InventoryNoMatchingItems"); - sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } } @@ -1814,7 +1816,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = llround(sFont->getLineHeight()); + S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder S32 max_height_to_show = mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); @@ -2123,8 +2125,10 @@ void LLFolderView::updateRenamerPosition() { if(mRenameItem) { + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + mRenameItem->getIndentation(); - S32 y = llfloor(mRenameItem->getRect().getHeight()-sFont->getLineHeight()-2); + S32 y = llfloor(mRenameItem->getRect().getHeight() - font->getLineHeight()-2); mRenameItem->localPointToScreen( x, y, &x, &y ); screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); @@ -2136,7 +2140,7 @@ void LLFolderView::updateRenamerPosition() } S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD); + S32 height = llfloor(font->getLineHeight() + RENAME_HEIGHT_PAD); mRenamer->reshape( width, height, TRUE ); } } @@ -2176,12 +2180,6 @@ PermissionMask LLFolderView::getFilterPermissions() const return mFilter->getFilterPermissions(); } -// JAMESDEBUG -//LLInventoryFilter::EFolderShow LLFolderView::getShowFolderState() -//{ -// return mFilter->getShowFolderState(); -//} - BOOL LLFolderView::isFilterModified() { return mFilter->isNotDefault(); diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 490929e5a6..ee5fba5ace 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -51,7 +51,7 @@ ///---------------------------------------------------------------------------- // statics -const LLFontGL* LLFolderViewItem::sFont = NULL; +std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts const LLFontGL* LLFolderViewItem::sSmallFont = NULL; LLUIImagePtr LLFolderViewItem::sArrowImage; LLUIImagePtr LLFolderViewItem::sBoxImage; @@ -63,9 +63,21 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; const LLColor4U DEFAULT_WHITE(255, 255, 255); //static +LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) +{ + LLFontGL* rtn = sFonts[style]; + if (!rtn) // grab label font with this style, lazily + { + LLFontDescriptor labelfontdesc("SansSerif", "Small", style); + rtn = LLFontGL::getFont(labelfontdesc); + sFonts[style] = rtn; + } + return rtn; +} + +//static void LLFolderViewItem::initClass() { - sFont = LLFontGL::getFontSansSerifSmall(); sSmallFont = LLFontGL::getFontMonospace(); sArrowImage = LLUI::getUIImage("folder_arrow.tga"); sBoxImage = LLUI::getUIImage("rounded_square.tga"); @@ -74,6 +86,7 @@ void LLFolderViewItem::initClass() //static void LLFolderViewItem::cleanupClass() { + sFonts.clear(); sArrowImage = NULL; sBoxImage = NULL; } @@ -365,7 +378,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) mIndentation = mParentFolder ? mParentFolder->getIndentation() + LEFT_INDENTATION : 0; if (mLabelWidthDirty) { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + sFont->getWidth(mSearchableLabel); + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mSearchableLabel); mLabelWidthDirty = false; } @@ -377,7 +390,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) S32 LLFolderViewItem::getItemHeight() { S32 icon_height = mIcon->getHeight(); - S32 label_height = llround(sFont->getLineHeight()); + S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); return llmax( icon_height, label_height ) + ICON_PAD; } @@ -563,7 +576,7 @@ const std::string& LLFolderViewItem::getSearchableLabel() const return mSearchableLabel; } -const std::string& LLFolderViewItem::getName( void ) const +std::string LLFolderViewItem::getName( void ) const { if(mListener) { @@ -795,6 +808,8 @@ void LLFolderViewItem::draw() F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + // If we have keyboard focus, draw selection filled BOOL show_context = getRoot()->getShowSelectionContext(); BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); @@ -826,7 +841,7 @@ void LLFolderViewItem::draw() 0, getRect().getHeight(), getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), bg_color, filled); if (mIsCurSelection) { @@ -834,14 +849,14 @@ void LLFolderViewItem::draw() 0, getRect().getHeight(), getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), sHighlightFgColor, FALSE); } - if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 2) { gl_rect_2d( 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, getRect().getWidth() - 2, 2, sHighlightFgColor, FALSE); @@ -849,7 +864,7 @@ void LLFolderViewItem::draw() { gl_rect_2d( 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, getRect().getWidth() - 2, 2, sHighlightBgColor, TRUE); @@ -863,14 +878,14 @@ void LLFolderViewItem::draw() 0, getRect().getHeight(), getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), sHighlightBgColor, FALSE); - if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 2) { gl_rect_2d( 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, getRect().getWidth() - 2, 2, sHighlightBgColor, FALSE); @@ -890,7 +905,7 @@ void LLFolderViewItem::draw() BOOL debug_filters = getRoot()->getDebugFilters(); LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); F32 right_x; - F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD; if (debug_filters) { @@ -910,18 +925,18 @@ void LLFolderViewItem::draw() if ( mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime") ) { - sFont->renderUTF8(LLTrans::getString("LoadingData"), 0, text_left, y, sSearchStatusColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE); + font->renderUTF8(LLTrans::getString("LoadingData"), 0, text_left, y, sSearchStatusColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE); text_left = right_x; } - sFont->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + font->renderUTF8( mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); if (!mLabelSuffix.empty()) { - sFont->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } @@ -932,33 +947,21 @@ void LLFolderViewItem::draw() if (filter_string_length > 0) { std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - sFont->getLineHeight() - 3); + S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3); S32 top = getRect().getHeight(); LLRect box_rect(left, top, right, bottom); sBoxImage->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD; + font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } } } - - 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..e9aab560c8 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -125,7 +125,6 @@ protected: LLFolderViewItem(Params p = LLFolderViewItem::Params()); - static const LLFontGL* sFont; static const LLFontGL* sSmallFont; static LLUIImagePtr sArrowImage; static LLUIImagePtr sBoxImage; @@ -169,6 +168,8 @@ protected: virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } + static LLFontGL* getLabelFontForStyle(U8 style); + public: // This function clears the currently selected item, and records // the specified selected item appropriately for display and use @@ -255,7 +256,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; @@ -322,6 +323,9 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + + private: + static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts }; 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..9b75c15597 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. } @@ -113,18 +218,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 +264,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 +284,8 @@ void LLInspectAvatar::onOpen(const LLSD& data) // can't call from constructor as widgets are not built yet requestUpdate(); + + updateVolumeSlider(); } //virtual @@ -167,6 +293,7 @@ void LLInspectAvatar::onFocusLost() { // Start closing when we lose focus mCloseTimer.start(); + mOpenTimer.stop(); } void LLInspectAvatar::requestUpdate() @@ -178,7 +305,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 +315,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 +342,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/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp new file mode 100644 index 0000000000..6a932d76bf --- /dev/null +++ b/indra/newview/llmediadataclient.cpp @@ -0,0 +1,627 @@ +/** + * @file llmediadataclient.cpp + * @brief class for queueing up requests for media data + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmediadataclient.h" + +#include <boost/lexical_cast.hpp> + +#include "llhttpstatuscodes.h" +#include "llnotifications.h" +#include "llsdutil.h" +#include "llmediaentry.h" +#include "lltextureentry.h" +#include "llviewerregion.h" +#include "llvovolume.h" + +// +// When making a request +// - obtain the "overall interest score" of the object. +// This would be the sum of the impls' interest scores. +// - put the request onto a queue sorted by this score +// (highest score at the front of the queue) +// - On a timer, once a second, pull off the head of the queue and send +// the request. +// - Any request that gets a 503 still goes through the retry logic +// + +// Some helpful logging macros + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Request +// +////////////////////////////////////////////////////////////////////////////////////// +/*static*/U32 LLMediaDataClient::Request::sNum = 0; + +LLMediaDataClient::Request::Request(const std::string &cap_name, + const LLSD& sd_payload, + LLVOVolume *obj, + LLMediaDataClient *mdc) + : mCapName(cap_name), + mPayload(sd_payload), + mObject(obj), + mNum(++sNum), + mRetryCount(0), + mMDC(mdc) +{ +} + +LLMediaDataClient::Request::~Request() +{ + mMDC = NULL; + mObject = NULL; +} + + +std::string LLMediaDataClient::Request::getCapability() const +{ + return getObject()->getRegion()->getCapability(getCapName()); +} + +// Helper function to get the "type" of request, which just pokes around to +// discover it. +LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const +{ + if (mCapName == "ObjectMediaNavigate") + { + return NAVIGATE; + } + else if (mCapName == "ObjectMedia") + { + const std::string &verb = mPayload["verb"]; + if (verb == "GET") + { + return GET; + } + else if (verb == "UPDATE") + { + return UPDATE; + } + } + llassert(false); + return GET; +} + +const char *LLMediaDataClient::Request::getTypeAsString() const +{ + Type t = getType(); + switch (t) + { + case GET: + return "GET"; + break; + case UPDATE: + return "UPDATE"; + break; + case NAVIGATE: + return "NAVIGATE"; + break; + } + return ""; +} + + +void LLMediaDataClient::Request::reEnqueue() const +{ + // I sure hope this doesn't deref a bad pointer: + mMDC->enqueue(this); +} + +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) +{ + s << "<request>" + << "<num>" << r.getNum() << "</num>" + << "<type>" << r.getTypeAsString() << "</type>" + << "<object_id>" << r.getObject()->getID() << "</object_id>" + << "<num_retries>" << r.getRetryCount() << "</num_retries>" + << "</request> "; + return s; +} + + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Responder::RetryTimer +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) + : LLEventTimer(time), mResponder(mdr) +{ +} + +// virtual +LLMediaDataClient::Responder::RetryTimer::~RetryTimer() +{ + mResponder = NULL; +} + +// virtual +BOOL LLMediaDataClient::Responder::RetryTimer::tick() +{ + // Instead of retrying, we just put the request back onto the queue + LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL; + mResponder->getRequest()->reEnqueue(); + // Don't fire again + return TRUE; +} + + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Responder +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::Responder::Responder(const request_ptr_t &request) + : mRequest(request) +{ +} + +LLMediaDataClient::Responder::~Responder() +{ + mRequest = NULL; +} + +/*virtual*/ +void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) +{ + extern LLControlGroup gSavedSettings; + + if (status == HTTP_SERVICE_UNAVAILABLE) + { + F32 retry_timeout = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + if (retry_timeout <= 0.0) + { + retry_timeout = (F32)UNAVAILABLE_RETRY_TIMER_DELAY; + } + LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; + + mRequest->incRetryCount(); + + // Start timer (instances are automagically tracked by + // InstanceTracker<> and LLEventTimer) + new RetryTimer(F32(retry_timeout/*secs*/), this); + } + else { + std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; + LL_INFOS("LLMediaDataClient") << *mRequest << " error(" << msg << ")" << LL_ENDL; + LLSD args; + args["ERROR"] = msg; + LLNotifications::instance().add("ObjectMediaFailure", args); + } +} + + +/*virtual*/ +void LLMediaDataClient::Responder::result(const LLSD& content) +{ + LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_pretty_print_sd(content) << LL_ENDL; +} + + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Comparator +// +////////////////////////////////////////////////////////////////////////////////////// + +bool LLMediaDataClient::Comparator::operator() (const request_ptr_t &o1, const request_ptr_t &o2) const +{ + if (o2.isNull()) return true; + if (o1.isNull()) return false; + + // The score is intended to be a measure of how close an object is or + // how much screen real estate (interest) it takes up + // Further away = lower score. + // Lesser interest = lower score + // For instance, here are some cases: + // 1: Two items with no impl, closest one wins + // 2: Two items with an impl: interest should rule, but distance is + // still taken into account (i.e. something really close might take + // precedence over a large item far away) + // 3: One item with an impl, another without: item with impl wins + // (XXX is that what we want?) + // Calculate the scores for each. + F64 o1_score = Comparator::getObjectScore(o1->getObject()); + F64 o2_score = Comparator::getObjectScore(o2->getObject()); + + return ( o1_score > o2_score ); +} + +// static +F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj) +{ + // *TODO: make this less expensive? + F32 dist = obj->getRenderPosition().length() + 0.1; // avoids div by 0 + // square the distance so that they are in the same "unit magnitude" as + // the interest (which is an area) + dist *= dist; + F64 interest = (F64)1; + int i = 0; + int end = obj->getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = obj->getMediaImpl(i); + if (!impl.isNull()) + { + interest += impl->getInterest(); + } + } + + return interest/dist; +} + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::PriorityQueue +// Queue of LLVOVolume smart pointers to request media for. +// +////////////////////////////////////////////////////////////////////////////////////// + +// dump the queue +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::PriorityQueue &q) +{ + int i = 0; + std::vector<LLMediaDataClient::request_ptr_t>::const_iterator iter = q.c.begin(); + std::vector<LLMediaDataClient::request_ptr_t>::const_iterator end = q.c.end(); + while (iter < end) + { + s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString(); + iter++; + i++; + } + return s; +} + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::QueueTimer +// Queue of LLVOVolume smart pointers to request media for. +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc) + : LLEventTimer(time), mMDC(mdc) +{ + mMDC->setIsRunning(true); +} + +LLMediaDataClient::QueueTimer::~QueueTimer() +{ + mMDC->setIsRunning(false); + mMDC = NULL; +} + +// virtual +BOOL LLMediaDataClient::QueueTimer::tick() +{ + if (NULL == mMDC->pRequestQueue) + { + // Shutting down? stop. + LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL; + return TRUE; + } + + LLMediaDataClient::PriorityQueue &queue = *(mMDC->pRequestQueue); + + if (queue.empty()) + { + LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL; + return TRUE; + } + + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL; + + // Peel one off of the items from the queue, and execute request + request_ptr_t request = queue.top(); + llassert(!request.isNull()); + const ll_vo_volume_ptr_t &object = request->getObject(); + bool performed_request = false; + llassert(!object.isNull()); + if (!object.isNull() && object->hasMedia()) + { + std::string url = request->getCapability(); + if (!url.empty()) + { + const LLSD &sd_payload = request->getPayload(); + LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; + + // Call the subclass for creating the responder + LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request)); + performed_request = true; + } + else { + LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; + } + } + else { + if (!object->hasMedia()) + { + LL_INFOS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; + } + } + bool exceeded_retries = request->getRetryCount() > LLMediaDataClient::MAX_RETRIES; + if (performed_request || exceeded_retries) // Try N times before giving up + { + if (exceeded_retries) + { + LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << LLMediaDataClient::MAX_RETRIES << " tries...popping object id " << object->getID() << LL_ENDL; + // XXX Should we bring up a warning dialog?? + } + queue.pop(); + } + else { + request->incRetryCount(); + } + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL; + + return queue.empty(); +} + +void LLMediaDataClient::startQueueTimer() +{ + if (! mQueueTimerIsRunning) + { + extern LLControlGroup gSavedSettings; + F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + if (queue_timer_delay <= 0.0f) + { + queue_timer_delay = (F32)LLMediaDataClient::QUEUE_TIMER_DELAY; + } + LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << queue_timer_delay << " seconds)" << LL_ENDL; + // LLEventTimer automagically takes care of the lifetime of this object + new QueueTimer(queue_timer_delay, this); + } +} + +void LLMediaDataClient::stopQueueTimer() +{ + mQueueTimerIsRunning = false; +} + +void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload) +{ + if (NULL == object || ! object->hasMedia()) return; + + // Push the object on the priority queue + enqueue(new Request(getCapabilityName(), payload, object, this)); +} + +void LLMediaDataClient::enqueue(const Request *request) +{ + LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL; + // Push the request on the priority queue + // Sadly, we have to const-cast because items put into the queue are not const + pRequestQueue->push(const_cast<LLMediaDataClient::Request*>(request)); + LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL; + // Start the timer if not already running + startQueueTimer(); +} + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::LLMediaDataClient() +{ + pRequestQueue = new PriorityQueue(); +} + + +LLMediaDataClient::~LLMediaDataClient() +{ + stopQueueTimer(); + + // This should clear the queue, and hopefully call all the destructors. + while (! pRequestQueue->empty()) pRequestQueue->pop(); + + delete pRequestQueue; + pRequestQueue = NULL; +} + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLObjectMediaDataClient +// Subclass of LLMediaDataClient for the ObjectMedia cap +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const +{ + return new LLObjectMediaDataClient::Responder(request); +} + +const char *LLObjectMediaDataClient::getCapabilityName() const +{ + return "ObjectMedia"; +} + +void LLObjectMediaDataClient::fetchMedia(LLVOVolume *object) +{ + LLSD sd_payload; + sd_payload["verb"] = "GET"; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + request(object, sd_payload); +} + +void LLObjectMediaDataClient::updateMedia(LLVOVolume *object) +{ + LLSD sd_payload; + sd_payload["verb"] = "UPDATE"; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + LLSD object_media_data; + for (int i=0; i < object->getNumTEs(); i++) { + LLTextureEntry *texture_entry = object->getTE(i); + llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia()); + const LLSD &media_data = + (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD(); + object_media_data.append(media_data); + } + sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; + + LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_pretty_print_sd(sd_payload) << LL_ENDL; + + request(object, sd_payload); +} + +/*virtual*/ +void LLObjectMediaDataClient::Responder::result(const LLSD& content) +{ + const LLMediaDataClient::Request::Type type = getRequest()->getType(); + llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE) + if (type == LLMediaDataClient::Request::GET) + { + LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_pretty_print_sd(content) << LL_ENDL; + + // Look for an error + if (content.has("error")) + { + const LLSD &error = content["error"]; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << + error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; + + // XXX Warn user? + } + else { + // Check the data + const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY]; + if (object_id != getRequest()->getObject()->getID()) + { + // NOT good, wrong object id!! + LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; + return; + } + + // Otherwise, update with object media data + getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]); + } + } + else if (type == LLMediaDataClient::Request::UPDATE) + { + // just do what our superclass does + LLMediaDataClient::Responder::result(content); + } +} + +////////////////////////////////////////////////////////////////////////////////////// +// +// LLObjectMediaNavigateClient +// Subclass of LLMediaDataClient for the ObjectMediaNavigate cap +// +////////////////////////////////////////////////////////////////////////////////////// +LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const +{ + return new LLObjectMediaNavigateClient::Responder(request); +} + +const char *LLObjectMediaNavigateClient::getCapabilityName() const +{ + return "ObjectMediaNavigate"; +} + +void LLObjectMediaNavigateClient::navigate(LLVOVolume *object, U8 texture_index, const std::string &url) +{ + LLSD sd_payload; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + sd_payload[LLMediaEntry::CURRENT_URL_KEY] = url; + sd_payload[LLTextureEntry::TEXTURE_INDEX_KEY] = (LLSD::Integer)texture_index; + request(object, sd_payload); +} + +/*virtual*/ +void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string& reason) +{ + // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base + // class + if (status == HTTP_SERVICE_UNAVAILABLE) + { + LLMediaDataClient::Responder::error(status, reason); + } + else { + // bounce the face back + bounceBack(); + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL; + } +} + +/*virtual*/ +void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) +{ + LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_pretty_print_sd(content) << LL_ENDL; + + if (content.has("error")) + { + const LLSD &error = content["error"]; + int error_code = error["code"]; + + if (ERROR_PERMISSION_DENIED_CODE == error_code) + { + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL; + // bounce the face back + bounceBack(); + } + else { + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << + error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; + } + // XXX Warn user? + } + else { + // just do what our superclass does + LLMediaDataClient::Responder::result(content); + } +} + + +void LLObjectMediaNavigateClient::Responder::bounceBack() +{ + const LLSD &payload = getRequest()->getPayload(); + U8 texture_index = (U8)(LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]; + viewer_media_t impl = getRequest()->getObject()->getMediaImpl(texture_index); + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getRequest()->getObject()->getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { +// impl->navigateTo(mep->getCurrentURL()); + } +} diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h new file mode 100644 index 0000000000..59c4334251 --- /dev/null +++ b/indra/newview/llmediadataclient.h @@ -0,0 +1,263 @@ +/** + * @file llmediadataclient.h + * @brief class for queueing up requests to the media service + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMEDIADATACLIENT_H +#define LL_LLMEDIADATACLIENT_H + +#include "llhttpclient.h" +#include <queue> +#include "llrefcount.h" +#include "lltimer.h" + +// Forward decls +class LLVOVolume; + +typedef LLPointer<LLVOVolume> ll_vo_volume_ptr_t; + +// This object creates a priority queue for requests. +// Abstracts the Cap URL, the request, and the responder +class LLMediaDataClient : public LLRefCount +{ +public: + LOG_CLASS(LLMediaDataClient); + + const static int QUEUE_TIMER_DELAY = 1; // seconds(s) + const static int MAX_RETRIES = 4; + + // Constructor + LLMediaDataClient(); + + // Make the request + void request(LLVOVolume *object, const LLSD &payload); + +protected: + // Destructor + virtual ~LLMediaDataClient(); // use unref + + // Request + class Request : public LLRefCount + { + public: + enum Type { + GET, + UPDATE, + NAVIGATE + }; + + Request(const std::string &cap_name, const LLSD& sd_payload, LLVOVolume *obj, LLMediaDataClient *mdc); + const std::string &getCapName() const { return mCapName; } + const LLSD &getPayload() const { return mPayload; } + LLVOVolume *getObject() const { return mObject; } + + U32 getNum() const { return mNum; } + + U32 getRetryCount() const { return mRetryCount; } + void incRetryCount() { mRetryCount++; } + + // Note: may return empty string! + std::string getCapability() const; + + Type getType() const; + const char *getTypeAsString() const; + + // Re-enqueue thyself + void reEnqueue() const; + + public: + friend std::ostream& operator<<(std::ostream &s, const Request &q); + + protected: + virtual ~Request(); // use unref(); + + private: + std::string mCapName; + LLSD mPayload; + ll_vo_volume_ptr_t mObject; + // Simple tracking + const U32 mNum; + static U32 sNum; + U32 mRetryCount; + + // Back pointer to the MDC...not a ref! + LLMediaDataClient *mMDC; + }; + typedef LLPointer<Request> request_ptr_t; + + // Responder + class Responder : public LLHTTPClient::Responder + { + static const int UNAVAILABLE_RETRY_TIMER_DELAY = 5; // secs + + public: + Responder(const request_ptr_t &request); + //If we get back an error (not found, etc...), handle it here + virtual void error(U32 status, const std::string& reason); + //If we get back a normal response, handle it here. Default just logs it. + virtual void result(const LLSD& content); + + const request_ptr_t &getRequest() const { return mRequest; } + + protected: + virtual ~Responder(); + + private: + + class RetryTimer : public LLEventTimer + { + public: + RetryTimer(F32 time, Responder *); + virtual ~RetryTimer(); + virtual BOOL tick(); + private: + // back-pointer + boost::intrusive_ptr<Responder> mResponder; + }; + + request_ptr_t mRequest; + }; + +protected: + + void enqueue(const Request*); + + // Subclasses must override this factory method to return a new responder + virtual Responder *createResponder(const request_ptr_t &request) const = 0; + + // Subclasses must override to return a cap name + virtual const char *getCapabilityName() const = 0; + +private: + + // Comparator for PriorityQueue + class Comparator + { + public: + bool operator() (const request_ptr_t &o1, const request_ptr_t &o2) const; + private: + static F64 getObjectScore(const ll_vo_volume_ptr_t &obj); + }; + + class PriorityQueue : public std::priority_queue< + request_ptr_t, + std::vector<request_ptr_t>, + Comparator > + { + public: + friend std::ostream& operator<<(std::ostream &s, const PriorityQueue &q); + }; + + friend std::ostream& operator<<(std::ostream &s, const Request &q); + friend std::ostream& operator<<(std::ostream &s, const PriorityQueue &q); + + class QueueTimer : public LLEventTimer + { + public: + QueueTimer(F32 time, LLMediaDataClient *mdc); + virtual BOOL tick(); + protected: + virtual ~QueueTimer(); + private: + // back-pointer + LLPointer<LLMediaDataClient> mMDC; + }; + + void startQueueTimer(); + void stopQueueTimer(); + void setIsRunning(bool val) { mQueueTimerIsRunning = val; } + + bool mQueueTimerIsRunning; + + PriorityQueue *pRequestQueue; +}; + + +// MediaDataResponder specific for the ObjectMedia cap +class LLObjectMediaDataClient : public LLMediaDataClient +{ +public: + LLObjectMediaDataClient() {} + ~LLObjectMediaDataClient() {} + + void fetchMedia(LLVOVolume *object); + void updateMedia(LLVOVolume *object); + +protected: + // Subclasses must override this factory method to return a new responder + virtual Responder *createResponder(const request_ptr_t &request) const; + + // Subclasses must override to return a cap name + virtual const char *getCapabilityName() const; + + class Responder : public LLMediaDataClient::Responder + { + public: + Responder(const request_ptr_t &request) + : LLMediaDataClient::Responder(request) {} + virtual void result(const LLSD &content); + }; +}; + + +// MediaDataResponder specific for the ObjectMediaNavigate cap +class LLObjectMediaNavigateClient : public LLMediaDataClient +{ + // NOTE: from llmediaservice.h + static const int ERROR_PERMISSION_DENIED_CODE = 8002; + +public: + LLObjectMediaNavigateClient() {} + ~LLObjectMediaNavigateClient() {} + + void navigate(LLVOVolume *object, U8 texture_index, const std::string &url); + +protected: + // Subclasses must override this factory method to return a new responder + virtual Responder *createResponder(const request_ptr_t &request) const; + + // Subclasses must override to return a cap name + virtual const char *getCapabilityName() const; + + class Responder : public LLMediaDataClient::Responder + { + public: + Responder(const request_ptr_t &request) + : LLMediaDataClient::Responder(request) {} + virtual void error(U32 status, const std::string& reason); + virtual void result(const LLSD &content); + private: + void bounceBack(); + }; + +}; + + +#endif // LL_LLMEDIADATACLIENT_H 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/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 9754094aaa..bc0dec1fdb 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -261,7 +261,7 @@ BOOL LLTeleportHistoryPanel::postBuild() if (fl) { fl->setCommitOnSelectionChange(true); - //fl->setDoubleClickCallback(onDoubleClickItem, this); + fl->setDoubleClickCallback(boost::bind(&LLTeleportHistoryPanel::onDoubleClickItem, this)); fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl)); } } @@ -497,20 +497,10 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) updateVerbs(); } -//static -void LLTeleportHistoryPanel::onDoubleClickItem(void* user_data) +void LLTeleportHistoryPanel::onDoubleClickItem() { - /*LLTeleportHistoryPanel* self = (LLTeleportHistoryPanel*)user_data; - - LLScrollListItem* itemp = self->mHistoryItems->getFirstSelected(); - if(!itemp) - return; - - LLSD key; - key["type"] = "teleport_history"; - key["id"] = itemp->getColumn(LIST_INDEX)->getValue().asInteger(); - - LLSideTray::getInstance()->showPanel("panel_places", key);*/ + // If item got doubleclick, then that item is already selected + onTeleport(); } void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask) diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index ebba25cfa5..c4b7f995e0 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -78,7 +78,7 @@ public: private: - static void onDoubleClickItem(void* user_data); + void onDoubleClickItem(); void onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask); void onAccordionTabOpen(LLAccordionCtrlTab *tab); void onAccordionTabClose(LLAccordionCtrlTab *tab); 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/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 8a96a5a1ae..a72100a9b3 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -213,7 +213,7 @@ void LLScreenChannel::deleteToast(LLToast* toast) toast->mOnDeleteToastSignal(toast); // update channel's Hovering state - // turning hovering off mannualy because onMouseLeave won't happen if a toast was closed using a keyboard + // turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard if(toast->hasFocus()) setHovering(false); @@ -372,7 +372,8 @@ void LLScreenChannel::redrawToasts() void LLScreenChannel::showToastsBottom() { LLRect toast_rect; - S32 bottom = getRect().mBottom; + S32 bottom = getRect().mBottom - gFloaterView->getRect().mBottom; + S32 toast_margin = 0; std::vector<ToastElem>::reverse_iterator it; for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) @@ -380,19 +381,20 @@ void LLScreenChannel::showToastsBottom() if(it != mToastList.rbegin()) { bottom = (*(it-1)).toast->getRect().mTop; + toast_margin = gSavedSettings.getS32("ToastMargin"); } toast_rect = (*it).toast->getRect(); - toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); + toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight()); (*it).toast->setRect(toast_rect); - bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().getHeight(); + bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; if(!stop_showing_toasts) { if( it != mToastList.rend()-1) { - stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().getHeight(); + stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().mTop; } } @@ -477,6 +479,28 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) void LLScreenChannel::onOverflowToastHide() { mOverflowToastHidden = true; + + // remove all hidden toasts from channel and save interactive notifications + for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) + { + if(!(*it).toast->getVisible()) + { + if((*it).toast->getCanBeStored()) + { + storeToast((*it)); + } + else + { + deleteToast((*it).toast); + } + + it = mToastList.erase(it); + } + else + { + ++it; + } + } } //-------------------------------------------------------------------------- @@ -583,9 +607,7 @@ void LLScreenChannel::removeAndStoreAllStorableToasts() { if((*it).toast->getCanBeStored()) { - mStoredToastList.push_back(*it); - mOnStoreToast((*it).toast->getPanel(), (*it).id); - (*it).toast->stopTimer(); + storeToast(*(it)); it = mToastList.erase(it); } else @@ -664,14 +686,30 @@ void LLScreenChannel::updateShowToastsState() return; } - if(dynamic_cast<LLIMFloater*>(floater) || dynamic_cast<LLSysWellWindow*>(floater)) + // for IM floaters showed in a docked state - prohibit showing of ani toast + if(dynamic_cast<LLIMFloater*>(floater)) { setShowToasts(!(floater->getVisible() && floater->isDocked())); if (!getShowToasts()) { removeAndStoreAllStorableToasts(); } - + } + + // for Message Well floater showed in a docked state - adjust channel's height + if(dynamic_cast<LLSysWellWindow*>(floater)) + { + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; + LLRect this_rect = getRect(); + if(floater->getVisible() && floater->isDocked()) + { + channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastMargin")); + } + + if(channel_bottom != this_rect.mBottom) + { + setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); + } } } 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/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 669d8d1d70..2bb1e80eb8 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -266,10 +266,6 @@ void LLSysWellWindow::toggleWindow() if(!getVisible()) { - if(mChannel) - { - mChannel->removeAndStoreAllStorableToasts(); - } if(isWindowEmpty()) { return; @@ -345,6 +341,13 @@ void LLSysWellWindow::reshapeWindow() curRect.setLeftTopAndSize(curRect.mLeft, newY, MIN_WINDOW_WIDTH, new_window_height); reshape(curRect.getWidth(), curRect.getHeight(), TRUE); setRect(curRect); + + // update notification channel state + // update on a window reshape is important only when a window is visible and docked + if(mChannel && getVisible() && isDocked()) + { + mChannel->updateShowToastsState(); + } } //--------------------------------------------------------------------------------- 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 8064320a85..d534ef97b9 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 5e000bba6d..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,9 +5612,6 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLPanelLandCovenant::updateLastModified(last_modified); LLFloaterBuyLand::updateLastModified(last_modified); - BOOL is_group = FALSE; - gCacheName->get(estate_owner_id, is_group, &callbackCacheEstateOwnerName); - // load the actual covenant asset data const BOOL high_priority = TRUE; if (covenant_id.notNull()) @@ -5639,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/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 05011a1568..1f4f1322fd 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -47,7 +47,6 @@ #include "llframetimer.h" #include "llinventory.h" #include "llmaterialtable.h" -#include "llmediadataresponder.h" #include "llmutelist.h" #include "llnamevalue.h" #include "llprimitive.h" 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/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a2f6b70006..9f096209dd 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2348,6 +2348,14 @@ void LLViewerMediaTexture::addFace(LLFace* facep) return ; } } + + //check if it is a parcel media + if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID) + { + mTextureList.push_back(facep->getTexture()) ; //a parcel media. + return ; + } + llerrs << "The face does not have a valid texture before media texture." << llendl ; } @@ -2406,6 +2414,18 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) } } } + + //check if it is a parcel media + for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + if((*iter)->getID() == mID) + { + mTextureList.erase(iter) ; //decrease the reference number for tex by one. + return ; + } + } + llerrs << "mTextureList texture reference number is corrupted." << llendl ; } @@ -2442,6 +2462,10 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) if(te) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + if(!tex && te->getID() != mID)//try parcel media. + { + tex = gTextureList.findImage(mID) ; + } facep->switchTexture(tex) ; } } 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/llvovolume.cpp b/indra/newview/llvovolume.cpp index e69779b2dc..583246c23e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -46,7 +46,6 @@ #include "llvolumemessage.h" #include "material_codes.h" #include "message.h" -#include "llmediadataresponder.h" #include "llpluginclassmedia.h" // for code in the mediaEvent handler #include "object_flags.h" #include "llagentconstants.h" @@ -69,7 +68,7 @@ #include "pipeline.h" #include "llsdutil.h" #include "llmediaentry.h" -#include "llmediadatafetcher.h" +#include "llmediadataclient.h" #include "llagent.h" const S32 MIN_QUIET_FRAMES_COALESCE = 30; @@ -86,6 +85,8 @@ F32 LLVOVolume::sLODFactor = 1.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; +LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL; +LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL; static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); @@ -133,13 +134,15 @@ LLVOVolume::~LLVOVolume() // static void LLVOVolume::initClass() { - LLMediaDataFetcher::initClass(); + sObjectMediaClient = new LLObjectMediaDataClient(); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(); } // static void LLVOVolume::cleanupClass() { - LLMediaDataFetcher::cleanupClass(); + sObjectMediaClient = NULL; + sObjectMediaNavigateClient = NULL; } U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, @@ -1621,7 +1624,7 @@ bool LLVOVolume::hasMedia() const void LLVOVolume::requestMediaDataUpdate() { - LLMediaDataFetcher::fetchMedia(this); + sObjectMediaClient->fetchMedia(this); } void LLVOVolume::cleanUpMediaImpls() @@ -1752,21 +1755,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, llinfos << "broadcasting navigate with URI " << new_location << llendl; - // Post the navigate to the cap - std::string cap = getRegion()->getCapability("ObjectMediaNavigate"); - if(cap.empty()) - { - // XXX *TODO: deal with no cap! It may happen! (retry?) - LL_WARNS("Media") << "Can't broadcast navigate event -- ObjectMediaNavigate cap is not available" << LL_ENDL; - return; - } - - // If we got here, the cap is available. Index through all faces that have this media and send the navigate message. - LLSD sd; - sd["object_id"] = mID; - sd["current_url"] = new_location; - sd["texture_index"] = face_index; - LLHTTPClient::post(cap, sd, new LLMediaDataResponder("ObjectMediaNavigate", sd, this)); + sObjectMediaNavigateClient->navigate(this, face_index, new_location); } } break; @@ -1790,29 +1779,9 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, } -void LLVOVolume::sendMediaDataUpdate() const +void LLVOVolume::sendMediaDataUpdate() { - std::string url = getRegion()->getCapability("ObjectMedia"); - if (!url.empty()) - { - LLSD sd_payload; - sd_payload["verb"] = "UPDATE"; - sd_payload[LLTextureEntry::OBJECT_ID_KEY] = mID; - LLSD object_media_data; - for (int i=0; i < getNumTEs(); i++) { - LLTextureEntry *texture_entry = getTE(i); - llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia()); - const LLSD &media_data = - (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD(); - object_media_data.append(media_data); - } - sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; - - llinfos << "Sending media data: " << getID() << " " << ll_pretty_print_sd(sd_payload) << llendl; - - LLHTTPClient::post(url, sd_payload, new LLMediaDataResponder("ObjectMedia", sd_payload, this)); - } - // XXX *TODO: deal with no cap! It may happen! (retry?) + sObjectMediaClient->updateMedia(this); } void LLVOVolume::removeMediaImpl(S32 texture_index) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 9a79b620d5..250c3ed917 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -45,6 +45,8 @@ class LLViewerTextureAnim; class LLDrawPool; class LLSelectNode; +class LLObjectMediaDataClient; +class LLObjectMediaNavigateClient; typedef std::vector<viewer_media_t> media_list_t; @@ -238,7 +240,7 @@ public: void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent); // Send media data update to the simulator. - void sendMediaDataUpdate() const; + void sendMediaDataUpdate(); viewer_media_t getMediaImpl(U8 face_id) const; S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id); @@ -283,6 +285,9 @@ public: static F32 sLODFactor; // LOD scale factor static F32 sDistanceFactor; // LOD distance factor + static LLPointer<LLObjectMediaDataClient> sObjectMediaClient; + static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient; + protected: static S32 sNumLODChanges; 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 Binary files differnew file mode 100644 index 0000000000..81078c32dc --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Info_Small.png 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/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml index dda5e9bd1a..9849f2f56d 100644 --- a/indra/newview/skins/default/xui/da/strings.xml +++ b/indra/newview/skins/default/xui/da/strings.xml @@ -513,4 +513,112 @@ <string name="GraphicsQualityHigh"> Høj </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Linden sted</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Kunst & kultur</string> + <string name="Business">Business</string> + <string name="Educational">Uddannelse</string> + <string name="Gaming">Spil</string> + <string name="Hangout">Afslapning</string> + <string name="Newcomer Friendly">Nybegynder venligt</string> + <string name="Parks&Nature">Parker & natur</string> + <string name="Residential">Beboelse</string> + <string name="Shopping">Indkøb</string> + <string name="Other">Andet</string> + + <string name="ringing"> + Forbinder til stemmechat... + </string> + <string name="connected"> + Forbundet + </string> + <string name="unavailable"> + Stemmechat er ikke tilladt hvor du befinder dig + </string> + <string name="hang_up"> + Stemme chat er afbrudt + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', en genstand, ejet af '[OWNERNAME]', lokaliseret i [REGIONNAME] på [REGIONPOS], har fået tilladelse til: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + '[OBJECTNAME]', en genstand, ejet af '[OWNERNAME]', lokaliseret i [REGIONNAME] på [REGIONPOS], er afvist tilladelse til: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Tag Linden dollars (L$) fra dig + </string> + <string name="ActOnControlInputs"> + Reagér på dine kontrol-taster + </string> + <string name="RemapControlInputs"> + Ændre dine kontrol-taster + </string> + <string name="AnimateYourAvatar"> + Animér din avatar + </string> + <string name="AttachToYourAvatar"> + Sæt på din avatar + </string> + <string name="ReleaseOwnership"> + Fjern ejerskabet og sæt til offentlig + </string> + <string name="LinkAndDelink"> + Sammenkæd og adskil andre genstande + </string> + <string name="AddAndRemoveJoints"> + Tilføj og fjern sammenkødninger med andre genstande + </string> + <string name="ChangePermissions"> + Ændre dens tilladelser + </string> + <string name="TrackYourCamera"> + Spor dit kamera + </string> + <string name="ControlYourCamera"> + Kontrollér dit kamera + </string> + <string name="only_user_message"> + Du er den eneste deltager i denne samtale + </string> + <string name="offline_message"> + [FIRST] [LAST] er ikke logget på. + </string> + <string name="invite_message"> + Tryk på [BUTTON NAME] knappen for at acceptére/tilslutte til denne stemme chat. + </string> + <string name="muted_message"> + Du har blokeret denne beboer. Hvis du starter en samtale vil denne blokering automatisk blive fjernet. + </string> + <string name="generic_request_error"> + Kunne ikke etablere forbindelse, prøv igen senere + </string> + <string name="insufficient_perms_error"> + Du har ikke de fornødne rettigheder. + </string> + <string name="session_does_not_exist_error"> + Denne samtale er lukket ned + </string> + <string name="no_ability_error"> + Du har ikke den mulighed. + </string> + <string name="not_a_mod_error"> + Du er ikke moderator for denne samtale. + </string> + <string name="muted_error"> + Du er blevet "blokeret". + </string> + <string name="add_session_event"> + Ikke muligt at tilføge brugere til samtale med [RECIPIENT]. + </string> + <string name="message_session_event"> + Ikke muligt at sende din besked til samtalen med [RECIPIENT]. + </string> + <string name="removed_from_group"> + Du er blevet fjernet fra gruppen. + </string> + <string name="close_on_no_ability"> + Du har ikke længere mulighed for at deltage i samtalen + </string> </strings> diff --git a/indra/newview/skins/default/xui/de/floater_god_tools.xml b/indra/newview/skins/default/xui/de/floater_god_tools.xml index 39c064b265..c7cfb5d9d3 100644 --- a/indra/newview/skins/default/xui/de/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_god_tools.xml @@ -115,17 +115,17 @@ Ziel: </text> <combo_box name="destination"> - <combo_box.item name="Selection" label="Auswahl" /> - <combo_box.item name="AgentRegion" label="Avatar-Region" /> + <combo_box.item name="item1" label="Auswahl" /> + <combo_box.item name="item2" label="Avatar-Region" /> </combo_box> <text name="Request:"> Anfrage: </text> <combo_box name="request"> - <combo_box.item name="colliders<steps>" label="Kollisionsobjekte <Schritte>" /> - <combo_box.item name="scripts<count>,<optionalpattern>" label="Skripts <Zähler>,<Optionales Muster>" /> - <combo_box.item name="objects<pattern>" label="Objekte <Muster>" /> - <combo_box.item name="rez<asset_id>" label="lt;asset_id> erstellen" /> + <combo_box.item name="item1" label="Kollisionsobjekte <Schritte>" /> + <combo_box.item name="item2" label="Skripts <Zähler>,<Optionales Muster>" /> + <combo_box.item name="item3" label="Objekte <Muster>" /> + <combo_box.item name="item4" label="lt;asset_id> erstellen" /> </combo_box> <text name="Parameter:"> Parameter: diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index b5741438ae..b738b2d864 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -565,7 +565,7 @@ Verschieben Sie alle betreffenden Objekte in dieselbe Region. <notification name="PromptGoToCurrencyPage"> [EXTRA] -[URL] für Informationen zum Deviseneinkauf öffnen? +[_URL] für Informationen zum Deviseneinkauf öffnen? <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -796,7 +796,6 @@ Keine Gruppe ausgewählt. <notification name="CannotDeedLandNoRegion"> Land kann nicht übertragen werden: Kann die Region nicht finden, in der sich dieses Land befindet. -Bitte melden Sie dies über „Hilfe“ > „Fehler melden“. </notification> <notification name="CannotDeedLandMultipleSelected"> Land kann nicht übertragen werden: @@ -842,8 +841,6 @@ Parzellen, die Ihnen gehören, werden grün dargestellt. <notification name="CannotReleaseLandRegionNotFound"> Land kann nicht aufgegeben werden: Kann die Region nicht finden, in der sich dieses Land befindet. - -Bitte melden Sie dies über „Hilfe“ > „Fehler melden“. </notification> <notification name="CannotReleaseLandNoTransfer"> Land kann nicht aufgegeben werden: @@ -882,14 +879,10 @@ Land teilen? <notification name="CannotDivideLandNoRegion"> Land kann nicht aufgeteilt werden: Kann die Region nicht finden, in der sich dieses Land befindet. - -Bitte melden Sie dies über „Hilfe“ > „Fehler melden“. </notification> <notification name="CannotJoinLandNoRegion"> Land kann nicht zusammengelegt werden: Kann die Region nicht finden, in der sich dieses Land befindet. - -Bitte melden Sie dies über „Hilfe“ > „Fehler melden“. </notification> <notification name="CannotJoinLandNothingSelected"> Land kann nicht zusammengelegt werden: @@ -949,8 +942,6 @@ Grau = Öffentlich <notification name="CannotSaveToAssetStore"> [NAME] kann nicht in Zentral-Asset-Speicher geladen werden. Dies ist ein temporärer Fehler. Bitte passen Sie das Kleidungsstück in einigen Minuten noch einmal an und speichern Sie es erneut. - -Tritt dieses Problem wiederholt auf, klicken Sie auf das Pulldown-Menü „Hilfe“ > „Fehler melden“ und geben Sie Details zu Ihrem Netzwerk-Setup an. </notification> <notification name="YouHaveBeenLoggedOut"> Sie wurden von [SECOND_LIFE] abgemeldet: @@ -1290,10 +1281,6 @@ In Ihren Anwendungsordner herunterladen? Zu www.secondlife.com, um Ihr Konto zu verwalten? <usetemplate ignoretext="Beim Starten eines Browsers, um Ihr Konto zu verwalten" name="okcancelignore" notext="Abbrechen" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Informieren Sie sich im [SECOND_LIFE] Wiki, wie man Fehler richtig meldet. - <usetemplate ignoretext="Beim Starten eines Browsers, um das Fehlermeldungs-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Informieren Sie sich im [SECOND_LIFE] Wiki, wie man Sicherheitsprobleme richtig meldet. <usetemplate ignoretext="Beim Starten eines Browsers, um das Sicherheitsfragen-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> @@ -1974,23 +1961,10 @@ Als besonderen Service für Einwohner und Besucher übernimmt der Eigentümer di - Das Resultat, das sich aus dieser Meldung ergibt, betrifft nur diese Region; der Einwohnerzugang zu anderen Bereichen von [SECOND_LIFE] ist davon nicht betroffen. Nur Linden Lab kann den Zugang zu [SECOND_LIFE] beschränken. </notification> - <notification name="HelpReportBug"> - Verwenden Sie dieses Tool *nur*, um technische Features zu melden, die nicht wie beschrieben oder erwartet funktionieren. Bitte machen Sie so viele Angaben wie möglich. Sie können auf die automatische Antwort-E-Mail antworten, um Ihre Meldung noch zu ergänzen. -Alle gemeldeten Fehler werden geprüft und bewertet. Sie erhalten keine persönliche Antwort auf Ihre E-Mail. -- -Bei technischen Problemen wenden Sie sich bitte an den Support unter: -http://secondlife.com/community/support.php -- -Hinweis: Unvollständige Meldungen werden nicht bearbeitet. - </notification> <notification name="HelpReportAbuseSelectCategory"> Wählen Sie eine Missbrauchskategorie aus. Die Angabe einer Kategorie hilft uns bei der Bearbeitung des Berichts. </notification> - <notification name="HelpReportBugSelectCategory"> - Wählen Sie eine Fehler-Kategorie aus. -Die Angabe einer Kategorie hilft uns bei der Bearbeitung des Berichts. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Geben Sie den Namen des Täters ein. Eine genaue Angabe hilft uns, Fälle von Missbrauch zu ahnden. @@ -2003,18 +1977,10 @@ Eine genaue Angabe hilft uns, Fälle von Missbrauch zu ahnden. Bitte geben Sie eine Zusammenfassung des Vorfalls ein. Eine genaue Zusammenfassung hilft uns, Fälle von Missbrauch zu ahnden. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Bitte geben Sie eine Zusammenfassung des Fehlers ein. -Eine genaue Zusammenfassung hilft uns, Fehler schneller zu beseitigen. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Bitte geben Sie eine ausführliche Beschreibung des Vorfalls ein. Eine möglichst genaue Beschreibung mit Namen und Einzelheiten hilft uns, Fälle von Missbrauch zu ahnden. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Bitte geben Sie eine ausführliche Fehlerbeschreibung ein. -Eine möglichst genaue Beschreibung mit Schritten zur Reproduktion des Fehlers hilft uns, Fehler schneller zu beseitigen. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Sehr geehrte(r) Einwohner(in), diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 380046f72d..5df1570bfd 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -517,4 +517,108 @@ <string name="GraphicsQualityHigh"> Hoch </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Lindenort</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Kunst & Kultur</string> + <string name="Business">Business</string> + <string name="Educational">Bildung</string> + <string name="Gaming">Spielen</string> + <string name="Hangout">Treffpunkt</string> + <string name="Newcomer Friendly">Anfängergerecht</string> + <string name="Parks&Nature">Parks und Natur</string> + <string name="Residential">Wohngebiet</string> + <string name="Shopping">Shopping</string> + <string name="Other">Sonstige</string> + <string name="ringing"> + Verbindung mit In-Welt-Voice-Chat... + </string> + <string name="connected"> + Verbunden + </string> + <string name="unavailable"> + Der aktuelle Standort unterstützt keine Voice-Kommunikation + </string> + <string name="hang_up"> + Verbindung mit In-Welt-Voice-Chat getrennt + </string> + <string name="ScriptQuestionCautionChatGranted"> + Dem Objekt „[OBJECTNAME]“, ein Objekt von „[OWNERNAME]“, in [REGIONNAME] [REGIONPOS], wurde folgende Berechtigung erteilt: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + Dem Objekt „[OBJECTNAME]“, ein Objekt von „[OWNERNAME]“, in [REGIONNAME] [REGIONPOS], wurde folgende Berechtigung verweigert: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Linden-Dollar (L$) von Ihnen nehmen + </string> + <string name="ActOnControlInputs"> + Steuerung festlegen + </string> + <string name="RemapControlInputs"> + Steuerung neu zuweisen + </string> + <string name="AnimateYourAvatar"> + Avatar animieren + </string> + <string name="AttachToYourAvatar"> + An Avatar anhängen + </string> + <string name="ReleaseOwnership"> + Eigentum aufgeben und öffentlich machen + </string> + <string name="LinkAndDelink"> + Mit Objekten verknüpfen und davon trennen + </string> + <string name="AddAndRemoveJoints"> + Verbindungen zu anderen Objekten hinzufügen und entfernen + </string> + <string name="ChangePermissions"> + Berechtigungen ändern + </string> + <string name="TrackYourCamera"> + Kameraverfolgung + </string> + <string name="ControlYourCamera"> + Kamerasteuerung + </string> + <string name="only_user_message"> + Sie sind der einzige Benutzer in dieser Sitzung. + </string> + <string name="offline_message"> + [FIRST] [LAST] ist offline. + </string> + <string name="invite_message"> + Klicken Sie auf [BUTTON NAME], um eine Verbindung zu diesem Voice-Chat herzustellen. + </string> + <string name="generic_request_error"> + Fehler bei Anfrage, bitte versuchen Sie es später. + </string> + <string name="insufficient_perms_error"> + Sie sind dazu nicht berechtigt. + </string> + <string name="session_does_not_exist_error"> + Die Sitzung ist abgelaufen + </string> + <string name="no_ability_error"> + Sie besitzen diese Fähigkeit nicht. + </string> + <string name="not_a_mod_error"> + Sie sind kein Sitzungsmoderator. + </string> + <string name="muted_error"> + Ein Gruppenmoderator hat Ihren Text-Chat deaktiviert. + </string> + <string name="add_session_event"> + Es konnten keine Benutzer zur Chat-Sitzung mit [RECIPIENT] hinzugefügt werden. + </string> + <string name="message_session_event"> + Ihre Nachricht konnte nicht an die Chat-Sitzung mit [RECIPIENT] gesendet werden. + </string> + <string name="removed_from_group"> + Sie wurden von der Gruppe ausgeschlossen. + </string> + <string name="close_on_no_ability"> + Sie haben nicht mehr die Berechtigung an der Chat-Sitzung teilzunehmen. + </string> </strings> 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 > 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_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index 3ab5c18300..f76e4acbc9 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -55,14 +55,13 @@ width="220"> Type part of a person's name: </text> - <text_editor + <line_editor bevel_style="none" border_style="line" border.border_thickness="0" commit_on_focus_lost="false" follows="left|top|right" height="23" - layout="topleft" left_delta="0" name="Edit" top_pad="0" @@ -188,8 +187,8 @@ <button follows="right|bottom" height="23" - label="Ok" - label_selected="Ok" + label="OK" + label_selected="OK" name="Select" top_pad="3" left="46" 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'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_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 0784b88944..c4a2654403 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -5,7 +5,7 @@ can_close="false" center_horiz="true" follows="top" - height="95" + height="110" layout="topleft" name="camera_floater" help_topic="camera_floater" @@ -26,7 +26,7 @@ </floater.string> <panel border="true" - height="64" + height="79" layout="topleft" left="0" top="0" @@ -46,7 +46,7 @@ scale_image="false" sound_flags="3" tool_tip="Orbit Camera Around Focus" - top="0" + top="15" width="64" /> <joystick_track follows="top|left" @@ -61,7 +61,7 @@ scale_image="false" sound_flags="3" tool_tip="Move Camera Up and Down, Left and Right" - top="0" + top="15" visible="false" width="64" /> <joystick_zoom 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_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 82acea47be..65235da8d5 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -5,7 +5,7 @@ can_minimize="false" center_horiz="true" follows="bottom" - height="95" + height="110" layout="topleft" name="move_floater" help_topic="move_floater" @@ -38,7 +38,7 @@ </string> <panel border="true" - height="70" + height="83" follows="left|top" layout="topleft" left="0" @@ -57,7 +57,7 @@ picture_style="true" scale_image="false" tool_tip="Turn Left (press Left Arrow or A)" - top="35" + top="45" width="25" /> <button follows="left|bottom" @@ -83,7 +83,7 @@ picture_style="true" scale_image="false" tool_tip="Fly Up, Press "E"" - top="4" + top="14" width="25" /> <button follows="left|bottom" @@ -130,7 +130,7 @@ <!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml --> <panel border="true" - height="25" + height="27" layout="topleft" left="0" name="panel_modes" 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_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml index 4e214c4095..5d9baf4019 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml @@ -172,7 +172,7 @@ name="auto_play" radio_style="false" width="150" /> <text bottom_delta="-14" follows="top|left" height="15" left="30" width="340" enabled="false" name=""> - Note: Parcel Owners & Residents can override this setting + Note: Residents can override this setting </text> <check_box bottom_delta="-25" enabled="true" follows="left|top" font="SansSerifSmall" 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_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml index aa76a61c15..3b1b049ff2 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml @@ -28,7 +28,8 @@ name="show_help" top="5" right="-8" - width="28"> + width="28" + tool_tip="Show Help"> <button.commit_callback function="Button.ShowHelp" /> </button> 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_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index bb37f43220..d640d3ad88 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -42,11 +42,12 @@ height="20" layout="topleft" left_pad="5" + use_ellipsis="true" name="region" text_color="white" top="4" value="Unknown" - width="380" /> + width="330" /> <button follows="right" height="18" 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 1e85cac539..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 --> @@ -301,1450 +302,1452 @@ <string name="choose_the_directory">Choose Directory</string> <!-- LSL Usage Hover Tips --> - <string name="LSLTipSleepTime"> + <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window). + This has no effect on viewer code, but prevents Linden Lab internal localization tool from scraping these strings. --> + <string name="LSLTipSleepTime" translate="false"> Sleeps script for [SLEEP_TIME] seconds. </string> - <string name="LSLTipText_llSin"> + <string name="LSLTipText_llSin" translate="false"> float llSin(float theta) Returns the sine of theta (theta in radians) </string> - <string name="LSLTipText_llCos"> + <string name="LSLTipText_llCos" translate="false"> float llCos(float theta) Returns the cosine of theta (theta in radians) </string> - <string name="LSLTipText_llTan"> + <string name="LSLTipText_llTan" translate="false"> float llTan(float theta) Returns the tangent of theta (theta in radians) </string> - <string name="LSLTipText_llAtan2"> + <string name="LSLTipText_llAtan2" translate="false"> float llAtan2(float y, float x) Returns the arctangent2 of y, x </string> - <string name="LSLTipText_llSqrt"> + <string name="LSLTipText_llSqrt" translate="false"> float llSqrt(float val) Returns the square root of val, or returns 0 and triggers a Math Error for imaginary results </string> - <string name="LSLTipText_llPow"> + <string name="LSLTipText_llPow" translate="false"> float llPow(float base, float exponent) Returns the base raised to the power exponent, or returns 0 and triggers Math Error for imaginary results </string> - <string name="LSLTipText_llAbs"> + <string name="LSLTipText_llAbs" translate="false"> integer llAbs(integer val) Returns the positive version of val </string> - <string name="LSLTipText_llFabs"> + <string name="LSLTipText_llFabs" translate="false"> float llFabs(float val) Returns the positive version of val </string> - <string name="LSLTipText_llFrand"> + <string name="LSLTipText_llFrand" translate="false"> float llFrand(float mag) Returns a pseudo random number in the range [0,mag) or (mag,0] </string> - <string name="LSLTipText_llFloor"> + <string name="LSLTipText_llFloor" translate="false"> integer llFloor(float val) Returns largest integer value <= val </string> - <string name="LSLTipText_llCeil"> + <string name="LSLTipText_llCeil" translate="false"> integer llCeil(float val) Returns smallest integer value >= val </string> - <string name="LSLTipText_llRound"> + <string name="LSLTipText_llRound" translate="false"> integer llRound(float val) Returns val rounded to the nearest integer </string> - <string name="LSLTipText_llVecMag"> + <string name="LSLTipText_llVecMag" translate="false"> float llVecMag(vector v) Returns the magnitude of v </string> - <string name="LSLTipText_llVecNorm"> + <string name="LSLTipText_llVecNorm" translate="false"> vector llVecNorm(vector v) Returns the v normalized </string> - <string name="LSLTipText_llVecDist"> + <string name="LSLTipText_llVecDist" translate="false"> float llVecDist(vector v1, vector v2) Returns the 3D distance between v1 and v2 </string> - <string name="LSLTipText_llRot2Euler"> + <string name="LSLTipText_llRot2Euler" translate="false"> vector llRot2Euler(rotation q) Returns the Euler representation (roll, pitch, yaw) of q </string> - <string name="LSLTipText_llEuler2Rot"> + <string name="LSLTipText_llEuler2Rot" translate="false"> rotation llEuler2Rot(vector v) Returns the rotation representation of Euler Angles v </string> - <string name="LSLTipText_llAxes2Rot"> + <string name="LSLTipText_llAxes2Rot" translate="false"> rotation llAxes2Rot(vector fwd, vector left, vector up) Returns the rotation defined by the coordinate axes </string> - <string name="LSLTipText_llRot2Fwd"> + <string name="LSLTipText_llRot2Fwd" translate="false"> vector llRot2Fwd(rotation q) Returns the forward vector defined by q </string> - <string name="LSLTipText_llRot2Left"> + <string name="LSLTipText_llRot2Left" translate="false"> vector llRot2Left(rotation q) Returns the left vector defined by q </string> - <string name="LSLTipText_llRot2Up"> + <string name="LSLTipText_llRot2Up" translate="false"> vector llRot2Up(rotation q) Returns the up vector defined by q </string> - <string name="LSLTipText_llRotBetween"> + <string name="LSLTipText_llRotBetween" translate="false"> rotation llRotBetween(vector v1, vector v2) Returns the rotation to rotate v1 to v2 </string> - <string name="LSLTipText_llWhisper"> + <string name="LSLTipText_llWhisper" translate="false"> llWhisper(integer channel, string msg) Whispers the text of msg on channel </string> - <string name="LSLTipText_llSay"> + <string name="LSLTipText_llSay" translate="false"> llSay(integer channel, string msg) Says the text of msg on channel </string> - <string name="LSLTipText_llShout"> + <string name="LSLTipText_llShout" translate="false"> llShout(integer channel, string msg) Shouts the text of msg on channel </string> - <string name="LSLTipText_llListen"> + <string name="LSLTipText_llListen" translate="false"> integer llListen(integer channel, string name, key id, string msg) Sets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen </string> - <string name="LSLTipText_llListenControl"> + <string name="LSLTipText_llListenControl" translate="false"> llListenControl(integer number, integer active) Makes a listen event callback active or inactive </string> - <string name="LSLTipText_llListenRemove"> + <string name="LSLTipText_llListenRemove" translate="false"> llListenRemove(integer number) Removes listen event callback number </string> - <string name="LSLTipText_llSensor"> + <string name="LSLTipText_llSensor" translate="false"> llSensor(string name, key id, integer type, float range, float arc) Performs a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) </string> - <string name="LSLTipText_llSensorRepeat"> + <string name="LSLTipText_llSensorRepeat" translate="false"> llSensorRepeat(string name, key id, integer type, float range, float arc, float rate) Sets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds </string> - <string name="LSLTipText_llSensorRemove"> + <string name="LSLTipText_llSensorRemove" translate="false"> llSensorRemove() Removes the sensor setup by llSensorRepeat </string> - <string name="LSLTipText_llDetectedName"> + <string name="LSLTipText_llDetectedName" translate="false"> string llDetectedName(integer number) Returns the name of detected object number (returns empty string if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedKey"> + <string name="LSLTipText_llDetectedKey" translate="false"> key llDetectedKey(integer number) Returns the key of detected object number (returns empty key if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedOwner"> + <string name="LSLTipText_llDetectedOwner" translate="false"> key llDetectedOwner(integer number) Returns the key of detected object's owner (returns empty key if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedType"> + <string name="LSLTipText_llDetectedType" translate="false"> integer llDetectedType(integer number) Returns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedPos"> + <string name="LSLTipText_llDetectedPos" translate="false"> vector llDetectedPos(integer number) Returns the position of detected object number (returns <0,0,0> if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedVel"> + <string name="LSLTipText_llDetectedVel" translate="false"> vector llDetectedVel(integer number) Returns the velocity of detected object number (returns <0,0,0> if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedGrab"> + <string name="LSLTipText_llDetectedGrab" translate="false"> vector llDetectedGrab(integer number) Returns the grab offset of the user touching object (returns <0,0,0> if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedRot"> + <string name="LSLTipText_llDetectedRot" translate="false"> rotation llDetectedRot(integer number) Returns the rotation of detected object number (returns <0,0,0,1> if number is not a valid sensed object) </string> - <string name="LSLTipText_llDetectedGroup"> + <string name="LSLTipText_llDetectedGroup" translate="false"> integer llDetectedGroup(integer number) Returns TRUE if detected object is part of same group as owner </string> - <string name="LSLTipText_llDetectedLinkNumber"> + <string name="LSLTipText_llDetectedLinkNumber" translate="false"> integer llDetectedLinkNumber(integer number) Returns the link position of the triggered event for touches and collisions only </string> - <string name="LSLTipText_llDie"> + <string name="LSLTipText_llDie" translate="false"> llDie() Deletes the object </string> - <string name="LSLTipText_llGround"> + <string name="LSLTipText_llGround" translate="false"> float llGround(vector offset) Returns the ground height below the object position + offset </string> - <string name="LSLTipText_llCloud"> + <string name="LSLTipText_llCloud" translate="false"> float llCloud(vector offset) Returns the cloud density at the object position + offset </string> - <string name="LSLTipText_llWind"> + <string name="LSLTipText_llWind" translate="false"> vector llWind(vector offset) Returns the wind velocity at the object position + offset </string> - <string name="LSLTipText_llSetStatus"> + <string name="LSLTipText_llSetStatus" translate="false"> llSetStatus(integer status, integer value) Sets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value </string> - <string name="LSLTipText_llGetStatus"> + <string name="LSLTipText_llGetStatus" translate="false"> integer llGetStatus(integer status) Returns value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) </string> - <string name="LSLTipText_llSetScale"> + <string name="LSLTipText_llSetScale" translate="false"> llSetScale(vector scale) Sets the scale of the prim </string> - <string name="LSLTipText_llGetScale"> + <string name="LSLTipText_llGetScale" translate="false"> vector llGetScale() Returns the scale of the prim </string> - <string name="LSLTipText_llSetColor"> + <string name="LSLTipText_llSetColor" translate="false"> llSetColor(vector color, integer face) Sets the color on face of the prim </string> - <string name="LSLTipText_llGetAlpha"> + <string name="LSLTipText_llGetAlpha" translate="false"> float llGetAlpha(integer face) Returns the alpha of face </string> - <string name="LSLTipText_llSetAlpha"> + <string name="LSLTipText_llSetAlpha" translate="false"> llSetAlpha(float alpha, integer face) Sets the alpha on face </string> - <string name="LSLTipText_llGetColor"> + <string name="LSLTipText_llGetColor" translate="false"> vector llGetColor(integer face) Returns the color on face </string> - <string name="LSLTipText_llSetTexture"> + <string name="LSLTipText_llSetTexture" translate="false"> llSetTexture(string texture, integer face) Sets the texture of face or ALL_SIDES </string> - <string name="LSLTipText_llScaleTexture"> + <string name="LSLTipText_llScaleTexture" translate="false"> llScaleTexture(float u, float v, integer face) Sets the texture u & v scales for the chosen face or ALL_SIDES </string> - <string name="LSLTipText_llOffsetTexture"> + <string name="LSLTipText_llOffsetTexture" translate="false"> llOffsetTexture(float u, float v, integer face) Sets the texture u & v offsets for the chosen face or ALL_SIDES </string> - <string name="LSLTipText_llRotateTexture"> + <string name="LSLTipText_llRotateTexture" translate="false"> llRotateTexture(float rotation, integer face) Sets the texture rotation for the chosen face </string> - <string name="LSLTipText_llGetTexture"> + <string name="LSLTipText_llGetTexture" translate="false"> string llGetTexture(integer face) Returns a string that is the texture on face (the inventory name if it is a texture in the prim's inventory, otherwise the key) </string> - <string name="LSLTipText_llSetPos"> + <string name="LSLTipText_llSetPos" translate="false"> llSetPos(vector pos) Moves the object or prim towards pos without using physics (if the script isn't physical) </string> - <string name="LSLTipText_llGetPos"> + <string name="LSLTipText_llGetPos" translate="false"> vector llGetPos() Returns the position of the task in region coordinates </string> - <string name="LSLTipText_llGetLocalPos"> + <string name="LSLTipText_llGetLocalPos" translate="false"> vector llGetLocalPos() Returns the position relative to the root </string> - <string name="LSLTipText_llSetRot"> + <string name="LSLTipText_llSetRot" translate="false"> llSetRot(rotation rot) Sets the rotation </string> - <string name="LSLTipText_llGetRot"> + <string name="LSLTipText_llGetRot" translate="false"> rotation llGetRot() Returns the rotation relative to the region's axes </string> - <string name="LSLTipText_llGetLocalRot"> + <string name="LSLTipText_llGetLocalRot" translate="false"> rotation llGetLocalRot() Returns the rotation local to the root </string> - <string name="LSLTipText_llSetForce"> + <string name="LSLTipText_llSetForce" translate="false"> llSetForce(vector force, integer local) Applies force to the object (if the script is physical), in local coords if local == TRUE </string> - <string name="LSLTipText_llGetForce"> + <string name="LSLTipText_llGetForce" translate="false"> vector llGetForce() Returns the force (if the script is physical) </string> - <string name="LSLTipText_llTarget"> + <string name="LSLTipText_llTarget" translate="false"> integer llTarget(vector position, float range) Sets positions within range of position as a target and return an ID for the target </string> - <string name="LSLTipText_llTargetRemove"> + <string name="LSLTipText_llTargetRemove" translate="false"> llTargetRemove(integer number) Removes positional target number registered with llTarget </string> - <string name="LSLTipText_llRotTarget"> + <string name="LSLTipText_llRotTarget" translate="false"> integer llRotTarget(rotation rot, float error) Set rotations with error of rot as a rotational target and return an ID for the rotational target </string> - <string name="LSLTipText_llRotTargetRemove"> + <string name="LSLTipText_llRotTargetRemove" translate="false"> llRotTargetRemove(integer number) Removes rotational target number registered with llRotTarget </string> - <string name="LSLTipText_llMoveToTarget"> + <string name="LSLTipText_llMoveToTarget" translate="false"> llMoveToTarget(vector target, float tau) Critically damps to target in tau seconds (if the script is physical) </string> - <string name="LSLTipText_llStopMoveToTarget"> + <string name="LSLTipText_llStopMoveToTarget" translate="false"> llStopMoveToTarget() Stops critically damped motion </string> - <string name="LSLTipText_llApplyImpulse"> + <string name="LSLTipText_llApplyImpulse" translate="false"> llApplyImpulse(vector force, integer local) Applies impulse to object (if the script is physical), in local coords if local == TRUE </string> - <string name="LSLTipText_llApplyRotationalImpulse"> + <string name="LSLTipText_llApplyRotationalImpulse" translate="false"> llApplyRotationalImpulse(vector force, integer local) Applies rotational impulse to object (if the script is physical), in local coords if local == TRUE </string> - <string name="LSLTipText_llSetTorque"> + <string name="LSLTipText_llSetTorque" translate="false"> llSetTorque(vector torque, integer local) Sets the torque of object (if the script is physical), in local coords if local == TRUE </string> - <string name="LSLTipText_llGetTorque"> + <string name="LSLTipText_llGetTorque" translate="false"> vector llGetTorque() Returns the torque (if the script is physical) </string> - <string name="LSLTipText_llSetForceAndTorque"> + <string name="LSLTipText_llSetForceAndTorque" translate="false"> llSetForceAndTorque(vector force, vector torque, integer local) Sets the force and torque of object (if the script is physical), in local coords if local == TRUE </string> - <string name="LSLTipText_llGetVel"> + <string name="LSLTipText_llGetVel" translate="false"> vector llGetVel() Returns the velocity of the object </string> - <string name="LSLTipText_llGetAccel"> + <string name="LSLTipText_llGetAccel" translate="false"> vector llGetAccel() Returns the acceleration of the object relative to the region's axes </string> - <string name="LSLTipText_llGetOmega"> + <string name="LSLTipText_llGetOmega" translate="false"> vector llGetOmega() Returns the rotation velocity in radians per second </string> - <string name="LSLTipText_llGetTimeOfDay"> + <string name="LSLTipText_llGetTimeOfDay" translate="false"> float llGetTimeOfDay() Returns the time in seconds since [SECOND_LIFE] server midnight or since region up-time, whichever is smaller </string> - <string name="LSLTipText_llGetWallclock"> + <string name="LSLTipText_llGetWallclock" translate="false"> float llGetWallclock() Returns the time in seconds since midnight California Pacific time (PST/PDT) </string> - <string name="LSLTipText_llGetTime"> + <string name="LSLTipText_llGetTime" translate="false"> float llGetTime() Returns the time in seconds since the last region reset, script reset, or call to either llResetTime or llGetAndResetTime </string> - <string name="LSLTipText_llResetTime"> + <string name="LSLTipText_llResetTime" translate="false"> llResetTime() Sets the script timer to zero </string> - <string name="LSLTipText_llGetAndResetTime"> + <string name="LSLTipText_llGetAndResetTime" translate="false"> float llGetAndResetTime() Returns the script time in seconds and then resets the script timer to zero </string> - <string name="LSLTipText_llSound"> + <string name="LSLTipText_llSound" translate="false"> llSound(string sound, float volume, integer queue, integer loop) Plays sound at volume and whether it should loop or not </string> - <string name="LSLTipText_llPlaySound"> + <string name="LSLTipText_llPlaySound" translate="false"> llPlaySound(string sound, float volume) Plays attached sound once at volume (0.0 - 1.0) </string> - <string name="LSLTipText_llLoopSound"> + <string name="LSLTipText_llLoopSound" translate="false"> llLoopSound(string sound, float volume) Plays attached sound looping indefinitely at volume (0.0 - 1.0) </string> - <string name="LSLTipText_llLoopSoundMaster"> + <string name="LSLTipText_llLoopSoundMaster" translate="false"> llLoopSoundMaster(string sound, float volume) Plays attached sound looping at volume (0.0 - 1.0), declares it a sync master </string> - <string name="LSLTipText_llLoopSoundSlave"> + <string name="LSLTipText_llLoopSoundSlave" translate="false"> llLoopSoundSlave(string sound, float volume) Plays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master </string> - <string name="LSLTipText_llPlaySoundSlave"> + <string name="LSLTipText_llPlaySoundSlave" translate="false"> llPlaySoundSlave(string sound, float volume) Plays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master </string> - <string name="LSLTipText_llTriggerSound"> + <string name="LSLTipText_llTriggerSound" translate="false"> llTriggerSound(string sound, float volume) Plays sound at volume (0.0 - 1.0), centered at but not attached to object </string> - <string name="LSLTipText_llStopSound"> + <string name="LSLTipText_llStopSound" translate="false"> llStopSound() Stops currently attached sound </string> - <string name="LSLTipText_llPreloadSound"> + <string name="LSLTipText_llPreloadSound" translate="false"> llPreloadSound(string sound) Preloads a sound on viewers within range </string> - <string name="LSLTipText_llGetSubString"> + <string name="LSLTipText_llGetSubString" translate="false"> string llGetSubString(string src, integer start, integer end) Returns the indicated substring </string> - <string name="LSLTipText_llDeleteSubString"> + <string name="LSLTipText_llDeleteSubString" translate="false"> string llDeleteSubString(string src, integer start, integer end) Removes the indicated substring and returns the result </string> - <string name="LSLTipText_llInsertString"> + <string name="LSLTipText_llInsertString" translate="false"> string llInsertString(string dst, integer position, string src) Returns a destination string dst with the string src inserted starting at position pos </string> - <string name="LSLTipText_llToUpper"> + <string name="LSLTipText_llToUpper" translate="false"> string llToUpper(string src) Returns a string that is src with all upper-case characters </string> - <string name="LSLTipText_llToLower"> + <string name="LSLTipText_llToLower" translate="false"> string llToLower(string src) Returns a string that is src with all lower-case characters </string> - <string name="LSLTipText_llGiveMoney"> + <string name="LSLTipText_llGiveMoney" translate="false"> llGiveMoney(key destination, integer amount) Transfers amount of L$ from script owner to destination </string> - <string name="LSLTipText_llMakeExplosion"> + <string name="LSLTipText_llMakeExplosion" translate="false"> llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) Makes a round explosion of particles </string> - <string name="LSLTipText_llMakeFountain"> + <string name="LSLTipText_llMakeFountain" translate="false"> llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset) Makes a fountain of particles </string> - <string name="LSLTipText_llMakeSmoke"> + <string name="LSLTipText_llMakeSmoke" translate="false"> llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) Makes smoke like particles </string> - <string name="LSLTipText_llMakeFire"> + <string name="LSLTipText_llMakeFire" translate="false"> llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) Makes fire like particles </string> - <string name="LSLTipText_llRezObject"> + <string name="LSLTipText_llRezObject" translate="false"> llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param) Instantiates owner's inventory object at pos with velocity vel and rotation rot with start parameter param </string> - <string name="LSLTipText_llLookAt"> + <string name="LSLTipText_llLookAt" translate="false"> llLookAt(vector target, float strength, float damping) Causes object to point its up axis (positive z) towards target, while keeping its forward axis (positive x) below the horizon </string> - <string name="LSLTipText_llStopLookAt"> + <string name="LSLTipText_llStopLookAt" translate="false"> llStopLookAt() Stops causing object to point at a target </string> - <string name="LSLTipText_llSetTimerEvent"> + <string name="LSLTipText_llSetTimerEvent" translate="false"> llSetTimerEvent(float sec) Causes the timer event to be triggered a maximum of once every sec seconds </string> - <string name="LSLTipText_llSleep"> + <string name="LSLTipText_llSleep" translate="false"> llSleep(float sec) Puts the script to sleep for sec seconds </string> - <string name="LSLTipText_llGetMass"> + <string name="LSLTipText_llGetMass" translate="false"> float llGetMass() Returns the mass of object that the script is attached to </string> - <string name="LSLTipText_llCollisionFilter"> + <string name="LSLTipText_llCollisionFilter" translate="false"> llCollisionFilter(string name, key id, integer accept) Sets the collision filter, exclusively or inclusively. If accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id </string> - <string name="LSLTipText_llTakeControls"> + <string name="LSLTipText_llTakeControls" translate="false"> llTakeControls(integer controls, integer accept, integer pass_on) Allows for intercepting keyboard and mouse clicks from the agent the script has permissions for </string> - <string name="LSLTipText_llReleaseControls"> + <string name="LSLTipText_llReleaseControls" translate="false"> llReleaseControls() Stops taking inputs that were taken with llTakeControls </string> - <string name="LSLTipText_llAttachToAvatar"> + <string name="LSLTipText_llAttachToAvatar" translate="false"> llAttachToAvatar(integer attach_point) Attaches the object to the avatar who has granted permission to the script </string> - <string name="LSLTipText_llDetachFromAvatar"> + <string name="LSLTipText_llDetachFromAvatar" translate="false"> llDetachFromAvatar() Detaches object from avatar </string> - <string name="LSLTipText_llTakeCamera"> + <string name="LSLTipText_llTakeCamera" translate="false"> llTakeCamera(key avatar) Moves avatar's viewpoint to task </string> - <string name="LSLTipText_llReleaseCamera"> + <string name="LSLTipText_llReleaseCamera" translate="false"> llReleaseCamera(key avatar) Returns camera to agent avatar </string> - <string name="LSLTipText_llGetOwner"> + <string name="LSLTipText_llGetOwner" translate="false"> key llGetOwner() Returns the object owner's UUID </string> - <string name="LSLTipText_llInstantMessage"> + <string name="LSLTipText_llInstantMessage" translate="false"> llInstantMessage(key user, string message) Sends the specified string as an Instant Message to the user </string> - <string name="LSLTipText_llEmail"> + <string name="LSLTipText_llEmail" translate="false"> llEmail(string address, string subject, string message) Sends an email to address with the subject and message </string> - <string name="LSLTipText_llGetNextEmail"> + <string name="LSLTipText_llGetNextEmail" translate="false"> llGetNextEmail(string address, string subject) Gets the next waiting email that comes from address, with specified subject </string> - <string name="LSLTipText_llGetKey"> + <string name="LSLTipText_llGetKey" translate="false"> key llGetKey() Returns the key of the prim the script is attached to </string> - <string name="LSLTipText_llSetBuoyancy"> + <string name="LSLTipText_llSetBuoyancy" translate="false"> llSetBuoyancy(float buoyancy) Sets the buoyancy of the task or object (0 is disabled, < 1.0 sinks, 1.0 floats, > 1.0 rises) </string> - <string name="LSLTipText_llSetHoverHeight"> + <string name="LSLTipText_llSetHoverHeight" translate="false"> llSetHoverHeight(float height, integer water, float tau) Critically damps to a height above the ground (or water) in tau seconds </string> - <string name="LSLTipText_llStopHover"> + <string name="LSLTipText_llStopHover" translate="false"> llStopHover() Stops hovering to a height </string> - <string name="LSLTipText_llMinEventDelay"> + <string name="LSLTipText_llMinEventDelay" translate="false"> llMinEventDelay(float delay) Sets the minimum time between events being handled </string> - <string name="LSLTipText_llSoundPreload"> + <string name="LSLTipText_llSoundPreload" translate="false"> llSoundPreload(string sound) Preloads a sound on viewers within range </string> - <string name="LSLTipText_llRotLookAt"> + <string name="LSLTipText_llRotLookAt" translate="false"> llRotLookAt(rotation target, float strength, float damping) Causes object name to point its forward axis towards target </string> - <string name="LSLTipText_llStringLength"> + <string name="LSLTipText_llStringLength" translate="false"> integer llStringLength(string str) Returns the length of string </string> - <string name="LSLTipText_llStartAnimation"> + <string name="LSLTipText_llStartAnimation" translate="false"> llStartAnimation(string anim) Starts animation anim for agent that granted PERMISSION_TRIGGER_ANIMATION if the permission has not been revoked </string> - <string name="LSLTipText_llStopAnimation"> + <string name="LSLTipText_llStopAnimation" translate="false"> llStopAnimation(string anim) Stops animation anim for agent that granted permission </string> - <string name="LSLTipText_llPointAt"> + <string name="LSLTipText_llPointAt" translate="false"> llPointAt(vector pos) Makes agent that owns object point at pos </string> - <string name="LSLTipText_llStopPointAt"> + <string name="LSLTipText_llStopPointAt" translate="false"> llStopPointAt() Stops pointing agent that owns object </string> - <string name="LSLTipText_llTargetOmega"> + <string name="LSLTipText_llTargetOmega" translate="false"> llTargetOmega(vector axis, float spinrate, float gain) Rotates the object around axis at spinrate with strength gain </string> - <string name="LSLTipText_llGetStartParameter"> + <string name="LSLTipText_llGetStartParameter" translate="false"> integer llGetStartParameter() Returns an integer that is the script start/rez parameter </string> - <string name="LSLTipText_llGodLikeRezObject"> + <string name="LSLTipText_llGodLikeRezObject" translate="false"> llGodLikeRezObject(key inventory, vector pos) Rezzes directly off of UUID if owner is in God Mode </string> - <string name="LSLTipText_llRequestPermissions"> + <string name="LSLTipText_llRequestPermissions" translate="false"> llRequestPermissions(key agent, integer perm) Asks the agent for permission to run certain classes of functions </string> - <string name="LSLTipText_llGetPermissionsKey"> + <string name="LSLTipText_llGetPermissionsKey" translate="false"> key llGetPermissionsKey() Returns the key of the avatar that last granted permissions to the script </string> - <string name="LSLTipText_llGetPermissions"> + <string name="LSLTipText_llGetPermissions" translate="false"> integer llGetPermissions() Returns an integer bitfield with the permissions that have been granted </string> - <string name="LSLTipText_llGetLinkNumber"> + <string name="LSLTipText_llGetLinkNumber" translate="false"> integer llGetLinkNumber() Returns the link number of the prim containing the script (0 means not linked, 1 the prim is the root, 2 the prim is the first child, etc) </string> - <string name="LSLTipText_llSetLinkColor"> + <string name="LSLTipText_llSetLinkColor" translate="false"> llSetLinkColor(integer linknumber, vector color, integer face) Sets face to color if a task exists in the link chain at linknumber </string> - <string name="LSLTipText_llCreateLink"> + <string name="LSLTipText_llCreateLink" translate="false"> llCreateLink(key target, integer parent) Attempts to link the script's object with the target (requires that PERMISSION_CHANGE_LINKS be granted). If parent == TRUE, then the script's object becomes the root </string> - <string name="LSLTipText_llBreakLink"> + <string name="LSLTipText_llBreakLink" translate="false"> llBreakLink(integer linknum) Delinks the prim with the given link number in a linked object set (requires that PERMISSION_CHANGE_LINKS be granted) </string> - <string name="LSLTipText_llBreakAllLinks"> + <string name="LSLTipText_llBreakAllLinks" translate="false"> llBreakAllLinks() Delinks all prims in the link set (requires that PERMISSION_CHANGE_LINKS be granted) </string> - <string name="LSLTipText_llGetLinkKey"> + <string name="LSLTipText_llGetLinkKey" translate="false"> key llGetLinkKey(integer linknumber) Returns the key of the linked prim linknumber </string> - <string name="LSLTipText_llGetLinkName"> + <string name="LSLTipText_llGetLinkName" translate="false"> string llGetLinkName(integer linknumber) Returns the name of linknumber in a link set </string> - <string name="LSLTipText_llGetInventoryNumber"> + <string name="LSLTipText_llGetInventoryNumber" translate="false"> integer llGetInventoryNumber(integer type) Returns the number of items of a given type (INVENTORY_* flag) in the prim's inventory </string> - <string name="LSLTipText_llGetInventoryName"> + <string name="LSLTipText_llGetInventoryName" translate="false"> string llGetInventoryName(integer type, integer number) Returns the name of the inventory item number of a given type </string> - <string name="LSLTipText_llSetScriptState"> + <string name="LSLTipText_llSetScriptState" translate="false"> llSetScriptState(string name, integer run) Sets the running state of the specified script </string> - <string name="LSLTipText_llGetEnergy"> + <string name="LSLTipText_llGetEnergy" translate="false"> float llGetEnergy() Returns how much energy is in the object as a percentage of maximum </string> - <string name="LSLTipText_llGiveInventory"> + <string name="LSLTipText_llGiveInventory" translate="false"> llGiveInventory(key destination, string inventory) Gives inventory to destination </string> - <string name="LSLTipText_llRemoveInventory"> + <string name="LSLTipText_llRemoveInventory" translate="false"> llRemoveInventory(string item) Removes the named inventory item </string> - <string name="LSLTipText_llSetText"> + <string name="LSLTipText_llSetText" translate="false"> llSetText(string text, vector color, float alpha) Displays text that hovers over the prim with specific color and translucency specified with alpha </string> - <string name="LSLTipText_llWater"> + <string name="LSLTipText_llWater" translate="false"> float llWater(vector offset) Returns the water height below the object position + offset </string> - <string name="LSLTipText_llPassTouches"> + <string name="LSLTipText_llPassTouches" translate="false"> llPassTouches(integer pass) If pass == TRUE, touches are passed from children on to parents </string> - <string name="LSLTipText_llRequestAgentData"> + <string name="LSLTipText_llRequestAgentData" translate="false"> key llRequestAgentData(key id, integer data) Requests data about agent id. When data is available the dataserver event will be raised. </string> - <string name="LSLTipText_llRequestInventoryData"> + <string name="LSLTipText_llRequestInventoryData" translate="false"> key llRequestInventoryData(string name) Requests data from object's inventory object. When data is available the dataserver event will be raised. </string> - <string name="LSLTipText_llSetDamage"> + <string name="LSLTipText_llSetDamage" translate="false"> llSetDamage(float damage) Sets the amount of damage that will be done when this object hits an avatar. </string> - <string name="LSLTipText_llTeleportAgentHome"> + <string name="LSLTipText_llTeleportAgentHome" translate="false"> llTeleportAgentHome(key id) Teleports avatar on the owner's land to their home location without any warning </string> - <string name="LSLTipText_llModifyLand"> + <string name="LSLTipText_llModifyLand" translate="false"> llModifyLand(integer action, integer brush) Modifies land using the specified action on the specified brush size of land </string> - <string name="LSLTipText_llCollisionSound"> + <string name="LSLTipText_llCollisionSound" translate="false"> llCollisionSound(string impact_sound, float impact_volume) Suppresses default collision sounds, replaces default impact sounds with impact_sound at the volume impact_volume </string> - <string name="LSLTipText_llCollisionSprite"> + <string name="LSLTipText_llCollisionSprite" translate="false"> llCollisionSprite(string impact_sprite) Suppresses default collision sprites, replaces default impact sprite with impact_sprite (use an empty string to just suppress) </string> - <string name="LSLTipText_llGetAnimation"> + <string name="LSLTipText_llGetAnimation" translate="false"> string llGetAnimation(key id) Returns the name of the currently playing locomotion animation for avatar id </string> - <string name="LSLTipText_llResetScript"> + <string name="LSLTipText_llResetScript" translate="false"> llResetScript() Resets the script </string> - <string name="LSLTipText_llMessageLinked"> + <string name="LSLTipText_llMessageLinked" translate="false"> llMessageLinked(integer linknum, integer num, string str, key id) Allows scripts in the same object to communicate. Triggers a link_message event with the same parameters num, str, and id in all scripts in the prim(s) described by linknum. </string> - <string name="LSLTipText_llPushObject"> + <string name="LSLTipText_llPushObject" translate="false"> llPushObject(key id, vector impulse, vector ang_impulse, integer local) Applies impulse and ang_impulse to object id </string> - <string name="LSLTipText_llPassCollisions"> + <string name="LSLTipText_llPassCollisions" translate="false"> llPassCollisions(integer pass) If pass == TRUE, collisions are passed from children on to parents (default is FALSE) </string> - <string name="LSLTipText_llGetScriptName"> + <string name="LSLTipText_llGetScriptName" translate="false"> string llGetScriptName() Returns the name of the script that this function is used in </string> - <string name="LSLTipText_llGetNumberOfSides"> + <string name="LSLTipText_llGetNumberOfSides" translate="false"> integer llGetNumberOfSides() Returns the number of faces (or sides) of the prim </string> - <string name="LSLTipText_llAxisAngle2Rot"> + <string name="LSLTipText_llAxisAngle2Rot" translate="false"> rotation llAxisAngle2Rot(vector axis, float angle) Returns the rotation that is a generated angle about axis </string> - <string name="LSLTipText_llRot2Axis"> + <string name="LSLTipText_llRot2Axis" translate="false"> vector llRot2Axis(rotation rot) Returns the rotation axis represented by rot </string> - <string name="LSLTipText_llRot2Angle"> + <string name="LSLTipText_llRot2Angle" translate="false"> float llRot2Angle(rotation rot) Returns the rotation angle represented by rot </string> - <string name="LSLTipText_llAcos"> + <string name="LSLTipText_llAcos" translate="false"> float llAcos(float val) Returns the arccosine in radians of val </string> - <string name="LSLTipText_llAsin"> + <string name="LSLTipText_llAsin" translate="false"> float llAsin(float val) Returns the arcsine in radians of val </string> - <string name="LSLTipText_llAngleBetween"> + <string name="LSLTipText_llAngleBetween" translate="false"> float llAngleBetween(rotation a, rotation b) Returns angle between rotation a and b </string> - <string name="LSLTipText_llGetInventoryKey"> + <string name="LSLTipText_llGetInventoryKey" translate="false"> key llGetInventoryKey(string name) Returns the key that is the UUID of the inventory name </string> - <string name="LSLTipText_llAllowInventoryDrop"> + <string name="LSLTipText_llAllowInventoryDrop" translate="false"> llAllowInventoryDrop(integer add) If add == TRUE, users without modify permissions can still drop inventory items onto a prim </string> - <string name="LSLTipText_llGetSunDirection"> + <string name="LSLTipText_llGetSunDirection" translate="false"> vector llGetSunDirection() Returns a normalized vector of the direction of the sun in the region </string> - <string name="LSLTipText_llGetTextureOffset"> + <string name="LSLTipText_llGetTextureOffset" translate="false"> vector llGetTextureOffset(integer face) Returns the texture offset of face in the x and y components of a vector </string> - <string name="LSLTipText_llGetTextureScale"> + <string name="LSLTipText_llGetTextureScale" translate="false"> vector llGetTextureScale(integer side) Returns the texture scale of side in the x and y components of a vector </string> - <string name="LSLTipText_llGetTextureRot"> + <string name="LSLTipText_llGetTextureRot" translate="false"> float llGetTextureRot(integer side) Returns the texture rotation of side </string> - <string name="LSLTipText_llSubStringIndex"> + <string name="LSLTipText_llSubStringIndex" translate="false"> integer llSubStringIndex(string source, string pattern) Returns an integer that is the index in source where pattern first appears. (Returns -1 if not found) </string> - <string name="LSLTipText_llGetOwnerKey"> + <string name="LSLTipText_llGetOwnerKey" translate="false"> key llGetOwnerKey(key id) Returns the owner of object id </string> - <string name="LSLTipText_llGetCenterOfMass"> + <string name="LSLTipText_llGetCenterOfMass" translate="false"> vector llGetCenterOfMass() Returns the prim's center of mass (unless called from the root prim, where it returns the object's center of mass) </string> - <string name="LSLTipText_llListSort"> + <string name="LSLTipText_llListSort" translate="false"> list llListSort(list src, integer stride, integer ascending) Sorts the list into blocks of stride, in ascending order if ascending == TRUE. The sort order is affected by type. </string> - <string name="LSLTipText_llGetListLength"> + <string name="LSLTipText_llGetListLength" translate="false"> integer llGetListLength(list src) Returns the number of elements in the list </string> - <string name="LSLTipText_llList2Integer"> + <string name="LSLTipText_llList2Integer" translate="false"> integer llList2Integer(list src, integer index) Copies the integer at index in the list </string> - <string name="LSLTipText_llList2Float"> + <string name="LSLTipText_llList2Float" translate="false"> float llList2Float(list src, integer index) Copies the float at index in the list </string> - <string name="LSLTipText_llList2String"> + <string name="LSLTipText_llList2String" translate="false"> string llList2String(list src, integer index) Copies the string at index in the list </string> - <string name="LSLTipText_llList2Key"> + <string name="LSLTipText_llList2Key" translate="false"> key llList2Key(list src, integer index) Copies the key at index in the list </string> - <string name="LSLTipText_llList2Vector"> + <string name="LSLTipText_llList2Vector" translate="false"> vector llList2Vector(list src, integer index) Copies the vector at index in the list </string> - <string name="LSLTipText_llList2Rot"> + <string name="LSLTipText_llList2Rot" translate="false"> rotation llList2Rot(list src, integer index) Copies the rotation at index in the list </string> - <string name="LSLTipText_llList2List"> + <string name="LSLTipText_llList2List" translate="false"> list llList2List(list src, integer start, integer end) Copies the slice of the list from start to end </string> - <string name="LSLTipText_llDeleteSubList"> + <string name="LSLTipText_llDeleteSubList" translate="false"> list llDeleteSubList(list src, integer start, integer end) Removes the slice from start to end and returns the remainder of the list </string> - <string name="LSLTipText_llGetListEntryType"> + <string name="LSLTipText_llGetListEntryType" translate="false"> integer llGetListEntryType(list src, integer index) Returns the type of the index entry in the list (TYPE_INTEGER, TYPE_FLOAT, TYPE_STRING, TYPE_KEY, TYPE_VECTOR, TYPE_ROTATION, or TYPE_INVALID if index is off list) </string> - <string name="LSLTipText_llList2CSV"> + <string name="LSLTipText_llList2CSV" translate="false"> string llList2CSV(list src) Creates a string of comma separated values from list </string> - <string name="LSLTipText_llCSV2List"> + <string name="LSLTipText_llCSV2List" translate="false"> list llCSV2List(string src) Creates a list from a string of comma separated values </string> - <string name="LSLTipText_llListRandomize"> + <string name="LSLTipText_llListRandomize" translate="false"> list llListRandomize(list src, integer stride) Returns a randomized list of blocks of size stride </string> - <string name="LSLTipText_llList2ListStrided"> + <string name="LSLTipText_llList2ListStrided" translate="false"> list llList2ListStrided(list src, integer start, integer end, integer stride) Copies the strided slice of the list from start to end </string> - <string name="LSLTipText_llGetRegionCorner"> + <string name="LSLTipText_llGetRegionCorner" translate="false"> vector llGetRegionCorner() Returns a vector in meters that is the global location of the south-west corner of the region which the object is in </string> - <string name="LSLTipText_llListInsertList"> + <string name="LSLTipText_llListInsertList" translate="false"> list llListInsertList(list dest, list src, integer start) Returns a list that contains all the elements from dest but with the elements from src inserted at position start </string> - <string name="LSLTipText_llListFindList"> + <string name="LSLTipText_llListFindList" translate="false"> integer llListFindList(list src, list test) Returns the index of the first instance of test in src. (Returns -1 if not found) </string> - <string name="LSLTipText_llGetObjectName"> + <string name="LSLTipText_llGetObjectName" translate="false"> string llGetObjectName() Returns the name of the prim which the script is attached to </string> - <string name="LSLTipText_llSetObjectName"> + <string name="LSLTipText_llSetObjectName" translate="false"> llSetObjectName(string name) Sets the prim's name to the name parameter </string> - <string name="LSLTipText_llGetDate"> + <string name="LSLTipText_llGetDate" translate="false"> string llGetDate() Returns the current date in the UTC time zone in the format YYYY-MM-DD </string> - <string name="LSLTipText_llEdgeOfWorld"> + <string name="LSLTipText_llEdgeOfWorld" translate="false"> integer llEdgeOfWorld(vector pos, vector dir) Checks to see whether the border hit by dir from pos is the edge of the world (has no neighboring region) </string> - <string name="LSLTipText_llGetAgentInfo"> + <string name="LSLTipText_llGetAgentInfo" translate="false"> integer llGetAgentInfo(key id) Returns an integer bitfield containing the agent information about id. Returns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR. </string> - <string name="LSLTipText_llAdjustSoundVolume"> + <string name="LSLTipText_llAdjustSoundVolume" translate="false"> llAdjustSoundVolume(float volume) Adjusts volume of attached sound (0.0 - 1.0) </string> - <string name="LSLTipText_llSetSoundQueueing"> + <string name="LSLTipText_llSetSoundQueueing" translate="false"> llSetSoundQueueing(integer queue) Sets whether attached sounds wait for the current sound to finish (If queue == TRUE then queuing is enabled, if FALSE queuing is disabled [default]) </string> - <string name="LSLTipText_llSetSoundRadius"> + <string name="LSLTipText_llSetSoundRadius" translate="false"> llSetSoundRadius(float radius) Establishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered) </string> - <string name="LSLTipText_llKey2Name"> + <string name="LSLTipText_llKey2Name" translate="false"> string llKey2Name(key id) Returns the name of the prim or avatar specified by id. (The id must be a valid rezzed prim or avatar key in the current simulator, otherwise an empty string is returned.) </string> - <string name="LSLTipText_llSetTextureAnim"> + <string name="LSLTipText_llSetTextureAnim" translate="false"> llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate) Animates the texture on the specified face/faces </string> - <string name="LSLTipText_llTriggerSoundLimited"> + <string name="LSLTipText_llTriggerSoundLimited" translate="false"> llTriggerSoundLimited(string sound, float volume, vector top_north_east, vector bottom_south_west) Plays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to the box defined by vectors top_north_east and bottom_south_west </string> - <string name="LSLTipText_llEjectFromLand"> + <string name="LSLTipText_llEjectFromLand" translate="false"> llEjectFromLand(key avatar) Ejects avatar from the parcel </string> - <string name="LSLTipText_llParseString2List"> + <string name="LSLTipText_llParseString2List" translate="false"> list llParseString2List(string src, list separators, list spacers) Breaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each) </string> - <string name="LSLTipText_llOverMyLand"> + <string name="LSLTipText_llOverMyLand" translate="false"> integer llOverMyLand(key id) Returns TRUE if id is over land owned by the script owner, otherwise FALSE </string> - <string name="LSLTipText_llGetLandOwnerAt"> + <string name="LSLTipText_llGetLandOwnerAt" translate="false"> key llGetLandOwnerAt(vector pos) Returns the key of the land owner, returns NULL_KEY if public </string> - <string name="LSLTipText_llGetNotecardLine"> + <string name="LSLTipText_llGetNotecardLine" translate="false"> key llGetNotecardLine(string name, integer line) Returns line line of notecard name via the dataserver event </string> - <string name="LSLTipText_llGetAgentSize"> + <string name="LSLTipText_llGetAgentSize" translate="false"> vector llGetAgentSize(key id) If the avatar is in the same region, returns the size of the bounding box of the requested avatar by id, otherwise returns ZERO_VECTOR </string> - <string name="LSLTipText_llSameGroup"> + <string name="LSLTipText_llSameGroup" translate="false"> integer llSameGroup(key id) Returns TRUE if avatar id is in the same region and has the same active group, otherwise FALSE </string> - <string name="LSLTipText_llUnSit"> + <string name="LSLTipText_llUnSit" translate="false"> key llUnSit(key id) If avatar identified by id is sitting on the object the script is attached to or is over land owned by the object's owner, the avatar is forced to stand up </string> - <string name="LSLTipText_llGroundSlope"> + <string name="LSLTipText_llGroundSlope" translate="false"> vector llGroundSlope(vector offset) Returns the ground slope below the object position + offset </string> - <string name="LSLTipText_llGroundNormal"> + <string name="LSLTipText_llGroundNormal" translate="false"> vector llGroundNormal(vector offset) Returns the ground normal below the object position + offset </string> - <string name="LSLTipText_llGroundContour"> + <string name="LSLTipText_llGroundContour" translate="false"> vector llGroundCountour(vector offset) Returns the ground contour direction below the object position + offset </string> - <string name="LSLTipText_llGetAttached"> + <string name="LSLTipText_llGetAttached" translate="false"> integer llGetAttached() Returns the object's attachment point, or 0 if not attached </string> - <string name="LSLTipText_llGetFreeMemory"> + <string name="LSLTipText_llGetFreeMemory" translate="false"> integer llGetFreeMemory() Returns the number of free bytes of memory the script can use </string> - <string name="LSLTipText_llGetRegionName"> + <string name="LSLTipText_llGetRegionName" translate="false"> string llGetRegionName() Returns the current region name </string> - <string name="LSLTipText_llGetRegionTimeDilation"> + <string name="LSLTipText_llGetRegionTimeDilation" translate="false"> float llGetRegionTimeDilation() Returns the current time dilation as a float between 0.0 (full dilation) and 1.0 (no dilation) </string> - <string name="LSLTipText_llGetRegionFPS"> + <string name="LSLTipText_llGetRegionFPS" translate="false"> float llGetRegionFPS() Returns the mean region frames per second </string> - <string name="LSLTipText_llParticleSystem"> + <string name="LSLTipText_llParticleSystem" translate="false"> llParticleSystem(list rules) Creates a particle system based on rules. An empty list removes the particle system. List format is [ rule1, data1, rule2, data2 . . . rulen, datan ] </string> - <string name="LSLTipText_llGroundRepel"> + <string name="LSLTipText_llGroundRepel" translate="false"> llGroundRepel(float height, integer water, float tau) Critically damps to height if within height*0.5 of level (either above ground level, or above the higher of land and water if water == TRUE) </string> - <string name="LSLTipText_llGiveInventoryList"> + <string name="LSLTipText_llGiveInventoryList" translate="false"> llGiveInventoryList(key target, string folder, list inventory) Gives inventory items to target, creating a new folder to put them in </string> - <string name="LSLTipText_llSetVehicleType"> + <string name="LSLTipText_llSetVehicleType" translate="false"> llSetVehicleType(integer type) Sets the vehicle to one of the default types </string> - <string name="LSLTipText_llSetVehicleFloatParam"> + <string name="LSLTipText_llSetVehicleFloatParam" translate="false"> llSetVehicleFloatParam(integer param, float value) Sets the specified vehicle float parameter </string> - <string name="LSLTipText_llSetVehicleVectorParam"> + <string name="LSLTipText_llSetVehicleVectorParam" translate="false"> llSetVehicleVectorParam(integer param, vector vec) Sets the specified vehicle vector parameter </string> - <string name="LSLTipText_llSetVehicleRotationParam"> + <string name="LSLTipText_llSetVehicleRotationParam" translate="false"> llSetVehicleVectorParam(integer param, rotation rot) Sets the specified vehicle rotation parameter </string> - <string name="LSLTipText_llSetVehicleFlags"> + <string name="LSLTipText_llSetVehicleFlags" translate="false"> llSetVehicleFlags(integer flags) Sets the enabled bits in 'flags' </string> - <string name="LSLTipText_llRemoveVehicleFlags"> + <string name="LSLTipText_llRemoveVehicleFlags" translate="false"> llRemoveVehicleFlags(integer flags) Removes the enabled bits in 'flags' </string> - <string name="LSLTipText_llSitTarget"> + <string name="LSLTipText_llSitTarget" translate="false"> llSitTarget(vector offset, rotation rot) Sets the sit location for the prim. If offset == <0,0,0> then the sit target is removed. </string> - <string name="LSLTipText_llAvatarOnSitTarget"> + <string name="LSLTipText_llAvatarOnSitTarget" translate="false"> key llAvatarOnSitTarget() If an avatar is seated on the sit target, returns the avatar's key, otherwise NULL_KEY </string> - <string name="LSLTipText_llAddToLandPassList"> + <string name="LSLTipText_llAddToLandPassList" translate="false"> llAddToLandPassList(key avatar, float hours) Adds avatar to the land pass list for hours, or indefinitely if hours is 0 </string> - <string name="LSLTipText_llSetTouchText"> + <string name="LSLTipText_llSetTouchText" translate="false"> llSetTouchText(string text) Displays text rather than the default 'Touch' in the pie menu </string> - <string name="LSLTipText_llSetSitText"> + <string name="LSLTipText_llSetSitText" translate="false"> llSetSitText(string text) Displays text rather than the default 'Sit Here' in the pie menu </string> - <string name="LSLTipText_llSetCameraEyeOffset"> + <string name="LSLTipText_llSetCameraEyeOffset" translate="false"> llSetCameraEyeOffset(vector offset) Sets the camera eye offset for avatars that sit on the object </string> - <string name="LSLTipText_llSetCameraAtOffset"> + <string name="LSLTipText_llSetCameraAtOffset" translate="false"> llSetCameraAtOffset(vector offset) Sets the point the camera is looking at to offset for avatars that sit on the object </string> - <string name="LSLTipText_llDumpList2String"> + <string name="LSLTipText_llDumpList2String" translate="false"> string llDumpList2String(list src, string separator) Returns the list in a single string, using separator between the entries </string> - <string name="LSLTipText_llScriptDanger"> + <string name="LSLTipText_llScriptDanger" translate="false"> integer llScriptDanger(vector pos) Returns TRUE if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts </string> - <string name="LSLTipText_llDialog"> + <string name="LSLTipText_llDialog" translate="false"> llDialog(key avatar, string message, list buttons, integer chat_channel Shows a dialog box on the avatar's screen with a message and up to 12 buttons. If a button is pressed, the avatar says the text of the button label on chat_channel. </string> - <string name="LSLTipText_llVolumeDetect"> + <string name="LSLTipText_llVolumeDetect" translate="false"> llVolumeDetect(integer detect) If detect = TRUE, object works much like Phantom, but triggers collision_start and collision_end events when other objects start and stop interpenetrating. Must be applied to the root prim. </string> - <string name="LSLTipText_llResetOtherScript"> + <string name="LSLTipText_llResetOtherScript" translate="false"> llResetOtherScript(string name) Resets script name </string> - <string name="LSLTipText_llGetScriptState"> + <string name="LSLTipText_llGetScriptState" translate="false"> integer llGetScriptState(string name) Returns TRUE if the script name is running </string> - <string name="LSLTipText_llRemoteLoadScript"> + <string name="LSLTipText_llRemoteLoadScript" translate="false"> DEPRECATED! Please use llRemoteLoadScriptPin instead. </string> - <string name="LSLTipText_llSetRemoteScriptAccessPin"> + <string name="LSLTipText_llSetRemoteScriptAccessPin" translate="false"> llSetRemoteScriptAccessPin(integer pin) If pin is set to a non-zero number, allows a prim to have scripts remotely loaded via llRemoteLoadScriptPin when it passes in the correct pin. Otherwise, llRemoteLoadScriptPin is ignored. </string> - <string name="LSLTipText_llRemoteLoadScriptPin"> + <string name="LSLTipText_llRemoteLoadScriptPin" translate="false"> llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) Copies script name onto target, if the owner of this scripted object can modify target and is in the same region, and the matching pin is used. If running == TRUE, starts the script with start_param </string> - <string name="LSLTipText_llOpenRemoteDataChannel"> + <string name="LSLTipText_llOpenRemoteDataChannel" translate="false"> llOpenRemoteDataChannel() Creates a channel to listen for XML-RPC calls, and will trigger a remote_data event with channel id once it is available </string> - <string name="LSLTipText_llSendRemoteData"> + <string name="LSLTipText_llSendRemoteData" translate="false"> key llSendRemoteData(key channel, string dest, integer idata, string sdata) Sends an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata. Returns a key that is the message_id for the resulting remote_data events. </string> - <string name="LSLTipText_llRemoteDataReply"> + <string name="LSLTipText_llRemoteDataReply" translate="false"> llRemoteDataReply(key channel, key message_id, string sdata, integer idata) Sends an XML-RPC reply to message_id on channel with payload of string sdata and integer idata </string> - <string name="LSLTipText_llCloseRemoteDataChannel"> + <string name="LSLTipText_llCloseRemoteDataChannel" translate="false"> llCloseRemoteDataChannel(key channel) Closes XML-RPC channel </string> - <string name="LSLTipText_llMD5String"> + <string name="LSLTipText_llMD5String" translate="false"> string llMD5String(string src, integer nonce) Returns a string of 32 hex characters that is a RSA Data Security, Inc. MD5 Message-Digest Algorithm of src with nonce </string> - <string name="LSLTipText_llSetPrimitiveParams"> + <string name="LSLTipText_llSetPrimitiveParams" translate="false"> llSetPrimitiveParams(list rules) Sets the prim's parameters according to rules </string> - <string name="LSLTipText_llStringToBase64"> + <string name="LSLTipText_llStringToBase64" translate="false"> string llStringToBase64(string str) Converts a string to the Base64 representation of the string </string> - <string name="LSLTipText_llBase64ToString"> + <string name="LSLTipText_llBase64ToString" translate="false"> string llBase64ToString(string str) Converts a Base64 string to a conventional string. If the conversion creates any unprintable characters, they are converted to spaces. </string> - <string name="LSLTipText_llXorBase64Strings"> + <string name="LSLTipText_llXorBase64Strings" translate="false"> string llXorBase64Strings(string s1, string s2) DEPRECATED! Please use llXorBase64StringsCorrect instead. Incorrectly performs an exclusive or on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability. </string> - <string name="LSLTipText_llRemoteDataSetRegion"> + <string name="LSLTipText_llRemoteDataSetRegion" translate="false"> llRemoteDataSetRegion() DEPRECATED! Please use llOpenRemoteDataChannel instead. If an object using remote data channels changes regions, you must call this function to reregister the remote data channels. This call is not needed if the prim does not change regions. </string> - <string name="LSLTipText_llLog10"> + <string name="LSLTipText_llLog10" translate="false"> float llLog10(float val) Returns the base 10 logarithm of val. Returns zero if val <= 0. </string> - <string name="LSLTipText_llLog"> + <string name="LSLTipText_llLog" translate="false"> float llLog(float val) Returns the natural logarithm of val. Returns zero if val <= 0. </string> - <string name="LSLTipText_llGetAnimationList"> + <string name="LSLTipText_llGetAnimationList" translate="false"> list llGetAnimationList(key id) Returns a list of keys of playing animations for avatar described by id </string> - <string name="LSLTipText_llSetParcelMusicURL"> + <string name="LSLTipText_llSetParcelMusicURL" translate="false"> llSetParcelMusicURL(string url) Sets the streaming audio URL for the parcel which the object is on </string> - <string name="LSLTipText_llGetRootPosition"> + <string name="LSLTipText_llGetRootPosition" translate="false"> vector llGetRootPosition() Returns the position (in region coordinates) of the root prim of the object which the script is attached to </string> - <string name="LSLTipText_llGetRootRotation"> + <string name="LSLTipText_llGetRootRotation" translate="false"> rotation llGetRootRotation() Returns the rotation (relative to the region) of the root prim of the object which the script is attached to </string> - <string name="LSLTipText_llGetObjectDesc"> + <string name="LSLTipText_llGetObjectDesc" translate="false"> string llGetObjectDesc() Returns the description of the prim the script is attached to </string> - <string name="LSLTipText_llSetObjectDesc"> + <string name="LSLTipText_llSetObjectDesc" translate="false"> llSetObjectDesc(string name) Sets the prim's description </string> - <string name="LSLTipText_llGetCreator"> + <string name="LSLTipText_llGetCreator" translate="false"> key llGetCreator() Returns a key for the creator of the prim </string> - <string name="LSLTipText_llGetTimestamp"> + <string name="LSLTipText_llGetTimestamp" translate="false"> string llGetTimestamp() Returns the timestamp in the UTC time zone in the format: YYYY-MM-DDThh:mm:ss.ff..fZ </string> - <string name="LSLTipText_llSetLinkAlpha"> + <string name="LSLTipText_llSetLinkAlpha" translate="false"> llSetLinkAlpha(integer linknumber, float alpha, integer face) If a prim exists in the link chain at linknumber, sets face to alpha </string> - <string name="LSLTipText_llGetNumberOfPrims"> + <string name="LSLTipText_llGetNumberOfPrims" translate="false"> integer llGetNumberOfPrims() Returns the number of prims in a link set the script is attached to </string> - <string name="LSLTipText_llGetNumberOfNotecardLines"> + <string name="LSLTipText_llGetNumberOfNotecardLines" translate="false"> key llGetNumberOfNotecardLines(string name) Returns number of lines in notecard name via the dataserver event (cast return value to integer) </string> - <string name="LSLTipText_llGetBoundingBox"> + <string name="LSLTipText_llGetBoundingBox" translate="false"> list llGetBoundingBox(key object) Returns the bounding box around the object (including any linked prims) relative to its root prim, in a list in the format [ (vector) min_corner, (vector) max_corner ] </string> - <string name="LSLTipText_llGetGeometricCenter"> + <string name="LSLTipText_llGetGeometricCenter" translate="false"> vector llGetGeometricCenter() Returns the geometric center of the linked set the script is attached to. </string> - <string name="LSLTipText_llGetPrimitiveParams"> + <string name="LSLTipText_llGetPrimitiveParams" translate="false"> list llGetPrimitiveParams(list params) Returns the primitive parameters specified in the params list. </string> - <string name="LSLTipText_llIntegerToBase64"> + <string name="LSLTipText_llIntegerToBase64" translate="false"> string llIntegerToBase64(integer number) Returns a string that is a Base64 big endian encode of number </string> - <string name="LSLTipText_llBase64ToInteger"> + <string name="LSLTipText_llBase64ToInteger" translate="false"> integer llBase64ToInteger(string str) Returns an integer that is the str Base64 decoded as a big endian integer </string> - <string name="LSLTipText_llGetGMTclock"> + <string name="LSLTipText_llGetGMTclock" translate="false"> float llGetGMTclock() Returns the time in seconds since midnight GMT </string> - <string name="LSLTipText_llGetSimulatorHostname"> + <string name="LSLTipText_llGetSimulatorHostname" translate="false"> string llGetSimulatorHostname() Returns the hostname of the machine which the script is running on (same as string in viewer Help dialog) </string> - <string name="LSLTipText_llSetLocalRot"> + <string name="LSLTipText_llSetLocalRot" translate="false"> llSetLocalRot(rotation rot) Sets the rotation of a child prim relative to the root prim </string> - <string name="LSLTipText_llParseStringKeepNulls"> + <string name="LSLTipText_llParseStringKeepNulls" translate="false"> list llParseStringKeepNulls(string src, list separators, list spacers) Breaks src into a list, discarding separators, keeping spacers, keeping any null values generated. (separators and spacers must be lists of strings, maximum of 8 each) </string> - <string name="LSLTipText_llRezAtRoot"> + <string name="LSLTipText_llRezAtRoot" translate="false"> llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param) Instantiates owner's inventory object rotated to rot with its root at pos, moving at vel, using param as the start parameter </string> - <string name="LSLTipText_llGetObjectPermMask"> + <string name="LSLTipText_llGetObjectPermMask" translate="false"> integer llGetObjectPermMask(integer mask) Returns the requested permission mask for the root object the task is attached to </string> - <string name="LSLTipText_llSetObjectPermMask"> + <string name="LSLTipText_llSetObjectPermMask" translate="false"> llSetObjectPermMask(integer mask, integer value) Sets the given permission mask to the new value on the root object the task is attached to </string> - <string name="LSLTipText_llGetInventoryPermMask"> + <string name="LSLTipText_llGetInventoryPermMask" translate="false"> integer llGetInventoryPermMask(string item, integer mask) Returns the requested permission mask for the inventory item </string> - <string name="LSLTipText_llSetInventoryPermMask"> + <string name="LSLTipText_llSetInventoryPermMask" translate="false"> llSetInventoryPermMask(string item, integer mask, integer value) Sets the given permission mask to the new value on the inventory item </string> - <string name="LSLTipText_llGetInventoryCreator"> + <string name="LSLTipText_llGetInventoryCreator" translate="false"> key llGetInventoryCreator(string item) Returns a key for the creator of the inventory item </string> - <string name="LSLTipText_llOwnerSay"> + <string name="LSLTipText_llOwnerSay" translate="false"> llOwnerSay(string msg) Says msg to owner only. (Owner must be in the same region.) </string> - <string name="LSLTipText_llRequestSimulatorData"> + <string name="LSLTipText_llRequestSimulatorData" translate="false"> key llRequestSimulatorData(string simulator, integer data) Requests data about simulator. When data is available the dataserver event will be raised. </string> - <string name="LSLTipText_llForceMouselook"> + <string name="LSLTipText_llForceMouselook" translate="false"> llForceMouselook(integer mouselook) If mouselook is TRUE, any avatar that sits upon the prim will be forced into mouselook mode </string> - <string name="LSLTipText_llGetObjectMass"> + <string name="LSLTipText_llGetObjectMass" translate="false"> float llGetObjectMass(key id) Returns the mass of the avatar or object in the region </string> - <string name="LSLTipText_llListReplaceList"> + <string name="LSLTipText_llListReplaceList" translate="false"> list llListReplaceList(list dest, list src, integer start, integer end) Returns a list that is dest with start through end removed and src inserted at start </string> - <string name="LSLTipText_llLoadURL"> + <string name="LSLTipText_llLoadURL" translate="false"> llLoadURL(key avatar, string message, string url) Shows a dialog to avatar offering to load the web page at url with a message. If user clicks yes, launches the page in their web browser. </string> - <string name="LSLTipText_llParcelMediaCommandList"> + <string name="LSLTipText_llParcelMediaCommandList" translate="false"> llParcelMediaCommandList(list command) Sends a list of commands, some with arguments, to a parcel to control the playback of movies and other media </string> - <string name="LSLTipText_llParcelMediaQuery"> + <string name="LSLTipText_llParcelMediaQuery" translate="false"> list llParcelMediaQuery(list query) Returns a list containing results of the sent query </string> - <string name="LSLTipText_llModPow"> + <string name="LSLTipText_llModPow" translate="false"> integer llModPow(integer a, integer b, integer c) Returns a raised to the b power, mod c. ( (a**b)%c ) b is capped at 0xFFFF (16 bits). </string> - <string name="LSLTipText_llGetInventoryType"> + <string name="LSLTipText_llGetInventoryType" translate="false"> integer llGetInventoryType(string name) Returns the type of the inventory item name </string> - <string name="LSLTipText_llSetPayPrice"> + <string name="LSLTipText_llSetPayPrice" translate="false"> llSetPayPrice(integer price, list quick_pay_buttons) Sets the default amount on the dialog that appears when someone chooses to pay this prim </string> - <string name="LSLTipText_llGetCameraPos"> + <string name="LSLTipText_llGetCameraPos" translate="false"> vector llGetCameraPos() Returns the current camera position for the agent the task has permissions for </string> - <string name="LSLTipText_llGetCameraRot"> + <string name="LSLTipText_llGetCameraRot" translate="false"> rotation llGetCameraRot() Returns the current camera orientation for the agent the task has permissions for </string> - <string name="LSLTipText_llSetPrimURL"> + <string name="LSLTipText_llSetPrimURL" translate="false"> llSetPrimURL(string url) Updates the URL for the web page shown on the sides of the object </string> - <string name="LSLTipText_llRefreshPrimURL"> + <string name="LSLTipText_llRefreshPrimURL" translate="false"> llRefreshPrimURL() Reloads the web page shown on the sides of the object </string> - <string name="LSLTipText_llEscapeURL"> + <string name="LSLTipText_llEscapeURL" translate="false"> string llEscapeURL(string url) Returns an escaped/encoded version of url, replacing spaces with %20 etc. </string> - <string name="LSLTipText_llUnescapeURL"> + <string name="LSLTipText_llUnescapeURL" translate="false"> string llUnescapeURL(string url) Returns an unescaped/ unencoded version of url, replacing %20 with spaces etc. </string> - <string name="LSLTipText_llMapDestination"> + <string name="LSLTipText_llMapDestination" translate="false"> llMapDestination(string simname, vector pos, vector look_at) Opens the World Map centered on the region simname with pos highlighted. (NOTE: look_at currently does nothing.) Only works for scripts attached to avatar, or during touch events. </string> - <string name="LSLTipText_llAddToLandBanList"> + <string name="LSLTipText_llAddToLandBanList" translate="false"> llAddToLandBanList(key avatar, float hours) Adds avatar to the land ban list for hours, or indefinitely if hours is 0 </string> - <string name="LSLTipText_llRemoveFromLandPassList"> + <string name="LSLTipText_llRemoveFromLandPassList" translate="false"> llRemoveFromLandPassList(key avatar) Removes avatar from the land pass list </string> - <string name="LSLTipText_llRemoveFromLandBanList"> + <string name="LSLTipText_llRemoveFromLandBanList" translate="false"> llRemoveFromLandBanList(key avatar) Removes avatar from the land ban list </string> - <string name="LSLTipText_llSetCameraParams"> + <string name="LSLTipText_llSetCameraParams" translate="false"> llSetCameraParams(list rules) Sets multiple camera parameters at once. List format is [ rule1, data1, rule2, data2 . . . rulen, datan ] </string> - <string name="LSLTipText_llClearCameraParams"> + <string name="LSLTipText_llClearCameraParams" translate="false"> llClearCameraParams() Resets all camera parameters to default values and turns off scripted camera control </string> - <string name="LSLTipText_llListStatistics"> + <string name="LSLTipText_llListStatistics" translate="false"> float llListStatistics(integer operation, list src) Performs statistical aggregate functions on list src using LIST_STAT_* operations </string> - <string name="LSLTipText_llGetUnixTime"> + <string name="LSLTipText_llGetUnixTime" translate="false"> integer llGetUnixTime() Returns the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock </string> - <string name="LSLTipText_llGetParcelFlags"> + <string name="LSLTipText_llGetParcelFlags" translate="false"> integer llGetParcelFlags(vector pos) Returns a mask of the parcel flags (PARCEL_FLAG_*) for the parcel that includes the point pos </string> - <string name="LSLTipText_llGetRegionFlags"> + <string name="LSLTipText_llGetRegionFlags" translate="false"> integer llGetRegionFlags() Returns the region flags (REGION_FLAG_*) for the region the object is in </string> - <string name="LSLTipText_llXorBase64StringsCorrect"> + <string name="LSLTipText_llXorBase64StringsCorrect" translate="false"> string llXorBase64StringsCorrect(string s1, string s2) Correctly performs an exclusive or on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1. </string> - <string name="LSLTipText_llHTTPRequest"> + <string name="LSLTipText_llHTTPRequest" translate="false"> llHTTPRequest(string url, list parameters, string body) Sends an HTTP request to the specified url with the body of the request and parameters </string> - <string name="LSLTipText_llResetLandBanList"> + <string name="LSLTipText_llResetLandBanList" translate="false"> llResetLandBanList() Removes all residents from the land ban list </string> - <string name="LSLTipText_llResetLandPassList"> + <string name="LSLTipText_llResetLandPassList" translate="false"> llResetLandPassList() Removes all residents from the land access/pass list </string> - <string name="LSLTipText_llGetObjectPrimCount"> + <string name="LSLTipText_llGetObjectPrimCount" translate="false"> integer llGetObjectPrimCount(key object_id) Returns the total number of prims for an object in the region </string> - <string name="LSLTipText_llGetParcelPrimOwners"> + <string name="LSLTipText_llGetParcelPrimOwners" translate="false"> list llGetParcelPrimOwners(vector pos) Returns a list of all residents who own objects on the parcel at pos and with individual prim counts. Requires owner-like permissions for the parcel. </string> - <string name="LSLTipText_llGetParcelPrimCount"> + <string name="LSLTipText_llGetParcelPrimCount" translate="false"> integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) Returns the number of prims on the parcel at pos of the given category. Categories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP </string> - <string name="LSLTipText_llGetParcelMaxPrims"> + <string name="LSLTipText_llGetParcelMaxPrims" translate="false"> integer llGetParcelMaxPrims(vector pos, integer sim_wide) Returns the maximum number of prims allowed on the parcel at pos </string> - <string name="LSLTipText_llGetParcelDetails"> + <string name="LSLTipText_llGetParcelDetails" translate="false"> list llGetParcelDetails(vector pos, list params) Returns the parcel details specified in params for the parcel at pos. Params is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA </string> - <string name="LSLTipText_llSetLinkPrimitiveParams"> + <string name="LSLTipText_llSetLinkPrimitiveParams" translate="false"> llSetLinkPrimitiveParams(integer linknumber, list rules) Sets primitive parameters for linknumber based on rules </string> - <string name="LSLTipText_llSetLinkTexture"> + <string name="LSLTipText_llSetLinkTexture" translate="false"> llSetLinkTexture(integer linknumber, string texture, integer face) Sets the texture of face for a task that exists in the link chain at linknumber </string> - <string name="LSLTipText_llStringTrim"> + <string name="LSLTipText_llStringTrim" translate="false"> string llStringTrim(string src, integer trim_type) Trims the leading and/or trailing white spaces from a string. trim_type can be STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL. </string> - <string name="LSLTipText_llRegionSay"> + <string name="LSLTipText_llRegionSay" translate="false"> llRegionSay(integer channel, string msg) Broadcasts msg on channel (not 0) that can be heard anywhere in the region by a script listening on channel </string> - <string name="LSLTipText_llGetObjectDetails"> + <string name="LSLTipText_llGetObjectDetails" translate="false"> list llGetObjectDetails(key id, list params) Returns the object details specified in params for the object with key id. Params are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR </string> - <string name="LSLTipText_llSetClickAction"> + <string name="LSLTipText_llSetClickAction" translate="false"> llSetClickAction(integer action) Sets the action performed when a prim is clicked upon </string> - <string name="LSLTipText_llGetRegionAgentCount"> + <string name="LSLTipText_llGetRegionAgentCount" translate="false"> integer llGetRegionAgentCount() Returns the number of avatars in the region </string> - <string name="LSLTipText_llTextBox"> + <string name="LSLTipText_llTextBox" translate="false"> llTextBox(key avatar, string message, integer chat_channel Shows a dialog box on the avatar's screen with the message. It contains a text box for input, and if entered that text is chatted on chat_channel. </string> - <string name="LSLTipText_llGetAgentLanguage"> + <string name="LSLTipText_llGetAgentLanguage" translate="false"> string llGetAgentLanguage(key avatar) Returns the language code of the preferred interface language of the avatar </string> - <string name="LSLTipText_llDetectedTouchUV"> + <string name="LSLTipText_llDetectedTouchUV" translate="false"> vector llDetectedTouchUV(integer index) Returns the u and v coordinates in the first two components of a vector, for the texture coordinates where the prim was touched in a triggered touch event </string> - <string name="LSLTipText_llDetectedTouchFace"> + <string name="LSLTipText_llDetectedTouchFace" translate="false"> integer llDetectedTouchFace(integer index) Returns the index of the face where the avatar clicked in a triggered touch event </string> - <string name="LSLTipText_llDetectedTouchPos"> + <string name="LSLTipText_llDetectedTouchPos" translate="false"> vector llDetectedTouchPos(integer index) Returns the position where the object was touched in a triggered touch event </string> - <string name="LSLTipText_llDetectedTouchNormal"> + <string name="LSLTipText_llDetectedTouchNormal" translate="false"> vector llDetectedTouchNormal(integer index) Returns the surface normal for a triggered touch event </string> - <string name="LSLTipText_llDetectedTouchBinormal"> + <string name="LSLTipText_llDetectedTouchBinormal" translate="false"> vector llDetectedTouchBinormal(integer index) Returns the surface binormal for a triggered touch event </string> - <string name="LSLTipText_llDetectedTouchST"> + <string name="LSLTipText_llDetectedTouchST" translate="false"> vector llDetectedTouchST(integer index) Returns the s and t coordinates in the first two components of a vector, for the surface coordinates where the prim was touched in a triggered touch event </string> - <string name="LSLTipText_llSHA1String"> + <string name="LSLTipText_llSHA1String" translate="false"> string llSHA1String(string src) Returns a string of 40 hex characters that is the SHA1 security Hash of src </string> - <string name="LSLTipText_llGetFreeURLs"> + <string name="LSLTipText_llGetFreeURLs" translate="false"> integer llGetFreeURLs() Returns the number of available URLs for the current script </string> - <string name="LSLTipText_llRequestURL"> + <string name="LSLTipText_llRequestURL" translate="false"> key llRequestURL() Requests one HTTP:// url for use by this object. An http_request event is triggered with the results. </string> - <string name="LSLTipText_llRequestSecureURL"> + <string name="LSLTipText_llRequestSecureURL" translate="false"> key llRequestSecureURL() Requests one HTTPS:// (SSL) url for use by this object. An http_request event is triggered with the results. </string> - <string name="LSLTipText_llReleaseURL"> + <string name="LSLTipText_llReleaseURL" translate="false"> llReleaseURL(string url) Releases the specified URL, it will no longer be usable </string> - <string name="LSLTipText_llHTTPResponse"> + <string name="LSLTipText_llHTTPResponse" translate="false"> llHTTPResponse(key request_id, integer status, string body) Responds to request_id with status and body </string> - <string name="LSLTipText_llGetHTTPHeader"> + <string name="LSLTipText_llGetHTTPHeader" translate="false"> string llGetHTTPHeader(key request_id, string header) Returns the value for header for request_id </string> - <string name="LSLTipText_llSetPrimMediaParams"> + <string name="LSLTipText_llSetPrimMediaParams" translate="false"> llSetPrimMediaParams(integer face, list params) Sets the media params for a particular face on an object. If media is not already on this object, add it. List is a set of name/value pairs in no particular order. Params not specified are unchanged, or if new media is added then set to the default specified. The possible names are below, along with the types of values and what they mean. </string> - <string name="LSLTipText_llGetPrimMediaParams"> + <string name="LSLTipText_llGetPrimMediaParams" translate="false"> list llGetPrimMediaParams(integer face, list params) Returns the media params for a particular face on an object, given the desired list of names, in the order requested. (Returns an empty list if no media exists on the face.) </string> - <string name="LSLTipText_llClearPrimMedia"> + <string name="LSLTipText_llClearPrimMedia" translate="false"> llClearPrimMedia(integer face) Clears (deletes) the media and all params from the given face. </string> @@ -1929,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> @@ -1993,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" /> @@ -2249,9 +2255,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Belly Size">Belly Size</string> <string name="Blonde Hair">Blonde Hair</string> <string name="Big Eyeball">Big Eyeball</string> - <string name="Big Hair Back">Big Hair Back</string> - <string name="Big Hair Front">Big Hair Front</string> - <string name="Big Hair Top">Big Hair Top</string> + <string name="Big Hair Back">Big Hair: Back</string> + <string name="Big Hair Front">Big Hair: Front</string> + <string name="Big Hair Top">Big Hair: Top</string> <string name="Body Fat">Body Fat</string> <string name="Body Thickness">Body Thickness</string> <string name="Breast Buoyancy">Breast Buoyancy</string> @@ -2308,7 +2314,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Hair Thickess">Hair Thickess</string> <string name="Hair Tilted Left">Hair Tilted Left</string> <string name="Hair Tilted Right">Hair Tilted Right</string> - <string name="Hair Volume">Hair Volume</string> + <string name="Hair Volume">Hair: Volume</string> <string name="Hand Size">Hand Size</string> <string name="Head Length">Head Length</string> <string name="Head Shape">Head Shape</string> @@ -2356,10 +2362,39 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Nostril Division">Nostril Division</string> <string name="Nostril Width">Nostril Width</string> <string name="Open Front">Open Front</string> + <string name="Lipstick Color">Lipstick Color</string> + <string name="Lipstick">Lipstick</string> + <string name="Lipgloss">Lipgloss</string> + <string name="Blush">Blush</string> + <string name="Blush Color">Blush Color</string> + <string name="Blush Opacity">Blush Opacity</string> + <string name="Inner Shadow">Inner Shadow</string> + <string name="In Shdw Color">Inner Shadow Color</string> + <string name="In Shdw Opacity">Inner Shadow Opacity</string> + <string name="Body Definition">Body Definition</string> + <string name="Body Freckles">Body Freckles</string> + <string name="Facial Definition">Facial Definition</string> + <string name="Hair Front">Hair: Front</string> + <string name="Hair Sides">Hair: Sides</string> + <string name="Hair Back">Hair: Back</string> + <string name="Front Fringe">Front Fringe</string> + <string name="Side Fringe">Side Fringe</string> + <string name="Back Fringe">Back Fringe</string> + <string name="Hair Sweep">Hair Sweep</string> + <string name="Pigtails">Pigtails</string> + <string name="Ponytail">Ponytail</string> + <string name="Hair Tilt">Hair Tilt</string> + <string name="Eyebrow Size">Eyebrow Size</string> + <string name="Eyebrow Density">Eyebrow Density</string> + <!-- string name="Hair Thickess">Hair Thickess</string Need a second string for Body Parts > Hair > Facial? --> + <string name="Sideburns">Sideburns</string> + <string name="Moustache">Moustache</string> + <string name="Soulpatch">Soulpatch</string> + <string name="Chin Curtains">Chin Curtains</string> <string name="Outer Eye Corner">Outer Eye Corner</string> <string name="Outer Shadow">Outer Shadow</string> - <string name="Out Shdw Opacity">Out Shdw Opacity</string> - <string name="Out Shdw Color">Out Shdw Color</string> + <string name="Out Shdw Opacity">Outer Shadow Opacity</string> + <string name="Out Shdw Color">Outer Shadow Color</string> <string name="Package">Package</string> <string name="Pants Crotch">Pants Crotch</string> <string name="Pants Fit">Pants Fit</string> @@ -2399,10 +2434,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Slanted Forehead">Slanted Forehead</string> <string name="Sleeve Length">Sleeve Length</string> <string name="Sleeve Looseness">Sleeve Looseness</string> - <string name="Slit Back">Slit Back</string> - <string name="Slit Front">Slit Front</string> - <string name="Slit Left">Slit Left</string> - <string name="Slit Right">Slit Right</string> + <string name="Slit Back">Slit: Back</string> + <string name="Slit Front">Slit: Front</string> + <string name="Slit Left">Slit: Left</string> + <string name="Slit Right">Slit: Right</string> <string name="Socks Length">Socks Length</string> <string name="Spiked Hair">Spiked Hair</string> <string name="Squash/Stretch Head">Squash/Stretch Head</string> @@ -2424,12 +2459,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="White Hair">White Hair</string> <string name="big belly skirt">big belly skirt</string> <string name="bigbutt skirt">bigbutt skirt</string> - <string name="bustle skirt">bustle skirt</string> + <string name="bustle skirt">Bustle Skirt</string> <string name="legs skirt">legs skirt</string> <string name="loose skirt">loose skirt</string> <string name="poofy skirt">poofy skirt</string> <string name="tight skirt">tight skirt</string> - <string name="wrinkles">wrinkles</string> + <string name="wrinkles">Wrinkles</string> <!-- Favorites Bar --> <string name="location_ctrl_add_landmark">Add to My Landmarks</string> 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/es/floater_god_tools.xml b/indra/newview/skins/default/xui/es/floater_god_tools.xml index 1ba0b685c6..ea2571ecb8 100644 --- a/indra/newview/skins/default/xui/es/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_god_tools.xml @@ -54,7 +54,7 @@ Factor cobrable: </text> <text name="land cost text"> - L$ por m2: + L$ por m²: </text> <button label="Actualizar" label_selected="Actualizar" name="Refresh" tool_tip="Haga clic aquí para actualizar la información arriba." /> @@ -114,17 +114,17 @@ Destino: </text> <combo_box name="destination"> - <combo_box.item name="Selection" label="Selección" /> - <combo_box.item name="AgentRegion" label="Agente de región" /> + <combo_box.item name="item1" label="Selección" /> + <combo_box.item name="item2" label="Agente de región" /> </combo_box> <text name="Request:"> Exigencia: </text> <combo_box name="request"> - <combo_box.item name="colliders<steps>" label="colisionadores <pasos>" /> - <combo_box.item name="scripts<count>,<optionalpattern>" label="scripts <contar>,<patrón opcional>" /> - <combo_box.item name="objects<pattern>" label="objetos <patrón>" /> - <combo_box.item name="rez<asset_id>" label="rez <asset_id>" /> + <combo_box.item name="item1" label="colisionadores <pasos>" /> + <combo_box.item name="item2" label="scripts <contar>,<patrón opcional>" /> + <combo_box.item name="item3" label="objetos <patrón>" /> + <combo_box.item name="item4" label="rez <asset_id>" /> </combo_box> <text name="Parameter:"> Parámetro: diff --git a/indra/newview/skins/default/xui/es/floater_postcard.xml b/indra/newview/skins/default/xui/es/floater_postcard.xml index 0ebf459cef..6a9811c058 100644 --- a/indra/newview/skins/default/xui/es/floater_postcard.xml +++ b/indra/newview/skins/default/xui/es/floater_postcard.xml @@ -36,6 +36,6 @@ usted conseguirá un bono de referido. ¡Mira esto! </string> <string name="upload_message"> - "Enviando..." + Enviando... </string> </floater> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 0a722ccfd2..e418de3929 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -574,7 +574,7 @@ misma región. <notification name="PromptGoToCurrencyPage"> [EXTRA] -¿Ir a [URL] para informarse sobre la compra de moneda? +¿Ir a [_URL] para informarse sobre la compra de L$? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -808,7 +808,6 @@ no ha seleccionado un grupo. <notification name="CannotDeedLandNoRegion"> No se ha podido transferir el terreno: Ha sido imposible encontrar en qué región está. -Por favor, para informar de esto use Herramientas -> Informar de un fallo. </notification> <notification name="CannotDeedLandMultipleSelected"> No se ha podido transferir el terreno: @@ -854,8 +853,6 @@ Las parcelas de su propiedad se muestran en verde. <notification name="CannotReleaseLandRegionNotFound"> No se ha podido abandonar el terreno: Ha sido imposible encontrar en qué región está. - -Por favor, para informar de esto use Herramientas > Informar de un fallo. </notification> <notification name="CannotReleaseLandNoTransfer"> No se ha podido abandonar el terreno: @@ -894,14 +891,10 @@ Inténtelo seleccionando una parte. <notification name="CannotDivideLandNoRegion"> No se ha podido dividir el terreno: Ha sido imposible encontrar en qué región está. - -Por favor, para informar de esto use Herramientas -> Informar de un fallo. </notification> <notification name="CannotJoinLandNoRegion"> No se ha podido unir el terreno: Ha sido imposible encontrar en qué región está. - -Por favor, para informar de esto use Herramientas -> Informar de un fallo. </notification> <notification name="CannotJoinLandNothingSelected"> No se ha podido unir el terreno: @@ -960,8 +953,6 @@ Gris = Público <notification name="CannotSaveToAssetStore"> No se ha podido guardar [NAME] en la base central de almacenamiento. Esto es, generalmente, un fallo temporal. Por favor, reinténtelo en unos pocos minutos. - -Si persiste el problema, por favor, pulse en en el menú 'Herramientas > Informar de un fallo' y aporte detalles sobre la configuración de su conexión. </notification> <notification name="YouHaveBeenLoggedOut"> Se ha cerrado su sesión en [SECOND_LIFE]: @@ -1311,10 +1302,6 @@ Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar ¿Ir a www.secondlife.com para administrar su cuenta? <usetemplate ignoretext="Cuando se abra el navegador para administrar su cuenta" name="okcancelignore" notext="Cancelar" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Visite el wiki de [SECOND_LIFE] y aprenda cómo informar correctamente de fallos. - <usetemplate ignoretext="Cuando se abra el navegador para ver el wiki de Informes de fallos - instrucciones" name="okcancelignore" notext="Cancelar" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Visite el wiki de [SECOND_LIFE] para más detalles sobre cómo informar de una cuestión de seguridad. <usetemplate ignoretext="Cuando se abra el navegador para ver el wiki de cuestiones de seguridad" name="okcancelignore" notext="Cancelar" yestext="OK"/> @@ -2046,26 +2033,10 @@ El propietario de la región resolverá las denuncias basándose en las reglas l La resolución de esta denuncia se aplica exclusivamente a esta región; el acceso de los residentes a otras áreas de [SECOND_LIFE] no se verá afectado por el resultado de esta denuncia. Únicamente Linden Lab puede impedir el acceso a la totalidad de [SECOND_LIFE]. </notification> - <notification name="HelpReportBug"> - Use esta herramienta *sólo* para informar de cuestiones técnicas que no se comportan como se describe o era esperable. Por favor, aporte todos los detalles que pueda. -Deberá responder al correo electrónico de auto respuesta para añadir más detalles a su informe. - -Todos los informes de fallos serán investigados y evaluados. No se contestará por correo electrónico. - -Si tiene algún problema técnico, por favor, contacte con Soporte en: - -http://secondlife.com/community/support.php - -Nota: no se investigarán los informes incompletos. - </notification> <notification name="HelpReportAbuseSelectCategory"> Por favor, elija una categoría para esta denuncia de infracción. Seleccionar una categoría nos ayuda a clasificar y procesar las denuncias de infracciones. </notification> - <notification name="HelpReportBugSelectCategory"> - Por favor, elija una categoría para este fallo. -Seleccionar una categoría nos ayuda a clasificar y procesar los informes de fallos. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Por favor, escriba el nombre del infractor. Aportar el dato preciso nos ayuda a clasificar y procesar las denuncias de infracciones. @@ -2078,20 +2049,11 @@ Aportar el dato preciso nos ayuda a clasificar y procesar las denuncias de infra Por favor, escriba un resumen de la infracción que ha habido. Aportar un resumen preciso nos ayuda a clasificar y procesar las denuncias de infracciones. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Por favor, escriba un resumen del fallo. -Aportar un resumen preciso nos ayuda a clasificar y procesar los informes de fallos. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Por favor, escriba una descripción minuciosa de la infracción que ha habido. Sea tan específico como pueda, incluyendo los nombres y los detalles implicados en el incidente que denuncia. Aportar una descripción precisa nos ayuda a clasificar y procesar las denuncias de infracciones. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Por favor, escriba una descripción minuciosa del fallo. -Sea tan específico como pueda, incluyendo -si es posible- los pasos que permitan reproducir el fallo. -Aportar una descripción precisa nos ayuda a clasificar y procesar los informes de fallos. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Estimado Residente: diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 6b7019ba95..0735bb0082 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -527,4 +527,110 @@ Si sigue recibiendo este mensaje, contacte con el [SUPPORT_SITE]. <string name="GraphicsQualityHigh"> Alto </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Localización Linden</string> + <string name="Adult">'Adult'</string> + <string name="Arts&Culture">Arte y Cultura</string> + <string name="Business">Negocios</string> + <string name="Educational">Educativo</string> + <string name="Gaming">Juegos de azar</string> + <string name="Hangout">Entretenimiento</string> + <string name="Newcomer Friendly">Para recién llegados</string> + <string name="Parks&Nature">Parques y Naturaleza</string> + <string name="Residential">Residencial</string> + <string name="Shopping">Compras</string> + <string name="Other">Otra</string> + + <string name="ringing"> + Conectando al chat de voz... + </string> + <string name="connected"> + Conectado + </string> + <string name="unavailable"> + La voz no está disponible en su localización actual + </string> + <string name="hang_up"> + Desconectado del chat de voz + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', un objeto propiedad de '[OWNERNAME]', localizado en [REGIONNAME] con la posición [REGIONPOS], ha recibido permiso para: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + A '[OBJECTNAME]', un objeto propiedad de '[OWNERNAME]', localizado en [REGIONNAME] con la posición [REGIONPOS], se le ha denegado el permiso para: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Cogerle a usted dólares Linden (L$) + </string> + <string name="ActOnControlInputs"> + Actuar en sus controles de entrada + </string> + <string name="RemapControlInputs"> + Reconfigurar sus controles de entrada + </string> + <string name="AnimateYourAvatar"> + Ejecutar animaciones en su avatar + </string> + <string name="AttachToYourAvatar"> + Anexarse a su avatar + </string> + <string name="ReleaseOwnership"> + Anular la propiedad y que pase a ser público + </string> + <string name="LinkAndDelink"> + Enlazar y desenlazar de otros objetos + </string> + <string name="AddAndRemoveJoints"> + Añadir y quitar uniones con otros objetos + </string> + <string name="ChangePermissions"> + Cambiar sus permisos + </string> + <string name="TrackYourCamera"> + Seguir su cámara + </string> + <string name="ControlYourCamera"> + Controlar su cámara + </string> + + <string name="only_user_message"> + Usted es el único usuario en esta sesión. + </string> + <string name="offline_message"> + [FIRST] [LAST] no está conectado. + </string> + <string name="invite_message"> + Pulse el botón [BUTTON NAME] para aceptar/conectar este chat de voz. + </string> + <string name="generic_request_error"> + Error al hacer lo solicitado; por favor, inténtelo más tarde. + </string> + <string name="insufficient_perms_error"> + Usted no tiene permisos suficientes. + </string> + <string name="session_does_not_exist_error"> + La sesión ya acabó + </string> + <string name="no_ability_error"> + Usted no tiene esa capacidad. + </string> + <string name="not_a_mod_error"> + Usted no es un moderador de la sesión. + </string> + <string name="muted_error"> + Un moderador del grupo le ha desactivado el chat de texto. + </string> + <string name="add_session_event"> + No se ha podido añadir usuarios a la sesión de chat con [RECIPIENT]. + </string> + <string name="message_session_event"> + No se ha podido enviar su mensaje a la sesión de chat con [RECIPIENT]. + </string> + <string name="removed_from_group"> + Ha sido eliminado del grupo. + </string> + <string name="close_on_no_ability"> + Usted ya no tendrá más la capacidad de estar en la sesión de chat. + </string> </strings> diff --git a/indra/newview/skins/default/xui/fr/floater_god_tools.xml b/indra/newview/skins/default/xui/fr/floater_god_tools.xml index 4f43be47ea..461956ff34 100644 --- a/indra/newview/skins/default/xui/fr/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_god_tools.xml @@ -78,17 +78,17 @@ Destination : </text> <combo_box name="destination"> - <combo_box.item name="Selection" label="Sélection" /> - <combo_box.item name="AgentRegion" label="Région de l'avatar" /> + <combo_box.item name="item1" label="Sélection" /> + <combo_box.item name="item2" label="Région de l'avatar" /> </combo_box> <text name="Request:"> Requête : </text> <combo_box name="request"> - <combo_box.item name="colliders<steps>" label="Objets responsables de collisions : étapes" /> - <combo_box.item name="scripts<count>,<optionalpattern>" label="Nombre de scripts et schéma optionnel" /> - <combo_box.item name="objects<pattern>" label="Schéma des objets" /> - <combo_box.item name="rez<asset_id>" label="rezzer <asset_id>" /> + <combo_box.item name="item1" label="Objets responsables de collisions : étapes" /> + <combo_box.item name="item2" label="Nombre de scripts et schéma optionnel" /> + <combo_box.item name="item3" label="Schéma des objets" /> + <combo_box.item name="item4" label="rezzer <asset_id>" /> </combo_box> <text name="Parameter:"> Paramètre : diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 951c199b1c..3255cdb728 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -560,7 +560,7 @@ Veuillez mettre tous les objets que vous souhaitez acquérir dans la même régi <notification name="PromptGoToCurrencyPage"> [EXTRA] -Aller sur [URL] pour obtenir des informations sur l'achat de devises ? +Aller sur [_URL] pour obtenir des informations sur l'achat de L$ ? <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -788,7 +788,6 @@ aucun groupe sélectionné. <notification name="CannotDeedLandNoRegion"> Cession du terrain impossible : la région dans laquelle il est situé est introuvable. -Veuillez utiliser Aide > Signaler des bugs pour signaler le problème. </notification> <notification name="CannotDeedLandMultipleSelected"> Cession du terrain impossible : @@ -834,8 +833,6 @@ Les parcelles qui vous appartiennent sont en vert. <notification name="CannotReleaseLandRegionNotFound"> Impossible d'abandonner le terrain : la région dans laquelle il est situé est introuvable. - -Veuillez utiliser Aide > Signaler un bug pour signaler le problème. </notification> <notification name="CannotReleaseLandNoTransfer"> Impossible d'abandonner le terrain : @@ -874,14 +871,10 @@ Diviser le terrain ? <notification name="CannotDivideLandNoRegion"> Division du terrain impossible : la région dans laquelle il est situé est introuvable. - -Veuillez utiliser Aide > Signaler un bug pour signaler le problème. </notification> <notification name="CannotJoinLandNoRegion"> Impossible de fusionner le terrain : la région dans laquelle il est situé est introuvable. - -Veuillez utiliser Aide > Signaler un bug pour signaler le problème. </notification> <notification name="CannotJoinLandNothingSelected"> Impossible de fusionner le terrain : @@ -940,8 +933,6 @@ Gris = public <notification name="CannotSaveToAssetStore"> Impossible de sauvegarder le fichier [NAME] dans la base de données centrale. Cette erreur est généralement temporaire. Veuillez éditer et sauvegarder l'élément endossable à nouveau d'ici quelques minutes. - -Si le problème persiste, veuillez cliquer sur Aide | Signaler un bug dans le menu déroulant en indiquant les détails de votre connexion. </notification> <notification name="YouHaveBeenLoggedOut"> Vous avez été déconnecté(e) de [SECOND_LIFE] : @@ -1274,10 +1265,6 @@ Télécharger vers le dossier Applications ? Aller sur www.secondlife.com pour gérer votre compte ? <usetemplate ignoretext="Lors de l'ouverture du navigateur web pour gérer votre compte" name="okcancelignore" notext="Annuler" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Pour apprendre à signaler correctement des bugs, consultez le Wiki de [SECOND_LIFE]. - <usetemplate ignoretext="Lors de l'ouverture du navigateur web pour consulter le Wiki et apprendre à signaler des bugs" name="okcancelignore" notext="Annuler" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Pour apprendre à signaler un problème de sécurité, consultez le Wiki de [SECOND_LIFE]. <usetemplate ignoretext="Lors de l'ouverture du navigateur web pour consulter la page Wiki sur les problèmes de sécurité." name="okcancelignore" notext="Annuler" yestext="OK"/> @@ -1966,26 +1953,10 @@ Le propriétaire de la région traitera les rapports en fonction des règles de La résolution de ce rapport ne s'applique qu'à cette région ; L'accès aux autres endroits de [SECOND_LIFE] ne sera pas affecté par les résultats de cette enquête. Seul Linden Lab peut interdire l'accès à l'ensemble de [SECOND_LIFE]. </notification> - <notification name="HelpReportBug"> - N'utilisez cet outil que pour signaler des problèmes techniques et soyez aussi précis que possible. -Vous pouvez répondre à l'e-mail automatique pour ajouter des détails à votre rapport. - -Tous les bugs signalés sont reproduits et évalués. Aucune réponse ne sera envoyée par e-mail. - -Si vous avez un problème technique, veuillez contacter le service clientèle à : - -http://secondlife.com/community/support.php - -Remarque : les rapports incomplets ne feront pas l'objet d'une enquête. - </notification> <notification name="HelpReportAbuseSelectCategory"> Veuillez choisir une catégorie pour ce rapport d'infraction. Le choix d'une catégorie nous permet de traiter les rapports d'infraction plus rapidement. </notification> - <notification name="HelpReportBugSelectCategory"> - Veuillez choisir une catégorie pour ce bug. -Le choix d'une catégorie nous permet de traiter les bugs plus rapidement. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Veuillez saisir le nom du contrevenant. Lorsque nous avons le nom du contrevenant, nous sommes en mesure de traiter les rapports plus rapidement. @@ -1998,20 +1969,11 @@ Les informations précises et exactes nous permettent de traiter les rapports pl Veuillez saisir un récapitulatif de l'infraction. Les récapitulatifs précis nous permettent de traiter les rapports plus rapidement. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Veuillez saisir un récapitulatif du bug. -Les récapitulatifs précis nous permettent de résoudre les bugs plus rapidement. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Veuillez saisir une description détaillée de l'infraction. Soyez aussi précis que possible et essayez de fournir des noms ainsi que des détails sur l'incident que vous signalez. Les descriptions précises nous permettent de traiter les rapports plus rapidement. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Veuillez saisir une description détaillée du bug. -Soyez aussi spécifique que possible et essayez d'indiquer les étapes à suivre pour reproduire le bug. -Les descriptions précises nous permettent de résoudre les bugs plus rapidement. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Cher résident, diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 80248a95f8..6bdee836d9 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -517,4 +517,109 @@ <string name="GraphicsQualityHigh"> Élevé </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Appartenant aux Lindens</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Art et Culture</string> + <string name="Business">Affaires</string> + <string name="Educational">Éducation</string> + <string name="Gaming">Jeux</string> + <string name="Hangout">Favoris</string> + <string name="Newcomer Friendly">Accueil pour les nouveaux</string> + <string name="Parks&Nature">Parcs et Nature</string> + <string name="Residential">Résidentiel</string> + <string name="Shopping">Shopping</string> + <string name="Other">Autre</string> + + <string name="ringing"> + Connexion au chat vocal du Monde en cours… + </string> + <string name="connected"> + Connecté(e) + </string> + <string name="unavailable"> + Voix non disponible à l'endroit où vous êtes + </string> + <string name="hang_up"> + Déconnecté du chat vocal + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', un objet appartenant à [OWNERNAME], situé dans [REGIONNAME] à [REGIONPOS], a reçu le droit de : [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + '[OBJECTNAME]', un objet appartenant à [OWNERNAME], situé dans [REGIONNAME] à [REGIONPOS], n'a pas reçu le droit de : [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Débiter vos Linden dollars (L$) + </string> + <string name="ActOnControlInputs"> + Utiliser vos touches de commandes + </string> + <string name="RemapControlInputs"> + Reconfigurer vos touches de commandes + </string> + <string name="AnimateYourAvatar"> + Animer votre avatar + </string> + <string name="AttachToYourAvatar"> + Attacher à votre avatar + </string> + <string name="ReleaseOwnership"> + Passer l'objet dans le domaine public (sans propriétaire) + </string> + <string name="LinkAndDelink"> + Lier et délier d'autres objets + </string> + <string name="AddAndRemoveJoints"> + Créer et supprimer des liens avec d'autres objets + </string> + <string name="ChangePermissions"> + Modifier ses droits + </string> + <string name="TrackYourCamera"> + Suivre votre caméra + </string> + <string name="ControlYourCamera"> + Contrôler votre caméra + </string> + <text name="only_user_message"> + Vous êtes le seul participant à cette session. + </text> + <text name="offline_message"> + [FIRST] [LAST] est déconnecté(e). + </text> + <string name="invite_message"> + Pour accepter ce chat vocal/vous connecter, cliquez sur le bouton [BUTTON NAME]. + </string> + <string name="generic_request_error"> + Erreur lors de la requête, veuillez réessayer ultérieurement. + </string> + <string name="insufficient_perms_error"> + Vous n'avez pas les droits requis. + </string> + <string name="session_does_not_exist_error"> + La session a expiré + </string> + <string name="no_ability_error"> + Vous n'avez pas ce pouvoir. + </string> + <string name="not_a_mod_error"> + Vous n'êtes pas modérateur de session. + </string> + <string name="muted_error"> + Un modérateur de groupe a désactivé votre chat écrit. + </string> + <string name="add_session_event"> + Impossible d'ajouter des participants à la session de chat avec [RECIPIENT]. + </string> + <string name="message_session_event"> + Impossible d'envoyer votre message à la session de chat avec [RECIPIENT]. + </string> + <string name="removed_from_group"> + Vous avez été supprimé du groupe. + </string> + <string name="close_on_no_ability"> + Vous ne pouvez plus participer à la session de chat. + </string> </strings> diff --git a/indra/newview/skins/default/xui/it/floater_postcard.xml b/indra/newview/skins/default/xui/it/floater_postcard.xml index a2522baaf4..5132771acc 100644 --- a/indra/newview/skins/default/xui/it/floater_postcard.xml +++ b/indra/newview/skins/default/xui/it/floater_postcard.xml @@ -35,6 +35,6 @@ Vieni a vedere! </string> <string name="upload_message"> - "In spedizione..." + In spedizione... </string> </floater> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 427247634b..d85dd7732a 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -574,7 +574,7 @@ Sposta tutti gli oggetti che vuoi acquisire su una sola regione. <notification name="PromptGoToCurrencyPage"> [EXTRA] -Vuoi andare su [URL] per maggiori informazioni su come acquistare denaro? +Vuoi andare su [_URL] per maggiori informazioni su come acquistare L$? <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -804,7 +804,6 @@ Nessun gruppo selezionato. <notification name="CannotDeedLandNoRegion"> Impossibile cedere il terreno: Non riesco a trovare la regione dove è situato il terreno. -Usa Strumenti -> Segnala Bug per segnalare il problema. </notification> <notification name="CannotDeedLandMultipleSelected"> Impossibile cedere il terreno: @@ -850,8 +849,6 @@ I terreni di tua proprietà vengono visualizzati in verde. <notification name="CannotReleaseLandRegionNotFound"> Impossibile abbandonare il terreno: Non riesco a trovare la regione dove è situato il terreno. - -Usa Strumenti > Segnala Bug segnalare questo problema. </notification> <notification name="CannotReleaseLandNoTransfer"> Impossibile abbandonare il terreno: @@ -890,14 +887,10 @@ Dividi il terreno? <notification name="CannotDivideLandNoRegion"> Impossibile dividere il terreno: Non riesco a trovare la regione dove è situato. - -Usa Strumenti -> Segnala Bug per segnalare il problema. </notification> <notification name="CannotJoinLandNoRegion"> Impossibile unire il terreno: Non riesco a trovare la regione dove è situato. - -Usa Strumenti -> Segnala Bug per segnalare il problema. </notification> <notification name="CannotJoinLandNothingSelected"> Impossibile unire il terreno: @@ -956,8 +949,6 @@ Grigia = pubblica <notification name="CannotSaveToAssetStore"> Impossibile salvare [NAME] nel database centrale. Normalmente questo problema è temporaneo. Riprova a generare la parte indossabile e a salvarla fra qualche minuto. - -Se questo problema persiste, clicca sul menu a tendina 'Strumenti > Segnala Bug' e fornisci i dettagli sulla tua configurazione di rete. </notification> <notification name="YouHaveBeenLoggedOut"> Sei stato sconnesso da [SECOND_LIFE]: @@ -1298,10 +1289,6 @@ Vuoi avviarne lo scaricamento nella tua cartella applicazioni? Vuoi andare su www.secondlife.com per gestire il tuo account? <usetemplate ignoretext="Quando lanci il browser web per gestire il tuo account." name="okcancelignore" notext="Annulla" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Visita la Wiki di [SECOND_LIFE] per imparare a segnalare un bug correttamente. - <usetemplate ignoretext="Quando lanci il browser web per vedere come segnalare bug nella wiki." name="okcancelignore" notext="Annulla" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Visita la Wiki di [SECOND_LIFE] per i dettagli su come segnalare un problema di sicurezza. <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki sui problemi di sicurezza." name="okcancelignore" notext="Annulla" yestext="OK"/> @@ -2040,25 +2027,10 @@ Il proprietario della regione risolverà le segnalazione basandosi sulle regole La risoluzione di questa segnalazione verrà applicata solo in questa regione; L'accesso dei residenti ad altre aree di [SECOND_LIFE] non verrà influenzato dal risultato di questa segnalazione. Soltanto i Linden Lab possono restringere l'accesso alla totalità di [SECOND_LIFE]. </notification> - <notification name="HelpReportBug"> - Usa questo strumento per segnalare *soltanto* caratteristiche tecniche che non funzionano come descitto o atteso, fornisci quanti più dettagli è possibile, Puoi rispondere all'email automatica aggiungendo ulteriori dettagli sulla tua segnalazione. - -Tutte le segnalazioni di bug sono investigate e valutate. Non vengono inviate risposte via email. - -Se hai difficoltà tecniche contatta il supporto: - -http://secondlife.com/community/support.php - -Nota: segnalazioni incomplete non verranno prese in considerazione - </notification> <notification name="HelpReportAbuseSelectCategory"> Scegli una categoria per questa segnalazione di abuso. Scegliere una categoria, ci aiuta a gestire ed elaborare le segnalazioni di abuso. </notification> - <notification name="HelpReportBugSelectCategory"> - Scegli una categoria per questo bug. -Scegliere una categoria, ci aiuta a gestire ed elaborare le segnalazioni di bug. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Introduci il nome di chi abusa. Introducendo un valore accurato, ci aiuti a gestire ed elaborare le segnalazioni di abuso. @@ -2071,20 +2043,11 @@ Introducendo un valore accurato, ci aiuti a gestire ed elaborare le segnalazioni Inserisci un yiyolo descrittivo dell'abuso che è avvenuto. Introducendo un titolo descrittivo accurato, ci aiuti a gestire ed elaborare le segnalazioni di abuso. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Introduci una descrizione del bug. -Introducendo una descrizione accurata ci aiuti a gestire ed elaborare le segnalazioni di bug. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Inserisci una descrizione dettagliata dell'abuso che è avvenuto. Devi essere il più specifico possibile, includendo i nomi e i dettagli dell'incidente che stai segnalando. Inserendo una descrizione accurata ci aiuti a gestire ed elaborare le segnalazioni di abuso. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Inserisci una descrizione dettagliata del bug. -Devi essere il pià specifico possibile, includendo se possibil i passi per riprodurre il problema. -Inserendo una descrizione accurata, ci aiuti a gestire ed elaborare le segnalazioni di bug. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Caro residente, diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 38283df469..67b946e1de 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -513,4 +513,109 @@ <string name="GraphicsQualityHigh"> Alto </string> + + <!-- PARCEL_CATEGORY_UI_STRING - TAKE FROM floater_about_land."land category with adult".item1-item12 --> + <string name="Linden Location">Luogo dei Linden</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Arte & Cultura</string> + <string name="Business">Affari</string> + <string name="Educational">Educazione</string> + <string name="Gaming">Gioco</string> + <string name="Hangout">Divertimento</string> + <string name="Newcomer Friendly">Accoglienza nuovi residenti</string> + <string name="Parks&Nature">Parchi & Natura</string> + <string name="Residential">Residenziale</string> + <string name="Shopping">Shopping</string> + <string name="Other">Altro</string> + + <string name="ringing"> + In connessione alla Voice Chat in-world... + </string> + <string name="connected"> + Connesso + </string> + <string name="unavailable"> + Il voice non è disponibile nel posto dove ti trovi ora + </string> + <string name="hang_up"> + Disconnesso dalla Voice Chat in-world + </string> + <string name="ScriptQuestionCautionChatGranted"> + A '[OBJECTNAME]', un oggetto di proprietà di '[OWNERNAME]', situato in [REGIONNAME] [REGIONPOS], è stato concesso il permesso di: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + A '[OBJECTNAME]', un oggetto di proprietà di '[OWNERNAME]', situato in [REGIONNAME] [REGIONPOS], è stato negato il permesso di: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Prendere dollari Linden (L$) da te + </string> + <string name="ActOnControlInputs"> + Agire sul tuo controllo degli input + </string> + <string name="RemapControlInputs"> + Rimappare il tuo controllo degli input + </string> + <string name="AnimateYourAvatar"> + Animare il tuo avatar + </string> + <string name="AttachToYourAvatar"> + Far indossare al tuo avatar + </string> + <string name="ReleaseOwnership"> + Rilasciare la propietà è far diventare pubblico. + </string> + <string name="LinkAndDelink"> + Collegare e scollegare dagli altri oggetti + </string> + <string name="AddAndRemoveJoints"> + Aggiungere e rimuovere le giunzioni insieme con gli altri oggetti + </string> + <string name="ChangePermissions"> + Cambiare i permessi + </string> + <string name="TrackYourCamera"> + Tracciare la fotocamera + </string> + <string name="ControlYourCamera"> + Controllare la tua fotocamera + </string> + <string name="only_user_message"> + Sei l'unico utente di questa sessione. + </string> + <string name="offline_message"> + [FIRST] [LAST] è offline. + </string> + <string name="invite_message"> + Clicca il tasto [BUTTON NAME] per accettare/connetterti a questa voice chat. + </string> + <string name="generic_request_error"> + Errore durante la richiesta, riprova più tardi. + </string> + <string name="insufficient_perms_error"> + Non hai sufficienti permessi. + </string> + <string name="session_does_not_exist_error"> + Questa sessione non esiste più + </string> + <string name="no_ability_error"> + Non hai questa abilitazione. + </string> + <string name="not_a_mod_error"> + Non sei un moderatore. + </string> + <string name="muted_error"> + Un moderatore di gruppo ti ha disabilitato dalla chat di testo. + </string> + <string name="add_session_event"> + Impossibile aggiungere utenti alla chat con [RECIPIENT]. + </string> + <string name="message_session_event"> + Impossibile inviare il messaggio nella chat con [RECIPIENT]. + </string> + <string name="removed_from_group"> + Sei stato espulso dal gruppo. + </string> + <string name="close_on_no_ability"> + Non hai più le abilitazioni per rimanere nella sessione chat. + </string> </strings> diff --git a/indra/newview/skins/default/xui/ja/floater_god_tools.xml b/indra/newview/skins/default/xui/ja/floater_god_tools.xml index d91744c391..8fe41a823a 100644 --- a/indra/newview/skins/default/xui/ja/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/ja/floater_god_tools.xml @@ -122,29 +122,17 @@ 目的地: </text> <combo_box name="destination"> - <combo_item name="Selection"> - 選択 - </combo_item> - <combo_item name="AgentRegion"> - エージェント地域 - </combo_item> + <combo_box.item name="item1" label="選択"/> + <combo_box.item name="item2" label="エージェント地域"/> </combo_box> <text name="Request:"> 要求: </text> <combo_box name="request"> - <combo_item name="colliders<steps>"> - コライダー<ステップ> - </combo_item> - <combo_item name="scripts<count>,<optionalpattern>"> - スクリプト<回数>、<オプション・パターン> - </combo_item> - <combo_item name="objects<pattern>"> - オブジェクト<パターン> - </combo_item> - <combo_item name="rez<asset_id>"> - rez <asset_id> - </combo_item> + <combo_box.item name="item1" label="コライダー<ステップ>"/> + <combo_box.item name="item2" label="スクリプト<回数>、<オプション・パターン>"/> + <combo_box.item name="item3" label="オブジェクト<パターン>"/> + <combo_box.item name="item4" label="rez <asset_id>"/> </combo_box> <text name="Parameter:"> パラメーター: diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index f9d91c31fa..5c22fbf474 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -603,7 +603,7 @@ L$が不足しているのでこのグループに参加することができま <notification name="PromptGoToCurrencyPage"> [EXTRA] -[URL]に移動して貨幣購入に関する情報を確認しますか? +[_URL]に移動して貨幣購入に関する情報を確認しますか? <usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -845,7 +845,6 @@ L$が不足しているのでこのグループに参加することができま <notification name="CannotDeedLandNoRegion"> 土地を譲渡できません: この土地がある地域が見つかりません。 -「ツール」>「バグを報告する」を使って報告してください。 </notification> <notification name="CannotDeedLandMultipleSelected"> 土地を譲渡できません: @@ -891,8 +890,6 @@ L$が不足しているのでこのグループに参加することができま <notification name="CannotReleaseLandRegionNotFound"> 土地を破棄できません: この土地がある地域が見つかりません。 - -「ツール」>「バグを報告する」を使って報告してください。 </notification> <notification name="CannotReleaseLandNoTransfer"> 土地を破棄できません: @@ -933,14 +930,10 @@ L$は返金されません。 <notification name="CannotDivideLandNoRegion"> 土地を分割できません: この土地がある地域が見つかりません。 - -「ツール」>「バグを報告する」を使って報告してください。 </notification> <notification name="CannotJoinLandNoRegion"> 土地を統合できません: この土地がある地域が見つかりません。 - -「ツール」>「バグを報告する」を使って報告してください。 </notification> <notification name="CannotJoinLandNothingSelected"> 土地を統合できませんでした: @@ -1003,8 +996,6 @@ L$は返金されません。 [NAME]を中央資産格納庫に保存できません。 これは一時的な不具合です。 服飾品などをカスタマイズし、数分後にもう一度保存してください。 - -この問題が続くようなら、「ツール」>「バグを報告する」をクリックし、お使いのネットワーク設定の詳細を報告してください。 </notification> <notification name="YouHaveBeenLoggedOut"> あなたは[SECOND_LIFE]からログアウトされました。 @@ -1365,10 +1356,6 @@ F1キーを押してください。 www.secondlife.comに移動してアカウントを管理しますか? <usetemplate ignoretext="アカウントを管理するため、ウェブ・ブラウザを起動するとき" name="okcancelignore" notext="取り消し" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - [SECOND_LIFE]Wikiで、バグを報告する正しい方法をご覧ください。 - <usetemplate ignoretext="バグレポート101 Wikiを閲覧するためのブラウザを開くにあたって" name="okcancelignore" notext="キャンセル" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> [SECOND_LIFE] Wikiで、 セキュリティ問題を報告する方法をご覧ください。 @@ -2180,26 +2167,10 @@ http://secondlife.com/support/incidentreport.php Linden Lab 社だけが[SECOND_LIFE] 全域における アクセス制限権を持っています。 </notification> - <notification name="HelpReportBug"> - このツールは、説明どおりに動作しないなどのテクニカルなフィーチャーのレポートのみに使用してください。 -できるだけ詳しい情報を提供してください。 -自動返答メールに、より詳しい情報を付け加えて返信することもできます。 -バグレポートは全て調査され解決されます。これによってEメールで返答が送られてくることはありません。 -- -テクニカルな問題が生じた場合は、 -次のサポートに連絡してください: -http://secondlife.com/community/support.php -- -注意:未完成の報告は調査されません。 - </notification> <notification name="HelpReportAbuseSelectCategory"> 嫌がらせ報告のカテゴリを選択してください。 カテゴリを選択することにより、嫌がらせ報告の処理や保管に大変役立ちます。 </notification> - <notification name="HelpReportBugSelectCategory"> - バグのカテゴリを選択してください。 -カテゴリを選択することにより、バグ報告の処理や保管に大変役立ちます。 - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> 嫌がらせ行為をした人の名前を入力してください。 正確な情報の入力により、嫌がらせ報告の処理や保管に大変役立ちます。 @@ -2213,10 +2184,6 @@ http://secondlife.com/community/support.php 正確な概要の入力により、 嫌がらせ報告の処理や保管に大変役立ちます。 </notification> - <notification name="HelpReportBugSummaryEmpty"> - バグの概要を入力してください。 -正確な概要の入力により、バグ報告の処理や保管に大変役立ちます。 - </notification> <notification name="HelpReportAbuseDetailsEmpty"> 嫌がらせの詳細な説明を入力してください。 名前や嫌がらせの詳細を、できるだけ具体的に入力してください。 @@ -2224,12 +2191,6 @@ http://secondlife.com/community/support.php 正確な説明の入力により、 嫌がらせ報告の処理や保管に大変役立ちます。 </notification> - <notification name="HelpReportBugDetailsEmpty"> - バグの詳細な説明を入力してください。 -バグがどのような条件で再現するかなどを、できるだけ具体的に入力してください。 - -正確な説明の入力により、バグ報告の処理や保管に大変役立ちます。 - </notification> <notification name="HelpReportAbuseContainsCopyright"> 住人の皆様へ、 diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 5d308f78d1..7b21146651 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -517,4 +517,108 @@ <string name="GraphicsQualityHigh"> 高 </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Linden所在地</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">アートとカルチャー</string> + <string name="Business">ビジネス</string> + <string name="Educational">教育的</string> + <string name="Gaming">ゲーム</string> + <string name="Hangout">たまり場</string> + <string name="Newcomer Friendly">新住人に好意的</string> + <string name="Parks&Nature">公園と自然</string> + <string name="Residential">住宅用</string> + <string name="Shopping">ショッピング</string> + <string name="Other">その他</string> + <string name="ringing"> + インワールドボイスチャットに接続中... + </string> + <string name="connected"> + 接続しました + </string> + <string name="unavailable"> + あなたの現在のロケーションでは、ボイスを利用できません。 + </string> + <string name="hang_up"> + インワールドボイスチャットの通話が切断されました + </string> + <string name="ScriptQuestionCautionChatGranted"> + [REGIONNAME]の[REGIONPOS]という場所にある「[OWNERNAME]」所有の「[OBJECTNAME]」というオブジェクトは、次の権限を許可しました: [PERMISSIONS] + </string> + <string name="ScriptQuestionCautionChatDenied"> + [REGIONNAME]の[REGIONPOS]という場所にある「[OWNERNAME]」所有の「[OBJECTNAME]」というオブジェクトは、次の権限を拒否しました: [PERMISSIONS] + </string> + <string name="ScriptTakeMoney"> + リンデンドル(L$)を支払う + </string> + <string name="ActOnControlInputs"> + 制御入力に基づいて行動 + </string> + <string name="RemapControlInputs"> + 制御入力のリマップ + </string> + <string name="AnimateYourAvatar"> + アバターへのアニメーション動作 + </string> + <string name="AttachToYourAvatar"> + アバターに装着 + </string> + <string name="ReleaseOwnership"> + 所有権を解放し公のものとする + </string> + <string name="LinkAndDelink"> + 他のオブジェクトのリンクとリンク解除 + </string> + <string name="AddAndRemoveJoints"> + 他のオブジェクトとのジョイントの追加と削除 + </string> + <string name="ChangePermissions"> + 権限の変更 + </string> + <string name="TrackYourCamera"> + カメラ追従 + </string> + <string name="ControlYourCamera"> + カメラのコントロール + </string> + <string name="only_user_message"> + このセッションにいるユーザーはあなただけです。 + </string> + <string name="offline_message"> + [FIRST] [LAST]はオフラインです。 + </string> + <string name="invite_message"> + このボイスチャットに応答/接続する場合は、[BUTTON NAME]をクリックしてください。 + </string> + <string name="generic_request_error"> + 要求中にエラーが発生しました。後でもう一度試してください。 + </string> + <string name="insufficient_perms_error"> + あなたには充分な権限がありません。 + </string> + <string name="session_does_not_exist_error"> + このセッションは既に切断されています。 + </string> + <string name="no_ability_error"> + あなたにはその能力がありません。 + </string> + <string name="not_a_mod_error"> + あなたはセッション・モデレータではありません。 + </string> + <string name="muted_error"> + グループモデレータがあなたのテキストチャットを無効化しました + </string> + <string name="add_session_event"> + [RECIPIENT] とのチャット・セッションにユーザーを追加することができません + </string> + <string name="message_session_event"> + [RECIPIENT] とのチャット・セッションにメッセージを送ることができません + </string> + <string name="removed_from_group"> + あなたはグループから削除されました。 + </string> + <string name="close_on_no_ability"> + このチャット・セッションを継続することはできません + </string> </strings> diff --git a/indra/newview/skins/default/xui/nl/floater_postcard.xml b/indra/newview/skins/default/xui/nl/floater_postcard.xml index 9ca6fcc026..a6d10f2244 100644 --- a/indra/newview/skins/default/xui/nl/floater_postcard.xml +++ b/indra/newview/skins/default/xui/nl/floater_postcard.xml @@ -31,6 +31,6 @@ Kom dit zien! </string> <string name="upload_message"> - "Verzenden…" + Verzenden... </string> </floater> 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/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml index cbe075362a..b47e92b682 100644 --- a/indra/newview/skins/default/xui/nl/notifications.xml +++ b/indra/newview/skins/default/xui/nl/notifications.xml @@ -576,7 +576,7 @@ Verplaats alstublieft alle objecten die u wilt verwerven naar dezelfde regio. <notification name="PromptGoToCurrencyPage"> [EXTRA] -Naar [URL] gaan voor informatie over de aankoop valuta? +Naar [_URL] gaan voor informatie over de aankoop L$? <usetemplate name="okcancelbuttons" notext="Annuleren" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -805,7 +805,6 @@ Geen groep geselecteerd. <notification name="CannotDeedLandNoRegion"> Kan land niet toekennen: Kan de regio niet vinden waar dit land zich bevind. -Gebruik alstublieft Gereedschappen -> Report Bug om het te rapporteren. </notification> <notification name="CannotDeedLandMultipleSelected"> Kan land niet toekennen: @@ -852,8 +851,6 @@ Percelen in uw eigendom verschijnen in groen. <notification name="CannotReleaseLandRegionNotFound"> Kan land niet afstaan: Kan de regio niet vinden waar dit land zich bevind. - -Gebruik alstublieft Gereedschappen > Report Bug om het te rapporteren. </notification> <notification name="CannotReleaseLandNoTransfer"> Kan land niet afstaan: @@ -892,14 +889,10 @@ Land opdelen? <notification name="CannotDivideLandNoRegion"> Kan het land niet opdelen: Kan de regio niet vinden waar dit land zich bevind. - -Gebruik alstublieft Gereedschappen > Report Bug om het te rapporteren. </notification> <notification name="CannotJoinLandNoRegion"> Kan land niet verbinden: Kan de regio niet vinden waar dit land zich bevind. - -Gebruik alstublieft Gereedschappen > Report Bug om het te rapporteren. </notification> <notification name="CannotJoinLandNothingSelected"> Kan land niet verbinden: @@ -959,8 +952,6 @@ Grijs = Openbaar Kon [NAME] niet opslaan in centrale (asset) opslag. Meestal is dit een tijdelijk probleem. Wijzig en sla het draagbaar item over een paar minuten opnieuw op. - -Indien dit probleem aanhoudt, klik dan alstublieft op 'Gereedschap > Rapporteer Bug' in het menu en voeg informatie toe over uw netwerk instellingen. </notification> <notification name="YouHaveBeenLoggedOut"> U bent uitgelogd uit [SECOND_LIFE]: @@ -1302,10 +1293,6 @@ Downloaden naar uw Applicatie Data map? Naar www.secondlife.com gaan om uw account te beheren? <usetemplate ignoretext="Bij openen van webbrowser om uw account te beheren" name="okcancelignore" notext="Annuleren" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Bezoek de [SECOND_LIFE] Wiki en leer hoe Bugs correct gerapporteerd kunnen worden. - <usetemplate ignoretext="Bij openen webbrowser om de Bug Reporting 101 Wiki te bekijken" name="okcancelignore" notext="Annuleren" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Bezoek de [SECOND_LIFE] Wiki voor details over hoe een Veiligheids Probleem (Security Issue) te rapporteren. <usetemplate ignoretext="Bij openen webbrowser om de Veiligheids Problemen Wiki (Security Issues Wiki) te bekijken" name="okcancelignore" notext="Annuleren" yestext="OK"/> @@ -2044,26 +2031,11 @@ De regio eigenaar zal de rapporten afhandelen op basis van de regels geldend voo De afhandeling van dit rapport is alleen van toepassing op deze regio. Toegang van Inwoners tot andere gebieden van [SECOND_LIFE] zullen niet beïnvloed worden door de uitkomst van dit rapport. Alleen Linden Lab kan de toegang tot geheel [SECOND_LIFE] beperken. </notification> - <notification name="HelpReportBug"> - Gebruik dit gereedschap *alleen* voor het rapporteren van technische opties die niet functioneren als verwacht. Geef alstublieft zoveel mogelijk technische details als mogelijk. U kunt de automatische-antwoord email gebruiken om op te reageren om aanvullende gegevens toe te voegen aan uw rapport. - -Alle bug rapporten worden onderzocht en ingeschat. Er zal geen antwoord per email worden verzonden. - -Als u technische problemen heeft, neem dan contact op met Support op: -http://secondlife.com/community/support.php - -Opmerking: Onvolledige rapporten zullen niet worden onderzocht. - </notification> <notification name="HelpReportAbuseSelectCategory"> Selecteer alstublieft een categorie voor dit misbruik rapport. Het selecteren van een categorie helpt ons met het archiveren en verwerken van misbruik rapporten. </notification> - <notification name="HelpReportBugSelectCategory"> - Selecteer alstublieft een categorie voor dit bug rapport. - -Het selecteren van een categorie helpt ons met het archiveren en verwerken van bug rapporten. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Geef alstublieft een naam op van de misbruiker. @@ -2079,11 +2051,6 @@ Een accurate waarde opgeven helpt ons met het archiveren en verwerken van misbru Een accurate waarde opgeven helpt ons met het archiveren en verwerken van misbruik rapporten. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Geef alstublieft een korte samenvatting van de bug. - -Een accurate samenvatting opgeven helpt ons met het archiveren en verwerken van bug rapporten. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Geef alstublieft een gedetailleerde omschrijving van het misbruik dat plaats vond. @@ -2091,13 +2058,6 @@ Wees zo specifiek als mogelijk, inclusief namen en details van het incident waar Het opgeven van een accurate omschrijving helpt ons met het archiveren en verwerken van misbruik rapporten. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Geef alstublieft een gedetailleerde omschrijving van de bug. - -Wees zo specifiek als mogelijk, inclusief stappen om de bug te reproduceren, indien mogelijk. - -Het opgeven van een accurate omschrijving helpt ons met het archiveren en verwerken van misbruik rapporten. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Beste Inwoner, diff --git a/indra/newview/skins/default/xui/nl/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml index 4f5f60bcfe..bb073f735d 100644 --- a/indra/newview/skins/default/xui/nl/strings.xml +++ b/indra/newview/skins/default/xui/nl/strings.xml @@ -516,4 +516,110 @@ <string name="GraphicsQualityHigh"> Hoog </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Linden locatie</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Kunst & Cultuur</string> + <string name="Business">Zakelijk</string> + <string name="Educational">Educatief</string> + <string name="Gaming">Spelen</string> + <string name="Hangout">Ontmoetingsplaats</string> + <string name="Newcomer Friendly">Nieuwkomervriendelijk</string> + <string name="Parks&Nature">Parken & natuur</string> + <string name="Residential">Woongebied</string> + <string name="Shopping">Winkelen</string> + <string name="Other">Anders</string> + + <string name="ringing"> + Verbinden met in-wereld voice chat... + </string> + <string name="connected"> + Verbonden + </string> + <string name="unavailable"> + Voice is niet beschikbaar op uw huidige locatie + </string> + <string name="hang_up"> + Verbinding met in-wereld voicechat verbroken + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', een object van '[OWNERNAME]', gevestigd in [REGIONNAME] op [REGIONPOS], is toestemming verleend om te: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + '[OBJECTNAME]', een object van '[OWNERNAME]', gevestigd in [REGIONNAME] op [REGIONPOS], is toestemming geweigerd om te: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Linden dollars (L$) van u wegnemen + </string> + <string name="ActOnControlInputs"> + Acteren op uw bedieningsinvoer + </string> + <string name="RemapControlInputs"> + Uw bedieningsinvoer herdefiniëren + </string> + <string name="AnimateYourAvatar"> + Animeer uw avatar + </string> + <string name="AttachToYourAvatar"> + Bevestig aan uw avatar + </string> + <string name="ReleaseOwnership"> + Eigendom vrijgeven en openbaar worden + </string> + <string name="LinkAndDelink"> + Koppelen met en ontkoppelen van andere objecten + </string> + <string name="AddAndRemoveJoints"> + Toevoegen en verwijderen koppelingen met andere objecten + </string> + <string name="ChangePermissions"> + Wijzig zijn permissies + </string> + <string name="TrackYourCamera"> + Volg uw camera + </string> + <string name="ControlYourCamera"> + Bedien uw camera + </string> + + <string name="only_user_message"> + U bent de enige gebruiker in deze sessie. + </string> + <string name="offline_message"> + [FIRST] [LAST] is offline. + </string> + <string name="invite_message"> + Klik de [BUTTON NAME] knop om deze voicechat te accepteren/verbinden. + </string> + <string name="generic_request_error"> + Fout tijdens het maken van het verzoek, probeer het later nog een keer. + </string> + <string name="insufficient_perms_error"> + U heeft niet voldoende permissies. + </string> + <string name="session_does_not_exist_error"> + De sessie bestaat niet meer + </string> + <string name="no_ability_error"> + U beschikt niet over die mogelijkheid. + </string> + <string name="not_a_mod_error"> + U bent geen sessie moderateur + </string> + <string name="muted_error"> + Een groepsmoderator heeft uw textchat uitgeschakeld. + </string> + <string name="add_session_event"> + Kan geen gebruikers toevoegen aan chatsessie met [RECIPIENT]. + </string> + <string name="message_session_event"> + Kan uw bericht niet versturen naar de chatsessie met [RECIPIENT]. + </string> + <string name="removed_from_group"> + U bent verwijderd uit de groep. + </string> + <string name="close_on_no_ability"> + U heeft niet langer de mogelijkheid om in deze chatsessie te zijn. + </string> </strings> diff --git a/indra/newview/skins/default/xui/pl/floater_about_land.xml b/indra/newview/skins/default/xui/pl/floater_about_land.xml index b146891787..83d4b717a7 100755 --- a/indra/newview/skins/default/xui/pl/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pl/floater_about_land.xml @@ -320,7 +320,7 @@ Jedynie większe posiadłości mogą być umieszczone w bazie wyszukiwarki. /> <combo_box.item name="item8" label="Przyjazne dla nowych" /> - <combo_box.item name="item9" label=" Park i Natura" + <combo_box.item name="item9" label="Park i Natura" /> <combo_box.item name="item10" label="Mieszkalna" /> diff --git a/indra/newview/skins/default/xui/pl/floater_god_tools.xml b/indra/newview/skins/default/xui/pl/floater_god_tools.xml index 762b9f0f55..df821f3b6d 100755 --- a/indra/newview/skins/default/xui/pl/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/pl/floater_god_tools.xml @@ -46,7 +46,7 @@ </text> <spinner name="land cost"/> <text name="land cost text"> - L$/m: + L$/m²: </text> <button label="Odśwież" label_selected="Odśwież" name="Refresh" /> <button label="Zastosuj" label_selected="Zastosuj" name="Apply" /> @@ -80,17 +80,17 @@ Cel: </text> <combo_box name="destination"> - <combo_box.item name="Selection" label="Selekcja" /> - <combo_box.item name="AgentRegion" label="Agent Regionu" /> + <combo_box.item name="item1" label="Selekcja" /> + <combo_box.item name="item2" label="Agent Regionu" /> </combo_box> <text name="Request:"> Żądanie: </text> <combo_box name="request"> - <combo_box.item name="colliders<steps>" label="kolidery <kroki>" /> - <combo_box.item name="scripts<count>,<optionalpattern>" label="skrypty <policz>,<opcjonalnie powtórzenie>" /> - <combo_box.item name="objects<pattern>" label="obiekty <powtórzenia>" /> - <combo_box.item name="rez<asset_id>" label="rez <asset_id>" /> + <combo_box.item name="item1" label="kolidery <kroki>" /> + <combo_box.item name="item2" label="skrypty <policz>,<opcjonalnie powtórzenie>" /> + <combo_box.item name="item3" label="obiekty <powtórzenia>" /> + <combo_box.item name="item4" label="rez <asset_id>" /> </combo_box> <text name="Parameter:"> Parameter: diff --git a/indra/newview/skins/default/xui/pl/floater_postcard.xml b/indra/newview/skins/default/xui/pl/floater_postcard.xml index b6b0dcb858..e5bdaf2ba9 100755 --- a/indra/newview/skins/default/xui/pl/floater_postcard.xml +++ b/indra/newview/skins/default/xui/pl/floater_postcard.xml @@ -31,6 +31,6 @@ Sprawdź i przekonaj się sam! </string> <string name="upload_message"> - "Wysyłanie..." + Wysyłanie... </string> </floater> diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 15089926b2..ef5dad8786 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -562,7 +562,7 @@ Ta osoba tymczasowo nie będzie mógła się poruszać, nie będzie mógł używ <notification name="PromptGoToCurrencyPage"> [EXTRA] -Iść na stronę [URL] po informacje dotyczące zakupu gotówki? +Iść na stronę [_URL] po informacje dotyczące zakupu L$? <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> </notification> <notification name="UnableToLinkObjects"> @@ -792,8 +792,6 @@ Grupa nie została wybrana. <notification name="CannotDeedLandNoRegion"> Nie można przekazać posiadłości: Region nie znaleziony. - -Zgłoś ten problem pod Pomoc > Zgłoś Błędy Klienta </notification> <notification name="CannotDeedLandMultipleSelected"> Nie można przekazać posiadłości: @@ -840,8 +838,6 @@ Twoje posiadłości są podkreślone na zielono. <notification name="CannotReleaseLandRegionNotFound"> Nie można porzucić posiadłości: Region nie znaleziony. - -Zgłoś ten problem pod Pomoc > Zgłoś Błędy Klienta </notification> <notification name="CannotReleaseLandNoTransfer"> Nie możesz porzucić posiadłości: @@ -881,14 +877,10 @@ Podzielić posiadłość? <notification name="CannotDivideLandNoRegion"> Nie można podzielić posiadłości: Region nie znaleziony. - -Zgłoś ten problem pod Pomoc > Zgłoś Błędy Klienta </notification> <notification name="CannotJoinLandNoRegion"> Nie można połączyć posiadłości: Region nie znaleziony. - -Zgłoś ten problem pod Pomoc > Zgłoś Błędy Klienta </notification> <notification name="CannotJoinLandNothingSelected"> Nie można połączyć posiadłości: @@ -944,9 +936,8 @@ Szary = Publiczna Nie można zapisać '[NAME]' do pliku stroju. Musisz zwolnić trochę miejsca na Twoim komputerze i zapisać strój jeszcze raz. </notification> <notification name="CannotSaveToAssetStore"> - Nie można zapisać [NAME] w centralnym zbiorze danych. Zazwyczaj jest to tymczasowy problem. Możesz kontynuować modyfikacje i zapisać strój ponownie za kilka minut. - -Jeżeli wciąż masz ten problem, wybierz Pomoc > Zgłoś Błędy Klienta i podaj szczegóły dotyczące konfiguracji sieci. + Nie można zapisać [NAME] w centralnym zbiorze danych. +Zazwyczaj jest to tymczasowy problem. Możesz kontynuować modyfikacje i zapisać strój ponownie za kilka minut. </notification> <notification name="YouHaveBeenLoggedOut"> Twoja sesja [SECOND_LIFE] została zakończona: @@ -1282,10 +1273,6 @@ Załadować do foldera Aplikacji? Otworzyć stronę www.secondlife.com żeby zarządzać Twoim kontem? <usetemplate ignoretext="Otwierając systemową przeglądarkę żeby zarządzać Twoim kontem" name="okcancelignore" notext="Anuluj" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Odwiedź [SECOND_LIFE] Wiki i zobacz jak zgłaszać błędy. - <usetemplate ignoretext="Otwierając przeglądarkę żeby zobaczyć Wiki zgłaszania błędów" name="okcancelignore" notext="Anuluj" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Odwiedź [SECOND_LIFE] Wiki i zobacz jak zgłaszać problemy z bezpieczeństwem danych. <usetemplate ignoretext="Otwierając przeglądarkę żeby zobaczyć Wiki kwestii bezpieczeństwa danych" name="okcancelignore" notext="Anuluj" yestext="OK"/> @@ -1988,25 +1975,10 @@ Właściciel regionu będzie rozpatrywał raporty w oparciu o lokalne prawa tego Rozwiązanie tego raportu odnosi się wyłącznie do tego regionu; konkluzja tego raportu nie będzie miała wpływu na dostęp Rezydentów do innych regionów w [SECOND_LIFE]. Wyłącznie Linden Lab może całkowicie odebrać dostęp do [SECOND_LIFE]. </notification> - <notification name="HelpReportBug"> - Używaj tej opcji *wyłącznie* w celu zgłaszania technicznych problemów, dołączając szczegółowy opis problemu. Możesz odpowiedzieć na automatyczną email z odpowiedzią żeby dodać więcej szczegółów do Twojego raportu. - -Wszystkie raporty błędów są analizowane i oceniane. Kontakt przez email nie będzie nawiązany. - -Jeżeli masz techniczne problemy, skontaktuj się z pomocą techniczną pod: - -http://secondlife.com/community/support.php - -Uwaga: Niekompletne raporty nie będą analizowane. - </notification> <notification name="HelpReportAbuseSelectCategory"> Wybierz kategorię dla tego raportu o nadużyciu. Określenie kategorii pomoże nam w klasyfikacji i prztwarzaniu raportu. </notification> - <notification name="HelpReportBugSelectCategory"> - Wybierz kategorię dla tego błędu. -Określenie kategorii pomoże nam w klasyfikacji i prztwarzaniu raportu. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Wprowadź imię i nazwisko osoby popełniającej nadużycie. Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. @@ -2019,19 +1991,11 @@ Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. Wprowadź opis popełnionego nadużycia. Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Wprowadź opis błędu. -Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Wprowadź szczgółowy opis popełnionego nadużycia. Podaj maksymalną ilość szczgółów oraz imiona i nazwiska osób związanych z nadużyciem które zgłaszasz. Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Wprowadź szczgółowy opis błędu. Podaj maksymalną ilość szczgółów oraz, jeżeli to możliwe, kroki niezbędne do odtworzenia problemu. -Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Szanowny Rezydencie, diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index 402bf0a3ed..294353ee03 100755 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -516,4 +516,109 @@ <string name="GraphicsQualityHigh"> Wysoka </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Linden Lokacja</string> + <string name="Adult">'Adult'</string> + <string name="Arts&Culture">Sztuka i Kultura</string> + <string name="Business">Biznes</string> + <string name="Educational">Edukacyjna</string> + <string name="Gaming">Gra</string> + <string name="Hangout">Poznawanie ludzi</string> + <string name="Newcomer Friendly">Przyjazne dla nowych</string> + <string name="Parks&Nature">Park i Natura</string> + <string name="Residential">Mieszkalna</string> + <string name="Shopping">Zakupy</string> + <string name="Other">Inna</string> + + <string name="ringing"> + Łączenie z rozmowami głosem w świecie... + </string> + <string name="connected"> + Połączenie uzyskane. + </string> + <string name="unavailable"> + Niestety, rozmowy głosem są niedozwolone w tym miejscu. + </string> + <string name="hang_up"> + Połączenie rozmowy utracone. + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', właściciel: '[OWNERNAME]', położenie: [REGIONNAME] [REGIONPOS], pozwala Ci na: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + '[OBJECTNAME]', właściciel: '[OWNERNAME]', położenie: [REGIONNAME] [REGIONPOS], nie pozwala Ci na: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Zabiera Lindeny (L$) od Ciebie + </string> + <string name="ActOnControlInputs"> + Używaj klawiszy sterowania + </string> + <string name="RemapControlInputs"> + Zmień klawisze sterowania + </string> + <string name="AnimateYourAvatar"> + Animuj Awatara + </string> + <string name="AttachToYourAvatar"> + Dołącz do Awatara + </string> + <string name="ReleaseOwnership"> + Usuń prawo własności (zmień na publiczne) + </string> + <string name="LinkAndDelink"> + Łącz / odłącz z innymi obiektów + </string> + <string name="AddAndRemoveJoints"> + Dodaj / usuń połączenia z innymi obiektami + </string> + <string name="ChangePermissions"> + Ustaw zezwolenia + </string> + <string name="TrackYourCamera"> + Chodź za kamerą + </string> + <string name="ControlYourCamera"> + Kontroluj kamerę + </string> + <string name="only_user_message"> + Jesteś jedyną osobą w tej konferencji. + </string> + <string name="offline_message"> + [FIRST] [LAST] - ta osoba jest obecnie niedostępna. + </string> + <string name="invite_message"> + Kliknij na [BUTTON NAME] przycisk by zaakceptować/dołączyć do tej rozmowy. + </string> + <string name="generic_request_error"> + Błąd. Spróbuj ponownie za kilka minut. + </string> + <string name="insufficient_perms_error"> + Nie posiadasz praw do kontynuacji. + </string> + <string name="session_does_not_exist_error"> + Ta konferencja jest już zakończona. + </string> + <string name="no_ability_error"> + Nie posiadesz tego przywileju. + </string> + <string name="not_a_mod_error"> + Nie jesteś moderatorem konferencji. + </string> + <string name="muted_error"> + Moderator wyciszył Cię. + </string> + <string name="add_session_event"> + Nie można dodać nikogo do czatu z [RECIPIENT]. + </string> + <string name="message_session_event"> + Nie można wysłać Twojej wiadomości do sesji czatu z [RECIPIENT]. + </string> + <string name="removed_from_group"> + Usunięto Cię z grupy. + </string> + <string name="close_on_no_ability"> + Nie posiadasz praw by uczestniczyć w tej konferencji. + </string> </strings> diff --git a/indra/newview/skins/default/xui/pt/floater_god_tools.xml b/indra/newview/skins/default/xui/pt/floater_god_tools.xml index 6b88db1d9c..9406658f62 100644 --- a/indra/newview/skins/default/xui/pt/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_god_tools.xml @@ -39,7 +39,7 @@ Fator cobrança: </text> <text name="land cost text"> - L$ por metros quadrados + L$ por m²: </text> <button label="Atualizar" label_selected="Atualizar" name="Refresh" tool_tip="Clique aqui para atualizar a informação acima."/> <button label="Aplicar" label_selected="Aplicar" name="Apply" tool_tip="Clique aqui para aplicar qualquer mudança acima"/> @@ -73,17 +73,17 @@ Destino: </text> <combo_box name="destination"> - <combo_box.item name="Selection" label="Seleção" /> - <combo_box.item name="AgentRegion" label="Região do Agente" /> + <combo_box.item name="item1" label="Seleção" /> + <combo_box.item name="item2" label="Região do Agente" /> </combo_box> <text name="Request:"> Requisição: </text> <combo_box name="request"> - <combo_box.item name="colliders<steps>" label="Passos de Colisão" /> - <combo_box.item name="scripts<count>,<optionalpattern>" label="Contagem de scripts, padrão opcional" /> - <combo_box.item name="objects<pattern>" label="Padrão de Objetos" /> - <combo_box.item name="rez<asset_id>" label="rez <asset_id>" /> + <combo_box.item name="item1" label="Passos de Colisão" /> + <combo_box.item name="item2" label="Contagem de scripts, padrão opcional" /> + <combo_box.item name="item3" label="Padrão de Objetos" /> + <combo_box.item name="item4" label="rez <asset_id>" /> </combo_box> <text name="Parameter:"> Parametro: diff --git a/indra/newview/skins/default/xui/pt/floater_postcard.xml b/indra/newview/skins/default/xui/pt/floater_postcard.xml index bd3d41e52f..62fd050ea4 100644 --- a/indra/newview/skins/default/xui/pt/floater_postcard.xml +++ b/indra/newview/skins/default/xui/pt/floater_postcard.xml @@ -35,6 +35,6 @@ Dá uma olhada nisto! </string> <string name="upload_message"> - "Enviando..." + Enviando... </string> </floater> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 411f45a650..1f15feef49 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -570,7 +570,7 @@ Por favor, mova todos os objetos a serem adquiridos para uma mesma região. <notification name="PromptGoToCurrencyPage"> [EXTRA] -Vá para [URL] para informação sobre compra de dinheiro. +Vá para [_URL] para informação sobre compra de L$. <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Ir até a página"/> </notification> <notification name="UnableToLinkObjects"> @@ -798,7 +798,6 @@ Nenhum grupo selecionado. <notification name="CannotDeedLandNoRegion"> Não é possível transferir posse do terreno: Não é possível se achar a região em que este terreno se encontra. -Por favor, use Ferramentas > Reporte de Bug para reportar isto. </notification> <notification name="CannotDeedLandMultipleSelected"> Impossibilitado de passar a propriedade da terra: @@ -844,8 +843,6 @@ Os lotes que você possui estão em verde. <notification name="CannotReleaseLandRegionNotFound"> Impossibilitado de abandonar a terra: Não consegue achar a região em que esta terra se encontra. - -Por favor, usar Ferramentas > Reportar Bug, para reportar este erro. </notification> <notification name="CannotReleaseLandNoTransfer"> Não é possível abandonar terreno: @@ -884,14 +881,10 @@ Quer dividir o terreno? <notification name="CannotDivideLandNoRegion"> Impossibilitado de dividir a terra: Não consegue achar a região em que esta terra se encontra. - -Por favor, usar Ferramentas > Reportar Bug, para reportar este erro. </notification> <notification name="CannotJoinLandNoRegion"> Impossibilitado de unir a terra: Não consegue achar a região em que esta terra se encontra. - -Por favor, usar Ferramentas > Reportar Bug, para reportar este erro. </notification> <notification name="CannotJoinLandNothingSelected"> Não é possível unir terreno: @@ -950,8 +943,6 @@ Grey = Pública <notification name="CannotSaveToAssetStore"> Impossibilitado de salvar [NAME] no armazenamento central de ativos. Isso é geralmente uma falha temporária. Por favor personalize e salve novamente a vestimenta em poucos minutos. - -Se o problema persistir, por favor clicar sobre 'Ferramentas > Bug Report' no menu superior e forneça detalhes sobre a configuração de sua rede. </notification> <notification name="YouHaveBeenLoggedOut"> Você foi deslogado do [SECOND_LIFE]: @@ -1284,10 +1275,6 @@ Baixar para sua pasta de Aplicativos? Ir ao www.secondlife.com para gerenciar sua conta? <usetemplate ignoretext="Ao abrir o navegador web para gerenciar sua conta" name="okcancelignore" notext="Cancelar" yestext="OK"/> </notification> - <notification name="WebLaunchBugReport101"> - Visite a Wiki [SECOND_LIFE] para aprender como reportar bugs corretamente. - <usetemplate ignoretext="Ao abrir o web browser para visualizar o report de Bug 101 na Wiki" name="okcancelignore" notext="Cancelar" yestext="OK"/> - </notification> <notification name="WebLaunchSecurityIssues"> Visite a Wiki do [SECOND_LIFE] para detalhes de como Reportar um Problema de Segurança. <usetemplate ignoretext="Ao abrir o navegador da web para visualizar a Wiki de Problemas de Segurança" name="okcancelignore" notext="Cancelar" yestext="OK"/> @@ -2008,27 +1995,10 @@ O dono da região resolverá as reportagens baseado nas regras locais desta regi A resolução desta reportagem se aplica apenas a esta região; o acesso de Residentes às outras áreas do [SECOND_LIFE] não será afetado pelas decisões desta reportagem. Apenas a Linden Lab pode restringir acesso a todo o [SECOND_LIFE]. </notification> - <notification name="HelpReportBug"> - Use esta ferramenta para reportar *apenas* características técnicas que não atuem como descrito ou esperado. -Por favor, forneça tantos detalhes quanto possível. -Você pode responder ao e-mail de resposta automática para adicionar mais detalhes à sua reportagem. - -Todas as reportagens de bugs são investigadas e avaliadas. -Nenhum e-mail de resposta será enviado. - -Se você estiver tendo uma dificuldade técnica, por favor contate o Suporte em: -http://secondlife.com/community/support.php - -Nota: reportagens incompletas não serão investigadas - </notification> <notification name="HelpReportAbuseSelectCategory"> Por favor, selecione uma categoria para a reportagem deste abuso. A seleção de uma categoria nos ajuda a arquivar e processar as reportagens de abuso. </notification> - <notification name="HelpReportBugSelectCategory"> - Por favor, selecione uma categoria para este bug. -A seleção de uma categoria nos ajuda a arquivar e processar as reportagens de bugs. - </notification> <notification name="HelpReportAbuseAbuserNameEmpty"> Por favor, entre com o nome do perturbador. Entrando com um valor preciso, nos ajuda a arquivar e processar as reportagens de abuso. @@ -2041,19 +2011,11 @@ Entrando com um valor preciso, nos ajuda a arquivar e processar as reportagens d Por favor, digite um resumo de como ocorreu o abuso. Fazer um resumo detalhado nos ajuda a arquivar e processar as reportagens de abuso. </notification> - <notification name="HelpReportBugSummaryEmpty"> - Por favor, digite um resumo do bug. Realizar um resumo detalhado nos ajuda a arquivar e processar as reportagens de abuso. - </notification> <notification name="HelpReportAbuseDetailsEmpty"> Por favor, digite uma descrição detalhada do abuso que ocorreu. Seja tão específico quanto você puder, incluindo nomes e os detalhes do incidente que está denunciando. Fazer uma descrição precisa nos ajuda a arquivar e processar as reportagens de abuso. </notification> - <notification name="HelpReportBugDetailsEmpty"> - Por favor, digite uma descrição detalhada do bug. -Seja tão específico quanto você puder, incluindo as etapas para reproduzir o bug, se possível. -Fazer uma descrição precisa nos ajuda a arquivar e processar os relatórios de bugs. - </notification> <notification name="HelpReportAbuseContainsCopyright"> Caro Residente, diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 36377b346b..b6788567e2 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -513,4 +513,108 @@ <string name="GraphicsQualityHigh"> Alto </string> + + <!-- PARCEL_CATEGORY_UI_STRING --> + <string name="Linden Location">Locação Linden</string> + <string name="Adult">Adult</string> + <string name="Arts&Culture">Artes e Cultura</string> + <string name="Business">Negócios</string> + <string name="Educational">Educacional</string> + <string name="Gaming">Jogos</string> + <string name="Hangout">Moradia</string> + <string name="Newcomer Friendly">Amigável a Novos Usuários</string> + <string name="Parks&Nature">Parques & Natureza</string> + <string name="Residential">Residencial</string> + <string name="Shopping">Compras</string> + <string name="Other">Outros</string> + <string name="ringing"> + Conectando à conversa de Voz no mundo + </string> + <string name="connected"> + Conectado + </string> + <string name="unavailable"> + Voz não disponível na sua localização atual + </string> + <string name="hang_up"> + Desconectado da conversa de Voz no mundo + </string> + <string name="ScriptQuestionCautionChatGranted"> + '[OBJECTNAME]', um objeto de '[OWNERNAME]', localizado em [REGIONNAME] a [REGIONPOS], obteve permissão para: [PERMISSIONS]. + </string> + <string name="ScriptQuestionCautionChatDenied"> + '[OBJECTNAME]', um objeto de '[OWNERNAME]', localizado em [REGIONNAME] a [REGIONPOS], teve permissão negada para: [PERMISSIONS]. + </string> + <string name="ScriptTakeMoney"> + Tomar linden dólares (L$) de você + </string> + <string name="ActOnControlInputs"> + Atue nas suas entradas de controle + </string> + <string name="RemapControlInputs"> + Remapeie suas entradas de controle + </string> + <string name="AnimateYourAvatar"> + Faça uma animação para o seu avatar + </string> + <string name="AttachToYourAvatar"> + Anexe ao seu avatar + </string> + <string name="ReleaseOwnership"> + Libere a propriedade e torne-a pública + </string> + <string name="LinkAndDelink"> + Una e desuna de outros objetos + </string> + <string name="AddAndRemoveJoints"> + Adicione e remova junções com outros objetos + </string> + <string name="ChangePermissions"> + Modifique as permissões + </string> + <string name="TrackYourCamera"> + Acompanhe sua câmera + </string> + <string name="ControlYourCamera"> + Controle sua camera + </string> + <string name="only_user_message"> + Você é o único usuário desta sessão. + </string> + <string name="offline_message"> + [FIRST] [LAST] está offline. + </string> + <string name="invite_message"> + Clique no botão [BUTTON NAME] para aceitar/ conectar a este bate-papo em voz. + </string> + <string name="generic_request_error"> + Erro na requisição, por favor, tente novamente. + </string> + <string name="insufficient_perms_error"> + Você não tem permissões suficientes. + </string> + <string name="session_does_not_exist_error"> + A sessão deixou de existir + </string> + <string name="no_ability_error"> + Você não possui esta habilidade. + </string> + <string name="not_a_mod_error"> + Você não é um moderador de sessão. + </string> + <string name="muted_error"> + Um moderador do grupo desabilitou seu bate-papo em texto. + </string> + <string name="add_session_event"> + Não foi possível adicionar usuários na sessão de bate-papo com [RECIPIENT]. + </string> + <string name="message_session_event"> + Não foi possível enviar sua mensagem na sessão de bate- papo com [RECIPIENT]. + </string> + <string name="removed_from_group"> + Você foi removido do grupo. + </string> + <string name="close_on_no_ability"> + Você não possui mais a habilidade de estar na sessão de bate-papo. + </string> </strings> 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/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 036fa4923f..4ce7c953ed 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -271,8 +271,8 @@ class WindowsManifest(ViewerManifest): # For google-perftools tcmalloc allocator. if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("libtcmalloc_minimal.dll") - self.end_prefix() + self.path("libtcmalloc_minimal.dll") + self.end_prefix() def nsi_file_commands(self, install=True): @@ -395,6 +395,8 @@ class WindowsManifest(ViewerManifest): # We use the Unicode version of NSIS, available from # http://www.scratchpaper.com/ NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' + if not os.path.exists(NSIS_path): + NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe') self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) # self.remove(self.dst_path_of(tempfile)) # If we're on a build machine, sign the code using our Authenticode certificate. JC diff --git a/indra/test/test.cpp b/indra/test/test.cpp index e7ba8e33b8..721e9da917 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -141,12 +141,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) @@ -350,9 +347,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(); } @@ -362,7 +361,7 @@ int main(int argc, char **argv) delete output; } - if (touch) + if (touch && success) { std::ofstream s; s.open(touch); @@ -371,5 +370,7 @@ int main(int argc, char **argv) } apr_terminate(); - return 0; + + int retval = (success ? 0 : 1); + return retval; } |