diff options
Diffstat (limited to 'indra/llui')
33 files changed, 451 insertions, 155 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 0e59fdf519..8028f397f3 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -102,6 +102,7 @@ LLButton::Params::Params() scale_image("scale_image", true), hover_glow_amount("hover_glow_amount"), commit_on_return("commit_on_return", true), + commit_on_capture_lost("commit_on_capture_lost", false), display_pressed_state("display_pressed_state", true), use_draw_context_alpha("use_draw_context_alpha", true), badge("badge"), @@ -165,6 +166,7 @@ LLButton::LLButton(const LLButton::Params& p) mBottomVPad(p.pad_bottom), mHoverGlowStrength(p.hover_glow_amount), mCommitOnReturn(p.commit_on_return), + mCommitOnCaptureLost(p.commit_on_capture_lost), mFadeWhenDisabled(FALSE), mForcePressedState(false), mDisplayPressedState(p.display_pressed_state), @@ -475,6 +477,10 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // We only handle the click if the click both started and ended within us if( hasMouseCapture() ) { + // reset timers before focus change, to not cause + // additional commits if mCommitOnCaptureLost. + resetMouseDownTimer(); + // Always release the mouse gFocusMgr.setMouseCapture( NULL ); @@ -489,8 +495,6 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // Regardless of where mouseup occurs, handle callback if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); - resetMouseDownTimer(); - // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. // If mouseup in the widget, it's been clicked if (pointInView(x, y)) @@ -1195,6 +1199,18 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen void LLButton::onMouseCaptureLost() { + if (mCommitOnCaptureLost + && mMouseDownTimer.getStarted()) + { + if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + + if (mIsToggle) + { + toggleState(); + } + + LLUICtrl::onCommit(); + } resetMouseDownTimer(); } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 572d36996c..ccd31e90c0 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -124,6 +124,7 @@ public: Optional<bool> is_toggle, scale_image, commit_on_return, + commit_on_capture_lost, display_pressed_state; Optional<F32> hover_glow_amount; @@ -374,6 +375,7 @@ protected: F32 mCurGlowStrength; bool mCommitOnReturn; + bool mCommitOnCaptureLost; bool mFadeWhenDisabled; bool mForcePressedState; bool mDisplayPressedState; diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 5e00bf7f45..b13e7389cc 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -505,6 +505,17 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) } }; +LLFlatListView::~LLFlatListView() +{ + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); +} + // virtual void LLFlatListView::draw() { diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 230ea200d8..d47c1cf333 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -299,6 +299,7 @@ public: virtual S32 notify(const LLSD& info) ; + virtual ~LLFlatListView(); protected: /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 03efd09689..d413fab270 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -259,6 +259,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mMinHeight(p.min_height), mHeaderHeight(p.header_height), mLegacyHeaderHeight(p.legacy_header_height), + mDefaultRectForGroup(true), mMinimized(FALSE), mForeground(FALSE), mFirstLook(TRUE), @@ -761,17 +762,13 @@ void LLFloater::closeFloater(bool app_quitting) for(handle_set_iter_t dependent_it = mDependents.begin(); dependent_it != mDependents.end(); ) { - LLFloater* floaterp = dependent_it->get(); - if (floaterp) - { - ++dependent_it; - floaterp->closeFloater(app_quitting); - } - else - { - mDependents.erase(dependent_it++); - } + dependent_it = mDependents.erase(dependent_it); + if (floaterp) + { + floaterp->mDependeeHandle = LLHandle<LLFloater>(); + floaterp->closeFloater(app_quitting); + } } cleanupHandles(); @@ -906,7 +903,10 @@ bool LLFloater::applyRectControl() if (last_in_group && last_in_group != this) { // other floaters in our group, position ourselves relative to them and don't save the rect - mRectControl.clear(); + if (mDefaultRectForGroup) + { + mRectControl.clear(); + } mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; } else @@ -1439,7 +1439,7 @@ void LLFloater::cleanupHandles() LLFloater* floaterp = dependent_it->get(); if (!floaterp) { - mDependents.erase(dependent_it++); + dependent_it = mDependents.erase(dependent_it); } else { @@ -3481,8 +3481,15 @@ void LLFloater::stackWith(LLFloater& other) } next_rect.translate(floater_offset, -floater_offset); - next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); - + const LLRect& rect = getControlGroup()->getRect(mRectControl); + if (rect.notEmpty() && !mDefaultRectForGroup && mResizable) + { + next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } + else + { + next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); + } setShape(next_rect); if (!other.getHost()) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 306760b7fb..668cd208a9 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -454,6 +454,7 @@ public: protected: bool mSaveRect; + bool mDefaultRectForGroup; std::string mRectControl; std::string mPosXControl; std::string mPosYControl; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ea2ca68e47..e1869e8125 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -163,6 +163,7 @@ LLFolderView::LLFolderView(const Params& p) : LLFolderViewFolder(p), mScrollContainer( NULL ), mPopupMenuHandle(), + mMenuFileName(p.options_menu), mAllowMultiSelect(p.allow_multiselect), mAllowDrag(p.allow_drag), mShowEmptyMessage(p.show_empty_message), @@ -182,6 +183,7 @@ LLFolderView::LLFolderView(const Params& p) mMinWidth(0), mDragAndDropThisFrame(FALSE), mCallbackRegistrar(NULL), + mEnableRegistrar(NULL), mUseEllipses(p.use_ellipses), mDraggingOverItem(NULL), mStatusTextBox(NULL), @@ -244,17 +246,6 @@ LLFolderView::LLFolderView(const Params& p) mStatusTextBox->setFollowsTop(); addChild(mStatusTextBox); - - // make the popup menu available - llassert(LLMenuGL::sMenuContainer != NULL); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - mViewModelItem->openItem(); mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. @@ -276,6 +267,7 @@ LLFolderView::~LLFolderView( void ) mStatusTextBox = NULL; if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); mAutoOpenItems.removeAllNodes(); clearSelection(); @@ -1438,22 +1430,56 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; S32 count = mSelectedItems.size(); - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + LLMenuGL* menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (!menu) + { + if (mCallbackRegistrar) + { + mCallbackRegistrar->pushScope(); + } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } + if (mCallbackRegistrar) + { + mCallbackRegistrar->popScope(); + } + } bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if ((handled - && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible - && menu ) && + if (menu && (handled + && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible !hide_folder_menu) { if (mCallbackRegistrar) { mCallbackRegistrar->pushScope(); } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } updateMenuOptions(menu); menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } if (mCallbackRegistrar) { mCallbackRegistrar->popScope(); @@ -1531,7 +1557,7 @@ void LLFolderView::deleteAllChildren() { closeRenamer(); if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle = LLHandle<LLView>(); + mPopupMenuHandle.markDead(); mScrollContainer = NULL; mRenameItem = NULL; mRenamer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 6bb5e6c02e..7dfa04828a 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -235,6 +235,7 @@ public: bool showItemLinkOverlays() { return mShowItemLinkOverlays; } void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } + void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } LLPanel* getParentPanel() { return mParentPanel.get(); } // DEBUG only @@ -272,6 +273,7 @@ protected: protected: LLHandle<LLView> mPopupMenuHandle; + std::string mMenuFileName; selected_items_t mSelectedItems; bool mKeyboardSelection, @@ -327,6 +329,7 @@ protected: LLFolderViewItem* mDraggingOverItem; // See EXT-719 LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; public: static F32 sAutoOpenTime; diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 093e213be3..dd5eb47a63 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -419,21 +419,15 @@ public: mFilter(filter) {} - virtual ~LLFolderViewModel() - { - delete mSorter; - mSorter = NULL; - delete mFilter; - mFilter = NULL; - } + virtual ~LLFolderViewModel() {} virtual SortType& getSorter() { return *mSorter; } virtual const SortType& getSorter() const { return *mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = new SortType(sorter); requestSortAll(); } + virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); } virtual FilterType& getFilter() { return *mFilter; } virtual const FilterType& getFilter() const { return *mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = new FilterType(filter); } + virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); } // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, // this method needs to be overloaded and return the relevant fetch status. @@ -471,8 +465,8 @@ public: } protected: - SortType* mSorter; - FilterType* mFilter; + std::unique_ptr<SortType> mSorter; + std::unique_ptr<FilterType> mFilter; }; #endif // LLFOLDERVIEWMODEL_H diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 82b01e705d..e01aba402e 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -35,6 +35,7 @@ #include "llui.h" #include "lluictrlfactory.h" #include "lluiimage.h" +#include "llwindow.h" static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon"); @@ -42,6 +43,7 @@ LLIconCtrl::Params::Params() : image("image_name"), color("color"), use_draw_context_alpha("use_draw_context_alpha", true), + interactable("interactable", false), scale_image("scale_image"), min_width("min_width", 0), min_height("min_height", 0) @@ -52,6 +54,7 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) mColor(p.color()), mImagep(p.image), mUseDrawContextAlpha(p.use_draw_context_alpha), + mInteractable(p.interactable), mPriority(0), mMinWidth(p.min_width), mMinHeight(p.min_height), @@ -81,6 +84,16 @@ void LLIconCtrl::draw() LLUICtrl::draw(); } +BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask) +{ + if (mInteractable && getEnabled()) + { + getWindow()->setCursor(UI_CURSOR_HAND); + return TRUE; + } + return LLUICtrl::handleHover(x, y, mask); +} + // 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 dd83e78fd3..9c3b517bca 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -48,7 +48,8 @@ public: { Optional<LLUIImage*> image; Optional<LLUIColor> color; - Optional<bool> use_draw_context_alpha; + Optional<bool> use_draw_context_alpha, + interactable; Optional<S32> min_width, min_height; Ignored scale_image; @@ -67,6 +68,9 @@ public: // llview overrides virtual void draw(); + // llview overrides + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + // lluictrl overrides virtual void setValue(const LLSD& value ); @@ -88,6 +92,7 @@ protected: // If set to true (default), use the draw context transparency. // If false, will use transparency returned by getCurrentTransparency(). See STORM-698. bool mUseDrawContextAlpha; + bool mInteractable; private: LLUIColor mColor; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index aac28e04b9..77938edf27 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -395,7 +395,6 @@ void LLLayoutStack::updateLayout() space_to_distribute += panelp ? ll_round((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; S32 remaining_space = space_to_distribute; - F32 fraction_distributed = 0.f; if (space_to_distribute > 0 && total_visible_fraction > 0.f) { // give space proportionally to visible auto resize panels BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) @@ -404,7 +403,6 @@ void LLLayoutStack::updateLayout() { F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction); S32 delta = ll_round((F32)space_to_distribute * fraction_to_distribute); - fraction_distributed += fraction_to_distribute; panelp->mTargetDim += delta; remaining_space -= delta; } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 33037b5001..940cf398c0 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -209,13 +209,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) setPrevalidateInput(p.prevalidate_input_callback()); setPrevalidate(p.prevalidate_callback()); - - llassert(LLMenuGL::sMenuContainer != NULL); - LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu> - ("menu_text_editor.xml", - LLMenuGL::sMenuContainer, - LLMenuHolderGL::child_registry_t::instance()); - setContextMenu(menu); } LLLineEditor::~LLLineEditor() @@ -1567,7 +1560,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) KEY_SHIFT != key && KEY_CONTROL != key && KEY_ALT != key && - KEY_CAPSLOCK ) + KEY_CAPSLOCK != key) { deselect(); } @@ -2637,6 +2630,15 @@ LLWString LLLineEditor::getConvertedText() const void LLLineEditor::showContextMenu(S32 x, S32 y) { LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); + if (!menu) + { + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::createFromFile<LLContextMenu> + ("menu_text_editor.xml", + LLMenuGL::sMenuContainer, + LLMenuHolderGL::child_registry_t::instance()); + setContextMenu(menu); + } if (menu) { diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 303afcda15..583704418b 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -40,6 +40,7 @@ void LLMenuButton::MenuPositions::declareValues() declare("topleft", MP_TOP_LEFT); declare("topright", MP_TOP_RIGHT); declare("bottomleft", MP_BOTTOM_LEFT); + declare("bottomright", MP_BOTTOM_RIGHT); } LLMenuButton::Params::Params() @@ -212,6 +213,13 @@ void LLMenuButton::updateMenuOrigin() mY = rect.mBottom; break; } + case MP_BOTTOM_RIGHT: + { + const LLRect& menu_rect = menu->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mBottom; + break; + } } } diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 67ec1983b3..e42f8f53bd 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -41,7 +41,8 @@ public: { MP_TOP_LEFT, MP_TOP_RIGHT, - MP_BOTTOM_LEFT + MP_BOTTOM_LEFT, + MP_BOTTOM_RIGHT } EMenuPosition; struct MenuPositions diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 8f00d1274e..5cb840fd61 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3960,8 +3960,8 @@ void LLTearOffMenu::draw() { // animate towards target height reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), (F32)mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); - mMenu->needsArrange(); } + mMenu->needsArrange(); LLFloater::draw(); } @@ -4087,25 +4087,39 @@ void LLTearOffMenu::closeTearOff() } LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) -: LLMenuItemGL(p), - mBranch( p.branch()->getHandle() ) +: LLMenuItemGL(p) { - mBranch.get()->hide(); - mBranch.get()->setParentMenuItem(this); + LLContextMenu* branch = static_cast<LLContextMenu*>(p.branch); + if (branch) + { + mBranch = branch->getHandle(); + branch->hide(); + branch->setParentMenuItem(this); + } +} + +LLContextMenuBranch::~LLContextMenuBranch() +{ + if (mBranch.get()) + { + mBranch.get()->die(); + } } // called to rebuild the draw label void LLContextMenuBranch::buildDrawLabel( void ) { + auto menu = getBranch(); + if (menu) { // default enablement is this -- if any of the subitems are // enabled, this item is enabled. JC - U32 sub_count = mBranch.get()->getItemCount(); + U32 sub_count = menu->getItemCount(); U32 i; BOOL any_enabled = FALSE; for (i = 0; i < sub_count; i++) { - LLMenuItemGL* item = mBranch.get()->getItem(i); + LLMenuItemGL* item = menu->getItem(i); item->buildDrawLabel(); if (item->getEnabled() && !item->getDrawTextDisabled() ) { @@ -4127,13 +4141,17 @@ void LLContextMenuBranch::buildDrawLabel( void ) void LLContextMenuBranch::showSubMenu() { - LLMenuItemGL* menu_item = mBranch.get()->getParentMenuItem(); - if (menu_item != NULL && menu_item->getVisible()) + auto menu = getBranch(); + if(menu) { - S32 center_x; - S32 center_y; - localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); - mBranch.get()->show(center_x, center_y); + LLMenuItemGL* menu_item = menu->getParentMenuItem(); + if (menu_item != NULL && menu_item->getVisible()) + { + S32 center_x; + S32 center_y; + localPointToScreen(getRect().getWidth(), getRect().getHeight(), ¢er_x, ¢er_y); + menu->show(center_x, center_y); + } } } @@ -4147,13 +4165,17 @@ void LLContextMenuBranch::setHighlight( BOOL highlight ) { if (highlight == getHighlight()) return; LLMenuItemGL::setHighlight(highlight); - if( highlight ) - { - showSubMenu(); - } - else + auto menu = getBranch(); + if (menu) { - mBranch.get()->hide(); + if (highlight) + { + showSubMenu(); + } + else + { + menu->hide(); + } } } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index abbfd9a24a..f84c4d41eb 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -745,8 +745,7 @@ public: LLContextMenuBranch(const Params&); - virtual ~LLContextMenuBranch() - {} + virtual ~LLContextMenuBranch(); // called to rebuild the draw label virtual void buildDrawLabel( void ); diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 5cfa8ea973..3e5978eb59 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -100,7 +100,10 @@ void LLModalDialog::onOpen(const LLSD& key) if (!sModalStack.empty()) { LLModalDialog* front = sModalStack.front(); - front->setVisible(FALSE); + if (front != this) + { + front->setVisible(FALSE); + } } // This is a modal dialog. It sucks up all mouse and keyboard operations. @@ -108,7 +111,14 @@ void LLModalDialog::onOpen(const LLSD& key) LLUI::getInstance()->addPopup(this); setFocus(TRUE); - sModalStack.push_front( this ); + std::list<LLModalDialog*>::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); + if (iter != sModalStack.end()) + { + // if already present, we want to move it to front. + sModalStack.erase(iter); + } + + sModalStack.push_front(this); } } diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index f89064d59a..604d246f12 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -92,7 +92,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) mMouseDownSignal(NULL), mMouseUpSignal(NULL) { - mValue.emptyMap(); + mValue = LLSD::emptyMap(); mCurSlider = LLStringUtil::null; if (mOrientation == HORIZONTAL) diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index 209796565c..cf57b1fe76 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -69,16 +69,22 @@ void LLProgressBar::draw() static LLTimer timer; F32 alpha = getDrawContext().mAlpha; - LLColor4 image_bar_color = mColorBackground.get(); - image_bar_color.setAlpha(alpha); - mImageBar->draw(getLocalRect(), image_bar_color); + if (mImageBar) // optional according to parameters + { + LLColor4 image_bar_color = mColorBackground.get(); + image_bar_color.setAlpha(alpha); + mImageBar->draw(getLocalRect(), image_bar_color); + } - alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); - LLColor4 bar_color = mColorBar.get(); - bar_color.mV[VALPHA] *= alpha; // modulate alpha - LLRect progress_rect = getLocalRect(); - progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f)); - mImageFill->draw(progress_rect, bar_color); + if (mImageFill) + { + alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); + LLColor4 bar_color = mColorBar.get(); + bar_color.mV[VALPHA] *= alpha; // modulate alpha + LLRect progress_rect = getLocalRect(); + progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f)); + mImageFill->draw(progress_rect, bar_color); + } } void LLProgressBar::setValue(const LLSD& value) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 11b0eb9f80..3922a94390 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -196,7 +196,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mHighlightedItem(-1), mBorder(NULL), mSortCallback(NULL), - mPopupMenu(NULL), mCommentTextView(NULL), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), @@ -348,6 +347,13 @@ LLScrollListCtrl::~LLScrollListCtrl() mItemList.clear(); clearColumns(); //clears columns and deletes headers delete mIsFriendSignal; + + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } } @@ -1307,14 +1313,14 @@ LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOO } -BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive, S32 column) { - return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive); + return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive, column); } // Selects first enabled item that has a name where the name's first part matched the target string. // Returns false if item not found. -BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive, S32 column) { BOOL found = FALSE; @@ -1329,7 +1335,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen { LLScrollListItem* item = *iter; // Only select enabled items with matching names - LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column); BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; if (select) { @@ -1352,7 +1358,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen LLScrollListItem* item = *iter; // Only select enabled items with matching names - LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column); if (!cellp) { continue; @@ -1388,6 +1394,84 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen return found; } +U32 LLScrollListCtrl::searchItems(const std::string& substring, bool case_sensitive, bool focus) +{ + return searchItems(utf8str_to_wstring(substring), case_sensitive, focus); +} + +U32 LLScrollListCtrl::searchItems(const LLWString& substring, bool case_sensitive, bool focus) +{ + U32 found = 0; + + LLWString substring_trimmed(substring); + S32 len = substring_trimmed.size(); + + if (0 == len) + { + // at the moment search for empty element is not supported + return 0; + } + else + { + deselectAllItems(TRUE); + if (!case_sensitive) + { + // do comparisons in lower case + LLWStringUtil::toLower(substring_trimmed); + } + + for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListItem* item = *iter; + // Only select enabled items with matching names + if (!item->getEnabled()) + { + continue; + } + LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + if (!cellp) + { + continue; + } + LLWString item_label = utf8str_to_wstring(cellp->getValue().asString()); + if (!case_sensitive) + { + LLWStringUtil::toLower(item_label); + } + // remove extraneous whitespace from searchable label + LLWStringUtil::trim(item_label); + + size_t found_iter = item_label.find(substring_trimmed); + + if (found_iter != std::string::npos) + { + // find offset of matching text + cellp->highlightText(found_iter, substring_trimmed.size()); + selectItem(item, -1, FALSE); + + found++; + + if (!mAllowMultipleSelection) + { + break; + } + } + } + } + + if (focus && found != 0) + { + mNeedsScroll = true; + } + + if (mCommitOnSelectionChange) + { + commitIfChanged(); + } + + return found; +} + const std::string LLScrollListCtrl::getSelectedItemLabel(S32 column) const { LLScrollListItem* item; @@ -1912,23 +1996,30 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id)); registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id)); registrar.add("Url.RemoveFriend", boost::bind(&LLScrollListCtrl::removeFriend, id)); + registrar.add("Url.ReportAbuse", boost::bind(&LLScrollListCtrl::reportAbuse, id, is_group)); registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group)); registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group)); registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group)); // create the context menu from the XUI file and display it std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml"; - delete mPopupMenu; + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } llassert(LLMenuGL::sMenuContainer != NULL); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( + menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (mPopupMenu) + if (menu) { + mPopupMenuHandle = menu->getHandle(); if (mIsFriendSignal) { bool isFriend = *(*mIsFriendSignal)(uuid); - LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend"); - LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend"); + LLView* addFriendButton = menu->getChild<LLView>("add_friend"); + LLView* removeFriendButton = menu->getChild<LLView>("remove_friend"); if (addFriendButton && removeFriendButton) { @@ -1937,8 +2028,8 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) } } - mPopupMenu->show(x, y); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(this, menu, x, y); return TRUE; } } @@ -1975,6 +2066,15 @@ void LLScrollListCtrl::removeFriend(std::string id) LLUrlAction::removeFriend(slurl); } +void LLScrollListCtrl::reportAbuse(std::string id, bool is_group) +{ + if (!is_group) + { + std::string slurl = "secondlife:///app/agent/" + id + "/about"; + LLUrlAction::reportAbuse(slurl); + } +} + void LLScrollListCtrl::showNameDetails(std::string id, bool is_group) { // open the resident's details or the group details diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 08134bbfc8..a908dbc968 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -261,12 +261,20 @@ public: virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); // FALSE if item not found - BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE); - BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE); + BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE, S32 column = -1); + BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE, S32 column = -1); LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); const std::string getSelectedItemLabel(S32 column = 0) const; LLSD getSelectedValue(); + // If multi select is on, select all element that include substring, + // otherwise select first match only. + // If focus is true will scroll to selection. + // Returns number of results. + // Note: at the moment search happens in one go and is expensive + U32 searchItems(const std::string& substring, bool case_sensitive = false, bool focus = true); + U32 searchItems(const LLWString& substring, bool case_sensitive = false, bool focus = true); + // DEPRECATED: Use LLSD versions of setCommentText() and getSelectedValue(). // "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which // has an associated, unique UUID, and only one of which can be selected at a time. @@ -325,6 +333,7 @@ public: // support right-click context menus for avatar/group lists enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP }; void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; } + ContextMenuType getContextMenuType() { return mContextMenuType; } // Overridden from LLView /*virtual*/ void draw(); @@ -460,6 +469,7 @@ private: static void sendIM(std::string id); static void addFriend(std::string id); static void removeFriend(std::string id); + static void reportAbuse(std::string id, bool is_group); static void showNameDetails(std::string id, bool is_group); static void copyNameToClipboard(std::string id, bool is_group); static void copySLURLToClipboard(std::string id, bool is_group); @@ -516,7 +526,7 @@ private: S32 mHighlightedItem; class LLViewBorder* mBorder; - LLContextMenu *mPopupMenu; + LLHandle<LLContextMenu> mPopupMenuHandle; LLView *mCommentTextView; diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ee78b82429..ef7c8ec012 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -103,6 +103,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height); up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); + up_button_params.commit_on_capture_lost = true; mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params); addChild(mUpBtn); @@ -111,6 +112,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height); down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); + down_button_params.commit_on_capture_lost = true; mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params); addChild(mDownBtn); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 459fdcf2ae..0aa7a2d217 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -402,9 +402,13 @@ void LLTabContainer::draw() S32 cur_scroll_pos = getScrollPos(); if (cur_scroll_pos > 0) { - S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1); - if (!mIsVertical) + if (mIsVertical) { + target_pixel_scroll = cur_scroll_pos * (BTN_HEIGHT + tabcntrv_pad); + } + else + { + S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1); for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { if (cur_scroll_pos == 0) @@ -1189,13 +1193,15 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) sendChildToFront(mNextArrowBtn); sendChildToFront(mJumpPrevArrowBtn); sendChildToFront(mJumpNextArrowBtn); - + + updateMaxScrollPos(); + if( select ) { selectLastTab(); + mScrollPos = mMaxScrollPos; } - updateMaxScrollPos(); } void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label) @@ -2079,9 +2085,9 @@ void LLTabContainer::updateMaxScrollPos() if( tab_total_height > available_height ) { static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); - S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad); + S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom; S32 additional_needed = tab_total_height - available_height_with_arrows; - setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) ); + setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) ); no_scroll = FALSE; } } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0dc99fdde6..fcfdd64e6a 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -163,6 +163,7 @@ LLTextBase::Params::Params() font_shadow("font_shadow"), wrap("wrap"), trusted_content("trusted_content", true), + always_show_icons("always_show_icons", false), use_ellipses("use_ellipses", false), parse_urls("parse_urls", false), force_urls_external("force_urls_external", false), @@ -212,6 +213,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mClip(p.clip), mClipPartial(p.clip_partial && !p.allow_scroll), mTrustedContent(p.trusted_content), + mAlwaysShowIcons(p.always_show_icons), mTrackEnd( p.track_end ), mScrollIndex(-1), mSelectionStart( 0 ), @@ -271,6 +273,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) LLTextBase::~LLTextBase() { mSegments.clear(); + LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get()); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } delete mURLClickSignal; delete mIsFriendSignal; delete mIsObjectBlockedSignal; @@ -448,8 +456,48 @@ void LLTextBase::drawSelectionBackground() ++rect_it) { LLRect selection_rect = *rect_it; - selection_rect = *rect_it; - selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); + if (mScroller) + { + // If scroller is On content_display_rect has correct rect and safe to use as is + // Note: we might need to account for border + selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); + } + else + { + // If scroller is Off content_display_rect will have rect from document, adjusted to text width, heigh and position + // and we have to acount for offset depending on position + S32 v_delta = 0; + S32 h_delta = 0; + switch (mVAlign) + { + case LLFontGL::TOP: + v_delta = mVisibleTextRect.mTop - content_display_rect.mTop - mVPad; + break; + case LLFontGL::VCENTER: + v_delta = (llmax(mVisibleTextRect.getHeight() - content_display_rect.mTop, -content_display_rect.mBottom) + (mVisibleTextRect.mBottom - content_display_rect.mBottom)) / 2; + break; + case LLFontGL::BOTTOM: + v_delta = mVisibleTextRect.mBottom - content_display_rect.mBottom; + break; + default: + break; + } + switch (mHAlign) + { + case LLFontGL::LEFT: + h_delta = mVisibleTextRect.mLeft - content_display_rect.mLeft + mHPad; + break; + case LLFontGL::HCENTER: + h_delta = (llmax(mVisibleTextRect.getWidth() - content_display_rect.mLeft, -content_display_rect.mRight) + (mVisibleTextRect.mRight - content_display_rect.mRight)) / 2; + break; + case LLFontGL::RIGHT: + h_delta = mVisibleTextRect.mRight - content_display_rect.mRight; + break; + default: + break; + } + selection_rect.translate(h_delta, v_delta); + } gl_rect_2d(selection_rect, selection_color); } } @@ -2007,6 +2055,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, url)); + registrar.add("Url.ReportAbuse", boost::bind(&LLUrlAction::reportAbuse, url)); registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); @@ -2116,7 +2165,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para LLUrlMatch match; std::string text = new_text; while ( LLUrlRegistry::instance().findUrl(text, match, - boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted())) + boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted() || mAlwaysShowIcons)) { start = match.getStart(); end = match.getEnd()+1; @@ -2141,7 +2190,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } // add icon before url if need - LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); + LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted() || mAlwaysShowIcons); if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() ) { setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon")); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a4e83b42b4..25f8fa1c2b 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -321,7 +321,8 @@ public: parse_highlights, clip, clip_partial, - trusted_content; + trusted_content, + always_show_icons; Optional<S32> v_pad, h_pad; @@ -369,6 +370,8 @@ public: virtual void onFocusReceived(); virtual void onFocusLost(); + void setParseHTML(bool parse_html) { mParseHTML = parse_html; } + // LLSpellCheckMenuHandler overrides /*virtual*/ bool getSpellCheck() const; @@ -702,6 +705,8 @@ protected: bool mAutoIndent; S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes bool mSkipTripleClick; + bool mAlwaysShowIcons; + bool mSkipLinkUnderline; // support widgets diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index b1f8b00cab..3d2a426913 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -257,7 +257,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mMouseDownY(0), mTabsToNextField(p.ignore_tab), mPrevalidateFunc(p.prevalidate_callback()), - mContextMenu(NULL), mShowContextMenu(p.show_context_menu), mEnableTooltipPaste(p.enable_tooltip_paste), mPassDelete(FALSE), @@ -301,8 +300,13 @@ LLTextEditor::~LLTextEditor() // Scrollbar is deleted by LLView std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); mUndoStack.clear(); - // context menu is owned by menu holder, not us - //delete mContextMenu; + // Mark the menu as dead or its retained in memory till shutdown. + LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); + if(menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } } //////////////////////////////////////////////////////////// @@ -2051,12 +2055,19 @@ void LLTextEditor::setEnabled(BOOL enabled) void LLTextEditor::showContextMenu(S32 x, S32 y) { - if (!mContextMenu) + LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); + if (!menu) { llassert(LLMenuGL::sMenuContainer != NULL); - mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml", + menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if(!menu) + { + LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL; + return; + } + mContextMenuHandle = menu->getHandle(); } // Route menu to this class @@ -2102,11 +2113,11 @@ void LLTextEditor::showContextMenu(S32 x, S32 y) } } - mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); - mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); - mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); - mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); - mContextMenu->show(screen_x, screen_y, this); + menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + menu->show(screen_x, screen_y, this); } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 26702b2412..f3939248c2 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -196,6 +196,7 @@ public: const LLUUID& getSourceID() const { return mSourceID; } const LLTextSegmentPtr getPreviousSegment() const; + const LLTextSegmentPtr getLastSegment() const; void getSelectedSegments(segment_vec_t& segments) const; void setShowContextMenu(bool show) { mShowContextMenu = show; } @@ -328,7 +329,7 @@ private: keystroke_signal_t mKeystrokeSignal; LLTextValidate::validate_func_t mPrevalidateFunc; - LLContextMenu* mContextMenu; + LLHandle<LLContextMenu> mContextMenuHandle; }; // end class LLTextEditor // Build time optimization, generate once in .cpp file diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp index 538508b856..78049319bc 100644 --- a/indra/llui/lltextutil.cpp +++ b/indra/llui/lltextutil.cpp @@ -76,22 +76,6 @@ void LLTextUtil::textboxSetGreyedVal(LLTextBox *txtbox, const LLStyle::Params& n txtbox->appendText(text.substr(greyed_begin + greyed_len), false, normal_style); } -const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str) -{ - static const std::string PHONE_SEPARATOR = LLUI::getInstance()->mSettingGroups["config"]->getString("AvalinePhoneSeparator"); - static const S32 PHONE_PART_LEN = 2; - - static std::string formatted_phone_str; - formatted_phone_str = phone_str; - S32 separator_pos = (S32)(formatted_phone_str.size()) - PHONE_PART_LEN; - for (; separator_pos >= PHONE_PART_LEN; separator_pos -= PHONE_PART_LEN) - { - formatted_phone_str.insert(separator_pos, PHONE_SEPARATOR); - } - - return formatted_phone_str; -} - bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted) { if (match == 0 || text_base == 0) diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h index a9c143e445..1adc3516f7 100644 --- a/indra/llui/lltextutil.h +++ b/indra/llui/lltextutil.h @@ -59,18 +59,6 @@ namespace LLTextUtil const std::string& greyed); /** - * Formats passed phone number to be more human readable. - * - * It just divides the number on parts by two digits from right to left. The first left part - * can have 2 or 3 digits, i.e. +44-33-33-44-55-66 or 12-34-56-78-90. Separator is set in - * application settings (AvalinePhoneSeparator) - * - * @param[in] phone_str string with original phone number - * @return reference to string with formatted phone number - */ - const std::string& formatPhoneNumber(const std::string& phone_str); - - /** * Adds icon before url if need. * * @param[in] match an object with results of matching diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 5150df25f2..2707f7a15c 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -127,7 +127,12 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p) LLToolBar::~LLToolBar() { - delete mPopupMenuHandle.get(); + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } delete mButtonAddSignal; delete mButtonEnterSignal; delete mButtonLeaveSignal; diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index 84ea770a8d..8216046174 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -222,6 +222,15 @@ void LLUrlAction::removeFriend(std::string url) } } +void LLUrlAction::reportAbuse(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/reportAbuse"); + } +} + void LLUrlAction::blockObject(std::string url) { std::string object_id = getObjectId(url); diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 2d2a8dfef1..c2c576254d 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -82,6 +82,7 @@ public: static void sendIM(std::string url); static void addFriend(std::string url); static void removeFriend(std::string url); + static void reportAbuse(std::string url); static void blockObject(std::string url); static void unblockObject(std::string url); |