diff options
Diffstat (limited to 'indra')
147 files changed, 3712 insertions, 2123 deletions
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index 9adf24a492..8687a24655 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -87,7 +87,8 @@ #include "lldefs.h" #include "llerror.h" #include "llextendedstatus.h" -#include "llfasttimer.h" +// Don't do this, adds 15K lines of header code to every library file. +//#include "llfasttimer.h" #include "llfile.h" #include "llformat.h" diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 6a82a848be..41150ad057 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -38,7 +38,7 @@ #include "apr_time.h" #include <time.h> -#include <locale> +#include <locale.h> #include <string> #include <iomanip> #include <sstream> @@ -100,33 +100,28 @@ std::string LLDate::toHTTPDateString (std::string fmt) const { LLFastTimer ft1(FT_DATE_FORMAT); - std::ostringstream stream; time_t locSeconds = (time_t) mSecondsSinceEpoch; struct tm * gmt = gmtime (&locSeconds); - - stream.imbue (std::locale(LLStringUtil::getLocale().c_str())); - toHTTPDateStream (stream, gmt, fmt); - return stream.str(); + return toHTTPDateString(gmt, fmt); } std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) { LLFastTimer ft1(FT_DATE_FORMAT); - - std::ostringstream stream; - stream.imbue (std::locale(LLStringUtil::getLocale().c_str())); - toHTTPDateStream (stream, gmt, fmt); - return stream.str(); -} -void LLDate::toHTTPDateStream(std::ostream& s, tm * gmt, std::string fmt) -{ - LLFastTimer ft1(FT_DATE_FORMAT); + // avoid calling setlocale() unnecessarily - it's expensive. + static std::string prev_locale = ""; + std::string this_locale = LLStringUtil::getLocale(); + if (this_locale != prev_locale) + { + setlocale(LC_TIME, this_locale.c_str()); + prev_locale = this_locale; + } - const char * pBeg = fmt.c_str(); - const char * pEnd = pBeg + fmt.length(); - const std::time_put<char>& tp = std::use_facet<std::time_put<char> >(s.getloc()); - tp.put (s, s, s.fill(), gmt, pBeg, pEnd); + // use strftime() as it appears to be faster than std::time_put + char buffer[128]; + strftime(buffer, 128, fmt.c_str(), gmt); + return std::string(buffer); } void LLDate::toStream(std::ostream& s) const diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 23d3b900f8..9dcce9117f 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -86,7 +86,6 @@ public: void toStream(std::ostream&) const; std::string toHTTPDateString (std::string fmt) const; static std::string toHTTPDateString (tm * gmt, std::string fmt); - static void toHTTPDateStream(std::ostream&, tm *, std::string); /** * @brief Set the date from an ISO-8601 string. * diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 3b1379c76a..d0def896cf 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -36,7 +36,6 @@ #include <string> #include <locale> #include <iomanip> -#include <boost/regex.hpp> #include "llsd.h" #include "llfasttimer.h" @@ -232,7 +231,6 @@ public: typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims); - static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens); static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals); static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch); static S32 format(std::basic_string<T>& s, const format_map_t& substitutions); @@ -347,6 +345,8 @@ public: static void testHarness(); #endif +private: + static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens); }; template<class T> std::basic_string<T> LLStringUtilBase<T>::null; diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 9d46a8b454..9e38fddbd7 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -59,8 +59,11 @@ public: {} LLCoordGL(S32 x, S32 y) : LLCoord(x, y) {} + bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const LLCoordGL& other) const { return !(*this == other); } }; +//bool operator ==(const LLCoordGL& a, const LLCoordGL& b); // Window coords include things like window borders, // menu regions, etc. @@ -71,6 +74,8 @@ public: {} LLCoordWindow(S32 x, S32 y) : LLCoord(x, y) {} + bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const LLCoordWindow& other) const { return !(*this == other); } }; @@ -82,6 +87,8 @@ public: {} LLCoordScreen(S32 x, S32 y) : LLCoord(x, y) {} + bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const LLCoordScreen& other) const { return !(*this == other); } }; class LLCoordFont : public LLCoord @@ -96,6 +103,8 @@ public: void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; } void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; } + bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const LLCoordFont& other) const { return !(*this == other); } }; diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 7a8586fe2f..665a423d07 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -32,7 +32,7 @@ #ifndef LL_LLPLUGINCLASSMEDIA_H #define LL_LLPLUGINCLASSMEDIA_H -#include "llgl.h" +#include "llgltypes.h" #include "llpluginprocessparent.h" #include "llrect.h" #include "llpluginclassmediaowner.h" diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 3ae176cbeb..df6de0925e 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -32,7 +32,6 @@ #ifndef LL_LLPLUGINCLASSMEDIAOWNER_H #define LL_LLPLUGINCLASSMEDIAOWNER_H -#include "llgl.h" #include "llpluginprocessparent.h" #include "llrect.h" #include <queue> diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 95d693cdc4..cc9362a252 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -50,6 +50,7 @@ set(llui_SOURCE_FILES lllayoutstack.cpp lllineeditor.cpp lllistctrl.cpp + lllocalcliprect.cpp llmenugl.cpp llmodaldialog.cpp llmultifloater.cpp @@ -85,6 +86,7 @@ set(llui_SOURCE_FILES lltexteditor.cpp lltextparser.cpp lltransutil.cpp + lltooltip.cpp llui.cpp lluicolortable.cpp lluictrl.cpp @@ -133,6 +135,7 @@ set(llui_HEADER_FILES lllazyvalue.h lllineeditor.h lllistctrl.h + lllocalcliprect.h llmenugl.h llmodaldialog.h llmultifloater.h @@ -167,6 +170,7 @@ set(llui_HEADER_FILES lltextbox.h lltexteditor.h lltextparser.h + lltooltip.h lltransutil.h lluicolortable.h lluiconstants.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index bf58e19949..fa13ced037 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -514,6 +514,7 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) // virtual void LLButton::draw() { + F32 alpha = getDrawContext().mAlpha; bool flash = FALSE; static LLUICachedControl<F32> button_flash_rate("ButtonFlashRate", 0); static LLUICachedControl<S32> button_flash_count("ButtonFlashCount", 0); @@ -535,7 +536,7 @@ void LLButton::draw() // Unselected image assignments S32 local_mouse_x; S32 local_mouse_y; - LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); + LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); bool enabled = isInEnabledChain(); @@ -662,7 +663,7 @@ void LLButton::draw() if (hasFocus()) { F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); - drawBorder(imagep, gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt))); + drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, llround(lerp(1.f, 3.f, lerp_amt))); } if (use_glow_effect) @@ -685,21 +686,21 @@ void LLButton::draw() LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); if ( mScaleImage) { - imagep->draw(getLocalRect(), enabled ? mImageColor.get() : disabled_color ); + imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % mCurGlowStrength); + imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } else { - imagep->draw(0, 0, enabled ? mImageColor.get() : disabled_color ); + imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - imagep->drawSolid(0, 0, glow_color % mCurGlowStrength); + imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } @@ -709,7 +710,7 @@ void LLButton::draw() // no image lldebugs << "No image for button " << getName() << llendl; // draw it in pink so we can find it - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE); } // let overlay image and text play well together @@ -744,6 +745,7 @@ void LLButton::draw() { overlay_color.mV[VALPHA] = 0.5f; } + overlay_color.mV[VALPHA] *= alpha; switch(mImageOverlayAlignment) { @@ -815,7 +817,7 @@ void LLButton::draw() // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode. // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), - label_color, + label_color % alpha, mHAlign, LLFontGL::BOTTOM, LLFontGL::NORMAL, mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, @@ -956,17 +958,6 @@ void LLButton::setColor(const LLColor4& color) setImageColor(color); } -void LLButton::setAlpha(F32 alpha) -{ - LLColor4 temp = mImageColor.get(); - temp.setAlpha(alpha); - mImageColor.set(temp); - - temp = mDisabledImageColor.get(); - temp.setAlpha(alpha * 0.5f); - mDisabledImageColor.set(temp); -} - void LLButton::setImageDisabled(LLPointer<LLUIImage> image) { mImageDisabled = image; diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index e51cd443fa..06e1dac914 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -191,7 +191,6 @@ public: void setImageColor(const std::string& color_control); void setImageColor(const LLColor4& c); /*virtual*/ void setColor(const LLColor4& c); - /*virtual*/ void setAlpha(F32 alpha); void setImages(const std::string &image_name, const std::string &selected_name); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index ac56d15d1b..58aeb61728 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -55,6 +55,7 @@ #include "lllineeditor.h" #include "v2math.h" #include "lluictrlfactory.h" +#include "lltooltip.h" // Globals S32 LLCOMBOBOX_HEIGHT = 0; @@ -77,6 +78,7 @@ LLComboBox::ItemParams::ItemParams() LLComboBox::Params::Params() : allow_text_entry("allow_text_entry", false), + allow_new_values("allow_new_values", false), show_text_as_tentative("show_text_as_tentative", true), max_chars("max_chars", 20), list_position("list_position", BELOW), @@ -96,6 +98,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) mTextEntryTentative(p.show_text_as_tentative), mHasAutocompletedText(false), mAllowTextEntry(p.allow_text_entry), + mAllowNewValues(p.allow_new_values), mMaxChars(p.max_chars), mPrearrangeCallback(p.prearrange_callback()), mTextEntryCallback(p.text_entry_callback()), @@ -620,7 +623,15 @@ void LLComboBox::hideList() if (mList->getVisible()) { // assert selection in list - mList->selectNthItem(mLastSelectedIndex); + if(mAllowNewValues) + { + // mLastSelectedIndex = -1 means that we entered a new value, don't select + // any of existing items in this case. + if(mLastSelectedIndex >= 0) + mList->selectNthItem(mLastSelectedIndex); + } + else + mList->selectNthItem(mLastSelectedIndex); mButton->setToggleState(FALSE); mList->setVisible(FALSE); @@ -704,7 +715,7 @@ void LLComboBox::onItemSelected(const LLSD& data) } } -BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { std::string tool_tip; @@ -713,25 +724,17 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_re return TRUE; } - if (LLUI::sShowXUINames) + tool_tip = getToolTip(); + if (tool_tip.empty()) { - tool_tip = getShowNamesToolTip(); - } - else - { - tool_tip = getToolTip(); - if (tool_tip.empty()) - { - tool_tip = getSelectedItemLabel(); - } + tool_tip = getSelectedItemLabel(); } if( !tool_tip.empty() ) { - msg = tool_tip; - - // Convert rect local to screen coordinates - *sticky_rect_screen = calcScreenRect(); + LLToolTipMgr::instance().show(LLToolTipParams() + .message(tool_tip) + .sticky_rect(calcScreenRect())); } return TRUE; } diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 4becda195f..68cbfeeeeb 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -78,7 +78,8 @@ public: : public LLInitParam::Block<Params, LLUICtrl::Params> { Optional<bool> allow_text_entry, - show_text_as_tentative; + show_text_as_tentative, + allow_new_values; Optional<S32> max_chars; Optional<commit_callback_t> prearrange_callback, text_entry_callback, @@ -112,7 +113,7 @@ public: // LLView interface virtual void onFocusLost(); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleUnicodeCharHere(llwchar uni_char); @@ -224,6 +225,7 @@ protected: private: BOOL mAllowTextEntry; + BOOL mAllowNewValues; S32 mMaxChars; BOOL mTextEntryTentative; commit_callback_t mPrearrangeCallback; diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index d0789d6502..29f78f6290 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -34,10 +34,14 @@ #include "lldockablefloater.h" +//static +LLDockableFloater* LLDockableFloater::instance = NULL; + LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params) : LLFloater(key, params), mDockControl(dockControl) { + resetInstance(); } LLDockableFloater::~LLDockableFloater() @@ -51,23 +55,66 @@ BOOL LLDockableFloater::postBuild() return LLView::postBuild(); } +void LLDockableFloater::resetInstance() +{ + if (instance != this) + { + if (instance != NULL && instance->isDocked()) + { + //closeFloater() is not virtual + if (instance->canClose()) + { + instance->closeFloater(); + } + else + { + instance->setVisible(FALSE); + } + } + instance = this; + } +} + +void LLDockableFloater::setVisible(BOOL visible) +{ + if(visible && isDocked()) + { + resetInstance(); + } + LLFloater::setVisible(visible); +} + void LLDockableFloater::setDocked(bool docked, bool pop_on_undock) { - if (docked) + if (mDockControl.get() != NULL) { - mDockControl.get()->on(); + if (docked) + { + resetInstance(); + mDockControl.get()->on(); + } + else + { + mDockControl.get()->off(); + } } - else + + if (!docked && pop_on_undock) { - mDockControl.get()->off(); + // visually pop up a little bit to emphasize the undocking + translate(0, UNDOCK_LEAP_HEIGHT); } + LLFloater::setDocked(docked, pop_on_undock); } void LLDockableFloater::draw() { - mDockControl.get()->repositionDockable(); - mDockControl.get()->drawToungue(); + if (mDockControl.get() != NULL) + { + mDockControl.get()->repositionDockable(); + mDockControl.get()->drawToungue(); + } LLFloater::draw(); } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 5ece78a925..b977888803 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -43,6 +43,7 @@ */ class LLDockableFloater : public LLFloater { + static const U32 UNDOCK_LEAP_HEIGHT = 12; public: LOG_CLASS(LLDockableFloater); LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params = getDefaultParams()); @@ -51,6 +52,14 @@ public: /* virtula */BOOL postBuild(); /* virtual */void setDocked(bool docked, bool pop_on_undock = true); /* virtual */void draw(); + /*virtual*/ void setVisible(BOOL visible); + +private: + /** + * Provides unique of dockable floater. + * If dockable floater already exists it should be closed. + */ + void resetInstance(); protected: void setDockControl(LLDockControl* dockControl); @@ -60,6 +69,7 @@ protected: private: std::auto_ptr<LLDockControl> mDockControl; LLUIImagePtr mDockTongue; + static LLDockableFloater* instance; }; #endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp index 7d6a4007a2..26b5f2e182 100644 --- a/indra/llui/llfiltereditor.cpp +++ b/indra/llui/llfiltereditor.cpp @@ -44,6 +44,7 @@ LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p) line_editor_p.rect(getLocalRect()); line_editor_p.follows.flags(FOLLOWS_ALL); line_editor_p.text_pad_right(getRect().getHeight()); + line_editor_p.revert_on_esc(false); line_editor_p.keystroke_callback(boost::bind(&LLUICtrl::onCommit, this)); mFilterEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_p); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index ca3829e1bd..c027b59c71 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -218,9 +218,6 @@ LLFloater::Params::Params() close_callback("close_callback"), can_dock("can_dock", false) { - name = "floater"; - // defaults that differ from LLPanel: - background_visible = true; visible = false; } @@ -241,41 +238,39 @@ void LLFloater::initClass() } } +// defaults for floater param block pulled from widgets/floater.xml +static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater"); + LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) - : LLPanel(), - mDragHandle(NULL), - mTitle(p.title), - mShortTitle(p.short_title), - mSingleInstance(p.single_instance), - mKey(key), - mAutoTile(p.auto_tile), - mCanTearOff(p.can_tear_off), - mCanMinimize(p.can_minimize), - mCanClose(p.can_close), - mDragOnLeft(p.can_drag_on_left), - mResizable(p.can_resize), - mMinWidth(p.min_width), - mMinHeight(p.min_height), - mMinimized(FALSE), - mForeground(FALSE), - mFirstLook(TRUE), - mEditing(FALSE), - mButtonScale(1.0f), - mAutoFocus(TRUE), // automatically take focus when opened - mCanDock(false), - mDocked(false), - mHasBeenDraggedWhileMinimized(FALSE), - mPreviousMinimizedBottom(0), - mPreviousMinimizedLeft(0), - mNotificationContext(NULL) -{ - static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor"); - static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor"); - +: LLPanel(), + mDragHandle(NULL), + mTitle(p.title), + mShortTitle(p.short_title), + mSingleInstance(p.single_instance), + mKey(key), + mAutoTile(p.auto_tile), + mCanTearOff(p.can_tear_off), + mCanMinimize(p.can_minimize), + mCanClose(p.can_close), + mDragOnLeft(p.can_drag_on_left), + mResizable(p.can_resize), + mMinWidth(p.min_width), + mMinHeight(p.min_height), + mMinimized(FALSE), + mForeground(FALSE), + mFirstLook(TRUE), + mEditing(FALSE), + mButtonScale(1.0f), + mAutoFocus(TRUE), // automatically take focus when opened + mCanDock(false), + mDocked(false), + mHasBeenDraggedWhileMinimized(FALSE), + mPreviousMinimizedBottom(0), + mPreviousMinimizedLeft(0), + mNotificationContext(NULL) +{ mHandle.bind(this); mNotificationContext = new LLFloaterNotificationContext(getHandle()); - mBgColorAlpha = default_background_color; - mBgColorOpaque = focus_background_color; // Clicks stop here. setMouseOpaque(TRUE); @@ -779,11 +774,6 @@ void LLFloater::applyRectControl() void LLFloater::applyTitle() { - if (gNoRender) - { - return; - } - if (!mDragHandle) { return; @@ -1546,6 +1536,7 @@ void LLFloater::onClickClose( LLFloater* self ) // virtual void LLFloater::draw() { + F32 alpha = getDrawContext().mAlpha; // draw background if( isBackgroundVisible() ) { @@ -1565,27 +1556,29 @@ void LLFloater::draw() shadow_color.mV[VALPHA] *= 0.5f; } gl_drop_shadow(left, top, right, bottom, - shadow_color, + shadow_color % alpha, llround(shadow_offset)); // No transparent windows in simple UI if (isBackgroundOpaque()) { - gl_rect_2d( left, top, right, bottom, mBgColorOpaque ); + gl_rect_2d( left, top, right, bottom, getBackgroundColor() % alpha ); } else { - gl_rect_2d( left, top, right, bottom, mBgColorAlpha ); + gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha ); } - if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty()) + if(hasFocus() + && !getIsChrome() + && !getCurrentTitle().empty()) { static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor"); // draw highlight on title bar to indicate focus. RDW const LLFontGL* font = LLFontGL::getFontSansSerif(); LLRect r = getRect(); gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, - titlebar_focus_color, 0, TRUE); + titlebar_focus_color % alpha, 0, TRUE); } } @@ -1643,7 +1636,7 @@ void LLFloater::draw() static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor"); LLUI::setLineWidth(1.5f); LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color; - gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor, -LLPANEL_BORDER_WIDTH, FALSE); + gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE); LLUI::setLineWidth(1.f); } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index ee066317e0..513f6a6918 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -373,9 +373,6 @@ private: S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; - LLColor4 mBgColorAlpha; - LLColor4 mBgColorOpaque; - LLFloaterNotificationContext* mNotificationContext; LLRootHandle<LLFloater> mHandle; }; diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 673c742e7a..0330a2b374 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -74,20 +74,12 @@ void LLIconCtrl::draw() { if( mImagep.notNull() ) { - mImagep->draw(getLocalRect(), mColor.get() ); + mImagep->draw(getLocalRect(), mColor.get() % getDrawContext().mAlpha ); } LLUICtrl::draw(); } -// virtual -void LLIconCtrl::setAlpha(F32 alpha) -{ - LLColor4 temp = mColor.get(); - temp.setAlpha(alpha); - mColor.set(temp); -} - // virtual // value might be a string or a UUID void LLIconCtrl::setValue(const LLSD& value ) diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index aceb70b9d5..ff25b0d53e 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -71,8 +71,6 @@ public: std::string getImageName() const; - /*virtual*/ void setAlpha(F32 alpha); - void setColor(const LLColor4& color) { mColor = color; } private: diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index f98edec1f3..2d582c0568 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -35,6 +35,7 @@ #include "linden_common.h" #include "lllayoutstack.h" +#include "lllocalcliprect.h" #include "llresizebar.h" #include "llcriticaldamp.h" @@ -297,6 +298,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o FALSE, output_child); LLPanel::Params p; + p.mouse_opaque(false); LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p); LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child); if (new_child) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 5435b9ffbf..ede67ad17d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -97,6 +97,7 @@ LLLineEditor::Params::Params() background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), handle_edit_keys_directly("handle_edit_keys_directly", false), + revert_on_esc("revert_on_esc", true), commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), cursor_color("cursor_color"), @@ -130,7 +131,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mMinHPixels(0), // computed in updateTextPadding() below mMaxHPixels(0), // computed in updateTextPadding() below mCommitOnFocusLost( p.commit_on_focus_lost ), - mRevertOnEsc( TRUE ), + mRevertOnEsc( p.revert_on_esc ), mKeystrokeCallback( p.keystroke_callback() ), mIsSelecting( FALSE ), mSelectionStart( 0 ), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 0986ce5a87..a024f48cc6 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -90,6 +90,7 @@ public: Optional<bool> select_on_focus, handle_edit_keys_directly, + revert_on_esc, commit_on_focus_lost, ignore_tab; diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp new file mode 100644 index 0000000000..058b6ae178 --- /dev/null +++ b/indra/llui/lllocalcliprect.cpp @@ -0,0 +1,143 @@ +/** +* @file lllocalcliprect.cpp +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#include "linden_common.h" + +#include "lllocalcliprect.h" + +#include "llfontgl.h" +#include "llgl.h" +#include "llui.h" + +#include <stack> + +//--------------------------------------------------------------------------- +// LLScreenClipRect +// implementation class in screen space +//--------------------------------------------------------------------------- +class LLScreenClipRect +{ +public: + LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); + virtual ~LLScreenClipRect(); + +private: + static void pushClipRect(const LLRect& rect); + static void popClipRect(); + static void updateScissorRegion(); + +private: + LLGLState mScissorState; + BOOL mEnabled; + + static std::stack<LLRect> sClipRectStack; +}; + +/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack; + + +LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) +: mScissorState(GL_SCISSOR_TEST), + mEnabled(enabled) +{ + if (mEnabled) + { + pushClipRect(rect); + } + mScissorState.setEnabled(!sClipRectStack.empty()); + updateScissorRegion(); +} + +LLScreenClipRect::~LLScreenClipRect() +{ + if (mEnabled) + { + popClipRect(); + } + updateScissorRegion(); +} + +//static +void LLScreenClipRect::pushClipRect(const LLRect& rect) +{ + LLRect combined_clip_rect = rect; + if (!sClipRectStack.empty()) + { + LLRect top = sClipRectStack.top(); + combined_clip_rect.intersectWith(top); + + if(combined_clip_rect.isEmpty()) + { + // avoid artifacts where zero area rects show up as lines + combined_clip_rect = LLRect::null; + } + } + sClipRectStack.push(combined_clip_rect); +} + +//static +void LLScreenClipRect::popClipRect() +{ + sClipRectStack.pop(); +} + +//static +void LLScreenClipRect::updateScissorRegion() +{ + if (sClipRectStack.empty()) return; + + LLRect rect = sClipRectStack.top(); + stop_glerror(); + S32 x,y,w,h; + x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); + y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); + w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; + h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; + glScissor( x,y,w,h ); + stop_glerror(); +} + +//--------------------------------------------------------------------------- +// LLLocalClipRect +//--------------------------------------------------------------------------- +LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */) +{ + LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX, + rect.mTop + LLFontGL::sCurOrigin.mY, + rect.mRight + LLFontGL::sCurOrigin.mX, + rect.mBottom + LLFontGL::sCurOrigin.mY); + mScreenClipRect = new LLScreenClipRect(screen, enabled); +} + +LLLocalClipRect::~LLLocalClipRect() +{ + delete mScreenClipRect; + mScreenClipRect = NULL; +} diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h new file mode 100644 index 0000000000..cd0c55ca72 --- /dev/null +++ b/indra/llui/lllocalcliprect.h @@ -0,0 +1,53 @@ +/** +* @file lllocalcliprect.h +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLLOCALCLIPRECT_H +#define LLLOCALCLIPRECT_H + +#include "llrect.h" // can't forward declare, it's templated + +// Clip rendering to a specific rectangle using GL scissor +// Just create one of these on the stack: +// { +// LLLocalClipRect(rect); +// draw(); +// } +class LLLocalClipRect +{ +public: + LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); + ~LLLocalClipRect(); + +private: + // implementation class + class LLScreenClipRect* mScreenClipRect; +}; + +#endif diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index d6dfe6c198..e0bb6bd5d3 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2929,7 +2929,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) // If the mouse doesn't move, the menu will stay open ala the Mac. // See also LLContextMenu::show() S32 mouse_x, mouse_y; - LLUI::getCursorPositionLocal(menu->getParent(), &mouse_x, &mouse_y); + LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y); LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y); const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); @@ -3371,6 +3371,34 @@ BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask ) return handled; } +BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + BOOL handled = false; + LLMenuGL* const pMenu = dynamic_cast<LLMenuGL*>(getVisibleMenu()); + + if (pMenu) + { + //handle ESCAPE and RETURN key + handled = LLPanel::handleKey(key, mask, called_from_parent); + if (!handled) + { + if (pMenu->getHighlightedItem()) + { + handled = pMenu->handleKey(key, mask, TRUE); + } + else + { + //highlight first enabled one + pMenu->highlightNextItem(NULL); + handled = true; + } + } + } + + return handled; + +} + void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) @@ -3380,17 +3408,17 @@ void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent) LLView::reshape(width, height, called_from_parent); } -BOOL LLMenuHolderGL::hasVisibleMenu() const +LLView* const LLMenuHolderGL::getVisibleMenu() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { LLView* viewp = *child_it; if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL) { - return TRUE; + return viewp; } } - return FALSE; + return NULL; } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 0bf6301f93..8309fedf7f 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -772,8 +772,10 @@ public: // Close context menus on right mouse up not handled by menus. /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual const LLRect getMenuRect() const { return getLocalRect(); } - virtual BOOL hasVisibleMenu() const; + LLView*const getVisibleMenu() const; + virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} static void setActivatedItem(LLMenuItemGL* item); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index c81be6086a..26136e0a23 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -91,8 +91,8 @@ LLPanel::Params::Params() LLPanel::LLPanel(const LLPanel::Params& p) : LLUICtrl(p), - mBgColorAlpha(p.bg_alpha_color().get()), - mBgColorOpaque(p.bg_opaque_color().get()), + mBgColorAlpha(p.bg_alpha_color()), + mBgColorOpaque(p.bg_opaque_color()), mBgVisible(p.background_visible), mBgOpaque(p.background_opaque), mDefaultBtn(NULL), @@ -100,7 +100,7 @@ LLPanel::LLPanel(const LLPanel::Params& p) mLabel(p.label), mCommitCallbackRegistrar(false), mEnableCallbackRegistrar(false), - mXMLFilename("") + mXMLFilename(p.filename) { setIsChrome(FALSE); @@ -171,6 +171,8 @@ void LLPanel::setCtrlsEnabled( BOOL b ) void LLPanel::draw() { + F32 alpha = getDrawContext().mAlpha; + // draw background if( mBgVisible ) { @@ -182,11 +184,11 @@ void LLPanel::draw() if (mBgOpaque ) { - gl_rect_2d( left, top, right, bottom, mBgColorOpaque ); + gl_rect_2d( left, top, right, bottom, mBgColorOpaque.get() % alpha); } else { - gl_rect_2d( left, top, right, bottom, mBgColorAlpha ); + gl_rect_2d( left, top, right, bottom, mBgColorAlpha.get() % alpha); } } @@ -195,12 +197,6 @@ void LLPanel::draw() LLView::draw(); } -/*virtual*/ -void LLPanel::setAlpha(F32 alpha) -{ - mBgColorOpaque.setAlpha(alpha); -} - void LLPanel::updateDefaultBtn() { if( mDefaultBtn) @@ -403,6 +399,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p) setVisible(p.visible); setEnabled(p.enabled); + setSoundFlags(p.sound_flags); + // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible LLUICtrl::initFromParams(p); @@ -709,14 +707,6 @@ void LLPanel::childSetColor(const std::string& id, const LLColor4& color) child->setColor(color); } } -void LLPanel::childSetAlpha(const std::string& id, F32 alpha) -{ - LLUICtrl* child = getChild<LLUICtrl>(id, true); - if (child) - { - child->setAlpha(alpha); - } -} LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const { diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 3f1d1fdc5d..81b5b68f05 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -114,8 +114,6 @@ public: // From LLFocusableElement /*virtual*/ void setFocus( BOOL b ); - virtual void setAlpha(F32 alpha); - // New virtuals virtual void refresh(); // called in setFocus() @@ -190,7 +188,6 @@ public: void childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb ); void childSetColor(const std::string& id, const LLColor4& color); - void childSetAlpha(const std::string& id, F32 alpha); LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const; LLCtrlListInterface* childGetListInterface(const std::string& id) const; @@ -236,6 +233,7 @@ public: virtual void onOpen(const LLSD& key) {} void setXMLFilename(std::string filename) { mXMLFilename = filename; }; + std::string getXMLFilename() { return mXMLFilename; }; protected: // Override to set not found list @@ -247,13 +245,8 @@ protected: commit_signal_t mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD() private: - // Unified error reporting for the child* functions - typedef std::set<std::string> expected_members_list_t; - mutable expected_members_list_t mExpectedMembers; - mutable expected_members_list_t mNewExpectedMembers; - - LLColor4 mBgColorAlpha; - LLColor4 mBgColorOpaque; + LLUIColor mBgColorAlpha; + LLUIColor mBgColorOpaque; BOOL mBgVisible; BOOL mBgOpaque; LLViewBorder* mBorder; diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index b46915b379..172c4a9c65 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -484,7 +484,7 @@ void LLScrollbar::draw() S32 local_mouse_x; S32 local_mouse_y; - LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); + LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); if (hovered) diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 556ff80991..30a042cff1 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -37,6 +37,7 @@ #include "llrender.h" #include "llcontainerview.h" +#include "lllocalcliprect.h" // #include "llfolderview.h" #include "llscrollingpanellist.h" #include "llscrollbar.h" diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 36a3b007b6..483106e857 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -44,6 +44,8 @@ #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llfocusmgr.h" +#include "llgl.h" // LLGLSUIDefault() +#include "lllocalcliprect.h" //#include "llrender.h" #include "llresmgr.h" #include "llscrollbar.h" @@ -60,6 +62,7 @@ #include "llcachename.h" #include "llmenugl.h" #include "llurlaction.h" +#include "lltooltip.h" #include <boost/bind.hpp> @@ -1522,7 +1525,7 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) return handled; } -BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { S32 column_index = getColumnIndexFromOffset(x); LLScrollListColumn* columnp = getColumn(column_index); @@ -1545,8 +1548,11 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti LLRect cell_rect; cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight); // Convert rect local to screen coordinates - localRectToScreen(cell_rect, sticky_rect_screen); - msg = hit_cell->getValue().asString(); + LLRect sticky_rect; + localRectToScreen(cell_rect, &sticky_rect); + LLToolTipMgr::instance().show(LLToolTipParams() + .message(hit_cell->getValue().asString()) + .sticky_rect(sticky_rect)); } handled = TRUE; } @@ -1555,8 +1561,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti LLScrollColumnHeader* headerp = columnp->mHeader; if (headerp && !handled) { - headerp->handleToolTip(x, y, msg, sticky_rect_screen); - handled = !msg.empty(); + handled = headerp->handleToolTip(x, y, msg, sticky_rect_screen); } return handled; diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 5c18f85160..49a49499ef 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -286,7 +286,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, std::string& msg, LLRect& sticky_rect); /*virtual*/ void setEnabled(BOOL enabled); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void onFocusReceived(); @@ -350,7 +350,7 @@ public: void sortOnce(S32 column, BOOL ascending); // manually call this whenever editing list items in place to flag need for resorting - void setNeedsSort() { mSorted = false; } + void setNeedsSort(bool val = true) { mSorted = !val; } void dirtyColumns(); // some operation has potentially affected column layout or ordering protected: diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 1b0f3c9885..4bb45a3065 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -90,15 +90,7 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool mNameStack.clear(); setParseSilently(silent); - // must have named elements at top level to submit for parsing - if (sd.isMap()) - { - readSDValues(sd, block); - } - else - { - parserWarning("Top level map required for LLSD->Block conversion"); - } + readSDValues(sd, block); } void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block) diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 1c394a71dd..07b6895378 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -239,6 +239,8 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask) void LLSlider::draw() { + F32 alpha = getDrawContext().mAlpha; + // since thumb image might still be decoding, need thumb to accomodate image size updateThumbRect(); @@ -253,14 +255,14 @@ void LLSlider::draw() getRect().getWidth() - mThumbImage->getWidth() / 2, getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) ); LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom); - mTrackImage->draw(track_rect); - mTrackHighlightImage->draw(highlight_rect); + mTrackImage->draw(track_rect, LLColor4::white % alpha); + mTrackHighlightImage->draw(highlight_rect, LLColor4::white % alpha); // Thumb if (hasFocus()) { // Draw focus highlighting. - mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); + mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth()); } if( hasMouseCapture() ) // currently clicking on slider @@ -268,25 +270,25 @@ void LLSlider::draw() // Show ghost where thumb was before dragging began. if (mThumbImage.notNull()) { - mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); + mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % (0.3f * alpha)); } if (mThumbImagePressed.notNull()) { - mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor); + mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor % alpha); } } else if (!isInEnabledChain()) { if (mThumbImageDisabled.notNull()) { - mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor); + mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor % alpha); } } else { if (mThumbImage.notNull()) { - mThumbImage->draw(mThumbRect, mThumbCenterColor); + mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha); } } diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index e379954b4f..cabd0be522 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -31,9 +31,12 @@ */ #include "linden_common.h" + #include "lltabcontainer.h" + #include "llfocusmgr.h" #include "llbutton.h" +#include "lllocalcliprect.h" #include "llrect.h" #include "llresizehandle.h" #include "lltextbox.h" @@ -590,7 +593,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) } // virtual -BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect ) +BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect ) { static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0); BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect ); @@ -731,7 +734,7 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag { BOOL has_scroll_arrows = (getMaxScrollPos() > 0); - if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME ) + if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME ) { if (has_scroll_arrows) { diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index ebe76af966..89a0346896 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -99,7 +99,7 @@ public: /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect ); + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect ); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 038ea2188f..cb60b4fe36 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -38,6 +38,7 @@ #include "llview.h" #include "llwindow.h" #include "llmenugl.h" +#include "lltooltip.h" #include "lluictrl.h" #include "llurlaction.h" #include "llurlregistry.h" @@ -402,18 +403,23 @@ BOOL LLTextBase::handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y) return FALSE; } -BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +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( msg ) && view) + 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; + 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; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 27b88761a8..82b9f6a43f 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -90,7 +90,7 @@ protected: 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); + BOOL handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); // pure virtuals that have to be implemented by any subclasses virtual S32 getLineCount() const = 0; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 30bf182deb..810626268f 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -52,7 +52,6 @@ LLTextBox::Params::Params() drop_shadow_visible("drop_shadow_visible"), disabled_color("disabled_color"), background_color("background_color"), - border_color("border_color"), v_pad("v_pad", 0), h_pad("h_pad", 0), line_spacing("line_spacing", 0), @@ -75,7 +74,6 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p) mTextColor(p.text_color()), mDisabledColor(p.disabled_color()), mBackgroundColor(p.background_color()), - mBorderColor(p.border_color()), mHAlign(p.font_halign), mLineSpacing(p.line_spacing), mDidWordWrap(FALSE) @@ -161,7 +159,7 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) return LLView::handleHover(x,y,mask); } -BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen); } @@ -387,6 +385,8 @@ BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text void LLTextBox::draw() { + F32 alpha = getDrawContext().mAlpha; + if (mBorderVisible) { gl_rect_2d_offset_local(getLocalRect(), 2, FALSE); @@ -397,13 +397,13 @@ void LLTextBox::draw() static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0); gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, drop_shadow_tooltip); + color_drop_shadow % alpha, drop_shadow_tooltip); } if (mBackgroundVisible) { LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - gl_rect_2d( r, mBackgroundColor.get() ); + gl_rect_2d( r, mBackgroundColor.get() % alpha ); } S32 text_x = 0; @@ -453,6 +453,7 @@ void LLTextBox::reshape(S32 width, S32 height, BOOL 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) @@ -461,7 +462,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& c else if( mLineLengthList.empty() ) { // simple case of 1 line of text in one style - mDefaultFont->render(text, 0, (F32)x, (F32)y, color, + mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha, mHAlign, mVAlign, 0, mShadowType, @@ -475,7 +476,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& c iter != mLineLengthList.end(); ++iter) { S32 line_length = *iter; - mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color, + mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha, mHAlign, mVAlign, 0, mShadowType, @@ -491,6 +492,9 @@ void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& c void LLTextBox::reshapeToFitText() { + // wrap remaining lines that did not fit on call to setWrappedText() + setLineLengths(); + S32 width = getTextPixelWidth(); S32 height = getTextPixelHeight(); reshape( width + 2 * mHPad, height + 2 * mVPad ); @@ -665,6 +669,8 @@ bool LLTextBox::isClickable() const 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) { @@ -729,6 +735,7 @@ void LLTextBox::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text) { color = mDisabledColor.get(); } + color = color % alpha; // render a single line worth for this segment mDefaultFont->render(text, seg_start, text_x, text_y, color, diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 940b820004..291d1dc517 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -66,8 +66,7 @@ public: Optional<LLUIColor> text_color, disabled_color, - background_color, - border_color; + background_color; Optional<S32> v_pad, h_pad, @@ -90,12 +89,11 @@ public: 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); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); void setColor( const LLColor4& c ) { mTextColor = c; } void setDisabledColor( const LLColor4& c) { mDisabledColor = c; } void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; } - void setBorderColor( const LLColor4& c) { mBorderColor = c; } void setText( const LLStringExplicit& text ); void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.f); // -1 means use existing control width diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 51c259ff53..983777b747 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -38,6 +38,8 @@ #include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR #include "llfontgl.h" +#include "llgl.h" // LLGLSUIDefault() +#include "lllocalcliprect.h" #include "llrender.h" #include "llui.h" #include "lluictrlfactory.h" @@ -60,6 +62,7 @@ #include "llscrollcontainer.h" #include "llpanel.h" #include "llurlregistry.h" +#include "lltooltip.h" #include <queue> #include "llcombobox.h" @@ -1341,18 +1344,11 @@ void LLTextEditor::selectAll() } -BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { - for ( child_list_const_iter_t child_it = getChildList()->begin(); - child_it != getChildList()->end(); ++child_it) + if (childrenHandleToolTip(x, y, msg, sticky_rect_screen)) { - LLView* viewp = *child_it; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) ) - { - return TRUE; - } + return TRUE; } return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen); @@ -3193,7 +3189,7 @@ void LLTextEditor::draw() mDocumentPanel->setBackgroundColor(bg_color); - drawChildren(); + LLView::draw(); drawBackground(); //overlays scrolling panel bg drawLineNumbers(); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index d537751130..68b8f2c3b1 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -151,7 +151,7 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask ); virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp new file mode 100644 index 0000000000..5c017dabd7 --- /dev/null +++ b/indra/llui/lltooltip.cpp @@ -0,0 +1,445 @@ +/** + * @file lltooltip.cpp + * @brief LLToolTipMgr class implementation and related classes + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// self include +#include "lltooltip.h" + +// Library includes +#include "llpanel.h" +#include "lltextbox.h" +#include "lliconctrl.h" +#include "llui.h" // positionViewNearMouse() +#include "llwindow.h" + +// +// Constants +// +const F32 DELAY_BEFORE_SHOW_TIP = 0.35f; + +// +// Local globals +// + +LLToolTipView *gToolTipView = NULL; + +// +// Member functions +// + +LLToolTipView::LLToolTipView(const LLToolTipView::Params& p) +: LLView(p) +{ +} + +void LLToolTipView::draw() +{ + if (LLUI::getWindow()->isCursorHidden() ) + { + LLToolTipMgr::instance().hideToolTips(); + } + + // do the usual thing + LLView::draw(); +} + +BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask) +{ + static S32 last_x = x; + static S32 last_y = y; + + LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance(); + + // hide existing tooltips when mouse moves out of sticky rect + if (tooltip_mgr.toolTipVisible() + && !tooltip_mgr.getStickyRect().pointInRect(x, y)) + { + tooltip_mgr.hideToolTips(); + } + + // allow new tooltips whenever mouse moves + if (x != last_x && y != last_y) + { + tooltip_mgr.enableToolTips(); + } + + last_x = x; + last_y = y; + return LLView::handleHover(x, y, mask); +} + +BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask) +{ + LLToolTipMgr::instance().hideToolTips(); + return LLView::handleMouseDown(x, y, mask); +} + +BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask) +{ + LLToolTipMgr::instance().hideToolTips(); + return LLView::handleMiddleMouseDown(x, y, mask); +} + +BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + LLToolTipMgr::instance().hideToolTips(); + return LLView::handleRightMouseDown(x, y, mask); +} + + +BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks ) +{ + LLToolTipMgr::instance().hideToolTips(); + return FALSE; +} + +void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLToolTipMgr::instance().hideToolTips(); +} + + +void LLToolTipView::drawStickyRect() +{ + gl_rect_2d(LLToolTipMgr::instance().getStickyRect(), LLColor4::white, false); +} +// +// LLToolTip +// +class LLToolTip : public LLPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + { + Mandatory<F32> visible_time; + + Optional<LLToolTipParams::click_callback_t> click_callback; + Optional<LLUIImage*> image; + + Params() + { + //use_bounding_rect = true; + } + }; + /*virtual*/ void draw(); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + + /*virtual*/ void setValue(const LLSD& value); + /*virtual*/ void setVisible(BOOL visible); + + bool isFading() { return mFadeTimer.getStarted(); } + + LLToolTip(const Params& p); + +private: + LLTextBox* mTextBox; + LLFrameTimer mFadeTimer; + F32 mVisibleTime; + bool mHasClickCallback; +}; + +static LLDefaultChildRegistry::Register<LLToolTip> r("tool_tip"); + +const S32 TOOLTIP_PADDING = 4; + +LLToolTip::LLToolTip(const LLToolTip::Params& p) +: LLPanel(p), + mVisibleTime(p.visible_time), + mHasClickCallback(p.click_callback.isProvided()) +{ + LLTextBox::Params params; + params.text = "tip_text"; + params.name = params.text; + // bake textbox padding into initial rect + params.rect = LLRect (TOOLTIP_PADDING, TOOLTIP_PADDING + 1, TOOLTIP_PADDING + 1, TOOLTIP_PADDING); + params.follows.flags = FOLLOWS_ALL; + params.h_pad = 4; + params.v_pad = 2; + params.mouse_opaque = false; + params.text_color = LLUIColorTable::instance().getColor( "ToolTipTextColor" ); + params.bg_visible = false; + params.font.style = "NORMAL"; + //params.border_drop_shadow_visible = true; + mTextBox = LLUICtrlFactory::create<LLTextBox> (params); + addChild(mTextBox); + + if (p.image.isProvided()) + { + LLIconCtrl::Params icon_params; + icon_params.name = "tooltip_icon"; + LLRect icon_rect; + const S32 TOOLTIP_ICON_SIZE = 18; + icon_rect.setOriginAndSize(TOOLTIP_PADDING, TOOLTIP_PADDING, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); + icon_params.rect = icon_rect; + icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; + icon_params.image = p.image; + icon_params.mouse_opaque = false; + addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params)); + + // move text over to fit image in + mTextBox->translate(TOOLTIP_ICON_SIZE,0); + } + + if (p.click_callback.isProvided()) + { + setMouseUpCallback(boost::bind(p.click_callback())); + } +} + +void LLToolTip::setValue(const LLSD& value) +{ + mTextBox->setWrappedText(value.asString()); + mTextBox->reshapeToFitText(); + + // reshape tooltip panel to fit text box + LLRect tooltip_rect = calcBoundingRect(); + tooltip_rect.mTop += TOOLTIP_PADDING; + tooltip_rect.mRight += TOOLTIP_PADDING; + tooltip_rect.mBottom = 0; + tooltip_rect.mLeft = 0; + + setRect(tooltip_rect); +} + +void LLToolTip::setVisible(BOOL visible) +{ + // fade out tooltip over time + if (!visible) + { + // don't actually change mVisible state, start fade out transition instead + if (!mFadeTimer.getStarted()) + { + mFadeTimer.start(); + } + } + else + { + mFadeTimer.stop(); + LLPanel::setVisible(TRUE); + } +} + +BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask) +{ + LLPanel::handleHover(x, y, mask); + if (mHasClickCallback) + { + getWindow()->setCursor(UI_CURSOR_HAND); + } + return TRUE; +} + +void LLToolTip::draw() +{ + F32 alpha = 1.f; + + if (LLUI::getMouseIdleTime() > mVisibleTime) + { + LLToolTipMgr::instance().hideToolTips(); + } + + if (mFadeTimer.getStarted()) + { + F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime"); + alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f); + if (alpha == 0.f) + { + // finished fading out, so hide ourselves + mFadeTimer.stop(); + LLPanel::setVisible(false); + } + } + + // draw tooltip contents with appropriate alpha + { + LLViewDrawContext context(alpha); + LLPanel::draw(); + } +} + + + +// +// LLToolTipMgr +// +LLToolTipParams::LLToolTipParams() +: pos("pos"), + message("message"), + delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )), + visible_time("visible_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTime" )), + sticky_rect("sticky_rect"), + width("width", 200), + image("image") +{} + +LLToolTipMgr::LLToolTipMgr() +: mToolTip(NULL) +{ +} + +LLToolTip* LLToolTipMgr::createToolTip(const LLToolTipParams& params) +{ + S32 mouse_x; + S32 mouse_y; + LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y); + + + LLToolTip::Params tooltip_params; + tooltip_params.name = "tooltip"; + tooltip_params.mouse_opaque = true; + tooltip_params.rect = LLRect (0, 1, 1, 0); + tooltip_params.bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" ); + tooltip_params.background_visible = true; + tooltip_params.visible_time = params.visible_time; + if (params.image.isProvided()) + { + tooltip_params.image = params.image; + } + if (params.click_callback.isProvided()) + { + tooltip_params.click_callback = params.click_callback; + } + + LLToolTip* tooltip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); + + // make tooltip fixed width and tall enough to fit text + tooltip->reshape(params.width, 2000); + tooltip->setValue(params.message()); + gToolTipView->addChild(tooltip); + + if (params.pos.isProvided()) + { + // try to spawn at requested position + LLUI::positionViewNearMouse(tooltip, params.pos.x, params.pos.y); + } + else + { + // just spawn at mouse location + LLUI::positionViewNearMouse(tooltip); + } + + //...update "sticky" rect and tooltip position + if (params.sticky_rect.isProvided()) + { + mToolTipStickyRect = params.sticky_rect; + } + else + { + // otherwise just use one pixel rect around mouse cursor + mToolTipStickyRect.setOriginAndSize(mouse_x, mouse_y, 1, 1); + } + + if (params.click_callback.isProvided()) + { + // keep tooltip up when we mouse over it + mToolTipStickyRect.unionWith(tooltip->getRect()); + } + + return tooltip; +} + + +void LLToolTipMgr::show(const std::string& msg) +{ + show(LLToolTipParams().message(msg)); +} + +void LLToolTipMgr::show(const LLToolTipParams& params) +{ + if (!params.validateBlock()) + { + llwarns << "Could not display tooltip!" << llendl; + return; + } + + bool tooltip_shown = mToolTip + && mToolTip->getVisible() + && !mToolTip->isFading(); + + // if tooltip contents change, hide existing tooltip + if (tooltip_shown && mLastToolTipMessage != params.message()) + { + hideToolTips(); + } + + if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc. + && LLUI::getMouseIdleTime() > params.delay_time // the mouse has been still long enough + && !tooltip_shown) // tooltip not visible + { + // create new tooltip at mouse cursor position + delete mToolTip; + mToolTip = createToolTip(params); + + // remember this tooltip so we know when it changes + mLastToolTipMessage = params.message(); + } +} + +// allow new tooltips to be created, e.g. after mouse has moved +void LLToolTipMgr::enableToolTips() +{ + mToolTipsBlocked = false; +} + +void LLToolTipMgr::hideToolTips() +{ + mToolTipsBlocked = true; + if (mToolTip) + { + mToolTip->setVisible(FALSE); + } +} + +bool LLToolTipMgr::toolTipVisible() +{ + return mToolTip ? mToolTip->getVisible() : false; +} + +LLRect LLToolTipMgr::getToolTipRect() +{ + if (mToolTip && mToolTip->getVisible()) + { + return mToolTip->getRect(); + } + return LLRect(); +} + + +LLRect LLToolTipMgr::getStickyRect() +{ + if (!mToolTip) return LLRect(); + + return mToolTip->isInVisibleChain() ? mToolTipStickyRect : LLRect(); +} + +// EOF diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h new file mode 100644 index 0000000000..fb7f942099 --- /dev/null +++ b/indra/llui/lltooltip.h @@ -0,0 +1,127 @@ +/** + * @file lltooltip.h + * @brief LLToolTipMgr class definition and related classes + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTOOLTIP_H +#define LL_LLTOOLTIP_H + +// Library includes +#include "llsingleton.h" +#include "llinitparam.h" +#include "llview.h" + +// +// Classes +// +class LLToolTipView : public LLView +{ +public: + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + Params() + { + mouse_opaque = false; + } + }; + LLToolTipView(const LLToolTipView::Params&); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + + void drawStickyRect(); + + /*virtual*/ void draw(); +}; + +struct LLToolTipPosParams : public LLInitParam::Block<LLToolTipPosParams> +{ + Mandatory<S32> x, + y; + LLToolTipPosParams() + : x("x"), + y("y") + {} +}; + +struct LLToolTipParams : public LLInitParam::Block<LLToolTipParams> +{ + typedef boost::function<void(void)> click_callback_t; + + Mandatory<std::string> message; + + Optional<LLToolTipPosParams> pos; + Optional<F32> delay_time, + visible_time; + Optional<LLRect> sticky_rect; + Optional<S32> width; + Optional<LLUIImage*> image; + + Optional<click_callback_t> click_callback; + + LLToolTipParams(); + LLToolTipParams(const std::string& message); +}; + +class LLToolTipMgr : public LLSingleton<LLToolTipMgr> +{ + LOG_CLASS(LLToolTipMgr); +public: + LLToolTipMgr(); + void show(const LLToolTipParams& params); + void show(const std::string& message); + + void enableToolTips(); + void hideToolTips(); + bool toolTipVisible(); + LLRect getToolTipRect(); + + LLRect getStickyRect(); + +private: + class LLToolTip* createToolTip(const LLToolTipParams& params); + + bool mToolTipsBlocked; + class LLToolTip* mToolTip; + std::string mLastToolTipMessage; + LLRect mToolTipStickyRect; +}; + +// +// Globals +// + +extern LLToolTipView *gToolTipView; + +#endif diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 1d62ed93f9..950eaf2ea7 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -44,6 +44,7 @@ #include "llrect.h" #include "lldir.h" #include "llfontgl.h" +#include "llgl.h" // Project includes #include "llcontrol.h" @@ -80,10 +81,9 @@ std::list<std::string> gUntranslated; /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL; /*static*/ LLView* LLUI::sRootView = NULL; -/*static*/ BOOL LLUI::sShowXUINames = FALSE; -/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack; /*static*/ std::vector<std::string> LLUI::sXUIPaths; +/*static*/ LLFrameTimer LLUI::sMouseIdleTimer; // register filtereditor here static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor"); @@ -1561,12 +1561,6 @@ void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3 gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); } -bool handleShowXUINamesChanged(const LLSD& newvalue) -{ - LLUI::sShowXUINames = newvalue.asBoolean(); - return true; -} - void LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback, @@ -1588,10 +1582,6 @@ void LLUI::initClass(const settings_map_t& settings, sWindow = NULL; // set later in startup LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow"); - static LLUICachedControl<bool> show_xui_names ("ShowXUINames", false); - LLUI::sShowXUINames = show_xui_names; - LLUI::sSettingGroups["config"]->getControl("ShowXUINames")->getSignal()->connect(boost::bind(&handleShowXUINamesChanged, _2)); - // Callbacks for associating controls with floater visibilty: LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2)); LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2)); @@ -1661,7 +1651,7 @@ void LLUI::setLineWidth(F32 width) } //static -void LLUI::setCursorPositionScreen(S32 x, S32 y) +void LLUI::setMousePositionScreen(S32 x, S32 y) { S32 screen_x, screen_y; screen_x = llround((F32)x * sGLScaleFactor.mV[VX]); @@ -1674,16 +1664,16 @@ void LLUI::setCursorPositionScreen(S32 x, S32 y) } //static -void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y) +void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y) { S32 screen_x, screen_y; viewp->localPointToScreen(x, y, &screen_x, &screen_y); - setCursorPositionScreen(screen_x, screen_y); + setMousePositionScreen(screen_x, screen_y); } //static -void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y) +void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y) { LLCoordWindow cursor_pos_window; LLView::getWindow()->getCursorPosition(&cursor_pos_window); @@ -1867,74 +1857,46 @@ LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname) return *sSettingGroups["config"]; // default group } -LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled) +//static +// spawn_x and spawn_y are top left corner of view in screen GL coordinates +void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y) { - if (mEnabled) - { - pushClipRect(rect); - } - mScissorState.setEnabled(!sClipRectStack.empty()); - updateScissorRegion(); -} + const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size + const S32 CURSOR_WIDTH = 12; -LLScreenClipRect::~LLScreenClipRect() -{ - if (mEnabled) - { - popClipRect(); - } - updateScissorRegion(); -} + LLView* parent = view->getParent(); -//static -void LLScreenClipRect::pushClipRect(const LLRect& rect) -{ - LLRect combined_clip_rect = rect; - if (!sClipRectStack.empty()) - { - LLRect top = sClipRectStack.top(); - combined_clip_rect.intersectWith(top); + S32 mouse_x; + S32 mouse_y; + LLUI::getMousePositionLocal(parent, &mouse_x, &mouse_y); - if(combined_clip_rect.isEmpty()) - { - // avoid artifacts where zero area rects show up as lines - combined_clip_rect = LLRect::null; - } + // If no spawn location provided, use mouse position + if (spawn_x == S32_MAX || spawn_y == S32_MAX) + { + spawn_x = mouse_x + CURSOR_WIDTH; + spawn_y = mouse_y - CURSOR_HEIGHT; } - sClipRectStack.push(combined_clip_rect); -} -//static -void LLScreenClipRect::popClipRect() -{ - sClipRectStack.pop(); -} + LLRect virtual_window_rect = parent->getLocalRect(); -//static -void LLScreenClipRect::updateScissorRegion() -{ - if (sClipRectStack.empty()) return; + LLRect mouse_rect; + const S32 MOUSE_CURSOR_PADDING = 5; + mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING, + mouse_y + MOUSE_CURSOR_PADDING, + CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, + CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); - LLRect rect = sClipRectStack.top(); - stop_glerror(); - S32 x,y,w,h; - x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); - y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); - w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; - h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; - glScissor( x,y,w,h ); - stop_glerror(); + S32 local_x, local_y; + view->getParent()->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y); + + // Start at spawn position (using left/top) + view->setOrigin( local_x, local_y - view->getRect().getHeight()); + // Make sure we're onscreen and not overlapping the mouse + view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE ); } -LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) -: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX, - rect.mTop + LLFontGL::sCurOrigin.mY, - rect.mRight + LLFontGL::sCurOrigin.mX, - rect.mBottom + LLFontGL::sCurOrigin.mY), - enabled) -{ -} +// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp namespace LLInitParam { @@ -2084,6 +2046,19 @@ namespace LLInitParam return rect; } + TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) + : super_t(descriptor, name, value, func, min_count, max_count), + x("x"), + y("y") + { + } + + LLCoordGL TypedParam<LLCoordGL>::getValueFromBlock() const + { + return LLCoordGL(x, y); + } + + void TypeValues<LLFontGL::HAlign>::declareValues() { declare("left", LLFontGL::LEFT); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 1f9b0b2dbc..33338f30f9 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -39,8 +39,6 @@ #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" -#include "llgl.h" // *TODO: break this dependency -#include <stack> #include "lluiimage.h" // *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional<LLUIImage*> in their paramblocks #include "llinitparam.h" #include "llregistry.h" @@ -50,6 +48,7 @@ #include "lllazyvalue.h" #include "llhandle.h" // *TODO: remove this dependency, added as a // convenience when LLHandle moved to llhandle.h +#include "llframetimer.h" // LLUIFactory #include "llsd.h" @@ -188,9 +187,9 @@ public: static LLView* getRootView() { return sRootView; } static void setRootView(LLView* view) { sRootView = view; } static std::string locateSkin(const std::string& filename); - static void setCursorPositionScreen(S32 x, S32 y); - static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y); - static void getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y); + static void setMousePositionScreen(S32 x, S32 y); + static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y); + static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y); static void setScaleFactor(const LLVector2& scale_factor); static void setLineWidth(F32 width); static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id); @@ -203,7 +202,16 @@ public: static void setHtmlHelp(LLHtmlHelp* html_help); // Returns the control group containing the control name, or the default group static LLControlGroup& getControlControlGroup (const std::string& controlname); - + static F32 getMouseIdleTime() { return sMouseIdleTimer.getElapsedTimeF32(); } + static void resetMouseIdleTimer() { sMouseIdleTimer.reset(); } + static LLWindow* getWindow() { return sWindow; } + + // Ensures view does not overlap mouse cursor, but is inside + // the view's parent rectangle. Used for tooltips, inspectors. + // Optionally override the view's default X/Y, which are relative to the + // view's parent. + static void positionViewNearMouse(LLView* view, S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX); + // // Data // @@ -211,38 +219,16 @@ public: static LLUIAudioCallback sAudioCallback; static LLVector2 sGLScaleFactor; static LLWindow* sWindow; - static BOOL sShowXUINames; static LLHtmlHelp* sHtmlHelp; static LLView* sRootView; private: static LLImageProviderInterface* sImageProvider; static std::vector<std::string> sXUIPaths; + static LLFrameTimer sMouseIdleTimer; }; -class LLScreenClipRect -{ -public: - LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); - virtual ~LLScreenClipRect(); - -private: - static void pushClipRect(const LLRect& rect); - static void popClipRect(); - static void updateScissorRegion(); - -private: - LLGLState mScissorState; - BOOL mEnabled; - - static std::stack<LLRect> sClipRectStack; -}; - -class LLLocalClipRect : public LLScreenClipRect -{ -public: - LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); -}; +// Moved LLLocalClipRect to lllocalcliprect.h // Moved all LLHandle-related code to llhandle.h @@ -406,10 +392,10 @@ namespace LLInitParam { typedef BlockValue<LLUIColor> super_t; public: - Optional<F32> red; - Optional<F32> green; - Optional<F32> blue; - Optional<F32> alpha; + Optional<F32> red, + green, + blue, + alpha; Optional<std::string> control; TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); @@ -422,9 +408,9 @@ namespace LLInitParam { typedef BlockValue<const LLFontGL*> super_t; public: - Optional<std::string> name; - Optional<std::string> size; - Optional<std::string> style; + Optional<std::string> name, + size, + style; TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); const LLFontGL* getValueFromBlock() const; @@ -447,6 +433,19 @@ namespace LLInitParam { static void declareValues(); }; + + template<> + class TypedParam<LLCoordGL> + : public BlockValue<LLCoordGL> + { + typedef BlockValue<LLCoordGL> super_t; + public: + Optional<S32> x, + y; + + TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); + LLCoordGL getValueFromBlock() const; + }; } #endif diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 1ab04054ff..28cdb1ac27 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -839,10 +839,6 @@ BOOL LLUICtrl::getTentative() const void LLUICtrl::setColor(const LLColor4& color) { } -// virtual -void LLUICtrl::setAlpha(F32 alpha) -{ } - namespace LLInitParam { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 5011adcfe9..4030230684 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -213,7 +213,6 @@ public: virtual void onTabInto(); virtual void clear(); virtual void setColor(const LLColor4& color); - virtual void setAlpha(F32 alpha); BOOL focusNextItem(BOOL text_entry_only); BOOL focusPrevItem(BOOL text_entry_only); diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 1161101f90..538e1ec492 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -200,10 +200,7 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen floaterp->initFloaterXML(root, floaterp->getParent(), output_node); - if (LLUI::sShowXUINames) - { - floaterp->setToolTip(filename); - } + floaterp->setXMLFilename(filename); floaterp->getCommitCallbackRegistrar().popScope(); floaterp->getEnableCallbackRegistrar().popScope(); @@ -276,10 +273,7 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L panelp->getCommitCallbackRegistrar().popScope(); panelp->getEnableCallbackRegistrar().popScope(); - if (LLUI::sShowXUINames) - { - panelp->setToolTip(filename); - } + panelp->setXMLFilename(filename); if (!panelp->getFactoryMap().empty()) { @@ -317,10 +311,6 @@ LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const parent = mDummyPanel; } LLView *view = (*funcp)(node, parent, output_node); - if (LLUI::sShowXUINames && view && !filename.empty()) - { - view->setToolTip(filename); - } return view; } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 55d94b325f..46510804f8 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -49,6 +49,7 @@ #include "llwindow.h" #include "v3color.h" #include "lluictrlfactory.h" +#include "lltooltip.h" // for ui edit hack #include "llbutton.h" @@ -70,6 +71,8 @@ LLView* LLView::sPreviewClickedElement = NULL; BOOL LLView::sDrawPreviewHighlights = FALSE; S32 LLView::sLastLeftXML = S32_MIN; S32 LLView::sLastBottomXML = S32_MIN; +std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack; + #if LL_DEBUG BOOL LLView::sIsDrawing = FALSE; @@ -662,86 +665,52 @@ void LLView::onMouseLeave(S32 x, S32 y, MASK mask) } -std::string LLView::getShowNamesToolTip() +LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { - LLView* view = getParent(); - std::string name; - std::string tool_tip = mName; - - while (view) + LLView* handled_view = NULL; + for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { - name = view->getName(); - - if (name == "root") break; - - if (view->getToolTip().find(".xml") != std::string::npos) + LLView* viewp = *child_it; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if(viewp->pointInView(local_x, local_y) && + viewp->getVisible() && + viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) ) { - tool_tip = view->getToolTip() + "/" + tool_tip; + if (sDebugMouseHandling) + { + sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; + } + + handled_view = viewp; break; } - else - { - tool_tip = view->getName() + "/" + tool_tip; - } - - view = view->getParent(); } - - return "/" + tool_tip; + return handled_view; } - -BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { - BOOL handled = FALSE; - - std::string tool_tip; + LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen); + BOOL handled = child_handler != NULL; - for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) + // child widgets get priority on tooltips + if (!handled && !mToolTipMsg.empty()) { - LLView* viewp = *child_it; - S32 local_x = x - viewp->mRect.mLeft; - S32 local_y = y - viewp->mRect.mBottom; - // Allow tooltips for disabled views so we can explain to the user why - // the view is disabled. JC - if( viewp->pointInView(local_x, local_y) - && viewp->getVisible() - // && viewp->getEnabled() - && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen )) - { - // child provided a tooltip, just return - if (!msg.empty()) return TRUE; - - // otherwise, one of our children ate the event so don't traverse - // siblings however, our child did not actually provide a tooltip - // so we might want to - handled = TRUE; - break; - } - } + // allow "scrubbing" over ui by showing next tooltip immediately + // if previous one was still visible + F32 timeout = LLToolTipMgr::instance().toolTipVisible() + ? 0.f + : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); + LLToolTipMgr::instance().show(LLToolTipParams() + .message(mToolTipMsg) + .sticky_rect(calcScreenRect()) + .delay_time(timeout)); - // get our own tooltip - tool_tip = mToolTipMsg.getString(); - - if (LLUI::sShowXUINames - && (tool_tip.find(".xml", 0) == std::string::npos) - && (mName.find("Drag", 0) == std::string::npos)) - { - tool_tip = getShowNamesToolTip(); + handled = TRUE; } - if(!tool_tip.empty()) - { - msg = tool_tip; - - // Convert rect local to screen coordinates - *sticky_rect_screen = calcScreenRect(); - } - // don't allow any siblings to handle this event - // even if we don't have a tooltip - if (getMouseOpaque() || - (!tool_tip.empty() && - (!LLUI::sShowXUINames || dynamic_cast<LLTextBox*>(this)))) + if( blockMouseEvent(x, y) ) { handled = TRUE; } @@ -1518,45 +1487,51 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) updateBoundingRect(); } -void LLView::updateBoundingRect() +LLRect LLView::calcBoundingRect() { - if (isDead()) return; + LLRect local_bounding_rect = LLRect::null; - if (mUseBoundingRect) + child_list_const_iter_t child_it; + for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { - LLRect local_bounding_rect = LLRect::null; - - child_list_const_iter_t child_it; - for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) + LLView* childp = *child_it; + // ignore invisible and "top" children when calculating bounding rect + // such as combobox popups + if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl()) { - LLView* childp = *child_it; - // ignore invisible and "top" children when calculating bounding rect - // such as combobox popups - if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl()) - { - continue; - } + continue; + } - LLRect child_bounding_rect = childp->getBoundingRect(); + LLRect child_bounding_rect = childp->getBoundingRect(); - if (local_bounding_rect.isEmpty()) - { - // start out with bounding rect equal to first visible child's bounding rect - local_bounding_rect = child_bounding_rect; - } - else + if (local_bounding_rect.isEmpty()) + { + // start out with bounding rect equal to first visible child's bounding rect + local_bounding_rect = child_bounding_rect; + } + else + { + // accumulate non-null children rectangles + if (!child_bounding_rect.isEmpty()) { - // accumulate non-null children rectangles - if (!child_bounding_rect.isEmpty()) - { - local_bounding_rect.unionWith(child_bounding_rect); - } + local_bounding_rect.unionWith(child_bounding_rect); } } + } + + // convert to parent-relative coordinates + local_bounding_rect.translate(mRect.mLeft, mRect.mBottom); + return local_bounding_rect; +} + + +void LLView::updateBoundingRect() +{ + if (isDead()) return; - mBoundingRect = local_bounding_rect; - // translate into parent-relative coordinates - mBoundingRect.translate(mRect.mLeft, mRect.mBottom); + if (mUseBoundingRect) + { + mBoundingRect = calcBoundingRect(); } else { @@ -1817,73 +1792,123 @@ void LLView::deleteViewByHandle(LLHandle<LLView> handle) } -// Moves the view so that it is entirely inside of constraint. -// If the view will not fit because it's too big, aligns with the top and left. -// (Why top and left? That's where the drag bars are for floaters.) -BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside ) +LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside) { - S32 delta_x = 0; - S32 delta_y = 0; + LLCoordGL delta; if (allow_partial_outside) { const S32 KEEP_ONSCREEN_PIXELS = 16; - if( getRect().mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) + if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) { - delta_x = constraint.mLeft - (getRect().mRight - KEEP_ONSCREEN_PIXELS); + delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS); } else - if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) + if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) { - delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS); + delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS); } - if( getRect().mTop > constraint.mTop ) + if( input.mTop > constraint.mTop ) { - delta_y = constraint.mTop - getRect().mTop; + delta.mY = constraint.mTop - input.mTop; } else - if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) + if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) { - delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS); + delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS); } } else { - if( getRect().mLeft < constraint.mLeft ) + if( input.mLeft < constraint.mLeft ) { - delta_x = constraint.mLeft - getRect().mLeft; + delta.mX = constraint.mLeft - input.mLeft; } else - if( getRect().mRight > constraint.mRight ) + if( input.mRight > constraint.mRight ) { - delta_x = constraint.mRight - getRect().mRight; + delta.mX = constraint.mRight - input.mRight; // compensate for left edge possible going off screen - delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() ); + delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() ); } - if( getRect().mTop > constraint.mTop ) + if( input.mTop > constraint.mTop ) { - delta_y = constraint.mTop - getRect().mTop; + delta.mY = constraint.mTop - input.mTop; } else - if( getRect().mBottom < constraint.mBottom ) + if( input.mBottom < constraint.mBottom ) { - delta_y = constraint.mBottom - getRect().mBottom; + delta.mY = constraint.mBottom - input.mBottom; // compensate for top edge possible going off screen - delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() ); + delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() ); } } - if (delta_x != 0 || delta_y != 0) + return delta; +} + +// Moves the view so that it is entirely inside of constraint. +// If the view will not fit because it's too big, aligns with the top and left. +// (Why top and left? That's where the drag bars are for floaters.) +BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside ) +{ + LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside); + + if (translation.mX != 0 || translation.mY != 0) + { + translate(translation.mX, translation.mY); + return TRUE; + } + return FALSE; +} + +// move this view into "inside" but not onto "exclude" +// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect +BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ) +{ + LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside); + + if (translation.mX != 0 || translation.mY != 0) { - translate(delta_x, delta_y); + // translate ourselves into constraint rect + translate(translation.mX, translation.mY); + + // do we overlap with exclusion area? + // keep moving in the same direction to the other side of the exclusion rect + if (exclude.overlaps(getRect())) + { + // moving right + if (translation.mX > 0) + { + translate(exclude.mRight - getRect().mLeft, 0); + } + // moving left + else if (translation.mX < 0) + { + translate(exclude.mLeft - getRect().mRight, 0); + } + + // moving up + if (translation.mY > 0) + { + translate(0, exclude.mTop - getRect().mBottom); + } + // moving down + else if (translation.mY < 0) + { + translate(0, exclude.mBottom - getRect().mTop); + } + } + return TRUE; } return FALSE; } + void LLView::centerWithin(const LLRect& bounds) { S32 left = bounds.mLeft + (bounds.getWidth() - getRect().getWidth()) / 2; @@ -2712,19 +2737,44 @@ void LLView::setupParamsForExport(Params& p, LLView* parent) convert_coords_to_top_left(p, parent); } -LLView::tree_iterator_t LLView::beginTree() +LLView::tree_iterator_t LLView::beginTreeDFS() { return tree_iterator_t(this, boost::bind(boost::mem_fn(&LLView::beginChild), _1), boost::bind(boost::mem_fn(&LLView::endChild), _1)); } -LLView::tree_iterator_t LLView::endTree() +LLView::tree_iterator_t LLView::endTreeDFS() { // an empty iterator is an "end" iterator return tree_iterator_t(); } +LLView::tree_post_iterator_t LLView::beginTreeDFSPost() +{ + return tree_post_iterator_t(this, + boost::bind(boost::mem_fn(&LLView::beginChild), _1), + boost::bind(boost::mem_fn(&LLView::endChild), _1)); +} + +LLView::tree_post_iterator_t LLView::endTreeDFSPost() +{ + // an empty iterator is an "end" iterator + return tree_post_iterator_t(); +} + + +LLView::root_to_view_iterator_t LLView::beginRootToView() +{ + return root_to_view_iterator_t(this, boost::bind(&LLView::getParent, _1)); +} + +LLView::root_to_view_iterator_t LLView::endRootToView() +{ + return root_to_view_iterator_t(); +} + + // only create maps on demand, as they incur heap allocation/deallocation cost // when a view is constructed/deconstructed LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const @@ -2735,6 +2785,7 @@ LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const } return *mDefaultWidgets; } + void LLView::notifyParent(const LLSD& info) { LLView* parent = getParent(); @@ -2749,3 +2800,18 @@ void LLView::notifyChildren(const LLSD& info) } } +// convenient accessor for draw context +const LLViewDrawContext& LLView::getDrawContext() +{ + return LLViewDrawContext::getCurrentContext(); +} + +const LLViewDrawContext& LLViewDrawContext::getCurrentContext() +{ + static LLViewDrawContext default_context; + + if (sDrawContextStack.empty()) + return default_context; + + return *sDrawContextStack.back(); +} diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 1d48378081..d80c2af568 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -70,74 +70,35 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE; const U32 GL_NAME_UI_RESERVED = 2; -/* -// virtual functions defined in LLView: - -virtual BOOL isCtrl() const; - LLUICtrl -virtual BOOL isPanel(); - LLPanel -virtual void setRect(const LLRect &rect); - LLLineEditor - LLPanel -virtual BOOL canFocusChildren() const { return TRUE; } - LLFolderView -virtual void deleteAllChildren(); - LLFolderView, LLPanelInventory -virtual void setTentative(BOOL b) {} - LLUICtrl, LLSliderCtrl, LLSpinCtrl -virtual BOOL getTentative() const { return FALSE; } - LLUICtrl, LLCheckBoxCtrl -virtual void setVisible(BOOL visible); - LLFloater, LLAlertDialog, LLMenuItemGL, LLModalDialog -virtual void setEnabled(BOOL enabled) { mEnabled = enabled; } - LLCheckBoxCtrl, LLComboBox, LLLineEditor, LLMenuGL, LLRadioGroup, etc -virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) { return FALSE; } - LLUICtrl, LLButton, LLCheckBoxCtrl, LLLineEditor, LLMenuGL, LLSliderCtrl -virtual void handleVisibilityChange ( BOOL curVisibilityIn ); - LLMenuGL -virtual LLRect getSnapRect() const { return mRect; } *TODO: Make non virtual - LLFloater -virtual LLRect getRequiredRect() { return mRect; } - LLScrolllistCtrl -virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - LLUICtrl, et. al. -virtual void translate( S32 x, S32 y ); - LLMenuGL -virtual void setShape(const LLRect& new_rect, bool by_user); - LLFloater, LLScrollLIstVtrl -virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); -virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); - LLScrollListCtrl -virtual BOOL canSnapTo(const LLView* other_view) { return other_view != this && other_view->getVisible(); } - LLFloater -virtual void snappedTo(const LLView* snap_view) {} - LLFloater -virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - * -virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); - * -virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropType cargo_type,void* cargo_data,EAcceptance* accept,std::string& tooltip_msg); - * -virtual void draw(); - * - - * -virtual void onFocusLost() {} - LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox -virtual void onFocusReceived() {} - LLUICtrl, LLTextEditor, LLScrollListVtrl, LLMenuGL, LLLineEditor -virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; - LLTabContainer, LLPanel, LLMenuGL -virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata); - LLMenuItem -protected: -virtual BOOL handleKeyHere(KEY key, MASK mask); - * -virtual BOOL handleUnicodeCharHere(llwchar uni_char); - * -*/ +// maintains render state during traversal of UI tree +class LLViewDrawContext +{ +public: + F32 mAlpha; + + LLViewDrawContext(F32 alpha = 1.f) + : mAlpha(alpha) + { + if (!sDrawContextStack.empty()) + { + LLViewDrawContext* context_top = sDrawContextStack.back(); + // merge with top of stack + mAlpha *= context_top->mAlpha; + } + sDrawContextStack.push_back(this); + } + + ~LLViewDrawContext() + { + sDrawContextStack.pop_back(); + } + + static const LLViewDrawContext& getCurrentContext(); + +private: + static std::vector<LLViewDrawContext*> sDrawContextStack; +}; class LLViewWidgetRegistry : public LLChildRegistry<LLViewWidgetRegistry> {}; @@ -380,6 +341,7 @@ public: // Override and return required size for this object. 0 for width/height means don't care. virtual LLRect getRequiredRect(); + LLRect calcBoundingRect(); void updateBoundingRect(); LLView* getRootView(); @@ -393,9 +355,19 @@ public: BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const; BOOL childHasKeyboardFocus( const std::string& childname ) const; + // these iterators are used for collapsing various tree traversals into for loops typedef LLTreeDFSIter<LLView, child_list_const_iter_t> tree_iterator_t; - tree_iterator_t beginTree(); - tree_iterator_t endTree(); + tree_iterator_t beginTreeDFS(); + tree_iterator_t endTreeDFS(); + + typedef LLTreeDFSPostIter<LLView, child_list_const_iter_t> tree_post_iterator_t; + tree_post_iterator_t beginTreeDFSPost(); + tree_post_iterator_t endTreeDFSPost(); + + + typedef LLTreeDownIter<LLView> root_to_view_iterator_t; + root_to_view_iterator_t beginRootToView(); + root_to_view_iterator_t endRootToView(); // // UTILITIES @@ -406,6 +378,7 @@ public: virtual void translate( S32 x, S32 y ); void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); + BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ); void centerWithin(const LLRect& bounds); void setShape(const LLRect& new_rect, bool by_user = false); @@ -424,10 +397,7 @@ public: EAcceptance* accept, std::string& tooltip_msg); - virtual std::string getShowNamesToolTip(); - virtual void draw(); - void drawChildren(); void parseFollowsFlags(const LLView::Params& params); @@ -477,7 +447,8 @@ public: /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it. + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); // Display mToolTipMsg if no child handles it. + /*virtual*/ const std::string& getName() const; /*virtual*/ void onMouseCaptureLost(); /*virtual*/ BOOL hasMouseCapture(); @@ -552,9 +523,12 @@ public: virtual void notifyParent(const LLSD& info); virtual void notifyChildren(const LLSD& info); + static const LLViewDrawContext& getDrawContext(); + protected: void drawDebugRect(); void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE); + void drawChildren(); LLView* childrenHandleKey(KEY key, MASK mask); LLView* childrenHandleUnicodeChar(llwchar uni_char); @@ -574,10 +548,12 @@ protected: LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks); LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask); LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask); + LLView* childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect); ECursorType mHoverCursor; private: + LLView* mParentView; child_list_t mChildList; diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index f41c98f7b3..30717f87de 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -134,7 +134,7 @@ void LLViewBorder::draw() } } - drawChildren(); + LLView::draw(); } void LLViewBorder::drawOnePixelLines() diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h index 7bd0f2eebf..b5dbbc53fb 100644 --- a/indra/llwindow/llmousehandler.h +++ b/indra/llwindow/llmousehandler.h @@ -45,17 +45,20 @@ class LLMouseHandler public: LLMouseHandler() {} virtual ~LLMouseHandler() {} + typedef enum { SHOW_NEVER, SHOW_IF_NOT_BLOCKED, SHOW_ALWAYS, } EShowToolTip; + typedef enum { CLICK_LEFT, CLICK_MIDDLE, CLICK_RIGHT, CLICK_DOUBLELEFT } EClickType; + virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0; virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0; @@ -67,8 +70,7 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0; virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0; - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) = 0; - virtual EShowToolTip getShowToolTip() { return SHOW_IF_NOT_BLOCKED; }; + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) = 0; virtual const std::string& getName() const = 0; virtual void onMouseCaptureLost() = 0; diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index d35e7b40f8..1b867b79c9 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -517,6 +517,14 @@ namespace LLInitParam } template<> + bool ParamCompare<boost::function<void (void)> >::equals( + const boost::function<void (void)> &a, + const boost::function<void (void)> &b) + { + return false; + } + + template<> bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b) { return false; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index a1d0831939..baa782916e 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1815,7 +1815,13 @@ namespace LLInitParam bool ParamCompare<boost::function<void (const LLSD &,const LLSD &)> >::equals( const boost::function<void (const LLSD &,const LLSD &)> &a, const boost::function<void (const LLSD &,const LLSD &)> &b); - + + template<> + bool ParamCompare<boost::function<void (void)> >::equals( + const boost::function<void (void)> &a, + const boost::function<void (void)> &b); + + template<> bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b); } diff --git a/indra/media_plugins/base/media_plugin_base.exp b/indra/media_plugins/base/media_plugin_base.exp index d7a945a1c5..d8c7bb712a 100644 --- a/indra/media_plugins/base/media_plugin_base.exp +++ b/indra/media_plugins/base/media_plugin_base.exp @@ -1 +1,2 @@ -_LLPluginInitEntryPoint
\ No newline at end of file +_LLPluginInitEntryPoint + diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 767f93cf45..cd20648f74 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -196,6 +196,7 @@ set(viewer_SOURCE_FILES llfloatersettingsdebug.cpp llfloatersnapshot.cpp llfloatertelehub.cpp + llfloatertestinspectors.cpp llfloatertestlistview.cpp llfloatertools.cpp llfloatertopobjects.cpp @@ -220,7 +221,6 @@ set(viewer_SOURCE_FILES llgroupmgr.cpp llgroupnotify.cpp llhomelocationresponder.cpp - llhoverview.cpp llhudeffectbeam.cpp llhudeffect.cpp llhudeffectlookat.cpp @@ -652,6 +652,7 @@ set(viewer_HEADER_FILES llfloatersettingsdebug.h llfloatersnapshot.h llfloatertelehub.h + llfloatertestinspectors.h llfloatertestlistview.h llfloatertools.h llfloatertopobjects.h @@ -676,7 +677,6 @@ set(viewer_HEADER_FILES llgroupmgr.h llgroupnotify.h llhomelocationresponder.h - llhoverview.h llhudeffect.h llhudeffectbeam.h llhudeffectlookat.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 32b1443157..bbe69531b4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1706,7 +1706,18 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugStatModeFPS</key> + <key>DebugShowXUINames</key> + <map> + <key>Comment</key> + <string>Show tooltips with XUI path to widget</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DebugStatModeFPS</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3642,6 +3653,17 @@ <key>Value</key> <real>0.0</real> </map> + <key>InspectorFadeTime</key> + <map> + <key>Comment</key> + <string>Fade out timing for inspectors</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <string>0.1</string> + </map> <key>InstallLanguage</key> <map> <key>Comment</key> @@ -6864,7 +6886,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>ShowCameraAndMoveControls</key> <map> @@ -7309,17 +7331,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>ShowXUINames</key> - <map> - <key>Comment</key> - <string>Display XUI Names as Tooltips</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>SkinCurrent</key> <map> <key>Comment</key> @@ -7713,7 +7724,18 @@ <key>Value</key> <real>0.2</real> </map> - <key>ToolboxAutoMove</key> + <key>ToolTipVisibleTime</key> + <map> + <key>Comment</key> + <string>Fade tooltip after mouse is idle for this long</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> + <key>ToolboxAutoMove</key> <map> <key>Comment</key> <string>[NOT USED]</string> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 800c555113..9fe02a8ead 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -128,7 +128,7 @@ #include "lldebugview.h" #include "llconsole.h" #include "llcontainerview.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llsdserialize.h" @@ -409,7 +409,6 @@ static void settings_to_globals() gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); gMapScale = gSavedSettings.getF32("MapScale"); - LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips"); LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); } @@ -2353,7 +2352,7 @@ void LLAppViewer::cleanupSavedSettings() } gSavedSettings.setF32("MapScale", gMapScale ); - gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips); + gSavedSettings.setBOOL("ShowHoverTips", gToolTipView->getVisible()); // Some things are cached in LLAgent. if (gAgent.mInitialized) diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 05addf3f3a..a8b1ff6c92 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -147,7 +147,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) if (mAvatarId != value.asUUID()) { LLAvatarPropertiesProcessor::getInstance()->addObserver(value.asUUID(), this); - LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(value.asUUID(),APT_PROPERTIES); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(value.asUUID()); mAvatarId = value.asUUID(); // Check if cache already contains image_id for that avatar diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index ecd67e44ae..edf6e84b68 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -34,10 +34,16 @@ #include "llavatarpropertiesprocessor.h" -#include "message.h" +// Viewer includes #include "llagent.h" #include "llviewergenericmessage.h" +// Linden library includes +#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc. +#include "lldate.h" +#include "lltrans.h" +#include "message.h" + LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor() { } @@ -87,35 +93,18 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat } } -void LLAvatarPropertiesProcessor::sendDataRequest(const LLUUID& avatar_id, EAvatarProcessorType type, - const void * data) + +void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method) { - switch(type) + // Suppress duplicate requests while waiting for a response from the network + if (isPendingRequest(avatar_id, type)) { - case APT_PROPERTIES: - sendAvatarPropertiesRequest(avatar_id); - break; - case APT_PICKS: - sendGenericRequest(avatar_id, "avatarpicksrequest"); - break; - case APT_PICK_INFO: - if (data) { - sendPickInfoRequest(avatar_id, *static_cast<const LLUUID*>(data)); - } - break; - case APT_NOTES: - sendGenericRequest(avatar_id, "avatarnotesrequest"); - break; - case APT_GROUPS: - sendGenericRequest(avatar_id, "avatargroupsrequest"); - break; - default: - break; + // waiting for a response, don't re-request + return; } -} + // indicate we're going to make a request + addPendingRequest(avatar_id, type); -void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, const std::string method) -{ std::vector<std::string> strings; strings.push_back( avatar_id.asString() ); send_generic_message(method, strings); @@ -123,6 +112,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, co void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) { + if (isPendingRequest(avatar_id, APT_PROPERTIES)) + { + // waiting for a response, don't re-request + return; + } + // indicate we're going to make a request + addPendingRequest(avatar_id, APT_PROPERTIES); + LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); @@ -133,40 +130,29 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avat gAgent.sendReliableMessage(); } -void LLAvatarPropertiesProcessor::sendDataUpdate(const void* data, EAvatarProcessorType type) +void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id) { - switch(type) - { - case APT_PROPERTIES: - sendAvatarPropertiesUpdate(data); - break; - case APT_PICK_INFO: - sendPicInfoUpdate(data); - case APT_PICKS: -// sendGenericRequest(avatar_id, "avatarpicksrequest"); - break; - case APT_NOTES: -// sendGenericRequest(avatar_id, "avatarnotesrequest"); - break; - case APT_GROUPS: -// sendGenericRequest(avatar_id, "avatargroupsrequest"); - break; - default: - break; - } + sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest"); +} +void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id) +{ + sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest"); +} + +void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id) +{ + sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest"); } -void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const void* data) + +void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props) { llinfos << "Sending avatarinfo update" << llendl; - const LLAvatarData* avatar_props = static_cast<const LLAvatarData*>(data); // This value is required by sendAvatarPropertiesUpdate method. //A profile should never be mature. (From the original code) BOOL mature = FALSE; - - LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate); @@ -186,6 +172,156 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const void* data) gAgent.sendReliableMessage(); } +//static +std::string LLAvatarPropertiesProcessor::ageFromDate(const std::string& date_string) +{ + // Convert string date to malleable representation + S32 month, day, year; + S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &month, &day, &year); + if (matched != 3) return "???"; + + // Create ISO-8601 date string + std::string iso8601_date_string = + llformat("%04d-%02d-%02dT00:00:00Z", year, month, day); + LLDate date(iso8601_date_string); + + // Correct for the fact that account creation dates are in Pacific time, + // == UTC - 8 + F64 date_secs_since_epoch = date.secondsSinceEpoch(); + date_secs_since_epoch += 8.0 * 60.0 * 60.0; + + // Convert seconds from epoch to seconds from now + F64 now_secs_since_epoch = LLDate::now().secondsSinceEpoch(); + F64 age_secs = now_secs_since_epoch - date_secs_since_epoch; + + // We don't care about sub-day times + const F64 SEC_PER_DAY = 24.0 * 60.0 * 60.0; + S32 age_days = lltrunc(age_secs / SEC_PER_DAY); + + // Assume most values won't be used to fill in the format string: + // "[AGEYEARS][AGEMONTHS][AGEWEEKS][AGEDAYS]old" + LLStringUtil::format_map_t final_args; + final_args["[AGEYEARS]"] = ""; + final_args["[AGEMONTHS]"] = ""; + final_args["[AGEWEEKS]"] = ""; + final_args["[AGEDAYS]"] = ""; + + // Try for age in round number of years + LLStringUtil::format_map_t args; + S32 age_years = age_days / 365; + age_days = age_days % 365; + if (age_years > 1) + { + args["[YEARS]"] = llformat("%d", age_years); + final_args["[AGEYEARS]"] = LLTrans::getString("AgeYears", args); + } + else if (age_years == 1) + { + final_args["[AGEYEARS]"] = LLTrans::getString("Age1Year"); + } + // fall through because we show years + months for ages > 1 year + + S32 age_months = age_days / 30; + age_days = age_days % 30; + if (age_months > 1) + { + args["[MONTHS]"] = llformat("%d", age_months); + final_args["[AGEMONTHS]"] = LLTrans::getString("AgeMonths", args); + // Either N years M months, or just M months, + // so we can exit. + return LLTrans::getString("YearsMonthsOld", final_args); + } + else if (age_months == 1) + { + final_args["[AGEMONTHS]"] = LLTrans::getString("Age1Month"); + return LLTrans::getString("YearsMonthsOld", final_args); + } + + // Now for age in weeks + S32 age_weeks = age_days / 7; + age_days = age_days % 7; + if (age_weeks > 1) + { + args["[WEEKS]"] = llformat("%d", age_weeks); + final_args["[AGEWEEKS]"] = LLTrans::getString("AgeWeeks", args); + return LLTrans::getString("WeeksOld", final_args); + } + else if (age_weeks == 1) + { + final_args["[AGEWEEKS]"] = LLTrans::getString("Age1Week"); + return LLTrans::getString("WeeksOld", final_args); + } + + // Down to days now + if (age_days > 1) + { + args["[DAYS]"] = llformat("%d", age_days); + final_args["[AGEDAYS]"] = LLTrans::getString("AgeDays", args); + return LLTrans::getString("DaysOld", final_args); + } + else if (age_days == 1) + { + final_args["[AGEDAYS]"] = LLTrans::getString("Age1Day"); + return LLTrans::getString("DaysOld", final_args); + } + else + { + return LLTrans::getString("TodayOld"); + } +} + + +//static +std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data) +{ + // If you have a special account, like M Linden ("El Jefe!") + // return an untranslated "special" string + if (!avatar_data->caption_text.empty()) + { + return avatar_data->caption_text; + } + const char* const ACCT_TYPE[] = { + "AcctTypeResident", + "AcctTypeTrial", + "AcctTypeCharterMember", + "AcctTypeEmployee" + }; + U8 caption_max = (U8)LL_ARRAY_SIZE(ACCT_TYPE)-1; + U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, caption_max); + return LLTrans::getString(ACCT_TYPE[caption_index]); +} + +//static +std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data) +{ + // Special accounts like M Linden don't have payment info revealed. + if (!avatar_data->caption_text.empty()) return ""; + + // Linden employees don't have payment info revealed + const S32 LINDEN_EMPLOYEE_INDEX = 3; + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return ""; + + BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED); + BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED); + // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations + //BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED); + + const char* payment_text; + if(transacted) + { + payment_text = "PaymentInfoUsed"; + } + else if (identified) + { + payment_text = "PaymentInfoOnFile"; + } + else + { + payment_text = "NoPaymentInfoOnFile"; + } + return LLTrans::getString(payment_text); +} + void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**) { LLAvatarData avatar_data; @@ -214,7 +350,10 @@ void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* { msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text); } - notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES); + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES); + self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES); } void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**) @@ -228,11 +367,13 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply */ } + void LLAvatarPropertiesProcessor::processAvatarClassifiedReply(LLMessageSystem* msg, void**) { // avatarclassifiedsrequest is not sent according to new UI design but // keep this method according to resolved issues. } + void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**) { LLAvatarNotes avatar_notes; @@ -241,7 +382,10 @@ void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, msg->getUUID(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id); msg->getString(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes); - notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES); + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(avatar_notes.target_id, APT_NOTES); + self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES); } void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**) @@ -261,7 +405,10 @@ void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name)); } - notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS); + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(avatar_picks.target_id, APT_PICKS); + self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS); } void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**) @@ -306,7 +453,9 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi msg->getS32(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order); msg->getBOOL(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled); - notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO); + LLAvatarPropertiesProcessor* self = getInstance(); + // don't need to remove pending request as we don't track pick info + self->notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO); } void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**) @@ -329,12 +478,15 @@ void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, avatar_groups.group_list.push_back(group_data); } - notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS); + LLAvatarPropertiesProcessor* self = getInstance(); + self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS); + self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS); } void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type) { - LLAvatarPropertiesProcessor::observer_multimap_t observers = LLAvatarPropertiesProcessor::getInstance()->mObservers; + // Copy the map (because observers may delete themselves when updated?) + LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers; observer_multimap_t::iterator oi = observers.lower_bound(id); observer_multimap_t::iterator end = observers.upper_bound(id); @@ -397,10 +549,8 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id ) gAgent.sendReliableMessage(); } -void LLAvatarPropertiesProcessor::sendPicInfoUpdate(const void* pick_data) +void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) { - if (!pick_data) return; - const LLPickData *new_pick = static_cast<const LLPickData*>(pick_data); if (!new_pick) return; LLMessageSystem* msg = gMessageSystem; @@ -440,3 +590,38 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, request_params.push_back(pick_id.asString() ); send_generic_message("pickinforequest", request_params); } + + +bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) +{ + timestamp_map_t::key_type key = std::make_pair(avatar_id, type); + timestamp_map_t::iterator it = mRequestTimestamps.find(key); + + // Is this a new request? + if (it == mRequestTimestamps.end()) return false; + + // We found a request, check if it has timed out + U32 now = time(NULL); + const U32 REQUEST_EXPIRE_SECS = 5; + U32 expires = it->second + REQUEST_EXPIRE_SECS; + + // Request is still pending if it hasn't expired yet + // *NOTE: Expired requests will accumulate in this map, but they are rare, + // the data is small, and they will be updated if the same data is + // re-requested + return (now < expires); +} + +void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) +{ + timestamp_map_t::key_type key = std::make_pair(avatar_id, type); + U32 now = time(NULL); + // Add or update existing (expired) request + mRequestTimestamps[ key ] = now; +} + +void LLAvatarPropertiesProcessor::removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) +{ + timestamp_map_t::key_type key = std::make_pair(avatar_id, type); + mRequestTimestamps.erase(key); +} diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 2e10dea834..24675c44c0 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -43,10 +43,6 @@ - Remove EAvatarProcessorType in favor of separate observers, derived from a common parent (to get rid of void*). */ -/* -*TODO: mantipov: get rid of sendDataRequest and sendDataUpdate methods. Use exact methods instead of. -*/ - class LLMessageSystem; enum EAvatarProcessorType @@ -157,10 +153,20 @@ public: void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer); void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer); - - void sendDataRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const void * data = NULL); - void sendDataUpdate(const void* data, EAvatarProcessorType type); + // Request various types of avatar data. Duplicate requests will be + // suppressed while waiting for a response from the network. + void sendAvatarPropertiesRequest(const LLUUID& avatar_id); + void sendAvatarPicksRequest(const LLUUID& avatar_id); + void sendAvatarNotesRequest(const LLUUID& avatar_id); + void sendAvatarGroupsRequest(const LLUUID& avatar_id); + + // Duplicate pick info requests are not suppressed. + void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id); + + void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props); + + void sendPickInfoUpdate(const LLPickData* new_pick); void sendFriendRights(const LLUUID& avatar_id, S32 rights); @@ -168,6 +174,20 @@ public: void sendPickDelete(const LLUUID& pick_id); + // Convert a date provided by the server (MM/DD/YYYY) into a localized, + // human-readable age (1 year, 2 months) using translation strings from + // the XML file. + static std::string ageFromDate(const std::string& date_string); + + // Returns translated, human readable string for account type, such + // as "Resident" or "Linden Employee". Used for profiles, inspectors. + static std::string accountType(const LLAvatarData* avatar_data); + + // Returns translated, human readable string for payment info, such + // as "Payment Info on File" or "Payment Info Used". + // Used for profiles, inspectors. + static std::string paymentInfo(const LLAvatarData* avatar_data); + static void processAvatarPropertiesReply(LLMessageSystem* msg, void**); static void processAvatarInterestsReply(LLMessageSystem* msg, void**); @@ -181,19 +201,23 @@ public: static void processAvatarPicksReply(LLMessageSystem* msg, void**); static void processPickInfoReply(LLMessageSystem* msg, void**); + protected: - void sendAvatarPropertiesRequest(const LLUUID& avatar_id); + void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method); - void sendGenericRequest(const LLUUID& avatar_id, const std::string method); - - void sendAvatarPropertiesUpdate(const void* data); + void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type); - void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id); - - void sendPicInfoUpdate(const void * pick_data); + // Is there a pending, not timed out, request for this avatar's data? + // Use this to suppress duplicate requests for data when a request is + // pending. + bool isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type); - static void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type); + // Call this when a request has been sent + void addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type); + + // Call this when the reply to the request is received + void removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type); typedef void* (*processor_method_t)(LLMessageSystem*); static processor_method_t getProcessor(EAvatarProcessorType type); @@ -203,6 +227,13 @@ protected: typedef std::multimap<LLUUID, LLAvatarPropertiesObserver*> observer_multimap_t; observer_multimap_t mObservers; + + // Keep track of pending requests for data by avatar id and type. + // Maintain a timestamp for each request so a request that receives no reply + // does not block future requests forever. + // Map avatar_id+request_type -> U32 timestamp in seconds + typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t; + timestamp_map_t mRequestTimestamps; }; #endif // LL_LLAVATARPROPERTIESPROCESSOR_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 861f23abb7..d166715038 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -37,12 +37,12 @@ #include "llchiclet.h" #include "llfloaterreg.h" #include "llflyoutbutton.h" +#include "llimpanel.h" // for LLIMFloater #include "lllayoutstack.h" #include "llnearbychatbar.h" #include "llsplitbutton.h" #include "llsyswellwindow.h" #include "llfloatercamera.h" -#include "llimpanel.h" LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), @@ -119,6 +119,7 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl) } } +// *TODO Vadim: why void* ? void* LLBottomTray::createNearbyChatBar(void* userdata) { return new LLNearbyChatBar(); @@ -126,30 +127,19 @@ void* LLBottomTray::createNearbyChatBar(void* userdata) LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id) { - if(session_id.isNull()) - { - return NULL; - } + LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id); - LLFloaterIMPanel* im = LLIMMgr::getInstance()->findFloaterBySession(session_id); - if (!im) + switch (im_chiclet_type) { - return NULL; //should never happen - } - - switch(im->getDialogType()) - { - case IM_NOTHING_SPECIAL: + case LLIMChiclet::TYPE_IM: return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id); - break; - case IM_SESSION_GROUP_START: - case IM_SESSION_INVITE: + case LLIMChiclet::TYPE_GROUP: return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id); - break; - default: - return NULL; + case LLIMChiclet::TYPE_UNKNOWN: break; } + + return NULL; } //virtual @@ -182,6 +172,14 @@ void LLBottomTray::sessionRemoved(const LLUUID& session_id) { if(getChicletPanel()) { + // IM floater should be closed when session removed and associated chiclet closed + LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>( + "impanel", session_id); + if (iMfloater != NULL) + { + iMfloater->closeFloater(); + } + getChicletPanel()->removeChiclet(session_id); } } @@ -265,4 +263,10 @@ void LLBottomTray::showCameraAndMoveControls(BOOL visible) { mCamPanel->setVisible(visible); mMovementPanel->setVisible(visible); + + if (!visible) + { + LLFloaterReg::hideFloaterInstance("moveview"); + LLFloaterReg::hideFloaterInstance("camera"); + } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index f5dfbb2851..6fb6552f2d 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -38,6 +38,7 @@ #include "llchatmsgbox.h" #include "llavatariconctrl.h" #include "llfloaterreg.h" +#include "lllocalcliprect.h" #include "lltrans.h" #include "llviewercontrol.h" diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 808fcde312..9ce194c712 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -40,6 +40,7 @@ #include "llimpanel.h" // LLFloaterIMPanel #include "llimview.h" #include "llfloaterreg.h" +#include "lllocalcliprect.h" #include "llmenugl.h" #include "lloutputmonitorctrl.h" #include "lltextbox.h" @@ -210,19 +211,38 @@ void LLIMChiclet::draw() { LLUICtrl::draw(); - //if we have a docked floater, we want to position it relative to us - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", getSessionId()); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); +} + +// static +LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) +{ + EType type = TYPE_UNKNOWN; + LLFloaterIMPanel* im = NULL; + + if(session_id.isNull()) + return type; - if (im_floater && im_floater->isDocked()) + if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id))) { - S32 x, y; - getParent()->localPointToScreen(getRect().getCenterX(), 0, &x, &y); - im_floater->translate(x - im_floater->getRect().getCenterX(), 10 - im_floater->getRect().mBottom); - //set this so the docked floater knows it's been positioned and can now draw - im_floater->setPositioned(true); + llassert_always(0 && "IM session not found"); // should never happen + return type; } - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); + switch(im->getDialogType()) + { + case IM_NOTHING_SPECIAL: + type = TYPE_IM; + break; + case IM_SESSION_GROUP_START: + case IM_SESSION_INVITE: + type = TYPE_GROUP; + break; + default: + break; + } + + return type; } ////////////////////////////////////////////////////////////////////////// @@ -235,6 +255,7 @@ LLIMP2PChiclet::Params::Params() , speaker("speaker") , show_speaker("show_speaker") { + // *TODO Vadim: Get rid of hardcoded values. rect(LLRect(0, 25, 45, 0)); avatar_icon.name("avatar_icon"); @@ -1039,11 +1060,14 @@ BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +// *TODO Vadim: Move this out of llchiclet.cpp. + LLTalkButton::Params::Params() : speak_button("speak_button") , show_button("show_button") , monitor("monitor") { + // *TODO Vadim: move hardcoded labels (!) and other params to XUI. speak_button.name("left"); speak_button.label("Speak"); speak_button.label_selected("Speak"); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index f96dfb69ec..91f55915ed 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -272,6 +272,11 @@ private: class LLIMChiclet : public LLChiclet { public: + enum EType { + TYPE_UNKNOWN, + TYPE_IM, + TYPE_GROUP + }; /*virtual*/ ~LLIMChiclet() {}; @@ -307,6 +312,19 @@ public: /*virtual*/ void draw(); /** + * Determine whether given ID refers to a group or an IM chat session. + * + * This is used when we need to chose what IM chiclet (P2P/group) + * class to instantiate. + * + * @param session_id session ID. + * @return TYPE_GROUP in case of group chat session, + * TYPE_IM in case of P2P session, + * TYPE_UNKNOWN otherwise. + */ + static EType getIMSessionType(const LLUUID& session_id); + + /** * The action taken on mouse down event. * * Made public so that it can be triggered from outside @@ -368,7 +386,7 @@ public: Params(); }; - void setOtherParticipantId(const LLUUID& other_participant_id); + /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); /*virtual*/ void setShowSpeaker(bool show); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 31c2d93c05..113f4c2c54 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -197,6 +197,7 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask) // assumes GL state is set for 2D void LLColorSwatchCtrl::draw() { + F32 alpha = getDrawContext().mAlpha; mBorder->setKeyboardFocusHighlight(hasFocus()); // Draw border LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); @@ -232,15 +233,15 @@ void LLColorSwatchCtrl::draw() { gl_rect_2d_checkerboard( interior ); } - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image); + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image, LLColor4::white % alpha); fallback_image->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); } else { // Draw grey and an X - gl_rect_2d(interior, LLColor4::grey, TRUE); + gl_rect_2d(interior, LLColor4::grey % alpha, TRUE); - gl_draw_x(interior, LLColor4::black); + gl_draw_x(interior, LLColor4::black % alpha); } } diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp index 00ffff79a8..225f177546 100644 --- a/indra/newview/llconfirmationmanager.cpp +++ b/indra/newview/llconfirmationmanager.cpp @@ -37,8 +37,7 @@ #include "lluictrlfactory.h" // viewer includes -#include "llviewerwindow.h" -#include "lllineeditor.h" +#include "llnotifications.h" #include "llstring.h" LLConfirmationManager::ListenerBase::~ListenerBase() diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 8ceb41c27a..8af3a8b539 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -32,16 +32,18 @@ #include "llviewerprecompiledheaders.h" -#include "indra_constants.h" #include "llfasttimerview.h" + #include "llviewerwindow.h" #include "llrect.h" #include "llerror.h" #include "llgl.h" #include "llrender.h" +#include "lllocalcliprect.h" #include "llmath.h" #include "llfontgl.h" #include "llsdserialize.h" +#include "lltooltip.h" #include "llappviewer.h" #include "llviewertexturelist.h" @@ -242,15 +244,20 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) } -BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) { // tooltips for timer bars if (mHoverTimer) { - localRectToScreen(mToolTipRect, sticky_rect_screen); - msg = mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex); + LLRect screen_rect; + localRectToScreen(mToolTipRect, &screen_rect); + + LLToolTipMgr::instance().show(LLToolTipParams() + .message(mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex)) + .sticky_rect(screen_rect)); + return TRUE; } } @@ -262,11 +269,11 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* stic LLFastTimer::NamedTimer* idp = getLegendID(y); if (idp) { - msg = idp->getToolTip(); + LLToolTipMgr::instance().show(idp->getToolTip()); + return TRUE; } } - } return FALSE; diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index f301888984..97e4e94460 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -57,7 +57,7 @@ public: virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void draw(); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index a7f0a8ff9a..ef71e35254 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -42,6 +42,7 @@ #include "lltrans.h" #include "lluictrlfactory.h" #include "llmenugl.h" +#include "lltooltip.h" #include "llagent.h" #include "llclipboard.h" @@ -122,14 +123,9 @@ class LLFavoriteLandmarkButton : public LLButton { public: - BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect) { - if(LLUI::sShowXUINames) - { - return LLButton::handleToolTip(x, y, msg, sticky_rect); - } - - msg = mUrlGetter.getSLURL(); + LLToolTipMgr::instance().show(mUrlGetter.getSLURL()); return TRUE; } @@ -193,14 +189,9 @@ private: class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL { public: - BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect) { - if(LLUI::sShowXUINames) - { - return LLMenuItemCallGL::handleToolTip(x, y, msg, sticky_rect); - } - - msg = mUrlGetter.getSLURL(); + LLToolTipMgr::instance().show(mUrlGetter.getSLURL()); return TRUE; } @@ -227,6 +218,36 @@ private: LLSLURLGetter mUrlGetter; }; +/** + * This class is needed to update an item being copied to the favorites folder + * with a sort field value (required to save favorites bar's tabs order). + * See method handleNewFavoriteDragAndDrop for more details on how this class is used. + */ +class LLItemCopiedCallback : public LLInventoryCallback +{ +public: + LLItemCopiedCallback(S32 sortField): mSortField(sortField) {} + + virtual void fire(const LLUUID& inv_item) + { + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + + if (item) + { + item->setSortField(mSortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + + LLView::getWindow()->setCursor(UI_CURSOR_ARROW); + } + +private: + S32 mSortField; +}; // updateButtons's helper struct LLFavoritesSort @@ -378,7 +399,27 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con mItems.push_back(gInventory.getItem(item->getUUID())); } - saveItemsOrder(mItems); + int sortField = 0; + LLPointer<LLItemCopiedCallback> cb; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) + { + LLViewerInventoryItem* currItem = *i; + + if (currItem->getUUID() == item->getUUID()) + { + cb = new LLItemCopiedCallback(++sortField); + } + else + { + currItem->setSortField(++sortField); + currItem->setComplete(TRUE); + currItem->updateServer(FALSE); + + gInventory.updateItem(currItem); + } + } copy_inventory_item( gAgent.getID(), @@ -386,9 +427,7 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con item->getUUID(), favorites_id, std::string(), - LLPointer<LLInventoryCallback>(NULL)); - - getWindow()->setCursor(UI_CURSOR_ARROW); + cb); llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl; } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index dec27db74b..c062e6ccf2 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -505,7 +505,7 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) mAnimPreview->requestUpdate(); - LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY); + LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); } if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview) diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 07dbf98a1e..61568df12e 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -547,7 +547,7 @@ BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask) mSculptedPreview->refresh(); } - LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY); + LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); } if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index d389cf06ec..e2e9734012 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -103,6 +103,7 @@ #include "llviewermedia.h" #include "llpluginclassmedia.h" +#include <boost/regex.hpp> //RN temporary includes for resolution switching #include "llglheaders.h" diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index b5c36b1083..13a2594c45 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -75,6 +75,7 @@ #include "llimagepng.h" #include "llimagebmp.h" #include "llimagej2c.h" +#include "lllocalcliprect.h" #include "llresmgr.h" // LLLocale #include "llvfile.h" #include "llvfs.h" diff --git a/indra/newview/llfloatertestinspectors.cpp b/indra/newview/llfloatertestinspectors.cpp new file mode 100644 index 0000000000..c56586cb95 --- /dev/null +++ b/indra/newview/llfloatertestinspectors.cpp @@ -0,0 +1,109 @@ +/** +* @file llfloatertestinspectors.cpp +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#include "llviewerprecompiledheaders.h" + +#include "llfloatertestinspectors.h" + +// Viewer includes +#include "llstartup.h" + +// Linden library includes +#include "llfloaterreg.h" +//#include "lluictrlfactory.h" + +LLFloaterTestInspectors::LLFloaterTestInspectors(const LLSD& seed) +: LLFloater(seed) +{ + mCommitCallbackRegistrar.add("ShowAvatarInspector", + boost::bind(&LLFloaterTestInspectors::showAvatarInspector, this, _1, _2)); +} + +LLFloaterTestInspectors::~LLFloaterTestInspectors() +{} + +BOOL LLFloaterTestInspectors::postBuild() +{ +// getChild<LLUICtrl>("avatar_2d_btn")->setCommitCallback( +// boost::bind(&LLFloaterTestInspectors::onClickAvatar2D, this)); + getChild<LLUICtrl>("avatar_3d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickAvatar3D, this)); + getChild<LLUICtrl>("object_2d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickObject2D, this)); + getChild<LLUICtrl>("object_3d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickObject3D, this)); + getChild<LLUICtrl>("group_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickGroup, this)); + getChild<LLUICtrl>("place_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickPlace, this)); + getChild<LLUICtrl>("event_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickEvent, this)); + + return LLFloater::postBuild(); +} + +void LLFloaterTestInspectors::showAvatarInspector(LLUICtrl*, const LLSD& avatar_id) +{ + LLUUID id; // defaults to null + if (LLStartUp::getStartupState() >= STATE_STARTED) + { + id = avatar_id.asUUID(); + } + // spawns off mouse position automatically + LLFloaterReg::showInstance("inspect_avatar", id); +} + +void LLFloaterTestInspectors::onClickAvatar2D() +{ +} + +void LLFloaterTestInspectors::onClickAvatar3D() +{ +} + +void LLFloaterTestInspectors::onClickObject2D() +{ +} + +void LLFloaterTestInspectors::onClickObject3D() +{ +} + +void LLFloaterTestInspectors::onClickGroup() +{ +} + +void LLFloaterTestInspectors::onClickPlace() +{ +} + +void LLFloaterTestInspectors::onClickEvent() +{ +} diff --git a/indra/newview/llfloatertestinspectors.h b/indra/newview/llfloatertestinspectors.h new file mode 100644 index 0000000000..d2dc2248bb --- /dev/null +++ b/indra/newview/llfloatertestinspectors.h @@ -0,0 +1,64 @@ +/** +* @file llfloatertestinspectors.h +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLFLOATERTESTINSPECTORS_H +#define LLFLOATERTESTINSPECTORS_H + +#include "llfloater.h" + +class LLSD; + +class LLFloaterTestInspectors : public LLFloater +{ + friend class LLFloaterReg; +public: + // nothing yet + +private: + // Construction handled by LLFloaterReg + LLFloaterTestInspectors(const LLSD& seed); + ~LLFloaterTestInspectors(); + + /*virtual*/ BOOL postBuild(); + + // Button callback to show + void showAvatarInspector(LLUICtrl*, const LLSD& avatar_id); + + // Debug function hookups for buttons + void onClickAvatar2D(); + void onClickAvatar3D(); + void onClickObject2D(); + void onClickObject3D(); + void onClickGroup(); + void onClickPlace(); + void onClickEvent(); +}; + +#endif diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 3b3ada46a8..43fbe362d5 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -161,8 +161,6 @@ void LLAgent::renderAutoPilotTarget() } } -extern BOOL gDebugSelect; - // Returns true if you got at least one object void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) { diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 73d3a60701..cddc67cb0a 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -77,14 +77,20 @@ BOOL LLGroupList::update(const std::string& name_filter) const LLGroupData& group_data = gAgent.mGroups.get(i); if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter)) continue; - addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM); + addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM); // ADD_SORTED can only sort by first column anyway } + // Force sorting the list. + updateSort(); + // add "none" to list at top { std::string loc_none = LLTrans::getString("GroupsNone"); if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter)) addItem(LLUUID::null, loc_none, highlight_id.isNull(), ADD_TOP); + + // Prevent the "none" item from being sorted. + setNeedsSort(false); } group_list->selectByValue(highlight_id); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 674fff4040..0efe9b9849 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1917,19 +1917,8 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string void LLFloaterIMPanel::showSessionStartError( const std::string& error_string) { - //the error strings etc. should be really be static and local - //to this file instead of in the LLFloaterIM - //but they were in llimview.cpp first and unfortunately - //some translations into non English languages already occurred - //thus making it a tad harder to change over to a - //"correct" solution. The best solution - //would be to store all of the misc. strings into - //their own XML file which would be read in by any LLIMPanel - //post build function instead of repeating the same info - //in the group, adhoc and normal IM xml files. LLSD args; - args["REASON"] = - LLFloaterIM::sErrorStringsMap[error_string]; + args["REASON"] = LLTrans::getString(error_string); args["RECIPIENT"] = getTitle(); LLSD payload; @@ -1948,9 +1937,9 @@ void LLFloaterIMPanel::showSessionEventError( { LLSD args; args["REASON"] = - LLFloaterIM::sErrorStringsMap[error_string]; + LLTrans::getString(error_string); args["EVENT"] = - LLFloaterIM::sEventStringsMap[event_string]; + LLTrans::getString(event_string); args["RECIPIENT"] = getTitle(); LLNotifications::instance().add( @@ -1964,7 +1953,7 @@ void LLFloaterIMPanel::showSessionForceClose( LLSD args; args["NAME"] = getTitle(); - args["REASON"] = LLFloaterIM::sForceCloseSessionMap[reason_string]; + args["REASON"] = LLTrans::getString(reason_string); LLSD payload; payload["session_id"] = mSessionUUID; @@ -2000,7 +1989,7 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLIMFloater::LLIMFloater(const LLUUID& session_id) - : LLFloater(session_id), + : LLDockableFloater(NULL, session_id), mControlPanel(NULL), mSessionID(session_id), mLastMessageIndex(-1), @@ -2130,9 +2119,7 @@ BOOL LLIMFloater::postBuild() setTitle(LLIMModel::instance().getName(mSessionID)); setDocked(true); - mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png"); - - return TRUE; + return LLDockableFloater::postBuild(); } @@ -2156,8 +2143,6 @@ void* LLIMFloater::createPanelGroupControl(void* userdata) return self->mControlPanel; } - -const U32 UNDOCK_LEAP_HEIGHT = 12; const U32 DOCK_ICON_HEIGHT = 6; //virtual @@ -2175,20 +2160,6 @@ void LLIMFloater::onFocusLost() } } - - -//virtual -void LLIMFloater::setDocked(bool docked, bool pop_on_undock) -{ - LLFloater::setDocked(docked); - - if (!docked && pop_on_undock) - { - // visually pop up a little bit to emphasize the undocking - translate(0, UNDOCK_LEAP_HEIGHT); - } -} - void LLIMFloater::onSlide() { LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel"); @@ -2217,6 +2188,20 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) floater->updateMessages(); floater->mInputEditor->setFocus(TRUE); + + if (floater->getDockControl() == NULL) + { + LLView* chiclet = + LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLView>( + session_id); + if (chiclet == NULL) + { + llerror("Dock chiclet for LLIMFloater doesn't exists", 0); + } + floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), + LLDockControl::TOP, floater->isDocked())); + } + return floater; } @@ -2316,18 +2301,3 @@ void LLIMFloater::setTyping(BOOL typing) { } - -void LLIMFloater::draw() -{ - //if we are docked, make sure we've been positioned by the chiclet - if (!isDocked() || mPositioned) - { - LLFloater::draw(); - - if (isDocked()) - { - mDockTongue->draw( (getRect().getWidth()/2) - mDockTongue->getWidth()/2, -mDockTongue->getHeight()); - } - } -} - diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 284a486b0f..1d69f1567c 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -33,7 +33,7 @@ #ifndef LL_IMPANEL_H #define LL_IMPANEL_H -#include "llfloater.h" +#include "lldockablefloater.h" #include "lllogchat.h" #include "lluuid.h" #include "lldarray.h" @@ -363,7 +363,7 @@ private: // Individual IM window that appears at the bottom of the screen, // optionally "docked" to the bottom tray. -class LLIMFloater : public LLFloater +class LLIMFloater : public LLDockableFloater { public: LLIMFloater(const LLUUID& session_id); @@ -372,18 +372,11 @@ public: // LLView overrides /*virtual*/ BOOL postBuild(); - - // LLView overrides for drawing dock tongue - /*virtual*/ - void draw(); // Floater should close when user clicks away to other UI area, // hence causing focus loss. /*virtual*/ void onFocusLost(); - // LLFloater overrides - /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); - // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); @@ -426,7 +419,6 @@ private: LLViewerTextEditor* mHistoryEditor; LLLineEditor* mInputEditor; bool mPositioned; - LLUIImagePtr mDockTongue; }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c1a5f21010..901b3351c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -83,14 +83,7 @@ LLIMMgr* gIMMgr = NULL; // Statics // // *FIXME: make these all either UIStrings or Strings -static std::string sOnlyUserMessage; -static LLUIString sOfflineMessage; -static std::string sMutedMessage; -static LLUIString sInviteMessage; -std::map<std::string,std::string> LLFloaterIM::sEventStringsMap; -std::map<std::string,std::string> LLFloaterIM::sErrorStringsMap; -std::map<std::string,std::string> LLFloaterIM::sForceCloseSessionMap; std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap; @@ -750,101 +743,6 @@ LLUUID LLIMMgr::computeSessionID( } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLFloaterIM -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -LLFloaterIM::LLFloaterIM() - : LLMultiFloater(LLSD()) -{ - // autoresize=false is necessary to avoid resizing of the IM window whenever - // a session is opened or closed (it would otherwise resize the window to match - // the size of the im-sesssion when they were created. This happens in - // LLMultiFloater::resizeToContents() when called through LLMultiFloater::addFloater()) - mAutoResize = FALSE; - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im.xml", NULL); -} - -BOOL LLFloaterIM::postBuild() -{ - // IM session initiation warnings - sOnlyUserMessage = getString("only_user_message"); - sOfflineMessage = getString("offline_message"); - sMutedMessage = getString("muted_message"); - - sInviteMessage = getString("invite_message"); - - if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() ) - { - sErrorStringsMap["generic"] = - getString("generic_request_error"); - } - - if ( sErrorStringsMap.find("unverified") == - sErrorStringsMap.end() ) - { - sErrorStringsMap["unverified"] = - getString("insufficient_perms_error"); - } - - if ( sErrorStringsMap.end() == - sErrorStringsMap.find("no_ability") ) - { - sErrorStringsMap["no_ability"] = - getString("no_ability_error"); - } - - if ( sErrorStringsMap.end() == - sErrorStringsMap.find("muted") ) - { - sErrorStringsMap["muted"] = - getString("muted_error"); - } - - if ( sErrorStringsMap.end() == - sErrorStringsMap.find("not_a_moderator") ) - { - sErrorStringsMap["not_a_moderator"] = - getString("not_a_mod_error"); - } - - if ( sErrorStringsMap.end() == - sErrorStringsMap.find("does not exist") ) - { - sErrorStringsMap["does not exist"] = - getString("session_does_not_exist_error"); - } - - if ( sEventStringsMap.end() == sEventStringsMap.find("add") ) - { - sEventStringsMap["add"] = - getString("add_session_event"); - } - - if ( sEventStringsMap.end() == sEventStringsMap.find("message") ) - { - sEventStringsMap["message"] = - getString("message_session_event"); - } - - - if ( sForceCloseSessionMap.end() == - sForceCloseSessionMap.find("removed") ) - { - sForceCloseSessionMap["removed"] = - getString("removed_from_group"); - } - - if ( sForceCloseSessionMap.end() == - sForceCloseSessionMap.find("no ability") ) - { - sForceCloseSessionMap["no ability"] = - getString("close_on_no_ability"); - } - - return TRUE; -} - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLIncomingCallDialog //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : @@ -1151,11 +1049,6 @@ LLIMMgr::LLIMMgr() : mFriendObserver = new LLIMViewFriendObserver(this); LLAvatarTracker::instance().addObserver(mFriendObserver); - // *HACK: use floater to initialize string constants from xml file - // then delete it right away - LLFloaterIM* dummy_floater = new LLFloaterIM(); - delete dummy_floater; - mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); } @@ -1809,7 +1702,7 @@ void LLIMMgr::noteOfflineUsers( S32 count = ids.count(); if(count == 0) { - floater->addHistoryLine(sOnlyUserMessage, LLUIColorTable::instance().getColor("SystemChatColor")); + floater->addHistoryLine(LLTrans::getString("only_user_message"), LLUIColorTable::instance().getColor("SystemChatColor")); } else { @@ -1822,7 +1715,7 @@ void LLIMMgr::noteOfflineUsers( if(info && !info->isOnline() && gCacheName->getName(ids.get(i), first, last)) { - LLUIString offline = sOfflineMessage; + LLUIString offline = LLTrans::getString("offline_message"); offline.setArg("[FIRST]", first); offline.setArg("[LAST]", last); floater->addHistoryLine(offline, LLUIColorTable::instance().getColor("SystemChatColor")); @@ -1848,7 +1741,7 @@ void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater, { if( ml->isMuted(ids.get(i)) ) { - LLUIString muted = sMutedMessage; + LLUIString muted = LLTrans::getString("muted_message"); floater->addHistoryLine(muted); break; } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index aed3b68471..4eb743b1ac 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -44,7 +44,6 @@ class LLFloaterChatterBox; class LLUUID; class LLFloaterIMPanel; class LLFriendObserver; -class LLFloaterIM; class LLIMModel : public LLSingleton<LLIMModel> { @@ -269,18 +268,6 @@ private: LLUUID mBeingRemovedSessionID; }; - -class LLFloaterIM : public LLMultiFloater -{ -public: - LLFloaterIM(); - /*virtual*/ BOOL postBuild(); - - static std::map<std::string,std::string> sEventStringsMap; - static std::map<std::string,std::string> sErrorStringsMap; - static std::map<std::string,std::string> sForceCloseSessionMap; -}; - class LLIncomingCallDialog : public LLModalDialog { public: diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 5bb96f0469..72f89d2e72 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -36,22 +36,72 @@ // viewer files #include "llagentdata.h" #include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" #include "llcallingcard.h" // linden libraries +#include "lltooltip.h" // positionViewNearMouse() #include "lluictrl.h" +// This object represents a pending request for avatar properties information +class LLFetchAvatarData : public LLAvatarPropertiesObserver +{ +public: + // If the inspector closes it will delete the pending request object, so the + // inspector pointer will be valid for the lifetime of this object + LLFetchAvatarData(const LLUUID& avatar_id, LLInspectAvatar* inspector) + : mAvatarID(avatar_id), + mInspector(inspector) + { + LLAvatarPropertiesProcessor* processor = + LLAvatarPropertiesProcessor::getInstance(); + // register ourselves as an observer + processor->addObserver(mAvatarID, this); + // send a request (duplicates will be suppressed inside the avatar + // properties processor) + processor->sendAvatarPropertiesRequest(mAvatarID); + } + + ~LLFetchAvatarData() + { + // remove ourselves as an observer + LLAvatarPropertiesProcessor::getInstance()-> + removeObserver(mAvatarID, this); + } + + void processProperties(void* data, EAvatarProcessorType type) + { + // route the data to the inspector + if (data + && type == APT_PROPERTIES) + { + LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); + mInspector->processAvatarData(avatar_data); + } + } -LLInspectAvatar::LLInspectAvatar(const LLSD& avatar_id) -: LLFloater(avatar_id), - mAvatarID( avatar_id.asUUID() ), + // Store avatar ID so we can un-register the observer on destruction + LLUUID mAvatarID; + LLInspectAvatar* mInspector; +}; + +LLInspectAvatar::LLInspectAvatar(const LLSD& sd) +: LLFloater( LLSD() ), // single_instance, doesn't really need key + mAvatarID(), // set in onOpen() mFirstName(), - mLastName() + mLastName(), + mPropertiesRequest(NULL) { + // can't make the properties request until the widgets are constructed + // as it might return immediately, so do it in postBuild. } LLInspectAvatar::~LLInspectAvatar() { + // clean up any pending requests so they don't call back into a deleted + // view + delete mPropertiesRequest; + mPropertiesRequest = NULL; } /*virtual*/ @@ -63,31 +113,94 @@ BOOL LLInspectAvatar::postBuild(void) getChild<LLUICtrl>("view_profile_btn")->setCommitCallback( boost::bind(&LLInspectAvatar::onClickViewProfile, this) ); - // can't call from constructor as widgets are not built yet - refresh(); - return TRUE; } -void LLInspectAvatar::setAvatarID(const LLUUID &avatar_id) +void LLInspectAvatar::draw() { - mAvatarID = avatar_id; - refresh(); + static LLCachedControl<F32> FADE_OUT_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f); + if (mCloseTimer.getStarted()) + { + F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 1.f, 0.f); + LLViewDrawContext context(alpha); + LLFloater::draw(); + if (mCloseTimer.getElapsedTimeF32() > FADE_OUT_TIME) + { + closeFloater(false); + } + } + else + { + LLFloater::draw(); + } } -void LLInspectAvatar::refresh() + +// Multiple calls to showInstance("inspect_avatar", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLInspectAvatar::onOpen(const LLSD& data) { - // *HACK: Don't stomp data when spawning from login screen - if (mAvatarID.isNull()) return; + mCloseTimer.stop(); + + // Extract appropriate avatar id + mAvatarID = data.isUUID() ? data : data["avatar_id"]; + + // Position the inspector relative to the mouse cursor + // Similar to how tooltips are positioned + // See LLToolTipMgr::createToolTip + if (data.has("pos")) + { + LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); + } + else + { + LLUI::positionViewNearMouse(this); + } + + // can't call from constructor as widgets are not built yet + requestUpdate(); +} + +//virtual +void LLInspectAvatar::onFocusLost() +{ + // Start closing when we lose focus + mCloseTimer.start(); +} + +void LLInspectAvatar::requestUpdate() +{ + // Don't make network requests when spawning from the debug menu at the + // login screen (which is useful to work on the layout). + if (mAvatarID.isNull()) + { + getChild<LLUICtrl>("user_subtitle")-> + setValue("Test subtitle"); + getChild<LLUICtrl>("user_details")-> + setValue("Test details\nTest line 2"); + return; + } + + // Clear out old data so it doesn't flash between old and new + getChild<LLUICtrl>("user_name")->setValue(""); + getChild<LLUICtrl>("user_subtitle")->setValue(""); + getChild<LLUICtrl>("user_details")->setValue(""); + + // Make a new request for properties + delete mPropertiesRequest; + mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this); // You can't re-add someone as a friend if they are already your friend bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; bool is_self = (mAvatarID == gAgentID); childSetEnabled("add_friend_btn", !is_friend && !is_self); - // *TODO: replace with generic - // LLAvatarPropertiesProcessor::getInstance()->addObserver() - // ->sendDataRequest() + // Use an avatar_icon even though the image id will come down with the + // avatar properties because the avatar_icon code maintains a cache of icons + // and this may result in the image being visible sooner. + // *NOTE: This may generate a duplicate avatar properties request, but that + // will be suppressed internally in the avatar properties processor. childSetValue("avatar_icon", LLSD(mAvatarID) ); gCacheName->get(mAvatarID, FALSE, @@ -95,6 +208,26 @@ void LLInspectAvatar::refresh() this, _1, _2, _3, _4)); } +void LLInspectAvatar::processAvatarData(LLAvatarData* data) +{ + LLStringUtil::format_map_t args; + args["[BORN_ON]"] = data->born_on; + args["[AGE]"] = LLAvatarPropertiesProcessor::ageFromDate(data->born_on); + args["[SL_PROFILE]"] = data->about_text; + args["[RW_PROFILE"] = data->fl_about_text; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(data); + + std::string subtitle = getString("Subtitle", args); + getChild<LLUICtrl>("user_subtitle")->setValue( LLSD(subtitle) ); + std::string details = getString("Details", args); + getChild<LLUICtrl>("user_details")->setValue( LLSD(details) ); + + // Delete the request object as it has been satisfied + delete mPropertiesRequest; + mPropertiesRequest = NULL; +} + void LLInspectAvatar::nameUpdatedCallback( const LLUUID& id, const std::string& first, @@ -114,14 +247,14 @@ void LLInspectAvatar::nameUpdatedCallback( void LLInspectAvatar::onClickAddFriend() { std::string name; - name.assign(getFirstName()); + name.assign(mFirstName); name.append(" "); - name.append(getLastName()); + name.append(mLastName); - LLAvatarActions::requestFriendshipDialog(getAvatarID(), name); + LLAvatarActions::requestFriendshipDialog(mAvatarID, name); } void LLInspectAvatar::onClickViewProfile() { - LLAvatarActions::showProfile(getAvatarID()); + LLAvatarActions::showProfile(mAvatarID); } diff --git a/indra/newview/llinspectavatar.h b/indra/newview/llinspectavatar.h index 05b0d6fe20..8d490382d2 100644 --- a/indra/newview/llinspectavatar.h +++ b/indra/newview/llinspectavatar.h @@ -1,8 +1,5 @@ /** * @file llinspectavatar.h - * @brief Avatar Inspector, a small information window used when clicking - * on avatar names in the 2D UI and in the ambient inspector widget for - * the 3D world. * * $LicenseInfo:firstyear=2009&license=viewergpl$ * @@ -37,32 +34,45 @@ #include "llfloater.h" +struct LLAvatarData; +class LLFetchAvatarData; + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. class LLInspectAvatar : public LLFloater { friend class LLFloaterReg; public: - // key is the UUID of avatar for whom to show information - // *TODO: Needs to take a spawn location + // avatar_id - Avatar ID for which to show information + // Inspector will be positioned relative to current mouse position LLInspectAvatar(const LLSD& avatar_id); virtual ~LLInspectAvatar(); /*virtual*/ BOOL postBuild(void); + /*virtual*/ void draw(); + + // Because floater is single instance, need to re-parse data on each spawn + // (for example, inspector about same avatar but in different position) + /*virtual*/ void onOpen(const LLSD& avatar_id); - void setAvatarID(const LLUUID &avatar_id); + // Inspectors close themselves when they lose focus + /*virtual*/ void onFocusLost(); - const LLUUID& getAvatarID() const { return mAvatarID; } - const std::string& getFirstName() const { return mFirstName; } - const std::string& getLastName() const { return mLastName; } + // Update view based on information from avatar properties processor + void processAvatarData(LLAvatarData* data); private: - // Update widgets, including avatar name, buttons enabled, etc. - // Used after avatar id changes. - void refresh(); + // Make network requests for all the data to display in this view. + // Used on construction and if avatar id changes. + void requestUpdate(); + // Button callbacks void onClickAddFriend(); void onClickViewProfile(); + // Callback for gCacheName to look up avatar name void nameUpdatedCallback( const LLUUID& id, const std::string& first, @@ -74,6 +84,10 @@ private: // Need avatar name information to spawn friend add request std::string mFirstName; std::string mLastName; + // an in-flight request for avatar properties from LLAvatarPropertiesProcessor + // is represented by this object + LLFetchAvatarData* mPropertiesRequest; + LLFrameTimer mCloseTimer; }; diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index f54a614f62..1d9220cf3d 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -42,6 +42,7 @@ #include "llstring.h" #include "lltrans.h" #include "lluictrlfactory.h" +#include "lltooltip.h" // newview includes #include "llinventorymodel.h" @@ -290,12 +291,13 @@ void LLLocationInputCtrl::hideList() focusTextEntry(); } -BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { // Let the buttons show their tooltips. if (LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen) && !msg.empty()) { - if (mList->getRect().pointInRect(x, y)) { + if (mList->getRect().pointInRect(x, y)) + { S32 loc_x, loc_y; //x,y - contain coordinates related to the location input control, but without taking the expanded list into account //So we have to convert it again into local coordinates of mList @@ -307,7 +309,7 @@ BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* LLSD value = item->getValue(); if (value.has("tooltip")) { - msg = value["tooltip"].asString(); + LLToolTipMgr::instance().show(value["tooltip"]); } } } @@ -315,15 +317,14 @@ BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* return TRUE; } - msg = LLUI::sShowXUINames ? getShowNamesToolTip() : ""; - return mTextEntry->getRect().pointInRect(x, y); + return FALSE; } BOOL LLLocationInputCtrl::handleKeyHere(KEY key, MASK mask) { BOOL result = LLComboBox::handleKeyHere(key, mask); - if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0) + if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0 && !mList->getVisible()) { showList(); } diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 3c43e1a321..6edae9a9e2 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, std::string& msg, LLRect& sticky_rect); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index d1d112c4bf..14a8b7cb59 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -49,7 +49,7 @@ #include "llbutton.h" #include "llviewercontrol.h" #include "llcriticaldamp.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llfloatertools.h" #include "llselectmgr.h" #include "llstatusbar.h" diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index cc2531d139..2153f77336 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -379,7 +379,7 @@ BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) } else if (gSavedSettings.getBOOL("SnapToMouseCursor")) { - LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY); + LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); x = mouse_pos.mX; y = mouse_pos.mY; } diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp index 3c7716e9c2..b3aa67733b 100644 --- a/indra/newview/llmemoryview.cpp +++ b/indra/newview/llmemoryview.cpp @@ -32,11 +32,11 @@ #include "llviewerprecompiledheaders.h" -#include "indra_constants.h" #include "llmemoryview.h" #include "llappviewer.h" #include "llallocator_heap_profile.h" +#include "llgl.h" // LLGLSUIDefault #include "llviewerwindow.h" #include "llviewercontrol.h" diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index c283b3a05f..69cebcfb5e 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -62,6 +62,8 @@ #include "llfavoritesbar.h" #include "llagentui.h" +#include <boost/regex.hpp> + //-- LLTeleportHistoryMenuItem ----------------------------------------------- /** @@ -300,8 +302,8 @@ void LLNavigationBar::onSearchCommit() if(!search_query.empty()) { LLSearchHistory::getInstance()->addEntry(search_query); - invokeSearch(mSearchComboBox->getValue().asString()); } + invokeSearch(search_query); } void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 7b0b0c2fb7..5e65f2244d 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -35,15 +35,19 @@ #include "llnetmap.h" +// Library includes (should move below) #include "indra_constants.h" #include "llmath.h" #include "llfloaterreg.h" #include "llfocusmgr.h" +#include "lllocalcliprect.h" #include "llrender.h" #include "llui.h" +#include "lltooltip.h" #include "llglheaders.h" +// Viewer includes #include "llagent.h" #include "llappviewer.h" // for gDisconnected #include "llcallingcard.h" // LLAvatarTracker @@ -286,7 +290,7 @@ void LLNetMap::draw() S32 local_mouse_x; S32 local_mouse_y; //localMouse(&local_mouse_x, &local_mouse_y); - LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); + LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mClosestAgentToCursor.setNull(); F32 closest_dist = F32_MAX; @@ -496,9 +500,8 @@ BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks) return TRUE; } -BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ) +BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen ) { - BOOL handled = FALSE; if (gDisconnected) { return FALSE; @@ -530,19 +533,23 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec msg = mToolTipMsg; LLStringUtil::format(msg, args); + LLRect sticky_rect; // set sticky_rect if (region) { S32 SLOP = 4; localPointToScreen( x - SLOP, y - SLOP, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; - sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; + &(sticky_rect.mLeft), &(sticky_rect.mBottom) ); + sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; + sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP; } - - handled = TRUE; - return handled; + + LLToolTipMgr::instance().show(LLToolTipParams() + .message(msg) + .sticky_rect(sticky_rect)); + + return TRUE; } diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index a673ea3f57..7598154480 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -67,7 +67,7 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ); + /*virtual*/ BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen ); void setScale( F32 scale ); void setRotateMap( BOOL b ) { mRotateMap = b; } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index fd3519bf4b..ba383a8dee 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -35,7 +35,7 @@ #include "llagent.h" #include "llavataractions.h" -#include "llavatarconstants.h" +#include "llavatarconstants.h" // AVATAR_ONLINE #include "llcallingcard.h" #include "llcombobox.h" #include "llimview.h" @@ -131,7 +131,8 @@ LLPanelAvatarNotes::LLPanelAvatarNotes() void LLPanelAvatarNotes::updateData() { - LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_NOTES); + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarNotesRequest(getAvatarId()); } BOOL LLPanelAvatarNotes::postBuild() @@ -356,8 +357,10 @@ void LLPanelAvatarProfile::updateData() { if (getAvatarId().notNull()) { - LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_PROPERTIES); - LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_GROUPS); + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarPropertiesRequest(getAvatarId()); + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarGroupsRequest(getAvatarId()); } } @@ -486,55 +489,13 @@ void LLPanelAvatarProfile::fillOnlineStatus(const LLAvatarData* avatar_data) void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) { - std::string caption_text = avatar_data->caption_text; - if(caption_text.empty()) - { - LLStringUtil::format_map_t args; - caption_text = getString("CaptionTextAcctInfo"); - BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED); - BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED); - BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED); // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations - - const char* ACCT_TYPE[] = { - "AcctTypeResident", - "AcctTypeTrial", - "AcctTypeCharterMember", - "AcctTypeEmployee" - }; - U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, (U8)(LL_ARRAY_SIZE(ACCT_TYPE)-1)); - args["[ACCTTYPE]"] = getString(ACCT_TYPE[caption_index]); - - std::string payment_text = " "; - const S32 DEFAULT_CAPTION_LINDEN_INDEX = 3; - if(caption_index != DEFAULT_CAPTION_LINDEN_INDEX) - { - if(transacted) - { - payment_text = "PaymentInfoUsed"; - } - else if (identified) - { - payment_text = "PaymentInfoOnFile"; - } - else - { - payment_text = "NoPaymentInfoOnFile"; - } - args["[PAYMENTINFO]"] = getString(payment_text); - - std::string age_text = age_verified ? "AgeVerified" : "NotAgeVerified"; - // Do not display age verification status at this time - //args["[[AGEVERIFICATION]]"] = mPanelSecondLife->getString(age_text); - args["[AGEVERIFICATION]"] = " "; - } - else - { - args["[PAYMENTINFO]"] = " "; - args["[AGEVERIFICATION]"] = " "; - } - LLStringUtil::format(caption_text, args); - } - + LLStringUtil::format_map_t args; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + // *NOTE: AVATAR_AGEVERIFIED not currently getting set in + // dataserver/lldataavatar.cpp for privacy considerations + args["[AGEVERIFICATION]"] = ""; + std::string caption_text = getString("CaptionTextAcctInfo", args); childSetValue("acc_status_text", caption_text); } diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index f7ca54c732..bde6d1cf6c 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -159,7 +159,7 @@ void LLPanelPick::requestData() { mDataReceived = FALSE; LLAvatarPropertiesProcessor::instance().addObserver(mCreatorId, this); - LLAvatarPropertiesProcessor::instance().sendDataRequest(mCreatorId, APT_PICK_INFO, &mPickId); + LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorId, mPickId); } void LLPanelPick::init(LLPickData *pick_data) @@ -335,7 +335,7 @@ void LLPanelPick::sendUpdate() mDataReceived = FALSE; LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this); - LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO); + LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); } diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index c34038c672..d374d24316 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -88,7 +88,7 @@ void* LLPanelPicks::create(void* data /* = NULL */) void LLPanelPicks::updateData() { - LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_PICKS); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); } void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) @@ -447,7 +447,7 @@ const std::string LLPickItem::getDescription() void LLPickItem::update() { mNeedData = true; - LLAvatarPropertiesProcessor::instance().sendDataRequest(mCreatorID, APT_PICK_INFO, &mPickID); + LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID); mNeedData = false; } diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index ec1c10d8c9..457109f869 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -894,7 +894,7 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& global_pos) pick_data.sort_order = 0; pick_data.enabled = TRUE; - LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO); + LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); } // virtual diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp index c903f40f3f..29d31e8b56 100644 --- a/indra/newview/llsearchcombobox.cpp +++ b/indra/newview/llsearchcombobox.cpp @@ -152,19 +152,16 @@ void LLSearchComboBox::onSelectionCommit() { std::string search_query = getSimple(); LLStringUtil::trim(search_query); - if(search_query.empty()) - { - mTextEntry->setText(search_query); - setControlValue(search_query); - - return; - } - remove(search_query); - add(search_query, ADD_TOP); mTextEntry->setText(search_query); setControlValue(search_query); + if(!search_query.empty()) + { + remove(search_query); + add(search_query, ADD_TOP); + } + LLUICtrl::onCommit(); } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 32fe996125..b25331e439 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -393,7 +393,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, } // Collect all of the objects - LLDynamicArray<LLViewerObject*> objects; + std::vector<LLViewerObject*> objects; root->addThisAndNonJointChildren(objects); addAsFamily(objects, add_to_end); @@ -439,7 +439,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV BOOL send_to_sim) { // Collect all of the objects, children included - LLDynamicArray<LLViewerObject*> objects; + std::vector<LLViewerObject*> objects; //clear primary object (no primary object) mSelectedObjects->mPrimaryObject = NULL; @@ -563,7 +563,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s if(!object->isSelected()) return; // Collect all of the objects, and remove them - LLDynamicArray<LLViewerObject*> objects; + std::vector<LLViewerObject*> objects; if (include_entire_object) { @@ -779,47 +779,55 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face) { - // Always blitz hover list when setting - mHoverObjects->deleteAllNodes(); - if (!objectp) { + mHoverObjects->deleteAllNodes(); return NULL; } // Can't select yourself if (objectp->mID == gAgentID) { + mHoverObjects->deleteAllNodes(); return NULL; } // Can't select land if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) { + mHoverObjects->deleteAllNodes(); return NULL; } - // Collect all of the objects - LLDynamicArray<LLViewerObject*> objects; objectp = objectp->getRootEdit(); - objectp->addThisAndNonJointChildren(objects); - for (std::vector<LLViewerObject*>::iterator iter = objects.begin(); - iter != objects.end(); ++iter) + // is the requested object the same as the existing hover object root? + // NOTE: there is only ever one linked set in mHoverObjects + if (mHoverObjects->getFirstRootObject() != objectp) { - LLViewerObject* cur_objectp = *iter; - LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); - nodep->selectTE(face, TRUE); - mHoverObjects->addNodeAtEnd(nodep); + // Collect all of the objects + std::vector<LLViewerObject*> objects; + objectp = objectp->getRootEdit(); + objectp->addThisAndNonJointChildren(objects); + + for (std::vector<LLViewerObject*>::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* cur_objectp = *iter; + LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); + nodep->selectTE(face, TRUE); + mHoverObjects->addNodeAtEnd(nodep); + } + + requestObjectPropertiesFamily(objectp); } - requestObjectPropertiesFamily(objectp); return mHoverObjects; } LLSelectNode *LLSelectMgr::getHoverNode() { - return getHoverObjects()->getFirstRootNode(); + return mHoverObjects->getFirstRootNode(); } void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) @@ -1286,7 +1294,7 @@ void LLSelectMgr::promoteSelectionToRoot() //----------------------------------------------------------------------------- void LLSelectMgr::demoteSelectionToIndividuals() { - LLDynamicArray<LLViewerObject*> objects; + std::vector<LLViewerObject*> objects; for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); iter != getSelection()->root_end(); iter++) @@ -1295,7 +1303,7 @@ void LLSelectMgr::demoteSelectionToIndividuals() object->addThisAndNonJointChildren(objects); } - if (objects.getLength()) + if (!objects.empty()) { deselectAll(); for (std::vector<LLViewerObject*>::iterator iter = objects.begin(); @@ -4480,7 +4488,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use return (node->getObject() && node->getObject()->mID == mID); } } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func); + LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func); if (node) { diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index c41a86e355..08c2783746 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -411,6 +411,7 @@ public: LLObjectSelectionHandle selectHighlightedObjects(); LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1); + LLSelectNode *getHoverNode(); void highlightObjectOnly(LLViewerObject *objectp); void highlightObjectAndFamily(LLViewerObject *objectp); @@ -445,14 +446,11 @@ public: //////////////////////////////////////////////////////////////// // Selection accessors //////////////////////////////////////////////////////////////// - LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } LLObjectSelectionHandle getSelection() { return mSelectedObjects; } // right now this just renders the selection with root/child colors instead of a single color LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } - LLSelectNode *getHoverNode(); - //////////////////////////////////////////////////////////////// // Grid manipulation //////////////////////////////////////////////////////////////// diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 7ddbf0a744..98428bf0f7 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -154,6 +154,8 @@ void LLSysWellWindow::toggleWindow() getDockTongue(), LLDockControl::TOP, isDocked())); } setVisible(!getVisible()); + //set window in foreground + setFocus(getVisible()); } //--------------------------------------------------------------------------------- @@ -179,7 +181,7 @@ void LLSysWellWindow::setVisible(BOOL visible) if(mChannel) mChannel->setShowToasts(!visible); - LLFloater::setVisible(visible); + LLDockableFloater::setVisible(visible); } //--------------------------------------------------------------------------------- @@ -329,11 +331,28 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) //--------------------------------------------------------------------------------- LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : - LLScrollingPanel(LLPanel::Params()), mParent(parent) + LLScrollingPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL); - mChiclet = getChild<LLIMChiclet>("chiclet"); + // Choose which of the pre-created chiclets (IM/group) to use. + // The other one gets hidden. + + LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId); + switch (im_chiclet_type) + { + case LLIMChiclet::TYPE_GROUP: + mChiclet = getChild<LLIMChiclet>("group_chiclet"); + childSetVisible("p2p_chiclet", false); + break; + case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway + case LLIMChiclet::TYPE_IM: + mChiclet = getChild<LLIMChiclet>("p2p_chiclet"); + childSetVisible("group_chiclet", false); + break; + } + + // Initialize chiclet. mChiclet->setCounter(chicletCounter); mChiclet->setSessionId(sessionId); mChiclet->setIMSessionName(name); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index ef0974b428..d76147b489 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -69,6 +69,7 @@ public: virtual void setVisible(BOOL visible); void adjustWindowPosition(); void toggleWindow(); + /*virtua*/BOOL canClose() { return FALSE; } // Handlers void onItemClick(LLSysWellItem* item); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 70a8ab9f61..9da2446354 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -43,7 +43,7 @@ #include "llimageworker.h" #include "llrender.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llselectmgr.h" #include "lltexlayer.h" #include "lltexturecache.h" @@ -662,16 +662,20 @@ void LLTextureView::draw() #if 1 if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard)) { - LLViewerObject *objectp = gHoverView->getLastHoverObject(); - if (objectp) + LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode(); + if (hover_node) { - S32 tex_count = objectp->getNumTEs(); - for (S32 i = 0; i < tex_count; i++) + LLViewerObject *objectp = hover_node->getObject(); + if (objectp) { - if (imagep == objectp->getTEImage(i)) + S32 tex_count = objectp->getNumTEs(); + for (S32 i = 0; i < tex_count; i++) { - pri += 2*HIGH_PRIORITY; - break; + if (imagep == objectp->getTEImage(i)) + { + pri += 2*HIGH_PRIORITY; + break; + } } } } diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp index 7b058e9efa..ceb1358d1c 100644 --- a/indra/newview/lltool.cpp +++ b/indra/newview/lltool.cpp @@ -65,6 +65,20 @@ LLTool::~LLTool() } } +BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down) +{ + // This is necessary to force clicks in the world to cause edit + // boxes that might have keyboard focus to relinquish it, and hence + // cause a commit to update their value. JC + if (down) + { + gFocusMgr.setKeyboardFocus(NULL); + } + + return LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down); +} + + BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask) { if (gDebugClicks) @@ -139,7 +153,7 @@ BOOL LLTool::handleMiddleMouseUp(S32 x, S32 y, MASK mask) return FALSE; } -BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { // by default, didn't handle it // llinfos << "LLTool::handleToolTip" << llendl; diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h index f954a8c243..bef4a2e1fd 100644 --- a/indra/newview/lltool.h +++ b/indra/newview/lltool.h @@ -55,6 +55,7 @@ public: virtual BOOL isView() const { return FALSE; } // Virtual functions inherited from LLMouseHandler + virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); @@ -65,9 +66,7 @@ public: virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); - - virtual EShowToolTip getShowToolTip() { return SHOW_ALWAYS; }; // tools should permit tips even when the mouse is down, as that's pretty normal for tools + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); // Return FALSE to allow context menu to be shown. virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index c58457d599..b35208cd03 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -56,6 +56,7 @@ #include "llpreviewnotecard.h" #include "llselectmgr.h" #include "lltoolmgr.h" +#include "lltooltip.h" #include "lltrans.h" #include "llui.h" #include "llviewertexturelist.h" @@ -758,12 +759,13 @@ BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask) return FALSE; } -BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen) +BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { if (!mToolTipMsg.empty()) { - msg = mToolTipMsg; - //*sticky_rect_screen = gViewerWindow->getWindowRect(); + LLToolTipMgr::instance().show(LLToolTipParams() + .message(mToolTipMsg) + .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" ))); return TRUE; } return FALSE; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index f9e5bec143..c9fef26b58 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -57,7 +57,7 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleKey(KEY key, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); virtual void onMouseCaptureLost(); virtual void handleDeselect(); diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index 297cf2c667..9400840bdf 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -45,7 +45,7 @@ #include "llbutton.h" #include "llviewercontrol.h" #include "lldrawable.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llhudmanager.h" #include "llfloatertools.h" #include "llselectmgr.h" @@ -287,12 +287,12 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask) BOOL success = LLViewerCamera::getInstance()->projectPosAgentToScreen(focus_pos, mouse_pos); if (success) { - LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY); + LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); } } else if (mMouseSteering) { - LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY); + LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY); } else { @@ -302,7 +302,7 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask) else { // not a valid zoomable object - LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY); + LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY); } // calls releaseMouse() internally diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index abadd251c1..b7a97562bd 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -134,7 +134,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) if (!gAgent.leftButtonGrabbed()) { // can grab transparent objects (how touch event propagates, scripters rely on this) - gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE); } return TRUE; } @@ -996,7 +996,7 @@ void LLToolGrab::onMouseCaptureLost() // ...move cursor "naturally", as if it had moved when hidden S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX; S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY; - LLUI::setCursorPositionScreen(x, y); + LLUI::setMousePositionScreen(x, y); } else if (mHasMoved) { @@ -1006,13 +1006,13 @@ void LLToolGrab::onMouseCaptureLost() LLCoordGL gl_point; if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point)) { - LLUI::setCursorPositionScreen(gl_point.mX, gl_point.mY); + LLUI::setMousePositionScreen(gl_point.mX, gl_point.mY); } } else { // ...move cursor back to click position - LLUI::setCursorPositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY); + LLUI::setMousePositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY); } gViewerWindow->showCursor(); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 235d4acf9d..d6297c30c7 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -45,7 +45,7 @@ #include "llfloaterland.h" #include "llfloaterreg.h" #include "llfloaterscriptdebug.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llmenugl.h" @@ -55,6 +55,7 @@ #include "lltoolgrab.h" #include "lltoolmgr.h" #include "lltoolselect.h" +#include "lltrans.h" #include "llviewercamera.h" #include "llviewerparcelmedia.h" #include "llviewermenu.h" @@ -68,6 +69,7 @@ #include "llworld.h" #include "llui.h" #include "llweb.h" +#include "llinspectavatar.h" extern void handle_buy(void*); @@ -91,7 +93,7 @@ LLToolPie::LLToolPie() BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { //left mouse down always picks transparent - gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); + gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE); mGrabMouseButtonDown = TRUE; return TRUE; } @@ -108,7 +110,7 @@ void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) { // don't pick transparent so users can't "pay" transparent objects - gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE); + gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE); // claim not handled so UI focus stays same return FALSE; } @@ -463,31 +465,13 @@ void LLToolPie::selectionPropertiesReceived() BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { - /* - // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag - // gets started. - const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() ); - const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; - // ...normal modes can only yaw - if (x < ROTATE_H_MARGIN) - { - gAgent.yaw(rotate_angle); - mMouseOutsideSlop = TRUE; - } - else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) - { - gAgent.yaw(-rotate_angle); - mMouseOutsideSlop = TRUE; - } - */ + mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE); // FIXME: This was in the pluginapi branch, but I don't think it's correct. // gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - LLViewerObject *object = NULL; LLViewerObject *parent = NULL; - object = gViewerWindow->getHoverPick().getObject(); + LLViewerObject *object = mHoverPick.getObject(); if (object) { @@ -500,7 +484,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) gViewerWindow->setCursor(cursor); lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; } - else if (handle_media_hover(gViewerWindow->getHoverPick())) + else if (handle_media_hover(mHoverPick)) { // cursor set by media object lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; @@ -553,7 +537,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) // same object anymore. gViewerWindow->setCursor(UI_CURSOR_ARROW); // Make sure the hover-picked object is ignored. - gHoverView->resetLastHoverObject(); + //gToolTipView->resetLastHoverObject(); break; default: break; @@ -584,41 +568,439 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) else if (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()) { - // Hit an object - // HACK: Call the last hit position the point we hit on the object - //gLastHitPosGlobal += gLastHitObjectOffset; handle_go_to(); return TRUE; } } return FALSE; +} - /* JC - don't do go-there, because then double-clicking on physical - objects gets you into trouble. +//FIXME - RN: get this in LLToolSelectLand too or share some other way? +const char* DEFAULT_DESC = "(No Description)"; - // If double-click on object or land, go there. - LLViewerObject *object = gViewerWindow->getLastPick().getObject(); - if (object) +BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, std::string& msg, LLRect& sticky_rect_screen) +{ + if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE; + if (!mHoverPick.isValid()) return TRUE; + + LLViewerObject* hover_object = mHoverPick.getObject(); + + // update hover object and hover parcel + LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace); + + if (mHoverPick.mPickType == LLPickInfo::PICK_LAND) + { + LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal ); + } + + std::string tooltip_msg; + std::string line; + + if ( hover_object ) { - if (object->isAvatar()) + if ( hover_object->isHUDAttachment() ) { - LLFloaterAvatarInfo::showFromAvatar(object->getID()); + // no hover tips for HUD elements, since they can obscure + // what the HUD is displaying + return TRUE; + } + + if ( hover_object->isAttachment() ) + { + // get root of attachment then parent, which is avatar + LLViewerObject* root_edit = hover_object->getRootEdit(); + if (!root_edit) + { + // Strange parenting issue, don't show any text + return TRUE; + } + hover_object = (LLViewerObject*)root_edit->getParent(); + if (!hover_object) + { + // another strange parenting issue, bail out + return TRUE; + } + } + + line.clear(); + if (hover_object->isAvatar()) + { + // only show tooltip if inspector not already open + if (!LLFloaterReg::instanceVisible("inspect_avatar")) + { + std::string avatar_name; + LLNameValue* firstname = hover_object->getNVPair("FirstName"); + LLNameValue* lastname = hover_object->getNVPair("LastName"); + if (firstname && lastname) + { + avatar_name = llformat("%s %s", firstname->getString(), lastname->getString()); + } + else + { + avatar_name = LLTrans::getString("TooltipPerson"); + } + LLToolTipParams params; + params.message(avatar_name); + params.image.name("Info"); + params.sticky_rect(gViewerWindow->getVirtualWorldViewRect()); + params.click_callback(boost::bind(showAvatarInspector, hover_object->getID())); + LLToolTipMgr::instance().show(params); + } } else { - handle_go_to(NULL); + // + // We have hit a regular object (not an avatar or attachment) + // + + // + // Default prefs will suppress display unless the object is interactive + // + BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip"); + + LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode(); + if (nodep) + { + line.clear(); + if (nodep->mName.empty()) + { + line.append(LLTrans::getString("TooltipNoName")); + } + else + { + line.append( nodep->mName ); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + + if (!nodep->mDescription.empty() + && nodep->mDescription != DEFAULT_DESC) + { + tooltip_msg.append( nodep->mDescription ); + tooltip_msg.push_back('\n'); + } + + // Line: "Owner: James Linden" + line.clear(); + line.append(LLTrans::getString("TooltipOwner") + " "); + + if (nodep->mValid) + { + LLUUID owner; + std::string name; + if (!nodep->mPermissions->isGroupOwned()) + { + owner = nodep->mPermissions->getOwner(); + if (LLUUID::null == owner) + { + line.append(LLTrans::getString("TooltipPublic")); + } + else if(gCacheName->getFullName(owner, name)) + { + line.append(name); + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + } + else + { + std::string name; + owner = nodep->mPermissions->getGroup(); + if (gCacheName->getGroupName(owner, name)) + { + line.append(name); + line.append(LLTrans::getString("TooltipIsGroup")); + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + } + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + + // Build a line describing any special properties of this object. + LLViewerObject *object = hover_object; + LLViewerObject *parent = (LLViewerObject *)object->getParent(); + + if (object && + (object->usePhysics() || + object->flagScripted() || + object->flagHandleTouch() || (parent && parent->flagHandleTouch()) || + object->flagTakesMoney() || (parent && parent->flagTakesMoney()) || + object->flagAllowInventoryAdd() || + object->flagTemporary() || + object->flagPhantom()) ) + { + line.clear(); + if (object->flagScripted()) + { + line.append(LLTrans::getString("TooltipFlagScript") + " "); + } + + if (object->usePhysics()) + { + line.append(LLTrans::getString("TooltipFlagPhysics") + " "); + } + + if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) + { + line.append(LLTrans::getString("TooltipFlagTouch") + " "); + suppressObjectHoverDisplay = FALSE; // Show tip + } + + if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ) + { + line.append(LLTrans::getString("TooltipFlagL$") + " "); + suppressObjectHoverDisplay = FALSE; // Show tip + } + + if (object->flagAllowInventoryAdd()) + { + line.append(LLTrans::getString("TooltipFlagDropInventory") + " "); + suppressObjectHoverDisplay = FALSE; // Show tip + } + + if (object->flagPhantom()) + { + line.append(LLTrans::getString("TooltipFlagPhantom") + " "); + } + + if (object->flagTemporary()) + { + line.append(LLTrans::getString("TooltipFlagTemporary") + " "); + } + + if (object->usePhysics() || + object->flagHandleTouch() || + (parent && parent->flagHandleTouch()) ) + { + line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " "); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + } + + // Free to copy / For Sale: L$ + line.clear(); + if (nodep->mValid) + { + BOOL for_copy = nodep->mPermissions->getMaskEveryone() & PERM_COPY && object->permCopy(); + BOOL for_sale = nodep->mSaleInfo.isForSale() && + nodep->mPermissions->getMaskOwner() & PERM_TRANSFER && + (nodep->mPermissions->getMaskOwner() & PERM_COPY || + nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY); + if (for_copy) + { + line.append(LLTrans::getString("TooltipFreeToCopy")); + suppressObjectHoverDisplay = FALSE; // Show tip + } + else if (for_sale) + { + LLStringUtil::format_map_t args; + args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice()); + line.append(LLTrans::getString("TooltipForSaleL$", args)); + suppressObjectHoverDisplay = FALSE; // Show tip + } + else + { + // Nothing if not for sale + // line.append("Not for sale"); + } + } + else + { + LLStringUtil::format_map_t args; + args["[MESSAGE]"] = LLTrans::getString("RetrievingData"); + line.append(LLTrans::getString("TooltipForSaleMsg", args)); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + + if (!suppressObjectHoverDisplay) + { + LLToolTipMgr::instance().show(tooltip_msg); + } + } } } - else if (!gLastHitPosGlobal.isExactlyZero()) + else if ( mHoverPick.mPickType == LLPickInfo::PICK_LAND ) { - handle_go_to(NULL); + // + // Do not show hover for land unless prefs are set to allow it. + // + + if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE; + + // Didn't hit an object, but since we have a land point we + // must be hovering over land. + + LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); + LLUUID owner; + S32 width = 0; + S32 height = 0; + + if ( hover_parcel ) + { + owner = hover_parcel->getOwnerID(); + width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth()); + height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight()); + } + + // Line: "Land" + line.clear(); + line.append(LLTrans::getString("TooltipLand")); + if (hover_parcel) + { + line.append(hover_parcel->getName()); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + + // Line: "Owner: James Linden" + line.clear(); + line.append(LLTrans::getString("TooltipOwner") + " "); + + if ( hover_parcel ) + { + std::string name; + if (LLUUID::null == owner) + { + line.append(LLTrans::getString("TooltipPublic")); + } + else if (hover_parcel->getIsGroupOwned()) + { + if (gCacheName->getGroupName(owner, name)) + { + line.append(name); + line.append(LLTrans::getString("TooltipIsGroup")); + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + } + else if(gCacheName->getFullName(owner, name)) + { + line.append(name); + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + } + else + { + line.append(LLTrans::getString("RetrievingData")); + } + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + + // Line: "no fly, not safe, no build" + + // Don't display properties for your land. This is just + // confusing, because you can do anything on your own land. + if ( hover_parcel && owner != gAgent.getID() ) + { + S32 words = 0; + + line.clear(); + // JC - Keep this in the same order as the checkboxes + // on the land info panel + if ( !hover_parcel->getAllowModify() ) + { + if ( hover_parcel->getAllowGroupModify() ) + { + line.append(LLTrans::getString("TooltipFlagGroupBuild")); + } + else + { + line.append(LLTrans::getString("TooltipFlagNoBuild")); + } + words++; + } + + if ( !hover_parcel->getAllowTerraform() ) + { + if (words) line.append(", "); + line.append(LLTrans::getString("TooltipFlagNoEdit")); + words++; + } + + if ( hover_parcel->getAllowDamage() ) + { + if (words) line.append(", "); + line.append(LLTrans::getString("TooltipFlagNotSafe")); + words++; + } + + // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04 + if ( !hover_parcel->getAllowFly() ) + { + if (words) line.append(", "); + line.append(LLTrans::getString("TooltipFlagNoFly")); + words++; + } + + if ( !hover_parcel->getAllowOtherScripts() ) + { + if (words) line.append(", "); + if ( hover_parcel->getAllowGroupScripts() ) + { + line.append(LLTrans::getString("TooltipFlagGroupScripts")); + } + else + { + line.append(LLTrans::getString("TooltipFlagNoScripts")); + } + + words++; + } + + if (words) + { + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + } + } + + if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE)) + { + LLStringUtil::format_map_t args; + args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice()); + line = LLTrans::getString("TooltipForSaleL$", args); + tooltip_msg.append(line); + tooltip_msg.push_back('\n'); + } + LLToolTipMgr::instance().show(tooltip_msg); } + return TRUE; - */ } +// static +void LLToolPie::showAvatarInspector(const LLUUID& avatar_id) +{ + LLSD params; + params["avatar_id"] = avatar_id; + if (LLToolTipMgr::instance().toolTipVisible()) + { + LLRect rect = LLToolTipMgr::instance().getToolTipRect(); + params["pos"]["x"] = rect.mLeft; + params["pos"]["y"] = rect.mTop; + } + + LLFloaterReg::showInstance("inspect_avatar", params); +} void LLToolPie::handleDeselect() { @@ -627,6 +1009,7 @@ void LLToolPie::handleDeselect() setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly } // remove temporary selection for pie menu + LLSelectMgr::getInstance()->setHoverObject(NULL); LLSelectMgr::getInstance()->validateSelection(); } diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index a55e435282..be6e539ffd 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -52,6 +52,7 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); virtual void render(); @@ -72,6 +73,7 @@ public: static void selectionPropertiesReceived(); + static void showAvatarInspector(const LLUUID& id); private: BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y); @@ -84,6 +86,7 @@ private: BOOL mGrabMouseButtonDown; BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region LLPickInfo mPick; + LLPickInfo mHoverPick; LLPointer<LLViewerObject> mClickActionObject; U8 mClickAction; LLSafeHandle<LLObjectSelection> mLeftClickSelection; diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp index 878ed0f9a9..9a92f2ae3f 100644 --- a/indra/newview/lltoolpipette.cpp +++ b/indra/newview/lltoolpipette.cpp @@ -40,6 +40,7 @@ #include "lltoolpipette.h" // Library includes +#include "lltooltip.h" // Viewer includes #include "llviewerobjectlist.h" @@ -92,15 +93,19 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask) return FALSE; } -BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen) +BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect &sticky_rect_screen) { if (mTooltipMsg.empty()) { return FALSE; } - // keep tooltip message up when mouse in this part of screen - sticky_rect_screen->setCenterAndSize(x, y, 20, 20); - msg = mTooltipMsg; + + LLRect sticky_rect; + sticky_rect.setCenterAndSize(x, y, 20, 20); + LLToolTipMgr::instance().show(LLToolTipParams() + .message(mTooltipMsg) + .sticky_rect(sticky_rect)); + return TRUE; } diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 3b6ebec67e..cce5b6ce54 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -56,7 +56,7 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen); // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 8e65c7e65e..6d2482d3f0 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1260,10 +1260,6 @@ void render_ui_2d() stop_glerror(); } gViewerWindow->draw(); - if (gDebugSelect) - { - gViewerWindow->drawPickBuffer(); - } // reset current origin for font rendering, in case of tiling render LLFontGL::sCurOrigin.set(0, 0); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c8f2e03903..1fc387027d 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -95,6 +95,7 @@ #include "llfloatersettingsdebug.h" #include "llfloatersnapshot.h" #include "llfloatertelehub.h" +#include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" #include "llfloatertools.h" #include "llfloatertos.h" @@ -207,6 +208,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("properties", "floater_inventory_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProperties>); LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>); + LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", + &LLFloaterReg::build<LLFloaterTestInspectors>); LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>); LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build<LLFloater>); LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index a06d913fd6..f033d66c1f 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -34,18 +34,17 @@ #include "llviewermedia.h" #include "llviewermediafocus.h" -#include "llhoverview.h" #include "llmimetypes.h" #include "llviewercontrol.h" #include "llviewertexture.h" #include "llviewerparcelmedia.h" #include "llviewerparcelmgr.h" -#include "llviewerwindow.h" #include "llversionviewer.h" #include "llviewertexturelist.h" #include "llpluginclassmedia.h" #include "llevent.h" // LLSimpleListener +#include "llnotifications.h" #include "lluuid.h" #include <boost/bind.hpp> // for SkinFolder listener diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 68a49662e7..9a61394383 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -180,10 +180,11 @@ public: /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }; /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { return FALSE; }; /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; /*virtual*/ const std::string& getName() const { return LLStringUtil::null; }; + /*virtual*/ BOOL isView() const { return FALSE; }; /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5536951ce6..338bb7ad7c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -134,7 +134,7 @@ #include "llmemoryview.h" #include "llgivemoney.h" #include "llgroupmgr.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llimage.h" @@ -582,6 +582,8 @@ void init_menus() gLoginMenuBarView->setBackgroundColor( color ); gMenuHolder->addChild(gLoginMenuBarView); + // tooltips are on top of EVERYTHING, including menus + gViewerWindow->getRootView()->sendChildToFront(gToolTipView); } /////////////////// @@ -1517,14 +1519,6 @@ class LLAdvancedSendTestIms : public view_listener_t } }; -class LLAdvancedAvatarInspector : public view_listener_t -{ - bool handleEvent(const LLSD& avatar_id) - { - LLFloaterReg::showInstance("inspect_avatar", avatar_id); - return true; - } -}; /////////////// // XUI NAMES // @@ -2905,7 +2899,7 @@ class LLObjectMute : public view_listener_t bool handle_go_to() { - // JAMESDEBUG try simulator autopilot + // try simulator autopilot std::vector<std::string> strings; std::string val; LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; @@ -6729,15 +6723,12 @@ BOOL enable_god_basic(void*) void toggle_show_xui_names(void *) { - BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames"); - - showXUINames = !showXUINames; - gSavedSettings.setBOOL("ShowXUINames", showXUINames); + gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames")); } BOOL check_show_xui_names(void *) { - return gSavedSettings.getBOOL("ShowXUINames"); + return gSavedSettings.getBOOL("DebugShowXUINames"); } class LLToolsSelectOnlyMyObjects : public view_listener_t @@ -7157,7 +7148,7 @@ class LLViewShowHoverTips : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLHoverView::sShowHoverTips = !LLHoverView::sShowHoverTips; + gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips")); return true; } }; @@ -7166,7 +7157,7 @@ class LLViewCheckShowHoverTips : public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = LLHoverView::sShowHoverTips; + bool new_value = gSavedSettings.getBOOL("ShowHoverTips"); return new_value; } }; @@ -7852,7 +7843,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames"); view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames"); view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs"); - view_listener_t::addMenu(new LLAdvancedAvatarInspector(), "Advanced.AvatarInspector"); // Advanced > Character > Grab Baked Texture view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1594a68f36..cf77f7e2b6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -582,9 +582,9 @@ void LLViewerObject::removeChild(LLViewerObject *childp) } } -void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects) +void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects) { - objects.put(this); + objects.push_back(this); for (child_list_t::iterator iter = mChildList.begin(); iter != mChildList.end(); iter++) { @@ -596,9 +596,9 @@ void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& obje } } -void LLViewerObject::addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects) +void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects) { - objects.put(this); + objects.push_back(this); // don't add any attachments when temporarily selecting avatar if (isAvatar()) { @@ -3475,7 +3475,7 @@ void LLViewerObject::setMediaType(U8 media_type) { if (!mMedia) { - // JAMESDEBUG TODO what if we don't have a media pointer? + // TODO what if we don't have a media pointer? } else if (mMedia->mMediaType != media_type) { @@ -3677,7 +3677,7 @@ void LLViewerObject::sendTEUpdate() const msg->addString("MediaURL", NULL); } - // JAMESDEBUG TODO send media type + // TODO send media type packTEMessage(msg); @@ -3688,7 +3688,7 @@ void LLViewerObject::sendTEUpdate() const void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) { LLPrimitive::setTE(te, texture_entry); -// JAMESDEBUG This doesn't work, don't get any textures. +// This doesn't work, don't get any textures. // if (mDrawable.notNull() && mDrawable->isVisible()) // { const LLUUID& image_id = getTE(te)->getID(); @@ -3865,7 +3865,7 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { - // JAMESDEBUG this might need work for media type + // this might need work for media type S32 retval = 0; const LLTextureEntry *tep = getTE(te); if (!tep) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index cda2c5114f..836e05728f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -242,8 +242,8 @@ public: virtual void removeChild(LLViewerObject *childp); const_child_list_t& getChildren() const { return mChildList; } S32 numChildren() const { return mChildList.size(); } - void addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects); - void addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects); + void addThisAndAllChildren(std::vector<LLViewerObject*>& objects); + void addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects); BOOL isChild(LLViewerObject *childp) const; BOOL isSeat() const; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index a8232e9a9d..acdc2c2513 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -49,7 +49,7 @@ #include "llagent.h" #include "pipeline.h" #include "llspatialpartition.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llworld.h" #include "llstring.h" #include "llhudtext.h" @@ -574,10 +574,14 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) // Slam priorities for textures that we care about (hovered, selected, and focused) // Hovered // Assumes only one level deep of parenting - objectp = gHoverView->getLastHoverObject(); - if (objectp) + LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); + if (nodep) { - objectp->boostTexturePriority(); + objectp = nodep->getObject(); + if (objectp) + { + objectp->boostTexturePriority(); + } } } diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index cb233085e5..86d51bfd4b 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -43,7 +43,7 @@ #include "message.h" #include "llviewermediafocus.h" #include "llviewerparcelmediaautoplay.h" -#include "llviewerwindow.h" +#include "llnotifications.h" #include "llfirstuse.h" #include "llpluginclassmedia.h" diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index ca3061e083..c5b09403cb 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1283,9 +1283,11 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag } -void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos) +void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos) { - LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos ); + //FIXME: only request parcel info when tooltip is shown + return; + /*LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos ); if (!region) { return; @@ -1317,7 +1319,7 @@ void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos) msg->addBOOL("SnapSelection", FALSE ); msg->sendReliable( region->getHost() ); - mHoverRequestResult = PARCEL_RESULT_NO_DATA; + mHoverRequestResult = PARCEL_RESULT_NO_DATA;*/ } diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 7373366cd7..275c79fd3b 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -217,7 +217,7 @@ public: void sendParcelDwellRequest(); // If the point is outside the current hover parcel, request more data - void requestHoverParcelProperties(const LLVector3d& pos_global); + void setHoverParcel(const LLVector3d& pos_global); bool canAgentBuyParcel(LLParcel*, bool forGroup) const; diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 5bb0c9a120..ceb2698223 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -658,45 +658,6 @@ void LLViewerTextEditor::makePristine() LLTextEditor::makePristine(); } -/////////////////////////////////////////////////////////////////// - -BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) -{ - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *viewp = *child_iter; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if( viewp->pointInView(local_x, local_y) - && viewp->getVisible() - && viewp->getEnabled() - && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) ) - { - return TRUE; - } - } - - if( mSegments.empty() ) - { - return TRUE; - } - - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment && cur_segment->getToolTip( msg ) ) - { - // Just use a slop area around the cursor - // Convert rect local to screen coordinates - S32 SLOP = 8; - localPointToScreen( - x - SLOP, y - SLOP, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; - sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; - } - return TRUE; -} - BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h index 2dfea4a589..100fa343af 100644 --- a/indra/newview/llviewertexteditor.h +++ b/indra/newview/llviewertexteditor.h @@ -68,7 +68,6 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 6ea1522b47..ec82f62a8b 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1810,7 +1810,7 @@ void LLViewerLODTexture::processTextureStats() // data than we need to. /*if (mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_PREVIEW || - mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? + mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // what about AVATAR_BAKED_SELF? { discard_level = 0; // full res } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 241c6fd511..e5d0e3ebb2 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -74,6 +74,7 @@ #include "lltimer.h" #include "timing.h" #include "llviewermenu.h" +#include "lltooltip.h" // newview includes #include "llagent.h" @@ -111,7 +112,7 @@ #include "llfontfreetype.h" #include "llgesturemgr.h" #include "llglheaders.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llhudmanager.h" #include "llhudview.h" #include "llimagebmp.h" @@ -208,22 +209,14 @@ extern BOOL gDebugClicks; extern BOOL gDisplaySwapBuffers; extern BOOL gDepthDirty; extern BOOL gResizeScreenTexture; -extern S32 gJamesInt; LLViewerWindow *gViewerWindow = NULL; - -BOOL gDebugSelect = FALSE; - -LLFrameTimer gMouseIdleTimer; LLFrameTimer gAwayTimer; LLFrameTimer gAwayTriggerTimer; -LLFrameTimer gAlphaFadeTimer; BOOL gShowOverlayTitle = FALSE; -BOOL gPickTransparent = TRUE; -BOOL gDebugFastUIRender = FALSE; LLViewerObject* gDebugRaycastObject = NULL; LLVector3 gDebugRaycastIntersection; LLVector2 gDebugRaycastTexCoord; @@ -234,7 +227,6 @@ S32 gDebugRaycastFaceHit; // HUD display lines in lower right BOOL gDisplayWindInfo = FALSE; BOOL gDisplayCameraPos = FALSE; -BOOL gDisplayNearestWater = FALSE; BOOL gDisplayFOV = FALSE; S32 CHAT_BAR_HEIGHT = 28; @@ -599,21 +591,6 @@ void LLViewerWindow::updateDebugText() // LLViewerWindow // -bool LLViewerWindow::shouldShowToolTipFor(LLMouseHandler *mh) -{ - if (mToolTip && mh) - { - LLMouseHandler::EShowToolTip showlevel = mh->getShowToolTip(); - - bool tool_tip_allowed = (showlevel == LLMouseHandler::SHOW_ALWAYS - || (showlevel == LLMouseHandler::SHOW_IF_NOT_BLOCKED - && !mToolTipBlocked)); - - return tool_tip_allowed; - } - return false; -} - BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down) { std::string buttonname; @@ -673,16 +650,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mWindow->releaseMouse(); // Indicate mouse was active - gMouseIdleTimer.reset(); - - // Hide tooltips on mousedown - mToolTipBlocked = down; - - // Also hide hover info on mousedown/mouseup - if (gHoverView) - { - gHoverView->cancelHover(); - } + LLUI::resetMouseIdleTimer(); // Don't let the user move the mouse out of the window until mouse up. if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() ) @@ -749,10 +717,6 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK if(LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) { - // This is necessary to force clicks in the world to cause edit - // boxes that might have keyboard focus to relinquish it, and hence - // cause a commit to update their value. JC - gFocusMgr.setKeyboardFocus(NULL); return TRUE; } } @@ -870,13 +834,10 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask // Save mouse point for access during idle() and display() - LLCoordGL prev_saved_mouse_point = mCurrentMousePoint; LLCoordGL mouse_point(x, y); saveLastMouse(mouse_point); - BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured - ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position - gMouseIdleTimer.reset(); + LLUI::resetMouseIdleTimer(); mWindow->showCursorFromMouseMove(); @@ -884,17 +845,6 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask { gAgent.clearAFK(); } - - if(mouse_actually_moved) - { - mToolTipBlocked = FALSE; - } - - // Activate the hover picker on mouse move. - if (gHoverView) - { - gHoverView->setTyping(FALSE); - } } void LLViewerWindow::handleMouseLeave(LLWindow *window) @@ -902,10 +852,6 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window) // Note: we won't get this if we have captured the mouse. llassert( gFocusMgr.getMouseCapture() == NULL ); mMouseInWindow = FALSE; - if (mToolTip) - { - mToolTip->setVisible( FALSE ); - } } BOOL LLViewerWindow::handleCloseRequest(LLWindow *window) @@ -1245,16 +1191,12 @@ LLViewerWindow::LLViewerWindow( mLeftMouseDown(FALSE), mMiddleMouseDown(FALSE), mRightMouseDown(FALSE), - mToolTip(NULL), - mToolTipBlocked(FALSE), mMouseInWindow( FALSE ), mLastMask( MASK_NONE ), mToolStored( NULL ), - mSuppressToolbox( FALSE ), mHideCursorPermanent( FALSE ), mCursorHidden(FALSE), mIgnoreActivate( FALSE ), - mHoverPick(), mResDirty(false), mStatesDirty(false), mIsFullscreenChecked(false), @@ -1479,7 +1421,7 @@ void LLViewerWindow::initBase() cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); gConsole = LLUICtrlFactory::create<LLConsole>(cp); - mRootView->addChild(gConsole); + getRootView()->addChild(gConsole); // optionally forward warnings to chat console/chat floater // for qa runs and dev builds @@ -1499,11 +1441,11 @@ void LLViewerWindow::initBase() debug_p.follows.flags(FOLLOWS_ALL); debug_p.visible(true); gDebugView = LLUICtrlFactory::create<LLDebugView>(debug_p); - mRootView->addChild(gDebugView); + getRootView()->addChild(gDebugView); // Add floater view at the end so it will be on top, and give it tab priority over others - mRootView->addChild(gFloaterView, -1); - mRootView->addChild(gSnapshotFloaterView); + getRootView()->addChild(gFloaterView, -1); + getRootView()->addChild(gSnapshotFloaterView); // notify above floaters! LLRect notify_rect = floater_view_rect; @@ -1513,28 +1455,18 @@ void LLViewerWindow::initBase() p.mouse_opaque(false); p.follows.flags(FOLLOWS_ALL); gNotifyBoxView = LLUICtrlFactory::create<LLNotifyBoxView> (p); - mRootView->addChild(gNotifyBoxView, -2); - - // Tooltips go above floaters - LLTextBox::Params params; - params.text("tool tip"); - params.name(params.text); - params.rect(LLRect (0, 1, 1, 0)); - params.h_pad(4); - params.v_pad(2); - params.text_color(LLUIColorTable::instance().getColor( "ToolTipTextColor" )); - params.border_color(LLUIColorTable::instance().getColor( "ToolTipBorderColor" )); - params.border_visible(false); - params.background_color(LLUIColorTable::instance().getColor( "ToolTipBgColor" )); - params.bg_visible(true); - params.font.style("NORMAL"); - params.border_drop_shadow_visible(true); - params.visible(false); - mToolTip = LLUICtrlFactory::create<LLTextBox> (params); + getRootView()->addChild(gNotifyBoxView, -2); + + // View for tooltips + LLToolTipView::Params hvp; + hvp.name("tooltip view"); + hvp.rect(full_window); + gToolTipView = LLUICtrlFactory::create<LLToolTipView>(hvp); + getRootView()->addChild(gToolTipView); // Add the progress bar view (startup view), which overrides everything mProgressView = new LLProgressView(full_window); - mRootView->addChild(mProgressView); + getRootView()->addChild(mProgressView); setShowProgress(FALSE); setProgressCancelButtonVisible(FALSE); } @@ -1560,13 +1492,6 @@ void LLViewerWindow::initWorldUI() LLBottomTray::getInstance()->reshape(rc.getWidth(),rc.getHeight(),FALSE); LLBottomTray::getInstance()->setRect(rc); - // View for hover information - LLHoverView::Params hvp; - hvp.name("gHoverview"); - hvp.rect(full_window); - gHoverView = LLUICtrlFactory::create<LLHoverView>(hvp); - mRootView->addChild(gHoverView); - // Pre initialize instance communicate instance; // currently needs to happen before initializing chat or IM LLFloaterReg::getInstance("communicate"); @@ -1584,7 +1509,7 @@ void LLViewerWindow::initWorldUI() mvp.rect(morph_view_rect); mvp.visible(false); gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp); - mRootView->addChild(gMorphView); + getRootView()->addChild(gMorphView); // Make space for nav bar. LLRect floater_view_rect = gFloaterView->getRect(); @@ -1674,6 +1599,9 @@ void LLViewerWindow::initWorldUI() // this allows not to see UI elements created while UI initializing after Alt+Tab was pressed during login. EXT-744. moveProgressViewToFront(); + + // tooltips are always on top + getRootView()->sendChildToFront(gToolTipView); } // Destroy the UI @@ -1691,10 +1619,6 @@ void LLViewerWindow::shutdownViews() gMorphView->setVisible(FALSE); } - // Delete Tool Tip - delete mToolTip; - mToolTip = NULL; - // Delete all child views. delete mRootView; mRootView = NULL; @@ -1702,7 +1626,7 @@ void LLViewerWindow::shutdownViews() // Automatically deleted as children of mRootView. Fix the globals. gStatusBar = NULL; gIMMgr = NULL; - gHoverView = NULL; + gToolTipView = NULL; gFloaterView = NULL; gMorphView = NULL; @@ -1775,12 +1699,6 @@ void LLViewerWindow::showCursor() void LLViewerWindow::hideCursor() { - // Hide tooltips - if(mToolTip ) mToolTip->setVisible( FALSE ); - - // Also hide hover info - if (gHoverView) gHoverView->cancelHover(); - // And hide the cursor mWindow->hideCursor(); @@ -2035,9 +1953,9 @@ void LLViewerWindow::draw() // No translation needed, this view is glued to 0,0 mRootView->draw(); - if (mToolTip->getVisible() && LLView::sDebugRects) + if (LLView::sDebugRects) { - gl_rect_2d(mToolTipStickyRect, LLColor4::white, false); + gToolTipView->drawStickyRect(); } // Draw optional on-top-of-everyone view @@ -2054,31 +1972,6 @@ void LLViewerWindow::draw() LLUI::popMatrix(); } - // Draw tooltips - // Adjust their rectangle so they don't go off the top or bottom - // of the screen. - if( mToolTip && mToolTip->getVisible() ) - { - glMatrixMode(GL_MODELVIEW); - LLUI::pushMatrix(); - { - S32 tip_height = mToolTip->getRect().getHeight(); - - S32 screen_x, screen_y; - mToolTip->localPointToScreen(0, -24 - tip_height, - &screen_x, &screen_y); - - // If tooltip would draw off the bottom of the screen, - // show it from the cursor tip position. - if (screen_y < tip_height) - { - mToolTip->localPointToScreen(0, 0, &screen_x, &screen_y); - } - LLUI::translate( (F32) screen_x, (F32) screen_y, 0); - mToolTip->draw(); - } - LLUI::popMatrix(); - } if( gShowOverlayTitle && !mOverlayTitle.empty() ) { @@ -2120,26 +2013,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } } - //// HACK look for UI editing keys - //if (LLView::sEditingUI) - //{ - // if (LLFloaterEditUI::processKeystroke(key, mask)) - // { - // return TRUE; - // } - //} - - // Hide tooltips on keypress - mToolTipBlocked = TRUE; // block until next time mouse is moved - - // Also hide hover info on keypress - if (gHoverView) - { - gHoverView->cancelHover(); - - gHoverView->setTyping(TRUE); - } - + // hide tooltips on keypress + LLToolTipMgr::instance().hideToolTips(); + // Explicit hack for debug menu. if ((MASK_ALT & mask) && (MASK_CONTROL & mask) && @@ -2197,6 +2073,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { return TRUE; } + //some of context menus use this container, let context menu handle navigation keys + if(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)) + { + return TRUE; + } // Traverses up the hierarchy LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); @@ -2360,14 +2241,8 @@ void LLViewerWindow::handleScrollWheel(S32 clicks) { LLView::sMouseHandlerMessage.clear(); - gMouseIdleTimer.reset(); - - // Hide tooltips - if( mToolTip ) - { - mToolTip->setVisible( FALSE ); - } - + LLUI::resetMouseIdleTimer(); + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); if( mouse_captor ) { @@ -2420,7 +2295,7 @@ void LLViewerWindow::moveCursorToCenter() mLastMousePoint.set(x,y); mCurrentMouseDelta.set(0,0); - LLUI::setCursorPositionScreen(x, y); + LLUI::setMousePositionScreen(x, y); } void LLViewerWindow::updateBottomTrayRect() @@ -2452,6 +2327,35 @@ void LLViewerWindow::updateBottomTrayRect() // Hover handlers // +void append_xui_tooltip(LLView* viewp, std::string& tool_tip_msg) +{ + if (viewp) + { + if (!tool_tip_msg.empty()) + { + tool_tip_msg.append("\n---------\n"); + } + LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); + // NOTE: we skip "root" since it is assumed + for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView(); + tooltip_it != end_tooltip_it; + ++tooltip_it) + { + LLView* viewp = *tooltip_it; + + tool_tip_msg.append(viewp->getName()); + LLPanel* panelp = dynamic_cast<LLPanel*>(viewp); + if (panelp && !panelp->getXMLFilename().empty()) + { + tool_tip_msg.append("("); + tool_tip_msg.append(panelp->getXMLFilename()); + tool_tip_msg.append(")"); + } + tool_tip_msg.append("/"); + } + } +} + // Update UI based on stored mouse position from mouse-move // event processing. void LLViewerWindow::updateUI() @@ -2473,6 +2377,17 @@ void LLViewerWindow::updateUI() return; } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gDebugRaycastFaceHit = -1; + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, + &gDebugRaycastFaceHit, + &gDebugRaycastIntersection, + &gDebugRaycastTexCoord, + &gDebugRaycastNormal, + &gDebugRaycastBinormal); + } + updateMouseDelta(); updateKeyboardFocus(); @@ -2500,8 +2415,8 @@ void LLViewerWindow::updateUI() if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y)) { // iterator over contents of top_ctrl, and throw into mouse_hover_set - for (LLView::tree_iterator_t it = top_ctrl->beginTree(); - it != top_ctrl->endTree(); + for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS(); + it != top_ctrl->endTreeDFS(); ++it) { LLView* viewp = *it; @@ -2521,9 +2436,8 @@ void LLViewerWindow::updateUI() else { // walk UI tree in depth-first order - LLView::tree_iterator_t end_it; - for (LLView::tree_iterator_t it = root_view->beginTree(); - it != end_it; + for (LLView::tree_iterator_t it = root_view->beginTreeDFS(); + it != root_view->endTreeDFS(); ++it) { LLView* viewp = *it; @@ -2536,7 +2450,7 @@ void LLViewerWindow::updateUI() if (viewp->getMouseOpaque()) { // constrain further iteration to children of this widget - it = viewp->beginTree(); + it = viewp->beginTreeDFS(); } // we have a view that contains the mouse, add it to the set @@ -2639,130 +2553,87 @@ void LLViewerWindow::updateUI() } } - if( !handled ) - { - lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl; - } - } - - // *NOTE: sometimes tools handle the mouse as a captor, so this - // logic is a little confusing - LLTool *tool = NULL; - if (gHoverView) - { - tool = LLToolMgr::getInstance()->getCurrentTool(); - - if(!handled && tool) + if (!handled) { - handled = tool->handleHover(x, y, mask); + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (!mWindow->isCursorHidden()) + if(mMouseInWindow && tool) { - gHoverView->updateHover(tool); + handled = tool->handleHover(x, y, mask); } } - else - { - // Cancel hovering if any UI element handled the event. - gHoverView->cancelHover(); - } - - // Suppress the toolbox view if our source tool was the pie tool, - // and we've overridden to something else. - mSuppressToolbox = - (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) && - (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()); - } - // Show a new tool tip (or update one that is alrady shown) + // Show a new tool tip (or update one that is already shown) BOOL tool_tip_handled = FALSE; std::string tool_tip_msg; if( handled - && !mWindow->isCursorHidden() - && mToolTip) + && !mWindow->isCursorHidden()) { - LLRect screen_sticky_rect; - LLMouseHandler *tooltip_source = NULL; + LLRect screen_sticky_rect = mRootView->getLocalRect(); S32 local_x, local_y; - if (mouse_captor) - { - mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); - tooltip_source = mouse_captor; - } - else if (handled_by_top_ctrl) - { - top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); - tooltip_source = top_ctrl; - } - else - { - local_x = x; local_y = y; - tooltip_source = mRootView; - } - - F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" ); - //HACK: hack for tool-based tooltips which need to pop up more quickly - //Also for show xui names as tooltips debug mode - if ((gFocusMgr.getMouseCapture() - && !gFocusMgr.getMouseCapture()->isView()) - || LLUI::sShowXUINames) - { - tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" ); - } - - BOOL tooltip_vis = FALSE; - if (shouldShowToolTipFor(tooltip_source)) + if (gSavedSettings.getBOOL("DebugShowXUINames")) { - tool_tip_handled = tooltip_source->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect ); - - // if we actually got a tooltip back... - if( tool_tip_handled && !tool_tip_msg.empty() ) + LLView* tooltip_view = mRootView; + LLView::tree_iterator_t end_it = mRootView->endTreeDFS(); + for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it) { - if (mToolTip->getVisible() // already showing a tooltip - || gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay) // mouse has been still long enough to show the tooltip + LLView* viewp = *it; + LLRect screen_rect; + viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); + if (!(viewp->getVisible() + && screen_rect.pointInRect(x, y))) + { + it.skipDescendants(); + } + else if (viewp->getMouseOpaque()) { - // if tooltip has changed or mouse has moved outside of "sticky" rectangle... - if (mLastToolTipMessage != tool_tip_msg - || !mToolTipStickyRect.pointInRect(x, y)) + if (!viewp->hasAncestor(tooltip_view)) { - //...update "sticky" rect and tooltip position - mToolTipStickyRect = screen_sticky_rect; - mToolTip->setOrigin( x, y ); + append_xui_tooltip(tooltip_view, tool_tip_msg); + screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); } - - // remember this tooltip so we know when it changes - mLastToolTipMessage = tool_tip_msg; - mToolTip->setWrappedText( tool_tip_msg, 200 ); - mToolTip->reshapeToFitText(); - LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0); - mToolTip->translateIntoRect( virtual_window_rect, FALSE ); - tooltip_vis = TRUE; + tooltip_view = viewp; } } - } - // HACK: assuming tooltip background is in ToolTipBGColor, perform fade out - LLColor4 bg_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" ); - if (tooltip_vis) + append_xui_tooltip(tooltip_view, tool_tip_msg); + screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); + + LLToolTipMgr::instance().show(LLToolTipParams() + .message(tool_tip_msg) + .sticky_rect(screen_sticky_rect) + .width(400)); + } + // if there is a mouse captor, nothing else gets a tooltip + else if (mouse_captor) { - mToolTipFadeTimer.stop(); - mToolTip->setBackgroundColor(bg_color); + mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect ); } else { - if (!mToolTipFadeTimer.getStarted()) + // next is top_ctrl + if (!tool_tip_handled && top_ctrl) { - mToolTipFadeTimer.start(); + top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect ); + } + + if (!tool_tip_handled) + { + local_x = x; local_y = y; + tool_tip_handled = mRootView->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect ); } - F32 tool_tip_fade_time = gSavedSettings.getF32("ToolTipFadeTime"); - bg_color.mV[VALPHA] = clamp_rescale(mToolTipFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, bg_color.mV[VALPHA], 0.f); - mToolTip->setBackgroundColor(bg_color); - } - // above interpolation of bg_color alpha is guaranteed to reach 0.f exactly - mToolTip->setVisible( bg_color.mV[VALPHA] != 0.f ); + LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool(); + if (!tool_tip_handled && current_tool) + { + current_tool->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = current_tool->handleToolTip(local_x, local_y, tool_tip_msg, screen_sticky_rect ); + } + } } updateLayout(); @@ -2779,67 +2650,8 @@ void LLViewerWindow::updateUI() { LLSelectMgr::getInstance()->deselectUnused(); } - - updatePicking(x, y, mask); } -void LLViewerWindow::updatePicking(S32 x, S32 y, MASK mask) -{ - // per frame picking - for tooltips and changing cursor over interactive objects - static S32 previous_x = -1; - static S32 previous_y = -1; - static BOOL mouse_moved_since_pick = FALSE; - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - gDebugRaycastFaceHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, - &gDebugRaycastFaceHit, - &gDebugRaycastIntersection, - &gDebugRaycastTexCoord, - &gDebugRaycastNormal, - &gDebugRaycastBinormal); - } - - - if ((previous_x != x) || (previous_y != y)) - mouse_moved_since_pick = TRUE; - - BOOL do_pick = FALSE; - - F32 picks_moving = gSavedSettings.getF32("PicksPerSecondMouseMoving"); - if ((mouse_moved_since_pick) && (picks_moving > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_moving)) - { - do_pick = TRUE; - } - - F32 picks_stationary = gSavedSettings.getF32("PicksPerSecondMouseStationary"); - if ((!mouse_moved_since_pick) && (picks_stationary > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_stationary)) - { - do_pick = TRUE; - } - - if (getCursorHidden()) - { - do_pick = FALSE; - } - - if(LLViewerMediaFocus::getInstance()->getFocus()) - { - // When in-world media is in focus, pick every frame so that browser mouse-overs, dragging scrollbars, etc. work properly. - do_pick = TRUE; - } - - if (do_pick) - { - mouse_moved_since_pick = FALSE; - mPickTimer.reset(); - pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE); - } - - previous_x = x; - previous_y = y; -} void LLViewerWindow::updateLayout() { @@ -2851,6 +2663,12 @@ void LLViewerWindow::updateLayout() && tool != LLToolDragAndDrop::getInstance() && !gSavedSettings.getBOOL("FreezeTime")) { + // Suppress the toolbox view if our source tool was the pie tool, + // and we've overridden to something else. + bool suppress_toolbox = + (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) && + (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()); + LLMouseHandler *captor = gFocusMgr.getMouseCapture(); // With the null, inspect, or drag and drop tool, don't muck // with visibility. @@ -2858,7 +2676,7 @@ void LLViewerWindow::updateLayout() if (gFloaterTools->isMinimized() || (tool != LLToolPie::getInstance() // not default tool && tool != LLToolCompGun::getInstance() // not coming out of mouselook - && !mSuppressToolbox // not override in third person + && !suppress_toolbox // not override in third person && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset && (!captor || captor->isView()))) // not dragging @@ -3043,13 +2861,6 @@ void LLViewerWindow::updateWorldViewRect(bool use_full_window) } } -/* static */ -void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info) -{ - gViewerWindow->mHoverPick = pick_info; -} - - void LLViewerWindow::saveLastMouse(const LLCoordGL &point) { // Store last mouse location. @@ -3295,7 +3106,7 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe return intersect; } -void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info) +void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent) { if (gNoRender) { @@ -3329,7 +3140,7 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback LLRect screen_region = mPickScreenRegion; screen_region.translate(mPicks.size() * PICK_DIAMETER, 0); - LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback); + LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, TRUE, callback); schedulePick(pick); } @@ -4900,11 +4711,6 @@ F32 LLViewerWindow::getWorldViewAspectRatio() const } } -void LLViewerWindow::drawPickBuffer() const -{ - mHoverPick.drawPickBuffer(); -} - void LLViewerWindow::calcDisplayScale() { F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); @@ -5153,49 +4959,6 @@ void LLPickInfo::updateXYCoords() } } -void LLPickInfo::drawPickBuffer() const -{ - if (mPickBuffer) - { - gGL.pushMatrix(); - LLGLDisable no_blend(GL_BLEND); - LLGLDisable no_alpha_test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glPixelZoom(10.f, 10.f); - LLVector2 display_scale = gViewerWindow->getDisplayScale(); - glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), - ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); - glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); - glPixelZoom(1.f, 1.f); - gGL.color4fv(LLColor4::white.mV); - gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), - FALSE); - gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), - llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f)); - gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), - llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); - gGL.translatef(10.f, 10.f, 0.f); - gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), - llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f), - llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f), - llround((F32)mPickPt.mY * display_scale.mV[VY]), - FALSE); - gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), - llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f), - llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f), - llround((F32)mPickPt.mY * display_scale.mV[VY]), - FALSE); - gGL.popMatrix(); - } -} - void LLPickInfo::getSurfaceInfo() { // set values to uninitialized - this is what we return if no intersection is found diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 7afb77bed8..c3c9d7021e 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -47,7 +47,6 @@ #include "llwindowcallbacks.h" #include "lltimer.h" #include "llstat.h" -#include "llnotifications.h" #include "llmousehandler.h" #include "llcursortypes.h" #include "llhandle.h" @@ -58,7 +57,7 @@ class LLUUID; class LLProgressView; class LLTool; class LLVelocityBar; -class LLTextBox; +class LLPanel; class LLImageRaw; class LLHUDIcon; class LLWindow; @@ -70,6 +69,17 @@ class LLRootView; class LLPickInfo { public: + typedef enum + { + PICK_OBJECT, + PICK_FLORA, + PICK_LAND, + PICK_ICON, + PICK_PARCEL_WALL, + PICK_INVALID + } EPickType; + +public: LLPickInfo(); LLPickInfo(const LLCoordGL& mouse_pos, const LLRect& screen_region, @@ -81,20 +91,10 @@ public: void fetchResults(); LLPointer<LLViewerObject> getObject() const; LLUUID getObjectID() const { return mObjectID; } - void drawPickBuffer() const; + bool isValid() const { return mPickType != PICK_INVALID; } static bool isFlora(LLViewerObject* object); - typedef enum - { - PICK_OBJECT, - PICK_FLORA, - PICK_LAND, - PICK_ICON, - PICK_PARCEL_WALL, - PICK_INVALID - } EPickType; - public: LLCoordGL mMousePt; MASK mKeyMask; @@ -147,6 +147,8 @@ public: void adjustControlRectanglesForFirstUse(const LLRect& window); void initWorldUI(); + BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down); + // // LLWindowCallback interface implementation // @@ -154,7 +156,6 @@ public: /*virtual*/ BOOL handleTranslatedKeyUp(KEY key, MASK mask); /*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended - /*virtual*/ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down); /*virtual*/ BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ BOOL handleCloseRequest(LLWindow *window); @@ -234,7 +235,6 @@ public: BOOL getRightMouseDown() const { return mRightMouseDown; } const LLPickInfo& getLastPick() const { return mLastPick; } - const LLPickInfo& getHoverPick() const { return mHoverPick; } void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0); void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0); @@ -281,7 +281,6 @@ public: void updateLayout(); void updateMouseDelta(); void updateKeyboardFocus(); - void updatePicking(S32 x, S32 y, MASK mask); void updateWorldViewRect(bool use_full_window=false); void updateBottomTrayRect(); @@ -332,11 +331,8 @@ public: void returnEmptyPicks(); - void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), - BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE); + void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), BOOL pick_transparent = FALSE); LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent); - static void hoverPickCallback(const LLPickInfo& pick_info); - LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, LLVector3* intersection); @@ -382,8 +378,6 @@ public: const LLVector2& getDisplayScale() const { return mDisplayScale; } void calcDisplayScale(); - void drawPickBuffer() const; - private: bool shouldShowToolTipFor(LLMouseHandler *mh); static bool onAlert(const LLSD& notify); @@ -422,9 +416,8 @@ protected: LLProgressView *mProgressView; LLFrameTimer mToolTipFadeTimer; - LLTextBox* mToolTip; + LLPanel* mToolTip; std::string mLastToolTipMessage; - BOOL mToolTipBlocked; // True after a key press or a mouse button event. False once the mouse moves again. LLRect mToolTipStickyRect; // Once a tool tip is shown, it will stay visible until the mouse leaves this rect. BOOL mMouseInWindow; // True if the mouse is over our window or if we have captured the mouse. @@ -435,12 +428,9 @@ protected: // Variables used for tool override switching based on modifier keys. JC MASK mLastMask; // used to detect changes in modifier mask LLTool* mToolStored; // the tool we're overriding - BOOL mSuppressToolbox; // sometimes hide the toolbox, despite - // having a camera tool selected BOOL mHideCursorPermanent; // true during drags, mouselook BOOL mCursorHidden; LLPickInfo mLastPick; - LLPickInfo mHoverPick; std::vector<LLPickInfo> mPicks; LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen) LLTimer mPickTimer; // timer for scheduling n picks per second @@ -477,13 +467,9 @@ void update_saved_window_size(const std::string& control,S32 delta_width, S32 de extern LLViewerWindow* gViewerWindow; -extern LLFrameTimer gMouseIdleTimer; // how long has it been since the mouse last moved? extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away -extern BOOL gDebugSelect; - -extern BOOL gDebugFastUIRender; extern LLViewerObject* gDebugRaycastObject; extern LLVector3 gDebugRaycastIntersection; extern LLVector2 gDebugRaycastTexCoord; @@ -495,7 +481,6 @@ extern S32 CHAT_BAR_HEIGHT; extern BOOL gDisplayCameraPos; extern BOOL gDisplayWindInfo; -extern BOOL gDisplayNearestWater; extern BOOL gDisplayFOV; #endif diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index a2793accea..570a3334b9 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -38,7 +38,7 @@ #include "llviewercontrol.h" #include "llagent.h" -#include "llviewerwindow.h" +#include "llnotifications.h" #include "lldrawable.h" #include "llface.h" #include "llsky.h" diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 67bc205f62..4d7423eaae 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -41,6 +41,7 @@ #include "lleventflags.h" #include "llfloaterreg.h" #include "llrender.h" +#include "lltooltip.h" #include "llagent.h" #include "llcallingcard.h" @@ -50,6 +51,7 @@ #include "llfloatermap.h" #include "llfloaterworldmap.h" #include "llfocusmgr.h" +#include "lllocalcliprect.h" #include "lltextbox.h" #include "lltextureview.h" #include "lltracker.h" @@ -1179,10 +1181,12 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) } -BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ) +BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen ) { LLVector3d pos_global = viewPosToGlobal(x, y); + std::string tooltip_msg; + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); if (info) { @@ -1217,22 +1221,26 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic } } } - msg.assign( message ); + tooltip_msg.assign( message ); // Optionally show region flags std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags); if (!region_flags.empty()) { - msg += '\n'; - msg += region_flags; + tooltip_msg += '\n'; + tooltip_msg += region_flags; } const S32 SLOP = 9; S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - sticky_rect_screen->setCenterAndSize(screen_x, screen_y, SLOP, SLOP); + sticky_rect_screen.setCenterAndSize(screen_x, screen_y, SLOP, SLOP); + + LLToolTipMgr::instance().show(LLToolTipParams() + .message(tooltip_msg) + .sticky_rect(sticky_rect_screen)); } return TRUE; } @@ -1744,7 +1752,7 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) LLRect clip_rect = getRect(); clip_rect.stretch(-8); clip_rect.clipPointToRect(mMouseDownX, mMouseDownY, local_x, local_y); - LLUI::setCursorPositionLocal(this, local_x, local_y); + LLUI::setMousePositionLocal(this, local_x, local_y); // finish the pan mPanning = FALSE; diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 41c9772694..8349d5399f 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -72,7 +72,7 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ); + virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen ); bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track); void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml new file mode 100644 index 0000000000..b23bf49435 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="true" + height="400" + layout="topleft" + name="floater_test_inspectors" + title="Test Inspectors" + width="400"> + <text + height="20" + left="10" + name="test_inspectors" + top="30" + width="300"> + Click to spawn an inspector: + </text> + <!-- James Tester, 4 years old --> + <button + name="avatar_2d_btn1" + label="Avatar 2D" + top="50" + left="10" + height="20" + width="100" + commit_callback.function="ShowAvatarInspector" + commit_callback.parameter="22df1dcb-810a-4975-aab9-0159958fe155" /> + <!-- DonkeyPuncher 2008-10-1 --> + <button + name="avatar_2d_btn5" + label="Avatar 2D" + top_pad="10" + left="10" + height="20" + width="100" + commit_callback.function="ShowAvatarInspector" + commit_callback.parameter="d5330e4e-391a-4f00-9352-b797ed2f9a97" /> + <!-- DonkeyPuncher 2009-01-15 --> + <button + name="avatar_2d_btn2" + label="Avatar 2D" + top_pad="10" + left="10" + height="20" + width="100" + commit_callback.function="ShowAvatarInspector" + commit_callback.parameter="05511655-a58a-48b6-b645-966f69fc17a7" /> + <!-- 2009-06-14 --> + <button + name="avatar_2d_btn3" + label="Avatar 2D" + top_pad="10" + left="10" + height="20" + width="100" + commit_callback.function="ShowAvatarInspector" + commit_callback.parameter="6a164b3d-7c2c-43eb-880a-0ebc0687b3ec" /> + <!-- jarvtest Bombastic 2009-10-3 --> + <button + name="avatar_2d_btn4" + label="Avatar 2D" + top_pad="10" + left="10" + height="20" + width="100" + commit_callback.function="ShowAvatarInspector" + commit_callback.parameter="e7dc3c83-1e11-4fa7-beeb-4b18adfb4efa" /> + <button + name="avatar_3d_btn" + label="Avatar 3D" + top="50" + left="150" + height="20" + width="100"/> + <button + name="object_2d_btn" + label="Object 2D" + top_pad="10" + left_delta="0" + height="20" + width="100"/> + <button + name="object_3d_btn" + label="Object 3D" + top_pad="10" + left_delta="0" + height="20" + width="100"/> + <button + name="group_btn" + label="Group" + top_pad="10" + left_delta="0" + height="20" + width="100"/> + <button + name="place_btn" + label="Place" + top_pad="10" + left_delta="0" + height="20" + width="100"/> + <button + name="event_btn" + label="Event" + top_pad="10" + left_delta="0" + height="20" + width="100"/> + +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index a126a932df..b53f4fb99c 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater follows="left|top|right" - height="615" + height="570" layout="topleft" name="toolbox floater" save_rect="true" @@ -27,7 +27,7 @@ </floater.string> <floater.string name="status_camera"> - Click and drag to change view + Click and drag to move camera </floater.string> <floater.string name="status_grab"> @@ -224,35 +224,27 @@ left="10" follows="left|top" control_name="EditLinkedParts" - label="Edit linked prims" + label="Edit linked" layout="topleft" name="checkbox edit linked parts" /> - <text - left="10" - type="string" - length="1" - follows="left|top" - layout="topleft" - name="text ruler mode"> - Ruler: - </text> <combo_box height="19" - left="30" + left="10" layout="topleft" follows="left|top" + top_pad="0" name="combobox grid mode" - width="90"> + width="120"> <combo_box.item - label="World" + label="World ruler" name="World" value="World" /> <combo_box.item - label="Local" + label="Local ruler" name="Local" value="Local" /> <combo_box.item - label="Reference" + label="Reference ruler" name="Reference" value="Reference" /> </combo_box> @@ -263,7 +255,7 @@ layout="topleft" left="143" name="checkbox uniform" - top="54" + top="50" width="134" /> <check_box control_name="ScaleStretchTextures" @@ -272,28 +264,27 @@ label="Stretch Textures" layout="topleft" name="checkbox stretch textures" - top_pad="1" + top_pad="0" width="134" /> <check_box control_name="SnapEnabled" height="19" initial_value="true" - label="Use Grid" + label="Snap to Grid" layout="topleft" name="checkbox snap to grid" - top_pad="1" + top_pad="0" width="134" /> <button - follows="left|top" - font="SansSerifSmall" - height="19" - left_delta="40" - top_delta="20" - label="Options..." - label_selected="Options..." + left="163" + top_pad="0" + image_overlay="Arrow_Right_Off" + picture_style="true" + label_selected="Options" layout="topleft" name="Options..." - width="78" /> + width="26" + height="22" /> <button follows="left|top" height="24" @@ -605,7 +596,7 @@ top_delta="15" width="114" /> </radio_group> - + <text type="string" length="1" @@ -680,7 +671,7 @@ type="string" text_color="LabelSelectedDisabledColor" length="1" - top_pad="7" + top_pad="4" height="12" follows="left|top" halign="right" @@ -722,7 +713,7 @@ top="16"> <panel.string name="text deed continued"> - Deed... + Deed </panel.string> <panel.string name="text deed"> @@ -776,7 +767,7 @@ layout="topleft" left="10" name="Name:" - top_pad="8" + top="0" width="90"> Name: </text> @@ -789,7 +780,7 @@ name="Object Name" select_on_focus="true" top_delta="0" - width="172" /> + width="165" /> <text type="string" length="1" @@ -811,8 +802,7 @@ name="Object Description" select_on_focus="true" top_delta="0" - width="172" /> - + width="165" /> <text type="string" left="10" @@ -833,21 +823,9 @@ height="19" layout="topleft" name="Creator Name" - width="150"> - Thrax Linden + width="175"> + Esbee Linden </text> -<!--TODO: Kill this--> -<!-- <button - follows="top|right" - font="SansSerifSmall" - height="19" - label="Profile..." - label_selected="Profile..." - layout="topleft" - left_pad="6" - name="button creator profile" - tool_tip="View creator profile" - width="78" />--> <text type="string" length="1" @@ -868,21 +846,9 @@ layout="topleft" name="Owner Name" left_pad="0" - width="150"> - Thrax Linden + width="175"> + Erica Linden </text> -<!--TODO: Kill this--> -<!--<button - follows="top|right" - font="SansSerifSmall" - height="19" - label="Profile..." - label_selected="Profile..." - layout="topleft" - left_pad="6" - name="button owner profile" - tool_tip="View owner profile" - width="78" />--> <text type="string" length="1" @@ -891,40 +857,39 @@ left="10" height="19" name="Group:" - width="90"> + width="70"> Group: </text> <name_box - follows="left|top|right" + follows="left|top" height="19" initial_value="Loading..." layout="topleft" left_pad="0" name="Group Name Proxy" - width="170" /> + width="159" /> + <button + follows="left|top" + left_pad="0" + image_overlay="Arrow_Right_Off" + picture_style="true" + layout="topleft" + name="button set group" + tool_tip="Choose a group to share this object's permissions" + width="26" + height="22" /> <button - follows="top|right" + follows="top|left" font="SansSerifSmall" height="19" - label="Deed..." - label_selected="Deed..." + label="Deed" + label_selected="Deed" layout="topleft" name="button deed" top_pad="0" - left="102" + left="80" tool_tip="Deeding gives this item away with Next Owner permissions. Group shared objects can be deeded by a group officer." - width="80" /> - <button - follows="left|top" - font="SansSerifSmall" - height="19" - label="Set..." - label_selected="Set..." - layout="topleft" - left_pad="7" - name="button set group" - tool_tip="Choose a group to share this object's permissions" - width="80" /> + width="90" /> <check_box height="19" follows="left|top" @@ -932,18 +897,18 @@ layout="topleft" name="checkbox share with group" tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." - left="100" + left_pad="5" width="93" /> <text type="string" length="1" follows="left|top" - height="19" + height="16" layout="topleft" - top_pad="7" + top_pad="15" left="10" name="label click action" - width="90"> + width="100"> Click to: </text> <combo_box @@ -951,7 +916,7 @@ height="22" layout="topleft" name="clickaction" - width="170" + width="155" left_pad="0"> <combo_box.item label="Touch (default)" @@ -973,23 +938,15 @@ label="Open" name="Open" value="Open" /> -<!--TODO: Kill this--> -<!-- <combo_box.item - label="Play parcel media" - name="Play" - value="Play" /> - <combo_box.item - label="Open parcel media" - name="Opemmedia" - value="Open Media" />--> </combo_box> <check_box - height="20" + height="16" + top_pad="15" label="For Sale:" layout="topleft" name="checkbox for sale" left="10" - width="90" /> + width="100" /> <!-- NEW SALE TYPE COMBO BOX --> <combo_box left_pad="0" @@ -997,22 +954,22 @@ follows="left|top" allow_text_entry="false" height="22" - width="170" + width="155" max_chars="20" mouse_opaque="true" name="sale type" intial_value="2"> <combo_item name="Copy" - label="Copy" + label="Copy" value="2" /> <combo_item name="Contents" - label="Contents" + label="Contents" value="3" /> <combo_item name="Original" - label="Original" + label="Original" value="1" /> </combo_box> <!-- NEW PRICE SPINNER --> @@ -1020,118 +977,55 @@ follows="left|top" decimal_digits="0" increment="1" + top_pad="10" control_name="Edit Cost" name="Edit Cost" label="Price: L$" label_width="60" - width="170" + width="155" min_val="1" height="19" max_val="999999999" /> - <panel + <check_box + left="107" + height="15" + width="100" + label="Show in search" + layout="topleft" + name="search_check" + tool_tip="Let people see this object in search results" + /> +<panel border="false" - follows="left|top|right" + follows="left|top" layout="topleft" mouse_opaque="false" background_visible="true" bg_alpha_color="FloaterUnfocusBorderColor" name="perms_build" left="0" - height="140" + top="240" + height="120" width="280"> <text type="string" length="1" left="10" - top_pad="6" - height="19" + top_pad="10" + text_color="EmphasisColor" + height="16" follows="left|top|right" layout="topleft" name="perm_modify" - width="180"> + width="250"> You can modify this object </text> <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - top_pad="0" - follows="left|top" - layout="topleft" - left="17" - name="B:" - width="30"> - B: - </text> - <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - layout="topleft" - left_pad="0" - name="O:" - width="30"> - O: - </text> - <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - layout="topleft" - left_pad="0" - name="G:" - width="30"> - G: - </text> - <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - left_pad="0" - layout="topleft" - name="E:" - width="30"> - E: - </text> - <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - layout="topleft" - left_pad="0" - name="N:" - width="30"> - N: - </text> - <text - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - layout="topleft" - left_pad="0" - name="F:" - width="30"> - F: - </text> - <check_box - left="15" - height="19" - label="Show in search" - layout="topleft" - name="search_check" - tool_tip="Let people see this object in search results" - /> - <text type="string" follows="left|top" name="Anyone can:" width="250" - top_pad="7" + top_pad="5" left="10"> Anyone: </text> @@ -1148,13 +1042,20 @@ layout="topleft" left_pad="0" name="checkbox allow everyone copy" - width="260" /> + width="90" /> + <check_box + height="19" + label="Use" + layout="topleft" + left_pad="0" + name="allow everyone to use" + width="90" /> <text type="string" follows="left|top" height="19" name="Next owner can:" - width="270" + width="250" left="10"> Next owner: </text> @@ -1183,192 +1084,134 @@ top_delta="0" tool_tip="Next owner can give away or resell this object" width="90" /> - </panel> -<!--TODO: KILL THIS--> -<!--<text + <text type="string" + text_color="EmphasisColor_35" length="1" + top_pad="5" follows="left|top" - height="19" layout="topleft" - left_pad="12" - name="Cost" - top_delta="0" - width="78"> - Price: L$ + left="18" + name="B:" + height="10" + width="30"> + B: </text> - <line_editor - follows="left|top|right" - height="19" + <text + type="string" + text_color="EmphasisColor_35" + length="1" + follows="left|top" layout="topleft" left_pad="0" - max_length="25" - name="Edit Cost" - top_delta="0" - width="75" />--> -<!--TODO: KILL THIS--> -<!--<radio_group - follows="left|top|right" - height="19" - left="15" - layout="topleft" - name="sale type" - width="218"> - <radio_item - height="19" - label="Original" - layout="topleft" - left="0" - name="Original" - top="0" - width="70" /> - <radio_item - height="19" - label="Copy" - layout="topleft" - left_delta="70" - name="Copy" - top_delta="0" - width="70" /> - <radio_item - height="19" - label="Contents" - layout="topleft" - left_delta="70" - name="Contents" - top_delta="0" - width="76" /> - </radio_group>--> - </panel> - <panel - border="false" - follows="left|top|right|bottom" - height="367" - label="Object" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="Object" - top_delta="0" - width="280"> + name="O:" + height="10" + width="30"> + O: + </text> <text type="string" + text_color="EmphasisColor_35" length="1" follows="left|top" + layout="topleft" + left_pad="0" + name="G:" height="10" + width="30"> + G: + </text> + <text + type="string" + text_color="EmphasisColor_35" + length="1" + follows="left|top" + left_pad="0" layout="topleft" - left="10" - name="select_single" - top="10" - width="252"> - Select only one primitive to edit parameters. + name="E:" + height="10" + width="30"> + E: </text> <text type="string" + text_color="EmphasisColor_35" length="1" follows="left|top" + layout="topleft" + left_pad="0" + name="N:" height="10" + width="30"> + N: + </text> + <text + type="string" + text_color="EmphasisColor_35" + length="1" + follows="left|top" layout="topleft" - left_delta="0" - name="edit_object" - top_delta="0" - width="252"> - Edit object parameters: + left_pad="0" + name="F:" + height="10" + width="30"> + F: </text> + </panel> + </panel> + <panel + border="false" + follows="left|top|right|bottom" + height="367" + label="Object" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="Object" + top="16" + width="280"> <check_box height="19" label="Locked" layout="topleft" - left_delta="-2" name="checkbox locked" tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits." - top_pad="10" + top_pad="5" + left="10" width="123" /> <check_box height="19" label="Physical" layout="topleft" - left_delta="0" name="Physical Checkbox Ctrl" tool_tip="Allows object to be pushed and affected by gravity" - top_pad="2" + top_pad="0" width="123" /> <check_box height="19" label="Temporary" layout="topleft" - left_delta="0" name="Temporary Checkbox Ctrl" tool_tip="Causes object to be deleted 1 minute after creation." - top_pad="2" + top_pad="0" width="123" /> <check_box height="19" label="Phantom" layout="topleft" - left_delta="0" name="Phantom Checkbox Ctrl" tool_tip="Causes object to not collide with other objects or avatars" - top_pad="2" + top_pad="0" width="123" /> - - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="label material" - top_pad="9" - width="121"> - Material - </text> - <combo_box - height="19" - layout="topleft" - left_delta="0" - name="material" - top_pad="4" - width="95"> - <combo_box.item - label="Stone" - name="Stone" - value="Stone" /> - <combo_box.item - label="Metal" - name="Metal" - value="Metal" /> - <combo_box.item - label="Glass" - name="Glass" - value="Glass" /> - <combo_box.item - label="Wood" - name="Wood" - value="Wood" /> - <combo_box.item - label="Flesh" - name="Flesh" - value="Flesh" /> - <combo_box.item - label="Plastic" - name="Plastic" - value="Plastic" /> - <combo_box.item - label="Rubber" - name="Rubber" - value="Rubber" /> - </combo_box> + <text type="string" length="1" follows="left|top" height="10" layout="topleft" - left_delta="2" name="label position" - top_pad="8" + top_pad="10" width="121"> Position (meters) </text> @@ -1384,7 +1227,7 @@ max_val="512" min_val="-256" name="Pos X" - text_enabled_color="0.43 0.06 0.06 1" + text_enabled_color="1 0 0.3 .7" top_pad="5" width="87" /> <spinner @@ -1399,7 +1242,7 @@ max_val="512" min_val="-256" name="Pos Y" - text_enabled_color="0 0.39 0.15 1" + text_enabled_color="EmphasisColor" top_pad="3" width="87" /> <spinner @@ -1413,7 +1256,7 @@ left_delta="0" max_val="4096" name="Pos Z" - text_enabled_color="0 0.26 0.51 1" + text_enabled_color="0 0.8 1 .65" top_pad="3" width="87" /> <text @@ -1533,8 +1376,8 @@ text_enabled_color="1 1 1 1" top_pad="3" width="87" /> - - <text + + <!-- <text type="string" length="1" follows="left|top" @@ -1542,16 +1385,16 @@ layout="topleft" left="125" name="label basetype" - top="26" + top="5" width="150"> - Building Block Type - </text> + Prim Type + </text>--> <combo_box height="19" layout="topleft" - left_delta="0" name="comboBaseType" - top_pad="4" + top="5" + left="125" width="150"> <combo_box.item label="Box" @@ -1586,6 +1429,41 @@ name="Sculpted" value="Sculpted" /> </combo_box> + <combo_box + height="19" + layout="topleft" + name="material" + top_pad="0" + width="150"> + <combo_box.item + label="Stone" + name="Stone" + value="Stone" /> + <combo_box.item + label="Metal" + name="Metal" + value="Metal" /> + <combo_box.item + label="Glass" + name="Glass" + value="Glass" /> + <combo_box.item + label="Wood" + name="Wood" + value="Wood" /> + <combo_box.item + label="Flesh" + name="Flesh" + value="Flesh" /> + <combo_box.item + label="Plastic" + name="Plastic" + value="Plastic" /> + <combo_box.item + label="Rubber" + name="Rubber" + value="Rubber" /> + </combo_box> <text type="string" length="1" @@ -1596,11 +1474,11 @@ name="text cut" top_pad="6" width="150"> - Path Cut Begin and End + Path Cut (begin/end) </text> <spinner follows="left|top" - height="19" + height="16" increment="0.025" initial_value="0" label="B" @@ -1613,7 +1491,7 @@ width="68" /> <spinner follows="left|top" - height="19" + height="16" increment="0.025" initial_value="1" label="E" @@ -1632,7 +1510,7 @@ layout="topleft" left="125" name="text hollow" - top_pad="6" + top_pad="5" width="68"> Hollow </text> @@ -1644,7 +1522,6 @@ layout="topleft" left_pad="10" name="text skew" - top_delta="0" width="63"> Skew </text> @@ -1681,7 +1558,7 @@ layout="topleft" left="125" name="Hollow Shape" - top_pad="6" + top_pad="0" width="150"> Hollow Shape </text> @@ -1717,9 +1594,9 @@ layout="topleft" left_delta="0" name="text twist" - top_pad="4" + top_pad="8" width="150"> - Twist Begin and End + Twist (begin/end) </text> <spinner decimal_digits="0" @@ -1811,7 +1688,7 @@ layout="topleft" left="125" name="text topshear" - top_pad="6" + top_pad="3" width="141"> Top Shear </text> @@ -1853,9 +1730,9 @@ layout="topleft" left="125" name="advanced_cut" - top_pad="6" + top_pad="3" width="150"> - Profile Cut Begin and End + Profile Cut (begin/end) </text> <text type="string" @@ -1867,7 +1744,7 @@ name="advanced_dimple" top_delta="0" width="150"> - Dimple Begin and End + Dimple (begin/end) </text> <text type="string" @@ -1879,7 +1756,7 @@ name="advanced_slice" top_delta="0" width="150"> - Slice Begin and End + Slice (begin/end) </text> <spinner follows="left|top" @@ -1892,7 +1769,7 @@ left_delta="0" max_val="0.95" name="Path Limit Begin" - top_pad="4" + top_pad="3" width="68" /> <spinner follows="left|top" @@ -1915,7 +1792,7 @@ layout="topleft" left="125" name="text taper2" - top_pad="6" + top_pad="3" width="150"> Taper </text> @@ -1931,7 +1808,7 @@ left_delta="0" min_val="-1" name="Taper X" - top_pad="4" + top_pad="3" width="68" /> <spinner decimal_digits="2" @@ -1955,7 +1832,7 @@ layout="topleft" left="125" name="text radius delta" - top_pad="6" + top_pad="0" width="78"> Radius </text> @@ -1967,7 +1844,6 @@ layout="topleft" left_delta="78" name="text revolutions" - top_delta="0" width="68"> Revolutions </text> @@ -2090,7 +1966,7 @@ layout="topleft" left="10" name="select_single" - top="10" + top="5" width="252"> Select only one primitive to edit features. </text> @@ -2100,9 +1976,9 @@ follows="left|top" height="10" layout="topleft" - left_delta="0" + left="10" name="edit_object" - top_delta="0" + top="5" width="252"> Edit object features: </text> @@ -2110,7 +1986,7 @@ height="19" label="Flexible Path" layout="topleft" - left_delta="0" + left="10" name="Flexible1D Checkbox Ctrl" tool_tip="Allows object to flex about the Z axis. (Client-side only)" top_pad="10" @@ -2224,60 +2100,50 @@ top_pad="4" width="128" /> <check_box - height="19" + height="16" label="Light" layout="topleft" - left_delta="0" + left="10" name="Light Checkbox Ctrl" tool_tip="Causes object to emit light" - top_pad="14" - width="121" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="label color" top_pad="15" - width="58"> - Color - </text> + width="60" /> <color_swatch - border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" + bevel_style="none" + border_style="line" color="0.5 0.5 0.5 1" + border.border_thickness="0" follows="left|top" - height="48" + height="50" layout="topleft" - left_delta="67" + left_pad="10" + top_pad="-17" name="colorswatch" tool_tip="Click to open Color Picker" - top_delta="-10" - width="32" /> + width="40" /> <spinner follows="left|top" height="19" initial_value="0.5" label="Intensity" - label_width="65" + label_width="70" layout="topleft" - left="10" + left_pad="15" name="Light Intensity" - top_pad="4" + top_pad="-50" width="128" /> <spinner follows="left|top" height="19" initial_value="5" label="Radius" - label_width="65" + label_width="70" layout="topleft" left_delta="0" max_val="20" name="Light Radius" - top_pad="0" + top_pad="3" width="128" /> <spinner follows="left|top" @@ -2285,12 +2151,12 @@ increment="0.25" initial_value="1" label="Falloff" - label_width="65" + label_width="70" layout="topleft" left_delta="0" max_val="2" name="Light Falloff" - top_pad="0" + top_pad="3" width="128" /> </panel> <panel @@ -2399,16 +2265,16 @@ left="10" name="tex gen" top_pad="10" - width="90"> + width="87"> Mapping </text> <combo_box - height="19" + height="22" layout="topleft" left_delta="0" name="combobox texgen" top_pad="4" - width="80"> + width="87"> <combo_box.item label="Default" name="Default" @@ -2424,19 +2290,19 @@ follows="left|top" height="10" layout="topleft" - left="100" name="label shininess" - top_pad="-33" - width="70"> + left_pad="5" + top_pad="-36" + width="80"> Shininess </text> <combo_box - height="19" + height="22" layout="topleft" left_delta="0" name="combobox shininess" top_pad="4" - width="70"> + width="80"> <combo_box.item label="None" name="None" @@ -2460,19 +2326,19 @@ follows="left|top" height="10" layout="topleft" - left="180" + left_pad="5" name="label bumpiness" - top_pad="-33" - width="80"> + top_pad="-36" + width="87"> Bumpiness </text> <combo_box - height="19" + height="22" layout="topleft" left_delta="0" name="combobox bumpiness" top_pad="4" - width="80"> + width="87"> <combo_box.item label="None" name="None" @@ -2555,7 +2421,7 @@ left="10" name="tex scale" top_pad="15" - width="160"> + width="200"> Repeats per Face </text> <spinner @@ -2650,13 +2516,12 @@ <button follows="left|top" font="SansSerifSmall" - height="19" + height="22" label="Apply" label_selected="Apply" layout="topleft" left_pad="10" name="button apply" - top_delta="-4" width="75" /> <text type="string" @@ -2667,8 +2532,8 @@ left="10" name="tex offset" top_pad="20" - width="160"> - Offset + width="200"> + Texture Offset </text> <spinner follows="left|top" @@ -2720,10 +2585,9 @@ top="340" width="68" />--> </panel> - <panel + <panel border="false" follows="left|top|right|bottom" - height="367" label="Content" layout="topleft" left_delta="0" @@ -2733,34 +2597,33 @@ width="280"> <button follows="left|top" - height="19" + height="22" label="New Script" - label_selected="New Script..." + label_selected="New Script" layout="topleft" left="10" name="button new script" top="10" - width="100" /> + width="120" /> <button follows="left|top" - height="19" - label="Permissions..." + height="22" + label="Permissions" layout="topleft" - left_pad="10" + left_pad="8" name="button permissions" - top_delta="0" - width="100" /> + width="130" /> <panel_inventory follows="left|top" - height="300" + height="310" layout="topleft" left="10" name="contents_inventory" - top="35" + top="50" width="260" /> </panel> - </tab_container> - <panel + </tab_container> + <panel follows="left|top" height="384" layout="topleft" @@ -2768,7 +2631,7 @@ name="land info panel" top_delta="0" width="280"> - <text + <text type="string" length="1" font="SansSerifBig" @@ -2807,9 +2670,9 @@ </text> <button follows="left|top" - height="19" - label="About Land..." - label_selected="About Land..." + height="22" + label="Land profile" + label_selected="Land profile" layout="topleft" left_delta="0" name="button about land" @@ -2822,19 +2685,16 @@ layout="topleft" left_delta="0" name="checkbox show owners" - tool_tip="Colour parcels according to their ownership" + tool_tip="Color parcels by owner" top_pad="8" - width="140" /> - <button - follows="left|top" - height="19" - label="?" - label_selected="?" - layout="topleft" + width="205" /> + <button + image_overlay="Arrow_Right_Off" + picture_style="true" left_pad="5" name="button show owners help" - top_delta="-2" - width="18" /> + width="26" + height="22" /> <text type="string" length="1" @@ -2850,9 +2710,9 @@ </text> <button follows="left|top" - height="19" - label="Subdivide..." - label_selected="Subdivide..." + height="22" + label="Subdivide" + label_selected="Subdivide" layout="topleft" left="30" name="button subdivide land" @@ -2860,9 +2720,9 @@ width="112" /> <button follows="left|top" - height="19" - label="Join..." - label_selected="Join..." + height="22" + label="Join" + label_selected="Join" layout="topleft" left_delta="0" name="button join land" @@ -2883,9 +2743,9 @@ </text> <button follows="left|top" - height="19" - label="Buy Land..." - label_selected="Buy Land..." + height="22" + label="Buy Land" + label_selected="Buy Land" layout="topleft" left="30" name="button buy land" @@ -2894,8 +2754,8 @@ <button follows="left|top" height="19" - label="Abandon Land..." - label_selected="Abandon Land..." + label="Abandon Land" + label_selected="Abandon Land" layout="topleft" left_delta="0" name="button abandon land" diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index cee789d435..f908e9d610 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -1,14 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- All our XML is utf-8 encoded. --> -<!-- No title to avoid window chrome --> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> <floater background_opaque="false" background_visible="true" bevel_style="in" - bg_alpha_color="black" + bg_alpha_color="PanelDefaultBackgroundColor" + can_close="false" can_minimize="false" name="inspect_avatar" + single_instance="true" + sound_flags="0" title="" visible="true" width="300" @@ -16,28 +22,39 @@ left="0" top="200" > + <!-- Allowed fields include: + [BORN_ON] ("12/3/2008") + [SL_PROFILE] (Second Life profile), + [RW_PROFILE] (real world profile), + [ACCTTYPE] ("Resident"), + [PAYMENTINFO] ("Payment Info on File"), + [AGE] ("1 year 2 months") --> + <string name="Subtitle"> +[AGE] + </string> + <string name="Details"> +[ACCTTYPE], [PAYMENTINFO] +Profile: [SL_PROFILE] + </string> <text - top="180" left="10" width="220" height="70" follows="left|top|right|bottom" + top="180" left="10" width="280" height="70" follows="left|top|right|bottom" use_ellipses="true" word_wrap="true" font="SansSerifHugeBold" text_color="white" mouse_opaque="true" name="user_name" > - Codex Linden + Test Name </text> + <!-- General purpose subtitle area, not sure yet what goes here --> <text top="155" left="10" width="150" height="20" follows="left|top|right|bottom" - font="SansSerifBig" font.style="UNDERLINE" + font="SansSerifBig" text_color="white" mouse_opaque="true" - name="active_group" > - The Guild - </text> + name="user_subtitle" /> + <!-- Leave text fields blank so it doesn't flash when data arrives off the network --> <text - top="110" left="10" width="290" height="50" follows="left|top|right|bottom" + top="115" left="10" width="290" height="50" follows="left|top|right|bottom" font="SansSerifSmall" text_color="white" word_wrap="true" - mouse_opaque="true" name="user_detail" > -3 year-old account, Payment info on file -Languages: English, Spanish; +5 Sexterity Vest - </text> + mouse_opaque="true" name="user_details" /> <avatar_icon top="185" left="230" width="60" height="60" follows="left|top|right|bottom" color="1 1 1 1" enabled="true" mouse_opaque="true" name="avatar_icon" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 1e911c2664..8a2955654e 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -97,18 +97,20 @@ layout="topleft" name="Widget Test" shortcut="control|shift|T"> - <menu_item_call.on_click - function="ShowFloater" - parameter="test_widgets" /> - </menu_item_call> - <menu_item_call - label="Avatar Inspector" - name="Avatar Inspector" - shortcut="control|shift|I"> - <menu_item_call.on_click - function="ShowFloater" - parameter="inspect_avatar" /> - </menu_item_call> + <menu_item_call.on_click + function="ShowFloater" + parameter="test_widgets" /> + </menu_item_call> + <menu_item_call + label="Inspectors Test" + name="inspectors_test" + shortcut="control|shift|I" + > + <menu_item_call.on_click + function="ShowFloater" + parameter="test_inspectors" /> + </menu_item_call> + <menu_item_separator /> <menu_item_call label="Show TOS" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 6bc12368b7..9ad9a87f95 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2751,14 +2751,13 @@ <menu_item_call.on_click function="Advanced.SendTestIMs" /> </menu_item_call> - <!-- *HACK: Hard code James Tester's UUID --> <menu_item_call - label="Avatar Inspector" - name="Avatar Inspector" + label="Test Inspectors" + name="Test Inspectors" shortcut="control|shift|I"> <menu_item_call.on_click - function="Advanced.AvatarInspector" - parameter="22df1dcb-810a-4975-aab9-0159958fe155" /> + function="Floater.Show" + parameter="test_inspectors" /> </menu_item_call> </menu> <menu diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml index f5af8e7b30..4dc4a9ff46 100644 --- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml +++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml @@ -11,7 +11,7 @@ bevel_style="in" bg_alpha_color="0 0 0 0"> <chiclet_im_p2p - name="chiclet" + name="p2p_chiclet" layout="topleft" follows="left" top="5" @@ -19,6 +19,15 @@ height="25" width="45"> </chiclet_im_p2p> + <chiclet_im_group + name="group_chiclet" + layout="topleft" + follows="left" + top="5" + left="5" + height="25" + width="45"> + </chiclet_im_group> <text type="string" name="contact_name" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 79ca839f28..df91920721 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -33,12 +33,13 @@ top="0" width="5"/> <layout_panel + auto_resize="false" follows="left|right" height="28" layout="topleft" left="5" min_height="28" - width="500" + width="600" top="0" min_width="305" name="chat_bar" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 794b69d7ed..d943b2ea23 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -55,6 +55,7 @@ max_length="31" name="first_name_edit" select_on_focus="true" + tool_tip="Enter first name here" top_pad="4" width="120" /> <text @@ -111,6 +112,25 @@ select_on_focus="true" top_pad="4" width="120" /> + <button + follows="left|bottom" + height="24" + label="Log In" + label_selected="Log In" + layout="topleft" + left="435" + name="connect_btn" + top="548" + width="120" /> + <combo_box + allow_text_entry="true" + follows="left|bottom" + height="18" + layout="topleft" + left_pad="15" + name="server_combo" + top_delta="2" + width="120" /> <text type="string" length="1" @@ -158,25 +178,7 @@ name="remember_check" top_delta="3" width="138" /> - <button - follows="left|bottom" - height="24" - label="Log In" - label_selected="Log In" - layout="topleft" - left="435" - name="connect_btn" - top="548" - width="120" /> - <combo_box - allow_text_entry="true" - follows="left|bottom" - height="18" - layout="topleft" - left_pad="15" - name="server_combo" - top_delta="2" - width="120" /> + <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 135dcb167b..41de34fbed 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -14,33 +14,6 @@ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] </string> <string - name="AcctTypeResident" - value="Resident" /> - <string - name="AcctTypeTrial" - value="Trial" /> - <string - name="AcctTypeCharterMember" - value="Charter Member" /> - <string - name="AcctTypeEmployee" - value="Linden Lab Employee" /> - <string - name="PaymentInfoUsed" - value="Payment Info Used" /> - <string - name="PaymentInfoOnFile" - value="Payment Info On File" /> - <string - name="NoPaymentInfoOnFile" - value="No Payment Info On File" /> - <string - name="AgeVerified" - value="Age-verified" /> - <string - name="NotAgeVerified" - value="Not Age-verified" /> - <string name="payment_update_link_url"> http://www.secondlife.com/account/billing.php?lang=en </string> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b8152a4956..faed615bdd 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -46,7 +46,7 @@ <string name="AgentLostConnection">This region may be experiencing trouble. Please check your connection to the Internet.</string> - <!-- Tooltip, llhoverview.cpp --> + <!-- Tooltip, lltooltipview.cpp --> <string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar --> <string name="TooltipNoName">(no name)</string> <!-- No name on an object --> <string name="TooltipOwner">Owner:</string> <!-- Owner name follows --> @@ -1913,8 +1913,35 @@ this texture in your inventory <string name="Stomach">Stomach</string> <string name="Left Pec">Left Pec</string> <string name="Right Pec">Right Pec</string> - - <!-- HUD Position --> + + <!-- Avatar age computation, see LLAvatarPropertiesProcessor::ageFromDate --> + <string name="YearsMonthsOld">[AGEYEARS][AGEMONTHS]old</string> + <string name="WeeksOld">[AGEWEEKS]old</string> + <string name="DaysOld">[AGEDAYS]old</string> + <string name="TodayOld">Joined today</string> + + <!-- Use value="" because of trailing spaces --> + <string name="AgeYears" value="[YEARS] years " /> + <string name="Age1Year" value="1 year "/> + <string name="AgeMonths" value="[MONTHS] months "/> + <string name="Age1Month" value="1 month "/> + <string name="AgeWeeks" value="[WEEKS] weeks "/> + <string name="Age1Week" value="1 week "/> + <string name="AgeDays" value="[DAYS] days "/> + <string name="Age1Day" value="1 day "/> + + <!-- Account types, see LLAvatarPropertiesProcessor --> + <string name="AcctTypeResident">Resident</string> + <string name="AcctTypeTrial">Trial</string> + <string name="AcctTypeCharterMember">Charter Member</string> + <string name="AcctTypeEmployee">Linden Lab Employee</string> + <string name="PaymentInfoUsed">Payment Info Used</string> + <string name="PaymentInfoOnFile">Payment Info On File</string> + <string name="NoPaymentInfoOnFile">No Payment Info On File</string> + <string name="AgeVerified">Age-verified</string> + <string name="NotAgeVerified">Not Age-verified</string> + + <!-- HUD Position --> <string name="Center 2">Center 2</string> <string name="Top Right">Top Right</string> <string name="Top">Top</string> @@ -2425,4 +2452,48 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="UpdaterFailStartTitle"> Failed to start viewer </string> + + <!-- IM system messages --> + <string name="only_user_message"> + You are the only user in this session. + </string> + <string name="offline_message"> + [FIRST] [LAST] is offline. + </string> + <string name="invite_message"> + Click the [BUTTON NAME] button to accept/connect to this voice chat. + </string> + <string name="muted_message"> + You have blocked this resident. Sending a message will automatically unblock them. + </string> + <string name="generic_request_error"> + Error making request, please try again later. + </string> + <string name="insufficient_perms_error"> + You do not have sufficient permissions. + </string> + <string name="session_does_not_exist_error"> + The session no longer exists + </string> + <string name="no_ability_error"> + You do not have that ability. + </string> + <string name="not_a_mod_error"> + You are not a session moderator. + </string> + <string name="muted_error"> + A group moderator disabled your text chat. + </string> + <string name="add_session_event"> + Unable to add users to chat session with [RECIPIENT]. + </string> + <string name="message_session_event"> + Unable to send your message to the chat session with [RECIPIENT]. + </string> + <string name="removed_from_group"> + You have been removed from the group. + </string> + <string name="close_on_no_ability"> + You no longer have the ability to be in the chat session. + </string> </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml new file mode 100644 index 0000000000..4a866c2eb2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater name="floater" + bg_opaque_color="FloaterFocusBackgroundColor" + bg_alpha_color="FloaterDefaultBackgroundColor" + background_visible="true" + background_opaque="false"/> diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 297a3762f6..a37ed76c51 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -17,6 +17,7 @@ show_text_as_tentative="false" max_chars="20" follows="left|top" + allow_new_values="true" > <info_button name="Place Information" label="" diff --git a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml index 1d43b25f1d..6e73e997e0 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml @@ -4,6 +4,8 @@ list_position="BELOW" show_text_as_tentative="false" dropdown_button_visible="false" + max_chars="256" + allow_new_values="true" background_image="TextField_Search_Off" background_image_disabled="TextField_Search_Disabled" background_image_focused="TextField_Search_Active"> diff --git a/indra/test/llhttpdate_tut.cpp b/indra/test/llhttpdate_tut.cpp index b9733dc030..8762938186 100644 --- a/indra/test/llhttpdate_tut.cpp +++ b/indra/test/llhttpdate_tut.cpp @@ -37,6 +37,9 @@ #include "lldate.h" #include "llframetimer.h" +#include <time.h> +#include <locale.h> + namespace tut { struct httpdate_data @@ -94,4 +97,70 @@ namespace tut // probably not a good idea to use strcmp but this is just a unit test ensure("Current time in RFC 1123", (strcmp(expected, actual.c_str()) == 0)); } + + void test_date_string(const std::string &locale, struct tm *t, + const std::string &fmt, const std::string &expected) + { + std::string result = LLDate::toHTTPDateString(t, fmt); + LLStringUtil::toLower(result); + std::string label = std::string("toHTTPDateString - ") + locale; + ensure_equals(label.c_str(), result, expected); + } + + template<> template<> + void httpdate_object::test<4>() + { + // test localization of http dates +#if LL_WINDOWS + const char *en_locale = "english"; + const char *fr_locale = "french"; +#else + const char *en_locale = "en_GB.UTF-8"; + const char *fr_locale = "fr_FR.UTF-8"; +#endif + + std::string prev_locale = LLStringUtil::getLocale(); + std::string prev_clocale = std::string(setlocale(LC_TIME, NULL)); + time_t test_time = 1252374030; // 8 Sep 2009 01:40:01 + struct tm *t = gmtime(&test_time); + + setlocale(LC_TIME, en_locale); + if (strcmp(setlocale(LC_TIME, NULL), en_locale) != 0) + { + setlocale(LC_TIME, prev_clocale.c_str()); + skip("Cannot set English locale"); + } + + LLStringUtil::setLocale(en_locale); + test_date_string(en_locale, t, "%d %B %Y - %H:%M", "08 september 2009 - 01:40"); + test_date_string(en_locale, t, "%H", "01"); + test_date_string(en_locale, t, "%M", "40"); + test_date_string(en_locale, t, "%I", "01"); + test_date_string(en_locale, t, "%d", "08"); + test_date_string(en_locale, t, "%Y", "2009"); + test_date_string(en_locale, t, "%p", "am"); + test_date_string(en_locale, t, "%A", "tuesday"); + test_date_string(en_locale, t, "%B", "september"); + + setlocale(LC_TIME, fr_locale); + if (strcmp(setlocale(LC_TIME, NULL), fr_locale) != 0) + { + LLStringUtil::setLocale(prev_locale); + setlocale(LC_TIME, prev_clocale.c_str()); + skip("Cannot set French locale"); + } + + LLStringUtil::setLocale(fr_locale); + test_date_string(fr_locale, t, "%d %B %Y - %H:%M", "08 septembre 2009 - 01:40"); + test_date_string(fr_locale, t, "%H", "01"); + test_date_string(fr_locale, t, "%M", "40"); + test_date_string(fr_locale, t, "%I", "01"); + test_date_string(fr_locale, t, "%d", "08"); + test_date_string(fr_locale, t, "%Y", "2009"); + test_date_string(fr_locale, t, "%A", "mardi"); + test_date_string(fr_locale, t, "%B", "septembre"); + + LLStringUtil::setLocale(prev_locale); + setlocale(LC_TIME, prev_clocale.c_str()); + } } diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h index 095a2ea3b3..c2b2baba95 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.h +++ b/indra/test_apps/llplugintest/llmediaplugintest.h @@ -35,6 +35,7 @@ #include <vector> #include <string> #include "llpluginclassmedia.h" +#include "llgl.h" // Forward declarations class GLUI_Rotation; |