From 3dd2641818f9be3a6a38c8223658814644b06ce8 Mon Sep 17 00:00:00 2001 From: Boroondas Gupte Date: Fri, 8 Oct 2010 01:35:14 +0200 Subject: VWR-23239 FIXED memory leak in LLUIString --- indra/llui/lluistring.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 3f91856e26..1ecd9bab36 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -68,6 +68,8 @@ public: LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args); LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); } + ~LLUIString() { delete mArgs; } + void assign(const std::string& instring); LLUIString& operator=(const std::string& s) { assign(s); return *this; } -- cgit v1.2.3 From ea2005edf062b69e88261e2a824bdbb6e2b2db7d Mon Sep 17 00:00:00 2001 From: Boroondas Gupte Date: Fri, 8 Oct 2010 00:53:55 +0200 Subject: fixed indentation in lluistring.h --- indra/llui/lluistring.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 1ecd9bab36..6a3a9dba46 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -64,7 +64,7 @@ class LLUIString public: // These methods all perform appropriate argument substitution // and modify mOrig where appropriate - LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {} + LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {} LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args); LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); } @@ -89,14 +89,14 @@ public: void clear(); void clearArgs() { if (mArgs) mArgs->clear(); } - + // These utility functions are included for text editing. // They do not affect mOrig and do not perform argument substitution void truncate(S32 maxchars); void erase(S32 charidx, S32 len); void insert(S32 charidx, const LLWString& wchars); void replace(S32 charidx, llwchar wc); - + private: // something changed, requiring reformatting of strings void dirty(); @@ -108,7 +108,7 @@ private: void updateResult() const; void updateWResult() const; LLStringUtil::format_map_t& getArgs(); - + std::string mOrig; mutable std::string mResult; mutable LLWString mWResult; // for displaying -- cgit v1.2.3 From 401fdbcfac1d7e8b6b91c958a23ec6705dfe4e07 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 13 Oct 2010 00:54:57 +0300 Subject: STORM-294 FIXED keyboard navigation in Favorites bar overflow menu. The menu items can now be scrolled cyclically with a keyboard even if not all items are visible at once. --- indra/llui/llmenugl.cpp | 205 +++++++++++++++++++++++++++++++----------------- indra/llui/llmenugl.h | 12 ++- 2 files changed, 142 insertions(+), 75 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 6d590cf54e..a6cf86d9b8 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1848,89 +1848,104 @@ BOOL LLMenuGL::isOpen() } } -void LLMenuGL::scrollItemsUp() + + +bool LLMenuGL::scrollItems(EScrollingDirection direction) { - // Slowing down the items scrolling when arrow button is held + // Slowing down items scrolling when arrow button is held if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem) { mScrollItemsTimer.setTimerExpirySec(.033f); } else { - return; + return false; } - item_list_t::iterator cur_item_iter; - item_list_t::iterator prev_item_iter; - for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) + switch (direction) { - if( (*cur_item_iter) == mFirstVisibleItem) + case SD_UP: + { + item_list_t::iterator cur_item_iter; + item_list_t::iterator prev_item_iter; + for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) { - break; + if( (*cur_item_iter) == mFirstVisibleItem) + { + break; + } + if ((*cur_item_iter)->getVisible()) + { + prev_item_iter = cur_item_iter; + } } - if ((*cur_item_iter)->getVisible()) + + if ((*prev_item_iter)->getVisible()) { - prev_item_iter = cur_item_iter; + mFirstVisibleItem = *prev_item_iter; } + break; } - - if ((*prev_item_iter)->getVisible()) - { - mFirstVisibleItem = *prev_item_iter; - } - - mNeedsArrange = TRUE; - arrangeAndClear(); -} - -void LLMenuGL::scrollItemsDown() -{ - // Slowing down the items scrolling when arrow button is held - if (mScrollItemsTimer.hasExpired()) - { - mScrollItemsTimer.setTimerExpirySec(.033f); - } - else - { - return; - } - - if (NULL == mFirstVisibleItem) - { - mFirstVisibleItem = *mItems.begin(); - } - - item_list_t::iterator cur_item_iter; - - for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) + case SD_DOWN: { - if( (*cur_item_iter) == mFirstVisibleItem) + if (NULL == mFirstVisibleItem) { - break; + mFirstVisibleItem = *mItems.begin(); } - } - item_list_t::iterator next_item_iter; + item_list_t::iterator cur_item_iter; - if (cur_item_iter != mItems.end()) - { - for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++) + for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) { - if( (*next_item_iter)->getVisible()) + if( (*cur_item_iter) == mFirstVisibleItem) { break; } } - - if (next_item_iter != mItems.end() && - (*next_item_iter)->getVisible()) + + item_list_t::iterator next_item_iter; + + if (cur_item_iter != mItems.end()) { - mFirstVisibleItem = *next_item_iter; + for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++) + { + if( (*next_item_iter)->getVisible()) + { + break; + } + } + + if (next_item_iter != mItems.end() && + (*next_item_iter)->getVisible()) + { + mFirstVisibleItem = *next_item_iter; + } } + break; } - + case SD_BEGIN: + { + mFirstVisibleItem = *mItems.begin(); + break; + } + case SD_END: + { + item_list_t::reverse_iterator first_visible_item_iter = mItems.rend(); + + // Advance by mMaxScrollableItems back from the end of the list + // to make the last item visible. + std::advance(first_visible_item_iter, mMaxScrollableItems); + mFirstVisibleItem = *first_visible_item_iter; + break; + } + default: + llwarns << "Unknown scrolling direction: " << direction << llendl; + } + mNeedsArrange = TRUE; arrangeAndClear(); + + return true; } // rearrange the child rects so they fit the shape of the menu. @@ -2162,7 +2177,7 @@ void LLMenuGL::arrange( void ) LLMenuScrollItem::Params item_params; item_params.name(ARROW_UP); item_params.arrow_type(LLMenuScrollItem::ARROW_UP); - item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsUp, this)); + item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP)); mArrowUpItem = LLUICtrlFactory::create(item_params); LLUICtrl::addChild(mArrowUpItem); @@ -2173,7 +2188,7 @@ void LLMenuGL::arrange( void ) LLMenuScrollItem::Params item_params; item_params.name(ARROW_DOWN); item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN); - item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsDown, this)); + item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN)); mArrowDownItem = LLUICtrlFactory::create(item_params); LLUICtrl::addChild(mArrowDownItem); @@ -2603,14 +2618,8 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa ((LLFloater*)getParent())->setFocus(TRUE); } - item_list_t::iterator cur_item_iter; - for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); ++cur_item_iter) - { - if( (*cur_item_iter) == cur_item) - { - break; - } - } + // Current item position in the items list + item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item); item_list_t::iterator next_item_iter; if (cur_item_iter == mItems.end()) @@ -2621,9 +2630,37 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa { next_item_iter = cur_item_iter; next_item_iter++; + + // First visible item position in the items list + item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem); + if (next_item_iter == mItems.end()) { next_item_iter = mItems.begin(); + + // If current item is the last in the list, the menu is scrolled to the beginning + // and the first item is highlighted. + if (mScrollable && !scrollItems(SD_BEGIN)) + { + return NULL; + } + } + // If current item is the last visible, the menu is scrolled one item down + // and the next item is highlighted. + else if (mScrollable && + (U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems) + { + // Call highlightNextItem() recursively only if the menu was successfully scrolled down. + // If scroll timer hasn't expired yet the menu won't be scrolled and calling + // highlightNextItem() will result in an endless recursion. + if (scrollItems(SD_DOWN)) + { + return highlightNextItem(cur_item, skip_disabled); + } + else + { + return NULL; + } } } @@ -2681,14 +2718,8 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa ((LLFloater*)getParent())->setFocus(TRUE); } - item_list_t::reverse_iterator cur_item_iter; - for (cur_item_iter = mItems.rbegin(); cur_item_iter != mItems.rend(); ++cur_item_iter) - { - if( (*cur_item_iter) == cur_item) - { - break; - } - } + // Current item reverse position from the end of the list + item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item); item_list_t::reverse_iterator prev_item_iter; if (cur_item_iter == mItems.rend()) @@ -2699,9 +2730,37 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa { prev_item_iter = cur_item_iter; prev_item_iter++; + + // First visible item reverse position in the items list + item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem); + if (prev_item_iter == mItems.rend()) { prev_item_iter = mItems.rbegin(); + + // If current item is the first in the list, the menu is scrolled to the end + // and the last item is highlighted. + if (mScrollable && !scrollItems(SD_END)) + { + return NULL; + } + } + // If current item is the first visible, the menu is scrolled one item up + // and the previous item is highlighted. + else if (mScrollable && + std::distance(first_visible_item_iter, cur_item_iter) <= 0) + { + // Call highlightNextItem() only if the menu was successfully scrolled up. + // If scroll timer hasn't expired yet the menu won't be scrolled and calling + // highlightNextItem() will result in an endless recursion. + if (scrollItems(SD_UP)) + { + return highlightPrevItem(cur_item, skip_disabled); + } + else + { + return NULL; + } } } @@ -2872,12 +2931,12 @@ BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks ) if( clicks > 0 ) { while( clicks-- ) - scrollItemsDown(); + scrollItems(SD_DOWN); } else { while( clicks++ ) - scrollItemsUp(); + scrollItems(SD_UP); } return TRUE; diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 19b738312e..35544402f4 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -397,6 +397,15 @@ public: static const std::string ARROW_UP; static const std::string ARROW_DOWN; + // for scrollable menus + typedef enum e_scrolling_direction + { + SD_UP = 0, + SD_DOWN = 1, + SD_BEGIN = 2, + SD_END = 3 + } EScrollingDirection; + protected: LLMenuGL(const LLMenuGL::Params& p); friend class LLUICtrlFactory; @@ -503,8 +512,7 @@ public: S32 getShortcutPad() { return mShortcutPad; } - void scrollItemsUp(); - void scrollItemsDown(); + bool scrollItems(EScrollingDirection direction); BOOL isScrollable() const { return mScrollable; } static class LLMenuHolderGL* sMenuContainer; -- cgit v1.2.3 From c12c60df4a28b3cb91870ae0666eb6b3422ff96b Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Fri, 15 Oct 2010 00:10:55 +0300 Subject: STORM-263 FIXED popup menu of Cog button in lower-left of sidebar panel closing on second click - Changed type of gear menu buttons from LLButton to LLMenuButton in all sidebar panels where gear menu button is used. - Added setMenuPosition(), setMenu() and updateMenuOrigin() to the LLMenuButton. - Moved actions common for displaying a context menu to LLMenuButton::toggleMenu(). - In all sidebar panels where LLButton was replaced with LLMenuButton the following steps were taken: 1. setting gearMenu and its position relative to the menuButton with LLMenuButton::setMenu() 2. setting mouse down callback for the menuButton if needed. 3. calculating the menu origin point with LLMenuButton::updateMenuOrigin() in mouse down callback --- indra/llui/llmenubutton.cpp | 108 ++++++++++++++++++++++++++++---------------- indra/llui/llmenubutton.h | 26 +++++++++-- 2 files changed, 92 insertions(+), 42 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 3df05f4d3f..c1b5efaa72 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -45,7 +45,8 @@ LLMenuButton::Params::Params() LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) : LLButton(p), mMenu(NULL), - mMenuVisibleLastFrame(false) + mMenuVisibleLastFrame(false), + mMenuPosition(MP_BOTTOM_LEFT) { std::string menu_filename = p.menu_filename; @@ -57,38 +58,51 @@ LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) llwarns << "Error loading menu_button menu" << llendl; } } + + updateMenuOrigin(); } -void LLMenuButton::toggleMenu() +boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) { - if(!mMenu) - return; + return LLUICtrl::setMouseDownCallback(cb); +} - if (mMenu->getVisible() || mMenuVisibleLastFrame) - { - mMenu->setVisible(FALSE); - } - else +void LLMenuButton::hideMenu() +{ + if(!mMenu) return; + mMenu->setVisible(FALSE); +} + +void LLMenuButton::setMenu(LLMenuGL* menu, EMenuPosition position /*MP_TOP_LEFT*/) +{ + mMenu = menu; + mMenuPosition = position; +} + +void LLMenuButton::draw() +{ + //we save this off so next frame when we try to close it by + //button click, and it hides menus before we get to it, we know + mMenuVisibleLastFrame = mMenu && mMenu->getVisible(); + + if (mMenuVisibleLastFrame) { - LLRect rect = getRect(); - //mMenu->needsArrange(); //so it recalculates the visible elements - LLMenuGL::showPopup(getParent(), mMenu, rect.mLeft, rect.mBottom); + setForcePressedState(true); } -} + LLButton::draw(); -void LLMenuButton::hideMenu() -{ - if(!mMenu) - return; - mMenu->setVisible(FALSE); + setForcePressedState(false); } - BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) { if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) { + // *HACK: We emit the mouse down signal to fire the callback bound to the + // menu emerging event before actually displaying the menu. See STORM-263. + LLUICtrl::handleMouseDown(-1, -1, MASK_NONE); + toggleMenu(); return TRUE; } @@ -104,34 +118,52 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) { - if (hasTabStop() && !getIsChrome()) - { - setFocus(TRUE); - } - + LLButton::handleMouseDown(x, y, mask); toggleMenu(); - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } - return TRUE; } -void LLMenuButton::draw() +void LLMenuButton::toggleMenu() { - //we save this off so next frame when we try to close it by - //button click, and it hides menus before we get to it, we know - mMenuVisibleLastFrame = mMenu && mMenu->getVisible(); - - if (mMenuVisibleLastFrame) + if(!mMenu) return; + + if (mMenu->getVisible() || mMenuVisibleLastFrame) { - setForcePressedState(true); + mMenu->setVisible(FALSE); } + else + { + mMenu->buildDrawLabels(); + mMenu->arrangeAndClear(); + mMenu->updateParent(LLMenuGL::sMenuContainer); - LLButton::draw(); + updateMenuOrigin(); - setForcePressedState(false); + //mMenu->needsArrange(); //so it recalculates the visible elements + LLMenuGL::showPopup(getParent(), mMenu, mX, mY); + } } +void LLMenuButton::updateMenuOrigin() +{ + if (!mMenu) return; + + LLRect rect = getRect(); + + switch (mMenuPosition) + { + case MP_TOP_LEFT: + { + mX = rect.mLeft; + mY = rect.mTop + mMenu->getRect().getHeight(); + break; + } + case MP_BOTTOM_LEFT: + { + mX = rect.mLeft; + mY = rect.mBottom; + break; + } + } +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 81ca0e047c..81c3592b16 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -42,22 +42,40 @@ public: Optional menu_filename; Params(); - }; + }; + + typedef enum e_menu_position + { + MP_TOP_LEFT, + MP_BOTTOM_LEFT + } EMenuPosition; - void toggleMenu(); + boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); + /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); + void hideMenu(); + LLMenuGL* getMenu() { return mMenu; } + void setMenu(LLMenuGL* menu, EMenuPosition position = MP_TOP_LEFT); + + void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } protected: friend class LLUICtrlFactory; LLMenuButton(const Params&); + void toggleMenu(); + void updateMenuOrigin(); + private: - LLMenuGL* mMenu; - bool mMenuVisibleLastFrame; + LLMenuGL* mMenu; + bool mMenuVisibleLastFrame; + EMenuPosition mMenuPosition; + S32 mX; + S32 mY; }; -- cgit v1.2.3 From d97355a19f3b88512105965cfd752956f0230b41 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Tue, 19 Oct 2010 19:55:19 +0300 Subject: STORM-390 FIXED "Place Profile" appeared instead of "Resident Profile" after clicking on user name in a nearby chat toast. Now clicking an avatar name opens avatar profile; clicking an object name opens object inspector. This change rolls back the fix of STORM-358. --- indra/llui/lltextbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 9adeddca99..758df418e8 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1622,7 +1622,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para style_params.fillFrom(getDefaultStyleParams()); S32 part = (S32)LLTextParser::WHOLE; - if(mParseHTML) + if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). { S32 start=0,end=0; LLUrlMatch match; -- cgit v1.2.3 From 07353619d0069acc9933bed2772e0e6925636efb Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Fri, 22 Oct 2010 19:39:38 +0300 Subject: STORM-297 FIXED Fixed "" text appearing in confirmation message if there is "<" symbol in Landmarks name. Modified the "..." clause parsing regexp to allow "<" in the middle. --- indra/llui/llurlentry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index f58c07754f..f49dfec82b 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -972,7 +972,7 @@ std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const // LLUrlEntryNoLink::LLUrlEntryNoLink() { - mPattern = boost::regex("[^<]*", + mPattern = boost::regex(".*", boost::regex::perl|boost::regex::icase); } -- cgit v1.2.3 From 54da19fdcfa3edadbc58a1f55a3503082e66f16e Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Fri, 22 Oct 2010 02:08:26 +0300 Subject: STORM-426 FIXED Menu button no longer looked pressed while its menu is displayed by another control. - LLMenuGL in menu button replaced by LLToggleableMenu that handles visibility change upon clicks inside specific button rect. - Added visibility change signal to LLToggleableMenu to update menu button pressed state. - Added using menu handle in LLMenuButton. --- indra/llui/llmenubutton.cpp | 100 ++++++++++++++++++++++++++-------------- indra/llui/llmenubutton.h | 19 ++++---- indra/llui/lltoggleablemenu.cpp | 18 ++++++++ indra/llui/lltoggleablemenu.h | 5 ++ 4 files changed, 98 insertions(+), 44 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index c1b5efaa72..ac568a83e4 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -29,7 +29,7 @@ #include "llmenubutton.h" // Linden library includes -#include "llmenugl.h" +#include "lltoggleablemenu.h" #include "llstring.h" #include "v4color.h" @@ -44,22 +44,26 @@ LLMenuButton::Params::Params() LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) : LLButton(p), - mMenu(NULL), - mMenuVisibleLastFrame(false), + mIsMenuShown(false), mMenuPosition(MP_BOTTOM_LEFT) { std::string menu_filename = p.menu_filename; if (!menu_filename.empty()) { - mMenu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!mMenu) + LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) { llwarns << "Error loading menu_button menu" << llendl; + return; } - } - updateMenuOrigin(); + menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); + + mMenuHandle = menu->getHandle(); + + updateMenuOrigin(); + } } boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) @@ -69,34 +73,34 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign void LLMenuButton::hideMenu() { - if(!mMenu) return; - mMenu->setVisible(FALSE); + if(mMenuHandle.isDead()) return; + + LLToggleableMenu* menu = dynamic_cast(mMenuHandle.get()); + if (menu) + { + menu->setVisible(FALSE); + } } -void LLMenuButton::setMenu(LLMenuGL* menu, EMenuPosition position /*MP_TOP_LEFT*/) +LLToggleableMenu* LLMenuButton::getMenu() { - mMenu = menu; - mMenuPosition = position; + return dynamic_cast(mMenuHandle.get()); } -void LLMenuButton::draw() +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/) { - //we save this off so next frame when we try to close it by - //button click, and it hides menus before we get to it, we know - mMenuVisibleLastFrame = mMenu && mMenu->getVisible(); - - if (mMenuVisibleLastFrame) - { - setForcePressedState(true); - } + if (!menu) return; - LLButton::draw(); + mMenuHandle = menu->getHandle(); + mMenuPosition = position; - setForcePressedState(false); + menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); } BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) { + if (mMenuHandle.isDead()) return FALSE; + if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) { // *HACK: We emit the mouse down signal to fire the callback bound to the @@ -107,9 +111,10 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) return TRUE; } - if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) + LLToggleableMenu* menu = dynamic_cast(mMenuHandle.get()); + if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) { - mMenu->setVisible(FALSE); + menu->setVisible(FALSE); return TRUE; } @@ -119,6 +124,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) { LLButton::handleMouseDown(x, y, mask); + toggleMenu(); return TRUE; @@ -126,28 +132,38 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) void LLMenuButton::toggleMenu() { - if(!mMenu) return; + if(mMenuHandle.isDead()) return; + + LLToggleableMenu* menu = dynamic_cast(mMenuHandle.get()); + if (!menu) return; - if (mMenu->getVisible() || mMenuVisibleLastFrame) + // Store the button rectangle to toggle menu visibility if a mouse event + // occurred inside or outside the button rect. + menu->setButtonRect(this); + + if (!menu->toggleVisibility() && mIsMenuShown) { - mMenu->setVisible(FALSE); + setForcePressedState(false); + mIsMenuShown = false; } else { - mMenu->buildDrawLabels(); - mMenu->arrangeAndClear(); - mMenu->updateParent(LLMenuGL::sMenuContainer); + menu->buildDrawLabels(); + menu->arrangeAndClear(); + menu->updateParent(LLMenuGL::sMenuContainer); updateMenuOrigin(); - //mMenu->needsArrange(); //so it recalculates the visible elements - LLMenuGL::showPopup(getParent(), mMenu, mX, mY); + LLMenuGL::showPopup(getParent(), menu, mX, mY); + + setForcePressedState(true); + mIsMenuShown = true; } } void LLMenuButton::updateMenuOrigin() { - if (!mMenu) return; + if (mMenuHandle.isDead()) return; LLRect rect = getRect(); @@ -156,7 +172,7 @@ void LLMenuButton::updateMenuOrigin() case MP_TOP_LEFT: { mX = rect.mLeft; - mY = rect.mTop + mMenu->getRect().getHeight(); + mY = rect.mTop + mMenuHandle.get()->getRect().getHeight(); break; } case MP_BOTTOM_LEFT: @@ -167,3 +183,17 @@ void LLMenuButton::updateMenuOrigin() } } } + +void LLMenuButton::onMenuVisibilityChange(const LLSD& param) +{ + bool new_visibility = param["visibility"].asBoolean(); + bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean(); + + // Reset the button "pressed" state only if the menu is shown by this particular + // menu button (not any other control) and is not being closed by a click on the button. + if (!new_visibility && !is_closed_by_button_click && mIsMenuShown) + { + setForcePressedState(false); + mIsMenuShown = false; + } +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 81c3592b16..9e91b9e99d 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -29,7 +29,7 @@ #include "llbutton.h" -class LLMenuGL; +class LLToggleableMenu; class LLMenuButton : public LLButton @@ -52,14 +52,13 @@ public: boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); - /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); void hideMenu(); - LLMenuGL* getMenu() { return mMenu; } - void setMenu(LLMenuGL* menu, EMenuPosition position = MP_TOP_LEFT); + LLToggleableMenu* getMenu(); + void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT); void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } @@ -70,12 +69,14 @@ protected: void toggleMenu(); void updateMenuOrigin(); + void onMenuVisibilityChange(const LLSD& param); + private: - LLMenuGL* mMenu; - bool mMenuVisibleLastFrame; - EMenuPosition mMenuPosition; - S32 mX; - S32 mY; + LLHandle mMenuHandle; + bool mIsMenuShown; + EMenuPosition mMenuPosition; + S32 mX; + S32 mY; }; diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp index 0eb2dc1387..d29260750f 100644 --- a/indra/llui/lltoggleablemenu.cpp +++ b/indra/llui/lltoggleablemenu.cpp @@ -35,10 +35,22 @@ static LLDefaultChildRegistry::Register r("toggleable_menu"); LLToggleableMenu::LLToggleableMenu(const LLToggleableMenu::Params& p) : LLMenuGL(p), mButtonRect(), + mVisibilityChangeSignal(NULL), mClosedByButtonClick(false) { } +LLToggleableMenu::~LLToggleableMenu() +{ + delete mVisibilityChangeSignal; +} + +boost::signals2::connection LLToggleableMenu::setVisibilityChangeCallback(const commit_signal_t::slot_type& cb) +{ + if (!mVisibilityChangeSignal) mVisibilityChangeSignal = new commit_signal_t(); + return mVisibilityChangeSignal->connect(cb); +} + // virtual void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn) { @@ -49,6 +61,12 @@ void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn) { mClosedByButtonClick = true; } + + if (mVisibilityChangeSignal) + { + (*mVisibilityChangeSignal)(this, + LLSD().with("visibility", curVisibilityIn).with("closed_by_button_click", mClosedByButtonClick)); + } } void LLToggleableMenu::setButtonRect(const LLRect& rect, LLView* current_view) diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index f036cdfffb..2094bd776f 100644 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -41,6 +41,10 @@ protected: LLToggleableMenu(const Params&); friend class LLUICtrlFactory; public: + ~LLToggleableMenu(); + + boost::signals2::connection setVisibilityChangeCallback( const commit_signal_t::slot_type& cb ); + virtual void handleVisibilityChange (BOOL curVisibilityIn); const LLRect& getButtonRect() const { return mButtonRect; } @@ -57,6 +61,7 @@ public: protected: bool mClosedByButtonClick; LLRect mButtonRect; + commit_signal_t* mVisibilityChangeSignal; }; #endif // LL_LLTOGGLEABLEMENU_H -- cgit v1.2.3 From f3d4643b5907dec71183e4f0927c0e5a6fc48c70 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Thu, 28 Oct 2010 23:03:09 +0300 Subject: STORM-489 FIXED 'ed text rendered as URL Changes: * Suppressed URLs in object (sender) names of nearby chat messages loaded from history. * Fixed text between ... text being rendered as URL (hand cursor on hover, context menu, context menu, opening Places SP on click). --- indra/llui/llurlentry.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index f49dfec82b..84678ef4db 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -989,7 +989,8 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC LLStyle::Params LLUrlEntryNoLink::getStyle() const { - return LLStyle::Params(); + // Don't render as URL (i.e. no context menu or hand cursor). + return LLStyle::Params().is_link(false); } -- cgit v1.2.3 From 463969116fa64c6f90cd7eb455e2432db375d359 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Fri, 29 Oct 2010 23:48:46 +0300 Subject: STORM-501 FIXED Script-editor shows ERRORS in the wrong line. LLTextBase::setCursor() sometimes failed to work properly if line wrapping was enabled. This is a slightly optimized version of the patch made by Satomi Ahn. --- indra/llui/lltextbase.cpp | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 758df418e8..5721df6b36 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2214,19 +2214,39 @@ bool LLTextBase::scrolledToEnd() return mScroller->isAtBottom(); } - bool LLTextBase::setCursor(S32 row, S32 column) { - if (0 <= row && row < (S32)mLineInfoList.size()) + if (row < 0 || column < 0) return false; + + S32 n_lines = mLineInfoList.size(); + for (S32 line = row; line < n_lines; ++line) { - S32 doc_pos = mLineInfoList[row].mDocIndexStart; - column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1); - doc_pos += column; - updateCursorXPos(); + const line_info& li = mLineInfoList[line]; + + if (li.mLineNum < row) + { + continue; + } + else if (li.mLineNum > row) + { + break; // invalid column specified + } + + // Found the given row. + S32 line_length = li.mDocIndexEnd - li.mDocIndexStart;; + if (column >= line_length) + { + column -= line_length; + continue; + } + // Found the given column. + updateCursorXPos(); + S32 doc_pos = li.mDocIndexStart + column; return setCursorPos(doc_pos); } - return false; + + return false; // invalid row or column specified } -- cgit v1.2.3 From b66389df893d1e316a5aabc9523c3f46d6f4c6c8 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 3 Nov 2010 22:50:09 +0200 Subject: STORM-536 FIXED scrolling to collapsed accordion tab with keyboard arrows in Places SP->My Landmarks. - Fixed scrolling to selected item when a folder view receives selection inside an accordion tab while being out of visible scrolling area. - Fixed scrolling to collapsed accordion tab when it receives selection while being out of visible scrolling area. --- indra/llui/llaccordionctrltab.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 179b32098a..174dba28d0 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -837,8 +837,13 @@ void LLAccordionCtrlTab::showAndFocusHeader() LLRect screen_rc; LLRect selected_rc = header->getRect(); localRectToScreen(selected_rc, &screen_rc); - notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); + // This call to notifyParent() is intended to deliver "scrollToShowRect" command + // to the parent LLAccordionCtrl so by calling it from the direct parent of this + // accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain + // is shortened and messages from inside the collapsed tabs are avoided. + // See STORM-536. + getParent()->notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); } void LLAccordionCtrlTab::storeOpenCloseState() { -- cgit v1.2.3 From 904738c475bf325666f121b9f9db10e76ec49fcd Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 3 Nov 2010 22:52:53 +0200 Subject: STORM-536 ADDITIONAL FIX Replaced extra calls to getChild() with using a member pointer to LLAccordionCtrlTabHeader. --- indra/llui/llaccordionctrltab.cpp | 48 ++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 174dba28d0..9d49c1a831 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -456,8 +456,7 @@ BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) { if(y >= (getRect().getHeight() - HEADER_HEIGHT) ) { - LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); - header->setFocus(true); + mHeader->setFocus(true); changeOpenClose(getDisplayChildren()); //reset stored state @@ -509,10 +508,9 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel) std::string LLAccordionCtrlTab::getTitle() const { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - return header->getTitle(); + return mHeader->getTitle(); } else { @@ -522,57 +520,51 @@ std::string LLAccordionCtrlTab::getTitle() const void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - header->setTitle(title, hl); + mHeader->setTitle(title, hl); } } void LLAccordionCtrlTab::setTitleFontStyle(std::string style) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - header->setTitleFontStyle(style); + mHeader->setTitleFontStyle(style); } } void LLAccordionCtrlTab::setTitleColor(LLUIColor color) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - header->setTitleColor(color); + mHeader->setTitleColor(color); } } boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - return header->setFocusReceivedCallback(cb); + return mHeader->setFocusReceivedCallback(cb); } return boost::signals2::connection(); } boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - return header->setFocusLostCallback(cb); + return mHeader->setFocusLostCallback(cb); } return boost::signals2::connection(); } void LLAccordionCtrlTab::setSelected(bool is_selected) { - LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); - if (header) + if (mHeader) { - header->setSelected(is_selected); + mHeader->setSelected(is_selected); } } @@ -776,8 +768,7 @@ S32 LLAccordionCtrlTab::notify(const LLSD& info) BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); - if( !header->hasFocus() ) + if( !mHeader->hasFocus() ) return LLUICtrl::handleKey(key, mask, called_from_parent); if ( (key == KEY_RETURN )&& mask == MASK_NONE) @@ -830,12 +821,11 @@ BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) void LLAccordionCtrlTab::showAndFocusHeader() { - LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); - header->setFocus(true); - header->setSelected(mSelectionEnabled); + mHeader->setFocus(true); + mHeader->setSelected(mSelectionEnabled); LLRect screen_rc; - LLRect selected_rc = header->getRect(); + LLRect selected_rc = mHeader->getRect(); localRectToScreen(selected_rc, &screen_rc); // This call to notifyParent() is intended to deliver "scrollToShowRect" command -- cgit v1.2.3 From 211e141444a260af553964ee964be3a7a3c5b37e Mon Sep 17 00:00:00 2001 From: Paul Guslisty Date: Thu, 4 Nov 2010 16:16:18 +0200 Subject: STORM-450 FIXED Incorrect help contexts for Sidebar People tab - Added checking whether panel is in visible chain instead of just visibility checking --- indra/llui/llpanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index c8e56630f1..900e2c789e 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -904,7 +904,7 @@ LLPanel *LLPanel::childGetVisiblePanelWithHelp() child = *it; // do we have a panel with a help topic? LLPanel *panel = dynamic_cast(child); - if (panel && panel->getVisible() && !panel->getHelpTopic().empty()) + if (panel && panel->isInVisibleChain() && !panel->getHelpTopic().empty()) { return panel; } -- cgit v1.2.3