From a67d2dd1a4c490eae337ae930eac98c714033711 Mon Sep 17 00:00:00 2001 From: James Cook Date: Tue, 8 Sep 2009 22:09:11 +0000 Subject: Remove llfasttimer.h from linden_common.h, not necessary and adds 15K lines of header code to every library .cpp file. --- indra/llcommon/linden_common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') 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" -- cgit v1.2.3 From 58bce2d205bee3f5adb33b15efe73098e77429eb Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Wed, 9 Sep 2009 01:26:44 +0000 Subject: merge -r132032-132812 svn+ssh://svn.lindenlab.com/svn/linden/branches/gooey/gooey-1 --- indra/llmath/llcoord.h | 9 + indra/llplugin/llpluginclassmedia.h | 2 +- indra/llplugin/llpluginclassmediaowner.h | 1 - indra/llui/CMakeLists.txt | 4 + indra/llui/llbutton.cpp | 29 +- indra/llui/llbutton.h | 1 - indra/llui/llcombobox.cpp | 23 +- indra/llui/llcombobox.h | 2 +- indra/llui/llfloater.cpp | 85 ++-- indra/llui/llfloater.h | 3 - indra/llui/lliconctrl.cpp | 10 +- indra/llui/lliconctrl.h | 2 - indra/llui/lllayoutstack.cpp | 2 + indra/llui/lllocalcliprect.cpp | 143 ++++++ indra/llui/lllocalcliprect.h | 53 +++ indra/llui/llmenugl.cpp | 2 +- indra/llui/llpanel.cpp | 28 +- indra/llui/llpanel.h | 13 +- indra/llui/llscrollbar.cpp | 2 +- indra/llui/llscrollcontainer.cpp | 1 + indra/llui/llscrolllistctrl.cpp | 15 +- indra/llui/llscrolllistctrl.h | 2 +- indra/llui/llsdparam.cpp | 10 +- indra/llui/llslider.cpp | 16 +- indra/llui/lltabcontainer.cpp | 7 +- indra/llui/lltabcontainer.h | 2 +- indra/llui/lltextbase.cpp | 18 +- indra/llui/lltextbase.h | 2 +- indra/llui/lltextbox.cpp | 21 +- indra/llui/lltextbox.h | 6 +- indra/llui/lltexteditor.cpp | 18 +- indra/llui/lltexteditor.h | 2 +- indra/llui/lltooltip.cpp | 445 ++++++++++++++++++ indra/llui/lltooltip.h | 127 +++++ indra/llui/llui.cpp | 121 ++--- indra/llui/llui.h | 73 ++- indra/llui/lluictrl.cpp | 4 - indra/llui/lluictrl.h | 1 - indra/llui/lluictrlfactory.cpp | 14 +- indra/llui/llview.cpp | 312 ++++++++----- indra/llui/llview.h | 122 ++--- indra/llui/llviewborder.cpp | 2 +- indra/llwindow/llmousehandler.h | 6 +- indra/llxuixml/llinitparam.cpp | 8 + indra/llxuixml/llinitparam.h | 8 +- indra/newview/CMakeLists.txt | 4 +- indra/newview/app_settings/settings.xml | 50 +- indra/newview/llappviewer.cpp | 5 +- indra/newview/llavatariconctrl.cpp | 2 +- indra/newview/llavatarpropertiesprocessor.cpp | 303 +++++++++--- indra/newview/llavatarpropertiesprocessor.h | 61 ++- indra/newview/llchatitemscontainerctrl.cpp | 1 + indra/newview/llchiclet.cpp | 1 + indra/newview/llcolorswatch.cpp | 7 +- indra/newview/llconfirmationmanager.cpp | 3 +- indra/newview/llfasttimerview.cpp | 19 +- indra/newview/llfasttimerview.h | 2 +- indra/newview/llfavoritesbar.cpp | 19 +- indra/newview/llfloateranimpreview.cpp | 2 +- indra/newview/llfloaterimagepreview.cpp | 2 +- indra/newview/llfloatersnapshot.cpp | 1 + indra/newview/llfloatertestinspectors.cpp | 109 +++++ indra/newview/llfloatertestinspectors.h | 64 +++ indra/newview/llglsandbox.cpp | 2 - indra/newview/llimpanel.cpp | 19 +- indra/newview/llimview.cpp | 113 +---- indra/newview/llimview.h | 13 - indra/newview/llinspectavatar.cpp | 173 ++++++- indra/newview/llinspectavatar.h | 38 +- indra/newview/lllocationinputctrl.cpp | 11 +- indra/newview/lllocationinputctrl.h | 2 +- indra/newview/llmaniprotate.cpp | 2 +- indra/newview/llmaniptranslate.cpp | 2 +- indra/newview/llmemoryview.cpp | 2 +- indra/newview/llnetmap.cpp | 25 +- indra/newview/llnetmap.h | 2 +- indra/newview/llpanelavatar.cpp | 67 +-- indra/newview/llpanelpick.cpp | 4 +- indra/newview/llpanelpicks.cpp | 4 +- indra/newview/llpanelplaceinfo.cpp | 2 +- indra/newview/llselectmgr.cpp | 48 +- indra/newview/llselectmgr.h | 4 +- indra/newview/lltextureview.cpp | 20 +- indra/newview/lltool.cpp | 16 +- indra/newview/lltool.h | 5 +- indra/newview/lltooldraganddrop.cpp | 8 +- indra/newview/lltooldraganddrop.h | 2 +- indra/newview/lltoolfocus.cpp | 8 +- indra/newview/lltoolgrab.cpp | 8 +- indra/newview/lltoolpie.cpp | 461 ++++++++++++++++-- indra/newview/lltoolpie.h | 3 + indra/newview/lltoolpipette.cpp | 13 +- indra/newview/lltoolpipette.h | 2 +- indra/newview/llviewerdisplay.cpp | 4 - indra/newview/llviewerfloaterreg.cpp | 3 + indra/newview/llviewermedia.cpp | 3 +- indra/newview/llviewermedia.h | 3 +- indra/newview/llviewermenu.cpp | 26 +- indra/newview/llviewerobject.cpp | 16 +- indra/newview/llviewerobject.h | 4 +- indra/newview/llviewerobjectlist.cpp | 12 +- indra/newview/llviewerparcelmedia.cpp | 2 +- indra/newview/llviewerparcelmgr.cpp | 8 +- indra/newview/llviewerparcelmgr.h | 2 +- indra/newview/llviewertexteditor.cpp | 39 -- indra/newview/llviewertexteditor.h | 1 - indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewerwindow.cpp | 516 ++++++--------------- indra/newview/llviewerwindow.h | 49 +- indra/newview/llvograss.cpp | 2 +- indra/newview/llworldmapview.cpp | 20 +- indra/newview/llworldmapview.h | 2 +- .../default/xui/en/floater_test_inspectors.xml | 110 +++++ .../skins/default/xui/en/inspect_avatar.xml | 43 +- indra/newview/skins/default/xui/en/menu_login.xml | 26 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 9 +- indra/newview/skins/default/xui/en/panel_login.xml | 40 +- .../newview/skins/default/xui/en/panel_profile.xml | 27 -- indra/newview/skins/default/xui/en/strings.xml | 77 ++- .../skins/default/xui/en/widgets/floater.xml | 6 + 120 files changed, 3007 insertions(+), 1556 deletions(-) create mode 100644 indra/llui/lllocalcliprect.cpp create mode 100644 indra/llui/lllocalcliprect.h create mode 100644 indra/llui/lltooltip.cpp create mode 100644 indra/llui/lltooltip.h create mode 100644 indra/newview/llfloatertestinspectors.cpp create mode 100644 indra/newview/llfloatertestinspectors.h create mode 100644 indra/newview/skins/default/xui/en/floater_test_inspectors.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/floater.xml (limited to 'indra') 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 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 button_flash_rate("ButtonFlashRate", 0); static LLUICachedControl 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 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..ef0d4c1c03 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; @@ -704,7 +705,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 +714,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..018d472d62 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -112,7 +112,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); 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 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(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/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 + +//--------------------------------------------------------------------------- +// 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 sClipRectStack; +}; + +/*static*/ std::stack 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..2bc4f009cc 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(); 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(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 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 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 @@ -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..bbf8e86660 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(); 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 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 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 text_color, disabled_color, - background_color, - border_color; + background_color; Optional 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 #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 + { + Mandatory visible_time; + + Optional click_callback; + Optional 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 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 (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(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 (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() + { + 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 +{ + Mandatory x, + y; + LLToolTipPosParams() + : x("x"), + y("y") + {} +}; + +struct LLToolTipParams : public LLInitParam::Block +{ + typedef boost::function click_callback_t; + + Mandatory message; + + Optional pos; + Optional delay_time, + visible_time; + Optional sticky_rect; + Optional width; + Optional image; + + Optional click_callback; + + LLToolTipParams(); + LLToolTipParams(const std::string& message); +}; + +class LLToolTipMgr : public LLSingleton +{ + 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 gUntranslated; /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL; /*static*/ LLView* LLUI::sRootView = NULL; -/*static*/ BOOL LLUI::sShowXUINames = FALSE; -/*static*/ std::stack LLScreenClipRect::sClipRectStack; /*static*/ std::vector LLUI::sXUIPaths; +/*static*/ LLFrameTimer LLUI::sMouseIdleTimer; // register filtereditor here static LLDefaultChildRegistry::Register 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 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::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::getValueFromBlock() const + { + return LLCoordGL(x, y); + } + + void TypeValues::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 #include "lluiimage.h" // *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional 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 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 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 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 super_t; public: - Optional red; - Optional green; - Optional blue; - Optional alpha; + Optional red, + green, + blue, + alpha; Optional 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 super_t; public: - Optional name; - Optional size; - Optional style; + Optional 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 + : public BlockValue + { + typedef BlockValue super_t; + public: + Optional 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::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(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 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 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 sDrawContextStack; +}; class LLViewWidgetRegistry : public LLChildRegistry {}; @@ -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 tree_iterator_t; - tree_iterator_t beginTree(); - tree_iterator_t endTree(); + tree_iterator_t beginTreeDFS(); + tree_iterator_t endTreeDFS(); + + typedef LLTreeDFSPostIter tree_post_iterator_t; + tree_post_iterator_t beginTreeDFSPost(); + tree_post_iterator_t endTreeDFSPost(); + + + typedef LLTreeDownIter 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 @@ -516,6 +516,14 @@ namespace LLInitParam return false; } + template<> + bool ParamCompare >::equals( + const boost::function &a, + const boost::function &b) + { + return false; + } + template<> bool ParamCompare::equals(const LLSD &a, const LLSD &b) { 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 >::equals( const boost::function &a, const boost::function &b); - + + template<> + bool ParamCompare >::equals( + const boost::function &a, + const boost::function &b); + + template<> bool ParamCompare::equals(const LLSD &a, const LLSD &b); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f4194ed511..321a238f70 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 @@ Value 0 - DebugStatModeFPS + DebugShowXUINames + + Comment + Show tooltips with XUI path to widget + Persist + 0 + Type + Boolean + Value + 0 + + DebugStatModeFPS Comment Mode of stat in Statistics floater @@ -3642,6 +3653,17 @@ Value 0.0 + InspectorFadeTime + + Comment + Fade out timing for inspectors + Persist + 1 + Type + F32 + Value + 0.1 + InstallLanguage Comment @@ -6864,7 +6886,7 @@ Type Boolean Value - 0 + 1 ShowCameraAndMoveControls @@ -7309,17 +7331,6 @@ Value 0 - ShowXUINames - - Comment - Display XUI Names as Tooltips - Persist - 0 - Type - Boolean - Value - 0 - SkinCurrent Comment @@ -7713,7 +7724,18 @@ Value 0.2 - ToolboxAutoMove + ToolTipVisibleTime + + Comment + Fade tooltip after mouse is idle for this long + Persist + 1 + Type + F32 + Value + 10.0 + + ToolboxAutoMove Comment [NOT USED] 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(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 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(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(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 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, U32> timestamp_map_t; + timestamp_map_t mRequestTimestamps; }; #endif // LL_LLAVATARPROPERTIESPROCESSOR_H 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..197ab9d352 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" 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..df2bf53a05 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; } 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/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("avatar_2d_btn")->setCommitCallback( +// boost::bind(&LLFloaterTestInspectors::onClickAvatar2D, this)); + getChild("avatar_3d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickAvatar3D, this)); + getChild("object_2d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickObject2D, this)); + getChild("object_3d_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickObject3D, this)); + getChild("group_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickGroup, this)); + getChild("place_btn")->setCommitCallback( + boost::bind(&LLFloaterTestInspectors::onClickPlace, this)); + getChild("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/llimpanel.cpp b/indra/newview/llimpanel.cpp index 674fff4040..020eff375b 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; 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 LLFloaterIM::sEventStringsMap; -std::map LLFloaterIM::sErrorStringsMap; -std::map LLFloaterIM::sForceCloseSessionMap; std::map LLIMModel::sSessionsMap; @@ -749,101 +742,6 @@ LLUUID LLIMMgr::computeSessionID( return session_id; } -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// 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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -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 { @@ -269,18 +268,6 @@ private: LLUUID mBeingRemovedSessionID; }; - -class LLFloaterIM : public LLMultiFloater -{ -public: - LLFloaterIM(); - /*virtual*/ BOOL postBuild(); - - static std::map sEventStringsMap; - static std::map sErrorStringsMap; - static std::map 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(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("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 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("user_subtitle")-> + setValue("Test subtitle"); + getChild("user_details")-> + setValue("Test details\nTest line 2"); + return; + } + + // Clear out old data so it doesn't flash between old and new + getChild("user_name")->setValue(""); + getChild("user_subtitle")->setValue(""); + getChild("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("user_subtitle")->setValue( LLSD(subtitle) ); + std::string details = getString("Details", args); + getChild("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..d8c89690e8 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,8 +317,7 @@ 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) 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/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/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 objects; + std::vector objects; root->addThisAndNonJointChildren(objects); addAsFamily(objects, add_to_end); @@ -439,7 +439,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector objects; + std::vector 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 objects; + std::vector 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 objects; objectp = objectp->getRootEdit(); - objectp->addThisAndNonJointChildren(objects); - for (std::vector::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 objects; + objectp = objectp->getRootEdit(); + objectp->addThisAndNonJointChildren(objects); + + for (std::vector::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 objects; + std::vector 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::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/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 mClickActionObject; U8 mClickAction; LLSafeHandle 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 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); LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build); + LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", + &LLFloaterReg::build); LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build); LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build); LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); 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 // 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 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& objects) +void LLViewerObject::addThisAndAllChildren(std::vector& 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& obje } } -void LLViewerObject::addThisAndNonJointChildren(LLDynamicArray& objects) +void LLViewerObject::addThisAndNonJointChildren(std::vector& 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& objects); - void addThisAndNonJointChildren(LLDynamicArray& objects); + void addThisAndAllChildren(std::vector& objects); + void addThisAndNonJointChildren(std::vector& 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..a088006c53 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(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(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 (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 (params); + getRootView()->addChild(gNotifyBoxView, -2); + + // View for tooltips + LLToolTipView::Params hvp; + hvp.name("tooltip view"); + hvp.rect(full_window); + gToolTipView = LLUICtrlFactory::create(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(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(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) && @@ -2360,14 +2236,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 +2290,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 +2322,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(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 +2372,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 +2410,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 +2431,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 +2445,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 +2548,87 @@ void LLViewerWindow::updateUI() } } - if( !handled ) + if (!handled) { - lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl; - } - } - - // *NOTE: sometimes tools handle the mouse as a captor, so this - // logic is a little confusing - LLTool *tool = NULL; - if (gHoverView) - { - tool = LLToolMgr::getInstance()->getCurrentTool(); - - if(!handled && tool) - { - handled = tool->handleHover(x, y, mask); + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (!mWindow->isCursorHidden()) + if(mMouseInWindow && tool) { - gHoverView->updateHover(tool); + handled = tool->handleHover(x, y, mask); } } - else - { - // Cancel hovering if any UI element handled the event. - gHoverView->cancelHover(); - } - - // Suppress the toolbox view if our source tool was the pie tool, - // and we've overridden to something else. - mSuppressToolbox = - (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) && - (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()); - } - // Show a new tool tip (or update one that is alrady shown) + // Show a new tool tip (or update one that is already shown) BOOL tool_tip_handled = FALSE; std::string tool_tip_msg; if( handled - && !mWindow->isCursorHidden() - && mToolTip) + && !mWindow->isCursorHidden()) { - LLRect screen_sticky_rect; - LLMouseHandler *tooltip_source = NULL; + LLRect screen_sticky_rect = mRootView->getLocalRect(); S32 local_x, local_y; - if (mouse_captor) - { - mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); - tooltip_source = mouse_captor; - } - else if (handled_by_top_ctrl) - { - top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); - tooltip_source = top_ctrl; - } - else - { - local_x = x; local_y = y; - tooltip_source = mRootView; - } - F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" ); - //HACK: hack for tool-based tooltips which need to pop up more quickly - //Also for show xui names as tooltips debug mode - if ((gFocusMgr.getMouseCapture() - && !gFocusMgr.getMouseCapture()->isView()) - || LLUI::sShowXUINames) + if (gSavedSettings.getBOOL("DebugShowXUINames")) { - tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" ); - } - - - BOOL tooltip_vis = FALSE; - if (shouldShowToolTipFor(tooltip_source)) - { - tool_tip_handled = tooltip_source->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect ); - - // if we actually got a tooltip back... - if( tool_tip_handled && !tool_tip_msg.empty() ) + LLView* tooltip_view = mRootView; + LLView::tree_iterator_t end_it = mRootView->endTreeDFS(); + for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it) { - if (mToolTip->getVisible() // already showing a tooltip - || gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay) // mouse has been still long enough to show the tooltip + LLView* viewp = *it; + LLRect screen_rect; + viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); + if (!(viewp->getVisible() + && screen_rect.pointInRect(x, y))) + { + 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 +2645,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 +2658,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 +2671,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 +2856,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 +3101,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 +3135,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 +4706,6 @@ F32 LLViewerWindow::getWorldViewAspectRatio() const } } -void LLViewerWindow::drawPickBuffer() const -{ - mHoverPick.drawPickBuffer(); -} - void LLViewerWindow::calcDisplayScale() { F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); @@ -5153,49 +4954,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; @@ -69,6 +68,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, @@ -81,20 +91,10 @@ public: void fetchResults(); LLPointer 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 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 @@ + + + + Click to spawn an inspector: + + +