diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2023-10-03 19:46:29 +0300 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2023-10-03 19:55:49 +0300 |
commit | 878fb36a0bb632f5e541b132a7ded5eb047ff947 (patch) | |
tree | 9280a9ce33ddec5e186526077c7edcba2f6fe736 /indra/llui | |
parent | bcfd5d5279f1796abaf347d2276d2a0b9983f35e (diff) | |
parent | 2465470817957c8378e81ec1a7e32551fbac7b26 (diff) |
Merge branch 'main' into DRTVWR-591-maint-X
# Conflicts:
# indra/newview/app_settings/settings.xml
# indra/newview/llinventorybridge.cpp
# indra/newview/lltexturectrl.h
# indra/newview/llvovolume.cpp
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/llbutton.cpp | 3 | ||||
-rw-r--r-- | indra/llui/llfolderview.cpp | 101 | ||||
-rw-r--r-- | indra/llui/llfolderview.h | 19 | ||||
-rw-r--r-- | indra/llui/llfolderviewitem.cpp | 153 | ||||
-rw-r--r-- | indra/llui/llfolderviewitem.h | 15 | ||||
-rw-r--r-- | indra/llui/llfolderviewmodel.cpp | 4 | ||||
-rw-r--r-- | indra/llui/llfolderviewmodel.h | 8 | ||||
-rw-r--r-- | indra/llui/lliconctrl.h | 4 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.cpp | 17 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.h | 4 | ||||
-rw-r--r-- | indra/llui/llmenugl.cpp | 17 | ||||
-rw-r--r-- | indra/llui/llmenugl.h | 9 | ||||
-rw-r--r-- | indra/llui/llscrollbar.cpp | 11 | ||||
-rw-r--r-- | indra/llui/llscrollbar.h | 4 | ||||
-rw-r--r-- | indra/llui/llscrollcontainer.cpp | 11 | ||||
-rw-r--r-- | indra/llui/llscrollcontainer.h | 6 | ||||
-rw-r--r-- | indra/llui/lltabcontainer.cpp | 16 | ||||
-rw-r--r-- | indra/llui/lltabcontainer.h | 1 | ||||
-rw-r--r-- | indra/llui/lltooltip.cpp | 36 | ||||
-rw-r--r-- | indra/llui/lltooltip.h | 12 | ||||
-rw-r--r-- | indra/llui/lluictrl.cpp | 9 | ||||
-rw-r--r-- | indra/llui/lluictrl.h | 1 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 29 | ||||
-rw-r--r-- | indra/llui/llview.h | 1 |
24 files changed, 395 insertions, 96 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 061c24db50..ceceb90f0a 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -204,7 +204,8 @@ LLButton::LLButton(const LLButton::Params& p) } // Hack to make sure there is space for at least one character - if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) + if (getRect().mRight >= 0 && getRect().getWidth() > 0 && + getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { // Use old defaults mLeftHPad = llbutton_orig_h_pad; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ed49c0dcfd..bbbb4afb54 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -189,7 +189,9 @@ LLFolderView::LLFolderView(const Params& p) mStatusTextBox(NULL), mShowItemLinkOverlays(p.show_item_link_overlays), mViewModel(p.view_model), - mGroupedItemModel(p.grouped_item_model) + mGroupedItemModel(p.grouped_item_model), + mForceArrange(false), + mSingleFolderMode(false) { LLPanel* panel = p.parent_panel; mParentPanel = panel->getHandle(); @@ -609,6 +611,7 @@ void LLFolderView::clearSelection() } mSelectedItems.clear(); + mNeedsScroll = false; } std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const @@ -665,7 +668,7 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); + mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); mStatusTextBox->setVisible( TRUE ); // firstly reshape message textbox with current size. This is necessary to @@ -693,12 +696,16 @@ void LLFolderView::draw() } } - if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect())) - { - // renamer is not connected to the item we are renaming in any form so manage it manually - // TODO: consider stopping on any scroll action instead of when out of visible area - finishRenamingItem(); - } + if (mRenameItem + && mRenamer + && mRenamer->getVisible() + && !getVisibleRect().overlaps(mRenamer->getRect())) + { + // renamer is not connected to the item we are renaming in any form so manage it manually + // TODO: consider stopping on any scroll action instead of when out of visible area + LL_DEBUGS("Inventory") << "Renamer out of bounds, hiding" << LL_ENDL; + finishRenamingItem(); + } // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, // and arrow for the root folder @@ -832,9 +839,12 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); item->setOpen(TRUE); + if(!item->isSingleFolderMode()) + { LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); scrollToShowItem(item, constraint_rect); + } } void LLFolderView::closeAutoOpenedFolders() @@ -1038,6 +1048,8 @@ void LLFolderView::paste() // public rename functionality - can only start the process void LLFolderView::startRenamingSelectedItem( void ) { + LL_DEBUGS("Inventory") << "Starting inventory renamer" << LL_ENDL; + // make sure selection is visible scrollToShowSelection(); @@ -1273,6 +1285,11 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if(mSelectedItems.size()) { LLFolderViewItem* last_selected = getCurSelectedItem(); + if(last_selected && last_selected->isSingleFolderMode()) + { + handled = FALSE; + break; + } LLFolderViewItem* parent_folder = last_selected->getParentFolder(); if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) { @@ -1458,9 +1475,19 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) mCallbackRegistrar->popScope(); } } + + BOOL item_clicked = FALSE; + for (selected_items_t::iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + item_clicked |= (*item_it)->getRect().pointInRect(x, y); + } + if(!item_clicked && mSingleFolderMode) + { + clearSelection(); + } bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if (menu && (handled - && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible + if (menu && (mSingleFolderMode || (handled + && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible !hide_folder_menu) { if (mCallbackRegistrar) @@ -1532,6 +1559,22 @@ BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) return LLView::handleHover( x, y, mask ); } +LLFolderViewItem* LLFolderView::getHoveredItem() const +{ + return dynamic_cast<LLFolderViewItem*>(mHoveredItem.get()); +} + +void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) +{ + if (mHoveredItem.get() != itemp) + { + if (itemp) + mHoveredItem = itemp->getHandle(); + else + mHoveredItem.markDead(); + } +} + BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -1716,7 +1759,7 @@ void LLFolderView::update() mNeedsAutoSelect = FALSE; } - BOOL is_visible = isInVisibleChain(); + BOOL is_visible = isInVisibleChain() || mForceArrange; //Puts folders/items in proper positions // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) @@ -1817,13 +1860,28 @@ void LLFolderView::update() } } - if (mSignalSelectCallback) - { - //RN: we use keyboard focus as a proxy for user-explicit actions - BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); - mSelectSignal(mSelectedItems, take_keyboard_focus); - } - mSignalSelectCallback = FALSE; + if (mSelectedItems.size()) + { + LLFolderViewItem* item = mSelectedItems.back(); + // If the goal is to show renamer, don't callback untill + // item is visible or is no longer being scrolled to. + // Otherwise renamer will be instantly closed + // Todo: consider moving renamer out of selection callback + if (!mNeedsAutoRename || !mNeedsScroll || item->getVisible()) + { + if (mSignalSelectCallback) + { + //RN: we use keyboard focus as a proxy for user-explicit actions + BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + mSelectSignal(mSelectedItems, take_keyboard_focus); + } + mSignalSelectCallback = FALSE; + } + } + else + { + mSignalSelectCallback = FALSE; + } } void LLFolderView::dumpSelectionInformation() @@ -1886,6 +1944,11 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + if(mSingleFolderMode && (mSelectedItems.size() == 0)) + { + buildContextMenu(*menu, flags); + } + // This adds a check for restrictions based on the entire // selection set - for example, any one wearable may not push you // over the limit, but all wearables together still might. @@ -2042,7 +2105,7 @@ LLFolderViewItem* LLFolderView::getNextUnselectedItem() return new_selection; } -S32 LLFolderView::getItemHeight() +S32 LLFolderView::getItemHeight() const { if(!hasVisibleChildren()) { diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 7dfa04828a..6de366044c 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -127,6 +127,9 @@ public: bool getAllowMultiSelect() { return mAllowMultiSelect; } bool getAllowDrag() { return mAllowDrag; } + void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; } + bool isSingleFolderMode() { return mSingleFolderMode; } + // Close all folders in the view void closeAllFolders(); void openTopLevelFolders(); @@ -136,7 +139,7 @@ public: // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); + virtual S32 getItemHeight() const; void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } @@ -144,6 +147,10 @@ public: // applies filters to control visibility of items virtual void filter( LLFolderViewFilter& filter); + void clearHoveredItem() { setHoveredItem(nullptr); } + LLFolderViewItem* getHoveredItem() const; + void setHoveredItem(LLFolderViewItem* itemp); + // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); selected_items_t& getSelectedItems( void ); @@ -237,11 +244,15 @@ public: void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } + void setForceArrange(bool force) { mForceArrange = force; } + LLPanel* getParentPanel() { return mParentPanel.get(); } // DEBUG only void dumpSelectionInformation(); virtual S32 notify(const LLSD& info) ; + + void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; } bool useLabelSuffix() { return mUseLabelSuffix; } virtual void updateMenu(); @@ -275,6 +286,7 @@ protected: LLHandle<LLView> mPopupMenuHandle; std::string mMenuFileName; + LLHandle<LLView> mHoveredItem; selected_items_t mSelectedItems; bool mKeyboardSelection, mAllowMultiSelect, @@ -291,7 +303,8 @@ protected: mShowItemLinkOverlays, mShowSelectionContext, mShowSingleSelection, - mSuppressFolderMenu; + mSuppressFolderMenu, + mSingleFolderMode; // Renaming variables and methods LLFolderViewItem* mRenameItem; // The item currently being renamed @@ -330,6 +343,8 @@ protected: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; + + bool mForceArrange; public: static F32 sAutoOpenTime; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index ed0e705fd5..6ae150dca5 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -32,6 +32,7 @@ #include "llfolderview.h" #include "llfolderviewmodel.h" #include "llpanel.h" +#include "llcallbacklist.h" #include "llcriticaldamp.h" #include "llclipboard.h" #include "llfocusmgr.h" // gFocusMgr @@ -113,6 +114,8 @@ LLFolderViewItem::Params::Params() icon_width("icon_width", 0), text_pad("text_pad", 0), text_pad_right("text_pad_right", 0), + single_folder_mode("single_folder_mode", false), + double_click_override("double_click_override", false), arrow_size("arrow_size", 0), max_folder_item_overlap("max_folder_item_overlap", 0) { } @@ -151,7 +154,9 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mTextPad(p.text_pad), mTextPadRight(p.text_pad_right), mArrowSize(p.arrow_size), - mMaxFolderItemOverlap(p.max_folder_item_overlap) + mSingleFolderMode(p.single_folder_mode), + mMaxFolderItemOverlap(p.max_folder_item_overlap), + mDoubleClickOverride(p.double_click_override) { if (!sColorSetInitialized) { @@ -162,7 +167,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); sColorSetInitialized = true; } @@ -396,7 +401,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) // it is purely visual, so it is fine to do at our laisure refreshSuffix(); } - mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; + mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } @@ -413,7 +418,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) return *height; } -S32 LLFolderViewItem::getItemHeight() +S32 LLFolderViewItem::getItemHeight() const { return mItemHeight; } @@ -623,11 +628,14 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) getWindow()->setCursor(UI_CURSOR_NOLOCKED); } + root->clearHoveredItem(); return TRUE; } else { - getRoot()->setShowSelectionContext(FALSE); + LLFolderView* pRoot = getRoot(); + pRoot->setHoveredItem(this); + pRoot->setShowSelectionContext(FALSE); getWindow()->setCursor(UI_CURSOR_ARROW); // let parent handle this then... return FALSE; @@ -682,6 +690,13 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) { mIsMouseOverTitle = false; + + // NOTE: LLViewerWindow::updateUI() calls "enter" before "leave"; if the mouse moved to another item, we can't just outright clear it + LLFolderView* pRoot = getRoot(); + if (this == pRoot->getHoveredItem()) + { + pRoot->clearHoveredItem(); + } } BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -888,7 +903,10 @@ void LLFolderViewItem::draw() getViewModelItem()->update(); - drawOpenFolderArrow(default_params, sFgColor); + if(!mSingleFolderMode) + { + drawOpenFolderArrow(default_params, sFgColor); + } drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); @@ -924,16 +942,43 @@ void LLFolderViewItem::draw() F32 text_left = (F32)getLabelXPos(); std::string combined_string = mLabel + mLabelSuffix; + const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL); + S32 filter_offset = mViewModelItem->getFilterStringOffset(); if (filter_string_length > 0) { - S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; + if(mLabelSuffix.empty() || (font == suffix_font)) + { + S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; LLUIImage* box_image = default_params.selection_image; LLRect box_rect(left, top, right, bottom); box_image->draw(box_rect, sFilterBGColor); + } + else + { + S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); + if(label_filter_length > 0) + { + S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, llmin(filter_offset, (S32)mLabel.size())) - 2; + S32 right = left + font->getWidthF32(mLabel, filter_offset, label_filter_length) + 2; + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; + if(suffix_filter_length > 0) + { + S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); + S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2; + S32 right = left + suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length) + 2; + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + } } LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; @@ -950,7 +995,7 @@ void LLFolderViewItem::draw() // if (!mLabelSuffix.empty()) { - font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, + suffix_font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } @@ -960,12 +1005,35 @@ void LLFolderViewItem::draw() // if (filter_string_length > 0) { - S32 filter_offset = mViewModelItem->getFilterStringOffset(); - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - font->renderUTF8( combined_string, filter_offset, match_string_left, yy, + if(mLabelSuffix.empty() || (font == suffix_font)) + { + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + font->renderUTF8( combined_string, filter_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); + } + else + { + S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); + if(label_filter_length > 0) + { + F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel, filter_offset, label_filter_length); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + font->renderUTF8( mLabel, filter_offset, match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, label_filter_length, S32_MAX, &right_x, FALSE ); + } + + S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; + if(suffix_filter_length > 0) + { + S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); + F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); + F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + suffix_font->renderUTF8( mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, suffix_filter_length, S32_MAX, &right_x, FALSE ); + } + } + } //Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to @@ -1276,7 +1344,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem child_selected = TRUE; } } - if(openitem && child_selected) + if(openitem && child_selected && !mSingleFolderMode) { setOpenArrangeRecursively(TRUE); } @@ -1701,6 +1769,11 @@ BOOL LLFolderViewFolder::isRemovable() return TRUE; } +void LLFolderViewFolder::destroyRoot() +{ + delete this; +} + // this is an internal method used for adding items to folders. void LLFolderViewFolder::addItem(LLFolderViewItem* item) { @@ -1769,7 +1842,19 @@ void LLFolderViewFolder::toggleOpen() // Force a folder open or closed void LLFolderViewFolder::setOpen(BOOL openitem) { - setOpenArrangeRecursively(openitem); + if(mSingleFolderMode) + { + // navigateToFolder can destroy this view + // delay it in case setOpen was called from click or key processing + doOnIdleOneTime([this]() + { + getViewModelItem()->navigateToFolder(); + }); + } + else + { + setOpenArrangeRecursively(openitem); + } } void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) @@ -1972,7 +2057,8 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + && !mSingleFolderMode) { toggleOpen(); handled = TRUE; @@ -1990,12 +2076,45 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; + if(mSingleFolderMode) + { + static LLUICachedControl<bool> double_click_new_window("SingleModeDoubleClickOpenWindow", false); + if (double_click_new_window) + { + getViewModelItem()->navigateToFolder(true); + } + else + { + // navigating is going to destroy views and change children + // delay it untill handleDoubleClick processing is complete + doOnIdleOneTime([this]() + { + getViewModelItem()->navigateToFolder(false); + }); + } + return TRUE; + } + if( isOpen() ) { handled = childrenHandleDoubleClick( x, y, mask ) != NULL; } if( !handled ) { + if(mDoubleClickOverride) + { + static LLUICachedControl<U32> double_click_action("MultiModeDoubleClickFolder", false); + if (double_click_action == 1) + { + getViewModelItem()->navigateToFolder(true); + return TRUE; + } + if (double_click_action == 2) + { + getViewModelItem()->navigateToFolder(false, true); + return TRUE; + } + } if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) { // don't select when user double-clicks plus sign diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index a5157266c5..5c2a1ecff0 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -72,6 +72,8 @@ public: text_pad_right, arrow_size, max_folder_item_overlap; + Optional<bool> single_folder_mode, + double_click_override; Params(); }; @@ -121,6 +123,8 @@ protected: mIsMouseOverTitle, mAllowWear, mAllowDrop, + mSingleFolderMode, + mDoubleClickOverride, mSelectPending, mIsItemCut; @@ -174,7 +178,7 @@ public: // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); + virtual S32 getItemHeight() const; virtual S32 getLabelXPos(); S32 getIconPad(); S32 getTextPad(); @@ -213,9 +217,9 @@ public: void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - BOOL getIsCurSelection() { return mIsCurSelection; } + BOOL getIsCurSelection() const { return mIsCurSelection; } - BOOL hasVisibleChildren() { return mHasVisibleChildren; } + BOOL hasVisibleChildren() const { return mHasVisibleChildren; } // true if object can't have children virtual bool isFolderComplete() { return true; } @@ -264,7 +268,7 @@ public: virtual LLFolderView* getRoot(); virtual const LLFolderView* getRoot() const; BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() { return mIndentation; } + S32 getIndentation() const { return mIndentation; } virtual BOOL passedFilter(S32 filter_generation = -1); virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); @@ -277,6 +281,8 @@ public: // Does not need filter update virtual void refreshSuffix(); + bool isSingleFolderMode() { return mSingleFolderMode; } + // LLView functionality virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); @@ -387,6 +393,7 @@ public: // destroys this folder, and all children virtual void destroyView(); + void destroyRoot(); // whether known children are fully loaded (arrange sets to true) virtual bool isFolderComplete() { return mIsFolderComplete; } diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 394581d6d7..96aca62927 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -34,7 +34,7 @@ bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) return item->getSortVersion() < mTargetSortVersion; } -std::string LLFolderViewModelCommon::getStatusText() +std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder) { if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration()) { @@ -42,7 +42,7 @@ std::string LLFolderViewModelCommon::getStatusText() } else { - return getFilter().getEmptyLookupMessage(); + return getFilter().getEmptyLookupMessage(is_empty_folder); } } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index c5e027d314..551a60e097 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -69,7 +69,7 @@ public: virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; virtual void setEmptyLookupMessage(const std::string& message) = 0; - virtual std::string getEmptyLookupMessage() const = 0; + virtual std::string getEmptyLookupMessage(bool is_empty_folder = false) const = 0; virtual bool showAllResults() const = 0; @@ -125,7 +125,7 @@ public: virtual void setFolderView(LLFolderView* folder_view) = 0; virtual LLFolderViewFilter& getFilter() = 0; virtual const LLFolderViewFilter& getFilter() const = 0; - virtual std::string getStatusText() = 0; + virtual std::string getStatusText(bool is_empty_folder = false) = 0; virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; }; @@ -159,6 +159,8 @@ public: virtual void openItem( void ) = 0; virtual void closeItem( void ) = 0; virtual void selectItem(void) = 0; + + virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0; virtual BOOL isItemWearable() const { return FALSE; } @@ -392,7 +394,7 @@ public: // sort everything mTargetSortVersion++; } - virtual std::string getStatusText(); + virtual std::string getStatusText(bool is_empty_folder = false); virtual void filter(); void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 5d6c544571..e983d63a01 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -39,7 +39,9 @@ class LLUICtrlFactory; // Classes // -// +// Class for diplaying named UI textures +// Do not use for displaying textures from network, +// UI textures are stored permanently! class LLIconCtrl : public LLUICtrl { diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 7b22f9dbdc..7e4e828a88 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -216,7 +216,8 @@ LLLayoutStack::Params::Params() drag_handle_first_indent("drag_handle_first_indent", 0), drag_handle_second_indent("drag_handle_second_indent", 0), drag_handle_thickness("drag_handle_thickness", 5), - drag_handle_shift("drag_handle_shift", 2) + drag_handle_shift("drag_handle_shift", 2), + drag_handle_color("drag_handle_color", LLUIColorTable::instance().getColor("ResizebarBody")) { addSynonym(border_size, "drag_handle_gap"); } @@ -236,7 +237,8 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) mDragHandleFirstIndent(p.drag_handle_first_indent), mDragHandleSecondIndent(p.drag_handle_second_indent), mDragHandleThickness(p.drag_handle_thickness), - mDragHandleShift(p.drag_handle_shift) + mDragHandleShift(p.drag_handle_shift), + mDragHandleColor(p.drag_handle_color()) { } @@ -523,6 +525,15 @@ void LLLayoutStack::updateLayout() mNeedsLayout = continue_animating; } // end LLLayoutStack::updateLayout +void LLLayoutStack::setPanelSpacing(S32 val) +{ + if (mPanelSpacing != val) + { + mPanelSpacing = val; + mNeedsLayout = true; + } +} + LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const { if (!panelp) return NULL; @@ -576,7 +587,7 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) resize_bar_bg_panel_p.follows.flags = FOLLOWS_ALL; resize_bar_bg_panel_p.tab_stop = false; resize_bar_bg_panel_p.background_visible = true; - resize_bar_bg_panel_p.bg_alpha_color = LLUIColorTable::instance().getColor("ResizebarBody"); + resize_bar_bg_panel_p.bg_alpha_color = mDragHandleColor; resize_bar_bg_panel_p.has_border = true; resize_bar_bg_panel_p.border.border_thickness = 1; resize_bar_bg_panel_p.border.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight"); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 22f11eb20f..000b919ae7 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -59,6 +59,8 @@ public: Optional<S32> drag_handle_thickness; Optional<S32> drag_handle_shift; + Optional<LLUIColor> drag_handle_color; + Params(); }; @@ -89,6 +91,7 @@ public: void updateLayout(); S32 getPanelSpacing() const { return mPanelSpacing; } + void setPanelSpacing(S32 val); static void updateClass(); @@ -128,6 +131,7 @@ private: S32 mDragHandleSecondIndent; S32 mDragHandleThickness; S32 mDragHandleShift; + LLUIColor mDragHandleColor; }; // end class LLLayoutStack diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index fe25ac1647..10da3fb7e0 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -573,13 +573,13 @@ void LLMenuItemGL::onVisibilityChange(BOOL new_visibility) // // This class represents a separator. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LLMenuItemSeparatorGL::Params::Params() -{ -} - LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) : LLMenuItemGL( p ) { + if (p.on_visible.isProvided()) + { + mVisibleSignal.connect(initEnableCallback(p.on_visible)); + } } //virtual @@ -596,6 +596,15 @@ void LLMenuItemSeparatorGL::draw( void ) gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); } +void LLMenuItemSeparatorGL::buildDrawLabel( void ) +{ + if (mVisibleSignal.num_slots() > 0) + { + bool visible = mVisibleSignal(this, LLSD()); + setVisible(visible); + } +} + BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask) { LLMenuGL* parent_menu = getMenu(); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 9d3be8d94f..87e3f18ebc 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -234,7 +234,9 @@ class LLMenuItemSeparatorGL : public LLMenuItemGL public: struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> { - Params(); + Optional<EnableCallbackParam > on_visible; + Params() : on_visible("on_visible") + {} }; LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params()); @@ -243,7 +245,12 @@ public: /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + virtual void buildDrawLabel(); + /*virtual*/ U32 getNominalHeight( void ) const; + +private: + enable_signal_t mVisibleSignal; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index fde6de4921..735e2d529e 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -188,12 +188,12 @@ void LLScrollbar::setPageSize( S32 page_size ) } } -BOOL LLScrollbar::isAtBeginning() +bool LLScrollbar::isAtBeginning() const { return mDocPos == 0; } -BOOL LLScrollbar::isAtEnd() +bool LLScrollbar::isAtEnd() const { return mDocPos == getDocPosMax(); } @@ -591,7 +591,12 @@ void LLScrollbar::setValue(const LLSD& value) BOOL LLScrollbar::handleKeyHere(KEY key, MASK mask) { - BOOL handled = FALSE; + if (getDocPosMax() == 0 && !getVisible()) + { + return FALSE; + } + + BOOL handled = FALSE; switch( key ) { diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 5f2f490d81..9be9d22db8 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -105,8 +105,8 @@ public: bool setDocPos( S32 pos, BOOL update_thumb = TRUE ); S32 getDocPos() const { return mDocPos; } - BOOL isAtBeginning(); - BOOL isAtEnd(); + bool isAtBeginning() const; + bool isAtEnd() const; // Setting both at once. void setDocParams( S32 size, S32 pos ); diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 3db38bbfac..ad32f7186c 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -105,8 +105,8 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mBorder = LLUICtrlFactory::create<LLViewBorder> (params); LLView::addChild( mBorder ); - mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mInnerRect.stretch( -getBorderWidth() ); + mInnerRect = getLocalRect(); + mInnerRect.stretch( -getBorderWidth() ); LLRect vertical_scroll_rect = mInnerRect; vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size; @@ -124,8 +124,9 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mScrollbar[VERTICAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams); LLView::addChild( mScrollbar[VERTICAL] ); - LLRect horizontal_scroll_rect = mInnerRect; - horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size; + LLRect horizontal_scroll_rect; + horizontal_scroll_rect.mTop = scrollbar_size; + horizontal_scroll_rect.mRight = mInnerRect.getWidth(); sbparams.name("scrollable horizontal"); sbparams.rect(horizontal_scroll_rect); sbparams.orientation(LLScrollbar::HORIZONTAL); @@ -134,7 +135,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) sbparams.page_size(mInnerRect.getWidth()); sbparams.step_size(VERTICAL_MULTIPLE); sbparams.visible(false); - sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT); + sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); sbparams.change_callback(p.scroll_callback); mScrollbar[HORIZONTAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams); LLView::addChild( mScrollbar[HORIZONTAL] ); diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index c14099dbd5..dacea2a987 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -98,8 +98,10 @@ public: void pageDown(S32 overlap = 0); void goToTop(); void goToBottom(); - bool isAtTop() { return mScrollbar[VERTICAL]->isAtBeginning(); } - bool isAtBottom() { return mScrollbar[VERTICAL]->isAtEnd(); } + bool isAtTop() const { return mScrollbar[VERTICAL]->isAtBeginning(); } + bool isAtBottom() const { return mScrollbar[VERTICAL]->isAtEnd(); } + S32 getDocPosVertical() const { return mScrollbar[VERTICAL]->getDocPos(); } + S32 getDocPosHorizontal() const { return mScrollbar[HORIZONTAL]->getDocPos(); } S32 getBorderWidth() const; // LLView functionality diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 8c841540a5..76b9e448a1 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -605,6 +605,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) LLButton* tab_button = getTab(index)->mButton; gFocusMgr.setMouseCapture(this); tab_button->setFocus(TRUE); + mMouseDownTimer.start(); } } if (handled) { @@ -653,7 +654,11 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) handled = LLPanel::handleHover(x, y, mask); } - commitHoveredButton(x, y); + F32 drag_delay = 0.25f; // filter out clicks from dragging + if (mMouseDownTimer.getElapsedTimeF32() > drag_delay) + { + commitHoveredButton(x, y); + } return handled; } @@ -699,6 +704,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) } commitHoveredButton(x, y); + mMouseDownTimer.stop(); LLPanel* cur_panel = getCurrentPanel(); if (hasMouseCapture()) { @@ -1002,7 +1008,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - //Scip tab button space if they are invisible(EXT - 576) + // Skip tab button space if tabs are invisible (EXT-576) tab_panel_top = getRect().getHeight(); tab_panel_bottom = LLPANEL_BORDER_WIDTH; } @@ -1017,9 +1023,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH, + tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3, tab_panel_top, - getRect().getWidth()-LLPANEL_BORDER_WIDTH, + getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2, tab_panel_bottom ); } child->setFollowsAll(); @@ -1106,7 +1112,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.follows.flags = p.follows.flags() | FOLLOWS_TOP; } else - { + { p.name("htab_"+std::string(child->getName())); p.visible(false); p.image_unselected(tab_img); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 8f8cedb1b9..aa4a08c4ff 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -320,6 +320,7 @@ private: LLUIColor mTabsFlashingColor; S32 mTabIconCtrlPad; bool mUseTabEllipses; + LLFrameTimer mMouseDownTimer; }; #endif // LL_TABCONTAINER_H diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 2f56a8b1d0..a6552d4ff1 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -163,6 +163,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) : LLPanel(p), mHasClickCallback(p.click_callback.isProvided()), mPadding(p.padding), + mMaxWidth(p.max_width), mTextBox(NULL), mInfoButton(NULL), mPlayMediaButton(NULL), @@ -272,7 +273,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) // do this *after* we've had our size set in LLPanel::initFromParams(); const S32 REALLY_LARGE_HEIGHT = 10000; - mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT); + mTextBox->reshape(mMaxWidth, REALLY_LARGE_HEIGHT); if (p.styled_message.isProvided()) { @@ -288,16 +289,19 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->setText(p.message()); } - S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1); + updateTextBox(); + snapToChildren(); +} + +void LLToolTip::updateTextBox() +{ + S32 text_width = llmin(mMaxWidth, mTextBox->getTextPixelWidth() + 1); S32 text_height = mTextBox->getTextPixelHeight(); mTextBox->reshape(text_width, text_height); - if (mInfoButton) - { - LLRect text_rect = mTextBox->getRect(); - LLRect icon_rect = mInfoButton->getRect(); - mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY()); - } - +} + +void LLToolTip::snapToChildren() +{ // reshape tooltip panel to fit text box LLRect tooltip_rect = calcBoundingRect(); tooltip_rect.mTop += mPadding; @@ -305,7 +309,14 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) tooltip_rect.mBottom = 0; tooltip_rect.mLeft = 0; - mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); + if (mInfoButton) + { + mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); + + LLRect text_rect = mTextBox->getRect(); + LLRect icon_rect = mInfoButton->getRect(); + mInfoButton->translate(0, text_rect.getCenterY() - icon_rect.getCenterY()); + } setShape(tooltip_rect); } @@ -428,7 +439,10 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) } tooltip_params.rect = LLRect (0, 1, 1, 0); - mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); + if (tooltip_params.create_callback.isProvided()) + mToolTip = tooltip_params.create_callback()(tooltip_params); + else + mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); gToolTipView->addChild(mToolTip); diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 0b1fbe5367..86943625ff 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -68,6 +68,7 @@ public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { typedef boost::function<void(void)> click_callback_t; + typedef boost::function<LLToolTip*(LLToolTip::Params)> create_callback_t; Optional<std::string> message; Multiple<StyledText> styled_message; @@ -84,6 +85,8 @@ public: Optional<bool> time_based_media, web_based_media, media_playing; + Optional<create_callback_t> create_callback; + Optional<LLSD> create_params; Optional<click_callback_t> click_callback, click_playmedia_callback, click_homepage_callback; @@ -103,11 +106,15 @@ public: bool hasClickCallback(); LLToolTip(const Params& p); - void initFromParams(const LLToolTip::Params& params); + virtual void initFromParams(const LLToolTip::Params& params); void getToolTipMessage(std::string & message); -private: +protected: + void updateTextBox(); + void snapToChildren(); + +protected: class LLTextBox* mTextBox; class LLButton* mInfoButton; class LLButton* mPlayMediaButton; @@ -117,6 +124,7 @@ private: LLFrameTimer mVisibleTimer; bool mHasClickCallback; S32 mPadding; // pixels + S32 mMaxWidth; }; // used for the inspector tooltips which need different background images etc. diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 2196ba201b..21afcae7c3 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -531,6 +531,15 @@ void LLUICtrl::setControlVariable(LLControlVariable* control) } } +void LLUICtrl::removeControlVariable() +{ + if (mControlVariable) + { + mControlConnection.disconnect(); + mControlVariable = NULL; + } +} + //virtual void LLUICtrl::setControlName(const std::string& control_name, LLView *context) { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 424b4879ce..ef295976a2 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -176,6 +176,7 @@ public: bool setControlValue(const LLSD& value); void setControlVariable(LLControlVariable* control); virtual void setControlName(const std::string& control, LLView *context = NULL); + void removeControlVariable(); LLControlVariable* getControlVariable() { return mControlVariable; } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 3344300635..da7868d804 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -311,7 +311,13 @@ bool LLView::addChild(LLView* child, S32 tab_group) } child->mParentView = this; - updateBoundingRect(); + if (getVisible() && child->getVisible()) + { + // if child isn't visible it won't affect bounding rect + // if current view is not visible it will be recalculated + // on visibility change + updateBoundingRect(); + } mLastTabGroup = tab_group; return true; } @@ -581,6 +587,7 @@ void LLView::deleteAllChildren() delete viewp; mChildList.pop_front(); } + updateBoundingRect(); } void LLView::setAllChildrenEnabled(BOOL b) @@ -879,6 +886,17 @@ LLView* LLView::childFromPoint(S32 x, S32 y, bool recur) return 0; } +F32 LLView::getTooltipTimeout() +{ + static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f); + static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f); + // allow "scrubbing" over ui by showing next tooltip immediately + // if previous one was still visible + return (F32)(LLToolTipMgr::instance().toolTipVisible() + ? tooltip_fast_delay + : tooltip_delay); +} + BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -888,14 +906,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) std::string tooltip = getToolTip(); if (!tooltip.empty()) { - static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f); - static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f); static LLCachedControl<bool> allow_ui_tooltips(*LLUI::getInstance()->mSettingGroups["config"], "BasicUITooltips", true); - // allow "scrubbing" over ui by showing next tooltip immediately - // if previous one was still visible - F32 timeout = LLToolTipMgr::instance().toolTipVisible() - ? tooltip_fast_delay - : tooltip_delay; // Even if we don't show tooltips, consume the event, nothing below should show tooltip if (allow_ui_tooltips) @@ -903,7 +914,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) LLToolTipMgr::instance().show(LLToolTip::Params() .message(tooltip) .sticky_rect(calcScreenRect()) - .delay_time(timeout)); + .delay_time(getTooltipTimeout())); } handled = TRUE; } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 8aa97aac39..7360fd0fb9 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -243,6 +243,7 @@ public: ECursorType getHoverCursor() { return mHoverCursor; } + static F32 getTooltipTimeout(); virtual const std::string getToolTip() const { return mToolTipMsg.getString(); } void sendChildToFront(LLView* child); |