From 1b68f71348ecf3983b76b40d7940da8377f049b7 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Mon, 29 Apr 2024 07:43:28 +0300 Subject: #824 Process source files in bulk: replace tabs with spaces, convert CRLF to LF, and trim trailing whitespaces as needed --- indra/llui/llaccordionctrl.cpp | 1316 +++--- indra/llui/llaccordionctrl.h | 240 +- indra/llui/llaccordionctrltab.cpp | 1538 +++---- indra/llui/llaccordionctrltab.h | 266 +- indra/llui/llbadge.cpp | 610 +-- indra/llui/llbadge.h | 186 +- indra/llui/llbadgeholder.cpp | 24 +- indra/llui/llbadgeholder.h | 26 +- indra/llui/llbadgeowner.cpp | 122 +- indra/llui/llbadgeowner.h | 34 +- indra/llui/llbutton.cpp | 1914 ++++----- indra/llui/llbutton.h | 660 +-- indra/llui/llcallbackmap.h | 48 +- indra/llui/llchat.h | 120 +- indra/llui/llchatentry.cpp | 302 +- indra/llui/llchatentry.h | 98 +- indra/llui/llcheckboxctrl.cpp | 268 +- indra/llui/llcheckboxctrl.h | 126 +- indra/llui/llclipboard.cpp | 132 +- indra/llui/llclipboard.h | 84 +- indra/llui/llcombobox.cpp | 1554 +++---- indra/llui/llcombobox.h | 430 +- indra/llui/llcommandmanager.cpp | 174 +- indra/llui/llcommandmanager.h | 250 +- indra/llui/llconsole.cpp | 624 +-- indra/llui/llconsole.h | 220 +- indra/llui/llcontainerview.cpp | 412 +- indra/llui/llcontainerview.h | 88 +- indra/llui/llctrlselectioninterface.cpp | 20 +- indra/llui/llctrlselectioninterface.h | 96 +- indra/llui/lldockablefloater.cpp | 302 +- indra/llui/lldockablefloater.h | 206 +- indra/llui/lldockcontrol.cpp | 624 +-- indra/llui/lldockcontrol.h | 94 +- indra/llui/lldraghandle.cpp | 520 +-- indra/llui/lldraghandle.h | 144 +- indra/llui/lleditmenuhandler.cpp | 18 +- indra/llui/lleditmenuhandler.h | 76 +- indra/llui/llemojihelper.cpp | 178 +- indra/llui/llemojihelper.h | 40 +- indra/llui/llf32uictrl.cpp | 20 +- indra/llui/llf32uictrl.h | 58 +- indra/llui/llfiltereditor.cpp | 22 +- indra/llui/llfiltereditor.h | 36 +- indra/llui/llflashtimer.cpp | 66 +- indra/llui/llflashtimer.h | 58 +- indra/llui/llflatlistview.cpp | 1962 ++++----- indra/llui/llflatlistview.h | 814 ++-- indra/llui/llfloater.cpp | 5530 ++++++++++++------------ indra/llui/llfloater.h | 954 ++--- indra/llui/llfloaterreg.cpp | 730 ++-- indra/llui/llfloaterreg.h | 220 +- indra/llui/llfloaterreglistener.cpp | 10 +- indra/llui/llfloaterreglistener.h | 10 +- indra/llui/llflyoutbutton.cpp | 56 +- indra/llui/llflyoutbutton.h | 46 +- indra/llui/llfocusmgr.cpp | 620 +-- indra/llui/llfocusmgr.h | 184 +- indra/llui/llfolderview.cpp | 3090 +++++++------- indra/llui/llfolderview.h | 506 +-- indra/llui/llfolderviewitem.cpp | 3128 +++++++------- indra/llui/llfolderviewitem.h | 628 +-- indra/llui/llfolderviewmodel.cpp | 34 +- indra/llui/llfolderviewmodel.h | 722 ++-- indra/llui/llfunctorregistry.h | 138 +- indra/llui/llhelp.h | 26 +- indra/llui/lliconctrl.cpp | 140 +- indra/llui/lliconctrl.h | 82 +- indra/llui/llkeywords.cpp | 1342 +++--- indra/llui/llkeywords.h | 266 +- indra/llui/lllayoutstack.cpp | 1606 +++---- indra/llui/lllayoutstack.h | 270 +- indra/llui/lllazyvalue.h | 78 +- indra/llui/lllineeditor.cpp | 4204 +++++++++---------- indra/llui/lllineeditor.h | 796 ++-- indra/llui/llloadingindicator.cpp | 80 +- indra/llui/llloadingindicator.h | 88 +- indra/llui/lllocalcliprect.cpp | 98 +- indra/llui/lllocalcliprect.h | 32 +- indra/llui/llmenubutton.cpp | 298 +- indra/llui/llmenubutton.h | 100 +- indra/llui/llmenugl.cpp | 6466 ++++++++++++++--------------- indra/llui/llmenugl.h | 1262 +++--- indra/llui/llmodaldialog.cpp | 422 +- indra/llui/llmodaldialog.h | 78 +- indra/llui/llmultifloater.cpp | 694 ++-- indra/llui/llmultifloater.h | 120 +- indra/llui/llmultislider.cpp | 1264 +++--- indra/llui/llmultislider.h | 212 +- indra/llui/llmultisliderctrl.cpp | 710 ++-- indra/llui/llmultisliderctrl.h | 188 +- indra/llui/llnotificationptr.h | 8 +- indra/llui/llnotifications.cpp | 2638 ++++++------ indra/llui/llnotifications.h | 1514 +++---- indra/llui/llnotificationslistener.cpp | 80 +- indra/llui/llnotificationslistener.h | 18 +- indra/llui/llnotificationsutil.cpp | 82 +- indra/llui/llnotificationsutil.h | 52 +- indra/llui/llnotificationtemplate.h | 498 +-- indra/llui/llnotificationvisibilityrule.h | 114 +- indra/llui/llpanel.cpp | 1248 +++--- indra/llui/llpanel.h | 444 +- indra/llui/llprogressbar.cpp | 42 +- indra/llui/llprogressbar.h | 48 +- indra/llui/llradiogroup.cpp | 640 +-- indra/llui/llradiogroup.h | 130 +- indra/llui/llresizebar.cpp | 616 +-- indra/llui/llresizebar.h | 86 +- indra/llui/llresizehandle.cpp | 624 +-- indra/llui/llresizehandle.h | 62 +- indra/llui/llresmgr.cpp | 442 +- indra/llui/llresmgr.h | 46 +- indra/llui/llrngwriter.cpp | 516 +-- indra/llui/llrngwriter.h | 52 +- indra/llui/llscrollbar.cpp | 1008 ++--- indra/llui/llscrollbar.h | 188 +- indra/llui/llscrollcontainer.cpp | 1184 +++--- indra/llui/llscrollcontainer.h | 172 +- indra/llui/llscrollingpanellist.cpp | 340 +- indra/llui/llscrollingpanellist.h | 84 +- indra/llui/llscrolllistcell.cpp | 512 +-- indra/llui/llscrolllistcell.h | 318 +- indra/llui/llscrolllistcolumn.cpp | 476 +-- indra/llui/llscrolllistcolumn.h | 230 +- indra/llui/llscrolllistctrl.cpp | 4784 ++++++++++----------- indra/llui/llscrolllistctrl.h | 958 ++--- indra/llui/llscrolllistitem.cpp | 154 +- indra/llui/llscrolllistitem.h | 182 +- indra/llui/llsearchablecontrol.h | 62 +- indra/llui/llsearcheditor.cpp | 256 +- indra/llui/llsearcheditor.h | 134 +- indra/llui/llslider.cpp | 570 +-- indra/llui/llslider.h | 128 +- indra/llui/llsliderctrl.cpp | 646 +-- indra/llui/llsliderctrl.h | 236 +- indra/llui/llspellcheck.cpp | 704 ++-- indra/llui/llspellcheck.h | 82 +- indra/llui/llspellcheckmenuhandler.h | 26 +- indra/llui/llspinctrl.cpp | 666 +-- indra/llui/llspinctrl.h | 132 +- indra/llui/llstatbar.cpp | 1228 +++--- indra/llui/llstatbar.h | 150 +- indra/llui/llstatgraph.cpp | 146 +- indra/llui/llstatgraph.h | 210 +- indra/llui/llstatview.cpp | 38 +- indra/llui/llstatview.h | 44 +- indra/llui/llstyle.cpp | 64 +- indra/llui/llstyle.h | 124 +- indra/llui/lltabcontainer.cpp | 3516 ++++++++-------- indra/llui/lltabcontainer.h | 556 +-- indra/llui/lltextbase.cpp | 5746 ++++++++++++------------- indra/llui/lltextbase.h | 1158 +++--- indra/llui/lltextbox.cpp | 162 +- indra/llui/lltextbox.h | 70 +- indra/llui/lltexteditor.cpp | 4634 ++++++++++----------- indra/llui/lltexteditor.h | 468 +-- indra/llui/lltextparser.cpp | 348 +- indra/llui/lltextparser.h | 36 +- indra/llui/lltextutil.cpp | 98 +- indra/llui/lltextutil.h | 84 +- indra/llui/lltextvalidate.cpp | 598 +-- indra/llui/lltextvalidate.h | 46 +- indra/llui/lltimectrl.cpp | 486 +-- indra/llui/lltimectrl.h | 124 +- indra/llui/lltoggleablemenu.cpp | 92 +- indra/llui/lltoggleablemenu.h | 52 +- indra/llui/lltoolbar.cpp | 2048 ++++----- indra/llui/lltoolbar.h | 504 +-- indra/llui/lltooltip.cpp | 824 ++-- indra/llui/lltooltip.h | 198 +- indra/llui/lltrans.cpp | 506 +-- indra/llui/lltrans.h | 160 +- indra/llui/lltransutil.cpp | 56 +- indra/llui/lltransutil.h | 24 +- indra/llui/llui.cpp | 982 ++--- indra/llui/llui.h | 706 ++-- indra/llui/lluicolor.cpp | 44 +- indra/llui/lluicolor.h | 48 +- indra/llui/lluicolortable.cpp | 476 +-- indra/llui/lluicolortable.h | 94 +- indra/llui/lluiconstants.h | 20 +- indra/llui/lluictrl.cpp | 1484 +++---- indra/llui/lluictrl.h | 536 +-- indra/llui/lluictrlfactory.cpp | 296 +- indra/llui/lluictrlfactory.h | 424 +- indra/llui/lluifwd.h | 8 +- indra/llui/lluistring.cpp | 136 +- indra/llui/lluistring.h | 94 +- indra/llui/lluiusage.cpp | 124 +- indra/llui/lluiusage.h | 30 +- indra/llui/llundo.cpp | 176 +- indra/llui/llundo.h | 64 +- indra/llui/llurlaction.cpp | 234 +- indra/llui/llurlaction.h | 92 +- indra/llui/llurlentry.cpp | 1744 ++++---- indra/llui/llurlentry.h | 422 +- indra/llui/llurlmatch.cpp | 66 +- indra/llui/llurlmatch.h | 106 +- indra/llui/llurlregistry.cpp | 460 +- indra/llui/llurlregistry.h | 68 +- indra/llui/llview.cpp | 4020 +++++++++--------- indra/llui/llview.h | 1212 +++--- indra/llui/llviewborder.cpp | 392 +- indra/llui/llviewborder.h | 134 +- indra/llui/llviewereventrecorder.cpp | 54 +- indra/llui/llviewereventrecorder.h | 22 +- indra/llui/llviewinject.cpp | 2 +- indra/llui/llviewinject.h | 2 +- indra/llui/llviewmodel.cpp | 26 +- indra/llui/llviewmodel.h | 134 +- indra/llui/llviewquery.cpp | 152 +- indra/llui/llviewquery.h | 96 +- indra/llui/llvirtualtrackball.cpp | 10 +- indra/llui/llvirtualtrackball.h | 2 +- indra/llui/llwindowshade.cpp | 576 +-- indra/llui/llwindowshade.h | 70 +- indra/llui/llxuiparser.cpp | 2528 +++++------ indra/llui/llxuiparser.h | 304 +- indra/llui/llxyvector.cpp | 4 +- indra/llui/llxyvector.h | 36 +- indra/llui/tests/llurlentry_stub.cpp | 136 +- indra/llui/tests/llurlentry_test.cpp | 1682 ++++---- indra/llui/tests/llurlmatch_test.cpp | 400 +- 223 files changed, 62253 insertions(+), 62253 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 0a82bed896..89969acb1b 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llaccordionctrl.cpp * @brief Accordion panel implementation * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,7 +45,7 @@ static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; // LLAccordionCtrl =================================================================| -static LLDefaultChildRegistry::Register t2("accordion"); +static LLDefaultChildRegistry::Register t2("accordion"); LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mFitParent(params.fit_parent) @@ -57,13 +57,13 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString()) , mSkipScrollToChild(false) { - initNoTabsWidget(params.no_matched_tabs_text); + initNoTabsWidget(params.no_matched_tabs_text); - mSingleExpansion = params.single_expansion; - if (mFitParent && !mSingleExpansion) - { - LL_INFOS() << "fit_parent works best when combined with single_expansion" << LL_ENDL; - } + mSingleExpansion = params.single_expansion; + if (mFitParent && !mSingleExpansion) + { + LL_INFOS() << "fit_parent works best when combined with single_expansion" << LL_ENDL; + } } LLAccordionCtrl::LLAccordionCtrl() : LLPanel() @@ -72,102 +72,102 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel() , mSelectedTab( NULL ) , mNoVisibleTabsHelpText(NULL) { - initNoTabsWidget(LLTextBox::Params()); + initNoTabsWidget(LLTextBox::Params()); - mSingleExpansion = false; - mFitParent = false; - buildFromFile( "accordion_parent.xml"); + mSingleExpansion = false; + mFitParent = false; + buildFromFile( "accordion_parent.xml"); } //--------------------------------------------------------------------------------- void LLAccordionCtrl::draw() { - if (mAutoScrolling) - { - // add acceleration to autoscroll - mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); - } - else - { - // reset to minimum for next time - mAutoScrollRate = MIN_AUTO_SCROLL_RATE; - } - // clear this flag to be set on next call to autoScroll - mAutoScrolling = false; - - LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - - LLLocalClipRect clip(local_rect); - - LLPanel::draw(); + if (mAutoScrolling) + { + // add acceleration to autoscroll + mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); + } + else + { + // reset to minimum for next time + mAutoScrollRate = MIN_AUTO_SCROLL_RATE; + } + // clear this flag to be set on next call to autoScroll + mAutoScrolling = false; + + LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + + LLLocalClipRect clip(local_rect); + + LLPanel::draw(); } //--------------------------------------------------------------------------------- BOOL LLAccordionCtrl::postBuild() { - static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); - - LLRect scroll_rect; - scroll_rect.setOriginAndSize( - getRect().getWidth() - scrollbar_size, - 1, - scrollbar_size, - getRect().getHeight() - 1); - - LLScrollbar::Params sbparams; - sbparams.name("scrollable vertical"); - sbparams.rect(scroll_rect); - sbparams.orientation(LLScrollbar::VERTICAL); - sbparams.doc_size(mInnerRect.getHeight()); - sbparams.doc_pos(0); - sbparams.page_size(mInnerRect.getHeight()); - sbparams.step_size(VERTICAL_MULTIPLE); - sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2)); - - mScrollbar = LLUICtrlFactory::create(sbparams); - LLView::addChild(mScrollbar); - mScrollbar->setVisible(FALSE); - mScrollbar->setFollowsRight(); - mScrollbar->setFollowsTop(); - mScrollbar->setFollowsBottom(); - - //if it was created from xml... - std::vector accordion_tabs; - for (child_list_const_iter_t it = getChildList()->begin(); - getChildList()->end() != it; ++it) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(*it); - if (accordion_tab == NULL) - continue; - if (std::find(mAccordionTabs.begin(), mAccordionTabs.end(), accordion_tab) == mAccordionTabs.end()) - { - accordion_tabs.push_back(accordion_tab); - } - } - - for (std::vector::reverse_iterator it = accordion_tabs.rbegin(); - it < accordion_tabs.rend(); ++it) - { - addCollapsibleCtrl(*it); - } - - arrange(); - - if (mSingleExpansion) - { - if (!mAccordionTabs[0]->getDisplayChildren()) - mAccordionTabs[0]->setDisplayChildren(true); - for (size_t i = 1; i < mAccordionTabs.size(); ++i) - { - if (mAccordionTabs[i]->getDisplayChildren()) - mAccordionTabs[i]->setDisplayChildren(false); - } - } - - updateNoTabsHelpTextVisibility(); - - return TRUE; + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + LLScrollbar::Params sbparams; + sbparams.name("scrollable vertical"); + sbparams.rect(scroll_rect); + sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(mInnerRect.getHeight()); + sbparams.doc_pos(0); + sbparams.page_size(mInnerRect.getHeight()); + sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2)); + + mScrollbar = LLUICtrlFactory::create(sbparams); + LLView::addChild(mScrollbar); + mScrollbar->setVisible(FALSE); + mScrollbar->setFollowsRight(); + mScrollbar->setFollowsTop(); + mScrollbar->setFollowsBottom(); + + //if it was created from xml... + std::vector accordion_tabs; + for (child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*it); + if (accordion_tab == NULL) + continue; + if (std::find(mAccordionTabs.begin(), mAccordionTabs.end(), accordion_tab) == mAccordionTabs.end()) + { + accordion_tabs.push_back(accordion_tab); + } + } + + for (std::vector::reverse_iterator it = accordion_tabs.rbegin(); + it < accordion_tabs.rend(); ++it) + { + addCollapsibleCtrl(*it); + } + + arrange(); + + if (mSingleExpansion) + { + if (!mAccordionTabs[0]->getDisplayChildren()) + mAccordionTabs[0]->setDisplayChildren(true); + for (size_t i = 1; i < mAccordionTabs.size(); ++i) + { + if (mAccordionTabs[i]->getDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + } + + updateNoTabsHelpTextVisibility(); + + return TRUE; } @@ -181,478 +181,478 @@ LLAccordionCtrl::~LLAccordionCtrl() void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) { - // adjust our rectangle - LLRect rcLocal = getRect(); - rcLocal.mRight = rcLocal.mLeft + width; - rcLocal.mTop = rcLocal.mBottom + height; + // adjust our rectangle + LLRect rcLocal = getRect(); + rcLocal.mRight = rcLocal.mLeft + width; + rcLocal.mTop = rcLocal.mBottom + height; - // get textbox a chance to reshape its content - mNoVisibleTabsHelpText->reshape(width, height, called_from_parent); + // get textbox a chance to reshape its content + mNoVisibleTabsHelpText->reshape(width, height, called_from_parent); - setRect(rcLocal); + setRect(rcLocal); - // assume that help text is always fit accordion. - // necessary text paddings can be set via h_pad and v_pad - mNoVisibleTabsHelpText->setRect(getLocalRect()); + // assume that help text is always fit accordion. + // necessary text paddings can be set via h_pad and v_pad + mNoVisibleTabsHelpText->setRect(getLocalRect()); - arrange(); + arrange(); } //--------------------------------------------------------------------------------- BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) { - return LLPanel::handleRightMouseDown(x, y, mask); + return LLPanel::handleRightMouseDown(x, y, mask); } //--------------------------------------------------------------------------------- void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta) { - for (size_t i = panel_num; i < mAccordionTabs.size(); ++i) - { - ctrlShiftVertical(mAccordionTabs[i],delta); - } + for (size_t i = panel_num; i < mAccordionTabs.size(); ++i) + { + ctrlShiftVertical(mAccordionTabs[i],delta); + } } //--------------------------------------------------------------------------------- -void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) +void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) { - if (mSingleExpansion) - { - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - if (i == panel_num) - continue; - if (mAccordionTabs[i]->getDisplayChildren()) - mAccordionTabs[i]->setDisplayChildren(false); - } + if (mSingleExpansion) + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + if (i == panel_num) + continue; + if (mAccordionTabs[i]->getDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } - } - arrange(); + } + arrange(); } void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height) { - calcRecuiredHeight(); - if (getRecuiredHeight() > height) - showScrollbar(width, height); - else - hideScrollbar(width, height); + calcRecuiredHeight(); + if (getRecuiredHeight() > height) + showScrollbar(width, height); + else + hideScrollbar(width, height); } void LLAccordionCtrl::showScrollbar(S32 width, S32 height) { - bool was_visible = mScrollbar->getVisible(); + bool was_visible = mScrollbar->getVisible(); + + mScrollbar->setVisible(TRUE); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - mScrollbar->setVisible(TRUE); - - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + ctrlSetLeftTopAndSize(mScrollbar + , width - scrollbar_size - PARENT_BORDER_MARGIN / 2 + , height - PARENT_BORDER_MARGIN + , scrollbar_size + , height - PARENT_BORDER_MARGIN * 2); - ctrlSetLeftTopAndSize(mScrollbar - , width - scrollbar_size - PARENT_BORDER_MARGIN / 2 - , height - PARENT_BORDER_MARGIN - , scrollbar_size - , height - PARENT_BORDER_MARGIN * 2); - - mScrollbar->setPageSize(height); - mScrollbar->setDocParams(mInnerRect.getHeight(), mScrollbar->getDocPos()); + mScrollbar->setPageSize(height); + mScrollbar->setDocParams(mInnerRect.getHeight(), mScrollbar->getDocPos()); - if (was_visible) - { - S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); - mScrollbar->setDocPos(scroll_pos); - } + if (was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); + mScrollbar->setDocPos(scroll_pos); + } } void LLAccordionCtrl::hideScrollbar(S32 width, S32 height) { - if (mScrollbar->getVisible() == FALSE) - return; - mScrollbar->setVisible(FALSE); + if (mScrollbar->getVisible() == FALSE) + return; + mScrollbar->setVisible(FALSE); - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - S32 panel_width = width - 2*BORDER_MARGIN; + S32 panel_width = width - 2*BORDER_MARGIN; - // Reshape all accordions and shift all draggers - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLRect panel_rect = mAccordionTabs[i]->getRect(); - ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_rect.mTop, panel_width, panel_rect.getHeight()); - } + // Reshape all accordions and shift all draggers + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_rect.mTop, panel_width, panel_rect.getHeight()); + } - mScrollbar->setDocPos(0); + mScrollbar->setDocPos(0); - if (!mAccordionTabs.empty()) - { - S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel - S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; - shiftAccordionTabs(0, diff); - } + if (!mAccordionTabs.empty()) + { + S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel + S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; + shiftAccordionTabs(0, diff); + } } //--------------------------------------------------------------------------------- S32 LLAccordionCtrl::calcRecuiredHeight() { - S32 rec_height = 0; - - std::vector::iterator panel; - for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(*panel); - if(accordion_tab && accordion_tab->getVisible()) - { - rec_height += accordion_tab->getRect().getHeight(); - } - } + S32 rec_height = 0; - mInnerRect.setLeftTopAndSize(0, rec_height + BORDER_MARGIN * 2, getRect().getWidth(), rec_height + BORDER_MARGIN); + std::vector::iterator panel; + for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*panel); + if(accordion_tab && accordion_tab->getVisible()) + { + rec_height += accordion_tab->getRect().getHeight(); + } + } + + mInnerRect.setLeftTopAndSize(0, rec_height + BORDER_MARGIN * 2, getRect().getWidth(), rec_height + BORDER_MARGIN); - return mInnerRect.getHeight(); + return mInnerRect.getHeight(); } //--------------------------------------------------------------------------------- void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) { - if (!panel) - return; - LLRect panel_rect = panel->getRect(); - panel_rect.setLeftTopAndSize( left, top, width, height); - panel->reshape( width, height, 1); - panel->setRect(panel_rect); + if (!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize( left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); } void LLAccordionCtrl::ctrlShiftVertical(LLView* panel, S32 delta) { - if (!panel) - return; - panel->translate(0,delta); + if (!panel) + return; + panel->translate(0,delta); } //--------------------------------------------------------------------------------- void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); - if (!accordion_tab) - return; - if (std::find(beginChild(), endChild(), accordion_tab) == endChild()) - addChild(accordion_tab); - mAccordionTabs.push_back(accordion_tab); + LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); + if (!accordion_tab) + return; + if (std::find(beginChild(), endChild(), accordion_tab) == endChild()) + addChild(accordion_tab); + mAccordionTabs.push_back(accordion_tab); - accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, (S16)(mAccordionTabs.size() - 1)) ); - arrange(); + accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, (S16)(mAccordionTabs.size() - 1)) ); + arrange(); } void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); - if(!accordion_tab) - return; + LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); + if(!accordion_tab) + return; - if(std::find(beginChild(), endChild(), accordion_tab) != endChild()) - removeChild(accordion_tab); + if(std::find(beginChild(), endChild(), accordion_tab) != endChild()) + removeChild(accordion_tab); - for (std::vector::iterator iter = mAccordionTabs.begin(); - iter != mAccordionTabs.end(); ++iter) - { - if (accordion_tab == (*iter)) - { - mAccordionTabs.erase(iter); - break; - } - } + for (std::vector::iterator iter = mAccordionTabs.begin(); + iter != mAccordionTabs.end(); ++iter) + { + if (accordion_tab == (*iter)) + { + mAccordionTabs.erase(iter); + break; + } + } - // if removed is selected - reset selection - if (mSelectedTab == view) - { - mSelectedTab = NULL; - } + // if removed is selected - reset selection + if (mSelectedTab == view) + { + mSelectedTab = NULL; + } } void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) { - LLTextBox::Params tp = tb_params; - tp.rect(getLocalRect()); - mNoMatchedTabsOrigString = tp.initial_value().asString(); - mNoVisibleTabsHelpText = LLUICtrlFactory::create(tp, this); + LLTextBox::Params tp = tb_params; + tp.rect(getLocalRect()); + mNoMatchedTabsOrigString = tp.initial_value().asString(); + mNoVisibleTabsHelpText = LLUICtrlFactory::create(tp, this); } void LLAccordionCtrl::updateNoTabsHelpTextVisibility() { - bool visible_exists = false; - std::vector::const_iterator it = mAccordionTabs.begin(); - const std::vector::const_iterator it_end = mAccordionTabs.end(); - while (it < it_end) - { - if ((*(it++))->getVisible()) - { - visible_exists = true; - break; - } - } + bool visible_exists = false; + std::vector::const_iterator it = mAccordionTabs.begin(); + const std::vector::const_iterator it_end = mAccordionTabs.end(); + while (it < it_end) + { + if ((*(it++))->getVisible()) + { + visible_exists = true; + break; + } + } - mNoVisibleTabsHelpText->setVisible(visible_exists ? FALSE : TRUE); + mNoVisibleTabsHelpText->setVisible(visible_exists ? FALSE : TRUE); } void LLAccordionCtrl::arrangeSingle() { - S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter - S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel - S32 panel_width = getRect().getWidth() - 4; - S32 panel_height; - - S32 collapsed_height = 0; - - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - - if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs - continue; - if (!accordion_tab->isExpanded() ) - { - collapsed_height+=mAccordionTabs[i]->getRect().getHeight(); - } - } - - S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height; - - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - - if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs - continue; - if (!accordion_tab->isExpanded() ) - { - panel_height = accordion_tab->getRect().getHeight(); - } - else - { - if (mFitParent) - { - panel_height = expanded_height; - } - else - { - if (accordion_tab->getAccordionView()) - { - panel_height = accordion_tab->getAccordionView()->getRect().getHeight() + - accordion_tab->getHeaderHeight() + BORDER_MARGIN * 2; - } - else - { - panel_height = accordion_tab->getRect().getHeight(); - } - } - } - - // make sure at least header is shown - panel_height = llmax(panel_height, accordion_tab->getHeaderHeight()); - - ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); - panel_top -= mAccordionTabs[i]->getRect().getHeight(); - } - - show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); - updateLayout(getRect().getWidth(), getRect().getHeight()); + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; + S32 panel_height; + + S32 collapsed_height = 0; + + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs + continue; + if (!accordion_tab->isExpanded() ) + { + collapsed_height+=mAccordionTabs[i]->getRect().getHeight(); + } + } + + S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height; + + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs + continue; + if (!accordion_tab->isExpanded() ) + { + panel_height = accordion_tab->getRect().getHeight(); + } + else + { + if (mFitParent) + { + panel_height = expanded_height; + } + else + { + if (accordion_tab->getAccordionView()) + { + panel_height = accordion_tab->getAccordionView()->getRect().getHeight() + + accordion_tab->getHeaderHeight() + BORDER_MARGIN * 2; + } + else + { + panel_height = accordion_tab->getRect().getHeight(); + } + } + } + + // make sure at least header is shown + panel_height = llmax(panel_height, accordion_tab->getHeaderHeight()); + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top -= mAccordionTabs[i]->getRect().getHeight(); + } + + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); } void LLAccordionCtrl::arrangeMultiple() { - S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter - S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel - S32 panel_width = getRect().getWidth() - 4; - - //Calculate params - for (size_t i = 0; i < mAccordionTabs.size(); i++ ) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - - if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs - continue; - - if (!accordion_tab->isExpanded() ) - { - ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); - panel_top -= mAccordionTabs[i]->getRect().getHeight(); - } - else - { - S32 panel_height = accordion_tab->getRect().getHeight(); - - if (mFitParent) - { - // All expanded tabs will have equal height - panel_height = calcExpandedTabHeight(i, panel_top); - ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height); - - // Try to make accordion tab fit accordion view height. - // Accordion View should implement getRequiredRect() and provide valid height - S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight(); - optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN; - if (optimal_height < panel_height) - { - panel_height = optimal_height; - } - - // minimum tab height is equal to header height - if (mAccordionTabs[i]->getHeaderHeight() > panel_height) - { - panel_height = mAccordionTabs[i]->getHeaderHeight(); - } - } - - ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); - panel_top -= panel_height; - - } - } - - show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); - - updateLayout(getRect().getWidth(), getRect().getHeight()); + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; + + //Calculate params + for (size_t i = 0; i < mAccordionTabs.size(); i++ ) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs + continue; + + if (!accordion_tab->isExpanded() ) + { + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); + panel_top -= mAccordionTabs[i]->getRect().getHeight(); + } + else + { + S32 panel_height = accordion_tab->getRect().getHeight(); + + if (mFitParent) + { + // All expanded tabs will have equal height + panel_height = calcExpandedTabHeight(i, panel_top); + ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height); + + // Try to make accordion tab fit accordion view height. + // Accordion View should implement getRequiredRect() and provide valid height + S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight(); + optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN; + if (optimal_height < panel_height) + { + panel_height = optimal_height; + } + + // minimum tab height is equal to header height + if (mAccordionTabs[i]->getHeaderHeight() > panel_height) + { + panel_height = mAccordionTabs[i]->getHeaderHeight(); + } + } + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top -= panel_height; + + } + } + + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); + + updateLayout(getRect().getWidth(), getRect().getHeight()); } void LLAccordionCtrl::arrange() { - updateNoTabsHelpTextVisibility(); - - if (mAccordionTabs.empty()) - { - // Nothing to arrange - return; - } - - if (mAccordionTabs.size() == 1) - { - S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel - S32 panel_width = getRect().getWidth() - 4; - - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[0]); - - LLRect panel_rect = accordion_tab->getRect(); - - S32 panel_height = getRect().getHeight() - BORDER_MARGIN * 2; - if (accordion_tab->getFitParent()) - panel_height = accordion_tab->getRect().getHeight(); - - ctrlSetLeftTopAndSize(accordion_tab, panel_rect.mLeft, panel_top, panel_width, panel_height); - - show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); - return; - } - - if (mSingleExpansion) - arrangeSingle(); - else - arrangeMultiple(); + updateNoTabsHelpTextVisibility(); + + if (mAccordionTabs.empty()) + { + // Nothing to arrange + return; + } + + if (mAccordionTabs.size() == 1) + { + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; + + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[0]); + + LLRect panel_rect = accordion_tab->getRect(); + + S32 panel_height = getRect().getHeight() - BORDER_MARGIN * 2; + if (accordion_tab->getFitParent()) + panel_height = accordion_tab->getRect().getHeight(); + + ctrlSetLeftTopAndSize(accordion_tab, panel_rect.mLeft, panel_top, panel_width, panel_height); + + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); + return; + } + + if (mSingleExpansion) + arrangeSingle(); + else + arrangeMultiple(); } //--------------------------------------------------------------------------------- BOOL LLAccordionCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if (LLPanel::handleScrollWheel(x, y, clicks)) - return TRUE; - if (mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) - return TRUE; - return FALSE; + if (LLPanel::handleScrollWheel(x, y, clicks)) + return TRUE; + if (mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) + return TRUE; + return FALSE; } BOOL LLAccordionCtrl::handleKeyHere(KEY key, MASK mask) { - if (mScrollbar->getVisible() && mScrollbar->handleKeyHere(key, mask)) - return TRUE; - return LLPanel::handleKeyHere(key, mask); + if (mScrollbar->getVisible() && mScrollbar->handleKeyHere(key, mask)) + return TRUE; + return LLPanel::handleKeyHere(key, mask); } BOOL LLAccordionCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - // Scroll folder view if needed. Never accepts a drag or drop. - *accept = ACCEPT_NO; - BOOL handled = autoScroll(x, y); + // Scroll folder view if needed. Never accepts a drag or drop. + *accept = ACCEPT_NO; + BOOL handled = autoScroll(x, y); - if (!handled) - { - handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg) != NULL; - } - return TRUE; + if (!handled) + { + handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg) != NULL; + } + return TRUE; } BOOL LLAccordionCtrl::autoScroll(S32 x, S32 y) { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - bool scrolling = false; - if (mScrollbar->getVisible()) - { - LLRect rect_local(0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0); - LLRect screen_local_extents; + bool scrolling = false; + if (mScrollbar->getVisible()) + { + LLRect rect_local(0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0); + LLRect screen_local_extents; - // clip rect against root view - screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); - rect_local.intersectWith(screen_local_extents); + // clip rect against root view + screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); + rect_local.intersectWith(screen_local_extents); - // autoscroll region should take up no more than one third of visible scroller area - S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10); - S32 auto_scroll_speed = ll_round(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + // autoscroll region should take up no more than one third of visible scroller area + S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10); + S32 auto_scroll_speed = ll_round(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); - LLRect bottom_scroll_rect = screen_local_extents; - bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height; - if (bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax())) - { - mScrollbar->setDocPos(mScrollbar->getDocPos() + auto_scroll_speed); - mAutoScrolling = true; - scrolling = true; - } + LLRect bottom_scroll_rect = screen_local_extents; + bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height; + if (bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax())) + { + mScrollbar->setDocPos(mScrollbar->getDocPos() + auto_scroll_speed); + mAutoScrolling = true; + scrolling = true; + } - LLRect top_scroll_rect = screen_local_extents; - top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height; - if (top_scroll_rect.pointInRect(x, y) && (mScrollbar->getDocPos() > 0)) - { - mScrollbar->setDocPos(mScrollbar->getDocPos() - auto_scroll_speed); - mAutoScrolling = true; - scrolling = true; - } - } + LLRect top_scroll_rect = screen_local_extents; + top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height; + if (top_scroll_rect.pointInRect(x, y) && (mScrollbar->getDocPos() > 0)) + { + mScrollbar->setDocPos(mScrollbar->getDocPos() - auto_scroll_speed); + mAutoScrolling = true; + scrolling = true; + } + } - return scrolling ? TRUE : FALSE; + return scrolling ? TRUE : FALSE; } void LLAccordionCtrl::updateLayout(S32 width, S32 height) { - S32 panel_top = height - BORDER_MARGIN ; - if (mScrollbar->getVisible()) - panel_top += mScrollbar->getDocPos(); + S32 panel_top = height - BORDER_MARGIN ; + if (mScrollbar->getVisible()) + panel_top += mScrollbar->getDocPos(); - S32 panel_width = width - BORDER_MARGIN * 2; + S32 panel_width = width - BORDER_MARGIN * 2; - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - if (mScrollbar->getVisible()) - panel_width -= scrollbar_size; + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + if (mScrollbar->getVisible()) + panel_width -= scrollbar_size; - // set sizes for first panels and dragbars - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - if (!mAccordionTabs[i]->getVisible()) - continue; - LLRect panel_rect = mAccordionTabs[i]->getRect(); - ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_top, panel_width, panel_rect.getHeight()); - panel_top -= panel_rect.getHeight(); - } + // set sizes for first panels and dragbars + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + if (!mAccordionTabs[i]->getVisible()) + continue; + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_top, panel_width, panel_rect.getHeight()); + panel_top -= panel_rect.getHeight(); + } } void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) { - updateLayout(getRect().getWidth(), getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); } // virtual @@ -676,7 +676,7 @@ void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl) S32 scroll_pos = llclamp(mScrollbar->getDocPos(), bottom, // min vertical scroll - top); // max vertical scroll + top); // max vertical scroll mScrollbar->setDocPos(scroll_pos); } @@ -687,252 +687,252 @@ void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl) void LLAccordionCtrl::onOpen(const LLSD& key) { - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - LLPanel* panel = dynamic_cast(accordion_tab->getAccordionView()); - if (panel != NULL) - { - panel->onOpen(key); - } - } -} - -S32 LLAccordionCtrl::notifyParent(const LLSD& info) -{ - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "size_changes") - { - // - arrange(); - return 1; - } - if (str_action == "select_next") - { - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - if (accordion_tab->hasFocus()) - { - while (++i < mAccordionTabs.size()) - { - if (mAccordionTabs[i]->getVisible()) - break; - } - if (i < mAccordionTabs.size()) - { - accordion_tab = dynamic_cast(mAccordionTabs[i]); - accordion_tab->notify(LLSD().with("action","select_first")); - return 1; - } - break; - } - } - return 0; - } - if (str_action == "select_prev") - { - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); - if (accordion_tab->hasFocus() && i > 0) - { - bool prev_visible_tab_found = false; - while (i > 0) - { - if (mAccordionTabs[--i]->getVisible()) - { - prev_visible_tab_found = true; - break; - } - } - - if (prev_visible_tab_found) - { - accordion_tab = dynamic_cast(mAccordionTabs[i]); - accordion_tab->notify(LLSD().with("action","select_last")); - return 1; - } - break; - } - } - return 0; - } - if (str_action == "select_current") - { - for (size_t i = 0; i < mAccordionTabs.size(); ++i) - { - // Set selection to the currently focused tab. - if (mAccordionTabs[i]->hasFocus()) - { - if (mAccordionTabs[i] != mSelectedTab) - { - if (mSelectedTab) - { - mSelectedTab->setSelected(false); - } - mSelectedTab = mAccordionTabs[i]; - mSelectedTab->setSelected(true); - } - - return 1; - } - } - return 0; - } - if (str_action == "deselect_current") - { - // Reset selection to the currently selected tab. - if (mSelectedTab) - { - mSelectedTab->setSelected(false); - mSelectedTab = NULL; - return 1; - } - return 0; - } - } - else if (info.has("scrollToShowRect")) - { - LLRect screen_rc, local_rc; - screen_rc.setValue(info["scrollToShowRect"]); - screenRectToLocal(screen_rc, &local_rc); - - // Translate to parent coordinatess to check if we are in visible rectangle - local_rc.translate(getRect().mLeft, getRect().mBottom); - - if (!getRect().contains (local_rc)) - { - // Back to local coords and calculate position for scroller - S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; - S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop; - - S32 scroll_pos = llclamp(mScrollbar->getDocPos(), - bottom, // min vertical scroll - top); // max vertical scroll - - mScrollbar->setDocPos(scroll_pos); - } - return 1; - } - else if (info.has("child_visibility_change")) - { - BOOL new_visibility = info["child_visibility_change"]; - if (new_visibility) - { - // there is at least one visible tab - mNoVisibleTabsHelpText->setVisible(FALSE); - } - else - { - // it could be the latest visible tab, check all of them - updateNoTabsHelpTextVisibility(); - } - } - return LLPanel::notifyParent(info); + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + LLPanel* panel = dynamic_cast(accordion_tab->getAccordionView()); + if (panel != NULL) + { + panel->onOpen(key); + } + } +} + +S32 LLAccordionCtrl::notifyParent(const LLSD& info) +{ + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "size_changes") + { + // + arrange(); + return 1; + } + if (str_action == "select_next") + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + if (accordion_tab->hasFocus()) + { + while (++i < mAccordionTabs.size()) + { + if (mAccordionTabs[i]->getVisible()) + break; + } + if (i < mAccordionTabs.size()) + { + accordion_tab = dynamic_cast(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_first")); + return 1; + } + break; + } + } + return 0; + } + if (str_action == "select_prev") + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + if (accordion_tab->hasFocus() && i > 0) + { + bool prev_visible_tab_found = false; + while (i > 0) + { + if (mAccordionTabs[--i]->getVisible()) + { + prev_visible_tab_found = true; + break; + } + } + + if (prev_visible_tab_found) + { + accordion_tab = dynamic_cast(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_last")); + return 1; + } + break; + } + } + return 0; + } + if (str_action == "select_current") + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + // Set selection to the currently focused tab. + if (mAccordionTabs[i]->hasFocus()) + { + if (mAccordionTabs[i] != mSelectedTab) + { + if (mSelectedTab) + { + mSelectedTab->setSelected(false); + } + mSelectedTab = mAccordionTabs[i]; + mSelectedTab->setSelected(true); + } + + return 1; + } + } + return 0; + } + if (str_action == "deselect_current") + { + // Reset selection to the currently selected tab. + if (mSelectedTab) + { + mSelectedTab->setSelected(false); + mSelectedTab = NULL; + return 1; + } + return 0; + } + } + else if (info.has("scrollToShowRect")) + { + LLRect screen_rc, local_rc; + screen_rc.setValue(info["scrollToShowRect"]); + screenRectToLocal(screen_rc, &local_rc); + + // Translate to parent coordinatess to check if we are in visible rectangle + local_rc.translate(getRect().mLeft, getRect().mBottom); + + if (!getRect().contains (local_rc)) + { + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos(scroll_pos); + } + return 1; + } + else if (info.has("child_visibility_change")) + { + BOOL new_visibility = info["child_visibility_change"]; + if (new_visibility) + { + // there is at least one visible tab + mNoVisibleTabsHelpText->setVisible(FALSE); + } + else + { + // it could be the latest visible tab, check all of them + updateNoTabsHelpTextVisibility(); + } + } + return LLPanel::notifyParent(info); } void LLAccordionCtrl::reset() { - if (mScrollbar) - mScrollbar->setDocPos(0); + if (mScrollbar) + mScrollbar->setDocPos(0); } void LLAccordionCtrl::expandDefaultTab() { - if (!mAccordionTabs.empty()) - { - LLAccordionCtrlTab* tab = mAccordionTabs.front(); + if (!mAccordionTabs.empty()) + { + LLAccordionCtrlTab* tab = mAccordionTabs.front(); - if (!tab->getDisplayChildren()) - { - tab->setDisplayChildren(true); - } + if (!tab->getDisplayChildren()) + { + tab->setDisplayChildren(true); + } - for (size_t i = 1; i < mAccordionTabs.size(); ++i) - { - tab = mAccordionTabs[i]; + for (size_t i = 1; i < mAccordionTabs.size(); ++i) + { + tab = mAccordionTabs[i]; - if (tab->getDisplayChildren()) - { - tab->setDisplayChildren(false); - } - } + if (tab->getDisplayChildren()) + { + tab->setDisplayChildren(false); + } + } - arrange(); - } + arrange(); + } } void LLAccordionCtrl::sort() { - if (!mTabComparator) - { - LL_WARNS() << "No comparator specified for sorting accordion tabs." << LL_ENDL; - return; - } + if (!mTabComparator) + { + LL_WARNS() << "No comparator specified for sorting accordion tabs." << LL_ENDL; + return; + } - std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator)); - arrange(); + std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator)); + arrange(); } void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) { - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(filter_string); - std::string text = filter_string.empty() ? mNoVisibleTabsOrigString : mNoMatchedTabsOrigString; - LLStringUtil::format(text, args); + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = filter_string.empty() ? mNoVisibleTabsOrigString : mNoMatchedTabsOrigString; + LLStringUtil::format(text, args); - mNoVisibleTabsHelpText->setValue(text); + mNoVisibleTabsHelpText->setValue(text); } const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const { - typedef std::vector::const_iterator tabs_const_iterator; + typedef std::vector::const_iterator tabs_const_iterator; - const LLAccordionCtrlTab* result = 0; + const LLAccordionCtrlTab* result = 0; - for (tabs_const_iterator i = mAccordionTabs.begin(); i != mAccordionTabs.end(); ++i) - { - if ((*i)->isExpanded()) - { - result = *i; - break; - } - } + for (tabs_const_iterator i = mAccordionTabs.begin(); i != mAccordionTabs.end(); ++i) + { + if ((*i)->isExpanded()) + { + result = *i; + break; + } + } - return result; + return result; } S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) { - if (tab_index < 0) - { - return available_height; - } - - S32 collapsed_tabs_height = 0; - S32 num_expanded = 0; - - for (size_t n = tab_index; n < mAccordionTabs.size(); ++n) - { - if (!mAccordionTabs[n]->isExpanded()) - { - collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); - } - else - { - ++num_expanded; - } - } - - if (0 == num_expanded) - { - return available_height; - } - - S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN - expanded_tab_height /= num_expanded; - return expanded_tab_height; + if (tab_index < 0) + { + return available_height; + } + + S32 collapsed_tabs_height = 0; + S32 num_expanded = 0; + + for (size_t n = tab_index; n < mAccordionTabs.size(); ++n) + { + if (!mAccordionTabs[n]->isExpanded()) + { + collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); + } + else + { + ++num_expanded; + } + } + + if (0 == num_expanded) + { + return available_height; + } + + S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN + expanded_tab_height /= num_expanded; + return expanded_tab_height; } diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 6a1989afba..182c8cfe04 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -1,25 +1,25 @@ -/** +/** * @file LLAccordionCtrl.h * @brief Accordion Panel implementation * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,157 +41,157 @@ class LLAccordionCtrl: public LLPanel { private: - std::vector mAccordionTabs; + std::vector mAccordionTabs; - void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height); - void ctrlShiftVertical(LLView* panel,S32 delta); - - void onCollapseCtrlCloseOpen(S16 panel_num); - void shiftAccordionTabs(S16 panel_num, S32 delta); + void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height); + void ctrlShiftVertical(LLView* panel,S32 delta); + + void onCollapseCtrlCloseOpen(S16 panel_num); + void shiftAccordionTabs(S16 panel_num, S32 delta); public: - /** - * Abstract comparator for accordion tabs. - */ - class LLTabComparator - { - public: - LLTabComparator() {}; - virtual ~LLTabComparator() {}; - - /** Returns true if tab1 < tab2, false otherwise */ - virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0; - }; - - struct Params - : public LLInitParam::Block - { - Optional single_expansion, - fit_parent; /* Accordion will fit its parent size, controls that are placed into - accordion tabs are responsible for scrolling their content. - *NOTE fit_parent works best when combined with single_expansion. - Accordion view should implement getRequiredRect() and provide valid height*/ - Optional no_matched_tabs_text; - Optional no_visible_tabs_text; - - Params() - : single_expansion("single_expansion",false) - , fit_parent("fit_parent", false) - , no_matched_tabs_text("no_matched_tabs_text") - , no_visible_tabs_text("no_visible_tabs_text") - {}; - }; - - LLAccordionCtrl(const Params& params); + /** + * Abstract comparator for accordion tabs. + */ + class LLTabComparator + { + public: + LLTabComparator() {}; + virtual ~LLTabComparator() {}; + + /** Returns true if tab1 < tab2, false otherwise */ + virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0; + }; + + struct Params + : public LLInitParam::Block + { + Optional single_expansion, + fit_parent; /* Accordion will fit its parent size, controls that are placed into + accordion tabs are responsible for scrolling their content. + *NOTE fit_parent works best when combined with single_expansion. + Accordion view should implement getRequiredRect() and provide valid height*/ + Optional no_matched_tabs_text; + Optional no_visible_tabs_text; + + Params() + : single_expansion("single_expansion",false) + , fit_parent("fit_parent", false) + , no_matched_tabs_text("no_matched_tabs_text") + , no_visible_tabs_text("no_visible_tabs_text") + {}; + }; + + LLAccordionCtrl(const Params& params); LLAccordionCtrl(); virtual ~LLAccordionCtrl(); - virtual BOOL postBuild(); - - virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask); - virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks ); - virtual BOOL handleKeyHere (KEY key, MASK mask); - virtual BOOL handleDragAndDrop (S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - // + virtual BOOL postBuild(); + + virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks ); + virtual BOOL handleKeyHere (KEY key, MASK mask); + virtual BOOL handleDragAndDrop (S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + // + + // Call reshape after changing splitter's size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - // Call reshape after changing splitter's size - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + void addCollapsibleCtrl(LLView* view); + void removeCollapsibleCtrl(LLView* view); + void arrange(); - void addCollapsibleCtrl(LLView* view); - void removeCollapsibleCtrl(LLView* view); - void arrange(); + void draw(); - void draw(); - - void onScrollPosChangeCallback(S32, LLScrollbar*); - virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); + void onScrollPosChangeCallback(S32, LLScrollbar*); + virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); - void onOpen (const LLSD& key); - S32 notifyParent(const LLSD& info); + void onOpen (const LLSD& key); + S32 notifyParent(const LLSD& info); - void reset (); - void expandDefaultTab(); + void reset (); + void expandDefaultTab(); - void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } - void sort(); + void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } + void sort(); - /** - * Sets filter substring as a search_term for help text when there are no any visible tabs. - */ - void setFilterSubString(const std::string& filter_string); + /** + * Sets filter substring as a search_term for help text when there are no any visible tabs. + */ + void setFilterSubString(const std::string& filter_string); - /** - * This method returns the first expanded accordion tab. - * It is expected to be called for accordion which doesn't allow multiple - * tabs to be expanded. Use with care. - */ - const LLAccordionCtrlTab* getExpandedTab() const; + /** + * This method returns the first expanded accordion tab. + * It is expected to be called for accordion which doesn't allow multiple + * tabs to be expanded. Use with care. + */ + const LLAccordionCtrlTab* getExpandedTab() const; - LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; } + LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; } - bool getFitParent() const {return mFitParent;} + bool getFitParent() const {return mFitParent;} - void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; } + void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; } private: - void initNoTabsWidget(const LLTextBox::Params& tb_params); - void updateNoTabsHelpTextVisibility(); + void initNoTabsWidget(const LLTextBox::Params& tb_params); + void updateNoTabsHelpTextVisibility(); - void arrangeSingle(); - void arrangeMultiple(); + void arrangeSingle(); + void arrangeMultiple(); - // Calc Splitter's height that is necessary to display all child content - S32 calcRecuiredHeight(); - S32 getRecuiredHeight() const { return mInnerRect.getHeight(); } - S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0); + // Calc Splitter's height that is necessary to display all child content + S32 calcRecuiredHeight(); + S32 getRecuiredHeight() const { return mInnerRect.getHeight(); } + S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0); - void updateLayout (S32 width, S32 height); + void updateLayout (S32 width, S32 height); - void show_hide_scrollbar (S32 width, S32 height); + void show_hide_scrollbar (S32 width, S32 height); - void showScrollbar (S32 width, S32 height); - void hideScrollbar (S32 width, S32 height); + void showScrollbar (S32 width, S32 height); + void hideScrollbar (S32 width, S32 height); - BOOL autoScroll (S32 x, S32 y); + BOOL autoScroll (S32 x, S32 y); - /** - * An adaptor for LLTabComparator - */ - struct LLComparatorAdaptor - { - LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {}; + /** + * An adaptor for LLTabComparator + */ + struct LLComparatorAdaptor + { + LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {}; - bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) - { - return mComparator.compare(tab1, tab2); - } + bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) + { + return mComparator.compare(tab1, tab2); + } - const LLTabComparator& mComparator; - }; + const LLTabComparator& mComparator; + }; private: - LLRect mInnerRect; - LLScrollbar* mScrollbar; - bool mSingleExpansion; - bool mFitParent; - bool mAutoScrolling; - F32 mAutoScrollRate; - LLTextBox* mNoVisibleTabsHelpText; + LLRect mInnerRect; + LLScrollbar* mScrollbar; + bool mSingleExpansion; + bool mFitParent; + bool mAutoScrolling; + F32 mAutoScrollRate; + LLTextBox* mNoVisibleTabsHelpText; - bool mSkipScrollToChild; + bool mSkipScrollToChild; - std::string mNoMatchedTabsOrigString; - std::string mNoVisibleTabsOrigString; + std::string mNoMatchedTabsOrigString; + std::string mNoVisibleTabsOrigString; - LLAccordionCtrlTab* mSelectedTab; - const LLTabComparator* mTabComparator; + LLAccordionCtrlTab* mSelectedTab; + const LLTabComparator* mTabComparator; }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 20da568746..52893e530f 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -1,25 +1,25 @@ -/** +/** * @file LLAccordionCtrlTab.cpp * @brief Collapsible control implementation * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -51,65 +51,65 @@ static LLDefaultChildRegistry::Register t1("accordion_tab"); class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl { public: - friend class LLUICtrlFactory; + friend class LLUICtrlFactory; - struct Params : public LLInitParam::Block - { - Params(); - }; + struct Params : public LLInitParam::Block + { + Params(); + }; + + LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p); - LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p); - - virtual ~LLAccordionCtrlTabHeader(); + virtual ~LLAccordionCtrlTabHeader(); - virtual void draw(); + virtual void draw(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual BOOL postBuild(); + virtual BOOL postBuild(); - std::string getTitle(); - void setTitle(const std::string& title, const std::string& hl); + std::string getTitle(); + void setTitle(const std::string& title, const std::string& hl); - void setTitleFontStyle(std::string style); + void setTitleFontStyle(std::string style); - void setTitleColor(LLUIColor); + void setTitleColor(LLUIColor); - void setSelected(bool is_selected) { mIsSelected = is_selected; } + void setSelected(bool is_selected) { mIsSelected = is_selected; } - virtual void onMouseEnter(S32 x, S32 y, MASK mask); - virtual void onMouseLeave(S32 x, S32 y, MASK mask); - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); private: - LLTextBox* mHeaderTextbox; + LLTextBox* mHeaderTextbox; - // Overlay images (arrows) - LLPointer mImageCollapsed; - LLPointer mImageExpanded; - LLPointer mImageCollapsedPressed; - LLPointer mImageExpandedPressed; + // Overlay images (arrows) + LLPointer mImageCollapsed; + LLPointer mImageExpanded; + LLPointer mImageCollapsedPressed; + LLPointer mImageExpandedPressed; - // Background images - LLPointer mImageHeader; - LLPointer mImageHeaderOver; - LLPointer mImageHeaderPressed; - LLPointer mImageHeaderFocused; + // Background images + LLPointer mImageHeader; + LLPointer mImageHeaderOver; + LLPointer mImageHeaderPressed; + LLPointer mImageHeaderFocused; - // style saved when applying it in setTitleFontStyle - LLStyle::Params mStyleParams; + // style saved when applying it in setTitleFontStyle + LLStyle::Params mStyleParams; - LLUIColor mHeaderBGColor; + LLUIColor mHeaderBGColor; - bool mNeedsHighlight; - bool mIsSelected; + bool mNeedsHighlight; + bool mIsSelected; - LLFrameTimer mAutoOpenTimer; + LLFrameTimer mAutoOpenTimer; }; LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() @@ -117,33 +117,33 @@ LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() } LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader( - const LLAccordionCtrlTabHeader::Params& p) + const LLAccordionCtrlTabHeader::Params& p) : LLUICtrl(p) , mHeaderBGColor(p.header_bg_color()) , mNeedsHighlight(false) , mIsSelected(false), - mImageCollapsed(p.header_collapse_img), - mImageCollapsedPressed(p.header_collapse_img_pressed), - mImageExpanded(p.header_expand_img), - mImageExpandedPressed(p.header_expand_img_pressed), - mImageHeader(p.header_image), - mImageHeaderOver(p.header_image_over), - mImageHeaderPressed(p.header_image_pressed), - mImageHeaderFocused(p.header_image_focused) + mImageCollapsed(p.header_collapse_img), + mImageCollapsedPressed(p.header_collapse_img_pressed), + mImageExpanded(p.header_expand_img), + mImageExpandedPressed(p.header_expand_img_pressed), + mImageHeader(p.header_image), + mImageHeaderOver(p.header_image_over), + mImageHeaderPressed(p.header_image_pressed), + mImageHeaderFocused(p.header_image_focused) { - LLTextBox::Params textboxParams; - textboxParams.name(DD_TEXTBOX_NAME); - textboxParams.initial_value(p.title()); - textboxParams.text_color(p.header_text_color()); - textboxParams.follows.flags(FOLLOWS_NONE); - textboxParams.font( p.font() ); - textboxParams.font_shadow(LLFontGL::NO_SHADOW); - textboxParams.use_ellipses = true; - textboxParams.bg_visible = false; - textboxParams.mouse_opaque = false; - textboxParams.parse_urls = false; - mHeaderTextbox = LLUICtrlFactory::create(textboxParams); - addChild(mHeaderTextbox); + LLTextBox::Params textboxParams; + textboxParams.name(DD_TEXTBOX_NAME); + textboxParams.initial_value(p.title()); + textboxParams.text_color(p.header_text_color()); + textboxParams.follows.flags(FOLLOWS_NONE); + textboxParams.font( p.font() ); + textboxParams.font_shadow(LLFontGL::NO_SHADOW); + textboxParams.use_ellipses = true; + textboxParams.bg_visible = false; + textboxParams.mouse_opaque = false; + textboxParams.parse_urls = false; + mHeaderTextbox = LLUICtrlFactory::create(textboxParams); + addChild(mHeaderTextbox); } LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader() @@ -152,235 +152,235 @@ LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader() BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() { - return TRUE; + return TRUE; } std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle() { - if (mHeaderTextbox) - { - return mHeaderTextbox->getText(); - } + if (mHeaderTextbox) + { + return mHeaderTextbox->getText(); + } - return LLStringUtil::null; + return LLStringUtil::null; } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl) { - if (mHeaderTextbox) - { - LLTextUtil::textboxSetHighlightedVal( - mHeaderTextbox, - mStyleParams, - title, - hl); - } + if (mHeaderTextbox) + { + LLTextUtil::textboxSetHighlightedVal( + mHeaderTextbox, + mStyleParams, + title, + hl); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string style) { - if (mHeaderTextbox) - { - std::string text = mHeaderTextbox->getText(); - mStyleParams.font(mHeaderTextbox->getFont()); - mStyleParams.font.style(style); - mHeaderTextbox->setText(text, mStyleParams); - } + if (mHeaderTextbox) + { + std::string text = mHeaderTextbox->getText(); + mStyleParams.font(mHeaderTextbox->getFont()); + mStyleParams.font.style(style); + mHeaderTextbox->setText(text, mStyleParams); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleColor(LLUIColor color) { - if (mHeaderTextbox) - { - mHeaderTextbox->setColor(color); - } + if (mHeaderTextbox) + { + mHeaderTextbox->setColor(color); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() { - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); - - F32 alpha = getCurrentTransparency(); - gl_rect_2d(0, 0, width - 1, height - 1, mHeaderBGColor.get() % alpha, TRUE); - - LLAccordionCtrlTab* parent = dynamic_cast(getParent()); - bool collapsible = parent && parent->getCollapsible(); - bool expanded = parent && parent->getDisplayChildren(); - - // Handle overlay images, if needed - // Only show green "focus" background image if the accordion is open, - // because the user's mental model of focus is that it goes away after - // the accordion is closed. - if (getParent()->hasFocus() || mIsSelected - /*&& !(collapsible && !expanded)*/ // WHY?? - ) - { - mImageHeaderFocused->draw(0, 0, width, height); - } - else - { - mImageHeader->draw(0, 0, width, height); - } - - if (mNeedsHighlight) - { - mImageHeaderOver->draw(0, 0, width, height); - } - - if (collapsible) - { - LLPointer overlay_image; - if (expanded) - { - overlay_image = mImageExpanded; - } - else - { - overlay_image = mImageCollapsed; - } - overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, (height - overlay_image->getHeight()) / 2); - } - - LLUICtrl::draw(); + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + F32 alpha = getCurrentTransparency(); + gl_rect_2d(0, 0, width - 1, height - 1, mHeaderBGColor.get() % alpha, TRUE); + + LLAccordionCtrlTab* parent = dynamic_cast(getParent()); + bool collapsible = parent && parent->getCollapsible(); + bool expanded = parent && parent->getDisplayChildren(); + + // Handle overlay images, if needed + // Only show green "focus" background image if the accordion is open, + // because the user's mental model of focus is that it goes away after + // the accordion is closed. + if (getParent()->hasFocus() || mIsSelected + /*&& !(collapsible && !expanded)*/ // WHY?? + ) + { + mImageHeaderFocused->draw(0, 0, width, height); + } + else + { + mImageHeader->draw(0, 0, width, height); + } + + if (mNeedsHighlight) + { + mImageHeaderOver->draw(0, 0, width, height); + } + + if (collapsible) + { + LLPointer overlay_image; + if (expanded) + { + overlay_image = mImageExpanded; + } + else + { + overlay_image = mImageCollapsed; + } + overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, (height - overlay_image->getHeight()) / 2); + } + + LLUICtrl::draw(); } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - S32 header_height = mHeaderTextbox->getTextPixelHeight(); - - LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET, (height + header_height) / 2, width, (height - header_height) / 2); - mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); - mHeaderTextbox->setRect(textboxRect); - - if (mHeaderTextbox->getTextPixelWidth() > mHeaderTextbox->getRect().getWidth()) - { - setToolTip(mHeaderTextbox->getText()); - } - else - { - setToolTip(LLStringUtil::null); - } + S32 header_height = mHeaderTextbox->getTextPixelHeight(); + + LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET, (height + header_height) / 2, width, (height - header_height) / 2); + mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); + mHeaderTextbox->setRect(textboxRect); + + if (mHeaderTextbox->getTextPixelWidth() > mHeaderTextbox->getRect().getWidth()) + { + setToolTip(mHeaderTextbox->getText()); + } + else + { + setToolTip(LLStringUtil::null); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask) { - LLUICtrl::onMouseEnter(x, y, mask); - mNeedsHighlight = true; + LLUICtrl::onMouseEnter(x, y, mask); + mNeedsHighlight = true; } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask) { - LLUICtrl::onMouseLeave(x, y, mask); - mNeedsHighlight = false; - mAutoOpenTimer.stop(); + LLUICtrl::onMouseLeave(x, y, mask); + mNeedsHighlight = false; + mAutoOpenTimer.stop(); } BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - if ((key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) - { - return getParent()->handleKey(key, mask, called_from_parent); - } + if ((key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) + { + return getParent()->handleKey(key, mask, called_from_parent); + } - return LLUICtrl::handleKey(key, mask, called_from_parent); + return LLUICtrl::handleKey(key, mask, called_from_parent); } BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - LLAccordionCtrlTab* parent = dynamic_cast(getParent()); - - if (parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose()) - { - if (mAutoOpenTimer.getStarted()) - { - if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME) - { - parent->changeOpenClose(false); - mAutoOpenTimer.stop(); - return TRUE; - } - } - else - { - mAutoOpenTimer.start(); - } - } - - return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg); + LLAccordionCtrlTab* parent = dynamic_cast(getParent()); + + if (parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose()) + { + if (mAutoOpenTimer.getStarted()) + { + if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME) + { + parent->changeOpenClose(false); + mAutoOpenTimer.stop(); + return TRUE; + } + } + else + { + mAutoOpenTimer.start(); + } + } + + return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg); } LLAccordionCtrlTab::Params::Params() - : title("title") - ,display_children("expanded", true) - ,header_height("header_height", HEADER_HEIGHT), - min_width("min_width", 0), - min_height("min_height", 0) - ,collapsible("collapsible", true) - ,header_bg_color("header_bg_color") - ,dropdown_bg_color("dropdown_bg_color") - ,header_visible("header_visible",true) - ,padding_left("padding_left",2) - ,padding_right("padding_right",2) - ,padding_top("padding_top",2) - ,padding_bottom("padding_bottom",2) - ,header_expand_img("header_expand_img") - ,header_expand_img_pressed("header_expand_img_pressed") - ,header_collapse_img("header_collapse_img") - ,header_collapse_img_pressed("header_collapse_img_pressed") - ,header_image("header_image") - ,header_image_over("header_image_over") - ,header_image_pressed("header_image_pressed") - ,header_image_focused("header_image_focused") - ,header_text_color("header_text_color") - ,fit_panel("fit_panel",true) - ,selection_enabled("selection_enabled", false) + : title("title") + ,display_children("expanded", true) + ,header_height("header_height", HEADER_HEIGHT), + min_width("min_width", 0), + min_height("min_height", 0) + ,collapsible("collapsible", true) + ,header_bg_color("header_bg_color") + ,dropdown_bg_color("dropdown_bg_color") + ,header_visible("header_visible",true) + ,padding_left("padding_left",2) + ,padding_right("padding_right",2) + ,padding_top("padding_top",2) + ,padding_bottom("padding_bottom",2) + ,header_expand_img("header_expand_img") + ,header_expand_img_pressed("header_expand_img_pressed") + ,header_collapse_img("header_collapse_img") + ,header_collapse_img_pressed("header_collapse_img_pressed") + ,header_image("header_image") + ,header_image_over("header_image_over") + ,header_image_pressed("header_image_pressed") + ,header_image_focused("header_image_focused") + ,header_text_color("header_text_color") + ,fit_panel("fit_panel",true) + ,selection_enabled("selection_enabled", false) { - changeDefault(mouse_opaque, false); + changeDefault(mouse_opaque, false); } LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) - : LLUICtrl(p) - ,mDisplayChildren(p.display_children) - ,mCollapsible(p.collapsible) - ,mExpandedHeight(0) - ,mDropdownBGColor(p.dropdown_bg_color()) - ,mHeaderVisible(p.header_visible) - ,mPaddingLeft(p.padding_left) - ,mPaddingRight(p.padding_right) - ,mPaddingTop(p.padding_top) - ,mPaddingBottom(p.padding_bottom) - ,mCanOpenClose(true) - ,mFitPanel(p.fit_panel) - ,mSelectionEnabled(p.selection_enabled) - ,mContainerPanel(NULL) - ,mScrollbar(NULL) + : LLUICtrl(p) + ,mDisplayChildren(p.display_children) + ,mCollapsible(p.collapsible) + ,mExpandedHeight(0) + ,mDropdownBGColor(p.dropdown_bg_color()) + ,mHeaderVisible(p.header_visible) + ,mPaddingLeft(p.padding_left) + ,mPaddingRight(p.padding_right) + ,mPaddingTop(p.padding_top) + ,mPaddingBottom(p.padding_bottom) + ,mCanOpenClose(true) + ,mFitPanel(p.fit_panel) + ,mSelectionEnabled(p.selection_enabled) + ,mContainerPanel(NULL) + ,mScrollbar(NULL) { - mStoredOpenCloseState = false; - mWasStateStored = false; - mSkipChangesOnNotifyParent = false; - - mDropdownBGColor = LLColor4::white; - LLAccordionCtrlTabHeader::Params headerParams; - headerParams.name(DD_HEADER_NAME); - headerParams.title(p.title); - mHeader = LLUICtrlFactory::create(headerParams); - addChild(mHeader, 1); - - LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this)); - - if (!p.selection_enabled) - { - LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this)); - } - - reshape(100, 200,FALSE); + mStoredOpenCloseState = false; + mWasStateStored = false; + mSkipChangesOnNotifyParent = false; + + mDropdownBGColor = LLColor4::white; + LLAccordionCtrlTabHeader::Params headerParams; + headerParams.name(DD_HEADER_NAME); + headerParams.title(p.title); + mHeader = LLUICtrlFactory::create(headerParams); + addChild(mHeader, 1); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this)); + + if (!p.selection_enabled) + { + LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this)); + } + + reshape(100, 200,FALSE); } LLAccordionCtrlTab::~LLAccordionCtrlTab() @@ -389,68 +389,68 @@ LLAccordionCtrlTab::~LLAccordionCtrlTab() void LLAccordionCtrlTab::setDisplayChildren(bool display) { - mDisplayChildren = display; - LLRect rect = getRect(); - - rect.mBottom = rect.mTop - (getDisplayChildren() ? mExpandedHeight : HEADER_HEIGHT); - setRect(rect); - - if (mContainerPanel) - { - mContainerPanel->setVisible(getDisplayChildren()); - } - - if (mDisplayChildren) - { - adjustContainerPanel(); - } - else - { - if (mScrollbar) - mScrollbar->setVisible(FALSE); - } + mDisplayChildren = display; + LLRect rect = getRect(); + + rect.mBottom = rect.mTop - (getDisplayChildren() ? mExpandedHeight : HEADER_HEIGHT); + setRect(rect); + + if (mContainerPanel) + { + mContainerPanel->setVisible(getDisplayChildren()); + } + + if (mDisplayChildren) + { + adjustContainerPanel(); + } + else + { + if (mScrollbar) + mScrollbar->setVisible(FALSE); + } } void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - LLRect headerRect; + LLRect headerRect; - headerRect.setLeftTopAndSize(0, height, width, HEADER_HEIGHT); - mHeader->setRect(headerRect); - mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + headerRect.setLeftTopAndSize(0, height, width, HEADER_HEIGHT); + mHeader->setRect(headerRect); + mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); - if (!mDisplayChildren) - return; + if (!mDisplayChildren) + return; - LLRect childRect; + LLRect childRect; - childRect.setLeftTopAndSize( - getPaddingLeft(), - height - getHeaderHeight() - getPaddingTop(), - width - getPaddingLeft() - getPaddingRight(), - height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + childRect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); - adjustContainerPanel(childRect); + adjustContainerPanel(childRect); } void LLAccordionCtrlTab::changeOpenClose(bool is_open) { - if (is_open) - mExpandedHeight = getRect().getHeight(); - - setDisplayChildren(!is_open); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); - if (mCommitSignal) - { - (*mCommitSignal)(this, getDisplayChildren()); - } + if (is_open) + mExpandedHeight = getRect().getHeight(); + + setDisplayChildren(!is_open); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + if (mCommitSignal) + { + (*mCommitSignal)(this, getDisplayChildren()); + } } void LLAccordionCtrlTab::onVisibilityChange(BOOL new_visibility) { - LLUICtrl::onVisibilityChange(new_visibility); + LLUICtrl::onVisibilityChange(new_visibility); - notifyParent(LLSD().with("child_visibility_change", new_visibility)); + notifyParent(LLSD().with("child_visibility_change", new_visibility)); } // virtual @@ -473,7 +473,7 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) S32 scroll_pos = llclamp(mScrollbar->getDocPos(), bottom, // min vertical scroll - top); // max vertical scroll + top); // max vertical scroll mScrollbar->setDocPos(scroll_pos); } @@ -484,643 +484,643 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) { - if (mCollapsible && mHeaderVisible && mCanOpenClose) - { - if (y >= (getRect().getHeight() - HEADER_HEIGHT)) - { - mHeader->setFocus(true); - changeOpenClose(getDisplayChildren()); - - // Reset stored state - mWasStateStored = false; - return TRUE; - } - } - return LLUICtrl::handleMouseDown(x,y,mask); + if (mCollapsible && mHeaderVisible && mCanOpenClose) + { + if (y >= (getRect().getHeight() - HEADER_HEIGHT)) + { + mHeader->setFocus(true); + changeOpenClose(getDisplayChildren()); + + // Reset stored state + mWasStateStored = false; + return TRUE; + } + } + return LLUICtrl::handleMouseDown(x,y,mask); } BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask) { - return LLUICtrl::handleMouseUp(x,y,mask); + return LLUICtrl::handleMouseUp(x,y,mask); } boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb) { - return setCommitCallback(cb); + return setCommitCallback(cb); } bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) { - if (DD_HEADER_NAME != child->getName()) - { - reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); - mExpandedHeight = getRect().getHeight(); - } - - bool res = LLUICtrl::addChild(child, tab_group); - - if (DD_HEADER_NAME != child->getName()) - { - if (!mCollapsible) - setDisplayChildren(true); - else - setDisplayChildren(getDisplayChildren()); - } - - if (!mContainerPanel) - mContainerPanel = findContainerView(); - - return res; + if (DD_HEADER_NAME != child->getName()) + { + reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); + mExpandedHeight = getRect().getHeight(); + } + + bool res = LLUICtrl::addChild(child, tab_group); + + if (DD_HEADER_NAME != child->getName()) + { + if (!mCollapsible) + setDisplayChildren(true); + else + setDisplayChildren(getDisplayChildren()); + } + + if (!mContainerPanel) + mContainerPanel = findContainerView(); + + return res; } void LLAccordionCtrlTab::setAccordionView(LLView* panel) { - addChild(panel, 0); + addChild(panel, 0); } std::string LLAccordionCtrlTab::getTitle() const { - if (mHeader) - { - return mHeader->getTitle(); - } + if (mHeader) + { + return mHeader->getTitle(); + } - return LLStringUtil::null; + return LLStringUtil::null; } void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) { - if (mHeader) - { - mHeader->setTitle(title, hl); - } + if (mHeader) + { + mHeader->setTitle(title, hl); + } } void LLAccordionCtrlTab::setTitleFontStyle(std::string style) { - if (mHeader) - { - mHeader->setTitleFontStyle(style); - } + if (mHeader) + { + mHeader->setTitleFontStyle(style); + } } void LLAccordionCtrlTab::setTitleColor(LLUIColor color) { - if (mHeader) - { - mHeader->setTitleColor(color); - } + if (mHeader) + { + mHeader->setTitleColor(color); + } } boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) { - if (mHeader) - { - return mHeader->setFocusReceivedCallback(cb); - } + if (mHeader) + { + return mHeader->setFocusReceivedCallback(cb); + } - return boost::signals2::connection(); + return boost::signals2::connection(); } boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb) { - if (mHeader) - { - return mHeader->setFocusLostCallback(cb); - } + if (mHeader) + { + return mHeader->setFocusLostCallback(cb); + } - return boost::signals2::connection(); + return boost::signals2::connection(); } void LLAccordionCtrlTab::setSelected(bool is_selected) { - if (mHeader) - { - mHeader->setSelected(is_selected); - } + if (mHeader) + { + mHeader->setSelected(is_selected); + } } -LLView* LLAccordionCtrlTab::findContainerView() +LLView* LLAccordionCtrlTab::findContainerView() { - child_list_const_iter_t it = getChildList()->begin(), it_end = getChildList()->end(); - while (it != it_end) - { - LLView* child = *(it++); - if (DD_HEADER_NAME != child->getName() && child->getVisible()) - return child; - } - - return NULL; + child_list_const_iter_t it = getChildList()->begin(), it_end = getChildList()->end(); + while (it != it_end) + { + LLView* child = *(it++); + if (DD_HEADER_NAME != child->getName() && child->getVisible()) + return child; + } + + return NULL; } void LLAccordionCtrlTab::selectOnFocusReceived() { - if (getParent()) // A parent may not be set if tabs are added dynamically. - { - getParent()->notifyParent(LLSD().with("action", "select_current")); - } + if (getParent()) // A parent may not be set if tabs are added dynamically. + { + getParent()->notifyParent(LLSD().with("action", "select_current")); + } } void LLAccordionCtrlTab::deselectOnFocusLost() { - if (getParent()) // A parent may not be set if tabs are added dynamically. - { - getParent()->notifyParent(LLSD().with("action", "deselect_current")); - } + if (getParent()) // A parent may not be set if tabs are added dynamically. + { + getParent()->notifyParent(LLSD().with("action", "deselect_current")); + } } S32 LLAccordionCtrlTab::getHeaderHeight() { - return mHeaderVisible ? HEADER_HEIGHT : 0; + return mHeaderVisible ? HEADER_HEIGHT : 0; } void LLAccordionCtrlTab::setHeaderVisible(bool value) { - if (mHeaderVisible == value) - return; + if (mHeaderVisible == value) + return; - mHeaderVisible = value; + mHeaderVisible = value; - if (mHeader) - { - mHeader->setVisible(value ? TRUE : FALSE); - } + if (mHeader) + { + mHeader->setVisible(value ? TRUE : FALSE); + } - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); }; //virtual BOOL LLAccordionCtrlTab::postBuild() { - if (mHeader) - { - mHeader->setVisible(mHeaderVisible); - } - - static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); - - LLRect scroll_rect; - scroll_rect.setOriginAndSize( - getRect().getWidth() - scrollbar_size, - 1, - scrollbar_size, - getRect().getHeight() - 1); - - mContainerPanel = findContainerView(); - - if (!mFitPanel) - { - LLScrollbar::Params sbparams; - sbparams.name("scrollable vertical"); - sbparams.rect(scroll_rect); - sbparams.orientation(LLScrollbar::VERTICAL); - sbparams.doc_size(getRect().getHeight()); - sbparams.doc_pos(0); - sbparams.page_size(getRect().getHeight()); - sbparams.step_size(VERTICAL_MULTIPLE); - sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - sbparams.change_callback(boost::bind(&LLAccordionCtrlTab::onScrollPosChangeCallback, this, _1, _2)); - - mScrollbar = LLUICtrlFactory::create(sbparams); - LLView::addChild(mScrollbar); - mScrollbar->setFollowsRight(); - mScrollbar->setFollowsTop(); - mScrollbar->setFollowsBottom(); - - mScrollbar->setVisible(false); - } - - if (mContainerPanel) - { - mContainerPanel->setVisible(mDisplayChildren); - } - - return LLUICtrl::postBuild(); + if (mHeader) + { + mHeader->setVisible(mHeaderVisible); + } + + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + mContainerPanel = findContainerView(); + + if (!mFitPanel) + { + LLScrollbar::Params sbparams; + sbparams.name("scrollable vertical"); + sbparams.rect(scroll_rect); + sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(getRect().getHeight()); + sbparams.doc_pos(0); + sbparams.page_size(getRect().getHeight()); + sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.change_callback(boost::bind(&LLAccordionCtrlTab::onScrollPosChangeCallback, this, _1, _2)); + + mScrollbar = LLUICtrlFactory::create(sbparams); + LLView::addChild(mScrollbar); + mScrollbar->setFollowsRight(); + mScrollbar->setFollowsTop(); + mScrollbar->setFollowsBottom(); + + mScrollbar->setVisible(false); + } + + if (mContainerPanel) + { + mContainerPanel->setVisible(mDisplayChildren); + } + + return LLUICtrl::postBuild(); } -bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) +bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) { - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "store_state") - { - storeOpenCloseState(); - return true; - } - - if (str_action == "restore_state") - { - restoreOpenCloseState(); - return true; - } - } - - return LLUICtrl::notifyChildren(info); + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "store_state") + { + storeOpenCloseState(); + return true; + } + + if (str_action == "restore_state") + { + restoreOpenCloseState(); + return true; + } + } + + return LLUICtrl::notifyChildren(info); } -S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) +S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) { - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "size_changes") - { - S32 height = info["height"]; - height = llmax(height, 10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); - - mExpandedHeight = height; - - if (isExpanded() && !mSkipChangesOnNotifyParent) - { - LLRect panel_rect = getRect(); - panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); - reshape(getRect().getWidth(),height); - setRect(panel_rect); - } - - // LLAccordionCtrl should rearrange accordion tab if one of accordions changed its size - if (getParent()) // A parent may not be set if tabs are added dynamically. - getParent()->notifyParent(info); - return 1; - } - - if (str_action == "select_prev") - { - showAndFocusHeader(); - return 1; - } - } - else if (info.has("scrollToShowRect")) - { - LLAccordionCtrl* parent = dynamic_cast(getParent()); - if (parent && parent->getFitParent()) - { - // EXT-8285 ('No attachments worn' text appears at the bottom of blank 'Attachments' accordion) - // The problem was in passing message "scrollToShowRect" IN LLAccordionCtrlTab::notifyParent - // FROM child LLScrollContainer TO parent LLAccordionCtrl with "it_parent" set to true. - - // It is wrong notification for parent accordion which leads to recursive call of adjustContainerPanel - // As the result of recursive call of adjustContainerPanel we got LLAccordionCtrlTab - // that reshaped and re-sized with different rectangles. - - // LLAccordionCtrl has own scrollContainer and LLAccordionCtrlTab has own scrollContainer - // both should handle own scroll container's event. - // So, if parent accordion "fit_parent" accordion tab should handle its scroll container events itself. - - return 1; - } - - if (!getDisplayChildren()) - { - // Don't pass scrolling event further if our contents are invisible (STORM-298). - return 1; - } - } - - return LLUICtrl::notifyParent(info); + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "size_changes") + { + S32 height = info["height"]; + height = llmax(height, 10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); + + mExpandedHeight = height; + + if (isExpanded() && !mSkipChangesOnNotifyParent) + { + LLRect panel_rect = getRect(); + panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); + reshape(getRect().getWidth(),height); + setRect(panel_rect); + } + + // LLAccordionCtrl should rearrange accordion tab if one of accordions changed its size + if (getParent()) // A parent may not be set if tabs are added dynamically. + getParent()->notifyParent(info); + return 1; + } + + if (str_action == "select_prev") + { + showAndFocusHeader(); + return 1; + } + } + else if (info.has("scrollToShowRect")) + { + LLAccordionCtrl* parent = dynamic_cast(getParent()); + if (parent && parent->getFitParent()) + { + // EXT-8285 ('No attachments worn' text appears at the bottom of blank 'Attachments' accordion) + // The problem was in passing message "scrollToShowRect" IN LLAccordionCtrlTab::notifyParent + // FROM child LLScrollContainer TO parent LLAccordionCtrl with "it_parent" set to true. + + // It is wrong notification for parent accordion which leads to recursive call of adjustContainerPanel + // As the result of recursive call of adjustContainerPanel we got LLAccordionCtrlTab + // that reshaped and re-sized with different rectangles. + + // LLAccordionCtrl has own scrollContainer and LLAccordionCtrlTab has own scrollContainer + // both should handle own scroll container's event. + // So, if parent accordion "fit_parent" accordion tab should handle its scroll container events itself. + + return 1; + } + + if (!getDisplayChildren()) + { + // Don't pass scrolling event further if our contents are invisible (STORM-298). + return 1; + } + } + + return LLUICtrl::notifyParent(info); } S32 LLAccordionCtrlTab::notify(const LLSD& info) { - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "select_first") - { - showAndFocusHeader(); - return 1; - } - - if (str_action == "select_last") - { - if (!getDisplayChildren()) - { - showAndFocusHeader(); - } - else - { - LLView* view = getAccordionView(); - if (view) - { - view->notify(LLSD().with("action", "select_last")); - } - } - } - } - - return 0; + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "select_first") + { + showAndFocusHeader(); + return 1; + } + + if (str_action == "select_last") + { + if (!getDisplayChildren()) + { + showAndFocusHeader(); + } + else + { + LLView* view = getAccordionView(); + if (view) + { + view->notify(LLSD().with("action", "select_last")); + } + } + } + } + + return 0; } BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - if (!mHeader->hasFocus()) - return LLUICtrl::handleKey(key, mask, called_from_parent); - - if ((key == KEY_RETURN) && mask == MASK_NONE) - { - changeOpenClose(getDisplayChildren()); - return TRUE; - } - - if ((key == KEY_ADD || key == KEY_RIGHT) && mask == MASK_NONE) - { - if (!getDisplayChildren()) - { - changeOpenClose(getDisplayChildren()); - return TRUE; - } - } - - if ((key == KEY_SUBTRACT || key == KEY_LEFT) && mask == MASK_NONE) - { - if (getDisplayChildren()) - { - changeOpenClose(getDisplayChildren()); - return TRUE; - } - } - - if (key == KEY_DOWN && mask == MASK_NONE) - { - // if collapsed go to the next accordion - if (!getDisplayChildren()) - { - // we're processing notifyParent so let call parent directly - getParent()->notifyParent(LLSD().with("action", "select_next")); - } - else - { - getAccordionView()->notify(LLSD().with("action", "select_first")); - } - return TRUE; - } - - if (key == KEY_UP && mask == MASK_NONE) - { - // go to the previous accordion - - // we're processing notifyParent so let call parent directly - getParent()->notifyParent(LLSD().with("action", "select_prev")); - return TRUE; - } - - return LLUICtrl::handleKey(key, mask, called_from_parent); + if (!mHeader->hasFocus()) + return LLUICtrl::handleKey(key, mask, called_from_parent); + + if ((key == KEY_RETURN) && mask == MASK_NONE) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + + if ((key == KEY_ADD || key == KEY_RIGHT) && mask == MASK_NONE) + { + if (!getDisplayChildren()) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + + if ((key == KEY_SUBTRACT || key == KEY_LEFT) && mask == MASK_NONE) + { + if (getDisplayChildren()) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + + if (key == KEY_DOWN && mask == MASK_NONE) + { + // if collapsed go to the next accordion + if (!getDisplayChildren()) + { + // we're processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action", "select_next")); + } + else + { + getAccordionView()->notify(LLSD().with("action", "select_first")); + } + return TRUE; + } + + if (key == KEY_UP && mask == MASK_NONE) + { + // go to the previous accordion + + // we're processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action", "select_prev")); + return TRUE; + } + + return LLUICtrl::handleKey(key, mask, called_from_parent); } void LLAccordionCtrlTab::showAndFocusHeader() { - if (!mHeader) - { - return; - } - - mHeader->setFocus(true); - mHeader->setSelected(mSelectionEnabled); - - LLRect screen_rc; - LLRect selected_rc = mHeader->getRect(); - localRectToScreen(selected_rc, &screen_rc); - - // This call to notifyParent() is intended to deliver "scrollToShowRect" command - // to the parent LLAccordionCtrl so by calling it from the direct parent of this - // accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain - // is shortened and messages from inside the collapsed tabs are avoided. - // See STORM-536. - getParent()->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); + if (!mHeader) + { + return; + } + + mHeader->setFocus(true); + mHeader->setSelected(mSelectionEnabled); + + LLRect screen_rc; + LLRect selected_rc = mHeader->getRect(); + localRectToScreen(selected_rc, &screen_rc); + + // This call to notifyParent() is intended to deliver "scrollToShowRect" command + // to the parent LLAccordionCtrl so by calling it from the direct parent of this + // accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain + // is shortened and messages from inside the collapsed tabs are avoided. + // See STORM-536. + getParent()->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); } void LLAccordionCtrlTab::storeOpenCloseState() { - if (mWasStateStored) - return; - mStoredOpenCloseState = getDisplayChildren(); - mWasStateStored = true; + if (mWasStateStored) + return; + mStoredOpenCloseState = getDisplayChildren(); + mWasStateStored = true; } void LLAccordionCtrlTab::restoreOpenCloseState() { - if (!mWasStateStored) - return; - if (getDisplayChildren() != mStoredOpenCloseState) - { - changeOpenClose(getDisplayChildren()); - } - mWasStateStored = false; + if (!mWasStateStored) + return; + if (getDisplayChildren() != mStoredOpenCloseState) + { + changeOpenClose(getDisplayChildren()); + } + mWasStateStored = false; } void LLAccordionCtrlTab::adjustContainerPanel() { - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); - LLRect child_rect; - child_rect.setLeftTopAndSize( - getPaddingLeft(), - height - getHeaderHeight() - getPaddingTop(), - width - getPaddingLeft() - getPaddingRight(), - height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + LLRect child_rect; + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); - adjustContainerPanel(child_rect); + adjustContainerPanel(child_rect); } void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect) { - if (!mContainerPanel) - return; - - if (!mFitPanel) - { - show_hide_scrollbar(child_rect); - updateLayout(child_rect); - } - else - { - mContainerPanel->reshape(child_rect.getWidth(), child_rect.getHeight()); - mContainerPanel->setRect(child_rect); - } + if (!mContainerPanel) + return; + + if (!mFitPanel) + { + show_hide_scrollbar(child_rect); + updateLayout(child_rect); + } + else + { + mContainerPanel->reshape(child_rect.getWidth(), child_rect.getHeight()); + mContainerPanel->setRect(child_rect); + } } S32 LLAccordionCtrlTab::getChildViewHeight() { - if (!mContainerPanel) - return 0; - return mContainerPanel->getRect().getHeight(); + if (!mContainerPanel) + return 0; + return mContainerPanel->getRect().getHeight(); } void LLAccordionCtrlTab::show_hide_scrollbar(const LLRect& child_rect) { - if (getChildViewHeight() > child_rect.getHeight()) - showScrollbar(child_rect); - else - hideScrollbar(child_rect); + if (getChildViewHeight() > child_rect.getHeight()) + showScrollbar(child_rect); + else + hideScrollbar(child_rect); } void LLAccordionCtrlTab::showScrollbar(const LLRect& child_rect) { - if (!mContainerPanel || !mScrollbar) - return; - bool was_visible = mScrollbar->getVisible(); - mScrollbar->setVisible(true); - - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - - ctrlSetLeftTopAndSize(mScrollbar, - child_rect.getWidth() - scrollbar_size, - child_rect.getHeight() - PARENT_BORDER_MARGIN, - scrollbar_size, - child_rect.getHeight() - PARENT_BORDER_MARGIN * 2); - - LLRect orig_rect = mContainerPanel->getRect(); - - mScrollbar->setPageSize(child_rect.getHeight()); - mScrollbar->setDocParams(orig_rect.getHeight(), mScrollbar->getDocPos()); - - if (was_visible) - { - S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1); - mScrollbar->setDocPos(scroll_pos); - } - else // Shrink child panel - { - updateLayout(child_rect); - } + if (!mContainerPanel || !mScrollbar) + return; + bool was_visible = mScrollbar->getVisible(); + mScrollbar->setVisible(true); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + ctrlSetLeftTopAndSize(mScrollbar, + child_rect.getWidth() - scrollbar_size, + child_rect.getHeight() - PARENT_BORDER_MARGIN, + scrollbar_size, + child_rect.getHeight() - PARENT_BORDER_MARGIN * 2); + + LLRect orig_rect = mContainerPanel->getRect(); + + mScrollbar->setPageSize(child_rect.getHeight()); + mScrollbar->setDocParams(orig_rect.getHeight(), mScrollbar->getDocPos()); + + if (was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1); + mScrollbar->setDocPos(scroll_pos); + } + else // Shrink child panel + { + updateLayout(child_rect); + } } void LLAccordionCtrlTab::hideScrollbar(const LLRect& child_rect) { - if (!mContainerPanel || !mScrollbar) - return; + if (!mContainerPanel || !mScrollbar) + return; - if (mScrollbar->getVisible() == FALSE) - return; + if (mScrollbar->getVisible() == FALSE) + return; - mScrollbar->setVisible(FALSE); - mScrollbar->setDocPos(0); + mScrollbar->setVisible(FALSE); + mScrollbar->setDocPos(0); - //shrink child panel - updateLayout(child_rect); + //shrink child panel + updateLayout(child_rect); } void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*) { - LLRect child_rect; + LLRect child_rect; - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); - child_rect.setLeftTopAndSize( - getPaddingLeft(), - height - getHeaderHeight() - getPaddingTop(), - width - getPaddingLeft() - getPaddingRight(), - height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); - updateLayout(child_rect); + updateLayout(child_rect); } void LLAccordionCtrlTab::drawChild(const LLRect& root_rect, LLView* child) { - if (child && child->getVisible() && child->getRect().isValid()) - { - LLRect screen_rect; - localRectToScreen(child->getRect(), &screen_rect); - - if (root_rect.overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect)) - { - gGL.matrixMode(LLRender::MM_MODELVIEW); - LLUI::pushMatrix(); - { - LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom); - child->draw(); - } - LLUI::popMatrix(); - } - } + if (child && child->getVisible() && child->getRect().isValid()) + { + LLRect screen_rect; + localRectToScreen(child->getRect(), &screen_rect); + + if (root_rect.overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect)) + { + gGL.matrixMode(LLRender::MM_MODELVIEW); + LLUI::pushMatrix(); + { + LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom); + child->draw(); + } + LLUI::popMatrix(); + } + } } void LLAccordionCtrlTab::draw() { - if (mFitPanel) - { - LLUICtrl::draw(); - } - else - { - LLRect root_rect(getRootView()->getRect()); - drawChild(root_rect, mHeader); - drawChild(root_rect, mScrollbar); - - LLRect child_rect; - - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); - - child_rect.setLeftTopAndSize( - getPaddingLeft(), - height - getHeaderHeight() - getPaddingTop(), - width - getPaddingLeft() - getPaddingRight(), - height - getHeaderHeight() - getPaddingTop() - getPaddingBottom()); - - LLLocalClipRect clip(child_rect); - drawChild(root_rect,mContainerPanel); - } + if (mFitPanel) + { + LLUICtrl::draw(); + } + else + { + LLRect root_rect(getRootView()->getRect()); + drawChild(root_rect, mHeader); + drawChild(root_rect, mScrollbar); + + LLRect child_rect; + + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + child_rect.setLeftTopAndSize( + getPaddingLeft(), + height - getHeaderHeight() - getPaddingTop(), + width - getPaddingLeft() - getPaddingRight(), + height - getHeaderHeight() - getPaddingTop() - getPaddingBottom()); + + LLLocalClipRect clip(child_rect); + drawChild(root_rect,mContainerPanel); + } } void LLAccordionCtrlTab::updateLayout(const LLRect& child_rect) { - LLView* child = getAccordionView(); - if (!mContainerPanel) - return; - - S32 panel_top = child_rect.getHeight(); - S32 panel_width = child_rect.getWidth(); - - static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); - if (mScrollbar && mScrollbar->getVisible()) - { - panel_top += mScrollbar->getDocPos(); - panel_width -= scrollbar_size; - } - - // Set sizes for first panels and dragbars - LLRect panel_rect = child->getRect(); - ctrlSetLeftTopAndSize(mContainerPanel, child_rect.mLeft, panel_top, panel_width, panel_rect.getHeight()); + LLView* child = getAccordionView(); + if (!mContainerPanel) + return; + + S32 panel_top = child_rect.getHeight(); + S32 panel_width = child_rect.getWidth(); + + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); + if (mScrollbar && mScrollbar->getVisible()) + { + panel_top += mScrollbar->getDocPos(); + panel_width -= scrollbar_size; + } + + // Set sizes for first panels and dragbars + LLRect panel_rect = child->getRect(); + ctrlSetLeftTopAndSize(mContainerPanel, child_rect.mLeft, panel_top, panel_width, panel_rect.getHeight()); } void LLAccordionCtrlTab::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) { - if (!panel) - return; - LLRect panel_rect = panel->getRect(); - panel_rect.setLeftTopAndSize(left, top, width, height); - panel->reshape( width, height, 1); - panel->setRect(panel_rect); + if (!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize(left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); } BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask) { - //header may be not the first child but we need to process it first - if (y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT / 2)) - { - //inside tab header - //fix for EXT-6619 - mHeader->handleToolTip(x, y, mask); - return TRUE; - } - return LLUICtrl::handleToolTip(x, y, mask); + //header may be not the first child but we need to process it first + if (y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT / 2)) + { + //inside tab header + //fix for EXT-6619 + mHeader->handleToolTip(x, y, mask); + return TRUE; + } + return LLUICtrl::handleToolTip(x, y, mask); } BOOL LLAccordionCtrlTab::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if (LLUICtrl::handleScrollWheel(x, y, clicks)) - { - return TRUE; - } + if (LLUICtrl::handleScrollWheel(x, y, clicks)) + { + return TRUE; + } - if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) - { - return TRUE; - } + if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) + { + return TRUE; + } - return FALSE; + return FALSE; } diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 496c34c38b..f01fff2519 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -1,25 +1,25 @@ -/** +/** * @file LLAccordionCtrlTab.h * @brief Collapsible box control implementation * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,7 +41,7 @@ class LLScrollbar; -// LLAccordionCtrlTab is a container for other controls. +// LLAccordionCtrlTab is a container for other controls. // It has a Header, by clicking on which hosted controls are shown or hidden. // When hosted controls are show - LLAccordionCtrlTab is expanded. // When hosted controls are hidden - LLAccordionCtrlTab is collapsed. @@ -51,201 +51,201 @@ class LLAccordionCtrlTab : public LLUICtrl // Interface public: - struct Params - : public LLInitParam::Block - { - Optional display_children, //expanded or collapsed after initialization - collapsible; + struct Params + : public LLInitParam::Block + { + Optional display_children, //expanded or collapsed after initialization + collapsible; + + Optional title; - Optional title; + Optional header_height, + min_width, + min_height; - Optional header_height, - min_width, - min_height; + // Overlay images (arrows on the left) + Mandatory header_expand_img, + header_expand_img_pressed, + header_collapse_img, + header_collapse_img_pressed; - // Overlay images (arrows on the left) - Mandatory header_expand_img, - header_expand_img_pressed, - header_collapse_img, - header_collapse_img_pressed; + // Background images for the accordion tabs + Mandatory header_image, + header_image_over, + header_image_pressed, + header_image_focused; - // Background images for the accordion tabs - Mandatory header_image, - header_image_over, - header_image_pressed, - header_image_focused; + Optional header_bg_color, + header_text_color, + dropdown_bg_color; - Optional header_bg_color, - header_text_color, - dropdown_bg_color; + Optional header_visible; - Optional header_visible; + Optional fit_panel; - Optional fit_panel; + Optional selection_enabled; - Optional selection_enabled; + Optional padding_left, + padding_right, + padding_top, + padding_bottom; - Optional padding_left, - padding_right, - padding_top, - padding_bottom; + Params(); + }; - Params(); - }; + typedef LLDefaultChildRegistry child_registry_t; - typedef LLDefaultChildRegistry child_registry_t; + virtual ~LLAccordionCtrlTab(); - virtual ~LLAccordionCtrlTab(); - - // Registers callback for expand/collapse events. - boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb); + // Registers callback for expand/collapse events. + boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb); - // Changes expand/collapse state - virtual void setDisplayChildren(bool display); + // Changes expand/collapse state + virtual void setDisplayChildren(bool display); - // Returns expand/collapse state - virtual bool getDisplayChildren() const { return mDisplayChildren; }; + // Returns expand/collapse state + virtual bool getDisplayChildren() const { return mDisplayChildren; }; - //set LLAccordionCtrlTab panel - void setAccordionView(LLView* panel); - LLView* getAccordionView() { return mContainerPanel; }; + //set LLAccordionCtrlTab panel + void setAccordionView(LLView* panel); + LLView* getAccordionView() { return mContainerPanel; }; - std::string getTitle() const; + std::string getTitle() const; - // Set text and highlight substring in LLAccordionCtrlTabHeader - void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); + // Set text and highlight substring in LLAccordionCtrlTabHeader + void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); - // Set text font style in LLAccordionCtrlTabHeader - void setTitleFontStyle(std::string style); + // Set text font style in LLAccordionCtrlTabHeader + void setTitleFontStyle(std::string style); - // Set text color in LLAccordionCtrlTabHeader - void setTitleColor(LLUIColor color); + // Set text color in LLAccordionCtrlTabHeader + void setTitleColor(LLUIColor color); - boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); - boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); - void setSelected(bool is_selected); + void setSelected(bool is_selected); - bool getCollapsible() { return mCollapsible; }; + bool getCollapsible() { return mCollapsible; }; - void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; - void changeOpenClose(bool is_open); + void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; + void changeOpenClose(bool is_open); - void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; }; - bool canOpenClose() const { return mCanOpenClose; }; + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; }; + bool canOpenClose() const { return mCanOpenClose; }; - virtual BOOL postBuild(); + virtual BOOL postBuild(); - S32 notifyParent(const LLSD& info); - S32 notify(const LLSD& info); - bool notifyChildren(const LLSD& info); + S32 notifyParent(const LLSD& info); + S32 notify(const LLSD& info); + bool notifyChildren(const LLSD& info); - void draw(); + void draw(); - void storeOpenCloseState(); - void restoreOpenCloseState(); + void storeOpenCloseState(); + void restoreOpenCloseState(); protected: - LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); - friend class LLUICtrlFactory; + LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); + friend class LLUICtrlFactory; // Overrides public: - // Call reshape after changing size - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + // Call reshape after changing size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /** - * Raises notifyParent event with "child_visibility_change" = new_visibility - */ - void onVisibilityChange(BOOL new_visibility); - virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); + /** + * Raises notifyParent event with "child_visibility_change" = new_visibility + */ + void onVisibilityChange(BOOL new_visibility); + virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); - // Changes expand/collapse state and triggers expand/collapse callbacks - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + // Changes expand/collapse state and triggers expand/collapse callbacks + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - virtual bool addChild(LLView* child, S32 tab_group = 0 ); + virtual bool addChild(LLView* child, S32 tab_group = 0 ); - bool isExpanded() const { return mDisplayChildren; } + bool isExpanded() const { return mDisplayChildren; } - S32 getHeaderHeight(); + S32 getHeaderHeight(); - // Min size functions + // Min size functions - void setHeaderVisible(bool value); + void setHeaderVisible(bool value); - bool getHeaderVisible() { return mHeaderVisible;} + bool getHeaderVisible() { return mHeaderVisible;} - S32 mExpandedHeight; // Height of expanded ctrl. - // Used to restore height after expand. + S32 mExpandedHeight; // Height of expanded ctrl. + // Used to restore height after expand. - S32 getPaddingLeft() const { return mPaddingLeft;} - S32 getPaddingRight() const { return mPaddingRight;} - S32 getPaddingTop() const { return mPaddingTop;} - S32 getPaddingBottom() const { return mPaddingBottom;} + S32 getPaddingLeft() const { return mPaddingLeft;} + S32 getPaddingRight() const { return mPaddingRight;} + S32 getPaddingTop() const { return mPaddingTop;} + S32 getPaddingBottom() const { return mPaddingBottom;} - void showAndFocusHeader(); + void showAndFocusHeader(); - void setFitPanel( bool fit ) { mFitPanel = true; } - bool getFitParent() const { return mFitPanel; } + void setFitPanel( bool fit ) { mFitPanel = true; } + bool getFitParent() const { return mFitPanel; } - void setIgnoreResizeNotification(bool ignore) { mSkipChangesOnNotifyParent = ignore;} + void setIgnoreResizeNotification(bool ignore) { mSkipChangesOnNotifyParent = ignore;} protected: - void adjustContainerPanel (const LLRect& child_rect); - void adjustContainerPanel (); - S32 getChildViewHeight (); + void adjustContainerPanel (const LLRect& child_rect); + void adjustContainerPanel (); + S32 getChildViewHeight (); - void onScrollPosChangeCallback(S32, LLScrollbar*); + void onScrollPosChangeCallback(S32, LLScrollbar*); - void show_hide_scrollbar (const LLRect& child_rect); - void showScrollbar (const LLRect& child_rect); - void hideScrollbar (const LLRect& child_rect); + void show_hide_scrollbar (const LLRect& child_rect); + void showScrollbar (const LLRect& child_rect); + void hideScrollbar (const LLRect& child_rect); - void updateLayout ( const LLRect& child_rect ); - void ctrlSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height); + void updateLayout ( const LLRect& child_rect ); + void ctrlSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height); - void drawChild(const LLRect& root_rect,LLView* child); + void drawChild(const LLRect& root_rect,LLView* child); - LLView* findContainerView (); + LLView* findContainerView (); - void selectOnFocusReceived(); - void deselectOnFocusLost(); + void selectOnFocusReceived(); + void deselectOnFocusLost(); private: - class LLAccordionCtrlTabHeader; - LLAccordionCtrlTabHeader* mHeader; //Header + class LLAccordionCtrlTabHeader; + LLAccordionCtrlTabHeader* mHeader; //Header - bool mDisplayChildren; //Expanded/collapsed - bool mCollapsible; - bool mHeaderVisible; + bool mDisplayChildren; //Expanded/collapsed + bool mCollapsible; + bool mHeaderVisible; - bool mCanOpenClose; - bool mFitPanel; + bool mCanOpenClose; + bool mFitPanel; - S32 mPaddingLeft; - S32 mPaddingRight; - S32 mPaddingTop; - S32 mPaddingBottom; + S32 mPaddingLeft; + S32 mPaddingRight; + S32 mPaddingTop; + S32 mPaddingBottom; - bool mStoredOpenCloseState; - bool mWasStateStored; - bool mSkipChangesOnNotifyParent; + bool mStoredOpenCloseState; + bool mWasStateStored; + bool mSkipChangesOnNotifyParent; - bool mSelectionEnabled; + bool mSelectionEnabled; - LLScrollbar* mScrollbar; - LLView* mContainerPanel; + LLScrollbar* mScrollbar; + LLView* mContainerPanel; - LLUIColor mDropdownBGColor; + LLUIColor mDropdownBGColor; }; #endif diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp index 589b75ab5b..f2b1f5720f 100644 --- a/indra/llui/llbadge.cpp +++ b/indra/llui/llbadge.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbadge.cpp * @brief Implementation for badges * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,115 +40,115 @@ template class LLBadge* LLView::getChild(const std::string& name, LLBadge::Params::Params() - : image("image") - , border_image("border_image") - , border_color("border_color") - , image_color("image_color") - , label("label") - , label_color("label_color") - , label_offset_horiz("label_offset_horiz") - , label_offset_vert("label_offset_vert") - , location("location", LLRelPos::TOP_LEFT) - , location_offset_hcenter("location_offset_hcenter") - , location_offset_vcenter("location_offset_vcenter") - , location_percent_hcenter("location_percent_hcenter") - , location_percent_vcenter("location_percent_vcenter") - , padding_horiz("padding_horiz") - , padding_vert("padding_vert") + : image("image") + , border_image("border_image") + , border_color("border_color") + , image_color("image_color") + , label("label") + , label_color("label_color") + , label_offset_horiz("label_offset_horiz") + , label_offset_vert("label_offset_vert") + , location("location", LLRelPos::TOP_LEFT) + , location_offset_hcenter("location_offset_hcenter") + , location_offset_vcenter("location_offset_vcenter") + , location_percent_hcenter("location_percent_hcenter") + , location_percent_vcenter("location_percent_vcenter") + , padding_horiz("padding_horiz") + , padding_vert("padding_vert") {} bool LLBadge::Params::equals(const Params& a) const { - bool comp = true; - - // skip owner in comparison on purpose - - comp &= (border_image() == a.border_image()); - comp &= (border_color() == a.border_color()); - comp &= (image() == a.image()); - comp &= (image_color() == a.image_color()); - comp &= (label() == a.label()); - comp &= (label_color() == a.label_color()); - comp &= (label_offset_horiz() == a.label_offset_horiz()); - comp &= (label_offset_vert() == a.label_offset_vert()); - comp &= (location() == a.location()); - comp &= (location_offset_hcenter() == a.location_offset_hcenter()); - comp &= (location_offset_vcenter() == a.location_offset_vcenter()); - comp &= (location_percent_hcenter() == a.location_percent_hcenter()); - comp &= (location_percent_vcenter() == a.location_percent_vcenter()); - comp &= (padding_horiz() == a.padding_horiz()); - comp &= (padding_vert() == a.padding_vert()); - - return comp; + bool comp = true; + + // skip owner in comparison on purpose + + comp &= (border_image() == a.border_image()); + comp &= (border_color() == a.border_color()); + comp &= (image() == a.image()); + comp &= (image_color() == a.image_color()); + comp &= (label() == a.label()); + comp &= (label_color() == a.label_color()); + comp &= (label_offset_horiz() == a.label_offset_horiz()); + comp &= (label_offset_vert() == a.label_offset_vert()); + comp &= (location() == a.location()); + comp &= (location_offset_hcenter() == a.location_offset_hcenter()); + comp &= (location_offset_vcenter() == a.location_offset_vcenter()); + comp &= (location_percent_hcenter() == a.location_percent_hcenter()); + comp &= (location_percent_vcenter() == a.location_percent_vcenter()); + comp &= (padding_horiz() == a.padding_horiz()); + comp &= (padding_vert() == a.padding_vert()); + + return comp; } LLBadge::LLBadge(const LLBadge::Params& p) - : LLUICtrl(p) - , mOwner(p.owner) - , mBorderImage(p.border_image) - , mBorderColor(p.border_color) - , mGLFont(p.font) - , mImage(p.image) - , mImageColor(p.image_color) - , mLabel(p.label) - , mLabelColor(p.label_color) - , mLabelOffsetHoriz(p.label_offset_horiz) - , mLabelOffsetVert(p.label_offset_vert) - , mLocation(p.location) - , mLocationOffsetHCenter(BADGE_OFFSET_NOT_SPECIFIED) - , mLocationOffsetVCenter(BADGE_OFFSET_NOT_SPECIFIED) - , mLocationPercentHCenter(0.5f) - , mLocationPercentVCenter(0.5f) - , mPaddingHoriz(p.padding_horiz) - , mPaddingVert(p.padding_vert) - , mParentScroller(NULL) - , mDrawAtParentTop(false) + : LLUICtrl(p) + , mOwner(p.owner) + , mBorderImage(p.border_image) + , mBorderColor(p.border_color) + , mGLFont(p.font) + , mImage(p.image) + , mImageColor(p.image_color) + , mLabel(p.label) + , mLabelColor(p.label_color) + , mLabelOffsetHoriz(p.label_offset_horiz) + , mLabelOffsetVert(p.label_offset_vert) + , mLocation(p.location) + , mLocationOffsetHCenter(BADGE_OFFSET_NOT_SPECIFIED) + , mLocationOffsetVCenter(BADGE_OFFSET_NOT_SPECIFIED) + , mLocationPercentHCenter(0.5f) + , mLocationPercentVCenter(0.5f) + , mPaddingHoriz(p.padding_horiz) + , mPaddingVert(p.padding_vert) + , mParentScroller(NULL) + , mDrawAtParentTop(false) { - if (mImage.isNull()) - { - LL_WARNS() << "Badge: " << getName() << " with no image!" << LL_ENDL; - } - - if (p.location_offset_hcenter.isProvided()) - { - mLocationOffsetHCenter = p.location_offset_hcenter(); - } - - if (p.location_offset_vcenter.isProvided()) - { - mLocationOffsetVCenter = p.location_offset_vcenter(); - } - - // - // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter - // based on the Location enum and our horizontal and vertical location percentages. The - // draw code then uses this on the owner rectangle to compute the screen location for - // the badge. - // - - if (!LLRelPos::IsCenter(mLocation)) - { - F32 h_center = p.location_percent_hcenter * 0.01f; - F32 v_center = p.location_percent_vcenter * 0.01f; - - if (LLRelPos::IsRight(mLocation)) - { - mLocationPercentHCenter = 0.5f * (1.0f + h_center); - } - else if (LLRelPos::IsLeft(mLocation)) - { - mLocationPercentHCenter = 0.5f * (1.0f - h_center); - } - - if (LLRelPos::IsTop(mLocation)) - { - mLocationPercentVCenter = 0.5f * (1.0f + v_center); - } - else if (LLRelPos::IsBottom(mLocation)) - { - mLocationPercentVCenter = 0.5f * (1.0f - v_center); - } - } + if (mImage.isNull()) + { + LL_WARNS() << "Badge: " << getName() << " with no image!" << LL_ENDL; + } + + if (p.location_offset_hcenter.isProvided()) + { + mLocationOffsetHCenter = p.location_offset_hcenter(); + } + + if (p.location_offset_vcenter.isProvided()) + { + mLocationOffsetVCenter = p.location_offset_vcenter(); + } + + // + // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter + // based on the Location enum and our horizontal and vertical location percentages. The + // draw code then uses this on the owner rectangle to compute the screen location for + // the badge. + // + + if (!LLRelPos::IsCenter(mLocation)) + { + F32 h_center = p.location_percent_hcenter * 0.01f; + F32 v_center = p.location_percent_vcenter * 0.01f; + + if (LLRelPos::IsRight(mLocation)) + { + mLocationPercentHCenter = 0.5f * (1.0f + h_center); + } + else if (LLRelPos::IsLeft(mLocation)) + { + mLocationPercentHCenter = 0.5f * (1.0f - h_center); + } + + if (LLRelPos::IsTop(mLocation)) + { + mLocationPercentVCenter = 0.5f * (1.0f + v_center); + } + else if (LLRelPos::IsBottom(mLocation)) + { + mLocationPercentVCenter = 0.5f * (1.0f - v_center); + } + } } LLBadge::~LLBadge() @@ -157,28 +157,28 @@ LLBadge::~LLBadge() bool LLBadge::addToView(LLView * view) { - bool child_added = view->addChild(this); + bool child_added = view->addChild(this); - if (child_added) - { - setShape(view->getLocalRect()); + if (child_added) + { + setShape(view->getLocalRect()); - // Find a parent scroll container, if there is one in case we need it for positioning + // Find a parent scroll container, if there is one in case we need it for positioning - LLView * parent = mOwner.get(); + LLView * parent = mOwner.get(); - while ((parent != NULL) && ((mParentScroller = dynamic_cast(parent)) == NULL)) - { - parent = parent->getParent(); - } - } + while ((parent != NULL) && ((mParentScroller = dynamic_cast(parent)) == NULL)) + { + parent = parent->getParent(); + } + } - return child_added; + return child_added; } void LLBadge::setLabel(const LLStringExplicit& label) { - mLabel = label; + mLabel = label; } // @@ -186,203 +186,203 @@ void LLBadge::setLabel(const LLStringExplicit& label) // void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color) { - gGL.pushUIMatrix(); - gGL.loadUIIdentity(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4ubv(color.mV); - gGL.texCoord2i(0, 0); - - F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f; - F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f; - - LLRectf screen_rect(ll_round(x), - ll_round(y), - ll_round(x) + width, - ll_round(y) + height); - - LLVector3 vertices[4]; - vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f); - vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f); - vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f); - vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f); - - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, 4); - } - gGL.end(); - - gGL.popUIMatrix(); + gGL.pushUIMatrix(); + gGL.loadUIIdentity(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4ubv(color.mV); + gGL.texCoord2i(0, 0); + + F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f; + F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f; + + LLRectf screen_rect(ll_round(x), + ll_round(y), + ll_round(x) + width, + ll_round(y) + height); + + LLVector3 vertices[4]; + vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f); + vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f); + vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f); + vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f); + + gGL.begin(LLRender::QUADS); + { + gGL.vertexBatchPreTransformed(vertices, 4); + } + gGL.end(); + + gGL.popUIMatrix(); } // virtual void LLBadge::draw() { - if (!mLabel.empty()) - { - LLView* owner_view = mOwner.get(); - - if (owner_view && owner_view->isInVisibleChain()) - { - // - // Calculate badge size based on label text - // - - LLWString badge_label_wstring = mLabel; - - S32 badge_label_begin_offset = 0; - S32 badge_char_length = S32_MAX; - S32 badge_pixel_length = S32_MAX; - F32 *right_position_out = NULL; - BOOL do_not_use_ellipses = false; - - F32 badge_width = (2.0f * mPaddingHoriz) + - mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length); - - F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight(); - - // - // Calculate badge position based on owner - // - - LLRect owner_rect; - owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this); - - S32 location_offset_horiz = mLocationOffsetHCenter; - S32 location_offset_vert = mLocationOffsetVCenter; - - // If we're in a scroll container, do some math to keep us in the same place on screen if applicable - if (mParentScroller != NULL) - { - LLRect visibleRect = mParentScroller->getVisibleContentRect(); - - if (mLocationOffsetHCenter != BADGE_OFFSET_NOT_SPECIFIED) - { - if (LLRelPos::IsRight(mLocation)) - { - location_offset_horiz += visibleRect.mRight; - } - else if (LLRelPos::IsLeft(mLocation)) - { - location_offset_horiz += visibleRect.mLeft; - } - else // center - { - location_offset_horiz += (visibleRect.mLeft + visibleRect.mRight) / 2; - } - } - - if (mLocationOffsetVCenter != BADGE_OFFSET_NOT_SPECIFIED) - { - if (LLRelPos::IsTop(mLocation)) - { - location_offset_vert += visibleRect.mTop; - } - else if (LLRelPos::IsBottom(mLocation)) - { - location_offset_vert += visibleRect.mBottom; - } - else // center - { - location_offset_vert += (visibleRect.mBottom + visibleRect.mTop) / 2; - } - } - } - - F32 badge_center_x; - F32 badge_center_y; - - // Compute x position - if (mLocationOffsetHCenter == BADGE_OFFSET_NOT_SPECIFIED) - { - badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter; - } - else - { - badge_center_x = location_offset_horiz; - } - - // Compute y position - if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED) - { - if(mDrawAtParentTop) - { - badge_center_y = owner_rect.mTop - badge_height * 0.5f - 1; - } - else - { - badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; - } - } - else - { - badge_center_y = location_offset_vert; - } - - // - // Draw button image, if available. - // Otherwise draw basic rectangular button. - // - - F32 alpha = getDrawContext().mAlpha; - - if (!mImage.isNull()) - { - F32 badge_x = badge_center_x - badge_width * 0.5f; - F32 badge_y = badge_center_y - badge_height * 0.5f; - - mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha); - - if (!mBorderImage.isNull()) - { - mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha); - } - } - else - { - LL_DEBUGS() << "No image for badge " << getName() << " on owner " << owner_view->getName() << LL_ENDL; - - renderBadgeBackground(badge_center_x, badge_center_y, - badge_width, badge_height, - mImageColor % alpha); - } - - // - // Draw the label - // - - mGLFont->render(badge_label_wstring, - badge_label_begin_offset, - badge_center_x + mLabelOffsetHoriz, - badge_center_y + mLabelOffsetVert, - mLabelColor % alpha, - LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position - LLFontGL::NORMAL, // normal text (not bold, italics, etc.) - LLFontGL::DROP_SHADOW_SOFT, - badge_char_length, badge_pixel_length, - right_position_out, do_not_use_ellipses); - } - } + if (!mLabel.empty()) + { + LLView* owner_view = mOwner.get(); + + if (owner_view && owner_view->isInVisibleChain()) + { + // + // Calculate badge size based on label text + // + + LLWString badge_label_wstring = mLabel; + + S32 badge_label_begin_offset = 0; + S32 badge_char_length = S32_MAX; + S32 badge_pixel_length = S32_MAX; + F32 *right_position_out = NULL; + BOOL do_not_use_ellipses = false; + + F32 badge_width = (2.0f * mPaddingHoriz) + + mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length); + + F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight(); + + // + // Calculate badge position based on owner + // + + LLRect owner_rect; + owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this); + + S32 location_offset_horiz = mLocationOffsetHCenter; + S32 location_offset_vert = mLocationOffsetVCenter; + + // If we're in a scroll container, do some math to keep us in the same place on screen if applicable + if (mParentScroller != NULL) + { + LLRect visibleRect = mParentScroller->getVisibleContentRect(); + + if (mLocationOffsetHCenter != BADGE_OFFSET_NOT_SPECIFIED) + { + if (LLRelPos::IsRight(mLocation)) + { + location_offset_horiz += visibleRect.mRight; + } + else if (LLRelPos::IsLeft(mLocation)) + { + location_offset_horiz += visibleRect.mLeft; + } + else // center + { + location_offset_horiz += (visibleRect.mLeft + visibleRect.mRight) / 2; + } + } + + if (mLocationOffsetVCenter != BADGE_OFFSET_NOT_SPECIFIED) + { + if (LLRelPos::IsTop(mLocation)) + { + location_offset_vert += visibleRect.mTop; + } + else if (LLRelPos::IsBottom(mLocation)) + { + location_offset_vert += visibleRect.mBottom; + } + else // center + { + location_offset_vert += (visibleRect.mBottom + visibleRect.mTop) / 2; + } + } + } + + F32 badge_center_x; + F32 badge_center_y; + + // Compute x position + if (mLocationOffsetHCenter == BADGE_OFFSET_NOT_SPECIFIED) + { + badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter; + } + else + { + badge_center_x = location_offset_horiz; + } + + // Compute y position + if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED) + { + if(mDrawAtParentTop) + { + badge_center_y = owner_rect.mTop - badge_height * 0.5f - 1; + } + else + { + badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; + } + } + else + { + badge_center_y = location_offset_vert; + } + + // + // Draw button image, if available. + // Otherwise draw basic rectangular button. + // + + F32 alpha = getDrawContext().mAlpha; + + if (!mImage.isNull()) + { + F32 badge_x = badge_center_x - badge_width * 0.5f; + F32 badge_y = badge_center_y - badge_height * 0.5f; + + mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha); + + if (!mBorderImage.isNull()) + { + mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha); + } + } + else + { + LL_DEBUGS() << "No image for badge " << getName() << " on owner " << owner_view->getName() << LL_ENDL; + + renderBadgeBackground(badge_center_x, badge_center_y, + badge_width, badge_height, + mImageColor % alpha); + } + + // + // Draw the label + // + + mGLFont->render(badge_label_wstring, + badge_label_begin_offset, + badge_center_x + mLabelOffsetHoriz, + badge_center_y + mLabelOffsetVert, + mLabelColor % alpha, + LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position + LLFontGL::NORMAL, // normal text (not bold, italics, etc.) + LLFontGL::DROP_SHADOW_SOFT, + badge_char_length, badge_pixel_length, + right_position_out, do_not_use_ellipses); + } + } } namespace LLInitParam { - void TypeValues::declareValues() - { - declare("bottom", LLRelPos::BOTTOM); - declare("bottom_left", LLRelPos::BOTTOM_LEFT); - declare("bottom_right", LLRelPos::BOTTOM_RIGHT); - declare("center", LLRelPos::CENTER); - declare("left", LLRelPos::LEFT); - declare("right", LLRelPos::RIGHT); - declare("top", LLRelPos::TOP); - declare("top_left", LLRelPos::TOP_LEFT); - declare("top_right", LLRelPos::TOP_RIGHT); - } + void TypeValues::declareValues() + { + declare("bottom", LLRelPos::BOTTOM); + declare("bottom_left", LLRelPos::BOTTOM_LEFT); + declare("bottom_right", LLRelPos::BOTTOM_RIGHT); + declare("center", LLRelPos::CENTER); + declare("left", LLRelPos::LEFT); + declare("right", LLRelPos::RIGHT); + declare("top", LLRelPos::TOP); + declare("top_left", LLRelPos::TOP_LEFT); + declare("top_right", LLRelPos::TOP_RIGHT); + } } diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h index 55f92e6e34..59296ffe86 100644 --- a/indra/llui/llbadge.h +++ b/indra/llui/llbadge.h @@ -1,25 +1,25 @@ -/** +/** * @file llbadge.h * @brief Header for badges * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -49,38 +49,38 @@ class LLUICtrlFactory; namespace LLRelPos { - enum Location - { - CENTER = 0, + enum Location + { + CENTER = 0, - LEFT = (1 << 0), - RIGHT = (1 << 1), + LEFT = (1 << 0), + RIGHT = (1 << 1), - TOP = (1 << 2), - BOTTOM = (1 << 3), + TOP = (1 << 2), + BOTTOM = (1 << 3), - BOTTOM_LEFT = (BOTTOM | LEFT), - BOTTOM_RIGHT = (BOTTOM | RIGHT), + BOTTOM_LEFT = (BOTTOM | LEFT), + BOTTOM_RIGHT = (BOTTOM | RIGHT), - TOP_LEFT = (TOP | LEFT), - TOP_RIGHT = (TOP | RIGHT), - }; + TOP_LEFT = (TOP | LEFT), + TOP_RIGHT = (TOP | RIGHT), + }; - inline bool IsBottom(Location relPos) { return (relPos & BOTTOM) == BOTTOM; } - inline bool IsCenter(Location relPos) { return (relPos == CENTER); } - inline bool IsLeft(Location relPos) { return (relPos & LEFT) == LEFT; } - inline bool IsRight(Location relPos) { return (relPos & RIGHT) == RIGHT; } - inline bool IsTop(Location relPos) { return (relPos & TOP) == TOP; } + inline bool IsBottom(Location relPos) { return (relPos & BOTTOM) == BOTTOM; } + inline bool IsCenter(Location relPos) { return (relPos == CENTER); } + inline bool IsLeft(Location relPos) { return (relPos & LEFT) == LEFT; } + inline bool IsRight(Location relPos) { return (relPos & RIGHT) == RIGHT; } + inline bool IsTop(Location relPos) { return (relPos & TOP) == TOP; } } // NOTE: This needs to occur before Optional declaration for proper compilation. namespace LLInitParam { - template<> - struct TypeValues : public TypeValuesHelper - { - static void declareValues(); - }; + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; } // @@ -91,82 +91,82 @@ class LLBadge : public LLUICtrl { public: - struct Params - : public LLInitParam::Block - { - Optional< LLHandle > owner; // Mandatory in code but not in xml - - Optional< LLUIImage* > border_image; - Optional< LLUIColor > border_color; - - Optional< LLUIImage* > image; - Optional< LLUIColor > image_color; - - Optional< std::string > label; - Optional< LLUIColor > label_color; - - Optional< S32 > label_offset_horiz; - Optional< S32 > label_offset_vert; - - Optional< LLRelPos::Location > location; - Optional< S32 > location_offset_hcenter; - Optional< S32 > location_offset_vcenter; - Optional< U32 > location_percent_hcenter; - Optional< U32 > location_percent_vcenter; - - Optional< F32 > padding_horiz; - Optional< F32 > padding_vert; - - Params(); - - bool equals(const Params&) const; - }; - + struct Params + : public LLInitParam::Block + { + Optional< LLHandle > owner; // Mandatory in code but not in xml + + Optional< LLUIImage* > border_image; + Optional< LLUIColor > border_color; + + Optional< LLUIImage* > image; + Optional< LLUIColor > image_color; + + Optional< std::string > label; + Optional< LLUIColor > label_color; + + Optional< S32 > label_offset_horiz; + Optional< S32 > label_offset_vert; + + Optional< LLRelPos::Location > location; + Optional< S32 > location_offset_hcenter; + Optional< S32 > location_offset_vcenter; + Optional< U32 > location_percent_hcenter; + Optional< U32 > location_percent_vcenter; + + Optional< F32 > padding_horiz; + Optional< F32 > padding_vert; + + Params(); + + bool equals(const Params&) const; + }; + protected: - friend class LLUICtrlFactory; - LLBadge(const Params& p); + friend class LLUICtrlFactory; + LLBadge(const Params& p); public: - ~LLBadge(); + ~LLBadge(); - bool addToView(LLView * view); + bool addToView(LLView * view); - virtual void draw(); + virtual void draw(); - const std::string getLabel() const { return wstring_to_utf8str(mLabel); } - void setLabel( const LLStringExplicit& label); + const std::string getLabel() const { return wstring_to_utf8str(mLabel); } + void setLabel( const LLStringExplicit& label); - void setDrawAtParentTop(bool draw_at_top) { mDrawAtParentTop = draw_at_top;} + void setDrawAtParentTop(bool draw_at_top) { mDrawAtParentTop = draw_at_top;} private: - LLPointer< LLUIImage > mBorderImage; - LLUIColor mBorderColor; - - const LLFontGL* mGLFont; - - LLPointer< LLUIImage > mImage; - LLUIColor mImageColor; - - LLUIString mLabel; - LLUIColor mLabelColor; - - S32 mLabelOffsetHoriz; - S32 mLabelOffsetVert; - - LLRelPos::Location mLocation; - S32 mLocationOffsetHCenter; - S32 mLocationOffsetVCenter; - F32 mLocationPercentHCenter; - F32 mLocationPercentVCenter; - - LLHandle< LLView > mOwner; - - F32 mPaddingHoriz; - F32 mPaddingVert; - - LLScrollContainer* mParentScroller; - bool mDrawAtParentTop; + LLPointer< LLUIImage > mBorderImage; + LLUIColor mBorderColor; + + const LLFontGL* mGLFont; + + LLPointer< LLUIImage > mImage; + LLUIColor mImageColor; + + LLUIString mLabel; + LLUIColor mLabelColor; + + S32 mLabelOffsetHoriz; + S32 mLabelOffsetVert; + + LLRelPos::Location mLocation; + S32 mLocationOffsetHCenter; + S32 mLocationOffsetVCenter; + F32 mLocationPercentHCenter; + F32 mLocationPercentVCenter; + + LLHandle< LLView > mOwner; + + F32 mPaddingHoriz; + F32 mPaddingVert; + + LLScrollContainer* mParentScroller; + bool mDrawAtParentTop; }; // Build time optimization, generate once in .cpp file diff --git a/indra/llui/llbadgeholder.cpp b/indra/llui/llbadgeholder.cpp index 1f786f36ae..bc22969ab4 100644 --- a/indra/llui/llbadgeholder.cpp +++ b/indra/llui/llbadgeholder.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbadgeholder.cpp * @brief Source for badge holders * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,14 +32,14 @@ bool LLBadgeHolder::addBadge(LLBadge * badge) { - bool badge_added = false; + bool badge_added = false; - LLView * this_view = dynamic_cast(this); + LLView * this_view = dynamic_cast(this); - if (this_view && mAcceptsBadge) - { - badge_added = badge->addToView(this_view); - } + if (this_view && mAcceptsBadge) + { + badge_added = badge->addToView(this_view); + } - return badge_added; + return badge_added; } diff --git a/indra/llui/llbadgeholder.h b/indra/llui/llbadgeholder.h index 2538eaae91..470baf7a9a 100644 --- a/indra/llui/llbadgeholder.h +++ b/indra/llui/llbadgeholder.h @@ -1,25 +1,25 @@ -/** +/** * @file llbadgeholder.h * @brief Header for badge holders * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,19 +37,19 @@ class LLBadgeHolder { public: - LLBadgeHolder(bool acceptsBadge) - : mAcceptsBadge(acceptsBadge) - { - } + LLBadgeHolder(bool acceptsBadge) + : mAcceptsBadge(acceptsBadge) + { + } - void setAcceptsBadge(bool acceptsBadge) { mAcceptsBadge = acceptsBadge; } - bool acceptsBadge() const { return mAcceptsBadge; } + void setAcceptsBadge(bool acceptsBadge) { mAcceptsBadge = acceptsBadge; } + bool acceptsBadge() const { return mAcceptsBadge; } - virtual bool addBadge(LLBadge * badge); + virtual bool addBadge(LLBadge * badge); private: - bool mAcceptsBadge; + bool mAcceptsBadge; }; diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp index 5f11c383ef..3194a4b56f 100644 --- a/indra/llui/llbadgeowner.cpp +++ b/indra/llui/llbadgeowner.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbadgeowner.cpp * @brief Class to manage badges attached to a UI control * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,86 +35,86 @@ // LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle) - : mHasBadgeHolderParent(false), - mBadge(NULL), - mBadgeOwnerView(viewHandle) + : mHasBadgeHolderParent(false), + mBadge(NULL), + mBadgeOwnerView(viewHandle) { } void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p) { - if (!p.equals(LLUICtrlFactory::getDefaultParams())) - { - mBadge = createBadge(p); - mHasBadgeHolderParent = false; - - LLView * owner_view = mBadgeOwnerView.get(); - if (owner_view) - { - mBadge->addToView(owner_view); - } - } + if (!p.equals(LLUICtrlFactory::getDefaultParams())) + { + mBadge = createBadge(p); + mHasBadgeHolderParent = false; + + LLView * owner_view = mBadgeOwnerView.get(); + if (owner_view) + { + mBadge->addToView(owner_view); + } + } } void LLBadgeOwner::reshapeBadge(const LLRect& new_rect) { - if (mBadge) - { - mBadge->setShape(new_rect); - } + if (mBadge) + { + mBadge->setShape(new_rect); + } } void LLBadgeOwner::setBadgeVisibility(bool visible) { - if (mBadge) - { - mBadge->setVisible(visible); - } + if (mBadge) + { + mBadge->setVisible(visible); + } } void LLBadgeOwner::setDrawBadgeAtTop(bool draw_at_top) { - if (mBadge) - { - mBadge->setDrawAtParentTop(draw_at_top); - } + if (mBadge) + { + mBadge->setDrawAtParentTop(draw_at_top); + } } void LLBadgeOwner::addBadgeToParentHolder() { - LLView * owner_view = mBadgeOwnerView.get(); - - if (mBadge && owner_view) - { - LLBadgeHolder * badge_holder = NULL; - - // Find the appropriate holder for the badge - LLView * parent = owner_view->getParent(); - - while (parent) - { - LLBadgeHolder * badge_holder_panel = dynamic_cast(parent); - - if (badge_holder_panel && badge_holder_panel->acceptsBadge()) - { - badge_holder = badge_holder_panel; - break; - } - - parent = parent->getParent(); - } - - if (badge_holder) - { - mHasBadgeHolderParent = badge_holder->addBadge(mBadge); - } - } + LLView * owner_view = mBadgeOwnerView.get(); + + if (mBadge && owner_view) + { + LLBadgeHolder * badge_holder = NULL; + + // Find the appropriate holder for the badge + LLView * parent = owner_view->getParent(); + + while (parent) + { + LLBadgeHolder * badge_holder_panel = dynamic_cast(parent); + + if (badge_holder_panel && badge_holder_panel->acceptsBadge()) + { + badge_holder = badge_holder_panel; + break; + } + + parent = parent->getParent(); + } + + if (badge_holder) + { + mHasBadgeHolderParent = badge_holder->addBadge(mBadge); + } + } } LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p) { - LLBadge::Params badge_params(p); - badge_params.owner = mBadgeOwnerView; + LLBadge::Params badge_params(p); + badge_params.owner = mBadgeOwnerView; - return LLUICtrlFactory::create(badge_params); + return LLUICtrlFactory::create(badge_params); } diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h index 4ce208fa0d..d2ac17cef0 100644 --- a/indra/llui/llbadgeowner.h +++ b/indra/llui/llbadgeowner.h @@ -1,25 +1,25 @@ -/** +/** * @file llbadgeowner.h * @brief Header for badge owners * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,24 +38,24 @@ class LLBadgeOwner { public: - LLBadgeOwner(LLHandle< LLView > viewHandle); + LLBadgeOwner(LLHandle< LLView > viewHandle); + + void initBadgeParams(const LLBadge::Params& p); + void addBadgeToParentHolder(); - void initBadgeParams(const LLBadge::Params& p); - void addBadgeToParentHolder(); - - bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; }; - void setBadgeVisibility(bool visible); - void setDrawBadgeAtTop(bool draw_at_top); - void reshapeBadge(const LLRect& new_rect); + bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; }; + void setBadgeVisibility(bool visible); + void setDrawBadgeAtTop(bool draw_at_top); + void reshapeBadge(const LLRect& new_rect); private: - LLBadge* createBadge(const LLBadge::Params& p); + LLBadge* createBadge(const LLBadge::Params& p); private: - bool mHasBadgeHolderParent; - LLBadge* mBadge; - LLHandle< LLView > mBadgeOwnerView; + bool mHasBadgeHolderParent; + LLBadge* mBadge; + LLHandle< LLView > mBadgeOwnerView; }; #endif // LL_LLBADGEOWNER_H diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 9ef019840a..8803d751d0 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -1,26 +1,26 @@ -/** +/** * @file llbutton.cpp * @brief LLButton base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -56,931 +56,931 @@ static LLDefaultChildRegistry::Register r("button"); // Compiler optimization, generate extern template template class LLButton* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; // globals loaded from settings.xml -S32 LLBUTTON_H_PAD = 0; +S32 LLBUTTON_H_PAD = 0; S32 BTN_HEIGHT_SMALL= 0; -S32 BTN_HEIGHT = 0; +S32 BTN_HEIGHT = 0; LLButton::Params::Params() -: label_selected("label_selected"), // requires is_toggle true - label_shadow("label_shadow", true), - auto_resize("auto_resize", false), - use_ellipses("use_ellipses", false), - use_font_color("use_font_color", true), - image_unselected("image_unselected"), - image_selected("image_selected"), - image_hover_selected("image_hover_selected"), - image_hover_unselected("image_hover_unselected"), - image_disabled_selected("image_disabled_selected"), - image_disabled("image_disabled"), - image_pressed("image_pressed"), - image_pressed_selected("image_pressed_selected"), - image_overlay("image_overlay"), - image_overlay_alignment("image_overlay_alignment", std::string("center")), - image_top_pad("image_top_pad"), - image_bottom_pad("image_bottom_pad"), - imgoverlay_label_space("imgoverlay_label_space", 1), - label_color("label_color"), - label_color_selected("label_color_selected"), // requires is_toggle true - label_color_disabled("label_color_disabled"), - label_color_disabled_selected("label_color_disabled_selected"), - image_color("image_color"), - image_color_disabled("image_color_disabled"), - image_overlay_color("image_overlay_color", LLColor4::white % 0.75f), - image_overlay_disabled_color("image_overlay_disabled_color", LLColor4::white % 0.3f), - image_overlay_selected_color("image_overlay_selected_color", LLColor4::white), - flash_color("flash_color"), - pad_right("pad_right", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")), - pad_left("pad_left", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")), - pad_bottom("pad_bottom"), - click_callback("click_callback"), - mouse_down_callback("mouse_down_callback"), - mouse_up_callback("mouse_up_callback"), - mouse_held_callback("mouse_held_callback"), - is_toggle("is_toggle", false), - scale_image("scale_image", true), - hover_glow_amount("hover_glow_amount"), - commit_on_return("commit_on_return", true), +: label_selected("label_selected"), // requires is_toggle true + label_shadow("label_shadow", true), + auto_resize("auto_resize", false), + use_ellipses("use_ellipses", false), + use_font_color("use_font_color", true), + image_unselected("image_unselected"), + image_selected("image_selected"), + image_hover_selected("image_hover_selected"), + image_hover_unselected("image_hover_unselected"), + image_disabled_selected("image_disabled_selected"), + image_disabled("image_disabled"), + image_pressed("image_pressed"), + image_pressed_selected("image_pressed_selected"), + image_overlay("image_overlay"), + image_overlay_alignment("image_overlay_alignment", std::string("center")), + image_top_pad("image_top_pad"), + image_bottom_pad("image_bottom_pad"), + imgoverlay_label_space("imgoverlay_label_space", 1), + label_color("label_color"), + label_color_selected("label_color_selected"), // requires is_toggle true + label_color_disabled("label_color_disabled"), + label_color_disabled_selected("label_color_disabled_selected"), + image_color("image_color"), + image_color_disabled("image_color_disabled"), + image_overlay_color("image_overlay_color", LLColor4::white % 0.75f), + image_overlay_disabled_color("image_overlay_disabled_color", LLColor4::white % 0.3f), + image_overlay_selected_color("image_overlay_selected_color", LLColor4::white), + flash_color("flash_color"), + pad_right("pad_right", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")), + pad_left("pad_left", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")), + pad_bottom("pad_bottom"), + click_callback("click_callback"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + mouse_held_callback("mouse_held_callback"), + is_toggle("is_toggle", false), + 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"), - handle_right_mouse("handle_right_mouse"), - held_down_delay("held_down_delay"), - button_flash_enable("button_flash_enable", false), - button_flash_count("button_flash_count"), - button_flash_rate("button_flash_rate") + display_pressed_state("display_pressed_state", true), + use_draw_context_alpha("use_draw_context_alpha", true), + badge("badge"), + handle_right_mouse("handle_right_mouse"), + held_down_delay("held_down_delay"), + button_flash_enable("button_flash_enable", false), + button_flash_count("button_flash_count"), + button_flash_rate("button_flash_rate") { - addSynonym(is_toggle, "toggle"); - changeDefault(initial_value, LLSD(false)); + addSynonym(is_toggle, "toggle"); + changeDefault(initial_value, LLSD(false)); } LLButton::LLButton(const LLButton::Params& p) -: LLUICtrl(p), - LLBadgeOwner(getHandle()), - mMouseDownFrame(0), - mMouseHeldDownCount(0), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), - mCurGlowStrength(0.f), - mNeedsHighlight(FALSE), - mUnselectedLabel(p.label()), - mSelectedLabel(p.label_selected()), - mGLFont(p.font), - mHeldDownDelay(p.held_down_delay.seconds), // seconds until held-down callback is called - mHeldDownFrameDelay(p.held_down_delay.frames), - mImageUnselected(p.image_unselected), - mImageSelected(p.image_selected), - mImageDisabled(p.image_disabled), - mImageDisabledSelected(p.image_disabled_selected), - mImageFlash(p.image_flash), - mImagePressed(p.image_pressed), - mImagePressedSelected(p.image_pressed_selected), - mImageHoverSelected(p.image_hover_selected), - mImageHoverUnselected(p.image_hover_unselected), - mUnselectedLabelColor(p.label_color()), - mSelectedLabelColor(p.label_color_selected()), - mDisabledLabelColor(p.label_color_disabled()), - mDisabledSelectedLabelColor(p.label_color_disabled_selected()), - mImageColor(p.image_color()), - mFlashBgColor(p.flash_color()), - mDisabledImageColor(p.image_color_disabled()), - mImageOverlay(p.image_overlay()), - mImageOverlayColor(p.image_overlay_color()), - mImageOverlayDisabledColor(p.image_overlay_disabled_color()), - mImageOverlaySelectedColor(p.image_overlay_selected_color()), - mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), - mImageOverlayTopPad(p.image_top_pad), - mImageOverlayBottomPad(p.image_bottom_pad), - mImgOverlayLabelSpace(p.imgoverlay_label_space), - mIsToggle(p.is_toggle), - mScaleImage(p.scale_image), - mDropShadowedText(p.label_shadow), - mAutoResize(p.auto_resize), - mUseEllipses( p.use_ellipses ), - mUseFontColor( p.use_font_color), - mHAlign(p.font_halign), - mLeftHPad(p.pad_left), - mRightHPad(p.pad_right), - mBottomVPad(p.pad_bottom), - mHoverGlowStrength(p.hover_glow_amount), - mCommitOnReturn(p.commit_on_return), +: LLUICtrl(p), + LLBadgeOwner(getHandle()), + mMouseDownFrame(0), + mMouseHeldDownCount(0), + mBorderEnabled( FALSE ), + mFlashing( FALSE ), + mCurGlowStrength(0.f), + mNeedsHighlight(FALSE), + mUnselectedLabel(p.label()), + mSelectedLabel(p.label_selected()), + mGLFont(p.font), + mHeldDownDelay(p.held_down_delay.seconds), // seconds until held-down callback is called + mHeldDownFrameDelay(p.held_down_delay.frames), + mImageUnselected(p.image_unselected), + mImageSelected(p.image_selected), + mImageDisabled(p.image_disabled), + mImageDisabledSelected(p.image_disabled_selected), + mImageFlash(p.image_flash), + mImagePressed(p.image_pressed), + mImagePressedSelected(p.image_pressed_selected), + mImageHoverSelected(p.image_hover_selected), + mImageHoverUnselected(p.image_hover_unselected), + mUnselectedLabelColor(p.label_color()), + mSelectedLabelColor(p.label_color_selected()), + mDisabledLabelColor(p.label_color_disabled()), + mDisabledSelectedLabelColor(p.label_color_disabled_selected()), + mImageColor(p.image_color()), + mFlashBgColor(p.flash_color()), + mDisabledImageColor(p.image_color_disabled()), + mImageOverlay(p.image_overlay()), + mImageOverlayColor(p.image_overlay_color()), + mImageOverlayDisabledColor(p.image_overlay_disabled_color()), + mImageOverlaySelectedColor(p.image_overlay_selected_color()), + mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), + mImageOverlayTopPad(p.image_top_pad), + mImageOverlayBottomPad(p.image_bottom_pad), + mImgOverlayLabelSpace(p.imgoverlay_label_space), + mIsToggle(p.is_toggle), + mScaleImage(p.scale_image), + mDropShadowedText(p.label_shadow), + mAutoResize(p.auto_resize), + mUseEllipses( p.use_ellipses ), + mUseFontColor( p.use_font_color), + mHAlign(p.font_halign), + mLeftHPad(p.pad_left), + mRightHPad(p.pad_right), + 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), - mLastDrawCharsCount(0), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL), - mHeldDownSignal(NULL), - mUseDrawContextAlpha(p.use_draw_context_alpha), - mHandleRightMouse(p.handle_right_mouse), - mFlashingTimer(NULL) -{ - if (p.button_flash_enable) - { - // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be - // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). - // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). - // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). - S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; - F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; - mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); - } - else - { - mButtonFlashCount = p.button_flash_count; - mButtonFlashRate = p.button_flash_rate; - } - - static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); - static Params default_params(LLUICtrlFactory::getDefaultParams()); - - if (!p.label_selected.isProvided()) - { - mSelectedLabel = mUnselectedLabel; - } - - // Hack to make sure there is space for at least one character - if (getRect().mRight >= 0 && getRect().getWidth() > 0 && - getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) - { - // Use old defaults - mLeftHPad = llbutton_orig_h_pad; - mRightHPad = llbutton_orig_h_pad; - } - - mMouseDownTimer.stop(); - - // if custom unselected button image provided... - if (p.image_unselected != default_params.image_unselected) - { - //...fade it out for disabled image by default... - if (p.image_disabled() == default_params.image_disabled() ) - { - mImageDisabled = p.image_unselected; - mFadeWhenDisabled = TRUE; - } - - if (p.image_pressed_selected == default_params.image_pressed_selected) - { - mImagePressedSelected = mImageUnselected; - } - } - - // if custom selected button image provided... - if (p.image_selected != default_params.image_selected) - { - //...fade it out for disabled image by default... - if (p.image_disabled_selected() == default_params.image_disabled_selected()) - { - mImageDisabledSelected = p.image_selected; - mFadeWhenDisabled = TRUE; - } - - if (p.image_pressed == default_params.image_pressed) - { - mImagePressed = mImageSelected; - } - } - - if (!p.image_pressed.isProvided()) - { - mImagePressed = mImageSelected; - } - - if (!p.image_pressed_selected.isProvided()) - { - mImagePressedSelected = mImageUnselected; - } - - if (mImageUnselected.isNull()) - { - LL_WARNS() << "Button: " << getName() << " with no image!" << LL_ENDL; - } - - if (p.click_callback.isProvided()) - { - setCommitCallback(initCommitCallback(p.click_callback)); // alias -> commit_callback - } - if (p.mouse_down_callback.isProvided()) - { - setMouseDownCallback(initCommitCallback(p.mouse_down_callback)); - } - if (p.mouse_up_callback.isProvided()) - { - setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); - } - if (p.mouse_held_callback.isProvided()) - { - setHeldDownCallback(initCommitCallback(p.mouse_held_callback)); - } - - if (p.badge.isProvided()) - { - LLBadgeOwner::initBadgeParams(p.badge()); - } + mFadeWhenDisabled(FALSE), + mForcePressedState(false), + mDisplayPressedState(p.display_pressed_state), + mLastDrawCharsCount(0), + mMouseDownSignal(NULL), + mMouseUpSignal(NULL), + mHeldDownSignal(NULL), + mUseDrawContextAlpha(p.use_draw_context_alpha), + mHandleRightMouse(p.handle_right_mouse), + mFlashingTimer(NULL) +{ + if (p.button_flash_enable) + { + // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be + // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). + // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). + S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; + F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; + mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + } + else + { + mButtonFlashCount = p.button_flash_count; + mButtonFlashRate = p.button_flash_rate; + } + + static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); + static Params default_params(LLUICtrlFactory::getDefaultParams()); + + if (!p.label_selected.isProvided()) + { + mSelectedLabel = mUnselectedLabel; + } + + // Hack to make sure there is space for at least one character + if (getRect().mRight >= 0 && getRect().getWidth() > 0 && + getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) + { + // Use old defaults + mLeftHPad = llbutton_orig_h_pad; + mRightHPad = llbutton_orig_h_pad; + } + + mMouseDownTimer.stop(); + + // if custom unselected button image provided... + if (p.image_unselected != default_params.image_unselected) + { + //...fade it out for disabled image by default... + if (p.image_disabled() == default_params.image_disabled() ) + { + mImageDisabled = p.image_unselected; + mFadeWhenDisabled = TRUE; + } + + if (p.image_pressed_selected == default_params.image_pressed_selected) + { + mImagePressedSelected = mImageUnselected; + } + } + + // if custom selected button image provided... + if (p.image_selected != default_params.image_selected) + { + //...fade it out for disabled image by default... + if (p.image_disabled_selected() == default_params.image_disabled_selected()) + { + mImageDisabledSelected = p.image_selected; + mFadeWhenDisabled = TRUE; + } + + if (p.image_pressed == default_params.image_pressed) + { + mImagePressed = mImageSelected; + } + } + + if (!p.image_pressed.isProvided()) + { + mImagePressed = mImageSelected; + } + + if (!p.image_pressed_selected.isProvided()) + { + mImagePressedSelected = mImageUnselected; + } + + if (mImageUnselected.isNull()) + { + LL_WARNS() << "Button: " << getName() << " with no image!" << LL_ENDL; + } + + if (p.click_callback.isProvided()) + { + setCommitCallback(initCommitCallback(p.click_callback)); // alias -> commit_callback + } + if (p.mouse_down_callback.isProvided()) + { + setMouseDownCallback(initCommitCallback(p.mouse_down_callback)); + } + if (p.mouse_up_callback.isProvided()) + { + setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); + } + if (p.mouse_held_callback.isProvided()) + { + setHeldDownCallback(initCommitCallback(p.mouse_held_callback)); + } + + if (p.badge.isProvided()) + { + LLBadgeOwner::initBadgeParams(p.badge()); + } } LLButton::~LLButton() { - delete mMouseDownSignal; - delete mMouseUpSignal; - delete mHeldDownSignal; + delete mMouseDownSignal; + delete mMouseUpSignal; + delete mHeldDownSignal; - if (mFlashingTimer) - { - mFlashingTimer->unset(); - } + if (mFlashingTimer) + { + mFlashingTimer->unset(); + } } // HACK: Committing a button is the same as instantly clicking it. // virtual void LLButton::onCommit() { - // WARNING: Sometimes clicking a button destroys the floater or - // panel containing it. Therefore we need to call LLUICtrl::onCommit() - // LAST, otherwise this becomes deleted memory. + // WARNING: Sometimes clicking a button destroys the floater or + // panel containing it. Therefore we need to call LLUICtrl::onCommit() + // LAST, otherwise this becomes deleted memory. - if (mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); - - if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + if (mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } + if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); - if (getSoundFlags() & MOUSE_UP) - { - make_ui_sound("UISndClickRelease"); - } + if (getSoundFlags() & MOUSE_DOWN) + { + make_ui_sound("UISndClick"); + } - if (mIsToggle) - { - toggleState(); - } + if (getSoundFlags() & MOUSE_UP) + { + make_ui_sound("UISndClickRelease"); + } - // do this last, as it can result in destroying this button - LLUICtrl::onCommit(); + if (mIsToggle) + { + toggleState(); + } + + // do this last, as it can result in destroying this button + LLUICtrl::onCommit(); } boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb) { - return setClickedCallback(initCommitCallback(cb)); + return setClickedCallback(initCommitCallback(cb)); } boost::signals2::connection LLButton::setMouseDownCallback(const CommitCallbackParam& cb) { - return setMouseDownCallback(initCommitCallback(cb)); + return setMouseDownCallback(initCommitCallback(cb)); } boost::signals2::connection LLButton::setMouseUpCallback(const CommitCallbackParam& cb) { - return setMouseUpCallback(initCommitCallback(cb)); + return setMouseUpCallback(initCommitCallback(cb)); } boost::signals2::connection LLButton::setHeldDownCallback(const CommitCallbackParam& cb) { - return setHeldDownCallback(initCommitCallback(cb)); + return setHeldDownCallback(initCommitCallback(cb)); } boost::signals2::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb ) { - if (!mCommitSignal) mCommitSignal = new commit_signal_t(); - return mCommitSignal->connect(cb); + if (!mCommitSignal) mCommitSignal = new commit_signal_t(); + return mCommitSignal->connect(cb); } boost::signals2::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb ) { - if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); - return mMouseDownSignal->connect(cb); + if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); + return mMouseDownSignal->connect(cb); } boost::signals2::connection LLButton::setMouseUpCallback( const commit_signal_t::slot_type& cb ) { - if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); - return mMouseUpSignal->connect(cb); + if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); + return mMouseUpSignal->connect(cb); } boost::signals2::connection LLButton::setHeldDownCallback( const commit_signal_t::slot_type& cb ) { - if (!mHeldDownSignal) mHeldDownSignal = new commit_signal_t(); - return mHeldDownSignal->connect(cb); + if (!mHeldDownSignal) mHeldDownSignal = new commit_signal_t(); + return mHeldDownSignal->connect(cb); } // *TODO: Deprecate (for backwards compatibility only) boost::signals2::connection LLButton::setClickedCallback( button_callback_t cb, void* data ) { - return setClickedCallback(boost::bind(cb, data)); + return setClickedCallback(boost::bind(cb, data)); } boost::signals2::connection LLButton::setMouseDownCallback( button_callback_t cb, void* data ) { - return setMouseDownCallback(boost::bind(cb, data)); + return setMouseDownCallback(boost::bind(cb, data)); } boost::signals2::connection LLButton::setMouseUpCallback( button_callback_t cb, void* data ) { - return setMouseUpCallback(boost::bind(cb, data)); + return setMouseUpCallback(boost::bind(cb, data)); } boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb, void* data ) { - return setHeldDownCallback(boost::bind(cb, data)); + return setHeldDownCallback(boost::bind(cb, data)); } BOOL LLButton::postBuild() { - autoResize(); + autoResize(); - addBadgeToParentHolder(); + addBadgeToParentHolder(); - return LLUICtrl::postBuild(); + return LLUICtrl::postBuild(); } BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) { - BOOL handled = FALSE; - if(' ' == uni_char - && !gKeyboard->getKeyRepeated(' ')) - { - if (mIsToggle) - { - toggleState(); - } + BOOL handled = FALSE; + if(' ' == uni_char + && !gKeyboard->getKeyRepeated(' ')) + { + if (mIsToggle) + { + toggleState(); + } + + LLUICtrl::onCommit(); - LLUICtrl::onCommit(); - - handled = TRUE; - } - return handled; + handled = TRUE; + } + return handled; } BOOL LLButton::handleKeyHere(KEY key, MASK mask ) { - BOOL handled = FALSE; - if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) - { - if (mIsToggle) - { - toggleState(); - } + BOOL handled = FALSE; + if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) + { + if (mIsToggle) + { + toggleState(); + } - handled = TRUE; + handled = TRUE; - LLUICtrl::onCommit(); - } - return handled; + LLUICtrl::onCommit(); + } + return handled; } BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) { - if (!childrenHandleMouseDown(x, y, mask)) - { - // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this ); + if (!childrenHandleMouseDown(x, y, mask)) + { + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); - if (hasTabStop() && !getIsChrome()) - { - setFocus(TRUE); - } + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + + if (!mFunctionName.empty()) + { + LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL; + LLUIUsage::instance().logCommand(mFunctionName); + LLUIUsage::instance().logControl(getPathname()); + } - if (!mFunctionName.empty()) - { - LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL; - LLUIUsage::instance().logCommand(mFunctionName); - LLUIUsage::instance().logControl(getPathname()); - } + /* + * ATTENTION! This call fires another mouse down callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseDownSignal(x, y, mask); + */ + LLUICtrl::handleMouseDown(x, y, mask); - /* - * ATTENTION! This call fires another mouse down callback. - * If you wish to remove this call emit that signal directly - * by calling LLUICtrl::mMouseDownSignal(x, y, mask); - */ - LLUICtrl::handleMouseDown(x, y, mask); + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); - LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); - if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); + mMouseDownTimer.start(); + mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseHeldDownCount = 0; - mMouseDownTimer.start(); - mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); - mMouseHeldDownCount = 0; - - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } - } - return TRUE; + if (getSoundFlags() & MOUSE_DOWN) + { + make_ui_sound("UISndClick"); + } + } + return TRUE; } 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() ) - { + // 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 ); - - /* - * ATTENTION! This call fires another mouse up callback. - * If you wish to remove this call emit that signal directly - * by calling LLUICtrl::mMouseUpSignal(x, y, mask); - */ - LLUICtrl::handleMouseUp(x, y, mask); - LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); - - // Regardless of where mouseup occurs, handle callback - if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); - - // 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)) - { - if (getSoundFlags() & MOUSE_UP) - { - make_ui_sound("UISndClickRelease"); - } - - if (mIsToggle) - { - toggleState(); - } - - LLUICtrl::onCommit(); - } - } - else - { - childrenHandleMouseUp(x, y, mask); - } - - return TRUE; -} - -BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask)) - { - // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this ); - - if (hasTabStop() && !getIsChrome()) - { - setFocus(TRUE); - } - -// if (pointInView(x, y)) -// { -// } - // send the mouse down signal - LLUICtrl::handleRightMouseDown(x,y,mask); - // *TODO: Return result of LLUICtrl call above? Should defer to base class - // but this might change the mouse handling of existing buttons in a bad way - // if they are not mouse opaque. - } - - return TRUE; -} - -BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) -{ - if (mHandleRightMouse) - { - // We only handle the click if the click both started and ended within us - if( hasMouseCapture() ) - { - // Always release the mouse - gFocusMgr.setMouseCapture( NULL ); - - // if (pointInView(x, y)) - // { - // mRightMouseUpSignal(this, x,y,mask); - // } - } - else - { - childrenHandleRightMouseUp(x, y, mask); - } - - // send the mouse up signal - LLUICtrl::handleRightMouseUp(x,y,mask); - // *TODO: Return result of LLUICtrl call above? Should defer to base class - // but this might change the mouse handling of existing buttons in a bad way. - // if they are not mouse opaque. - } - return TRUE; + // Always release the mouse + gFocusMgr.setMouseCapture( NULL ); + + /* + * ATTENTION! This call fires another mouse up callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseUpSignal(x, y, mask); + */ + LLUICtrl::handleMouseUp(x, y, mask); + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + + // Regardless of where mouseup occurs, handle callback + if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + + // 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)) + { + if (getSoundFlags() & MOUSE_UP) + { + make_ui_sound("UISndClickRelease"); + } + + if (mIsToggle) + { + toggleState(); + } + + LLUICtrl::onCommit(); + } + } + else + { + childrenHandleMouseUp(x, y, mask); + } + + return TRUE; +} + +BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask)) + { + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); + + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + +// if (pointInView(x, y)) +// { +// } + // send the mouse down signal + LLUICtrl::handleRightMouseDown(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way + // if they are not mouse opaque. + } + + return TRUE; +} + +BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + if (mHandleRightMouse) + { + // We only handle the click if the click both started and ended within us + if( hasMouseCapture() ) + { + // Always release the mouse + gFocusMgr.setMouseCapture( NULL ); + + // if (pointInView(x, y)) + // { + // mRightMouseUpSignal(this, x,y,mask); + // } + } + else + { + childrenHandleRightMouseUp(x, y, mask); + } + + // send the mouse up signal + LLUICtrl::handleRightMouseUp(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way. + // if they are not mouse opaque. + } + return TRUE; } void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) { - LLUICtrl::onMouseLeave(x, y, mask); + LLUICtrl::onMouseLeave(x, y, mask); - mNeedsHighlight = FALSE; + mNeedsHighlight = FALSE; } void LLButton::setHighlight(bool b) { - mNeedsHighlight = b; + mNeedsHighlight = b; } BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) { - if (isInEnabledChain() - && (!gFocusMgr.getMouseCapture() || gFocusMgr.getMouseCapture() == this)) - mNeedsHighlight = TRUE; - - if (!childrenHandleHover(x, y, mask)) - { - if (mMouseDownTimer.getStarted()) - { - F32 elapsed = getHeldDownTime(); - if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) - { - LLSD param; - param["count"] = mMouseHeldDownCount++; - if (mHeldDownSignal) (*mHeldDownSignal)(this, param); - } - } - - // We only handle the click if the click both started and ended within us - getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << LL_ENDL; - } - return TRUE; + if (isInEnabledChain() + && (!gFocusMgr.getMouseCapture() || gFocusMgr.getMouseCapture() == this)) + mNeedsHighlight = TRUE; + + if (!childrenHandleHover(x, y, mask)) + { + if (mMouseDownTimer.getStarted()) + { + F32 elapsed = getHeldDownTime(); + if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + { + LLSD param; + param["count"] = mMouseHeldDownCount++; + if (mHeldDownSignal) (*mHeldDownSignal)(this, param); + } + } + + // We only handle the click if the click both started and ended within us + getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << LL_ENDL; + } + return TRUE; } void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height) { - overlay_width = mImageOverlay->getWidth(); - overlay_height = mImageOverlay->getHeight(); + overlay_width = mImageOverlay->getWidth(); + overlay_height = mImageOverlay->getHeight(); - F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); - overlay_width = ll_round((F32)overlay_width * scale_factor); - overlay_height = ll_round((F32)overlay_height * scale_factor); + F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); + overlay_width = ll_round((F32)overlay_width * scale_factor); + overlay_height = ll_round((F32)overlay_height * scale_factor); } // virtual void LLButton::draw() { - static LLCachedControl sEnableButtonFlashing(*LLUI::getInstance()->mSettingGroups["config"], "EnableButtonFlashing", true); - F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - - bool pressed_by_keyboard = FALSE; - if (hasFocus()) - { - pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN)); - } - - bool mouse_pressed_and_over = false; - if (hasMouseCapture()) - { - S32 local_mouse_x ; - S32 local_mouse_y; - LLUI::getInstance()->getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); - mouse_pressed_and_over = pointInView(local_mouse_x, local_mouse_y); - } - - bool enabled = isInEnabledChain(); - - bool pressed = pressed_by_keyboard - || mouse_pressed_and_over - || mForcePressedState; - bool selected = getToggleState(); - - bool use_glow_effect = FALSE; - LLColor4 highlighting_color = LLColor4::white; - LLColor4 glow_color = LLColor4::white; - LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; + static LLCachedControl sEnableButtonFlashing(*LLUI::getInstance()->mSettingGroups["config"], "EnableButtonFlashing", true); + F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); + + bool pressed_by_keyboard = FALSE; + if (hasFocus()) + { + pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN)); + } + + bool mouse_pressed_and_over = false; + if (hasMouseCapture()) + { + S32 local_mouse_x ; + S32 local_mouse_y; + LLUI::getInstance()->getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); + mouse_pressed_and_over = pointInView(local_mouse_x, local_mouse_y); + } + + bool enabled = isInEnabledChain(); + + bool pressed = pressed_by_keyboard + || mouse_pressed_and_over + || mForcePressedState; + bool selected = getToggleState(); + + bool use_glow_effect = FALSE; + LLColor4 highlighting_color = LLColor4::white; + LLColor4 glow_color = LLColor4::white; + LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; LLUIImage* imagep = NULL; LLUIImage* image_glow = NULL; // Cancel sticking of color, if the button is pressed, - // or when a flashing of the previously selected button is ended - if (mFlashingTimer - && ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed)) - { - mFlashing = false; - } - - bool flash = mFlashing && sEnableButtonFlashing; - - if (pressed && mDisplayPressedState) - { - imagep = selected ? mImagePressedSelected : mImagePressed; - } - else if ( mNeedsHighlight ) - { - if (selected) - { - if (mImageHoverSelected) - { - imagep = mImageHoverSelected; - } - else - { - imagep = mImageSelected; - use_glow_effect = TRUE; - } - } - else - { - if (mImageHoverUnselected) - { - imagep = mImageHoverUnselected; - } - else - { - imagep = mImageUnselected; - use_glow_effect = TRUE; - } - } - } - else - { - imagep = selected ? mImageSelected : mImageUnselected; - } - - // Override if more data is available - // HACK: Use gray checked state to mean either: - // enabled and tentative - // or - // disabled but checked - if (!mImageDisabledSelected.isNull() - && - ( (enabled && getTentative()) - || (!enabled && selected ) ) ) - { - imagep = mImageDisabledSelected; - } - else if (!mImageDisabled.isNull() - && !enabled - && !selected) - { - imagep = mImageDisabled; - } - - image_glow = imagep; - - if (mFlashing) - { - if (flash && mImageFlash) - { - // if button should flash and we have icon for flashing, use it as image for button - image_glow = mImageFlash; - } - - // provide fade-in and fade-out via flash_color - if (mFlashingTimer) - { - LLColor4 flash_color = mFlashBgColor.get(); - use_glow_effect = TRUE; - glow_type = LLRender::BT_ALPHA; // blend the glow - - if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress()) - { - glow_color = flash_color; - } - else if (mNeedsHighlight) - { + // or when a flashing of the previously selected button is ended + if (mFlashingTimer + && ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed)) + { + mFlashing = false; + } + + bool flash = mFlashing && sEnableButtonFlashing; + + if (pressed && mDisplayPressedState) + { + imagep = selected ? mImagePressedSelected : mImagePressed; + } + else if ( mNeedsHighlight ) + { + if (selected) + { + if (mImageHoverSelected) + { + imagep = mImageHoverSelected; + } + else + { + imagep = mImageSelected; + use_glow_effect = TRUE; + } + } + else + { + if (mImageHoverUnselected) + { + imagep = mImageHoverUnselected; + } + else + { + imagep = mImageUnselected; + use_glow_effect = TRUE; + } + } + } + else + { + imagep = selected ? mImageSelected : mImageUnselected; + } + + // Override if more data is available + // HACK: Use gray checked state to mean either: + // enabled and tentative + // or + // disabled but checked + if (!mImageDisabledSelected.isNull() + && + ( (enabled && getTentative()) + || (!enabled && selected ) ) ) + { + imagep = mImageDisabledSelected; + } + else if (!mImageDisabled.isNull() + && !enabled + && !selected) + { + imagep = mImageDisabled; + } + + image_glow = imagep; + + if (mFlashing) + { + if (flash && mImageFlash) + { + // if button should flash and we have icon for flashing, use it as image for button + image_glow = mImageFlash; + } + + // provide fade-in and fade-out via flash_color + if (mFlashingTimer) + { + LLColor4 flash_color = mFlashBgColor.get(); + use_glow_effect = TRUE; + glow_type = LLRender::BT_ALPHA; // blend the glow + + if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress()) + { + glow_color = flash_color; + } + else if (mNeedsHighlight) + { glow_color = highlighting_color; - } + } else { // will fade from highlight color glow_color = flash_color; } - } - } - - if (mNeedsHighlight && !imagep) - { - use_glow_effect = TRUE; - } - - // Figure out appropriate color for the text - LLColor4 label_color; - - // label changes when button state changes, not when pressed - if ( enabled ) - { - if ( getToggleState() ) - { - label_color = mSelectedLabelColor.get(); - } - else - { - label_color = mUnselectedLabelColor.get(); - } - } - else - { - if ( getToggleState() ) - { - label_color = mDisabledSelectedLabelColor.get(); - } - else - { - label_color = mDisabledLabelColor.get(); - } - } - - // Highlight if needed - if( ll::ui::SearchableControl::getHighlighted() ) - label_color = ll::ui::SearchableControl::getHighlightColor(); - - // Unselected label assignments - LLWString label = getCurrentLabel(); - - // overlay with keyboard focus border - if (hasFocus()) - { - F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); - drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, ll_round(lerp(1.f, 3.f, lerp_amt))); - } - - if (use_glow_effect) - { - mCurGlowStrength = lerp(mCurGlowStrength, - mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.f : 0.f) : mHoverGlowStrength, - LLSmoothInterpolation::getInterpolant(0.05f)); - } - else - { - mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); - } - - // Draw button image, if available. - // Otherwise draw basic rectangular button. - if (imagep != NULL) - { - // apply automatic 50% alpha fade to disabled image - LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); - if ( mScaleImage) - { - imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha ); - if (mCurGlowStrength > 0.01f) - { - gGL.setSceneBlendType(glow_type); - image_glow->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - } - else - { - S32 y = getLocalRect().getHeight() - imagep->getHeight(); - imagep->draw(0, y, (enabled ? mImageColor.get() : disabled_color) % alpha); - if (mCurGlowStrength > 0.01f) - { - gGL.setSceneBlendType(glow_type); - image_glow->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha)); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - } - } - else - { - // no image - LL_DEBUGS() << "No image for button " << getName() << LL_ENDL; - // draw it in pink so we can find it - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE); - } - - // let overlay image and text play well together - S32 text_left = mLeftHPad; - S32 text_right = getRect().getWidth() - mRightHPad; - S32 text_width = getRect().getWidth() - mLeftHPad - mRightHPad; - - // draw overlay image - if (mImageOverlay.notNull()) - { - // get max width and height (discard level 0) - S32 overlay_width; - S32 overlay_height; - - getOverlayImageSize(overlay_width, overlay_height); - - S32 center_x = getLocalRect().getCenterX(); - S32 center_y = getLocalRect().getCenterY(); - - //FUGLY HACK FOR "DEPRESSED" BUTTONS - if (pressed && mDisplayPressedState) - { - center_y--; - center_x++; - } - - center_y += (mImageOverlayBottomPad - mImageOverlayTopPad); - // fade out overlay images on disabled buttons - LLColor4 overlay_color = mImageOverlayColor.get(); - if (!enabled) - { - overlay_color = mImageOverlayDisabledColor.get(); - } - else if (getToggleState()) - { - overlay_color = mImageOverlaySelectedColor.get(); - } - overlay_color.mV[VALPHA] *= alpha; - - switch(mImageOverlayAlignment) - { - case LLFontGL::LEFT: - text_left += overlay_width + mImgOverlayLabelSpace; - text_width -= overlay_width + mImgOverlayLabelSpace; - mImageOverlay->draw( - mLeftHPad, - center_y - (overlay_height / 2), - overlay_width, - overlay_height, - overlay_color); - break; - case LLFontGL::HCENTER: - mImageOverlay->draw( - center_x - (overlay_width / 2), - center_y - (overlay_height / 2), - overlay_width, - overlay_height, - overlay_color); - break; - case LLFontGL::RIGHT: - text_right -= overlay_width + mImgOverlayLabelSpace; - text_width -= overlay_width + mImgOverlayLabelSpace; - mImageOverlay->draw( - getRect().getWidth() - mRightHPad - overlay_width, - center_y - (overlay_height / 2), - overlay_width, - overlay_height, - overlay_color); - break; - default: - // draw nothing - break; - } - } - - // Draw label - if( !label.empty() ) - { - LLWStringUtil::trim(label); - - S32 x; - switch( mHAlign ) - { - case LLFontGL::RIGHT: - x = text_right; - break; - case LLFontGL::HCENTER: - x = text_left + (text_width / 2); - break; - case LLFontGL::LEFT: - default: - x = text_left; - break; - } - - if (pressed && mDisplayPressedState) - { - x++; - } - - // *NOTE: mantipov: before mUseEllipses is implemented in EXT-279 U32_MAX has been passed as - // max_chars. - // LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value. - // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode. - // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. - mLastDrawCharsCount = mGLFont->render(label, 0, - (F32)x, - (F32)(getRect().getHeight() / 2 + mBottomVPad), - label_color % alpha, - mHAlign, LLFontGL::VCENTER, - LLFontGL::NORMAL, - mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, - S32_MAX, text_width, - NULL, mUseEllipses, mUseFontColor); - } - - LLUICtrl::draw(); + } + } + + if (mNeedsHighlight && !imagep) + { + use_glow_effect = TRUE; + } + + // Figure out appropriate color for the text + LLColor4 label_color; + + // label changes when button state changes, not when pressed + if ( enabled ) + { + if ( getToggleState() ) + { + label_color = mSelectedLabelColor.get(); + } + else + { + label_color = mUnselectedLabelColor.get(); + } + } + else + { + if ( getToggleState() ) + { + label_color = mDisabledSelectedLabelColor.get(); + } + else + { + label_color = mDisabledLabelColor.get(); + } + } + + // Highlight if needed + if( ll::ui::SearchableControl::getHighlighted() ) + label_color = ll::ui::SearchableControl::getHighlightColor(); + + // Unselected label assignments + LLWString label = getCurrentLabel(); + + // overlay with keyboard focus border + if (hasFocus()) + { + F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); + drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, ll_round(lerp(1.f, 3.f, lerp_amt))); + } + + if (use_glow_effect) + { + mCurGlowStrength = lerp(mCurGlowStrength, + mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.f : 0.f) : mHoverGlowStrength, + LLSmoothInterpolation::getInterpolant(0.05f)); + } + else + { + mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); + } + + // Draw button image, if available. + // Otherwise draw basic rectangular button. + if (imagep != NULL) + { + // apply automatic 50% alpha fade to disabled image + LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); + if ( mScaleImage) + { + imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha ); + if (mCurGlowStrength > 0.01f) + { + gGL.setSceneBlendType(glow_type); + image_glow->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + } + else + { + S32 y = getLocalRect().getHeight() - imagep->getHeight(); + imagep->draw(0, y, (enabled ? mImageColor.get() : disabled_color) % alpha); + if (mCurGlowStrength > 0.01f) + { + gGL.setSceneBlendType(glow_type); + image_glow->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha)); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + } + } + else + { + // no image + LL_DEBUGS() << "No image for button " << getName() << LL_ENDL; + // draw it in pink so we can find it + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE); + } + + // let overlay image and text play well together + S32 text_left = mLeftHPad; + S32 text_right = getRect().getWidth() - mRightHPad; + S32 text_width = getRect().getWidth() - mLeftHPad - mRightHPad; + + // draw overlay image + if (mImageOverlay.notNull()) + { + // get max width and height (discard level 0) + S32 overlay_width; + S32 overlay_height; + + getOverlayImageSize(overlay_width, overlay_height); + + S32 center_x = getLocalRect().getCenterX(); + S32 center_y = getLocalRect().getCenterY(); + + //FUGLY HACK FOR "DEPRESSED" BUTTONS + if (pressed && mDisplayPressedState) + { + center_y--; + center_x++; + } + + center_y += (mImageOverlayBottomPad - mImageOverlayTopPad); + // fade out overlay images on disabled buttons + LLColor4 overlay_color = mImageOverlayColor.get(); + if (!enabled) + { + overlay_color = mImageOverlayDisabledColor.get(); + } + else if (getToggleState()) + { + overlay_color = mImageOverlaySelectedColor.get(); + } + overlay_color.mV[VALPHA] *= alpha; + + switch(mImageOverlayAlignment) + { + case LLFontGL::LEFT: + text_left += overlay_width + mImgOverlayLabelSpace; + text_width -= overlay_width + mImgOverlayLabelSpace; + mImageOverlay->draw( + mLeftHPad, + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + overlay_color); + break; + case LLFontGL::HCENTER: + mImageOverlay->draw( + center_x - (overlay_width / 2), + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + overlay_color); + break; + case LLFontGL::RIGHT: + text_right -= overlay_width + mImgOverlayLabelSpace; + text_width -= overlay_width + mImgOverlayLabelSpace; + mImageOverlay->draw( + getRect().getWidth() - mRightHPad - overlay_width, + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + overlay_color); + break; + default: + // draw nothing + break; + } + } + + // Draw label + if( !label.empty() ) + { + LLWStringUtil::trim(label); + + S32 x; + switch( mHAlign ) + { + case LLFontGL::RIGHT: + x = text_right; + break; + case LLFontGL::HCENTER: + x = text_left + (text_width / 2); + break; + case LLFontGL::LEFT: + default: + x = text_left; + break; + } + + if (pressed && mDisplayPressedState) + { + x++; + } + + // *NOTE: mantipov: before mUseEllipses is implemented in EXT-279 U32_MAX has been passed as + // max_chars. + // LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value. + // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode. + // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. + mLastDrawCharsCount = mGLFont->render(label, 0, + (F32)x, + (F32)(getRect().getHeight() / 2 + mBottomVPad), + label_color % alpha, + mHAlign, LLFontGL::VCENTER, + LLFontGL::NORMAL, + mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, + S32_MAX, text_width, + NULL, mUseEllipses, mUseFontColor); + } + + LLUICtrl::draw(); } void LLButton::drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size) { - if (imagep == NULL) return; - if (mScaleImage) - { - imagep->drawBorder(getLocalRect(), color, size); - } - else - { - S32 y = getLocalRect().getHeight() - imagep->getHeight(); - imagep->drawBorder(0, y, color, size); - } + if (imagep == NULL) return; + if (mScaleImage) + { + imagep->drawBorder(getLocalRect(), color, size); + } + else + { + S32 y = getLocalRect().getHeight() - imagep->getHeight(); + imagep->drawBorder(0, y, color, size); + } } BOOL LLButton::getToggleState() const @@ -990,214 +990,214 @@ BOOL LLButton::getToggleState() const void LLButton::setToggleState(BOOL b) { - if( b != getToggleState() ) - { - setControlValue(b); // will fire LLControlVariable callbacks (if any) - setValue(b); // may or may not be redundant - setFlashing(false); // stop flash state whenever the selected/unselected state if reset - // Unselected label assignments - autoResize(); - } + if( b != getToggleState() ) + { + setControlValue(b); // will fire LLControlVariable callbacks (if any) + setValue(b); // may or may not be redundant + setFlashing(false); // stop flash state whenever the selected/unselected state if reset + // Unselected label assignments + autoResize(); + } } void LLButton::setFlashing(bool b, bool force_flashing/* = false */) -{ - mForceFlashing = force_flashing; - if (mFlashingTimer) - { - mFlashing = b; - (b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing()); - } - else if (b != mFlashing) - { - mFlashing = b; - mFrameTimer.reset(); - } -} - -BOOL LLButton::toggleState() +{ + mForceFlashing = force_flashing; + if (mFlashingTimer) + { + mFlashing = b; + (b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing()); + } + else if (b != mFlashing) + { + mFlashing = b; + mFrameTimer.reset(); + } +} + +BOOL LLButton::toggleState() { bool flipped = ! getToggleState(); - setToggleState(flipped); + setToggleState(flipped); - return flipped; + return flipped; } void LLButton::setLabel( const std::string& label ) { - mUnselectedLabel = mSelectedLabel = label; + mUnselectedLabel = mSelectedLabel = label; } void LLButton::setLabel( const LLUIString& label ) { - mUnselectedLabel = mSelectedLabel = label; + mUnselectedLabel = mSelectedLabel = label; } void LLButton::setLabel( const LLStringExplicit& label ) { - setLabelUnselected(label); - setLabelSelected(label); + setLabelUnselected(label); + setLabelSelected(label); } //virtual BOOL LLButton::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - mUnselectedLabel.setArg(key, text); - mSelectedLabel.setArg(key, text); - return TRUE; + mUnselectedLabel.setArg(key, text); + mSelectedLabel.setArg(key, text); + return TRUE; } void LLButton::setLabelUnselected( const LLStringExplicit& label ) { - mUnselectedLabel = label; + mUnselectedLabel = label; } void LLButton::setLabelSelected( const LLStringExplicit& label ) { - mSelectedLabel = label; + mSelectedLabel = label; } bool LLButton::labelIsTruncated() const { - return getCurrentLabel().getString().size() > mLastDrawCharsCount; + return getCurrentLabel().getString().size() > mLastDrawCharsCount; } const LLUIString& LLButton::getCurrentLabel() const { - return getToggleState() ? mSelectedLabel : mUnselectedLabel; + return getToggleState() ? mSelectedLabel : mUnselectedLabel; } void LLButton::setImageUnselected(LLPointer image) { - mImageUnselected = image; - if (mImageUnselected.isNull()) - { - LL_WARNS() << "Setting default button image for: " << getName() << " to NULL" << LL_ENDL; - } + mImageUnselected = image; + if (mImageUnselected.isNull()) + { + LL_WARNS() << "Setting default button image for: " << getName() << " to NULL" << LL_ENDL; + } } void LLButton::autoResize() { - resize(getCurrentLabel()); + resize(getCurrentLabel()); } void LLButton::resize(LLUIString label) { - // get label length - S32 label_width = mGLFont->getWidth(label.getString()); - // get current btn length - S32 btn_width =getRect().getWidth(); - // check if it need resize - if (mAutoResize) - { - S32 min_width = label_width + mLeftHPad + mRightHPad; - if (mImageOverlay) - { - S32 overlay_width = mImageOverlay->getWidth(); - F32 scale_factor = (getRect().getHeight() - (mImageOverlayBottomPad + mImageOverlayTopPad)) / (F32)mImageOverlay->getHeight(); - overlay_width = ll_round((F32)overlay_width * scale_factor); - - switch(mImageOverlayAlignment) - { - case LLFontGL::LEFT: - case LLFontGL::RIGHT: - min_width += overlay_width + mImgOverlayLabelSpace; - break; - case LLFontGL::HCENTER: - min_width = llmax(min_width, overlay_width + mLeftHPad + mRightHPad); - break; - default: - // draw nothing - break; - } - } - if (btn_width < min_width) - { - reshape(min_width, getRect().getHeight()); - } - } + // get label length + S32 label_width = mGLFont->getWidth(label.getString()); + // get current btn length + S32 btn_width =getRect().getWidth(); + // check if it need resize + if (mAutoResize) + { + S32 min_width = label_width + mLeftHPad + mRightHPad; + if (mImageOverlay) + { + S32 overlay_width = mImageOverlay->getWidth(); + F32 scale_factor = (getRect().getHeight() - (mImageOverlayBottomPad + mImageOverlayTopPad)) / (F32)mImageOverlay->getHeight(); + overlay_width = ll_round((F32)overlay_width * scale_factor); + + switch(mImageOverlayAlignment) + { + case LLFontGL::LEFT: + case LLFontGL::RIGHT: + min_width += overlay_width + mImgOverlayLabelSpace; + break; + case LLFontGL::HCENTER: + min_width = llmax(min_width, overlay_width + mLeftHPad + mRightHPad); + break; + default: + // draw nothing + break; + } + } + if (btn_width < min_width) + { + reshape(min_width, getRect().getHeight()); + } + } } void LLButton::setImages( const std::string &image_name, const std::string &selected_name ) { - setImageUnselected(LLUI::getUIImage(image_name)); - setImageSelected(LLUI::getUIImage(selected_name)); + setImageUnselected(LLUI::getUIImage(image_name)); + setImageSelected(LLUI::getUIImage(selected_name)); } void LLButton::setImageSelected(LLPointer image) { - mImageSelected = image; + mImageSelected = image; } -void LLButton::setImageColor(const LLColor4& c) -{ - mImageColor = c; +void LLButton::setImageColor(const LLColor4& c) +{ + mImageColor = c; } void LLButton::setColor(const LLColor4& color) { - setImageColor(color); + setImageColor(color); } void LLButton::setImageDisabled(LLPointer image) { - mImageDisabled = image; - mDisabledImageColor = mImageColor; - mFadeWhenDisabled = TRUE; + mImageDisabled = image; + mDisabledImageColor = mImageColor; + mFadeWhenDisabled = TRUE; } void LLButton::setImageDisabledSelected(LLPointer image) { - mImageDisabledSelected = image; - mDisabledImageColor = mImageColor; - mFadeWhenDisabled = TRUE; + mImageDisabledSelected = image; + mDisabledImageColor = mImageColor; + mFadeWhenDisabled = TRUE; } void LLButton::setImagePressed(LLPointer image) { - mImagePressed = image; + mImagePressed = image; } void LLButton::setImageHoverSelected(LLPointer image) { - mImageHoverSelected = image; + mImageHoverSelected = image; } void LLButton::setImageHoverUnselected(LLPointer image) { - mImageHoverUnselected = image; + mImageHoverUnselected = image; } void LLButton::setImageFlash(LLPointer image) { - mImageFlash = image; + mImageFlash = image; } void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment, const LLColor4& color) { - if (image_name.empty()) - { - mImageOverlay = NULL; - } - else - { - mImageOverlay = LLUI::getUIImage(image_name); - mImageOverlayAlignment = alignment; - mImageOverlayColor = color; - } + if (image_name.empty()) + { + mImageOverlay = NULL; + } + else + { + mImageOverlay = LLUI::getUIImage(image_name); + mImageOverlayAlignment = alignment; + mImageOverlayColor = color; + } } void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color) { - if (image_id.isNull()) - { - mImageOverlay = NULL; - } - else - { - mImageOverlay = LLUI::getUIImageByID(image_id); - mImageOverlayAlignment = alignment; - mImageOverlayColor = color; - } + if (image_id.isNull()) + { + mImageOverlay = NULL; + } + else + { + mImageOverlay = LLUI::getUIImageByID(image_id); + mImageOverlayAlignment = alignment; + mImageOverlayColor = color; + } } void LLButton::onMouseCaptureLost() @@ -1214,7 +1214,7 @@ void LLButton::onMouseCaptureLost() LLUICtrl::onCommit(); } - resetMouseDownTimer(); + resetMouseDownTimer(); } //------------------------------------------------------------------------- @@ -1222,99 +1222,99 @@ void LLButton::onMouseCaptureLost() //------------------------------------------------------------------------- S32 round_up(S32 grid, S32 value) { - S32 mod = value % grid; + S32 mod = value % grid; - if (mod > 0) - { - // not even multiple - return value + (grid - mod); - } - else - { - return value; - } + if (mod > 0) + { + // not even multiple + return value + (grid - mod); + } + else + { + return value; + } } -void LLButton::addImageAttributeToXML(LLXMLNodePtr node, - const std::string& image_name, - const LLUUID& image_id, - const std::string& xml_tag_name) const +void LLButton::addImageAttributeToXML(LLXMLNodePtr node, + const std::string& image_name, + const LLUUID& image_id, + const std::string& xml_tag_name) const { - if( !image_name.empty() ) - { - node->createChild(xml_tag_name.c_str(), TRUE)->setStringValue(image_name); - } - else if( image_id != LLUUID::null ) - { - node->createChild((xml_tag_name + "_id").c_str(), TRUE)->setUUIDValue(image_id); - } + if( !image_name.empty() ) + { + node->createChild(xml_tag_name.c_str(), TRUE)->setStringValue(image_name); + } + else if( image_id != LLUUID::null ) + { + node->createChild((xml_tag_name + "_id").c_str(), TRUE)->setUUIDValue(image_id); + } } // static void LLButton::toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname) { - bool floater_vis = LLFloaterReg::toggleInstance(sdname.asString()); - LLButton* button = dynamic_cast(ctrl); - if (button) - button->setToggleState(floater_vis); + bool floater_vis = LLFloaterReg::toggleInstance(sdname.asString()); + LLButton* button = dynamic_cast(ctrl); + if (button) + button->setToggleState(floater_vis); } // static // Gets called once void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname) { - LLButton* button = dynamic_cast(ctrl); - if (!button) - return; - // Get the visibility control name for the floater - std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); - // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) - button->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name)); - // Set the clicked callback to toggle the floater - button->setClickedCallback(boost::bind(&LLFloaterReg::toggleInstance, sdname, LLSD())); + LLButton* button = dynamic_cast(ctrl); + if (!button) + return; + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) + button->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name)); + // Set the clicked callback to toggle the floater + button->setClickedCallback(boost::bind(&LLFloaterReg::toggleInstance, sdname, LLSD())); } // static void LLButton::setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname) { - LLButton* button = dynamic_cast(ctrl); - if (!button) - return; - // Get the visibility control name for the floater - std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); - // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) - button->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name)); - // Set the clicked callback to toggle the floater - button->setClickedCallback(boost::bind(&LLDockableFloater::toggleInstance, sdname)); + LLButton* button = dynamic_cast(ctrl); + if (!button) + return; + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) + button->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name)); + // Set the clicked callback to toggle the floater + button->setClickedCallback(boost::bind(&LLDockableFloater::toggleInstance, sdname)); } // static void LLButton::showHelp(LLUICtrl* ctrl, const LLSD& sdname) { - // search back through the button's parents for a panel - // with a help_topic string defined - std::string help_topic; - if (LLUI::getInstance()->mHelpImpl && - ctrl->findHelpTopic(help_topic)) - { - LLUI::getInstance()->mHelpImpl->showTopic(help_topic); - return; // success - } + // search back through the button's parents for a panel + // with a help_topic string defined + std::string help_topic; + if (LLUI::getInstance()->mHelpImpl && + ctrl->findHelpTopic(help_topic)) + { + LLUI::getInstance()->mHelpImpl->showTopic(help_topic); + return; // success + } - // display an error if we can't find a help_topic string. - // fix this by adding a help_topic attribute to the xui file - LLNotificationsUtil::add("UnableToFindHelpTopic"); + // display an error if we can't find a help_topic string. + // fix this by adding a help_topic attribute to the xui file + LLNotificationsUtil::add("UnableToFindHelpTopic"); } void LLButton::resetMouseDownTimer() { - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); } BOOL LLButton::handleDoubleClick(S32 x, S32 y, MASK mask) { - // just treat a double click as a second click - return handleMouseDown(x, y, mask); + // just treat a double click as a second click + return handleMouseDown(x, y, mask); } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 257159f64f..7054074fd8 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -1,25 +1,25 @@ -/** +/** * @file llbutton.h * @brief Header for buttons * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,9 +44,9 @@ // PLEASE please use these "constants" when building your own buttons. // They are loaded from settings.xml at run time. -extern S32 LLBUTTON_H_PAD; -extern S32 BTN_HEIGHT_SMALL; -extern S32 BTN_HEIGHT; +extern S32 LLBUTTON_H_PAD; +extern S32 BTN_HEIGHT_SMALL; +extern S32 BTN_HEIGHT; // // Helpful functions @@ -65,342 +65,342 @@ class LLButton , public ll::ui::SearchableControl { public: - struct Params - : public LLInitParam::Block - { - // text label - Optional label_selected; - Optional label_shadow; - Optional auto_resize; - Optional use_ellipses; - Optional use_font_color; - - // images - Optional image_unselected, - image_selected, - image_hover_selected, - image_hover_unselected, - image_disabled_selected, - image_disabled, - image_flash, - image_pressed, - image_pressed_selected, - image_overlay; - - Optional image_overlay_alignment; - - // colors - Optional label_color, - label_color_selected, - label_color_disabled, - label_color_disabled_selected, - image_color, - image_color_disabled, - image_overlay_color, - image_overlay_selected_color, - image_overlay_disabled_color, - flash_color; - - // layout - Optional pad_right; - Optional pad_left; - Optional pad_bottom; // under text label - - //image overlay paddings - Optional image_top_pad; - Optional image_bottom_pad; - - /** - * Space between image_overlay and label - */ - Optional imgoverlay_label_space; - - // callbacks - Optional click_callback, // alias -> commit_callback - mouse_down_callback, - mouse_up_callback, - mouse_held_callback; - - // misc - Optional is_toggle, - scale_image, - commit_on_return, - commit_on_capture_lost, - display_pressed_state; - - Optional hover_glow_amount; - Optional held_down_delay; - - Optional use_draw_context_alpha; - - Optional badge; - - Optional handle_right_mouse; - - Optional button_flash_enable; - Optional button_flash_count; - Optional button_flash_rate; - - Params(); - }; - + struct Params + : public LLInitParam::Block + { + // text label + Optional label_selected; + Optional label_shadow; + Optional auto_resize; + Optional use_ellipses; + Optional use_font_color; + + // images + Optional image_unselected, + image_selected, + image_hover_selected, + image_hover_unselected, + image_disabled_selected, + image_disabled, + image_flash, + image_pressed, + image_pressed_selected, + image_overlay; + + Optional image_overlay_alignment; + + // colors + Optional label_color, + label_color_selected, + label_color_disabled, + label_color_disabled_selected, + image_color, + image_color_disabled, + image_overlay_color, + image_overlay_selected_color, + image_overlay_disabled_color, + flash_color; + + // layout + Optional pad_right; + Optional pad_left; + Optional pad_bottom; // under text label + + //image overlay paddings + Optional image_top_pad; + Optional image_bottom_pad; + + /** + * Space between image_overlay and label + */ + Optional imgoverlay_label_space; + + // callbacks + Optional click_callback, // alias -> commit_callback + mouse_down_callback, + mouse_up_callback, + mouse_held_callback; + + // misc + Optional is_toggle, + scale_image, + commit_on_return, + commit_on_capture_lost, + display_pressed_state; + + Optional hover_glow_amount; + Optional held_down_delay; + + Optional use_draw_context_alpha; + + Optional badge; + + Optional handle_right_mouse; + + Optional button_flash_enable; + Optional button_flash_count; + Optional button_flash_rate; + + Params(); + }; + protected: - friend class LLUICtrlFactory; - LLButton(const Params&); + friend class LLUICtrlFactory; + LLButton(const Params&); public: - ~LLButton(); - // For backward compatability only - typedef boost::function button_callback_t; - - void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, - const LLUUID& imageID,const std::string& xmlTagName) const; - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual void draw(); - /*virtual*/ BOOL postBuild(); - - virtual void onMouseLeave(S32 x, S32 y, MASK mask); - virtual void onMouseCaptureLost(); - - virtual void onCommit(); - - void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; } - void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; } - void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; } - void setUseFontColor( BOOL use_font_color) { mUseFontColor = use_font_color; } - - - boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb); - boost::signals2::connection setMouseDownCallback(const CommitCallbackParam& cb); - boost::signals2::connection setMouseUpCallback(const CommitCallbackParam& cb); - boost::signals2::connection setHeldDownCallback(const CommitCallbackParam& cb); - - boost::signals2::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button - boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); - boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON - // Passes a 'count' parameter in the commit param payload, i.e. param["count"]) - boost::signals2::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button - - - // *TODO: Deprecate (for backwards compatability only) - boost::signals2::connection setClickedCallback( button_callback_t cb, void* data ); - boost::signals2::connection setMouseDownCallback( button_callback_t cb, void* data ); - boost::signals2::connection setMouseUpCallback( button_callback_t cb, void* data ); - boost::signals2::connection setHeldDownCallback( button_callback_t cb, void* data ); - - void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } - - F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } - - BOOL toggleState(); - BOOL getToggleState() const; - void setToggleState(BOOL b); - - void setHighlight(bool b); - void setFlashing( bool b, bool force_flashing = false ); - BOOL getFlashing() const { return mFlashing; } + ~LLButton(); + // For backward compatability only + typedef boost::function button_callback_t; + + void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, + const LLUUID& imageID,const std::string& xmlTagName) const; + virtual BOOL handleUnicodeCharHere(llwchar uni_char); + virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual void draw(); + /*virtual*/ BOOL postBuild(); + + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual void onMouseCaptureLost(); + + virtual void onCommit(); + + void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; } + void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; } + void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; } + void setUseFontColor( BOOL use_font_color) { mUseFontColor = use_font_color; } + + + boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb); + boost::signals2::connection setMouseDownCallback(const CommitCallbackParam& cb); + boost::signals2::connection setMouseUpCallback(const CommitCallbackParam& cb); + boost::signals2::connection setHeldDownCallback(const CommitCallbackParam& cb); + + boost::signals2::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button + boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON + // Passes a 'count' parameter in the commit param payload, i.e. param["count"]) + boost::signals2::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button + + + // *TODO: Deprecate (for backwards compatability only) + boost::signals2::connection setClickedCallback( button_callback_t cb, void* data ); + boost::signals2::connection setMouseDownCallback( button_callback_t cb, void* data ); + boost::signals2::connection setMouseUpCallback( button_callback_t cb, void* data ); + boost::signals2::connection setHeldDownCallback( button_callback_t cb, void* data ); + + void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } + + F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } + + BOOL toggleState(); + BOOL getToggleState() const; + void setToggleState(BOOL b); + + void setHighlight(bool b); + void setFlashing( bool b, bool force_flashing = false ); + BOOL getFlashing() const { return mFlashing; } LLFlashTimer* getFlashTimer() {return mFlashingTimer;} - void setFlashColor(const LLUIColor &color) { mFlashBgColor = color; }; - - void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } - LLFontGL::HAlign getHAlign() const { return mHAlign; } - void setLeftHPad( S32 pad ) { mLeftHPad = pad; } - void setRightHPad( S32 pad ) { mRightHPad = pad; } - - void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; } - S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; } - void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; } - S32 getImageOverlayBottomPad() const { return mImageOverlayBottomPad; } - - const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); } - const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } - - void setImageColor(const std::string& color_control); - void setImageColor(const LLColor4& c); - /*virtual*/ void setColor(const LLColor4& c); - - void setImages(const std::string &image_name, const std::string &selected_name); - - void setDisabledImageColor(const LLColor4& c) { mDisabledImageColor = c; } - - void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; } - - void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); - void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); - LLPointer getImageOverlay() { return mImageOverlay; } - LLFontGL::HAlign getImageOverlayHAlign() const { return mImageOverlayAlignment; } - - void autoResize(); // resize with label of current btn state - void resize(LLUIString label); // resize with label input - void setLabel(const std::string& label); - void setLabel(const LLUIString& label); - void setLabel( const LLStringExplicit& label); - virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - void setLabelUnselected(const LLStringExplicit& label); - void setLabelSelected(const LLStringExplicit& label); - void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; } - - void setFont(const LLFontGL *font) - { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } - const LLFontGL* getFont() const { return mGLFont; } - - - S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; } - bool labelIsTruncated() const; - const LLUIString& getCurrentLabel() const; - - void setScaleImage(BOOL scale) { mScaleImage = scale; } - BOOL getScaleImage() const { return mScaleImage; } - - void setDropShadowedText(BOOL b) { mDropShadowedText = b; } - - void setBorderEnabled(BOOL b) { mBorderEnabled = b; } - - void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } - - void setImageUnselected(LLPointer image); - void setImageSelected(LLPointer image); - void setImageHoverSelected(LLPointer image); - void setImageHoverUnselected(LLPointer image); - void setImageDisabled(LLPointer image); - void setImageDisabledSelected(LLPointer image); - void setImageFlash(LLPointer image); - void setImagePressed(LLPointer image); - - void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } - BOOL getCommitOnReturn() const { return mCommitOnReturn; } - - static void onHeldDown(void *userdata); // to be called by gIdleCallbacks - static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname); - static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); - static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); - static void showHelp(LLUICtrl* ctrl, const LLSD& sdname); - - void setForcePressedState(bool b) { mForcePressedState = b; } - - void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; } + void setFlashColor(const LLUIColor &color) { mFlashBgColor = color; }; + + void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } + LLFontGL::HAlign getHAlign() const { return mHAlign; } + void setLeftHPad( S32 pad ) { mLeftHPad = pad; } + void setRightHPad( S32 pad ) { mRightHPad = pad; } + + void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; } + S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; } + void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; } + S32 getImageOverlayBottomPad() const { return mImageOverlayBottomPad; } + + const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); } + const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } + + void setImageColor(const std::string& color_control); + void setImageColor(const LLColor4& c); + /*virtual*/ void setColor(const LLColor4& c); + + void setImages(const std::string &image_name, const std::string &selected_name); + + void setDisabledImageColor(const LLColor4& c) { mDisabledImageColor = c; } + + void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; } + + void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); + void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); + LLPointer getImageOverlay() { return mImageOverlay; } + LLFontGL::HAlign getImageOverlayHAlign() const { return mImageOverlayAlignment; } + + void autoResize(); // resize with label of current btn state + void resize(LLUIString label); // resize with label input + void setLabel(const std::string& label); + void setLabel(const LLUIString& label); + void setLabel( const LLStringExplicit& label); + virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + void setLabelUnselected(const LLStringExplicit& label); + void setLabelSelected(const LLStringExplicit& label); + void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; } + + void setFont(const LLFontGL *font) + { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } + const LLFontGL* getFont() const { return mGLFont; } + + + S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; } + bool labelIsTruncated() const; + const LLUIString& getCurrentLabel() const; + + void setScaleImage(BOOL scale) { mScaleImage = scale; } + BOOL getScaleImage() const { return mScaleImage; } + + void setDropShadowedText(BOOL b) { mDropShadowedText = b; } + + void setBorderEnabled(BOOL b) { mBorderEnabled = b; } + + void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } + + void setImageUnselected(LLPointer image); + void setImageSelected(LLPointer image); + void setImageHoverSelected(LLPointer image); + void setImageHoverUnselected(LLPointer image); + void setImageDisabled(LLPointer image); + void setImageDisabledSelected(LLPointer image); + void setImageFlash(LLPointer image); + void setImagePressed(LLPointer image); + + void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } + BOOL getCommitOnReturn() const { return mCommitOnReturn; } + + static void onHeldDown(void *userdata); // to be called by gIdleCallbacks + static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname); + static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); + static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); + static void showHelp(LLUICtrl* ctrl, const LLSD& sdname); + + void setForcePressedState(bool b) { mForcePressedState = b; } + + void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; } protected: - LLPointer getImageUnselected() const { return mImageUnselected; } - LLPointer getImageSelected() const { return mImageSelected; } - void getOverlayImageSize(S32& overlay_width, S32& overlay_height); - - LLFrameTimer mMouseDownTimer; - bool mNeedsHighlight; - S32 mButtonFlashCount; - F32 mButtonFlashRate; - - void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); - void resetMouseDownTimer(); - - commit_signal_t* mMouseDownSignal; - commit_signal_t* mMouseUpSignal; - commit_signal_t* mHeldDownSignal; - - const LLFontGL* mGLFont; - - S32 mMouseDownFrame; - S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback - F32 mHeldDownDelay; // seconds, after which held-down callbacks get called - S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called - S32 mLastDrawCharsCount; - - LLPointer mImageOverlay; - LLFontGL::HAlign mImageOverlayAlignment; - LLUIColor mImageOverlayColor; - LLUIColor mImageOverlaySelectedColor; - LLUIColor mImageOverlayDisabledColor; - - LLPointer mImageUnselected; - LLUIString mUnselectedLabel; - LLUIColor mUnselectedLabelColor; - - LLPointer mImageSelected; - LLUIString mSelectedLabel; - LLUIColor mSelectedLabelColor; - - LLPointer mImageHoverSelected; - - LLPointer mImageHoverUnselected; - - LLPointer mImageDisabled; - LLUIColor mDisabledLabelColor; - - LLPointer mImageDisabledSelected; - LLUIString mDisabledSelectedLabel; - LLUIColor mDisabledSelectedLabelColor; - - LLPointer mImagePressed; - LLPointer mImagePressedSelected; - - /* There are two ways an image can flash- by making changes in color according to flash_color attribute - or by changing icon from current to the one specified in image_flash. Second way is used only if - flash icon name is set in attributes(by default it isn't). First way is used otherwise. */ - LLPointer mImageFlash; - - LLUIColor mFlashBgColor; - - LLUIColor mImageColor; - LLUIColor mDisabledImageColor; - - bool mIsToggle; - bool mScaleImage; - - bool mDropShadowedText; - bool mAutoResize; - bool mUseEllipses; - bool mUseFontColor; - bool mBorderEnabled; - bool mFlashing; - - LLFontGL::HAlign mHAlign; - S32 mLeftHPad; - S32 mRightHPad; - S32 mBottomVPad; // under text label - - S32 mImageOverlayTopPad; - S32 mImageOverlayBottomPad; - - bool mUseDrawContextAlpha; - - /* - * Space between image_overlay and label - */ - S32 mImgOverlayLabelSpace; - - F32 mHoverGlowStrength; - F32 mCurGlowStrength; - - bool mCommitOnReturn; - bool mCommitOnCaptureLost; - bool mFadeWhenDisabled; - bool mForcePressedState; - bool mDisplayPressedState; - - LLFrameTimer mFrameTimer; - LLFlashTimer * mFlashingTimer; - bool mForceFlashing; // Stick flashing color even if button is pressed - bool mHandleRightMouse; + LLPointer getImageUnselected() const { return mImageUnselected; } + LLPointer getImageSelected() const { return mImageSelected; } + void getOverlayImageSize(S32& overlay_width, S32& overlay_height); + + LLFrameTimer mMouseDownTimer; + bool mNeedsHighlight; + S32 mButtonFlashCount; + F32 mButtonFlashRate; + + void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); + void resetMouseDownTimer(); + + commit_signal_t* mMouseDownSignal; + commit_signal_t* mMouseUpSignal; + commit_signal_t* mHeldDownSignal; + + const LLFontGL* mGLFont; + + S32 mMouseDownFrame; + S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback + F32 mHeldDownDelay; // seconds, after which held-down callbacks get called + S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called + S32 mLastDrawCharsCount; + + LLPointer mImageOverlay; + LLFontGL::HAlign mImageOverlayAlignment; + LLUIColor mImageOverlayColor; + LLUIColor mImageOverlaySelectedColor; + LLUIColor mImageOverlayDisabledColor; + + LLPointer mImageUnselected; + LLUIString mUnselectedLabel; + LLUIColor mUnselectedLabelColor; + + LLPointer mImageSelected; + LLUIString mSelectedLabel; + LLUIColor mSelectedLabelColor; + + LLPointer mImageHoverSelected; + + LLPointer mImageHoverUnselected; + + LLPointer mImageDisabled; + LLUIColor mDisabledLabelColor; + + LLPointer mImageDisabledSelected; + LLUIString mDisabledSelectedLabel; + LLUIColor mDisabledSelectedLabelColor; + + LLPointer mImagePressed; + LLPointer mImagePressedSelected; + + /* There are two ways an image can flash- by making changes in color according to flash_color attribute + or by changing icon from current to the one specified in image_flash. Second way is used only if + flash icon name is set in attributes(by default it isn't). First way is used otherwise. */ + LLPointer mImageFlash; + + LLUIColor mFlashBgColor; + + LLUIColor mImageColor; + LLUIColor mDisabledImageColor; + + bool mIsToggle; + bool mScaleImage; + + bool mDropShadowedText; + bool mAutoResize; + bool mUseEllipses; + bool mUseFontColor; + bool mBorderEnabled; + bool mFlashing; + + LLFontGL::HAlign mHAlign; + S32 mLeftHPad; + S32 mRightHPad; + S32 mBottomVPad; // under text label + + S32 mImageOverlayTopPad; + S32 mImageOverlayBottomPad; + + bool mUseDrawContextAlpha; + + /* + * Space between image_overlay and label + */ + S32 mImgOverlayLabelSpace; + + F32 mHoverGlowStrength; + F32 mCurGlowStrength; + + bool mCommitOnReturn; + bool mCommitOnCaptureLost; + bool mFadeWhenDisabled; + bool mForcePressedState; + bool mDisplayPressedState; + + LLFrameTimer mFrameTimer; + LLFlashTimer * mFlashingTimer; + bool mForceFlashing; // Stick flashing color even if button is pressed + bool mHandleRightMouse; protected: - virtual std::string _getSearchText() const - { - return getLabelUnselected() + getToolTip(); - } + virtual std::string _getSearchText() const + { + return getLabelUnselected() + getToolTip(); + } }; // Build time optimization, generate once in .cpp file #ifndef LLBUTTON_CPP extern template class LLButton* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; #endif #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index 0a10877c09..07775dc30f 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -1,25 +1,25 @@ -/** +/** * @file llcallbackmap.h * @brief LLCallbackMap base class * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,25 +34,25 @@ class LLCallbackMap { public: - // callback definition. - typedef boost::function callback_t; - - typedef std::map map_t; - typedef map_t::iterator map_iter_t; - typedef map_t::const_iterator map_const_iter_t; - - template - static void* buildPanel(void* data) - { - T* panel = new T(); - return (void*)panel; - } - - LLCallbackMap() : mCallback(NULL), mData(NULL) { } - LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } - - callback_t mCallback; - void* mData; + // callback definition. + typedef boost::function callback_t; + + typedef std::map map_t; + typedef map_t::iterator map_iter_t; + typedef map_t::const_iterator map_const_iter_t; + + template + static void* buildPanel(void* data) + { + T* panel = new T(); + return (void*)panel; + } + + LLCallbackMap() : mCallback(NULL), mData(NULL) { } + LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } + + callback_t mCallback; + void* mData; }; #endif // LLCALLBACKMAP_H diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h index b4fd5f60aa..56105add7e 100644 --- a/indra/llui/llchat.h +++ b/indra/llui/llchat.h @@ -1,4 +1,4 @@ -/** +/** * @file llchat.h * @author James Cook * @brief Chat constants and data structures. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,79 +34,79 @@ // enumerations used by the chat system typedef enum e_chat_source_type { - CHAT_SOURCE_SYSTEM = 0, - CHAT_SOURCE_AGENT = 1, - CHAT_SOURCE_OBJECT = 2, - CHAT_SOURCE_TELEPORT = 3, - CHAT_SOURCE_UNKNOWN = 4, - CHAT_SOURCE_REGION = 5, + CHAT_SOURCE_SYSTEM = 0, + CHAT_SOURCE_AGENT = 1, + CHAT_SOURCE_OBJECT = 2, + CHAT_SOURCE_TELEPORT = 3, + CHAT_SOURCE_UNKNOWN = 4, + CHAT_SOURCE_REGION = 5, } EChatSourceType; typedef enum e_chat_type { - CHAT_TYPE_WHISPER = 0, - CHAT_TYPE_NORMAL = 1, - CHAT_TYPE_SHOUT = 2, - CHAT_TYPE_START = 4, - CHAT_TYPE_STOP = 5, - CHAT_TYPE_DEBUG_MSG = 6, - CHAT_TYPE_REGION = 7, - CHAT_TYPE_OWNER = 8, - CHAT_TYPE_DIRECT = 9 // From llRegionSayTo() + CHAT_TYPE_WHISPER = 0, + CHAT_TYPE_NORMAL = 1, + CHAT_TYPE_SHOUT = 2, + CHAT_TYPE_START = 4, + CHAT_TYPE_STOP = 5, + CHAT_TYPE_DEBUG_MSG = 6, + CHAT_TYPE_REGION = 7, + CHAT_TYPE_OWNER = 8, + CHAT_TYPE_DIRECT = 9 // From llRegionSayTo() } EChatType; typedef enum e_chat_audible_level { - CHAT_AUDIBLE_NOT = -1, - CHAT_AUDIBLE_BARELY = 0, - CHAT_AUDIBLE_FULLY = 1 + CHAT_AUDIBLE_NOT = -1, + CHAT_AUDIBLE_BARELY = 0, + CHAT_AUDIBLE_FULLY = 1 } EChatAudible; typedef enum e_chat_style { - CHAT_STYLE_NORMAL, - CHAT_STYLE_IRC, - CHAT_STYLE_HISTORY, - CHAT_STYLE_TELEPORT_SEP + CHAT_STYLE_NORMAL, + CHAT_STYLE_IRC, + CHAT_STYLE_HISTORY, + CHAT_STYLE_TELEPORT_SEP }EChatStyle; // A piece of chat class LLChat { public: - LLChat(const std::string& text = std::string()) - : mText(text), - mFromName(), - mFromID(), - mNotifId(), - mOwnerID(), - mSourceType(CHAT_SOURCE_AGENT), - mChatType(CHAT_TYPE_NORMAL), - mAudible(CHAT_AUDIBLE_FULLY), - mMuted(FALSE), - mTime(0.0), - mTimeStr(), - mPosAgent(), - mURL(), - mChatStyle(CHAT_STYLE_NORMAL), - mSessionID() - { } - - std::string mText; // UTF-8 line of text - std::string mFromName; // agent or object name - LLUUID mFromID; // agent id or object id - LLUUID mNotifId; - LLUUID mOwnerID; - EChatSourceType mSourceType; - EChatType mChatType; - EChatAudible mAudible; - BOOL mMuted; // pass muted chat to maintain list of chatters - F64 mTime; // viewer only, seconds from viewer start - std::string mTimeStr; - LLVector3 mPosAgent; - std::string mURL; - EChatStyle mChatStyle; - LLUUID mSessionID; + LLChat(const std::string& text = std::string()) + : mText(text), + mFromName(), + mFromID(), + mNotifId(), + mOwnerID(), + mSourceType(CHAT_SOURCE_AGENT), + mChatType(CHAT_TYPE_NORMAL), + mAudible(CHAT_AUDIBLE_FULLY), + mMuted(FALSE), + mTime(0.0), + mTimeStr(), + mPosAgent(), + mURL(), + mChatStyle(CHAT_STYLE_NORMAL), + mSessionID() + { } + + std::string mText; // UTF-8 line of text + std::string mFromName; // agent or object name + LLUUID mFromID; // agent id or object id + LLUUID mNotifId; + LLUUID mOwnerID; + EChatSourceType mSourceType; + EChatType mChatType; + EChatAudible mAudible; + BOOL mMuted; // pass muted chat to maintain list of chatters + F64 mTime; // viewer only, seconds from viewer start + std::string mTimeStr; + LLVector3 mPosAgent; + std::string mURL; + EChatStyle mChatStyle; + LLUUID mSessionID; }; #endif diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index c506576126..8a8b9e7461 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -32,117 +32,117 @@ static LLDefaultChildRegistry::Register r("chat_editor"); LLChatEntry::Params::Params() -: has_history("has_history", true), - is_expandable("is_expandable", false), - expand_lines_count("expand_lines_count", 1) +: has_history("has_history", true), + is_expandable("is_expandable", false), + expand_lines_count("expand_lines_count", 1) {} LLChatEntry::LLChatEntry(const Params& p) -: LLTextEditor(p), - mTextExpandedSignal(NULL), - mHasHistory(p.has_history), - mIsExpandable(p.is_expandable), - mExpandLinesCount(p.expand_lines_count), - mPrevLinesCount(0), - mSingleLineMode(false), - mPrevExpandedLineCount(S32_MAX) +: LLTextEditor(p), + mTextExpandedSignal(NULL), + mHasHistory(p.has_history), + mIsExpandable(p.is_expandable), + mExpandLinesCount(p.expand_lines_count), + mPrevLinesCount(0), + mSingleLineMode(false), + mPrevExpandedLineCount(S32_MAX) { - // Initialize current history line iterator - mCurrentHistoryLine = mLineHistory.begin(); + // Initialize current history line iterator + mCurrentHistoryLine = mLineHistory.begin(); - mAutoIndent = false; - keepSelectionOnReturn(true); + mAutoIndent = false; + keepSelectionOnReturn(true); } LLChatEntry::~LLChatEntry() { - delete mTextExpandedSignal; + delete mTextExpandedSignal; } void LLChatEntry::draw() { - if(mIsExpandable) - { - reflow(); - expandText(); - } - LLTextEditor::draw(); + if(mIsExpandable) + { + reflow(); + expandText(); + } + LLTextEditor::draw(); } void LLChatEntry::onCommit() { - updateHistory(); - LLTextEditor::onCommit(); + updateHistory(); + LLTextEditor::onCommit(); } boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_signal_t::slot_type& cb) { - if (!mTextExpandedSignal) - { - mTextExpandedSignal = new commit_signal_t(); - } - return mTextExpandedSignal->connect(cb); + if (!mTextExpandedSignal) + { + mTextExpandedSignal = new commit_signal_t(); + } + return mTextExpandedSignal->connect(cb); } void LLChatEntry::expandText() { - S32 line_count = mSingleLineMode ? 1 : mExpandLinesCount; - - int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second); - bool can_changed = getLineCount() <= line_count || line_count < mPrevExpandedLineCount ; - mPrevExpandedLineCount = line_count; - - // true if pasted text has more lines than expand height limit and expand limit is not reached yet - bool text_pasted = (getLineCount() > line_count) && (visible_lines_count < line_count); - - if (mIsExpandable && (can_changed || text_pasted || mSingleLineMode) && getLineCount() != mPrevLinesCount) - { - int lines_height = 0; - if (text_pasted) - { - // text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty, - // so lines_height is the sum of the last 'expanded_line_count' lines height - lines_height = (mLineInfoList.end() - line_count)->mRect.mTop - mLineInfoList.back().mRect.mBottom; - } - else - { - lines_height = mLineInfoList.begin()->mRect.mTop - mLineInfoList.back().mRect.mBottom; - } - - int height = mVPad * 2 + lines_height; - - LLRect doc_rect = getRect(); - doc_rect.setOriginAndSize(doc_rect.mLeft, doc_rect.mBottom, doc_rect.getWidth(), height); - setShape(doc_rect); - - mPrevLinesCount = getLineCount(); - - if (mTextExpandedSignal) - { - (*mTextExpandedSignal)(this, LLSD() ); - } - - needsReflow(); - } + S32 line_count = mSingleLineMode ? 1 : mExpandLinesCount; + + int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second); + bool can_changed = getLineCount() <= line_count || line_count < mPrevExpandedLineCount ; + mPrevExpandedLineCount = line_count; + + // true if pasted text has more lines than expand height limit and expand limit is not reached yet + bool text_pasted = (getLineCount() > line_count) && (visible_lines_count < line_count); + + if (mIsExpandable && (can_changed || text_pasted || mSingleLineMode) && getLineCount() != mPrevLinesCount) + { + int lines_height = 0; + if (text_pasted) + { + // text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty, + // so lines_height is the sum of the last 'expanded_line_count' lines height + lines_height = (mLineInfoList.end() - line_count)->mRect.mTop - mLineInfoList.back().mRect.mBottom; + } + else + { + lines_height = mLineInfoList.begin()->mRect.mTop - mLineInfoList.back().mRect.mBottom; + } + + int height = mVPad * 2 + lines_height; + + LLRect doc_rect = getRect(); + doc_rect.setOriginAndSize(doc_rect.mLeft, doc_rect.mBottom, doc_rect.getWidth(), height); + setShape(doc_rect); + + mPrevLinesCount = getLineCount(); + + if (mTextExpandedSignal) + { + (*mTextExpandedSignal)(this, LLSD() ); + } + + needsReflow(); + } } // line history support void LLChatEntry::updateHistory() { - // On history enabled, remember committed line and - // reset current history line number. - // Be sure only to remember lines that are not empty and that are - // different from the last on the list. - if (mHasHistory && getLength()) - { - // Add text to history, ignoring duplicates - if (mLineHistory.empty() || getText() != mLineHistory.back()) - { - mLineHistory.push_back(getText()); - } - - mCurrentHistoryLine = mLineHistory.end(); - } + // On history enabled, remember committed line and + // reset current history line number. + // Be sure only to remember lines that are not empty and that are + // different from the last on the list. + if (mHasHistory && getLength()) + { + // Add text to history, ignoring duplicates + if (mLineHistory.empty() || getText() != mLineHistory.back()) + { + mLineHistory.push_back(getText()); + } + + mCurrentHistoryLine = mLineHistory.end(); + } } void LLChatEntry::beforeValueChange() @@ -166,86 +166,86 @@ bool LLChatEntry::useLabel() const void LLChatEntry::onFocusReceived() { - LLUICtrl::onFocusReceived(); - updateAllowingLanguageInput(); + LLUICtrl::onFocusReceived(); + updateAllowingLanguageInput(); } void LLChatEntry::onFocusLost() { - LLTextEditor::focusLostHelper(); - LLUICtrl::onFocusLost(); + LLTextEditor::focusLostHelper(); + LLUICtrl::onFocusLost(); } BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { - BOOL handled = FALSE; - - LLTextEditor::handleSpecialKey(key, mask); - - switch(key) - { - case KEY_RETURN: - if (MASK_NONE == mask) - { - needsReflow(); - } - break; - - case KEY_UP: - if (mHasHistory && MASK_CONTROL == mask) - { - if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin()) - { - setText(*(--mCurrentHistoryLine)); - endOfDoc(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - case KEY_DOWN: - if (mHasHistory && MASK_CONTROL == mask) - { - if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) ) - { - setText(*(++mCurrentHistoryLine)); - endOfDoc(); - } - else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) ) - { - mCurrentHistoryLine++; - std::string empty(""); - setText(empty); - needsReflow(); - endOfDoc(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - default: - break; - } - - return handled; + BOOL handled = FALSE; + + LLTextEditor::handleSpecialKey(key, mask); + + switch(key) + { + case KEY_RETURN: + if (MASK_NONE == mask) + { + needsReflow(); + } + break; + + case KEY_UP: + if (mHasHistory && MASK_CONTROL == mask) + { + if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin()) + { + setText(*(--mCurrentHistoryLine)); + endOfDoc(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + case KEY_DOWN: + if (mHasHistory && MASK_CONTROL == mask) + { + if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) ) + { + setText(*(++mCurrentHistoryLine)); + endOfDoc(); + } + else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) ) + { + mCurrentHistoryLine++; + std::string empty(""); + setText(empty); + needsReflow(); + endOfDoc(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + default: + break; + } + + return handled; } void LLChatEntry::enableSingleLineMode(bool single_line_mode) { - if (mScroller) - { - mScroller->setSize(single_line_mode ? 0 : -1); - } - - mSingleLineMode = single_line_mode; - mPrevLinesCount = -1; - setWordWrap(!single_line_mode); + if (mScroller) + { + mScroller->setSize(single_line_mode ? 0 : -1); + } + + mSingleLineMode = single_line_mode; + mPrevLinesCount = -1; + setWordWrap(!single_line_mode); } diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 3f13691a30..f7473b320d 100644 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -4,8 +4,8 @@ * @brief Text editor widget which is used for user input * * Features: - * Optional line history so previous entries can be recalled by CTRL UP/DOWN - * Optional auto-resize behavior on input chat field + * Optional line history so previous entries can be recalled by CTRL UP/DOWN + * Optional auto-resize behavior on input chat field * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -38,69 +38,69 @@ class LLChatEntry : public LLTextEditor { public: - struct Params : public LLInitParam::Block - { - Optional has_history, - is_expandable; + struct Params : public LLInitParam::Block + { + Optional has_history, + is_expandable; - Optional expand_lines_count; + Optional expand_lines_count; - Params(); - }; + Params(); + }; - virtual ~LLChatEntry(); + virtual ~LLChatEntry(); protected: - friend class LLUICtrlFactory; - LLChatEntry(const Params& p); + friend class LLUICtrlFactory; + LLChatEntry(const Params& p); /*virtual*/ void beforeValueChange(); /*virtual*/ void onValueChange(S32 start, S32 end); /*virtual*/ bool useLabel() const; public: - virtual void draw(); - virtual void onCommit(); - /*virtual*/ void onFocusReceived(); - /*virtual*/ void onFocusLost(); + virtual void draw(); + virtual void onCommit(); + /*virtual*/ void onFocusReceived(); + /*virtual*/ void onFocusLost(); - void enableSingleLineMode(bool single_line_mode); - boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); + void enableSingleLineMode(bool single_line_mode); + boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); private: - /** - * Implements auto-resize behavior. - * When user's typing reaches the right edge of the chat field - * the chat field expands vertically by one line. The bottom of - * the chat field remains bottom-justified. The chat field does - * not expand beyond mExpandLinesCount. - */ - void expandText(); - - /** - * Implements line history so previous entries can be recalled by CTRL UP/DOWN - */ - void updateHistory(); - - BOOL handleSpecialKey(const KEY key, const MASK mask); - - - // Fired when text height expanded to mExpandLinesCount - commit_signal_t* mTextExpandedSignal; - - // line history support: - typedef std::vector line_history_t; - line_history_t::iterator mCurrentHistoryLine; // currently browsed history line - line_history_t mLineHistory; // line history storage - bool mHasHistory; // flag for enabled/disabled line history - bool mIsExpandable; - bool mSingleLineMode; - - S32 mExpandLinesCount; - S32 mPrevLinesCount; - S32 mPrevExpandedLineCount; + /** + * Implements auto-resize behavior. + * When user's typing reaches the right edge of the chat field + * the chat field expands vertically by one line. The bottom of + * the chat field remains bottom-justified. The chat field does + * not expand beyond mExpandLinesCount. + */ + void expandText(); + + /** + * Implements line history so previous entries can be recalled by CTRL UP/DOWN + */ + void updateHistory(); + + BOOL handleSpecialKey(const KEY key, const MASK mask); + + + // Fired when text height expanded to mExpandLinesCount + commit_signal_t* mTextExpandedSignal; + + // line history support: + typedef std::vector line_history_t; + line_history_t::iterator mCurrentHistoryLine; // currently browsed history line + line_history_t mLineHistory; // line history storage + bool mHasHistory; // flag for enabled/disabled line history + bool mIsExpandable; + bool mSingleLineMode; + + S32 mExpandLinesCount; + S32 mPrevLinesCount; + S32 mPrevExpandedLineCount; }; #endif /* LLCHATENTRY_H_ */ diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 362fe0c19e..8ba37a8075 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcheckboxctrl.cpp * @brief LLCheckBoxCtrl base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,7 +45,7 @@ static LLDefaultChildRegistry::Register r("check_box"); // Compiler optimization, generate extern template template class LLCheckBoxCtrl* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; void LLCheckBoxCtrl::WordWrap::declareValues() { @@ -55,44 +55,44 @@ void LLCheckBoxCtrl::WordWrap::declareValues() } LLCheckBoxCtrl::Params::Params() -: initial_value("initial_value", false), - label_text("label_text"), - check_button("check_button"), - word_wrap("word_wrap", EWordWrap::WRAP_NONE), - radio_style("radio_style") +: initial_value("initial_value", false), + label_text("label_text"), + check_button("check_button"), + word_wrap("word_wrap", EWordWrap::WRAP_NONE), + radio_style("radio_style") {} LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) -: LLUICtrl(p), - mTextEnabledColor(p.label_text.text_color()), - mTextDisabledColor(p.label_text.text_readonly_color()), - mFont(p.font()), - mWordWrap(p.word_wrap) +: LLUICtrl(p), + mTextEnabledColor(p.label_text.text_color()), + mTextDisabledColor(p.label_text.text_readonly_color()), + mFont(p.font()), + mWordWrap(p.word_wrap) { - mViewModel->setValue(LLSD(p.initial_value)); - mViewModel->resetDirty(); - static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); - static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); - static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); - - // must be big enough to hold all children - setUseBoundingRect(TRUE); - - // *HACK Get rid of this with SL-55508... - // this allows blank check boxes and radio boxes for now - std::string local_label = p.label; - if(local_label.empty()) - { - local_label = " "; - } - - LLTextBox::Params tbparams = p.label_text; - tbparams.initial_value(local_label); - if (p.font.isProvided()) - { - tbparams.font(p.font); - } + mViewModel->setValue(LLSD(p.initial_value)); + mViewModel->resetDirty(); + static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); + static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); + static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); + + // must be big enough to hold all children + setUseBoundingRect(TRUE); + + // *HACK Get rid of this with SL-55508... + // this allows blank check boxes and radio boxes for now + std::string local_label = p.label; + if(local_label.empty()) + { + local_label = " "; + } + + LLTextBox::Params tbparams = p.label_text; + tbparams.initial_value(local_label); + if (p.font.isProvided()) + { + tbparams.font(p.font); + } mLabel = LLUICtrlFactory::create(tbparams); if (mWordWrap != WRAP_NONE) @@ -104,11 +104,11 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) label_rect.mRight = label_rect.mLeft + new_width; mLabel->setRect(label_rect); } - mLabel->reshapeToFitText(); + mLabel->reshapeToFitText(); - LLRect label_rect = mLabel->getRect(); - if (mLabel->getLineCount() > 1) - { + LLRect label_rect = mLabel->getRect(); + if (mLabel->getLineCount() > 1) + { if (mWordWrap == WRAP_DOWN) { // reshapeToFitText uses LLView::reshape() which always reshapes @@ -122,67 +122,67 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) // WRAP_UP is essentially done by reshapeToFitText() (extends from bottom to top) // howhever it doesn't respect rect of checkbox // todo: this should be fixed, but there are at least couple checkboxes that use this feature as is. - } - - addChild(mLabel); - - // Button - // Note: button cover the label by extending all the way to the right and down. - LLRect btn_rect = p.check_button.rect(); - btn_rect.setOriginAndSize( - btn_rect.mLeft, - llmin(btn_rect.mBottom, label_rect.mBottom), - llmax(btn_rect.mRight, label_rect.mRight - btn_rect.mLeft), - llmax(label_rect.getHeight(), btn_rect.mTop)); - std::string active_true_id, active_false_id; - std::string inactive_true_id, inactive_false_id; - - LLButton::Params params = p.check_button; - params.rect(btn_rect); - //params.control_name(p.control_name); - params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onCommit, this)); - params.commit_on_return(false); - // Checkboxes only allow boolean initial values, but buttons can - // take any LLSD. - params.initial_value(LLSD(p.initial_value)); - params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); - - mButton = LLUICtrlFactory::create(params); - addChild(mButton); + } + + addChild(mLabel); + + // Button + // Note: button cover the label by extending all the way to the right and down. + LLRect btn_rect = p.check_button.rect(); + btn_rect.setOriginAndSize( + btn_rect.mLeft, + llmin(btn_rect.mBottom, label_rect.mBottom), + llmax(btn_rect.mRight, label_rect.mRight - btn_rect.mLeft), + llmax(label_rect.getHeight(), btn_rect.mTop)); + std::string active_true_id, active_false_id; + std::string inactive_true_id, inactive_false_id; + + LLButton::Params params = p.check_button; + params.rect(btn_rect); + //params.control_name(p.control_name); + params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onCommit, this)); + params.commit_on_return(false); + // Checkboxes only allow boolean initial values, but buttons can + // take any LLSD. + params.initial_value(LLSD(p.initial_value)); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + + mButton = LLUICtrlFactory::create(params); + addChild(mButton); } LLCheckBoxCtrl::~LLCheckBoxCtrl() { - // Children all cleaned up by default view destructor. + // Children all cleaned up by default view destructor. } void LLCheckBoxCtrl::onCommit() { - if( getEnabled() ) - { - setTentative(FALSE); - setControlValue(getValue()); - LLUICtrl::onCommit(); - } + if( getEnabled() ) + { + setTentative(FALSE); + setControlValue(getValue()); + LLUICtrl::onCommit(); + } } void LLCheckBoxCtrl::setEnabled(BOOL b) { - LLView::setEnabled(b); - - if (b) - { - mLabel->setColor( mTextEnabledColor.get() ); - } - else - { - mLabel->setColor( mTextDisabledColor.get() ); - } + LLView::setEnabled(b); + + if (b) + { + mLabel->setColor( mTextEnabledColor.get() ); + } + else + { + mLabel->setColor( mTextDisabledColor.get() ); + } } void LLCheckBoxCtrl::clear() { - setValue( FALSE ); + setValue( FALSE ); } void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -202,34 +202,34 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) // reshapeToFitText reshapes label to minimal size according to last bounding box // it will work fine in case of decrease of space, but if we get more space or text // becomes longer, label will fail to grow so reinit label's dimentions. - + LLRect label_rect = mLabel->getRect(); S32 new_width = rect.getWidth() - label_rect.mLeft; mLabel->reshape(new_width, label_rect.getHeight(), TRUE); - S32 label_top = label_rect.mTop; - mLabel->reshapeToFitText(TRUE); + S32 label_top = label_rect.mTop; + mLabel->reshapeToFitText(TRUE); label_rect = mLabel->getRect(); - if (label_top != label_rect.mTop && mWordWrap == WRAP_DOWN) - { - // reshapeToFitText uses LLView::reshape() which always reshapes - // from bottom to top, but we want to extend the bottom so - // reposition control - S32 delta = label_top - label_rect.mTop; - label_rect.translate(0, delta); - mLabel->setRect(label_rect); - } - - // Button - // Note: button cover the label by extending all the way to the right and down. - LLRect btn_rect = mButton->getRect(); - btn_rect.setOriginAndSize( - btn_rect.mLeft, - llmin(btn_rect.mBottom, label_rect.mBottom), - llmax(btn_rect.getWidth(), label_rect.mRight - btn_rect.mLeft), - llmax(label_rect.mTop - btn_rect.mBottom, btn_rect.getHeight())); - mButton->setShape(btn_rect); + if (label_top != label_rect.mTop && mWordWrap == WRAP_DOWN) + { + // reshapeToFitText uses LLView::reshape() which always reshapes + // from bottom to top, but we want to extend the bottom so + // reposition control + S32 delta = label_top - label_rect.mTop; + label_rect.translate(0, delta); + mLabel->setRect(label_rect); + } + + // Button + // Note: button cover the label by extending all the way to the right and down. + LLRect btn_rect = mButton->getRect(); + btn_rect.setOriginAndSize( + btn_rect.mLeft, + llmin(btn_rect.mBottom, label_rect.mBottom), + llmax(btn_rect.getWidth(), label_rect.mRight - btn_rect.mLeft), + llmax(label_rect.mTop - btn_rect.mBottom, btn_rect.getHeight())); + mButton->setShape(btn_rect); updateBoundingRect(); } @@ -237,68 +237,68 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) //virtual void LLCheckBoxCtrl::setValue(const LLSD& value ) { - mButton->setValue( value ); + mButton->setValue( value ); } //virtual LLSD LLCheckBoxCtrl::getValue() const { - return mButton->getValue(); + return mButton->getValue(); } //virtual void LLCheckBoxCtrl::setTentative(BOOL b) { - mButton->setTentative(b); + mButton->setTentative(b); } //virtual BOOL LLCheckBoxCtrl::getTentative() const { - return mButton->getTentative(); + return mButton->getTentative(); } void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label ) { - mLabel->setText( label ); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + mLabel->setText( label ); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); } std::string LLCheckBoxCtrl::getLabel() const { - return mLabel->getText(); + return mLabel->getText(); } BOOL LLCheckBoxCtrl::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - BOOL res = mLabel->setTextArg(key, text); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); - return res; + BOOL res = mLabel->setTextArg(key, text); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + return res; } // virtual void LLCheckBoxCtrl::setControlName(const std::string& control_name, LLView* context) { - mButton->setControlName(control_name, context); + mButton->setControlName(control_name, context); } -// virtual Returns TRUE if the user has modified this control. -BOOL LLCheckBoxCtrl::isDirty() const +// virtual Returns TRUE if the user has modified this control. +BOOL LLCheckBoxCtrl::isDirty() const { - if ( mButton ) - { - return mButton->isDirty(); - } - return FALSE; // Shouldn't get here + if ( mButton ) + { + return mButton->isDirty(); + } + return FALSE; // Shouldn't get here } -// virtual Clear dirty state -void LLCheckBoxCtrl::resetDirty() +// virtual Clear dirty state +void LLCheckBoxCtrl::resetDirty() { - if ( mButton ) - { - mButton->resetDirty(); - } + if ( mButton ) + { + mButton->resetDirty(); + } } diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index eb5bd5b6da..43e887fab6 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -1,25 +1,25 @@ -/** +/** * @file llcheckboxctrl.h * @brief LLCheckBoxCtrl base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,8 +36,8 @@ // Constants // -const BOOL RADIO_STYLE = TRUE; -const BOOL CHECK_STYLE = FALSE; +const BOOL RADIO_STYLE = TRUE; +const BOOL CHECK_STYLE = FALSE; // // Classes @@ -63,95 +63,95 @@ public: static void declareValues(); }; - struct Params - : public LLInitParam::Block - { - Optional initial_value; // override LLUICtrl initial_value + struct Params + : public LLInitParam::Block + { + Optional initial_value; // override LLUICtrl initial_value - Optional label_text; - Optional check_button; + Optional label_text; + Optional check_button; - Optional word_wrap; + Optional word_wrap; - Ignored radio_style; + Ignored radio_style; - Params(); - }; + Params(); + }; - virtual ~LLCheckBoxCtrl(); + virtual ~LLCheckBoxCtrl(); protected: - LLCheckBoxCtrl(const Params&); - friend class LLUICtrlFactory; + LLCheckBoxCtrl(const Params&); + friend class LLUICtrlFactory; public: - // LLView interface + // LLView interface + + virtual void setEnabled( BOOL b ); - virtual void setEnabled( BOOL b ); + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + // LLUICtrl interface + virtual void setValue(const LLSD& value ); + virtual LLSD getValue() const; + BOOL get() { return (BOOL)getValue().asBoolean(); } + void set(BOOL value) { setValue(value); } - // LLUICtrl interface - virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; - BOOL get() { return (BOOL)getValue().asBoolean(); } - void set(BOOL value) { setValue(value); } + virtual void setTentative(BOOL b); + virtual BOOL getTentative() const; - virtual void setTentative(BOOL b); - virtual BOOL getTentative() const; + virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + virtual void clear(); + virtual void onCommit(); - virtual void clear(); - virtual void onCommit(); + // LLCheckBoxCtrl interface + virtual BOOL toggle() { return mButton->toggleState(); } // returns new state - // LLCheckBoxCtrl interface - virtual BOOL toggle() { return mButton->toggleState(); } // returns new state + void setBtnFocus() { mButton->setFocus(TRUE); } - void setBtnFocus() { mButton->setFocus(TRUE); } + void setEnabledColor( const LLColor4 &color ) { mTextEnabledColor = color; } + void setDisabledColor( const LLColor4 &color ) { mTextDisabledColor = color; } - void setEnabledColor( const LLColor4 &color ) { mTextEnabledColor = color; } - void setDisabledColor( const LLColor4 &color ) { mTextDisabledColor = color; } + void setLabel( const LLStringExplicit& label ); + std::string getLabel() const; - void setLabel( const LLStringExplicit& label ); - std::string getLabel() const; + void setFont( const LLFontGL* font ) { mFont = font; } + const LLFontGL* getFont() { return mFont; } - void setFont( const LLFontGL* font ) { mFont = font; } - const LLFontGL* getFont() { return mFont; } - - virtual void setControlName(const std::string& control_name, LLView* context); + virtual void setControlName(const std::string& control_name, LLView* context); - virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. - virtual void resetDirty(); // Clear dirty state + virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. + virtual void resetDirty(); // Clear dirty state protected: - virtual std::string _getSearchText() const - { - return getLabel() + getToolTip(); - } + virtual std::string _getSearchText() const + { + return getLabel() + getToolTip(); + } - virtual void onSetHighlight() const // When highlight, really do highlight the label - { - if( mLabel ) - mLabel->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() ); - } + virtual void onSetHighlight() const // When highlight, really do highlight the label + { + if( mLabel ) + mLabel->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() ); + } protected: - // note: value is stored in toggle state of button - LLButton* mButton; - LLTextBox* mLabel; - const LLFontGL* mFont; + // note: value is stored in toggle state of button + LLButton* mButton; + LLTextBox* mLabel; + const LLFontGL* mFont; - LLUIColor mTextEnabledColor; - LLUIColor mTextDisabledColor; + LLUIColor mTextEnabledColor; + LLUIColor mTextDisabledColor; - EWordWrap mWordWrap; // off, shifts text up, shifts text down + EWordWrap mWordWrap; // off, shifts text up, shifts text down }; // Build time optimization, generate once in .cpp file #ifndef LLCHECKBOXCTRL_CPP extern template class LLCheckBoxCtrl* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; #endif #endif // LL_LLCHECKBOXCTRL_H diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp index 06fac190ed..5132d33bbf 100644 --- a/indra/llui/llclipboard.cpp +++ b/indra/llui/llclipboard.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llclipboard.cpp * @brief LLClipboard base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,121 +35,121 @@ #include "llwindow.h" LLClipboard::LLClipboard() : - mGeneration(0) + mGeneration(0) { - reset(); + reset(); } LLClipboard::~LLClipboard() { - reset(); + reset(); } void LLClipboard::reset() { - // Increment the clipboard count - mGeneration++; - // Clear the clipboard - mObjects.clear(); - mCutMode = false; - mString = LLWString(); + // Increment the clipboard count + mGeneration++; + // Clear the clipboard + mObjects.clear(); + mCutMode = false; + mString = LLWString(); } // Copy the input uuid to the LL clipboard bool LLClipboard::copyToClipboard(const LLUUID& src, const LLAssetType::EType type) { - reset(); - return addToClipboard(src, type); + reset(); + return addToClipboard(src, type); } // Add the input uuid to the LL clipboard // Convert the uuid to string and concatenate that string to the system clipboard if legit bool LLClipboard::addToClipboard(const LLUUID& src, const LLAssetType::EType type) { - bool res = false; - if (src.notNull()) - { - res = true; - if (LLAssetType::lookupIsAssetIDKnowable(type)) - { - LLWString source = utf8str_to_wstring(src.asString()); - res = addToClipboard(source, 0, source.size()); - } - if (res) - { - mObjects.push_back(src); - mGeneration++; - } - } - return res; + bool res = false; + if (src.notNull()) + { + res = true; + if (LLAssetType::lookupIsAssetIDKnowable(type)) + { + LLWString source = utf8str_to_wstring(src.asString()); + res = addToClipboard(source, 0, source.size()); + } + if (res) + { + mObjects.push_back(src); + mGeneration++; + } + } + return res; } bool LLClipboard::pasteFromClipboard(std::vector& inv_objects) const { - bool res = false; - S32 count = mObjects.size(); - inv_objects.reserve(inv_objects.size() + count); - if (count > 0) - { - res = true; - inv_objects.clear(); - for (S32 i = 0; i < count; i++) - { - inv_objects.push_back(mObjects[i]); - } - } - return res; + bool res = false; + S32 count = mObjects.size(); + inv_objects.reserve(inv_objects.size() + count); + if (count > 0) + { + res = true; + inv_objects.clear(); + for (S32 i = 0; i < count; i++) + { + inv_objects.push_back(mObjects[i]); + } + } + return res; } // Returns true if the LL Clipboard has pasteable items in it bool LLClipboard::hasContents() const { - return (mObjects.size() > 0); + return (mObjects.size() > 0); } // Returns true if the input uuid is in the list of clipboard objects bool LLClipboard::isOnClipboard(const LLUUID& object) const { - std::vector::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); - return (iter != mObjects.end()); + std::vector::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); + return (iter != mObjects.end()); } // Copy the input string to the LL and the system clipboard bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) { - return addToClipboard(src, pos, len, use_primary); + return addToClipboard(src, pos, len, use_primary); } // Concatenate the input string to the LL and the system clipboard bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) { - try - { - mString = src.substr(pos, len); - } - catch (const std::exception& e) - { - LL_WARNS() << "Can't add the substring to clipboard: " << e.what() << LL_ENDL; - return false; - } - return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString)); + try + { + mString = src.substr(pos, len); + } + catch (const std::exception& e) + { + LL_WARNS() << "Can't add the substring to clipboard: " << e.what() << LL_ENDL; + return false; + } + return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString)); } // Copy the System clipboard to the output string. // Manage the LL Clipboard / System clipboard consistency bool LLClipboard::pasteFromClipboard(LLWString &dst, bool use_primary) { - bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst)); - if (res) - { - mString = dst; - } - return res; + bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst)); + if (res) + { + mString = dst; + } + return res; } // Return true if there's something on the System clipboard bool LLClipboard::isTextAvailable(bool use_primary) const { - return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable()); + return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable()); } diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index a668ac1ac6..12d8233e0a 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -1,25 +1,25 @@ -/** +/** * @file llclipboard.h * @brief LLClipboard base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,56 +38,56 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLClipboard // -// This class is used to cut/copy/paste text strings and inventory items around +// This class is used to cut/copy/paste text strings and inventory items around // the world. Use LLClipboard::instance().method() to use its methods. // Note that the text and UUIDs are loosely coupled only. There are few cases // where the viewer does offer a serialized version of the UUID on the clipboard. -// In those case, the text is overridden when copying/cutting the item. +// In those case, the text is overridden when copying/cutting the item. // In all other cases, the text and the UUIDs are very much independent. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLClipboard : public LLSingleton { - LLSINGLETON(LLClipboard); - ~LLClipboard(); - + LLSINGLETON(LLClipboard); + ~LLClipboard(); + public: - // Clears the clipboard - void reset(); - // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) - int getGeneration() const { return mGeneration; } + // Clears the clipboard + void reset(); + // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) + int getGeneration() const { return mGeneration; } + + // Text strings management: + // ------------------------ + // We support two flavors of text clipboards. The default is the explicitly + // copy-and-pasted clipboard. The second is the so-called 'primary' clipboard + // which is implicitly copied upon selection on platforms which expect this + // (i.e. X11/Linux, Mac). + bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool pasteFromClipboard(LLWString& dst, bool use_primary = false); + bool isTextAvailable(bool use_primary = false) const; + + // Object list management: + // ----------------------- + // Clears and adds one single object to the clipboard + bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Adds one object to the current list of objects on the clipboard + bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Gets a copy of the objects on the clipboard + bool pasteFromClipboard(std::vector& inventory_objects) const; - // Text strings management: - // ------------------------ - // We support two flavors of text clipboards. The default is the explicitly - // copy-and-pasted clipboard. The second is the so-called 'primary' clipboard - // which is implicitly copied upon selection on platforms which expect this - // (i.e. X11/Linux, Mac). - bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); - bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); - bool pasteFromClipboard(LLWString& dst, bool use_primary = false); - bool isTextAvailable(bool use_primary = false) const; - - // Object list management: - // ----------------------- - // Clears and adds one single object to the clipboard - bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); - // Adds one object to the current list of objects on the clipboard - bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); - // Gets a copy of the objects on the clipboard - bool pasteFromClipboard(std::vector& inventory_objects) const; - - bool hasContents() const; // True if the clipboard has pasteable objects - bool isOnClipboard(const LLUUID& object) const; // True if the input object uuid is on the clipboard + bool hasContents() const; // True if the clipboard has pasteable objects + bool isOnClipboard(const LLUUID& object) const; // True if the input object uuid is on the clipboard - bool isCutMode() const { return mCutMode; } - void setCutMode(bool mode) { mCutMode = mode; mGeneration++; } + bool isCutMode() const { return mCutMode; } + void setCutMode(bool mode) { mCutMode = mode; mGeneration++; } private: - std::vector mObjects; // Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat) - LLWString mString; // The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment) if the asset type is knowable. - bool mCutMode; // This is a convenience flag for the viewer. - int mGeneration; // Incremented when the clipboard changes so that interested parties can check for changes on the clipboard. + std::vector mObjects; // Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat) + LLWString mString; // The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment) if the asset type is knowable. + bool mCutMode; // This is a convenience flag for the viewer. + int mGeneration; // Incremented when the clipboard changes so that interested parties can check for changes on the clipboard. }; #endif // LL_LLCLIPBOARD_H diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 9ca05a16f3..1573ccb0d7 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcombobox.cpp * @brief LLComboBox base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -58,274 +58,274 @@ static LLDefaultChildRegistry::Register register_combo_box("combo_bo void LLComboBox::PreferredPositionValues::declareValues() { - declare("above", ABOVE); - declare("below", BELOW); + declare("above", ABOVE); + declare("below", BELOW); } LLComboBox::ItemParams::ItemParams() -: label("label") +: label("label") { } LLComboBox::Params::Params() -: allow_text_entry("allow_text_entry", false), - allow_new_values("allow_new_values", false), - show_text_as_tentative("show_text_as_tentative", true), - max_chars("max_chars", 20), - list_position("list_position", BELOW), - items("item"), - combo_button("combo_button"), - combo_list("combo_list"), - combo_editor("combo_editor"), - drop_down_button("drop_down_button") +: allow_text_entry("allow_text_entry", false), + allow_new_values("allow_new_values", false), + show_text_as_tentative("show_text_as_tentative", true), + max_chars("max_chars", 20), + list_position("list_position", BELOW), + items("item"), + combo_button("combo_button"), + combo_list("combo_list"), + combo_editor("combo_editor"), + drop_down_button("drop_down_button") { - addSynonym(items, "combo_item"); + addSynonym(items, "combo_item"); } LLComboBox::LLComboBox(const LLComboBox::Params& p) -: LLUICtrl(p), - mTextEntry(NULL), - mTextEntryTentative(p.show_text_as_tentative), - mHasAutocompletedText(false), - mAllowTextEntry(p.allow_text_entry), - mAllowNewValues(p.allow_new_values), - mMaxChars(p.max_chars), - mPrearrangeCallback(p.prearrange_callback()), - mTextEntryCallback(p.text_entry_callback()), - mTextChangedCallback(p.text_changed_callback()), - mListPosition(p.list_position), - mLastSelectedIndex(-1), - mLabel(p.label) -{ - // Text label button - - LLButton::Params button_params = (mAllowTextEntry ? p.combo_button : p.drop_down_button); - button_params.mouse_down_callback.function( - boost::bind(&LLComboBox::onButtonMouseDown, this)); - button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); - button_params.rect(p.rect); - - if(mAllowTextEntry) - { - button_params.pad_right(2); - } - - mArrowImage = button_params.image_unselected; +: LLUICtrl(p), + mTextEntry(NULL), + mTextEntryTentative(p.show_text_as_tentative), + mHasAutocompletedText(false), + mAllowTextEntry(p.allow_text_entry), + mAllowNewValues(p.allow_new_values), + mMaxChars(p.max_chars), + mPrearrangeCallback(p.prearrange_callback()), + mTextEntryCallback(p.text_entry_callback()), + mTextChangedCallback(p.text_changed_callback()), + mListPosition(p.list_position), + mLastSelectedIndex(-1), + mLabel(p.label) +{ + // Text label button + + LLButton::Params button_params = (mAllowTextEntry ? p.combo_button : p.drop_down_button); + button_params.mouse_down_callback.function( + boost::bind(&LLComboBox::onButtonMouseDown, this)); + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + button_params.rect(p.rect); + + if(mAllowTextEntry) + { + button_params.pad_right(2); + } + + mArrowImage = button_params.image_unselected; if (mArrowImage.notNull()) { mImageLoadedConnection = mArrowImage->addLoadedCallback(boost::bind(&LLComboBox::imageLoaded, this)); } - mButton = LLUICtrlFactory::create(button_params); + mButton = LLUICtrlFactory::create(button_params); - - if(mAllowTextEntry) - { - //redo to compensate for button hack that leaves space for a character - //unless it is a "minimal combobox"(drop down) - mButton->setRightHPad(2); - } - addChild(mButton); - LLScrollListCtrl::Params params = p.combo_list; - params.name("ComboBox"); - params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); - params.visible(false); - params.commit_on_keyboard_movement(false); + if(mAllowTextEntry) + { + //redo to compensate for button hack that leaves space for a character + //unless it is a "minimal combobox"(drop down) + mButton->setRightHPad(2); + } + addChild(mButton); - mList = LLUICtrlFactory::create(params); - addChild(mList); + LLScrollListCtrl::Params params = p.combo_list; + params.name("ComboBox"); + params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); - // Mouse-down on button will transfer mouse focus to the list - // Grab the mouse-up event and make sure the button state is correct - mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this)); + mList = LLUICtrlFactory::create(params); + addChild(mList); - for (LLInitParam::ParamIterator::const_iterator it = p.items.begin(); - it != p.items.end(); - ++it) - { - LLScrollListItem::Params item_params = *it; - if (it->label.isProvided()) - { - item_params.columns.add().value(it->label()); - } + // Mouse-down on button will transfer mouse focus to the list + // Grab the mouse-up event and make sure the button state is correct + mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this)); - mList->addRow(item_params); - } + for (LLInitParam::ParamIterator::const_iterator it = p.items.begin(); + it != p.items.end(); + ++it) + { + LLScrollListItem::Params item_params = *it; + if (it->label.isProvided()) + { + item_params.columns.add().value(it->label()); + } + + mList->addRow(item_params); + } - createLineEditor(p); + createLineEditor(p); - mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); + mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); } void LLComboBox::initFromParams(const LLComboBox::Params& p) { - LLUICtrl::initFromParams(p); + LLUICtrl::initFromParams(p); - if (!acceptsTextInput() && mLabel.empty()) - { - selectFirstItem(); - } + if (!acceptsTextInput() && mLabel.empty()) + { + selectFirstItem(); + } } // virtual BOOL LLComboBox::postBuild() { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - return TRUE; + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + return TRUE; } LLComboBox::~LLComboBox() { - // children automatically deleted, including mMenu, mButton + // children automatically deleted, including mMenu, mButton - // explicitly disconect this signal, since base class destructor might fire top lost - mTopLostSignalConnection.disconnect(); + // explicitly disconect this signal, since base class destructor might fire top lost + mTopLostSignalConnection.disconnect(); mImageLoadedConnection.disconnect(); } void LLComboBox::clear() -{ - if (mTextEntry) - { - mTextEntry->setText(LLStringUtil::null); - } - mButton->setLabelSelected(LLStringUtil::null); - mButton->setLabelUnselected(LLStringUtil::null); - mList->deselectAllItems(); - mLastSelectedIndex = -1; +{ + if (mTextEntry) + { + mTextEntry->setText(LLStringUtil::null); + } + mButton->setLabelSelected(LLStringUtil::null); + mButton->setLabelUnselected(LLStringUtil::null); + mList->deselectAllItems(); + mLastSelectedIndex = -1; } void LLComboBox::onCommit() { - if (mAllowTextEntry && getCurrentIndex() != -1) - { - // we have selected an existing item, blitz the manual text entry with - // the properly capitalized item - mTextEntry->setValue(getSimple()); - mTextEntry->setTentative(FALSE); - } - setControlValue(getValue()); - LLUICtrl::onCommit(); + if (mAllowTextEntry && getCurrentIndex() != -1) + { + // we have selected an existing item, blitz the manual text entry with + // the properly capitalized item + mTextEntry->setValue(getSimple()); + mTextEntry->setTentative(FALSE); + } + setControlValue(getValue()); + LLUICtrl::onCommit(); } // virtual BOOL LLComboBox::isDirty() const { - BOOL grubby = FALSE; - if ( mList ) - { - grubby = mList->isDirty(); - } - return grubby; + BOOL grubby = FALSE; + if ( mList ) + { + grubby = mList->isDirty(); + } + return grubby; } // virtual Clear dirty state -void LLComboBox::resetDirty() +void LLComboBox::resetDirty() { - if ( mList ) - { - mList->resetDirty(); - } + if ( mList ) + { + mList->resetDirty(); + } } bool LLComboBox::itemExists(const std::string& name) { - return mList->getItemByLabel(name); + return mList->getItemByLabel(name); } // add item "name" to menu LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOOL enabled) { - LLScrollListItem* item = mList->addSimpleElement(name, pos); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; + LLScrollListItem* item = mList->addSimpleElement(name, pos); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; } // add item "name" with a unique id to menu LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAddPosition pos, BOOL enabled ) { - LLScrollListItem* item = mList->addSimpleElement(name, pos, id); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; + LLScrollListItem* item = mList->addSimpleElement(name, pos, id); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; } // add item "name" with attached userdata LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddPosition pos, BOOL enabled ) { - LLScrollListItem* item = mList->addSimpleElement(name, pos); - item->setEnabled(enabled); - item->setUserdata( userdata ); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; + LLScrollListItem* item = mList->addSimpleElement(name, pos); + item->setEnabled(enabled); + item->setUserdata( userdata ); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; } // add item "name" with attached generic data LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosition pos, BOOL enabled ) { - LLScrollListItem* item = mList->addSimpleElement(name, pos, value); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; + LLScrollListItem* item = mList->addSimpleElement(name, pos, value); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; } LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos) { - return mList->addSeparator(pos); + return mList->addSeparator(pos); } void LLComboBox::sortByName(BOOL ascending) { - mList->sortOnce(0, ascending); + mList->sortOnce(0, ascending); } @@ -333,190 +333,190 @@ void LLComboBox::sortByName(BOOL ascending) // Returns TRUE if the item was found. BOOL LLComboBox::setSimple(const LLStringExplicit& name) { - BOOL found = mList->selectItemByLabel(name, FALSE); + BOOL found = mList->selectItemByLabel(name, FALSE); - if (found) - { - setLabel(name); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } + if (found) + { + setLabel(name); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } - return found; + return found; } // virtual void LLComboBox::setValue(const LLSD& value) { - BOOL found = mList->selectByValue(value); - if (found) - { - LLScrollListItem* item = mList->getFirstSelected(); - if (item) - { - updateLabel(); - } - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - mLastSelectedIndex = -1; - } + BOOL found = mList->selectByValue(value); + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + updateLabel(); + } + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + mLastSelectedIndex = -1; + } } const std::string LLComboBox::getSimple() const { - const std::string res = getSelectedItemLabel(); - if (res.empty() && mAllowTextEntry) - { - return mTextEntry->getText(); - } - else - { - return res; - } + const std::string res = getSelectedItemLabel(); + if (res.empty() && mAllowTextEntry) + { + return mTextEntry->getText(); + } + else + { + return res; + } } const std::string LLComboBox::getSelectedItemLabel(S32 column) const { - return mList->getSelectedItemLabel(column); + return mList->getSelectedItemLabel(column); } // virtual LLSD LLComboBox::getValue() const { - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return item->getValue(); - } - else if (mAllowTextEntry) - { - return mTextEntry->getValue(); - } - else - { - return LLSD(); - } + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getValue(); + } + else if (mAllowTextEntry) + { + return mTextEntry->getValue(); + } + else + { + return LLSD(); + } } void LLComboBox::setLabel(const LLStringExplicit& name) { - if ( mTextEntry ) - { - mTextEntry->setText(name); - if (mList->selectItemByLabel(name, FALSE)) - { - mTextEntry->setTentative(FALSE); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - mTextEntry->setTentative(mTextEntryTentative); - } - } - - if (!mAllowTextEntry) - { - mButton->setLabel(name); - } + if ( mTextEntry ) + { + mTextEntry->setText(name); + if (mList->selectItemByLabel(name, FALSE)) + { + mTextEntry->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + mTextEntry->setTentative(mTextEntryTentative); + } + } + + if (!mAllowTextEntry) + { + mButton->setLabel(name); + } } void LLComboBox::updateLabel() { - // Update the combo editor with the selected - // item label. - if (mTextEntry) - { - mTextEntry->setText(getSelectedItemLabel()); - mTextEntry->setTentative(FALSE); - } + // Update the combo editor with the selected + // item label. + if (mTextEntry) + { + mTextEntry->setText(getSelectedItemLabel()); + mTextEntry->setTentative(FALSE); + } - // If combo box doesn't allow text entry update - // the combo button label. - if (!mAllowTextEntry) - { - mButton->setLabel(getSelectedItemLabel()); - } + // If combo box doesn't allow text entry update + // the combo button label. + if (!mAllowTextEntry) + { + mButton->setLabel(getSelectedItemLabel()); + } } BOOL LLComboBox::remove(const std::string& name) { - BOOL found = mList->selectItemByLabel(name); + BOOL found = mList->selectItemByLabel(name); - if (found) - { - LLScrollListItem* item = mList->getFirstSelected(); - if (item) - { - mList->deleteSingleItem(mList->getItemIndex(item)); - } - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + mList->deleteSingleItem(mList->getItemIndex(item)); + } + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } - return found; + return found; } BOOL LLComboBox::remove(S32 index) { - if (index < mList->getItemCount()) - { - mList->deleteSingleItem(index); - setLabel(getSelectedItemLabel()); - return TRUE; - } - return FALSE; + if (index < mList->getItemCount()) + { + mList->deleteSingleItem(index); + setLabel(getSelectedItemLabel()); + return TRUE; + } + return FALSE; } // Keyboard focus lost. void LLComboBox::onFocusLost() { - hideList(); - // if valid selection - if (mAllowTextEntry && getCurrentIndex() != -1) - { - mTextEntry->selectAll(); - } - mButton->setForcePressedState(false); - LLUICtrl::onFocusLost(); + hideList(); + // if valid selection + if (mAllowTextEntry && getCurrentIndex() != -1) + { + mTextEntry->selectAll(); + } + mButton->setForcePressedState(false); + LLUICtrl::onFocusLost(); } void LLComboBox::setButtonVisible(BOOL visible) { - static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); - mButton->setVisible(visible); - if (mTextEntry) - { - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - if (visible) - { - S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; - } - //mTextEntry->setRect(text_entry_rect); - mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); - } + mButton->setVisible(visible); + if (mTextEntry) + { + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + if (visible) + { + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + } + //mTextEntry->setRect(text_entry_rect); + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); + } } BOOL LLComboBox::setCurrentByIndex( S32 index ) { - BOOL found = mList->selectNthItem( index ); - if (found) - { - setLabel(getSelectedItemLabel()); - mLastSelectedIndex = index; - } - return found; + BOOL found = mList->selectNthItem( index ); + if (found) + { + setLabel(getSelectedItemLabel()); + mLastSelectedIndex = index; + } + return found; } S32 LLComboBox::getCurrentIndex() const { - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return mList->getItemIndex( item ); - } - return -1; + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return mList->getItemIndex( item ); + } + return -1; } void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled) @@ -530,232 +530,232 @@ void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled) void LLComboBox::createLineEditor(const LLComboBox::Params& p) { - static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); - LLRect rect = getLocalRect(); - if (mAllowTextEntry) - { - S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = drop_shadow_button; - mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, - rect.mTop, rect.mRight, rect.mBottom)); - mButton->setTabStop(FALSE); - mButton->setHAlign(LLFontGL::HCENTER); - - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; - // clear label on button - std::string cur_label = mButton->getLabelSelected(); - LLLineEditor::Params params = p.combo_editor; - params.rect(text_entry_rect); - params.default_text(LLStringUtil::null); - params.max_length.bytes(mMaxChars); - params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); - params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); - params.commit_on_focus_lost(false); - params.follows.flags(FOLLOWS_ALL); - params.label(mLabel); - mTextEntry = LLUICtrlFactory::create (params); - mTextEntry->setText(cur_label); - mTextEntry->setIgnoreTab(TRUE); - addChild(mTextEntry); - - // clear label on button - setLabel(LLStringUtil::null); - - mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); - } - else - { - mButton->setRect(rect); - mButton->setLabel(mLabel.getString()); - - if (mTextEntry) - { - mTextEntry->setVisible(FALSE); - } - } + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); + LLRect rect = getLocalRect(); + if (mAllowTextEntry) + { + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + S32 shadow_size = drop_shadow_button; + mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, + rect.mTop, rect.mRight, rect.mBottom)); + mButton->setTabStop(FALSE); + mButton->setHAlign(LLFontGL::HCENTER); + + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + // clear label on button + std::string cur_label = mButton->getLabelSelected(); + LLLineEditor::Params params = p.combo_editor; + params.rect(text_entry_rect); + params.default_text(LLStringUtil::null); + params.max_length.bytes(mMaxChars); + params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); + params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); + params.commit_on_focus_lost(false); + params.follows.flags(FOLLOWS_ALL); + params.label(mLabel); + mTextEntry = LLUICtrlFactory::create (params); + mTextEntry->setText(cur_label); + mTextEntry->setIgnoreTab(TRUE); + addChild(mTextEntry); + + // clear label on button + setLabel(LLStringUtil::null); + + mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); + } + else + { + mButton->setRect(rect); + mButton->setLabel(mLabel.getString()); + + if (mTextEntry) + { + mTextEntry->setVisible(FALSE); + } + } } void LLComboBox::setLeftTextPadding(S32 pad) { - S32 left_pad, right_pad; - mTextEntry->getTextPadding(&left_pad, &right_pad); - mTextEntry->setTextPadding(pad, right_pad); + S32 left_pad, right_pad; + mTextEntry->getTextPadding(&left_pad, &right_pad); + mTextEntry->setTextPadding(pad, right_pad); } void* LLComboBox::getCurrentUserdata() { - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return item->getUserdata(); - } - return NULL; + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getUserdata(); + } + return NULL; } void LLComboBox::showList() { - // Make sure we don't go off top of screen. - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - //HACK: shouldn't have to know about scale here - mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); - - // Make sure that we can see the whole list - LLRect root_view_local; - LLView* root_view = getRootView(); - root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); - - LLRect rect = mList->getRect(); - - S32 min_width = getRect().getWidth(); - S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); - // make sure we have up to date content width metrics - S32 list_width = llclamp(mList->calcMaxContentWidth(), min_width, max_width); - - if (mListPosition == BELOW) - { - if (rect.getHeight() <= -root_view_local.mBottom) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); - } - else - { - // stack on top or bottom, depending on which has more room - if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); - } - else - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - } - } - else // ABOVE - { - if (rect.getHeight() <= root_view_local.mTop - getRect().getHeight()) - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - else - { - // stack on top or bottom, depending on which has more room - if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); - } - else - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - } - - } - mList->setOrigin(rect.mLeft, rect.mBottom); - mList->reshape(rect.getWidth(), rect.getHeight()); - mList->translateIntoRect(root_view_local); - - // Make sure we didn't go off bottom of screen - S32 x, y; - mList->localPointToScreen(0, 0, &x, &y); - - if (y < 0) - { - mList->translate(0, -y); - } - - // NB: this call will trigger the focuslost callback which will hide the list, so do it first - // before finally showing the list - - mList->setFocus(TRUE); - - // Show the list and push the button down - mButton->setToggleState(TRUE); - mList->setVisible(TRUE); - - LLUI::getInstance()->addPopup(this); - - setUseBoundingRect(TRUE); -// updateBoundingRect(); + // Make sure we don't go off top of screen. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + //HACK: shouldn't have to know about scale here + mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); + + // Make sure that we can see the whole list + LLRect root_view_local; + LLView* root_view = getRootView(); + root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); + + LLRect rect = mList->getRect(); + + S32 min_width = getRect().getWidth(); + S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); + // make sure we have up to date content width metrics + S32 list_width = llclamp(mList->calcMaxContentWidth(), min_width, max_width); + + if (mListPosition == BELOW) + { + if (rect.getHeight() <= -root_view_local.mBottom) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); + } + else + { + // stack on top or bottom, depending on which has more room + if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); + } + else + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + } + } + else // ABOVE + { + if (rect.getHeight() <= root_view_local.mTop - getRect().getHeight()) + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + else + { + // stack on top or bottom, depending on which has more room + if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); + } + else + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + } + + } + mList->setOrigin(rect.mLeft, rect.mBottom); + mList->reshape(rect.getWidth(), rect.getHeight()); + mList->translateIntoRect(root_view_local); + + // Make sure we didn't go off bottom of screen + S32 x, y; + mList->localPointToScreen(0, 0, &x, &y); + + if (y < 0) + { + mList->translate(0, -y); + } + + // NB: this call will trigger the focuslost callback which will hide the list, so do it first + // before finally showing the list + + mList->setFocus(TRUE); + + // Show the list and push the button down + mButton->setToggleState(TRUE); + mList->setVisible(TRUE); + + LLUI::getInstance()->addPopup(this); + + setUseBoundingRect(TRUE); +// updateBoundingRect(); } void LLComboBox::hideList() { - if (mList->getVisible()) - { - // assert selection in list - if(mAllowNewValues) - { - // mLastSelectedIndex = -1 means that we entered a new value, don't select - // any of existing items in this case. - if(mLastSelectedIndex >= 0) - mList->selectNthItem(mLastSelectedIndex); - } - else if(mLastSelectedIndex >= 0) - mList->selectNthItem(mLastSelectedIndex); - - mButton->setToggleState(FALSE); - mList->setVisible(FALSE); - mList->mouseOverHighlightNthItem(-1); - - setUseBoundingRect(FALSE); - LLUI::getInstance()->removePopup(this); -// updateBoundingRect(); - } + if (mList->getVisible()) + { + // assert selection in list + if(mAllowNewValues) + { + // mLastSelectedIndex = -1 means that we entered a new value, don't select + // any of existing items in this case. + if(mLastSelectedIndex >= 0) + mList->selectNthItem(mLastSelectedIndex); + } + else if(mLastSelectedIndex >= 0) + mList->selectNthItem(mLastSelectedIndex); + + mButton->setToggleState(FALSE); + mList->setVisible(FALSE); + mList->mouseOverHighlightNthItem(-1); + + setUseBoundingRect(FALSE); + LLUI::getInstance()->removePopup(this); +// updateBoundingRect(); + } } void LLComboBox::onButtonMouseDown() { - if (!mList->getVisible()) - { - // this might change selection, so do it first - prearrangeList(); + if (!mList->getVisible()) + { + // this might change selection, so do it first + prearrangeList(); - // highlight the last selected item from the original selection before potentially selecting a new item - // as visual cue to original value of combo box - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } + // highlight the last selected item from the original selection before potentially selecting a new item + // as visual cue to original value of combo box + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } - if (mList->getItemCount() != 0) - { - showList(); - } + if (mList->getItemCount() != 0) + { + showList(); + } - setFocus( TRUE ); + setFocus( TRUE ); - // pass mouse capture on to list if button is depressed - if (mButton->hasMouseCapture()) - { - gFocusMgr.setMouseCapture(mList); + // pass mouse capture on to list if button is depressed + if (mButton->hasMouseCapture()) + { + gFocusMgr.setMouseCapture(mList); - // But keep the "pressed" look, which buttons normally lose when they - // lose focus - mButton->setForcePressedState(true); - } - } - else - { - hideList(); - } + // But keep the "pressed" look, which buttons normally lose when they + // lose focus + mButton->setForcePressedState(true); + } + } + else + { + hideList(); + } } void LLComboBox::onListMouseUp() { - // In some cases this is the termination of a mouse click that started on - // the button, so clear its pressed state - mButton->setForcePressedState(false); + // In some cases this is the termination of a mouse click that started on + // the button, so clear its pressed state + mButton->setForcePressedState(false); } //------------------------------------------------------------------ @@ -764,282 +764,282 @@ void LLComboBox::onListMouseUp() void LLComboBox::onItemSelected(const LLSD& data) { - mLastSelectedIndex = getCurrentIndex(); - if (mLastSelectedIndex != -1) - { - updateLabel(); + mLastSelectedIndex = getCurrentIndex(); + if (mLastSelectedIndex != -1) + { + updateLabel(); - if (mAllowTextEntry) - { - gFocusMgr.setKeyboardFocus(mTextEntry); - mTextEntry->selectAll(); - } - } - // hiding the list reasserts the old value stored in the text editor/dropdown button - hideList(); + if (mAllowTextEntry) + { + gFocusMgr.setKeyboardFocus(mTextEntry); + mTextEntry->selectAll(); + } + } + // hiding the list reasserts the old value stored in the text editor/dropdown button + hideList(); - // commit does the reverse, asserting the value in the list - onCommit(); + // commit does the reverse, asserting the value in the list + onCommit(); } BOOL LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) { std::string tool_tip; - if(LLUICtrl::handleToolTip(x, y, mask)) - { - return TRUE; - } - - tool_tip = getToolTip(); - if (tool_tip.empty()) - { - tool_tip = getSelectedItemLabel(); - } - - if( !tool_tip.empty() ) - { - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tool_tip) - .sticky_rect(calcScreenRect())); - } - return TRUE; + if(LLUICtrl::handleToolTip(x, y, mask)) + { + return TRUE; + } + + tool_tip = getToolTip(); + if (tool_tip.empty()) + { + tool_tip = getSelectedItemLabel(); + } + + if( !tool_tip.empty() ) + { + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(tool_tip) + .sticky_rect(calcScreenRect())); + } + return TRUE; } BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) { - BOOL result = FALSE; - if (hasFocus()) - { - if (mList->getVisible() - && key == KEY_ESCAPE && mask == MASK_NONE) - { - hideList(); - return TRUE; - } - //give list a chance to pop up and handle key - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - // highlight the original selection before potentially selecting a new item - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } - result = mList->handleKeyHere(key, mask); - - // will only see return key if it is originating from line editor - // since the dropdown button eats the key - if (key == KEY_RETURN) - { - if (mask == MASK_NONE) - { - mOnReturnSignal(this, getValue()); - } - - // don't show list and don't eat key input when committing - // free-form text entry with RETURN since user already knows + BOOL result = FALSE; + if (hasFocus()) + { + if (mList->getVisible() + && key == KEY_ESCAPE && mask == MASK_NONE) + { + hideList(); + return TRUE; + } + //give list a chance to pop up and handle key + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + // highlight the original selection before potentially selecting a new item + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + result = mList->handleKeyHere(key, mask); + + // will only see return key if it is originating from line editor + // since the dropdown button eats the key + if (key == KEY_RETURN) + { + if (mask == MASK_NONE) + { + mOnReturnSignal(this, getValue()); + } + + // don't show list and don't eat key input when committing + // free-form text entry with RETURN since user already knows // what they are trying to select - return FALSE; - } - // if selection has changed, pop open list - else if (mList->getLastSelectedItem() != last_selected_item - || ((key == KEY_DOWN || key == KEY_UP) - && mList->getCanSelect() - && !mList->isEmpty())) - { - showList(); - } - } - return result; + return FALSE; + } + // if selection has changed, pop open list + else if (mList->getLastSelectedItem() != last_selected_item + || ((key == KEY_DOWN || key == KEY_UP) + && mList->getCanSelect() + && !mList->isEmpty())) + { + showList(); + } + } + return result; } BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) { - BOOL result = FALSE; - if (gFocusMgr.childHasKeyboardFocus(this)) - { - // space bar just shows the list - if (' ' != uni_char ) - { - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - // highlight the original selection before potentially selecting a new item - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } - result = mList->handleUnicodeCharHere(uni_char); - if (mList->getLastSelectedItem() != last_selected_item) - { - showList(); - } - } - } - return result; + BOOL result = FALSE; + if (gFocusMgr.childHasKeyboardFocus(this)) + { + // space bar just shows the list + if (' ' != uni_char ) + { + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + // highlight the original selection before potentially selecting a new item + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + result = mList->handleUnicodeCharHere(uni_char); + if (mList->getLastSelectedItem() != last_selected_item) + { + showList(); + } + } + } + return result; } void LLComboBox::setTextEntry(const LLStringExplicit& text) { - if (mTextEntry) - { - mTextEntry->setText(text); - mHasAutocompletedText = FALSE; - updateSelection(); - } + if (mTextEntry) + { + mTextEntry->setText(text); + mHasAutocompletedText = FALSE; + updateSelection(); + } } void LLComboBox::setKeystrokeOnEsc(BOOL enable) { - if (mTextEntry) - { - mTextEntry->setKeystrokeOnEsc(enable); - } + if (mTextEntry) + { + mTextEntry->setKeystrokeOnEsc(enable); + } } void LLComboBox::onTextEntry(LLLineEditor* line_editor) { - if (mTextEntryCallback != NULL) - { - (mTextEntryCallback)(line_editor, LLSD()); - } - - KEY key = gKeyboard->currentKey(); - if (key == KEY_BACKSPACE || - key == KEY_DELETE) - { - if (mList->selectItemByLabel(line_editor->getText(), FALSE)) - { - line_editor->setTentative(FALSE); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - line_editor->setTentative(mTextEntryTentative); - mList->deselectAllItems(); - mLastSelectedIndex = -1; - } - if (mTextChangedCallback != NULL) - { - (mTextChangedCallback)(line_editor, LLSD()); - } - return; - } - - if (key == KEY_LEFT || - key == KEY_RIGHT) - { - return; - } - - if (key == KEY_DOWN) - { - setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); - if (!mList->getVisible()) - { - prearrangeList(); - - if (mList->getItemCount() != 0) - { - showList(); - } - } - line_editor->selectAll(); - line_editor->setTentative(FALSE); - } - else if (key == KEY_UP) - { - setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); - if (!mList->getVisible()) - { - prearrangeList(); - - if (mList->getItemCount() != 0) - { - showList(); - } - } - line_editor->selectAll(); - line_editor->setTentative(FALSE); - } - else - { - // RN: presumably text entry - updateSelection(); - } - if (mTextChangedCallback != NULL) - { - (mTextChangedCallback)(line_editor, LLSD()); - } + if (mTextEntryCallback != NULL) + { + (mTextEntryCallback)(line_editor, LLSD()); + } + + KEY key = gKeyboard->currentKey(); + if (key == KEY_BACKSPACE || + key == KEY_DELETE) + { + if (mList->selectItemByLabel(line_editor->getText(), FALSE)) + { + line_editor->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + line_editor->setTentative(mTextEntryTentative); + mList->deselectAllItems(); + mLastSelectedIndex = -1; + } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } + return; + } + + if (key == KEY_LEFT || + key == KEY_RIGHT) + { + return; + } + + if (key == KEY_DOWN) + { + setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); + if (!mList->getVisible()) + { + prearrangeList(); + + if (mList->getItemCount() != 0) + { + showList(); + } + } + line_editor->selectAll(); + line_editor->setTentative(FALSE); + } + else if (key == KEY_UP) + { + setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); + if (!mList->getVisible()) + { + prearrangeList(); + + if (mList->getItemCount() != 0) + { + showList(); + } + } + line_editor->selectAll(); + line_editor->setTentative(FALSE); + } + else + { + // RN: presumably text entry + updateSelection(); + } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } } void LLComboBox::updateSelection() { - LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); - // user-entered portion of string, based on assumption that any selected + LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); + // user-entered portion of string, based on assumption that any selected // text was a result of auto-completion - LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText(); - std::string full_string = mTextEntry->getText(); - - // go ahead and arrange drop down list on first typed character, even - // though we aren't showing it... some code relies on prearrange - // callback to populate content - if( mTextEntry->getWText().size() == 1 ) - { - prearrangeList(mTextEntry->getText()); - } - - if (mList->selectItemByLabel(full_string, FALSE)) - { - mTextEntry->setTentative(FALSE); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else if (mList->selectItemByPrefix(left_wstring, FALSE)) - { - LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); - LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); - mTextEntry->setText(wstring_to_utf8str(wtext)); - mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); - mTextEntry->endSelection(); - mTextEntry->setTentative(FALSE); - mHasAutocompletedText = TRUE; - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else // no matching items found - { - mList->deselectAllItems(); - mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion - mTextEntry->setTentative(mTextEntryTentative); - mHasAutocompletedText = FALSE; - mLastSelectedIndex = -1; - } + LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText(); + std::string full_string = mTextEntry->getText(); + + // go ahead and arrange drop down list on first typed character, even + // though we aren't showing it... some code relies on prearrange + // callback to populate content + if( mTextEntry->getWText().size() == 1 ) + { + prearrangeList(mTextEntry->getText()); + } + + if (mList->selectItemByLabel(full_string, FALSE)) + { + mTextEntry->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else if (mList->selectItemByPrefix(left_wstring, FALSE)) + { + LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); + LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); + mTextEntry->setText(wstring_to_utf8str(wtext)); + mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); + mTextEntry->endSelection(); + mTextEntry->setTentative(FALSE); + mHasAutocompletedText = TRUE; + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else // no matching items found + { + mList->deselectAllItems(); + mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion + mTextEntry->setTentative(mTextEntryTentative); + mHasAutocompletedText = FALSE; + mLastSelectedIndex = -1; + } } void LLComboBox::onTextCommit(const LLSD& data) { - std::string text = mTextEntry->getText(); - setSimple(text); - onCommit(); - mTextEntry->selectAll(); + std::string text = mTextEntry->getText(); + setSimple(text); + onCommit(); + mTextEntry->selectAll(); } void LLComboBox::setFocus(BOOL b) { - LLUICtrl::setFocus(b); + LLUICtrl::setFocus(b); - if (b) - { - mList->clearSearchString(); - if (mList->getVisible()) - { - mList->setFocus(TRUE); - } - } + if (b) + { + mList->clearSearchString(); + if (mList->getVisible()) + { + mList->setFocus(TRUE); + } + } } void LLComboBox::prearrangeList(std::string filter) { - if (mPrearrangeCallback) - { - mPrearrangeCallback(this, LLSD(filter)); - } + if (mPrearrangeCallback) + { + mPrearrangeCallback(this, LLSD(filter)); + } } @@ -1108,43 +1108,43 @@ void LLComboBox::imageLoaded() S32 LLComboBox::getItemCount() const { - return mList->getItemCount(); + return mList->getItemCount(); } void LLComboBox::addColumn(const LLSD& column, EAddPosition pos) { - mList->clearColumns(); - mList->addColumn(column, pos); + mList->clearColumns(); + mList->addColumn(column, pos); } void LLComboBox::clearColumns() { - mList->clearColumns(); + mList->clearColumns(); } void LLComboBox::setColumnLabel(const std::string& column, const std::string& label) { - mList->setColumnLabel(column, label); + mList->setColumnLabel(column, label); } LLScrollListItem* LLComboBox::addElement(const LLSD& value, EAddPosition pos, void* userdata) { - return mList->addElement(value, pos, userdata); + return mList->addElement(value, pos, userdata); } LLScrollListItem* LLComboBox::addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) { - return mList->addSimpleElement(value, pos, id); + return mList->addSimpleElement(value, pos, id); } void LLComboBox::clearRows() { - mList->clearRows(); + mList->clearRows(); } void LLComboBox::sortByColumn(const std::string& name, BOOL ascending) { - mList->sortByColumn(name, ascending); + mList->sortByColumn(name, ascending); } //============================================================================ @@ -1152,83 +1152,83 @@ void LLComboBox::sortByColumn(const std::string& name, BOOL ascending) BOOL LLComboBox::setCurrentByID(const LLUUID& id) { - BOOL found = mList->selectByID( id ); + BOOL found = mList->selectByID( id ); - if (found) - { - setLabel(getSelectedItemLabel()); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } + if (found) + { + setLabel(getSelectedItemLabel()); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } - return found; + return found; } LLUUID LLComboBox::getCurrentID() const { - return mList->getStringUUIDSelectedItem(); + return mList->getStringUUIDSelectedItem(); } BOOL LLComboBox::setSelectedByValue(const LLSD& value, BOOL selected) { - BOOL found = mList->setSelectedByValue(value, selected); - if (found) - { - setLabel(getSelectedItemLabel()); - } - return found; + BOOL found = mList->setSelectedByValue(value, selected); + if (found) + { + setLabel(getSelectedItemLabel()); + } + return found; } LLSD LLComboBox::getSelectedValue() { - return mList->getSelectedValue(); + return mList->getSelectedValue(); } BOOL LLComboBox::isSelected(const LLSD& value) const { - return mList->isSelected(value); + return mList->isSelected(value); } BOOL LLComboBox::operateOnSelection(EOperation op) { - if (op == OP_DELETE) - { - mList->deleteSelectedItems(); - return TRUE; - } - return FALSE; + if (op == OP_DELETE) + { + mList->deleteSelectedItems(); + return TRUE; + } + return FALSE; } BOOL LLComboBox::operateOnAll(EOperation op) { - if (op == OP_DELETE) - { - clearRows(); - return TRUE; - } - return FALSE; + if (op == OP_DELETE) + { + clearRows(); + return TRUE; + } + return FALSE; } BOOL LLComboBox::selectItemRange( S32 first, S32 last ) { - return mList->selectItemRange(first, last); + return mList->selectItemRange(first, last); } static LLDefaultChildRegistry::Register register_icons_combo_box("icons_combo_box"); LLIconsComboBox::Params::Params() -: icon_column("icon_column", ICON_COLUMN), - label_column("label_column", LABEL_COLUMN) +: icon_column("icon_column", ICON_COLUMN), + label_column("label_column", LABEL_COLUMN) {} LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p) -: LLComboBox(p), - mIconColumnIndex(p.icon_column), - mLabelColumnIndex(p.label_column) +: LLComboBox(p), + mIconColumnIndex(p.icon_column), + mLabelColumnIndex(p.label_column) {} const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const { - mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); + mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); - return LLComboBox::getSelectedItemLabel(mLabelColumnIndex); + return LLComboBox::getSelectedItemLabel(mLabelColumnIndex); } diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index cac8850a25..93382a1022 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -1,25 +1,25 @@ -/** +/** * @file llcombobox.h * @brief LLComboBox base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -48,59 +48,59 @@ class LLComboBox , public LLCtrlListInterface , public ll::ui::SearchableControl { -public: - typedef enum e_preferred_position - { - ABOVE, - BELOW - } EPreferredPosition; - - struct PreferredPositionValues : public LLInitParam::TypeValuesHelper - { - static void declareValues(); - }; - - - struct ItemParams : public LLInitParam::Block - { - Optional label; - ItemParams(); - }; - - struct Params - : public LLInitParam::Block - { - Optional allow_text_entry, - show_text_as_tentative, - allow_new_values; - Optional max_chars; - Optional prearrange_callback, - text_entry_callback, - text_changed_callback; - - Optional list_position; - - // components - Optional combo_button; - Optional combo_list; - Optional combo_editor; - - Optional drop_down_button; - - Multiple items; - - Params(); - }; - - - virtual ~LLComboBox(); - /*virtual*/ BOOL postBuild(); - +public: + typedef enum e_preferred_position + { + ABOVE, + BELOW + } EPreferredPosition; + + struct PreferredPositionValues : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; + + + struct ItemParams : public LLInitParam::Block + { + Optional label; + ItemParams(); + }; + + struct Params + : public LLInitParam::Block + { + Optional allow_text_entry, + show_text_as_tentative, + allow_new_values; + Optional max_chars; + Optional prearrange_callback, + text_entry_callback, + text_changed_callback; + + Optional list_position; + + // components + Optional combo_button; + Optional combo_list; + Optional combo_editor; + + Optional drop_down_button; + + Multiple items; + + Params(); + }; + + + virtual ~LLComboBox(); + /*virtual*/ BOOL postBuild(); + protected: - friend class LLUICtrlFactory; - LLComboBox(const Params&); - void initFromParams(const Params&); - void prearrangeList(std::string filter = ""); + friend class LLUICtrlFactory; + LLComboBox(const Params&); + void initFromParams(const Params&); + void prearrangeList(std::string filter = ""); virtual std::string _getSearchText() const; virtual void onSetHighlight() const; @@ -108,177 +108,177 @@ protected: void imageLoaded(); public: - // LLView interface - virtual void onFocusLost(); - - virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); - virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - - // LLUICtrl interface - virtual void clear(); // select nothing - virtual void onCommit(); - virtual BOOL acceptsTextInput() const { return mAllowTextEntry; } - virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. - virtual void resetDirty(); // Clear dirty state - - virtual void setFocus(BOOL b); - - // Selects item by underlying LLSD value, using LLSD::asString() matching. - // For simple items, this is just the name of the label. - virtual void setValue(const LLSD& value ); - - // Gets underlying LLSD value for currently selected items. For simple - // items, this is just the label. - virtual LLSD getValue() const; - - void setTextEntry(const LLStringExplicit& text); - void setKeystrokeOnEsc(BOOL enable); - - LLScrollListItem* add(const std::string& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu - LLScrollListItem* add(const std::string& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); - LLScrollListItem* add(const std::string& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); - LLScrollListItem* add(const std::string& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); - LLScrollListItem* addSeparator(EAddPosition pos = ADD_BOTTOM); - BOOL remove( S32 index ); // remove item by index, return TRUE if found and removed - void removeall() { clearRows(); } - bool itemExists(const std::string& name); - - void sortByName(BOOL ascending = TRUE); // Sort the entries in the combobox by name - - // Select current item by name using selectItemByLabel. Returns FALSE if not found. - BOOL setSimple(const LLStringExplicit& name); - // Get name of current item. Returns an empty string if not found. - const std::string getSimple() const; - // Get contents of column x of selected row - virtual const std::string getSelectedItemLabel(S32 column = 0) const; - - // Sets the label, which doesn't have to exist in the label. - // This is probably a UI abuse. - void setLabel(const LLStringExplicit& name); - - // Updates the combobox label to match the selected list item. - void updateLabel(); - - BOOL remove(const std::string& name); // remove item "name", return TRUE if found and removed - - BOOL setCurrentByIndex( S32 index ); - S32 getCurrentIndex() const; - - void setEnabledByValue(const LLSD& value, BOOL enabled); - - void createLineEditor(const Params&); - - //======================================================================== - LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; - LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)this; }; - - // LLCtrlListInterface functions - // See llscrolllistctrl.h - virtual S32 getItemCount() const; - // Overwrites the default column (See LLScrollListCtrl for format) - virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); - virtual void clearColumns(); - virtual void setColumnLabel(const std::string& column, const std::string& label); - virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); - virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); - virtual void clearRows(); - virtual void sortByColumn(const std::string& name, BOOL ascending); - - // LLCtrlSelectionInterface functions - virtual BOOL getCanSelect() const { return TRUE; } - virtual BOOL selectFirstItem() { return setCurrentByIndex(0); } - virtual BOOL selectNthItem( S32 index ) { return setCurrentByIndex(index); } - virtual BOOL selectItemRange( S32 first, S32 last ); - virtual S32 getFirstSelectedIndex() const { return getCurrentIndex(); } - virtual BOOL setCurrentByID( const LLUUID& id ); - virtual LLUUID getCurrentID() const; // LLUUID::null if no items in menu - virtual BOOL setSelectedByValue(const LLSD& value, BOOL selected); - virtual LLSD getSelectedValue(); - virtual BOOL isSelected(const LLSD& value) const; - virtual BOOL operateOnSelection(EOperation op); - virtual BOOL operateOnAll(EOperation op); - - //======================================================================== - - void setLeftTextPadding(S32 pad); - - void* getCurrentUserdata(); - - void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; } - void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } - void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; } - - /** - * Connects callback to signal called when Return key is pressed. - */ - boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } - - void setButtonVisible(BOOL visible); - - void onButtonMouseDown(); - void onListMouseUp(); - void onItemSelected(const LLSD& data); - void onTextCommit(const LLSD& data); - - void updateSelection(); - virtual void showList(); - virtual void hideList(); - - virtual void onTextEntry(LLLineEditor* line_editor); - + // LLView interface + virtual void onFocusLost(); + + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); + virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); + + // LLUICtrl interface + virtual void clear(); // select nothing + virtual void onCommit(); + virtual BOOL acceptsTextInput() const { return mAllowTextEntry; } + virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. + virtual void resetDirty(); // Clear dirty state + + virtual void setFocus(BOOL b); + + // Selects item by underlying LLSD value, using LLSD::asString() matching. + // For simple items, this is just the name of the label. + virtual void setValue(const LLSD& value ); + + // Gets underlying LLSD value for currently selected items. For simple + // items, this is just the label. + virtual LLSD getValue() const; + + void setTextEntry(const LLStringExplicit& text); + void setKeystrokeOnEsc(BOOL enable); + + LLScrollListItem* add(const std::string& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu + LLScrollListItem* add(const std::string& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); + LLScrollListItem* add(const std::string& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); + LLScrollListItem* add(const std::string& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); + LLScrollListItem* addSeparator(EAddPosition pos = ADD_BOTTOM); + BOOL remove( S32 index ); // remove item by index, return TRUE if found and removed + void removeall() { clearRows(); } + bool itemExists(const std::string& name); + + void sortByName(BOOL ascending = TRUE); // Sort the entries in the combobox by name + + // Select current item by name using selectItemByLabel. Returns FALSE if not found. + BOOL setSimple(const LLStringExplicit& name); + // Get name of current item. Returns an empty string if not found. + const std::string getSimple() const; + // Get contents of column x of selected row + virtual const std::string getSelectedItemLabel(S32 column = 0) const; + + // Sets the label, which doesn't have to exist in the label. + // This is probably a UI abuse. + void setLabel(const LLStringExplicit& name); + + // Updates the combobox label to match the selected list item. + void updateLabel(); + + BOOL remove(const std::string& name); // remove item "name", return TRUE if found and removed + + BOOL setCurrentByIndex( S32 index ); + S32 getCurrentIndex() const; + + void setEnabledByValue(const LLSD& value, BOOL enabled); + + void createLineEditor(const Params&); + + //======================================================================== + LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; + LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)this; }; + + // LLCtrlListInterface functions + // See llscrolllistctrl.h + virtual S32 getItemCount() const; + // Overwrites the default column (See LLScrollListCtrl for format) + virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); + virtual void clearColumns(); + virtual void setColumnLabel(const std::string& column, const std::string& label); + virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); + virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); + virtual void clearRows(); + virtual void sortByColumn(const std::string& name, BOOL ascending); + + // LLCtrlSelectionInterface functions + virtual BOOL getCanSelect() const { return TRUE; } + virtual BOOL selectFirstItem() { return setCurrentByIndex(0); } + virtual BOOL selectNthItem( S32 index ) { return setCurrentByIndex(index); } + virtual BOOL selectItemRange( S32 first, S32 last ); + virtual S32 getFirstSelectedIndex() const { return getCurrentIndex(); } + virtual BOOL setCurrentByID( const LLUUID& id ); + virtual LLUUID getCurrentID() const; // LLUUID::null if no items in menu + virtual BOOL setSelectedByValue(const LLSD& value, BOOL selected); + virtual LLSD getSelectedValue(); + virtual BOOL isSelected(const LLSD& value) const; + virtual BOOL operateOnSelection(EOperation op); + virtual BOOL operateOnAll(EOperation op); + + //======================================================================== + + void setLeftTextPadding(S32 pad); + + void* getCurrentUserdata(); + + void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; } + void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } + void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; } + + /** + * Connects callback to signal called when Return key is pressed. + */ + boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } + + void setButtonVisible(BOOL visible); + + void onButtonMouseDown(); + void onListMouseUp(); + void onItemSelected(const LLSD& data); + void onTextCommit(const LLSD& data); + + void updateSelection(); + virtual void showList(); + virtual void hideList(); + + virtual void onTextEntry(LLLineEditor* line_editor); + protected: - LLButton* mButton; - LLLineEditor* mTextEntry; - LLScrollListCtrl* mList; - EPreferredPosition mListPosition; - LLPointer mArrowImage; - LLUIString mLabel; - BOOL mHasAutocompletedText; + LLButton* mButton; + LLLineEditor* mTextEntry; + LLScrollListCtrl* mList; + EPreferredPosition mListPosition; + LLPointer mArrowImage; + LLUIString mLabel; + BOOL mHasAutocompletedText; private: - BOOL mAllowTextEntry; - BOOL mAllowNewValues; - S32 mMaxChars; - BOOL mTextEntryTentative; - commit_callback_t mPrearrangeCallback; - commit_callback_t mTextEntryCallback; - commit_callback_t mTextChangedCallback; - commit_callback_t mSelectionCallback; - boost::signals2::connection mTopLostSignalConnection; + BOOL mAllowTextEntry; + BOOL mAllowNewValues; + S32 mMaxChars; + BOOL mTextEntryTentative; + commit_callback_t mPrearrangeCallback; + commit_callback_t mTextEntryCallback; + commit_callback_t mTextChangedCallback; + commit_callback_t mSelectionCallback; + boost::signals2::connection mTopLostSignalConnection; boost::signals2::connection mImageLoadedConnection; - commit_signal_t mOnReturnSignal; - S32 mLastSelectedIndex; + commit_signal_t mOnReturnSignal; + S32 mLastSelectedIndex; }; // A combo box with icons for the list of items. class LLIconsComboBox -: public LLComboBox +: public LLComboBox { public: - struct Params - : public LLInitParam::Block - { - Optional icon_column, - label_column; - Params(); - }; + struct Params + : public LLInitParam::Block + { + Optional icon_column, + label_column; + Params(); + }; - /*virtual*/ const std::string getSelectedItemLabel(S32 column = 0) const; + /*virtual*/ const std::string getSelectedItemLabel(S32 column = 0) const; private: - enum EColumnIndex - { - ICON_COLUMN = 0, - LABEL_COLUMN - }; - - friend class LLUICtrlFactory; - LLIconsComboBox(const Params&); - virtual ~LLIconsComboBox() {}; - - S32 mIconColumnIndex; - S32 mLabelColumnIndex; + enum EColumnIndex + { + ICON_COLUMN = 0, + LABEL_COLUMN + }; + + friend class LLUICtrlFactory; + LLIconsComboBox(const Params&); + virtual ~LLIconsComboBox() {}; + + S32 mIconColumnIndex; + S32 mLabelColumnIndex; }; #endif diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 8ef7bd837f..270ec86e01 100644 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcommandmanager.cpp * @brief LLCommandManager class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,43 +46,43 @@ const LLCommandId LLCommandId::null = LLCommandId("null command"); // LLCommand::Params::Params() - : available_in_toybox("available_in_toybox", false) - , icon("icon") - , label_ref("label_ref") - , name("name") - , tooltip_ref("tooltip_ref") - , execute_function("execute_function") - , execute_parameters("execute_parameters") - , execute_stop_function("execute_stop_function") - , execute_stop_parameters("execute_stop_parameters") - , is_enabled_function("is_enabled_function") - , is_enabled_parameters("is_enabled_parameters") - , is_running_function("is_running_function") - , is_running_parameters("is_running_parameters") - , is_starting_function("is_starting_function") - , is_starting_parameters("is_starting_parameters") - , is_flashing_allowed("is_flashing_allowed", false) + : available_in_toybox("available_in_toybox", false) + , icon("icon") + , label_ref("label_ref") + , name("name") + , tooltip_ref("tooltip_ref") + , execute_function("execute_function") + , execute_parameters("execute_parameters") + , execute_stop_function("execute_stop_function") + , execute_stop_parameters("execute_stop_parameters") + , is_enabled_function("is_enabled_function") + , is_enabled_parameters("is_enabled_parameters") + , is_running_function("is_running_function") + , is_running_parameters("is_running_parameters") + , is_starting_function("is_starting_function") + , is_starting_parameters("is_starting_parameters") + , is_flashing_allowed("is_flashing_allowed", false) { } LLCommand::LLCommand(const LLCommand::Params& p) - : mIdentifier(p.name) - , mAvailableInToybox(p.available_in_toybox) - , mIcon(p.icon) - , mLabelRef(p.label_ref) - , mName(p.name) - , mTooltipRef(p.tooltip_ref) - , mExecuteFunction(p.execute_function) - , mExecuteParameters(p.execute_parameters) - , mExecuteStopFunction(p.execute_stop_function) - , mExecuteStopParameters(p.execute_stop_parameters) - , mIsEnabledFunction(p.is_enabled_function) - , mIsEnabledParameters(p.is_enabled_parameters) - , mIsRunningFunction(p.is_running_function) - , mIsRunningParameters(p.is_running_parameters) - , mIsStartingFunction(p.is_starting_function) - , mIsStartingParameters(p.is_starting_parameters) - , mIsFlashingAllowed(p.is_flashing_allowed) + : mIdentifier(p.name) + , mAvailableInToybox(p.available_in_toybox) + , mIcon(p.icon) + , mLabelRef(p.label_ref) + , mName(p.name) + , mTooltipRef(p.tooltip_ref) + , mExecuteFunction(p.execute_function) + , mExecuteParameters(p.execute_parameters) + , mExecuteStopFunction(p.execute_stop_function) + , mExecuteStopParameters(p.execute_stop_parameters) + , mIsEnabledFunction(p.is_enabled_function) + , mIsEnabledParameters(p.is_enabled_parameters) + , mIsRunningFunction(p.is_running_function) + , mIsRunningParameters(p.is_running_parameters) + , mIsStartingFunction(p.is_starting_function) + , mIsStartingParameters(p.is_starting_parameters) + , mIsFlashingAllowed(p.is_flashing_allowed) { } @@ -97,95 +97,95 @@ LLCommandManager::LLCommandManager() LLCommandManager::~LLCommandManager() { - for (CommandVector::iterator cmdIt = mCommands.begin(); cmdIt != mCommands.end(); ++cmdIt) - { - LLCommand * command = *cmdIt; + for (CommandVector::iterator cmdIt = mCommands.begin(); cmdIt != mCommands.end(); ++cmdIt) + { + LLCommand * command = *cmdIt; - delete command; - } + delete command; + } } U32 LLCommandManager::commandCount() const { - return mCommands.size(); + return mCommands.size(); } LLCommand * LLCommandManager::getCommand(U32 commandIndex) { - return mCommands[commandIndex]; + return mCommands[commandIndex]; } LLCommand * LLCommandManager::getCommand(const LLCommandId& commandId) { - LLCommand * command_match = NULL; + LLCommand * command_match = NULL; + + CommandIndexMap::const_iterator found = mCommandIndices.find(commandId.uuid()); - CommandIndexMap::const_iterator found = mCommandIndices.find(commandId.uuid()); - - if (found != mCommandIndices.end()) - { - command_match = mCommands[found->second]; - } + if (found != mCommandIndices.end()) + { + command_match = mCommands[found->second]; + } - return command_match; + return command_match; } LLCommand * LLCommandManager::getCommand(const std::string& name) { - LLCommand * command_match = NULL; - - CommandVector::const_iterator it = mCommands.begin(); - - while (it != mCommands.end()) - { + LLCommand * command_match = NULL; + + CommandVector::const_iterator it = mCommands.begin(); + + while (it != mCommands.end()) + { if ((*it)->name() == name) { command_match = *it; break; } it++; - } - - return command_match; + } + + return command_match; } void LLCommandManager::addCommand(LLCommand * command) { - LLCommandId command_id = command->id(); - mCommandIndices[command_id.uuid()] = mCommands.size(); - mCommands.push_back(command); + LLCommandId command_id = command->id(); + mCommandIndices[command_id.uuid()] = mCommands.size(); + mCommands.push_back(command); - LL_DEBUGS() << "Successfully added command: " << command->name() << LL_ENDL; + LL_DEBUGS() << "Successfully added command: " << command->name() << LL_ENDL; } //static bool LLCommandManager::load() { - LLCommandManager& mgr = LLCommandManager::instance(); + LLCommandManager& mgr = LLCommandManager::instance(); + + std::string commands_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "commands.xml"); - std::string commands_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "commands.xml"); + LLCommandManager::Params commandsParams; - LLCommandManager::Params commandsParams; + LLSimpleXUIParser parser; - LLSimpleXUIParser parser; - - if (!parser.readXUI(commands_file, commandsParams)) - { - LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL; - return false; - } + if (!parser.readXUI(commands_file, commandsParams)) + { + LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL; + return false; + } - if (!commandsParams.validateBlock()) - { - LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL; - return false; - } + if (!commandsParams.validateBlock()) + { + LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL; + return false; + } - for (const LLCommand::Params& commandParams : commandsParams.commands) - { - LLCommand * command = new LLCommand(commandParams); + for (const LLCommand::Params& commandParams : commandsParams.commands) + { + LLCommand * command = new LLCommand(commandParams); - mgr.addCommand(command); - } + mgr.addCommand(command); + } - return true; + return true; } diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index 8cec5e2b24..3b2586a5a1 100644 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -1,25 +1,25 @@ -/** +/** * @file llcommandmanager.h * @brief LLCommandManager class to hold commands * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,48 +38,48 @@ class LLCommandManager; class LLCommandId { public: - friend class LLCommand; - friend class LLCommandManager; - - struct Params : public LLInitParam::Block - { - Mandatory name; - - Params() - : name("name") - {} - }; - - LLCommandId(const std::string& name) - { - mUUID = LLUUID::generateNewID(name); - } - - LLCommandId(const Params& p) - { - mUUID = LLUUID::generateNewID(p.name); - } - - LLCommandId(const LLUUID& uuid) - : mUUID(uuid) - {} - - const LLUUID& uuid() const { return mUUID; } - - bool operator!=(const LLCommandId& command) const - { - return (mUUID != command.mUUID); - } - - bool operator==(const LLCommandId& command) const - { - return (mUUID == command.mUUID); - } - - static const LLCommandId null; + friend class LLCommand; + friend class LLCommandManager; + + struct Params : public LLInitParam::Block + { + Mandatory name; + + Params() + : name("name") + {} + }; + + LLCommandId(const std::string& name) + { + mUUID = LLUUID::generateNewID(name); + } + + LLCommandId(const Params& p) + { + mUUID = LLUUID::generateNewID(p.name); + } + + LLCommandId(const LLUUID& uuid) + : mUUID(uuid) + {} + + const LLUUID& uuid() const { return mUUID; } + + bool operator!=(const LLCommandId& command) const + { + return (mUUID != command.mUUID); + } + + bool operator==(const LLCommandId& command) const + { + return (mUUID == command.mUUID); + } + + static const LLCommandId null; private: - LLUUID mUUID; + LLUUID mUUID; }; typedef std::list command_id_list_t; @@ -88,121 +88,121 @@ typedef std::list command_id_list_t; class LLCommand { public: - struct Params : public LLInitParam::Block - { - Mandatory available_in_toybox; - Mandatory icon; - Mandatory label_ref; - Mandatory name; - Mandatory tooltip_ref; + struct Params : public LLInitParam::Block + { + Mandatory available_in_toybox; + Mandatory icon; + Mandatory label_ref; + Mandatory name; + Mandatory tooltip_ref; - Mandatory execute_function; - Optional execute_parameters; + Mandatory execute_function; + Optional execute_parameters; - Optional execute_stop_function; - Optional execute_stop_parameters; - - Optional is_enabled_function; - Optional is_enabled_parameters; + Optional execute_stop_function; + Optional execute_stop_parameters; - Optional is_running_function; - Optional is_running_parameters; + Optional is_enabled_function; + Optional is_enabled_parameters; - Optional is_starting_function; - Optional is_starting_parameters; + Optional is_running_function; + Optional is_running_parameters; - Optional is_flashing_allowed; + Optional is_starting_function; + Optional is_starting_parameters; - Params(); - }; + Optional is_flashing_allowed; - LLCommand(const LLCommand::Params& p); + Params(); + }; - const bool availableInToybox() const { return mAvailableInToybox; } - const std::string& icon() const { return mIcon; } - const LLCommandId& id() const { return mIdentifier; } - const std::string& labelRef() const { return mLabelRef; } - const std::string& name() const { return mName; } - const std::string& tooltipRef() const { return mTooltipRef; } + LLCommand(const LLCommand::Params& p); - const std::string& executeFunctionName() const { return mExecuteFunction; } - const LLSD& executeParameters() const { return mExecuteParameters; } + const bool availableInToybox() const { return mAvailableInToybox; } + const std::string& icon() const { return mIcon; } + const LLCommandId& id() const { return mIdentifier; } + const std::string& labelRef() const { return mLabelRef; } + const std::string& name() const { return mName; } + const std::string& tooltipRef() const { return mTooltipRef; } - const std::string& executeStopFunctionName() const { return mExecuteStopFunction; } - const LLSD& executeStopParameters() const { return mExecuteStopParameters; } - - const std::string& isEnabledFunctionName() const { return mIsEnabledFunction; } - const LLSD& isEnabledParameters() const { return mIsEnabledParameters; } + const std::string& executeFunctionName() const { return mExecuteFunction; } + const LLSD& executeParameters() const { return mExecuteParameters; } - const std::string& isRunningFunctionName() const { return mIsRunningFunction; } - const LLSD& isRunningParameters() const { return mIsRunningParameters; } + const std::string& executeStopFunctionName() const { return mExecuteStopFunction; } + const LLSD& executeStopParameters() const { return mExecuteStopParameters; } - const std::string& isStartingFunctionName() const { return mIsStartingFunction; } - const LLSD& isStartingParameters() const { return mIsStartingParameters; } + const std::string& isEnabledFunctionName() const { return mIsEnabledFunction; } + const LLSD& isEnabledParameters() const { return mIsEnabledParameters; } - bool isFlashingAllowed() const { return mIsFlashingAllowed; } + const std::string& isRunningFunctionName() const { return mIsRunningFunction; } + const LLSD& isRunningParameters() const { return mIsRunningParameters; } + + const std::string& isStartingFunctionName() const { return mIsStartingFunction; } + const LLSD& isStartingParameters() const { return mIsStartingParameters; } + + bool isFlashingAllowed() const { return mIsFlashingAllowed; } private: - LLCommandId mIdentifier; + LLCommandId mIdentifier; - bool mAvailableInToybox; - std::string mIcon; - std::string mLabelRef; - std::string mName; - std::string mTooltipRef; + bool mAvailableInToybox; + std::string mIcon; + std::string mLabelRef; + std::string mName; + std::string mTooltipRef; - std::string mExecuteFunction; - LLSD mExecuteParameters; + std::string mExecuteFunction; + LLSD mExecuteParameters; - std::string mExecuteStopFunction; - LLSD mExecuteStopParameters; - - std::string mIsEnabledFunction; - LLSD mIsEnabledParameters; + std::string mExecuteStopFunction; + LLSD mExecuteStopParameters; - std::string mIsRunningFunction; - LLSD mIsRunningParameters; + std::string mIsEnabledFunction; + LLSD mIsEnabledParameters; - std::string mIsStartingFunction; - LLSD mIsStartingParameters; + std::string mIsRunningFunction; + LLSD mIsRunningParameters; - bool mIsFlashingAllowed; + std::string mIsStartingFunction; + LLSD mIsStartingParameters; + + bool mIsFlashingAllowed; }; class LLCommandManager -: public LLSingleton +: public LLSingleton { - LLSINGLETON(LLCommandManager); - ~LLCommandManager(); + LLSINGLETON(LLCommandManager); + ~LLCommandManager(); public: - struct Params : public LLInitParam::Block - { - Multiple< LLCommand::Params, AtLeast<1> > commands; + struct Params : public LLInitParam::Block + { + Multiple< LLCommand::Params, AtLeast<1> > commands; - Params() - : commands("command") - { - } - }; + Params() + : commands("command") + { + } + }; - U32 commandCount() const; - LLCommand * getCommand(U32 commandIndex); - LLCommand * getCommand(const LLCommandId& commandId); - LLCommand * getCommand(const std::string& name); + U32 commandCount() const; + LLCommand * getCommand(U32 commandIndex); + LLCommand * getCommand(const LLCommandId& commandId); + LLCommand * getCommand(const std::string& name); - static bool load(); + static bool load(); protected: - void addCommand(LLCommand * command); + void addCommand(LLCommand * command); private: - typedef std::map CommandIndexMap; - typedef std::vector CommandVector; - - CommandVector mCommands; - CommandIndexMap mCommandIndices; + typedef std::map CommandIndexMap; + typedef std::vector CommandVector; + + CommandVector mCommands; + CommandIndexMap mCommandIndices; }; diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 8fc2978bdd..795bf1070a 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llconsole.cpp * @brief a scrolling console output device * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -52,352 +52,352 @@ extern void AddNewDebugConsoleToLCD(const LLWString &newLine); LLConsole* gConsole = NULL; // Created and destroyed in LLViewerWindow. const F32 FADE_DURATION = 2.f; - + static LLDefaultChildRegistry::Register r("console"); -LLConsole::LLConsole(const LLConsole::Params& p) -: LLUICtrl(p), - LLFixedBuffer(p.max_lines), - mLinePersistTime(p.persist_time), // seconds - mFont(p.font), - mConsoleWidth(0), - mConsoleHeight(0) +LLConsole::LLConsole(const LLConsole::Params& p) +: LLUICtrl(p), + LLFixedBuffer(p.max_lines), + mLinePersistTime(p.persist_time), // seconds + mFont(p.font), + mConsoleWidth(0), + mConsoleHeight(0) { - if (p.font_size_index.isProvided()) - { - setFontSize(p.font_size_index); - } - mFadeTime = mLinePersistTime - FADE_DURATION; - setMaxLines(LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines")); + if (p.font_size_index.isProvided()) + { + setFontSize(p.font_size_index); + } + mFadeTime = mLinePersistTime - FADE_DURATION; + setMaxLines(LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines")); } void LLConsole::setLinePersistTime(F32 seconds) { - mLinePersistTime = seconds; - mFadeTime = mLinePersistTime - FADE_DURATION; + mLinePersistTime = seconds; + mFadeTime = mLinePersistTime - FADE_DURATION; } void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent) { - S32 new_width = llmax(50, llmin(getRect().getWidth(), width)); - S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height)); - - if ( mConsoleWidth == new_width - && mConsoleHeight == new_height ) - { - return; - } - - mConsoleWidth = new_width; - mConsoleHeight= new_height; - - LLUICtrl::reshape(new_width, new_height, called_from_parent); - - for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) - { - (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); - } + S32 new_width = llmax(50, llmin(getRect().getWidth(), width)); + S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height)); + + if ( mConsoleWidth == new_width + && mConsoleHeight == new_height ) + { + return; + } + + mConsoleWidth = new_width; + mConsoleHeight= new_height; + + LLUICtrl::reshape(new_width, new_height, called_from_parent); + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } } void LLConsole::setFontSize(S32 size_index) { - if (-1 == size_index) - { - mFont = LLFontGL::getFontMonospace(); - } - else if (0 == size_index) - { - mFont = LLFontGL::getFontSansSerif(); - } - else if (1 == size_index) - { - mFont = LLFontGL::getFontSansSerifBig(); - } - else - { - mFont = LLFontGL::getFontSansSerifHuge(); - } - // Make sure the font exists - if (mFont == NULL) - { - mFont = LLFontGL::getFontDefault(); - } - - for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) - { - (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); - } + if (-1 == size_index) + { + mFont = LLFontGL::getFontMonospace(); + } + else if (0 == size_index) + { + mFont = LLFontGL::getFontSansSerif(); + } + else if (1 == size_index) + { + mFont = LLFontGL::getFontSansSerifBig(); + } + else + { + mFont = LLFontGL::getFontSansSerifHuge(); + } + // Make sure the font exists + if (mFont == NULL) + { + mFont = LLFontGL::getFontDefault(); + } + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } } void LLConsole::draw() { - // Units in pixels - static const F32 padding_horizontal = 10; - static const F32 padding_vertical = 3; - LLGLSUIDefault gls_ui; - - // skip lines added more than mLinePersistTime ago - F32 cur_time = mTimer.getElapsedTimeF32(); - - F32 skip_time = cur_time - mLinePersistTime; - F32 fade_time = cur_time - mFadeTime; - - if (mParagraphs.empty()) //No text to draw. - { - return; - } - - U32 num_lines=0; - - paragraph_t::reverse_iterator paragraph_it; - paragraph_it = mParagraphs.rbegin(); - U32 paragraph_num=mParagraphs.size(); - - while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) - { - num_lines += (*paragraph_it).mLines.size(); - if(num_lines > mMaxLines - || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) - { //All lines above here are done. Lose them. - for (U32 i=0;i console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f); - F32 console_opacity = llclamp(console_bg_opacity(), 0.f, 1.f); - - LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground"); - color.mV[VALPHA] *= console_opacity; - - F32 line_height = mFont->getLineHeight(); - - for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) - { - S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + padding_vertical); - S32 target_width = llfloor( (*paragraph_it).mMaxWidth + padding_horizontal); - - y_pos += ((*paragraph_it).mLines.size()) * line_height; - imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); - - F32 y_off=0; - - F32 alpha; - - if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) - { - alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); - } - else - { - alpha = 1.0f; - } - - if( alpha > 0.f ) - { - for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); - line_it != (*paragraph_it).mLines.end(); - line_it ++) - { - for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); - seg_it != (*line_it).mLineColorSegments.end(); - seg_it++) - { - mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, - LLColor4( - (*seg_it).mColor.mV[VRED], - (*seg_it).mColor.mV[VGREEN], - (*seg_it).mColor.mV[VBLUE], - (*seg_it).mColor.mV[VALPHA]*alpha), - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW, - S32_MAX, - target_width - ); - } - y_off += line_height; - } - } - y_pos += padding_vertical; - } + // Units in pixels + static const F32 padding_horizontal = 10; + static const F32 padding_vertical = 3; + LLGLSUIDefault gls_ui; + + // skip lines added more than mLinePersistTime ago + F32 cur_time = mTimer.getElapsedTimeF32(); + + F32 skip_time = cur_time - mLinePersistTime; + F32 fade_time = cur_time - mFadeTime; + + if (mParagraphs.empty()) //No text to draw. + { + return; + } + + U32 num_lines=0; + + paragraph_t::reverse_iterator paragraph_it; + paragraph_it = mParagraphs.rbegin(); + U32 paragraph_num=mParagraphs.size(); + + while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) + { + num_lines += (*paragraph_it).mLines.size(); + if(num_lines > mMaxLines + || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) + { //All lines above here are done. Lose them. + for (U32 i=0;i console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f); + F32 console_opacity = llclamp(console_bg_opacity(), 0.f, 1.f); + + LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground"); + color.mV[VALPHA] *= console_opacity; + + F32 line_height = mFont->getLineHeight(); + + for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) + { + S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + padding_vertical); + S32 target_width = llfloor( (*paragraph_it).mMaxWidth + padding_horizontal); + + y_pos += ((*paragraph_it).mLines.size()) * line_height; + imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); + + F32 y_off=0; + + F32 alpha; + + if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) + { + alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); + } + else + { + alpha = 1.0f; + } + + if( alpha > 0.f ) + { + for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); + line_it != (*paragraph_it).mLines.end(); + line_it ++) + { + for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); + seg_it != (*line_it).mLineColorSegments.end(); + seg_it++) + { + mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, + LLColor4( + (*seg_it).mColor.mV[VRED], + (*seg_it).mColor.mV[VGREEN], + (*seg_it).mColor.mV[VBLUE], + (*seg_it).mColor.mV[VALPHA]*alpha), + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::NORMAL, + LLFontGL::DROP_SHADOW, + S32_MAX, + target_width + ); + } + y_off += line_height; + } + } + y_pos += padding_vertical; + } } //Generate highlight color segments for this paragraph. Pass in default color of paragraph. -void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) +void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) { - LLSD paragraph_color_segments; - paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); - LLSD color_sd = color.getValue(); - paragraph_color_segments[0]["color"]=color_sd; - - for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray(); - color_segment_it != paragraph_color_segments.endArray(); - ++color_segment_it) - { - LLSD color_llsd = (*color_segment_it)["color"]; - std::string color_str = (*color_segment_it)["text"].asString(); - - ParagraphColorSegment color_segment; - - color_segment.mColor.setValue(color_llsd); - color_segment.mNumChars = color_str.length(); - - mParagraphColorSegments.push_back(color_segment); - } + LLSD paragraph_color_segments; + paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); + LLSD color_sd = color.getValue(); + paragraph_color_segments[0]["color"]=color_sd; + + for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray(); + color_segment_it != paragraph_color_segments.endArray(); + ++color_segment_it) + { + LLSD color_llsd = (*color_segment_it)["color"]; + std::string color_str = (*color_segment_it)["text"].asString(); + + ParagraphColorSegment color_segment; + + color_segment.mColor.setValue(color_llsd); + color_segment.mNumChars = color_str.length(); + + mParagraphColorSegments.push_back(color_segment); + } } //Called when a paragraph is added to the console or window is resized. void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, bool force_resize) { - if ( !force_resize ) - { - if ( mMaxWidth >= 0.0f - && mMaxWidth < screen_width ) - { - return; //No resize required. - } - } - - screen_width = screen_width - 30; //Margin for small windows. - - if ( mParagraphText.empty() - || mParagraphColorSegments.empty() - || font == NULL) - { - return; //Not enough info to complete. - } - - mLines.clear(); //Chuck everything. - mMaxWidth = 0.0f; - - paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin(); - U32 current_color_length = (*current_color).mNumChars; - - S32 paragraph_offset = 0; //Offset into the paragraph text. - - // Wrap lines that are longer than the view is wide. - while( paragraph_offset < (S32)mParagraphText.length() && - mParagraphText[paragraph_offset] != 0) - { - S32 skip_chars; // skip '\n' - // Figure out if a word-wrapped line fits here. - LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('\n'), paragraph_offset); - if (line_end != LLWString::npos) - { - skip_chars = 1; // skip '\n' - } - else - { - line_end = mParagraphText.size(); - skip_chars = 0; - } - - U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, LLFontGL::WORD_BOUNDARY_IF_POSSIBLE); - - if (drawable != 0) - { - F32 x_position = 0; //Screen X position of text. - - mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); - Line line; - - U32 left_to_draw = drawable; - U32 drawn = 0; - - while (left_to_draw >= current_color_length - && current_color != mParagraphColorSegments.end() ) - { - LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); - line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. - (*current_color).mColor, - x_position ) ); - - x_position += font->getWidth( color_text.c_str() ); //Set up next screen position. - - drawn += current_color_length; - left_to_draw -= current_color_length; - - current_color++; //Goto next paragraph color record. - - if (current_color != mParagraphColorSegments.end()) - { - current_color_length = (*current_color).mNumChars; - } - } - - if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() ) - { - LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); - - line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. - (*current_color).mColor, - x_position ) ); - - current_color_length -= left_to_draw; - } - mLines.push_back(line); //Append line to paragraph line list. - } - paragraph_offset += (drawable + skip_chars); - } + if ( !force_resize ) + { + if ( mMaxWidth >= 0.0f + && mMaxWidth < screen_width ) + { + return; //No resize required. + } + } + + screen_width = screen_width - 30; //Margin for small windows. + + if ( mParagraphText.empty() + || mParagraphColorSegments.empty() + || font == NULL) + { + return; //Not enough info to complete. + } + + mLines.clear(); //Chuck everything. + mMaxWidth = 0.0f; + + paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin(); + U32 current_color_length = (*current_color).mNumChars; + + S32 paragraph_offset = 0; //Offset into the paragraph text. + + // Wrap lines that are longer than the view is wide. + while( paragraph_offset < (S32)mParagraphText.length() && + mParagraphText[paragraph_offset] != 0) + { + S32 skip_chars; // skip '\n' + // Figure out if a word-wrapped line fits here. + LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('\n'), paragraph_offset); + if (line_end != LLWString::npos) + { + skip_chars = 1; // skip '\n' + } + else + { + line_end = mParagraphText.size(); + skip_chars = 0; + } + + U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, LLFontGL::WORD_BOUNDARY_IF_POSSIBLE); + + if (drawable != 0) + { + F32 x_position = 0; //Screen X position of text. + + mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); + Line line; + + U32 left_to_draw = drawable; + U32 drawn = 0; + + while (left_to_draw >= current_color_length + && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + x_position += font->getWidth( color_text.c_str() ); //Set up next screen position. + + drawn += current_color_length; + left_to_draw -= current_color_length; + + current_color++; //Goto next paragraph color record. + + if (current_color != mParagraphColorSegments.end()) + { + current_color_length = (*current_color).mNumChars; + } + } + + if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); + + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + current_color_length -= left_to_draw; + } + mLines.push_back(line); //Append line to paragraph line list. + } + paragraph_offset += (drawable + skip_chars); + } } //Pass in the string and the default color for this block of text. -LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width) -: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) +LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width) +: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) { - makeParagraphColorSegments(color); - updateLines( screen_width, font ); + makeParagraphColorSegments(color); + updateLines( screen_width, font ); } - + // called once per frame regardless of console visibility // static void LLConsole::updateClass() -{ - for (auto& con : instance_snapshot()) - { - con.update(); - } +{ + for (auto& con : instance_snapshot()) + { + con.update(); + } } void LLConsole::update() { - { - LLMutexLock lock(&mMutex); - - while (!mLines.empty()) - { - mParagraphs.push_back( - Paragraph( mLines.front(), - LLColor4::white, - mTimer.getElapsedTimeF32(), - mFont, - (F32)getRect().getWidth())); - mLines.pop_front(); - } - } - - // remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible) - while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines))) - { - mParagraphs.pop_front(); - } + { + LLMutexLock lock(&mMutex); + + while (!mLines.empty()) + { + mParagraphs.push_back( + Paragraph( mLines.front(), + LLColor4::white, + mTimer.getElapsedTimeF32(), + mFont, + (F32)getRect().getWidth())); + mLines.pop_front(); + } + } + + // remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible) + while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines))) + { + mParagraphs.pop_front(); + } } diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index 04f5e71609..d3dc1bbfde 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -1,25 +1,25 @@ -/** +/** * @file llconsole.h * @brief a simple console-style output device * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,116 +38,116 @@ class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracke { public: - typedef enum e_font_size - { - MONOSPACE = -1, - SMALL = 0, - BIG = 1 - } EFontSize; - - struct Params : public LLInitParam::Block - { - Optional max_lines; - Optional persist_time; - Optional font_size_index; - Params() - : max_lines("max_lines", LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines")), - persist_time("persist_time", 0.f), // forever - font_size_index("font_size_index") - { - changeDefault(mouse_opaque, false); - } - }; + typedef enum e_font_size + { + MONOSPACE = -1, + SMALL = 0, + BIG = 1 + } EFontSize; + + struct Params : public LLInitParam::Block + { + Optional max_lines; + Optional persist_time; + Optional font_size_index; + Params() + : max_lines("max_lines", LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines")), + persist_time("persist_time", 0.f), // forever + font_size_index("font_size_index") + { + changeDefault(mouse_opaque, false); + } + }; protected: - LLConsole(const Params&); - friend class LLUICtrlFactory; + LLConsole(const Params&); + friend class LLUICtrlFactory; public: - // call once per frame to pull data out of LLFixedBuffer - static void updateClass(); - - //A paragraph color segment defines the color of text in a line - //of text that was received for console display. It has no - //notion of line wraps, screen position, or the text it contains. - //It is only the number of characters that are a color and the - //color. - struct ParagraphColorSegment - { - S32 mNumChars; - LLColor4 mColor; - }; - - //A line color segment is a chunk of text, the color associated - //with it, and the X Position it was calculated to begin at - //on the screen. X Positions are re-calculated if the - //screen changes size. - class LineColorSegment - { - public: - LineColorSegment(LLWString text, LLColor4 color, F32 xpos) : mText(text), mColor(color), mXPosition(xpos) {} - public: - LLWString mText; - LLColor4 mColor; - F32 mXPosition; - }; - - typedef std::list line_color_segments_t; - - //A line is composed of one or more color segments. - class Line - { - public: - line_color_segments_t mLineColorSegments; - }; - - typedef std::list lines_t; - typedef std::list paragraph_color_segments_t; - - //A paragraph is a processed element containing the entire text of the - //message (used for recalculating positions on screen resize) - //The time this message was added to the console output - //The visual screen width of the longest line in this block - //And a list of one or more lines which are used to display this message. - class Paragraph - { - public: - Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width); - void makeParagraphColorSegments ( const LLColor4 &color); - void updateLines ( F32 screen_width, const LLFontGL* font, bool force_resize=false ); - public: - LLWString mParagraphText; //The entire text of the paragraph - paragraph_color_segments_t mParagraphColorSegments; - F32 mAddTime; //Time this paragraph was added to the display. - F32 mMaxWidth; //Width of the widest line of text in this paragraph. - lines_t mLines; - - }; - - //The console contains a deque of paragraphs which represent the individual messages. - typedef std::deque paragraph_t; - paragraph_t mParagraphs; - - ~LLConsole(){}; - - // each line lasts this long after being added - void setLinePersistTime(F32 seconds); - - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - - // -1 = monospace, 0 means small, font size = 1 means big - void setFontSize(S32 size_index); - - - // Overrides - /*virtual*/ void draw(); + // call once per frame to pull data out of LLFixedBuffer + static void updateClass(); + + //A paragraph color segment defines the color of text in a line + //of text that was received for console display. It has no + //notion of line wraps, screen position, or the text it contains. + //It is only the number of characters that are a color and the + //color. + struct ParagraphColorSegment + { + S32 mNumChars; + LLColor4 mColor; + }; + + //A line color segment is a chunk of text, the color associated + //with it, and the X Position it was calculated to begin at + //on the screen. X Positions are re-calculated if the + //screen changes size. + class LineColorSegment + { + public: + LineColorSegment(LLWString text, LLColor4 color, F32 xpos) : mText(text), mColor(color), mXPosition(xpos) {} + public: + LLWString mText; + LLColor4 mColor; + F32 mXPosition; + }; + + typedef std::list line_color_segments_t; + + //A line is composed of one or more color segments. + class Line + { + public: + line_color_segments_t mLineColorSegments; + }; + + typedef std::list lines_t; + typedef std::list paragraph_color_segments_t; + + //A paragraph is a processed element containing the entire text of the + //message (used for recalculating positions on screen resize) + //The time this message was added to the console output + //The visual screen width of the longest line in this block + //And a list of one or more lines which are used to display this message. + class Paragraph + { + public: + Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width); + void makeParagraphColorSegments ( const LLColor4 &color); + void updateLines ( F32 screen_width, const LLFontGL* font, bool force_resize=false ); + public: + LLWString mParagraphText; //The entire text of the paragraph + paragraph_color_segments_t mParagraphColorSegments; + F32 mAddTime; //Time this paragraph was added to the display. + F32 mMaxWidth; //Width of the widest line of text in this paragraph. + lines_t mLines; + + }; + + //The console contains a deque of paragraphs which represent the individual messages. + typedef std::deque paragraph_t; + paragraph_t mParagraphs; + + ~LLConsole(){}; + + // each line lasts this long after being added + void setLinePersistTime(F32 seconds); + + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + // -1 = monospace, 0 means small, font size = 1 means big + void setFontSize(S32 size_index); + + + // Overrides + /*virtual*/ void draw(); private: - void update(); + void update(); - F32 mLinePersistTime; // Age at which to stop drawing. - F32 mFadeTime; // Age at which to start fading - const LLFontGL* mFont; - S32 mConsoleWidth; - S32 mConsoleHeight; + F32 mLinePersistTime; // Age at which to stop drawing. + F32 mFadeTime; // Age at which to start fading + const LLFontGL* mFont; + S32 mConsoleWidth; + S32 mConsoleHeight; }; diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index 1c33088e8d..f01d66382c 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcontainerview.cpp * @brief Container for all statistics info * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,257 +44,257 @@ static ContainerViewRegistry::Register r2("stat_view"); static ContainerViewRegistry::Register r3("panel", &LLPanel::fromXML); LLContainerView::LLContainerView(const LLContainerView::Params& p) -: LLView(p), - mShowLabel(p.show_label), - mLabel(p.label), - mDisplayChildren(p.display_children) +: LLView(p), + mShowLabel(p.show_label), + mLabel(p.label), + mDisplayChildren(p.display_children) { - mScrollContainer = NULL; + mScrollContainer = NULL; } LLContainerView::~LLContainerView() { - // Children all cleaned up by default view destructor. + // Children all cleaned up by default view destructor. } BOOL LLContainerView::postBuild() { - setDisplayChildren(mDisplayChildren); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); - return TRUE; + setDisplayChildren(mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + return TRUE; } bool LLContainerView::addChild(LLView* child, S32 tab_group) { - bool res = LLView::addChild(child, tab_group); - if (res) - { - sendChildToBack(child); - } - return res; + bool res = LLView::addChild(child, tab_group); + if (res) + { + sendChildToBack(child); + } + return res; } BOOL LLContainerView::handleDoubleClick(S32 x, S32 y, MASK mask) { - return handleMouseDown(x, y, mask); + return handleMouseDown(x, y, mask); } BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - if (mDisplayChildren) - { - handled = (LLView::childrenHandleMouseDown(x, y, mask) != NULL); - } - if (!handled) - { - if( mShowLabel && (y >= getRect().getHeight() - 10) ) - { - setDisplayChildren(!mDisplayChildren); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); - handled = TRUE; - } - } - return handled; + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseDown(x, y, mask) != NULL); + } + if (!handled) + { + if( mShowLabel && (y >= getRect().getHeight() - 10) ) + { + setDisplayChildren(!mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + handled = TRUE; + } + } + return handled; } BOOL LLContainerView::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - if (mDisplayChildren) - { - handled = (LLView::childrenHandleMouseUp(x, y, mask) != NULL); - } - return handled; + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseUp(x, y, mask) != NULL); + } + return handled; } void LLContainerView::draw() { - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); - } - - // Draw the label - if (mShowLabel) - { - LLFontGL::getFontMonospace()->renderUTF8( - mLabel, 0, 2, getRect().getHeight() - 2, LLColor4(1,1,1,1), LLFontGL::LEFT, LLFontGL::TOP); - } - - LLView::draw(); + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); + } + + // Draw the label + if (mShowLabel) + { + LLFontGL::getFontMonospace()->renderUTF8( + mLabel, 0, 2, getRect().getHeight() - 2, LLColor4(1,1,1,1), LLFontGL::LEFT, LLFontGL::TOP); + } + + LLView::draw(); } void LLContainerView::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLRect scroller_rect; - scroller_rect.setOriginAndSize(0, 0, width, height); - - if (mScrollContainer) - { - scroller_rect = mScrollContainer->getContentWindowRect(); - } - else - { - // if we're uncontained - make height as small as possible - scroller_rect.mTop = 0; - } - - arrange(scroller_rect.getWidth(), scroller_rect.getHeight(), called_from_parent); - - // sometimes, after layout, our container will change size (scrollbars popping in and out) - // if so, attempt another layout - if (mScrollContainer) - { - LLRect new_container_rect = mScrollContainer->getContentWindowRect(); - - if ((new_container_rect.getWidth() != scroller_rect.getWidth()) || - (new_container_rect.getHeight() != scroller_rect.getHeight())) // the container size has changed, attempt to arrange again - { - arrange(new_container_rect.getWidth(), new_container_rect.getHeight(), called_from_parent); - } - } + LLRect scroller_rect; + scroller_rect.setOriginAndSize(0, 0, width, height); + + if (mScrollContainer) + { + scroller_rect = mScrollContainer->getContentWindowRect(); + } + else + { + // if we're uncontained - make height as small as possible + scroller_rect.mTop = 0; + } + + arrange(scroller_rect.getWidth(), scroller_rect.getHeight(), called_from_parent); + + // sometimes, after layout, our container will change size (scrollbars popping in and out) + // if so, attempt another layout + if (mScrollContainer) + { + LLRect new_container_rect = mScrollContainer->getContentWindowRect(); + + if ((new_container_rect.getWidth() != scroller_rect.getWidth()) || + (new_container_rect.getHeight() != scroller_rect.getHeight())) // the container size has changed, attempt to arrange again + { + arrange(new_container_rect.getWidth(), new_container_rect.getHeight(), called_from_parent); + } + } } void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent) { - // Determine the sizes and locations of all contained views - S32 total_height = 0; - S32 top, left, right, bottom; - //LLView *childp; - - // These will be used for the children - left = 10; - top = getRect().getHeight() - 4; - right = width - 2; - bottom = top; - - // Leave some space for the top label/grab handle - if (mShowLabel) - { - total_height += 20; - } - - if (mDisplayChildren) - { - // Determine total height - U32 child_height = 0; - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *childp = *child_iter; - if (!childp->getVisible()) - { - LL_WARNS() << "Incorrect visibility!" << LL_ENDL; - } - LLRect child_rect = childp->getRequiredRect(); - child_height += child_rect.getHeight(); - child_height += 2; - } - total_height += child_height; - } - - if (total_height < height) - total_height = height; - - LLRect my_rect = getRect(); - if (followsTop()) - { - my_rect.mBottom = my_rect.mTop - total_height; - } - else - { - my_rect.mTop = my_rect.mBottom + total_height; - } - - my_rect.mRight = my_rect.mLeft + width; - setRect(my_rect); - - top = total_height; - if (mShowLabel) - { - top -= 20; - } - - bottom = top; - - if (mDisplayChildren) - { - // Iterate through all children, and put in container from top down. - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *childp = *child_iter; - LLRect child_rect = childp->getRequiredRect(); - bottom -= child_rect.getHeight(); - LLRect r(left, bottom + child_rect.getHeight(), right, bottom); - childp->setRect(r); - childp->reshape(right - left, top - bottom); - top = bottom - 2; - bottom = top; - } - } - - if (!called_from_parent) - { - if (getParent()) - { - getParent()->reshape(getParent()->getRect().getWidth(), getParent()->getRect().getHeight(), FALSE); - } - } + // Determine the sizes and locations of all contained views + S32 total_height = 0; + S32 top, left, right, bottom; + //LLView *childp; + + // These will be used for the children + left = 10; + top = getRect().getHeight() - 4; + right = width - 2; + bottom = top; + + // Leave some space for the top label/grab handle + if (mShowLabel) + { + total_height += 20; + } + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + if (!childp->getVisible()) + { + LL_WARNS() << "Incorrect visibility!" << LL_ENDL; + } + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + total_height += child_height; + } + + if (total_height < height) + total_height = height; + + LLRect my_rect = getRect(); + if (followsTop()) + { + my_rect.mBottom = my_rect.mTop - total_height; + } + else + { + my_rect.mTop = my_rect.mBottom + total_height; + } + + my_rect.mRight = my_rect.mLeft + width; + setRect(my_rect); + + top = total_height; + if (mShowLabel) + { + top -= 20; + } + + bottom = top; + + if (mDisplayChildren) + { + // Iterate through all children, and put in container from top down. + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + bottom -= child_rect.getHeight(); + LLRect r(left, bottom + child_rect.getHeight(), right, bottom); + childp->setRect(r); + childp->reshape(right - left, top - bottom); + top = bottom - 2; + bottom = top; + } + } + + if (!called_from_parent) + { + if (getParent()) + { + getParent()->reshape(getParent()->getRect().getWidth(), getParent()->getRect().getHeight(), FALSE); + } + } } LLRect LLContainerView::getRequiredRect() { - LLRect req_rect; - //LLView *childp; - U32 total_height = 0; - - // Determine the sizes and locations of all contained views - - // Leave some space for the top label/grab handle - - if (mShowLabel) - { - total_height = 20; - } - - - if (mDisplayChildren) - { - // Determine total height - U32 child_height = 0; - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *childp = *child_iter; - LLRect child_rect = childp->getRequiredRect(); - child_height += child_rect.getHeight(); - child_height += 2; - } - - total_height += child_height; - } - req_rect.mTop = total_height; - return req_rect; + LLRect req_rect; + //LLView *childp; + U32 total_height = 0; + + // Determine the sizes and locations of all contained views + + // Leave some space for the top label/grab handle + + if (mShowLabel) + { + total_height = 20; + } + + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + + total_height += child_height; + } + req_rect.mTop = total_height; + return req_rect; } void LLContainerView::setLabel(const std::string& label) { - mLabel = label; + mLabel = label; } void LLContainerView::setDisplayChildren(BOOL displayChildren) { - mDisplayChildren = displayChildren; - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *childp = *child_iter; - childp->setVisible(mDisplayChildren); - } + mDisplayChildren = displayChildren; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + childp->setVisible(mDisplayChildren); + } } diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index 8e75aaef6e..118d3a967c 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -1,25 +1,25 @@ -/** +/** * @file llcontainerview.h * @brief Container for all statistics info. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,59 +36,59 @@ class LLScrollContainer; struct ContainerViewRegistry : public LLChildRegistry { - LLSINGLETON_EMPTY_CTOR(ContainerViewRegistry); + LLSINGLETON_EMPTY_CTOR(ContainerViewRegistry); }; class LLContainerView : public LLView { public: - struct Params : public LLInitParam::Block - { - Optional label; - Optional show_label; - Optional display_children; - Params() - : label("label"), - show_label("show_label", FALSE), - display_children("display_children", TRUE) - { - changeDefault(mouse_opaque, false); - } - }; + struct Params : public LLInitParam::Block + { + Optional label; + Optional show_label; + Optional display_children; + Params() + : label("label"), + show_label("show_label", FALSE), + display_children("display_children", TRUE) + { + changeDefault(mouse_opaque, false); + } + }; + + // my valid children are stored in this registry + typedef ContainerViewRegistry child_registry_t; - // my valid children are stored in this registry - typedef ContainerViewRegistry child_registry_t; - protected: - LLContainerView(const Params& p); - friend class LLUICtrlFactory; + LLContainerView(const Params& p); + friend class LLUICtrlFactory; public: - ~LLContainerView(); + ~LLContainerView(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); - /*virtual*/ BOOL postBuild(); - /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); - - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ void draw(); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. + /*virtual*/ void draw(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. - void setLabel(const std::string& label); - void showLabel(BOOL show) { mShowLabel = show; } - void setDisplayChildren(BOOL displayChildren); - BOOL getDisplayChildren() { return mDisplayChildren; } - void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} + void setLabel(const std::string& label); + void showLabel(BOOL show) { mShowLabel = show; } + void setDisplayChildren(BOOL displayChildren); + BOOL getDisplayChildren() { return mDisplayChildren; } + void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} private: - LLScrollContainer* mScrollContainer; - void arrange(S32 width, S32 height, BOOL called_from_parent = TRUE); - BOOL mShowLabel; + LLScrollContainer* mScrollContainer; + void arrange(S32 width, S32 height, BOOL called_from_parent = TRUE); + BOOL mShowLabel; protected: - BOOL mDisplayChildren; - std::string mLabel; + BOOL mDisplayChildren; + std::string mLabel; }; #endif // LL_CONTAINERVIEW_ diff --git a/indra/llui/llctrlselectioninterface.cpp b/indra/llui/llctrlselectioninterface.cpp index 7e886aff48..10e5a75bff 100644 --- a/indra/llui/llctrlselectioninterface.cpp +++ b/indra/llui/llctrlselectioninterface.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llctrlselectioninterface.cpp * @brief Programmatic selection of items in a list. * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,12 +35,12 @@ LLCtrlSelectionInterface::~LLCtrlSelectionInterface() BOOL LLCtrlSelectionInterface::selectByValue(LLSD value) { - return setSelectedByValue(value, TRUE); + return setSelectedByValue(value, TRUE); } BOOL LLCtrlSelectionInterface::deselectByValue(LLSD value) -{ - return setSelectedByValue(value, FALSE); +{ + return setSelectedByValue(value, FALSE); } @@ -50,12 +50,12 @@ LLCtrlListInterface::~LLCtrlListInterface() LLScrollListItem* LLCtrlListInterface::addSimpleElement(const std::string& value) { - return addSimpleElement(value, ADD_BOTTOM, LLSD()); + return addSimpleElement(value, ADD_BOTTOM, LLSD()); } LLScrollListItem* LLCtrlListInterface::addSimpleElement(const std::string& value, EAddPosition pos) { - return addSimpleElement(value, pos, LLSD()); + return addSimpleElement(value, pos, LLSD()); } // virtual diff --git a/indra/llui/llctrlselectioninterface.h b/indra/llui/llctrlselectioninterface.h index a7b089c8f9..56dd7a7415 100644 --- a/indra/llui/llctrlselectioninterface.h +++ b/indra/llui/llctrlselectioninterface.h @@ -1,25 +1,25 @@ -/** +/** * @file llctrlselectioninterface.h * @brief Programmatic selection of items in a list. * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,67 +38,67 @@ class LLScrollListItem; class LLCtrlSelectionInterface { public: - virtual ~LLCtrlSelectionInterface(); - - enum EOperation - { - OP_DELETE = 1, - OP_SELECT, - OP_DESELECT, - }; + virtual ~LLCtrlSelectionInterface(); + + enum EOperation + { + OP_DELETE = 1, + OP_SELECT, + OP_DESELECT, + }; - virtual BOOL getCanSelect() const = 0; + virtual BOOL getCanSelect() const = 0; - virtual S32 getItemCount() const = 0; + virtual S32 getItemCount() const = 0; - virtual BOOL selectFirstItem() = 0; - virtual BOOL selectNthItem( S32 index ) = 0; - virtual BOOL selectItemRange( S32 first, S32 last ) = 0; + virtual BOOL selectFirstItem() = 0; + virtual BOOL selectNthItem( S32 index ) = 0; + virtual BOOL selectItemRange( S32 first, S32 last ) = 0; - virtual S32 getFirstSelectedIndex() const = 0; + virtual S32 getFirstSelectedIndex() const = 0; - // TomY TODO: Simply cast the UUIDs to LLSDs, using the selectByValue function - virtual BOOL setCurrentByID( const LLUUID& id ) = 0; - virtual LLUUID getCurrentID() const = 0; + // TomY TODO: Simply cast the UUIDs to LLSDs, using the selectByValue function + virtual BOOL setCurrentByID( const LLUUID& id ) = 0; + virtual LLUUID getCurrentID() const = 0; - BOOL selectByValue(const LLSD value); - BOOL deselectByValue(const LLSD value); - virtual BOOL setSelectedByValue(const LLSD& value, BOOL selected) = 0; - virtual LLSD getSelectedValue() = 0; + BOOL selectByValue(const LLSD value); + BOOL deselectByValue(const LLSD value); + virtual BOOL setSelectedByValue(const LLSD& value, BOOL selected) = 0; + virtual LLSD getSelectedValue() = 0; - virtual BOOL isSelected(const LLSD& value) const = 0; + virtual BOOL isSelected(const LLSD& value) const = 0; - virtual BOOL operateOnSelection(EOperation op) = 0; - virtual BOOL operateOnAll(EOperation op) = 0; + virtual BOOL operateOnSelection(EOperation op) = 0; + virtual BOOL operateOnAll(EOperation op) = 0; }; class LLCtrlListInterface : public LLCtrlSelectionInterface { public: - virtual ~LLCtrlListInterface(); - - virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0; - virtual void clearColumns() = 0; - virtual void setColumnLabel(const std::string& column, const std::string& label) = 0; - // TomY TODO: Document this - virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL) = 0; - - LLScrollListItem* addSimpleElement(const std::string& value); // defaults to bottom - LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos); // defaults to no LLSD() id - virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) = 0; - - virtual void clearRows() = 0; - virtual void sortByColumn(const std::string& name, BOOL ascending) = 0; + virtual ~LLCtrlListInterface(); + + virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0; + virtual void clearColumns() = 0; + virtual void setColumnLabel(const std::string& column, const std::string& label) = 0; + // TomY TODO: Document this + virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL) = 0; + + LLScrollListItem* addSimpleElement(const std::string& value); // defaults to bottom + LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos); // defaults to no LLSD() id + virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) = 0; + + virtual void clearRows() = 0; + virtual void sortByColumn(const std::string& name, BOOL ascending) = 0; }; class LLCtrlScrollInterface { public: - virtual ~LLCtrlScrollInterface(); - - virtual S32 getScrollPos() const = 0; - virtual void setScrollPos( S32 pos ) = 0; - virtual void scrollToShowSelected() = 0; + virtual ~LLCtrlScrollInterface(); + + virtual S32 getScrollPos() const = 0; + virtual void setScrollPos( S32 pos ) = 0; + virtual void scrollToShowSelected() = 0; }; #endif diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index c937d190c6..22e1ac4334 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldockablefloater.cpp * @brief Creates a panel of a specific kind for a toast * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,39 +35,39 @@ LLHandle LLDockableFloater::sInstanceHandle; //static void LLDockableFloater::init(LLDockableFloater* thiz) { - thiz->setDocked(thiz->mDockControl.get() != NULL - && thiz->mDockControl.get()->isDockVisible()); - thiz->resetInstance(); + thiz->setDocked(thiz->mDockControl.get() != NULL + && thiz->mDockControl.get()->isDockVisible()); + thiz->resetInstance(); - // all dockable floaters should have close, dock and minimize buttons - thiz->setCanClose(TRUE); - thiz->setCanDock(true); - thiz->setCanMinimize(TRUE); - thiz->setOverlapsScreenChannel(false); - thiz->mForceDocking = false; + // all dockable floaters should have close, dock and minimize buttons + thiz->setCanClose(TRUE); + thiz->setCanDock(true); + thiz->setCanMinimize(TRUE); + thiz->setOverlapsScreenChannel(false); + thiz->mForceDocking = false; } LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, - const LLSD& key, const Params& params) : - LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true) + const LLSD& key, const Params& params) : + LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true) { - init(this); - mUseTongue = true; + init(this); + mUseTongue = true; } LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, - const LLSD& key, const Params& params) : - LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(uniqueDocking) + const LLSD& key, const Params& params) : + LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(uniqueDocking) { - init(this); - mUseTongue = true; + init(this); + mUseTongue = true; } LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, - bool useTongue, const LLSD& key, const Params& params) : - LLFloater(key, params), mDockControl(dockControl), mUseTongue(useTongue), mUniqueDocking(uniqueDocking) + bool useTongue, const LLSD& key, const Params& params) : + LLFloater(key, params), mDockControl(dockControl), mUseTongue(useTongue), mUniqueDocking(uniqueDocking) { - init(this); + init(this); } LLDockableFloater::~LLDockableFloater() @@ -76,188 +76,188 @@ LLDockableFloater::~LLDockableFloater() BOOL LLDockableFloater::postBuild() { - // Remember we should force docking when the floater is opened for the first time - if (mIsDockedStateForcedCallback != NULL && mIsDockedStateForcedCallback()) - { - mForceDocking = true; - } + // Remember we should force docking when the floater is opened for the first time + if (mIsDockedStateForcedCallback != NULL && mIsDockedStateForcedCallback()) + { + mForceDocking = true; + } - mDockTongue = LLUI::getUIImage("Flyout_Pointer"); - LLFloater::setDocked(true); - return LLView::postBuild(); + mDockTongue = LLUI::getUIImage("Flyout_Pointer"); + LLFloater::setDocked(true); + return LLView::postBuild(); } //static void LLDockableFloater::toggleInstance(const LLSD& sdname) { - LLSD key; - std::string name = sdname.asString(); + LLSD key; + std::string name = sdname.asString(); - LLDockableFloater* instance = - dynamic_cast (LLFloaterReg::findInstance(name)); - // if floater closed or docked - if (instance == NULL || (instance && instance->isDocked())) - { - LLFloaterReg::toggleInstance(name, key); - // restore button toggle state - if (instance != NULL) - { - instance->storeVisibilityControl(); - } - } - // if floater undocked - else if (instance != NULL) - { - instance->setMinimized(FALSE); - if (instance->getVisible()) - { - instance->setVisible(FALSE); - } - else - { - instance->setVisible(TRUE); - gFloaterView->bringToFront(instance); - } - } + LLDockableFloater* instance = + dynamic_cast (LLFloaterReg::findInstance(name)); + // if floater closed or docked + if (instance == NULL || (instance && instance->isDocked())) + { + LLFloaterReg::toggleInstance(name, key); + // restore button toggle state + if (instance != NULL) + { + instance->storeVisibilityControl(); + } + } + // if floater undocked + else if (instance != NULL) + { + instance->setMinimized(FALSE); + if (instance->getVisible()) + { + instance->setVisible(FALSE); + } + else + { + instance->setVisible(TRUE); + gFloaterView->bringToFront(instance); + } + } } void LLDockableFloater::resetInstance() { - if (mUniqueDocking && sInstanceHandle.get() != this) - { - if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked()) - { - sInstanceHandle.get()->setVisible(FALSE); - } - sInstanceHandle = getHandle(); - } + if (mUniqueDocking && sInstanceHandle.get() != this) + { + if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked()) + { + sInstanceHandle.get()->setVisible(FALSE); + } + sInstanceHandle = getHandle(); + } } void LLDockableFloater::setVisible(BOOL visible) { - // Force docking if requested - if (visible && mForceDocking) - { - setCanDock(true); - setDocked(true); - mForceDocking = false; - } + // Force docking if requested + if (visible && mForceDocking) + { + setCanDock(true); + setDocked(true); + mForceDocking = false; + } - if(visible && isDocked()) - { - resetInstance(); - } + if(visible && isDocked()) + { + resetInstance(); + } - if (visible && mDockControl.get() != NULL) - { - mDockControl.get()->repositionDockable(); - } + if (visible && mDockControl.get() != NULL) + { + mDockControl.get()->repositionDockable(); + } - if (visible && !isMinimized()) - { - LLFloater::setFrontmost(getAutoFocus()); - } - LLFloater::setVisible(visible); + if (visible && !isMinimized()) + { + LLFloater::setFrontmost(getAutoFocus()); + } + LLFloater::setVisible(visible); } void LLDockableFloater::setMinimized(BOOL minimize) { - if(minimize && isDocked()) - { - // minimizing a docked floater just hides it - setVisible(FALSE); - } - else - { - LLFloater::setMinimized(minimize); - } + if(minimize && isDocked()) + { + // minimizing a docked floater just hides it + setVisible(FALSE); + } + else + { + LLFloater::setMinimized(minimize); + } } LLView * LLDockableFloater::getDockWidget() { - LLView * res = NULL; - if (getDockControl() != NULL) { - res = getDockControl()->getDock(); - } + LLView * res = NULL; + if (getDockControl() != NULL) { + res = getDockControl()->getDock(); + } - return res; + return res; } void LLDockableFloater::onDockHidden() { - setCanDock(FALSE); + setCanDock(FALSE); } void LLDockableFloater::onDockShown() { - if (!isMinimized()) - { - setCanDock(TRUE); - } + if (!isMinimized()) + { + setCanDock(TRUE); + } } void LLDockableFloater::setDocked(bool docked, bool pop_on_undock) { - if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible()) - { - if (docked) - { - resetInstance(); - mDockControl.get()->on(); - } - else - { - mDockControl.get()->off(); - } + if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible()) + { + if (docked) + { + resetInstance(); + mDockControl.get()->on(); + } + else + { + mDockControl.get()->off(); + } - if (!docked && pop_on_undock) - { - // visually pop up a little bit to emphasize the undocking - translate(0, UNDOCK_LEAP_HEIGHT); - } - } + if (!docked && pop_on_undock) + { + // visually pop up a little bit to emphasize the undocking + translate(0, UNDOCK_LEAP_HEIGHT); + } + } - LLFloater::setDocked(docked, pop_on_undock); + LLFloater::setDocked(docked, pop_on_undock); } void LLDockableFloater::draw() { - if (mDockControl.get() != NULL) - { - mDockControl.get()->repositionDockable(); - if (isDocked()) - { - mDockControl.get()->drawToungue(); - } - } - LLFloater::draw(); + if (mDockControl.get() != NULL) + { + mDockControl.get()->repositionDockable(); + if (isDocked()) + { + mDockControl.get()->drawToungue(); + } + } + LLFloater::draw(); } void LLDockableFloater::setDockControl(LLDockControl* dockControl) { - mDockControl.reset(dockControl); - setDocked(isDocked()); + mDockControl.reset(dockControl); + setDocked(isDocked()); } const LLUIImagePtr& LLDockableFloater::getDockTongue(LLDockControl::DocAt dock_side) { - switch(dock_side) - { - case LLDockControl::LEFT: - mDockTongue = LLUI::getUIImage("Flyout_Left"); - break; - case LLDockControl::RIGHT: - mDockTongue = LLUI::getUIImage("Flyout_Right"); - break; - default: - mDockTongue = LLUI::getUIImage("Flyout_Pointer"); - break; - } + switch(dock_side) + { + case LLDockControl::LEFT: + mDockTongue = LLUI::getUIImage("Flyout_Left"); + break; + case LLDockControl::RIGHT: + mDockTongue = LLUI::getUIImage("Flyout_Right"); + break; + default: + mDockTongue = LLUI::getUIImage("Flyout_Pointer"); + break; + } - return mDockTongue; + return mDockTongue; } LLDockControl* LLDockableFloater::getDockControl() { - return mDockControl.get(); + return mDockControl.get(); } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 5d90b3ef4e..e7ceb235a7 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -1,25 +1,25 @@ -/** +/** * @file lldockablefloater.h * @brief Creates a panel of a specific kind for a toast. * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,115 +38,115 @@ */ class LLDockableFloater : public LLFloater { - static const U32 UNDOCK_LEAP_HEIGHT = 12; + static const U32 UNDOCK_LEAP_HEIGHT = 12; - static void init(LLDockableFloater* thiz); + static void init(LLDockableFloater* thiz); public: - LOG_CLASS(LLDockableFloater); - LLDockableFloater(LLDockControl* dockControl, const LLSD& key, - const Params& params = getDefaultParams()); - - /** - * Constructor. - * @param dockControl a pointer to the doc control instance - * @param uniqueDocking - a flag defines is docking should work as tab(at one - * moment only one docked floater can be shown), also this flag defines is dock - * tongue should be used. - * @params key a floater key. - * @params params a floater parameters - */ - LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, - const LLSD& key, const Params& params = getDefaultParams()); - - /** - * Constructor. - * @param dockControl a pointer to the doc control instance - * @param uniqueDocking - a flag defines is docking should work as tab(at one - * moment only one docked floater can be shown). - * @praram useTongue - a flag defines is dock tongue should be used. - * @params key a floater key. - * @params params a floater parameters - */ - LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, - bool useTongue, const LLSD& key, - const Params& params = getDefaultParams()); - - virtual ~LLDockableFloater(); - - static LLHandle getInstanceHandle() { return sInstanceHandle; } - - static void toggleInstance(const LLSD& sdname); - - /** - * If descendant class overrides postBuild() in order to perform specific - * construction then it must still invoke its superclass' implementation. - */ - /* virtula */BOOL postBuild(); - /* virtual */void setDocked(bool docked, bool pop_on_undock = true); - /* virtual */void draw(); - - /** - * If descendant class overrides setVisible() then it must still invoke its - * superclass' implementation. - */ - /*virtual*/ void setVisible(BOOL visible); - - /** - * If descendant class overrides setMinimized() then it must still invoke its - * superclass' implementation. - */ - /*virtual*/ void setMinimized(BOOL minimize); - - LLView * getDockWidget(); - - virtual void onDockHidden(); - virtual void onDockShown(); - - LLDockControl* getDockControl(); - - /** - * Returns true if screen channel should consider floater's size when drawing toasts. - * - * By default returns false. - */ - virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } - virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } - - bool getUniqueDocking() { return mUniqueDocking; } - bool getUseTongue() { return mUseTongue; } - - void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;} + LOG_CLASS(LLDockableFloater); + LLDockableFloater(LLDockControl* dockControl, const LLSD& key, + const Params& params = getDefaultParams()); + + /** + * Constructor. + * @param dockControl a pointer to the doc control instance + * @param uniqueDocking - a flag defines is docking should work as tab(at one + * moment only one docked floater can be shown), also this flag defines is dock + * tongue should be used. + * @params key a floater key. + * @params params a floater parameters + */ + LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, + const LLSD& key, const Params& params = getDefaultParams()); + + /** + * Constructor. + * @param dockControl a pointer to the doc control instance + * @param uniqueDocking - a flag defines is docking should work as tab(at one + * moment only one docked floater can be shown). + * @praram useTongue - a flag defines is dock tongue should be used. + * @params key a floater key. + * @params params a floater parameters + */ + LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, + bool useTongue, const LLSD& key, + const Params& params = getDefaultParams()); + + virtual ~LLDockableFloater(); + + static LLHandle getInstanceHandle() { return sInstanceHandle; } + + static void toggleInstance(const LLSD& sdname); + + /** + * If descendant class overrides postBuild() in order to perform specific + * construction then it must still invoke its superclass' implementation. + */ + /* virtula */BOOL postBuild(); + /* virtual */void setDocked(bool docked, bool pop_on_undock = true); + /* virtual */void draw(); + + /** + * If descendant class overrides setVisible() then it must still invoke its + * superclass' implementation. + */ + /*virtual*/ void setVisible(BOOL visible); + + /** + * If descendant class overrides setMinimized() then it must still invoke its + * superclass' implementation. + */ + /*virtual*/ void setMinimized(BOOL minimize); + + LLView * getDockWidget(); + + virtual void onDockHidden(); + virtual void onDockShown(); + + LLDockControl* getDockControl(); + + /** + * Returns true if screen channel should consider floater's size when drawing toasts. + * + * By default returns false. + */ + virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } + virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } + + bool getUniqueDocking() { return mUniqueDocking; } + bool getUseTongue() { return mUseTongue; } + + void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;} private: - /** - * Provides unique of dockable floater. - * If dockable floater already exists it should be closed. - */ - void resetInstance(); + /** + * Provides unique of dockable floater. + * If dockable floater already exists it should be closed. + */ + void resetInstance(); protected: - void setDockControl(LLDockControl* dockControl); - const LLUIImagePtr& getDockTongue(LLDockControl::DocAt dock_side = LLDockControl::TOP); + void setDockControl(LLDockControl* dockControl); + const LLUIImagePtr& getDockTongue(LLDockControl::DocAt dock_side = LLDockControl::TOP); - // Checks if docking should be forced. - // It may be useful e.g. if floater created in mouselook mode (see EXT-5609) - boost::function mIsDockedStateForcedCallback; + // Checks if docking should be forced. + // It may be useful e.g. if floater created in mouselook mode (see EXT-5609) + boost::function mIsDockedStateForcedCallback; private: - std::unique_ptr mDockControl; - LLUIImagePtr mDockTongue; - static LLHandle sInstanceHandle; - /** - * Provides possibility to define that dockable floaters can be docked - * non exclusively. - */ - bool mUniqueDocking; + std::unique_ptr mDockControl; + LLUIImagePtr mDockTongue; + static LLHandle sInstanceHandle; + /** + * Provides possibility to define that dockable floaters can be docked + * non exclusively. + */ + bool mUniqueDocking; - bool mUseTongue; + bool mUseTongue; - bool mOverlapsScreenChannel; + bool mOverlapsScreenChannel; - // Force docking when the floater is being shown for the first time. - bool mForceDocking; + // Force docking when the floater is being shown for the first time. + bool mForceDocking; }; #endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index bd42497cb6..bf0862e8a9 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldockcontrol.cpp * @brief Creates a panel of a specific kind for a toast * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -30,50 +30,50 @@ #include "lldockablefloater.h" LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, - const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : - mDockableFloater(dockableFloater), - mDockTongue(dockTongue), - mDockTongueX(0), - mDockTongueY(0) + const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : + mDockableFloater(dockableFloater), + mDockTongue(dockTongue), + mDockTongueX(0), + mDockTongueY(0) { - mDockAt = dockAt; - - if (dockWidget != NULL) - { - mDockWidgetHandle = dockWidget->getHandle(); - } - - if (dockableFloater->isDocked()) - { - on(); - } - else - { - off(); - } - - if (!(get_allowed_rect_callback)) - { - mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1); - } - else - { - mGetAllowedRectCallback = get_allowed_rect_callback; - } - - if (dockWidget != NULL) - { - repositionDockable(); - } - - if (getDock() != NULL) - { - mDockWidgetVisible = isDockVisible(); - } - else - { - mDockWidgetVisible = false; - } + mDockAt = dockAt; + + if (dockWidget != NULL) + { + mDockWidgetHandle = dockWidget->getHandle(); + } + + if (dockableFloater->isDocked()) + { + on(); + } + else + { + off(); + } + + if (!(get_allowed_rect_callback)) + { + mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1); + } + else + { + mGetAllowedRectCallback = get_allowed_rect_callback; + } + + if (dockWidget != NULL) + { + repositionDockable(); + } + + if (getDock() != NULL) + { + mDockWidgetVisible = isDockVisible(); + } + else + { + mDockWidgetVisible = false; + } } LLDockControl::~LLDockControl() @@ -82,302 +82,302 @@ LLDockControl::~LLDockControl() void LLDockControl::setDock(LLView* dockWidget) { - if (dockWidget != NULL) - { - mDockWidgetHandle = dockWidget->getHandle(); - repositionDockable(); - mDockWidgetVisible = isDockVisible(); - } - else - { - mDockWidgetHandle = LLHandle(); - mDockWidgetVisible = false; - } + if (dockWidget != NULL) + { + mDockWidgetHandle = dockWidget->getHandle(); + repositionDockable(); + mDockWidgetVisible = isDockVisible(); + } + else + { + mDockWidgetHandle = LLHandle(); + mDockWidgetVisible = false; + } } void LLDockControl::getAllowedRect(LLRect& rect) { - rect = mDockableFloater->getRootView()->getChild("non_toolbar_panel")->getRect(); + rect = mDockableFloater->getRootView()->getChild("non_toolbar_panel")->getRect(); } void LLDockControl::repositionDockable() { - if (!getDock()) return; - LLRect dockRect = getDock()->calcScreenRect(); - LLRect rootRect; - LLRect floater_rect = mDockableFloater->calcScreenRect(); - mGetAllowedRectCallback(rootRect); - - // recalculate dockable position if: - if (mPrevDockRect != dockRect //dock position changed - || mDockWidgetVisible != isDockVisible() //dock visibility changed - || mRootRect != rootRect //root view rect changed - || mFloaterRect != floater_rect //floater rect changed - || mRecalculateDockablePosition //recalculation is forced - ) - { - // undock dockable and off() if dock not visible - if (!isDockVisible()) - { - mDockableFloater->setDocked(false); - // force off() since dockable may not have dockControll at this time - off(); - LLDockableFloater* dockable_floater = - dynamic_cast (mDockableFloater); - if(dockable_floater != NULL) - { - dockable_floater->onDockHidden(); - } - } - else - { - if(mEnabled) - { - moveDockable(); - } - LLDockableFloater* dockable_floater = - dynamic_cast (mDockableFloater); - if(dockable_floater != NULL) - { - dockable_floater->onDockShown(); - } - } - - mPrevDockRect = dockRect; - mRootRect = rootRect; - mFloaterRect = floater_rect; - mRecalculateDockablePosition = false; - mDockWidgetVisible = isDockVisible(); - } + if (!getDock()) return; + LLRect dockRect = getDock()->calcScreenRect(); + LLRect rootRect; + LLRect floater_rect = mDockableFloater->calcScreenRect(); + mGetAllowedRectCallback(rootRect); + + // recalculate dockable position if: + if (mPrevDockRect != dockRect //dock position changed + || mDockWidgetVisible != isDockVisible() //dock visibility changed + || mRootRect != rootRect //root view rect changed + || mFloaterRect != floater_rect //floater rect changed + || mRecalculateDockablePosition //recalculation is forced + ) + { + // undock dockable and off() if dock not visible + if (!isDockVisible()) + { + mDockableFloater->setDocked(false); + // force off() since dockable may not have dockControll at this time + off(); + LLDockableFloater* dockable_floater = + dynamic_cast (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockHidden(); + } + } + else + { + if(mEnabled) + { + moveDockable(); + } + LLDockableFloater* dockable_floater = + dynamic_cast (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockShown(); + } + } + + mPrevDockRect = dockRect; + mRootRect = rootRect; + mFloaterRect = floater_rect; + mRecalculateDockablePosition = false; + mDockWidgetVisible = isDockVisible(); + } } bool LLDockControl::isDockVisible() { - bool res = true; - - if (getDock() != NULL) - { - //we should check all hierarchy - res = getDock()->isInVisibleChain(); - if (res) - { - LLRect dockRect = getDock()->calcScreenRect(); - - switch (mDockAt) - { - case LEFT: // to keep compiler happy - break; - case BOTTOM: - case TOP: - { - // check is dock inside parent rect - // assume that parent for all dockable floaters - // is the root view - LLRect dockParentRect = - getDock()->getRootView()->calcScreenRect(); - if (dockRect.mRight <= dockParentRect.mLeft - || dockRect.mLeft >= dockParentRect.mRight) - { - res = false; - } - break; - } - default: - break; - } - } - } - - return res; + bool res = true; + + if (getDock() != NULL) + { + //we should check all hierarchy + res = getDock()->isInVisibleChain(); + if (res) + { + LLRect dockRect = getDock()->calcScreenRect(); + + switch (mDockAt) + { + case LEFT: // to keep compiler happy + break; + case BOTTOM: + case TOP: + { + // check is dock inside parent rect + // assume that parent for all dockable floaters + // is the root view + LLRect dockParentRect = + getDock()->getRootView()->calcScreenRect(); + if (dockRect.mRight <= dockParentRect.mLeft + || dockRect.mLeft >= dockParentRect.mRight) + { + res = false; + } + break; + } + default: + break; + } + } + } + + return res; } void LLDockControl::moveDockable() { - // calculate new dockable position - LLRect dockRect = getDock()->calcScreenRect(); - LLRect rootRect; - mGetAllowedRectCallback(rootRect); - - bool use_tongue = false; - LLDockableFloater* dockable_floater = - dynamic_cast (mDockableFloater); - if (dockable_floater != NULL) - { - use_tongue = dockable_floater->getUseTongue(); - } - - LLRect dockableRect = mDockableFloater->calcScreenRect(); - S32 x = 0; - S32 y = 0; - LLRect dockParentRect; - switch (mDockAt) - { - case LEFT: - - x = dockRect.mLeft - dockableRect.getWidth(); - y = dockRect.getCenterY() + dockableRect.getHeight() / 2; - - if (use_tongue) - { - x -= mDockTongue->getWidth(); - } - - mDockTongueX = dockableRect.mRight; - mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2; - - break; - - case RIGHT: - - x = dockRect.mRight; - y = dockRect.getCenterY() + dockableRect.getHeight() / 2; - - if (use_tongue) - { - x += mDockTongue->getWidth(); - } - - mDockTongueX = dockRect.mRight; - mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2; - - break; - - case TOP: - x = dockRect.getCenterX() - dockableRect.getWidth() / 2; - y = dockRect.mTop + dockableRect.getHeight(); - // unique docking used with dock tongue, so add tongue height to the Y coordinate - if (use_tongue) - { - y += mDockTongue->getHeight(); - - if ( y > rootRect.mTop) - { - y = rootRect.mTop; - } - } - - // check is dockable inside root view rect - if (x < rootRect.mLeft) - { - x = rootRect.mLeft; - } - if (x + dockableRect.getWidth() > rootRect.mRight) - { - x = rootRect.mRight - dockableRect.getWidth(); - } - - - // calculate dock tongue position - dockParentRect = getDock()->getParent()->calcScreenRect(); - if (dockRect.getCenterX() < dockParentRect.mLeft) - { - mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; - } - else if (dockRect.getCenterX() > dockParentRect.mRight) - { - mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;; - } - else - { - mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; - } - mDockTongueY = dockRect.mTop; - - break; - case BOTTOM: - x = dockRect.getCenterX() - dockableRect.getWidth() / 2; - y = dockRect.mBottom; - // unique docking used with dock tongue, so add tongue height to the Y coordinate - if (use_tongue) - { - y -= mDockTongue->getHeight(); - } - - // check is dockable inside root view rect - if (x < rootRect.mLeft) - { - x = rootRect.mLeft; - } - if (x + dockableRect.getWidth() > rootRect.mRight) - { - x = rootRect.mRight - dockableRect.getWidth(); - } - - // calculate dock tongue position - dockParentRect = getDock()->getParent()->calcScreenRect(); - if (dockRect.getCenterX() < dockParentRect.mLeft) - { - mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; - } - else if (dockRect.getCenterX() > dockParentRect.mRight) - { - mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;; - } - else - { - mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; - } - mDockTongueY = dockRect.mBottom - mDockTongue->getHeight(); - - break; - } - - S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom - mDockTongueY) - mDockTongue->getHeight(); - - // A floater should be shrunk so it doesn't cover a part of its docking tongue and - // there is a space between a dockable floater and a control to which it is docked. - if (use_tongue && dockableRect.getHeight() >= max_available_height) - { - dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height); - mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight()); - } - else - { - // move dockable - dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), - dockableRect.getHeight()); - } - - LLRect localDocableParentRect; - - mDockableFloater->getParent()->screenRectToLocal(dockableRect, &localDocableParentRect); - mDockableFloater->setRect(localDocableParentRect); - mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, &mDockTongueX, &mDockTongueY); + // calculate new dockable position + LLRect dockRect = getDock()->calcScreenRect(); + LLRect rootRect; + mGetAllowedRectCallback(rootRect); + + bool use_tongue = false; + LLDockableFloater* dockable_floater = + dynamic_cast (mDockableFloater); + if (dockable_floater != NULL) + { + use_tongue = dockable_floater->getUseTongue(); + } + + LLRect dockableRect = mDockableFloater->calcScreenRect(); + S32 x = 0; + S32 y = 0; + LLRect dockParentRect; + switch (mDockAt) + { + case LEFT: + + x = dockRect.mLeft - dockableRect.getWidth(); + y = dockRect.getCenterY() + dockableRect.getHeight() / 2; + + if (use_tongue) + { + x -= mDockTongue->getWidth(); + } + + mDockTongueX = dockableRect.mRight; + mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2; + + break; + + case RIGHT: + + x = dockRect.mRight; + y = dockRect.getCenterY() + dockableRect.getHeight() / 2; + + if (use_tongue) + { + x += mDockTongue->getWidth(); + } + + mDockTongueX = dockRect.mRight; + mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2; + + break; + + case TOP: + x = dockRect.getCenterX() - dockableRect.getWidth() / 2; + y = dockRect.mTop + dockableRect.getHeight(); + // unique docking used with dock tongue, so add tongue height to the Y coordinate + if (use_tongue) + { + y += mDockTongue->getHeight(); + + if ( y > rootRect.mTop) + { + y = rootRect.mTop; + } + } + + // check is dockable inside root view rect + if (x < rootRect.mLeft) + { + x = rootRect.mLeft; + } + if (x + dockableRect.getWidth() > rootRect.mRight) + { + x = rootRect.mRight - dockableRect.getWidth(); + } + + + // calculate dock tongue position + dockParentRect = getDock()->getParent()->calcScreenRect(); + if (dockRect.getCenterX() < dockParentRect.mLeft) + { + mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; + } + else if (dockRect.getCenterX() > dockParentRect.mRight) + { + mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;; + } + else + { + mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; + } + mDockTongueY = dockRect.mTop; + + break; + case BOTTOM: + x = dockRect.getCenterX() - dockableRect.getWidth() / 2; + y = dockRect.mBottom; + // unique docking used with dock tongue, so add tongue height to the Y coordinate + if (use_tongue) + { + y -= mDockTongue->getHeight(); + } + + // check is dockable inside root view rect + if (x < rootRect.mLeft) + { + x = rootRect.mLeft; + } + if (x + dockableRect.getWidth() > rootRect.mRight) + { + x = rootRect.mRight - dockableRect.getWidth(); + } + + // calculate dock tongue position + dockParentRect = getDock()->getParent()->calcScreenRect(); + if (dockRect.getCenterX() < dockParentRect.mLeft) + { + mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; + } + else if (dockRect.getCenterX() > dockParentRect.mRight) + { + mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;; + } + else + { + mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; + } + mDockTongueY = dockRect.mBottom - mDockTongue->getHeight(); + + break; + } + + S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom - mDockTongueY) - mDockTongue->getHeight(); + + // A floater should be shrunk so it doesn't cover a part of its docking tongue and + // there is a space between a dockable floater and a control to which it is docked. + if (use_tongue && dockableRect.getHeight() >= max_available_height) + { + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height); + mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight()); + } + else + { + // move dockable + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), + dockableRect.getHeight()); + } + + LLRect localDocableParentRect; + + mDockableFloater->getParent()->screenRectToLocal(dockableRect, &localDocableParentRect); + mDockableFloater->setRect(localDocableParentRect); + mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, &mDockTongueX, &mDockTongueY); } void LLDockControl::on() { - if (isDockVisible()) - { - mEnabled = true; - mRecalculateDockablePosition = true; - } + if (isDockVisible()) + { + mEnabled = true; + mRecalculateDockablePosition = true; + } } void LLDockControl::off() { - mEnabled = false; + mEnabled = false; } void LLDockControl::forceRecalculatePosition() { - mRecalculateDockablePosition = true; + mRecalculateDockablePosition = true; } void LLDockControl::drawToungue() { - bool use_tongue = false; - LLDockableFloater* dockable_floater = - dynamic_cast (mDockableFloater); - if (dockable_floater != NULL) - { - use_tongue = dockable_floater->getUseTongue(); - } - - if (mEnabled && use_tongue) - { - mDockTongue->draw(mDockTongueX, mDockTongueY); - } + bool use_tongue = false; + LLDockableFloater* dockable_floater = + dynamic_cast (mDockableFloater); + if (dockable_floater != NULL) + { + use_tongue = dockable_floater->getUseTongue(); + } + + if (mEnabled && use_tongue) + { + mDockTongue->draw(mDockTongueX, mDockTongueY); + } } diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 98a9c7236d..fb0bf7d251 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -1,25 +1,25 @@ -/** +/** * @file lldockcontrol.h * @brief Creates a panel of a specific kind for a toast. * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,58 +39,58 @@ class LLDockControl { public: - enum DocAt - { - TOP, - LEFT, - RIGHT, - BOTTOM - }; + enum DocAt + { + TOP, + LEFT, + RIGHT, + BOTTOM + }; public: - // callback for a function getting a rect valid for control's position - typedef boost::function get_allowed_rect_callback_t; + // callback for a function getting a rect valid for control's position + typedef boost::function get_allowed_rect_callback_t; - LOG_CLASS(LLDockControl); - LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, - const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL); - virtual ~LLDockControl(); + LOG_CLASS(LLDockControl); + LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, + const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL); + virtual ~LLDockControl(); public: - void on(); - void off(); - void forceRecalculatePosition(); - void setDock(LLView* dockWidget); - LLView* getDock() - { - return mDockWidgetHandle.get(); - } - void repositionDockable(); - void drawToungue(); - bool isDockVisible(); + void on(); + void off(); + void forceRecalculatePosition(); + void setDock(LLView* dockWidget); + LLView* getDock() + { + return mDockWidgetHandle.get(); + } + void repositionDockable(); + void drawToungue(); + bool isDockVisible(); - // gets a rect that bounds possible positions for a dockable control (EXT-1111) - void getAllowedRect(LLRect& rect); + // gets a rect that bounds possible positions for a dockable control (EXT-1111) + void getAllowedRect(LLRect& rect); - S32 getTongueWidth() { return mDockTongue->getWidth(); } - S32 getTongueHeight() { return mDockTongue->getHeight(); } + S32 getTongueWidth() { return mDockTongue->getWidth(); } + S32 getTongueHeight() { return mDockTongue->getHeight(); } private: - virtual void moveDockable(); + virtual void moveDockable(); private: - get_allowed_rect_callback_t mGetAllowedRectCallback; - bool mEnabled; - bool mRecalculateDockablePosition; - bool mDockWidgetVisible; - DocAt mDockAt; - LLHandle mDockWidgetHandle; - LLRect mPrevDockRect; - LLRect mRootRect; - LLRect mFloaterRect; - LLFloater* mDockableFloater; - LLUIImagePtr mDockTongue; - S32 mDockTongueX; - S32 mDockTongueY; + get_allowed_rect_callback_t mGetAllowedRectCallback; + bool mEnabled; + bool mRecalculateDockablePosition; + bool mDockWidgetVisible; + DocAt mDockAt; + LLHandle mDockWidgetHandle; + LLRect mPrevDockRect; + LLRect mRootRect; + LLRect mFloaterRect; + LLFloater* mDockableFloater; + LLUIImagePtr mDockTongue; + S32 mDockTongueX; + S32 mDockTongueY; }; #endif /* LL_DOCKCONTROL_H */ diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 220f5ee825..dbec1d5d80 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldraghandle.cpp * @brief LLDragHandle base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -50,221 +50,221 @@ const S32 LEFT_PAD = BORDER_PAD + TITLE_HPAD + LEADING_PAD; S32 LLDragHandle::sSnapMargin = 5; LLDragHandle::LLDragHandle(const LLDragHandle::Params& p) -: LLView(p), - mDragLastScreenX( 0 ), - mDragLastScreenY( 0 ), - mLastMouseScreenX( 0 ), - mLastMouseScreenY( 0 ), - mTitleBox( NULL ), - mMaxTitleWidth( 0 ), - mForeground( TRUE ), - mDragHighlightColor(p.drag_highlight_color()), - mDragShadowColor(p.drag_shadow_color()) +: LLView(p), + mDragLastScreenX( 0 ), + mDragLastScreenY( 0 ), + mLastMouseScreenX( 0 ), + mLastMouseScreenY( 0 ), + mTitleBox( NULL ), + mMaxTitleWidth( 0 ), + mForeground( TRUE ), + mDragHighlightColor(p.drag_highlight_color()), + mDragShadowColor(p.drag_shadow_color()) { - static LLUICachedControl snap_margin ("SnapMargin", 0); - sSnapMargin = snap_margin; + static LLUICachedControl snap_margin ("SnapMargin", 0); + sSnapMargin = snap_margin; } LLDragHandle::~LLDragHandle() { gFocusMgr.removeKeyboardFocusWithoutCallback(this); - removeChild(mTitleBox); - delete mTitleBox; + removeChild(mTitleBox); + delete mTitleBox; } void LLDragHandle::initFromParams(const LLDragHandle::Params& p) { - LLView::initFromParams(p); - setTitle( p.label ); + LLView::initFromParams(p); + setTitle( p.label ); } -void LLDragHandle::setTitleVisible(BOOL visible) -{ - if(mTitleBox) - { - mTitleBox->setVisible(visible); - } +void LLDragHandle::setTitleVisible(BOOL visible) +{ + if(mTitleBox) + { + mTitleBox->setVisible(visible); + } } void LLDragHandleTop::setTitle(const std::string& title) { - std::string trimmed_title = title; - LLStringUtil::trim(trimmed_title); - - if( mTitleBox ) - { - mTitleBox->setText(trimmed_title); - } - else - { - const LLFontGL* font = LLFontGL::getFontSansSerif(); - LLTextBox::Params params; - params.name("Drag Handle Title"); - params.rect(getRect()); - params.initial_value(trimmed_title); - params.font(font); - params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); - params.font_shadow(LLFontGL::DROP_SHADOW_SOFT); - params.use_ellipses = true; - params.parse_urls = false; //cancel URL replacement in floater title - mTitleBox = LLUICtrlFactory::create (params); - addChild( mTitleBox ); - } - - reshapeTitleBox(); + std::string trimmed_title = title; + LLStringUtil::trim(trimmed_title); + + if( mTitleBox ) + { + mTitleBox->setText(trimmed_title); + } + else + { + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLTextBox::Params params; + params.name("Drag Handle Title"); + params.rect(getRect()); + params.initial_value(trimmed_title); + params.font(font); + params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); + params.font_shadow(LLFontGL::DROP_SHADOW_SOFT); + params.use_ellipses = true; + params.parse_urls = false; //cancel URL replacement in floater title + mTitleBox = LLUICtrlFactory::create (params); + addChild( mTitleBox ); + } + + reshapeTitleBox(); } std::string LLDragHandleTop::getTitle() const { - return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText(); + return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText(); } void LLDragHandleLeft::setTitle(const std::string& ) { - if( mTitleBox ) - { - removeChild(mTitleBox); - delete mTitleBox; - mTitleBox = NULL; - } - /* no title on left edge */ + if( mTitleBox ) + { + removeChild(mTitleBox); + delete mTitleBox; + mTitleBox = NULL; + } + /* no title on left edge */ } std::string LLDragHandleLeft::getTitle() const { - return LLStringUtil::null; + return LLStringUtil::null; } void LLDragHandleTop::draw() { - /* Disable lines. Can drag anywhere in most windows. JC - if( getVisible() && getEnabled() && mForeground) - { - const S32 BORDER_PAD = 2; - const S32 HPAD = 2; - const S32 VPAD = 2; - S32 left = BORDER_PAD + HPAD; - S32 top = getRect().getHeight() - 2 * VPAD; - S32 right = getRect().getWidth() - HPAD; -// S32 bottom = VPAD; - - // draw lines for drag areas - - const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4; - S32 line = top - LINE_SPACING; - - LLRect title_rect = mTitleBox->getRect(); - S32 title_right = title_rect.mLeft + mTitleWidth; - BOOL show_right_side = title_right < getRect().getWidth(); - - for( S32 i=0; i<4; i++ ) - { - gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor); - if( show_right_side ) - { - gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor); - } - - gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor); - if( show_right_side ) - { - gl_line_2d(title_right, line, right, line, mDragShadowColor); - } - line -= LINE_SPACING; - } - } - */ - - // Colorize the text to match the frontmost state - if (mTitleBox) - { - mTitleBox->setEnabled(getForeground()); - } - - LLView::draw(); + /* Disable lines. Can drag anywhere in most windows. JC + if( getVisible() && getEnabled() && mForeground) + { + const S32 BORDER_PAD = 2; + const S32 HPAD = 2; + const S32 VPAD = 2; + S32 left = BORDER_PAD + HPAD; + S32 top = getRect().getHeight() - 2 * VPAD; + S32 right = getRect().getWidth() - HPAD; +// S32 bottom = VPAD; + + // draw lines for drag areas + + const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4; + S32 line = top - LINE_SPACING; + + LLRect title_rect = mTitleBox->getRect(); + S32 title_right = title_rect.mLeft + mTitleWidth; + BOOL show_right_side = title_right < getRect().getWidth(); + + for( S32 i=0; i<4; i++ ) + { + gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor); + if( show_right_side ) + { + gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor); + } + + gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor); + if( show_right_side ) + { + gl_line_2d(title_right, line, right, line, mDragShadowColor); + } + line -= LINE_SPACING; + } + } + */ + + // Colorize the text to match the frontmost state + if (mTitleBox) + { + mTitleBox->setEnabled(getForeground()); + } + + LLView::draw(); } // assumes GL state is set for 2D void LLDragHandleLeft::draw() { - /* Disable lines. Can drag anywhere in most windows. JC - if( getVisible() && getEnabled() && mForeground ) - { - const S32 BORDER_PAD = 2; -// const S32 HPAD = 2; - const S32 VPAD = 2; - const S32 LINE_SPACING = 3; - - S32 left = BORDER_PAD + LINE_SPACING; - S32 top = getRect().getHeight() - 2 * VPAD; -// S32 right = getRect().getWidth() - HPAD; - S32 bottom = VPAD; - - // draw lines for drag areas - - // no titles yet - //LLRect title_rect = mTitleBox->getRect(); - //S32 title_right = title_rect.mLeft + mTitleWidth; - //BOOL show_right_side = title_right < getRect().getWidth(); - - S32 line = left; - for( S32 i=0; i<4; i++ ) - { - gl_line_2d(line, top, line, bottom, mDragHighlightColor); - - gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor); - - line += LINE_SPACING; - } - } - */ - - // Colorize the text to match the frontmost state - if (mTitleBox) - { - mTitleBox->setEnabled(getForeground()); - } - - LLView::draw(); + /* Disable lines. Can drag anywhere in most windows. JC + if( getVisible() && getEnabled() && mForeground ) + { + const S32 BORDER_PAD = 2; +// const S32 HPAD = 2; + const S32 VPAD = 2; + const S32 LINE_SPACING = 3; + + S32 left = BORDER_PAD + LINE_SPACING; + S32 top = getRect().getHeight() - 2 * VPAD; +// S32 right = getRect().getWidth() - HPAD; + S32 bottom = VPAD; + + // draw lines for drag areas + + // no titles yet + //LLRect title_rect = mTitleBox->getRect(); + //S32 title_right = title_rect.mLeft + mTitleWidth; + //BOOL show_right_side = title_right < getRect().getWidth(); + + S32 line = left; + for( S32 i=0; i<4; i++ ) + { + gl_line_2d(line, top, line, bottom, mDragHighlightColor); + + gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor); + + line += LINE_SPACING; + } + } + */ + + // Colorize the text to match the frontmost state + if (mTitleBox) + { + mTitleBox->setEnabled(getForeground()); + } + + LLView::draw(); } void LLDragHandleTop::reshapeTitleBox() { - static LLUICachedControl title_vpad("UIFloaterTitleVPad", 0); - if( ! mTitleBox) - { - return; - } - const LLFontGL* font = LLFontGL::getFontSansSerif(); - S32 title_width = getRect().getWidth(); - title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); - S32 title_height = font->getLineHeight(); - LLRect title_rect; - title_rect.setLeftTopAndSize( - LEFT_PAD, - getRect().getHeight() - title_vpad, - title_width, - title_height); - - // calls reshape on mTitleBox - mTitleBox->setShape( title_rect ); + static LLUICachedControl title_vpad("UIFloaterTitleVPad", 0); + if( ! mTitleBox) + { + return; + } + const LLFontGL* font = LLFontGL::getFontSansSerif(); + S32 title_width = getRect().getWidth(); + title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); + S32 title_height = font->getLineHeight(); + LLRect title_rect; + title_rect.setLeftTopAndSize( + LEFT_PAD, + getRect().getHeight() - title_vpad, + title_width, + title_height); + + // calls reshape on mTitleBox + mTitleBox->setShape( title_rect ); } void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLView::reshape(width, height, called_from_parent); - reshapeTitleBox(); + LLView::reshape(width, height, called_from_parent); + reshapeTitleBox(); } void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLView::reshape(width, height, called_from_parent); + LLView::reshape(width, height, called_from_parent); } //------------------------------------------------------------- @@ -273,115 +273,115 @@ void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent) BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask) { - // Route future Mouse messages here preemptively. (Release on mouse up.) - // No handler needed for focus lost since this clas has no state that depends on it. - gFocusMgr.setMouseCapture(this); + // Route future Mouse messages here preemptively. (Release on mouse up.) + // No handler needed for focus lost since this clas has no state that depends on it. + gFocusMgr.setMouseCapture(this); - localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); - mLastMouseScreenX = mDragLastScreenX; - mLastMouseScreenY = mDragLastScreenY; + localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); + mLastMouseScreenX = mDragLastScreenX; + mLastMouseScreenY = mDragLastScreenY; - // Note: don't pass on to children - return TRUE; + // Note: don't pass on to children + return TRUE; } BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask) { - if( hasMouseCapture() ) - { - // Release the mouse - gFocusMgr.setMouseCapture( NULL ); - } - - // Note: don't pass on to children - return TRUE; + if( hasMouseCapture() ) + { + // Release the mouse + gFocusMgr.setMouseCapture( NULL ); + } + + // Note: don't pass on to children + return TRUE; } BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // We only handle the click if the click both started and ended within us - if( hasMouseCapture() ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - - // Resize the parent - S32 delta_x = screen_x - mDragLastScreenX; - S32 delta_y = screen_y - mDragLastScreenY; - - // if dragging a docked floater we want to undock - LLFloater * parent = dynamic_cast(getParent()); - if (parent && parent->isDocked()) - { - const S32 SLOP = 12; - - if (delta_y <= -SLOP || - delta_y >= SLOP) - { - parent->setDocked(false, false); - return TRUE; - } - else - { - return FALSE; - } - } - - LLRect original_rect = getParent()->getRect(); - LLRect translated_rect = getParent()->getRect(); - translated_rect.translate(delta_x, delta_y); - // temporarily slam dragged window to new position - getParent()->setRect(translated_rect); - S32 pre_snap_x = getParent()->getRect().mLeft; - S32 pre_snap_y = getParent()->getRect().mBottom; - mDragLastScreenX = screen_x; - mDragLastScreenY = screen_y; - - LLRect new_rect; - LLCoordGL mouse_dir; - // use hysteresis on mouse motion to preserve user intent when mouse stops moving - mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; - mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY; - mLastMouseDir = mouse_dir; - mLastMouseScreenX = screen_x; - mLastMouseScreenY = screen_y; - - LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin); - - getParent()->setSnappedTo(snap_view); - delta_x = new_rect.mLeft - pre_snap_x; - delta_y = new_rect.mBottom - pre_snap_y; - translated_rect.translate(delta_x, delta_y); - - // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc - getParent()->setRect(original_rect); - getParent()->setShape(translated_rect, true); - - mDragLastScreenX += delta_x; - mDragLastScreenY += delta_y; - - getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" <setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; - handled = TRUE; - } - - // Note: don't pass on to children - - return handled; + BOOL handled = FALSE; + + // We only handle the click if the click both started and ended within us + if( hasMouseCapture() ) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + // Resize the parent + S32 delta_x = screen_x - mDragLastScreenX; + S32 delta_y = screen_y - mDragLastScreenY; + + // if dragging a docked floater we want to undock + LLFloater * parent = dynamic_cast(getParent()); + if (parent && parent->isDocked()) + { + const S32 SLOP = 12; + + if (delta_y <= -SLOP || + delta_y >= SLOP) + { + parent->setDocked(false, false); + return TRUE; + } + else + { + return FALSE; + } + } + + LLRect original_rect = getParent()->getRect(); + LLRect translated_rect = getParent()->getRect(); + translated_rect.translate(delta_x, delta_y); + // temporarily slam dragged window to new position + getParent()->setRect(translated_rect); + S32 pre_snap_x = getParent()->getRect().mLeft; + S32 pre_snap_y = getParent()->getRect().mBottom; + mDragLastScreenX = screen_x; + mDragLastScreenY = screen_y; + + LLRect new_rect; + LLCoordGL mouse_dir; + // use hysteresis on mouse motion to preserve user intent when mouse stops moving + mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; + mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY; + mLastMouseDir = mouse_dir; + mLastMouseScreenX = screen_x; + mLastMouseScreenY = screen_y; + + LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin); + + getParent()->setSnappedTo(snap_view); + delta_x = new_rect.mLeft - pre_snap_x; + delta_y = new_rect.mBottom - pre_snap_y; + translated_rect.translate(delta_x, delta_y); + + // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc + getParent()->setRect(original_rect); + getParent()->setShape(translated_rect, true); + + mDragLastScreenX += delta_x; + mDragLastScreenY += delta_y; + + getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" <setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; + handled = TRUE; + } + + // Note: don't pass on to children + + return handled; } void LLDragHandle::setValue(const LLSD& value) { - setTitle(value.asString()); + setTitle(value.asString()); } diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index e095e577b1..f61dae8dc3 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -1,25 +1,25 @@ -/** +/** * @file lldraghandle.h * @brief LLDragHandle base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,64 +39,64 @@ class LLTextBox; class LLDragHandle : public LLView { public: - struct Params - : public LLInitParam::Block - { - Optional label; - Optional drag_highlight_color; - Optional drag_shadow_color; - - Params() - : label("label"), - drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), - drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")) - { - changeDefault(mouse_opaque, true); - changeDefault(follows.flags, FOLLOWS_ALL); - } - }; - void initFromParams(const Params&); - - virtual ~LLDragHandle(); - - virtual void setValue(const LLSD& value); - - void setForeground(BOOL b) { mForeground = b; } - BOOL getForeground() const { return mForeground; } - void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } - S32 getMaxTitleWidth() const { return mMaxTitleWidth; } - void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } - LLRect getButtonsRect() { return mButtonsRect; } - void setTitleVisible(BOOL visible); - - virtual void setTitle( const std::string& title ) = 0; - virtual std::string getTitle() const = 0; - - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + struct Params + : public LLInitParam::Block + { + Optional label; + Optional drag_highlight_color; + Optional drag_shadow_color; + + Params() + : label("label"), + drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), + drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")) + { + changeDefault(mouse_opaque, true); + changeDefault(follows.flags, FOLLOWS_ALL); + } + }; + void initFromParams(const Params&); + + virtual ~LLDragHandle(); + + virtual void setValue(const LLSD& value); + + void setForeground(BOOL b) { mForeground = b; } + BOOL getForeground() const { return mForeground; } + void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } + S32 getMaxTitleWidth() const { return mMaxTitleWidth; } + void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } + LLRect getButtonsRect() { return mButtonsRect; } + void setTitleVisible(BOOL visible); + + virtual void setTitle( const std::string& title ) = 0; + virtual std::string getTitle() const = 0; + + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); protected: - LLDragHandle(const Params&); - friend class LLUICtrlFactory; - + LLDragHandle(const Params&); + friend class LLUICtrlFactory; + protected: - LLTextBox* mTitleBox; - + LLTextBox* mTitleBox; + private: - LLRect mButtonsRect; - S32 mDragLastScreenX; - S32 mDragLastScreenY; - S32 mLastMouseScreenX; - S32 mLastMouseScreenY; - LLCoordGL mLastMouseDir; - LLUIColor mDragHighlightColor; - LLUIColor mDragShadowColor; - S32 mMaxTitleWidth; - BOOL mForeground; - - // Pixels near the edge to snap floaters. - static S32 sSnapMargin; + LLRect mButtonsRect; + S32 mDragLastScreenX; + S32 mDragLastScreenY; + S32 mLastMouseScreenX; + S32 mLastMouseScreenY; + LLCoordGL mLastMouseDir; + LLUIColor mDragHighlightColor; + LLUIColor mDragShadowColor; + S32 mMaxTitleWidth; + BOOL mForeground; + + // Pixels near the edge to snap floaters. + static S32 sSnapMargin; }; @@ -105,16 +105,16 @@ class LLDragHandleTop : public LLDragHandle { protected: - LLDragHandleTop(const Params& p) : LLDragHandle(p) {} - friend class LLUICtrlFactory; + LLDragHandleTop(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - virtual void setTitle( const std::string& title ); - virtual std::string getTitle() const; - virtual void draw(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + virtual void setTitle( const std::string& title ); + virtual std::string getTitle() const; + virtual void draw(); + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); private: - void reshapeTitleBox(); + void reshapeTitleBox(); }; @@ -123,13 +123,13 @@ class LLDragHandleLeft : public LLDragHandle { protected: - LLDragHandleLeft(const Params& p) : LLDragHandle(p) {} - friend class LLUICtrlFactory; + LLDragHandleLeft(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - virtual void setTitle( const std::string& title ); - virtual std::string getTitle() const; - virtual void draw(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + virtual void setTitle( const std::string& title ); + virtual std::string getTitle() const; + virtual void draw(); + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); }; diff --git a/indra/llui/lleditmenuhandler.cpp b/indra/llui/lleditmenuhandler.cpp index d48237e377..402628bc6b 100644 --- a/indra/llui/lleditmenuhandler.cpp +++ b/indra/llui/lleditmenuhandler.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lleditmenuhandler.cpp * @authors Aaron Yonas, James Cook * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,8 +33,8 @@ LLEditMenuHandler* LLEditMenuHandler::gEditMenuHandler = NULL; LLEditMenuHandler::~LLEditMenuHandler() { - if (gEditMenuHandler == this) - { - gEditMenuHandler = NULL; - } + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } } diff --git a/indra/llui/lleditmenuhandler.h b/indra/llui/lleditmenuhandler.h index cd4fea8c52..f516b0f2e2 100644 --- a/indra/llui/lleditmenuhandler.h +++ b/indra/llui/lleditmenuhandler.h @@ -1,25 +1,25 @@ -/** +/** * @file lleditmenuhandler.h * @authors Aaron Yonas, James Cook * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,40 +31,40 @@ class LLEditMenuHandler { public: - // this is needed even though this is just an interface class. - virtual ~LLEditMenuHandler(); - - virtual void undo() {}; - virtual BOOL canUndo() const { return FALSE; } - - virtual void redo() {}; - virtual BOOL canRedo() const { return FALSE; } - - virtual void cut() {}; - virtual BOOL canCut() const { return FALSE; } - - virtual void copy() {}; - virtual BOOL canCopy() const { return FALSE; } - - virtual void paste() {}; - virtual BOOL canPaste() const { return FALSE; } - - // "delete" is a keyword - virtual void doDelete() {}; - virtual BOOL canDoDelete() const { return FALSE; } - - virtual void selectAll() {}; - virtual BOOL canSelectAll() const { return FALSE; } - - virtual void deselect() {}; - virtual BOOL canDeselect() const { return FALSE; } + // this is needed even though this is just an interface class. + virtual ~LLEditMenuHandler(); + + virtual void undo() {}; + virtual BOOL canUndo() const { return FALSE; } + + virtual void redo() {}; + virtual BOOL canRedo() const { return FALSE; } + + virtual void cut() {}; + virtual BOOL canCut() const { return FALSE; } + + virtual void copy() {}; + virtual BOOL canCopy() const { return FALSE; } + + virtual void paste() {}; + virtual BOOL canPaste() const { return FALSE; } + + // "delete" is a keyword + virtual void doDelete() {}; + virtual BOOL canDoDelete() const { return FALSE; } + + virtual void selectAll() {}; + virtual BOOL canSelectAll() const { return FALSE; } + + virtual void deselect() {}; + virtual BOOL canDeselect() const { return FALSE; } - // TODO: Instead of being a public data member, it would be better to hide it altogether - // and have a "set" method and then a bunch of static versions of the cut, copy, paste - // methods, etc that operate on the current global instance. That would drastically - // simplify the existing code that accesses this global variable by putting all the - // null checks in the one implementation of those static methods. -MG - static LLEditMenuHandler* gEditMenuHandler; + // TODO: Instead of being a public data member, it would be better to hide it altogether + // and have a "set" method and then a bunch of static versions of the cut, copy, paste + // methods, etc that operate on the current global instance. That would drastically + // simplify the existing code that accesses this global variable by putting all the + // null checks in the one implementation of those static methods. -MG + static LLEditMenuHandler* gEditMenuHandler; }; diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 89e6ddf987..fbe313924c 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -46,124 +46,124 @@ constexpr S32 HELPER_FLOATER_OFFSET_Y = 0; std::string LLEmojiHelper::getToolTip(llwchar ch) const { - return LLEmojiDictionary::instance().getNameFromEmoji(ch); + return LLEmojiDictionary::instance().getNameFromEmoji(ch); } bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const { - return mHostHandle.get() == ctrl_p; + return mHostHandle.get() == ctrl_p; } // static bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos) { - // If the cursor is currently on a colon start the check one character further back - S32 shortCodePos = (cursorPos == 0 || L':' != wtext[cursorPos - 1]) ? cursorPos : cursorPos - 1; - - auto isPartOfShortcode = [](llwchar ch) { - switch (ch) - { - case L'-': - case L'_': - case L'+': - return true; - default: - return LLStringOps::isAlnum(ch); - } - }; - while (shortCodePos > 1 && isPartOfShortcode(wtext[shortCodePos - 1])) - { - shortCodePos--; - } - - bool isShortCode = (L':' == wtext[shortCodePos - 1]) && (cursorPos - shortCodePos >= 2); - if (pShortCodePos) - *pShortCodePos = (isShortCode) ? shortCodePos - 1 : -1; - return isShortCode; + // If the cursor is currently on a colon start the check one character further back + S32 shortCodePos = (cursorPos == 0 || L':' != wtext[cursorPos - 1]) ? cursorPos : cursorPos - 1; + + auto isPartOfShortcode = [](llwchar ch) { + switch (ch) + { + case L'-': + case L'_': + case L'+': + return true; + default: + return LLStringOps::isAlnum(ch); + } + }; + while (shortCodePos > 1 && isPartOfShortcode(wtext[shortCodePos - 1])) + { + shortCodePos--; + } + + bool isShortCode = (L':' == wtext[shortCodePos - 1]) && (cursorPos - shortCodePos >= 2); + if (pShortCodePos) + *pShortCodePos = (isShortCode) ? shortCodePos - 1 : -1; + return isShortCode; } void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) { - // Commit immediately if the user already typed a full shortcode - if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code)) - { - cb(emojiDescrp->Character); - hideHelper(); - return; - } - - if (mHelperHandle.isDead()) - { - LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); - mHelperHandle = pHelperFloater->getHandle(); - mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); - } - setHostCtrl(hostctrl_p); - mEmojiCommitCb = cb; - - S32 floater_x, floater_y; - if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView)) - { - LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL; - return; - } - - LLFloater* pHelperFloater = mHelperHandle.get(); - LLRect rect = pHelperFloater->getRect(); - S32 left = floater_x - HELPER_FLOATER_OFFSET_X; - S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight(); - rect.setLeftTopAndSize(left, top, rect.getWidth(), rect.getHeight()); - pHelperFloater->setRect(rect); - pHelperFloater->openFloater(LLSD().with("hint", short_code)); + // Commit immediately if the user already typed a full shortcode + if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code)) + { + cb(emojiDescrp->Character); + hideHelper(); + return; + } + + if (mHelperHandle.isDead()) + { + LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); + mHelperHandle = pHelperFloater->getHandle(); + mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); + } + setHostCtrl(hostctrl_p); + mEmojiCommitCb = cb; + + S32 floater_x, floater_y; + if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView)) + { + LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL; + return; + } + + LLFloater* pHelperFloater = mHelperHandle.get(); + LLRect rect = pHelperFloater->getRect(); + S32 left = floater_x - HELPER_FLOATER_OFFSET_X; + S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight(); + rect.setLeftTopAndSize(left, top, rect.getWidth(), rect.getHeight()); + pHelperFloater->setRect(rect); + pHelperFloater->openFloater(LLSD().with("hint", short_code)); } void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p, bool strict) { - mIsHideDisabled &= !strict; - if (mIsHideDisabled || (ctrl_p && !isActive(ctrl_p))) - { - return; - } + mIsHideDisabled &= !strict; + if (mIsHideDisabled || (ctrl_p && !isActive(ctrl_p))) + { + return; + } - setHostCtrl(nullptr); + setHostCtrl(nullptr); } bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask) { - if (mHelperHandle.isDead() || !isActive(ctrl_p)) - { - return false; - } + if (mHelperHandle.isDead() || !isActive(ctrl_p)) + { + return false; + } - return mHelperHandle.get()->handleKey(key, mask, true); + return mHelperHandle.get()->handleKey(key, mask, true); } void LLEmojiHelper::onCommitEmoji(llwchar emoji) { - if (!mHostHandle.isDead() && mEmojiCommitCb) - { - mEmojiCommitCb(emoji); - } + if (!mHostHandle.isDead() && mEmojiCommitCb) + { + mEmojiCommitCb(emoji); + } } void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p) { - const LLUICtrl* pCurHostCtrl = mHostHandle.get(); - if (pCurHostCtrl != hostctrl_p) - { - mHostCtrlFocusLostConn.disconnect(); - mHostHandle.markDead(); - mEmojiCommitCb = {}; - - if (!mHelperHandle.isDead()) - { - mHelperHandle.get()->closeFloater(); - } - - if (hostctrl_p) - { - mHostHandle = hostctrl_p->getHandle(); - mHostCtrlFocusLostConn = hostctrl_p->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); })); - } - } + const LLUICtrl* pCurHostCtrl = mHostHandle.get(); + if (pCurHostCtrl != hostctrl_p) + { + mHostCtrlFocusLostConn.disconnect(); + mHostHandle.markDead(); + mEmojiCommitCb = {}; + + if (!mHelperHandle.isDead()) + { + mHelperHandle.get()->closeFloater(); + } + + if (hostctrl_p) + { + mHostHandle = hostctrl_p->getHandle(); + mHostCtrlFocusLostConn = hostctrl_p->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); })); + } + } } diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index e826ff93e6..2834b06061 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -36,31 +36,31 @@ class LLUICtrl; class LLEmojiHelper : public LLSingleton { - LLSINGLETON(LLEmojiHelper) {} - ~LLEmojiHelper() override {} + LLSINGLETON(LLEmojiHelper) {} + ~LLEmojiHelper() override {} public: - // General - std::string getToolTip(llwchar ch) const; - bool isActive(const LLUICtrl* ctrl_p) const; - static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr); - void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); - void hideHelper(const LLUICtrl* ctrl_p = nullptr, bool strict = false); - void setIsHideDisabled(bool disabled) { mIsHideDisabled = disabled; }; + // General + std::string getToolTip(llwchar ch) const; + bool isActive(const LLUICtrl* ctrl_p) const; + static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr); + void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); + void hideHelper(const LLUICtrl* ctrl_p = nullptr, bool strict = false); + void setIsHideDisabled(bool disabled) { mIsHideDisabled = disabled; }; - // Eventing - bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); - void onCommitEmoji(llwchar emoji); + // Eventing + bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); + void onCommitEmoji(llwchar emoji); protected: - LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } - void setHostCtrl(LLUICtrl* hostctrl_p); + LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } + void setHostCtrl(LLUICtrl* hostctrl_p); private: - LLHandle mHostHandle; - LLHandle mHelperHandle; - boost::signals2::connection mHostCtrlFocusLostConn; - boost::signals2::connection mHelperCommitConn; - std::function mEmojiCommitCb; - bool mIsHideDisabled; + LLHandle mHostHandle; + LLHandle mHelperHandle; + boost::signals2::connection mHostCtrlFocusLostConn; + boost::signals2::connection mHelperCommitConn; + std::function mEmojiCommitCb; + bool mIsHideDisabled; }; diff --git a/indra/llui/llf32uictrl.cpp b/indra/llui/llf32uictrl.cpp index d186f085b4..52954ebbbb 100644 --- a/indra/llui/llf32uictrl.cpp +++ b/indra/llui/llf32uictrl.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2008-09-08 * @brief Implementation for llf32uictrl. - * + * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,13 +36,13 @@ // other Linden headers LLF32UICtrl::LLF32UICtrl(const Params& p) -: LLUICtrl(p), - mInitialValue(p.initial_value().asReal()), - mMinValue(p.min_value), - mMaxValue(p.max_value), +: LLUICtrl(p), + mInitialValue(p.initial_value().asReal()), + mMinValue(p.min_value), + mMaxValue(p.max_value), mIncrement(p.increment) { - mViewModel->setValue(p.initial_value); + mViewModel->setValue(p.initial_value); } F32 LLF32UICtrl::getValueF32() const diff --git a/indra/llui/llf32uictrl.h b/indra/llui/llf32uictrl.h index 6e648f9102..08b9ec7716 100644 --- a/indra/llui/llf32uictrl.h +++ b/indra/llui/llf32uictrl.h @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2008-09-08 * @brief Base class for float-valued LLUICtrl widgets - * + * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,42 +36,42 @@ class LLF32UICtrl: public LLUICtrl public: struct Params: public LLInitParam::Block { - Optional min_value, - max_value, - increment; + Optional min_value, + max_value, + increment; - Params() - : min_value("min_val", 0.f), - max_value("max_val", 1.f), - increment("increment", 0.1f) - {} + Params() + : min_value("min_val", 0.f), + max_value("max_val", 1.f), + increment("increment", 0.1f) + {} }; protected: LLF32UICtrl(const Params& p); public: - virtual F32 getValueF32() const; + virtual F32 getValueF32() const; - virtual void setValue(const LLSD& value ) { mViewModel->setValue(value); } - virtual LLSD getValue() const { return LLSD(getValueF32()); } + virtual void setValue(const LLSD& value ) { mViewModel->setValue(value); } + virtual LLSD getValue() const { return LLSD(getValueF32()); } - virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } - virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } - virtual F32 getInitialValue() const { return mInitialValue; } - virtual F32 getMinValue() const { return mMinValue; } - virtual F32 getMaxValue() const { return mMaxValue; } - virtual F32 getIncrement() const { return mIncrement; } - virtual void setMinValue(F32 min_value) { mMinValue = min_value; } - virtual void setMaxValue(F32 max_value) { mMaxValue = max_value; } - virtual void setIncrement(F32 increment) { mIncrement = increment;} + virtual F32 getInitialValue() const { return mInitialValue; } + virtual F32 getMinValue() const { return mMinValue; } + virtual F32 getMaxValue() const { return mMaxValue; } + virtual F32 getIncrement() const { return mIncrement; } + virtual void setMinValue(F32 min_value) { mMinValue = min_value; } + virtual void setMaxValue(F32 max_value) { mMaxValue = max_value; } + virtual void setIncrement(F32 increment) { mIncrement = increment;} protected: - F32 mInitialValue; - F32 mMinValue; - F32 mMaxValue; - F32 mIncrement; + F32 mInitialValue; + F32 mMinValue; + F32 mMaxValue; + F32 mIncrement; }; #endif /* ! defined(LL_LLF32UICTRL_H) */ diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp index d62874d793..7a5f342cd5 100644 --- a/indra/llui/llfiltereditor.cpp +++ b/indra/llui/llfiltereditor.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfiltereditor.cpp * @brief LLFilterEditor implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -27,20 +27,20 @@ // Text editor widget to let users enter a single line. #include "linden_common.h" - + #include "llfiltereditor.h" LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p) -: LLSearchEditor(p) +: LLSearchEditor(p) { - setCommitOnFocusLost(FALSE); // we'll commit on every keystroke, don't re-commit when we take focus away (i.e. we go to interact with the actual results!) + setCommitOnFocusLost(FALSE); // we'll commit on every keystroke, don't re-commit when we take focus away (i.e. we go to interact with the actual results!) } void LLFilterEditor::handleKeystroke() { - this->LLSearchEditor::handleKeystroke(); + this->LLSearchEditor::handleKeystroke(); - // Commit on every keystroke. - onCommit(); + // Commit on every keystroke. + onCommit(); } diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h index 52cad3bff4..686827d94c 100644 --- a/indra/llui/llfiltereditor.h +++ b/indra/llui/llfiltereditor.h @@ -1,34 +1,34 @@ -/** +/** * @file llfiltereditor.h * @brief Text editor widget that represents a filter operation * - * Features: - * Text entry of a single line (text, delete, left and right arrow, insert, return). - * Callbacks either on every keystroke or just on the return key. - * Focus (allow multiple text entry widgets) - * Clipboard (cut, copy, and paste) - * Horizontal scrolling to allow strings longer than widget size allows - * Pre-validation (limit which keys can be used) - * Optional line history so previous entries can be recalled by CTRL UP/DOWN + * Features: + * Text entry of a single line (text, delete, left and right arrow, insert, return). + * Callbacks either on every keystroke or just on the return key. + * Focus (allow multiple text entry widgets) + * Clipboard (cut, copy, and paste) + * Horizontal scrolling to allow strings longer than widget size allows + * Pre-validation (limit which keys can be used) + * Optional line history so previous entries can be recalled by CTRL UP/DOWN * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,15 +41,15 @@ class LLFilterEditor : public LLSearchEditor { public: - struct Params : public LLInitParam::Block - {}; + struct Params : public LLInitParam::Block + {}; virtual ~LLFilterEditor() {} protected: - LLFilterEditor(const Params&); - friend class LLUICtrlFactory; + LLFilterEditor(const Params&); + friend class LLUICtrlFactory; - /*virtual*/ void handleKeystroke(); + /*virtual*/ void handleKeystroke(); }; #endif // LL_FILTEREDITOR_H diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index 39793316f4..2de05f04c5 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -28,71 +28,71 @@ #include "llui.h" LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) -: LLEventTimer(period), - mCallback(cb), - mCurrentTickCount(0), +: LLEventTimer(period), + mCallback(cb), + mCurrentTickCount(0), mIsFlashingInProgress(false), mIsCurrentlyHighlighted(false), mUnset(false) { - mEventTimer.stop(); + mEventTimer.stop(); - // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. - // Due to Timer is implemented as derived class from EventTimer it is impossible to change period - // in runtime. So, both settings are made as required restart. - mFlashCount = 2 * ((count > 0) ? count : LLUI::getInstance()->mSettingGroups["config"]->getS32("FlashCount")); - if (mPeriod <= 0) - { - mPeriod = LLUI::getInstance()->mSettingGroups["config"]->getF32("FlashPeriod"); - } + // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. + // Due to Timer is implemented as derived class from EventTimer it is impossible to change period + // in runtime. So, both settings are made as required restart. + mFlashCount = 2 * ((count > 0) ? count : LLUI::getInstance()->mSettingGroups["config"]->getS32("FlashCount")); + if (mPeriod <= 0) + { + mPeriod = LLUI::getInstance()->mSettingGroups["config"]->getF32("FlashPeriod"); + } } void LLFlashTimer::unset() { - mUnset = true; - mCallback = NULL; + mUnset = true; + mCallback = NULL; } BOOL LLFlashTimer::tick() { - mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted; + mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted; - if (mCallback) - { - mCallback(mIsCurrentlyHighlighted); - } + if (mCallback) + { + mCallback(mIsCurrentlyHighlighted); + } - if (++mCurrentTickCount >= mFlashCount) - { - stopFlashing(); - } + if (++mCurrentTickCount >= mFlashCount) + { + stopFlashing(); + } - return mUnset; + return mUnset; } void LLFlashTimer::startFlashing() { - mIsFlashingInProgress = true; - mIsCurrentlyHighlighted = true; - mEventTimer.start(); + mIsFlashingInProgress = true; + mIsCurrentlyHighlighted = true; + mEventTimer.start(); } void LLFlashTimer::stopFlashing() { - mEventTimer.stop(); - mIsFlashingInProgress = false; - mIsCurrentlyHighlighted = false; - mCurrentTickCount = 0; + mEventTimer.stop(); + mIsFlashingInProgress = false; + mIsCurrentlyHighlighted = false; + mCurrentTickCount = 0; } bool LLFlashTimer::isFlashingInProgress() { - return mIsFlashingInProgress; + return mIsFlashingInProgress; } bool LLFlashTimer::isCurrentlyHighlighted() { - return mIsCurrentlyHighlighted; + return mIsCurrentlyHighlighted; } diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index db8d49f009..037e32ac50 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -34,41 +34,41 @@ class LLFlashTimer : public LLEventTimer { public: - typedef boost::function callback_t; + typedef boost::function callback_t; - /** - * Constructor. - * - * @param count - how many times callback should be called (twice to not change original state) - * @param period - how frequently callback should be called - * @param cb - callback to be called each tick - */ - LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); - ~LLFlashTimer() {}; + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); + ~LLFlashTimer() {}; - /*virtual*/ BOOL tick(); + /*virtual*/ BOOL tick(); - void startFlashing(); - void stopFlashing(); + void startFlashing(); + void stopFlashing(); - bool isFlashingInProgress(); - bool isCurrentlyHighlighted(); - /* - * Use this instead of deleting this object. - * The next call to tick() will return true and that will destroy this object. - */ - void unset(); + bool isFlashingInProgress(); + bool isCurrentlyHighlighted(); + /* + * Use this instead of deleting this object. + * The next call to tick() will return true and that will destroy this object. + */ + void unset(); private: - callback_t mCallback; - /** - * How many times parent will blink. - */ - S32 mFlashCount; - S32 mCurrentTickCount; - bool mIsCurrentlyHighlighted; - bool mIsFlashingInProgress; - bool mUnset; + callback_t mCallback; + /** + * How many times parent will blink. + */ + S32 mFlashCount; + S32 mCurrentTickCount; + bool mIsCurrentlyHighlighted; + bool mIsFlashingInProgress; + bool mUnset; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index fd4c33df30..cd866f1625 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llflatlistview.cpp * @brief LLFlatListView base class and extension to support messages for several cases of an empty list. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,76 +33,76 @@ static const LLDefaultChildRegistry::Register flat_list_view("flat_list_view"); -const LLSD SELECTED_EVENT = LLSD().with("selected", true); -const LLSD UNSELECTED_EVENT = LLSD().with("selected", false); +const LLSD SELECTED_EVENT = LLSD().with("selected", true); +const LLSD UNSELECTED_EVENT = LLSD().with("selected", false); //forward declaration bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2); LLFlatListView::Params::Params() -: item_pad("item_pad"), - allow_select("allow_select"), - multi_select("multi_select"), - keep_one_selected("keep_one_selected"), - keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false), - no_items_text("no_items_text") +: item_pad("item_pad"), + allow_select("allow_select"), + multi_select("multi_select"), + keep_one_selected("keep_one_selected"), + keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false), + no_items_text("no_items_text") {}; void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - S32 delta = height - getRect().getHeight(); - LLScrollContainer::reshape(width, height, called_from_parent); - setItemsNoScrollWidth(width); - rearrangeItems(); - - if(delta!= 0 && mKeepSelectionVisibleOnReshape) - { - ensureSelectedVisible(); - } + S32 delta = height - getRect().getHeight(); + LLScrollContainer::reshape(width, height, called_from_parent); + setItemsNoScrollWidth(width); + rearrangeItems(); + + if(delta!= 0 && mKeepSelectionVisibleOnReshape) + { + ensureSelectedVisible(); + } } const LLRect& LLFlatListView::getItemsRect() const { - return mItemsPanel->getRect(); + return mItemsPanel->getRect(); } bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/) { - if (!item) return false; - if (value.isUndefined()) return false; - - //force uniqueness of items, easiest check but unreliable - if (item->getParent() == mItemsPanel) return false; - - item_pair_t* new_pair = new item_pair_t(item, value); - switch (pos) - { - case ADD_TOP: - mItemPairs.push_front(new_pair); - //in LLView::draw() children are iterated in backorder - mItemsPanel->addChildInBack(item); - break; - case ADD_BOTTOM: - mItemPairs.push_back(new_pair); - mItemsPanel->addChild(item); - break; - default: - break; - } - - //_4 is for MASK - item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); - item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); - - // Children don't accept the focus - item->setTabStop(false); - - if (rearrange) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - } - return true; + if (!item) return false; + if (value.isUndefined()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item->getParent() == mItemsPanel) return false; + + item_pair_t* new_pair = new item_pair_t(item, value); + switch (pos) + { + case ADD_TOP: + mItemPairs.push_front(new_pair); + //in LLView::draw() children are iterated in backorder + mItemsPanel->addChildInBack(item); + break; + case ADD_BOTTOM: + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item); + break; + default: + break; + } + + //_4 is for MASK + item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + // Children don't accept the focus + item->setTabStop(false); + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + return true; } bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/) @@ -183,263 +183,263 @@ bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= tr bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/) { - if (!after_item) return false; - if (!item_to_add) return false; - if (value.isUndefined()) return false; - - if (mItemPairs.empty()) return false; - - //force uniqueness of items, easiest check but unreliable - if (item_to_add->getParent() == mItemsPanel) return false; - - item_pair_t* after_pair = getItemPair(after_item); - if (!after_pair) return false; - - item_pair_t* new_pair = new item_pair_t(item_to_add, value); - if (after_pair == mItemPairs.back()) - { - mItemPairs.push_back(new_pair); - mItemsPanel->addChild(item_to_add); - } - else - { - pairs_iterator_t it = mItemPairs.begin(); - for (; it != mItemPairs.end(); ++it) - { - if (*it == after_pair) - { - // insert new elements before the element at position of passed iterator. - mItemPairs.insert(++it, new_pair); - mItemsPanel->addChild(item_to_add); - break; - } - } - } - - //_4 is for MASK - item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); - item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); - - rearrangeItems(); - notifyParentItemsRectChanged(); - return true; + if (!after_item) return false; + if (!item_to_add) return false; + if (value.isUndefined()) return false; + + if (mItemPairs.empty()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item_to_add->getParent() == mItemsPanel) return false; + + item_pair_t* after_pair = getItemPair(after_item); + if (!after_pair) return false; + + item_pair_t* new_pair = new item_pair_t(item_to_add, value); + if (after_pair == mItemPairs.back()) + { + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item_to_add); + } + else + { + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + if (*it == after_pair) + { + // insert new elements before the element at position of passed iterator. + mItemPairs.insert(++it, new_pair); + mItemsPanel->addChild(item_to_add); + break; + } + } + } + + //_4 is for MASK + item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + rearrangeItems(); + notifyParentItemsRectChanged(); + return true; } bool LLFlatListView::removeItem(LLPanel* item, bool rearrange) { - if (!item) return false; - if (item->getParent() != mItemsPanel) return false; - - item_pair_t* item_pair = getItemPair(item); - if (!item_pair) return false; + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; - return removeItemPair(item_pair, rearrange); + return removeItemPair(item_pair, rearrange); } bool LLFlatListView::removeItemByValue(const LLSD& value, bool rearrange) { - if (value.isUndefined()) return false; - - item_pair_t* item_pair = getItemPair(value); - if (!item_pair) return false; + if (value.isUndefined()) return false; - return removeItemPair(item_pair, rearrange); + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; + + return removeItemPair(item_pair, rearrange); } bool LLFlatListView::removeItemByUUID(const LLUUID& uuid, bool rearrange) { - return removeItemByValue(LLSD(uuid), rearrange); + return removeItemByValue(LLSD(uuid), rearrange); } LLPanel* LLFlatListView::getItemByValue(const LLSD& value) const { - if (value.isUndefined()) return NULL; + if (value.isUndefined()) return NULL; - item_pair_t* pair = getItemPair(value); - if (pair) return pair->first; - return NULL; + item_pair_t* pair = getItemPair(value); + if (pair) return pair->first; + return NULL; } bool LLFlatListView::selectItem(LLPanel* item, bool select /*= true*/) { - if (!item) return false; - if (item->getParent() != mItemsPanel) return false; - - item_pair_t* item_pair = getItemPair(item); - if (!item_pair) return false; + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; - return selectItemPair(item_pair, select); + return selectItemPair(item_pair, select); } bool LLFlatListView::selectItemByValue(const LLSD& value, bool select /*= true*/) { - if (value.isUndefined()) return false; + if (value.isUndefined()) return false; - item_pair_t* item_pair = getItemPair(value); - if (!item_pair) return false; + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; - return selectItemPair(item_pair, select); + return selectItemPair(item_pair, select); } bool LLFlatListView::selectItemByUUID(const LLUUID& uuid, bool select /* = true*/) { - return selectItemByValue(LLSD(uuid), select); + return selectItemByValue(LLSD(uuid), select); } LLSD LLFlatListView::getSelectedValue() const { - if (mSelectedItemPairs.empty()) return LLSD(); + if (mSelectedItemPairs.empty()) return LLSD(); - item_pair_t* first_selected_pair = mSelectedItemPairs.front(); - return first_selected_pair->second; + item_pair_t* first_selected_pair = mSelectedItemPairs.front(); + return first_selected_pair->second; } void LLFlatListView::getSelectedValues(std::vector& selected_values) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_values.push_back((*it)->second); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_values.push_back((*it)->second); + } } LLUUID LLFlatListView::getSelectedUUID() const { - const LLSD& value = getSelectedValue(); - if (value.isDefined() && value.isUUID()) - { - return value.asUUID(); - } - else - { - return LLUUID::null; - } + const LLSD& value = getSelectedValue(); + if (value.isDefined() && value.isUUID()) + { + return value.asUUID(); + } + else + { + return LLUUID::null; + } } void LLFlatListView::getSelectedUUIDs(uuid_vec_t& selected_uuids) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_uuids.push_back((*it)->second.asUUID()); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_uuids.push_back((*it)->second.asUUID()); + } } LLPanel* LLFlatListView::getSelectedItem() const { - if (mSelectedItemPairs.empty()) return NULL; + if (mSelectedItemPairs.empty()) return NULL; - return mSelectedItemPairs.front()->first; + return mSelectedItemPairs.front()->first; } void LLFlatListView::getSelectedItems(std::vector& selected_items) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_items.push_back((*it)->first); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_items.push_back((*it)->first); + } } void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/) { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - item_pair_t* pair_to_deselect = *it; - LLPanel* item = pair_to_deselect->first; - item->setValue(UNSELECTED_EVENT); - } + for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* pair_to_deselect = *it; + LLPanel* item = pair_to_deselect->first; + item->setValue(UNSELECTED_EVENT); + } - mSelectedItemPairs.clear(); + mSelectedItemPairs.clear(); - if (mCommitOnSelectionChange && !no_commit_on_deselection) - { - onCommit(); - } + if (mCommitOnSelectionChange && !no_commit_on_deselection) + { + onCommit(); + } - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } void LLFlatListView::setNoItemsCommentText(const std::string& comment_text) { - mNoItemsCommentTextbox->setValue(comment_text); + mNoItemsCommentTextbox->setValue(comment_text); } U32 LLFlatListView::size(const bool only_visible_items) const { - if (only_visible_items) - { - U32 size = 0; - for (pairs_const_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - if ((*iter)->first->getVisible()) - ++size; - } - return size; - } - else - { - return mItemPairs.size(); - } + if (only_visible_items) + { + U32 size = 0; + for (pairs_const_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + if ((*iter)->first->getVisible()) + ++size; + } + return size; + } + else + { + return mItemPairs.size(); + } } void LLFlatListView::clear() { - // This will clear mSelectedItemPairs, calling all appropriate callbacks. - resetSelection(); - - // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex. - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - mItemsPanel->removeChild((*it)->first); - (*it)->first->die(); - delete *it; - } - mItemPairs.clear(); - - // also set items panel height to zero. Reshape it to allow reshaping of non-item children - LLRect rc = mItemsPanel->getRect(); - rc.mBottom = rc.mTop; - mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); - mItemsPanel->setRect(rc); - - setNoItemsCommentVisible(true); - notifyParentItemsRectChanged(); + // This will clear mSelectedItemPairs, calling all appropriate callbacks. + resetSelection(); + + // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex. + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); + + // also set items panel height to zero. Reshape it to allow reshaping of non-item children + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + + setNoItemsCommentVisible(true); + notifyParentItemsRectChanged(); } void LLFlatListView::sort() { - if (!mItemComparator) - { - LL_WARNS() << "No comparator specified for sorting FlatListView items." << LL_ENDL; - return; - } - - mItemPairs.sort(ComparatorAdaptor(*mItemComparator)); - rearrangeItems(); + if (!mItemComparator) + { + LL_WARNS() << "No comparator specified for sorting FlatListView items." << LL_ENDL; + return; + } + + mItemPairs.sort(ComparatorAdaptor(*mItemComparator)); + rearrangeItems(); } bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value) { - if (old_value.isUndefined() || new_value.isUndefined()) return false; - if (llsds_are_equal(old_value, new_value)) return false; + if (old_value.isUndefined() || new_value.isUndefined()) return false; + if (llsds_are_equal(old_value, new_value)) return false; - item_pair_t* item_pair = getItemPair(old_value); - if (!item_pair) return false; + item_pair_t* item_pair = getItemPair(old_value); + if (!item_pair) return false; - item_pair->second = new_value; - return true; + item_pair->second = new_value; + return true; } ////////////////////////////////////////////////////////////////////////// @@ -447,7 +447,7 @@ bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value) ////////////////////////////////////////////////////////////////////////// LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) -: LLScrollContainer(p) +: LLScrollContainer(p) , mItemComparator(NULL) , mItemsPanel(NULL) , mItemPad(p.item_pad) @@ -460,857 +460,857 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) , mIsConsecutiveSelection(false) , mKeepSelectionVisibleOnReshape(p.keep_selection_visible_on_reshape) { - mBorderThickness = getBorderWidth(); - - LLRect scroll_rect = getRect(); - LLRect items_rect; - - setItemsNoScrollWidth(scroll_rect.getWidth()); - items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0); - - LLPanel::Params pp; - pp.rect(items_rect); - mItemsPanel = LLUICtrlFactory::create (pp); - addChild(mItemsPanel); - - //we don't need to stretch in vertical direction on reshaping by a parent - //no bottom following! - mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - - LLViewBorder::Params params; - params.name("scroll border"); - params.rect(getLastSelectedItemRect()); - params.visible(false); - params.bevel_style(LLViewBorder::BEVEL_IN); - mSelectedItemsBorder = LLUICtrlFactory::create (params); - mItemsPanel->addChild( mSelectedItemsBorder ); - - { - // create textbox for "No Items" comment text - LLTextBox::Params text_p = p.no_items_text; - if (!text_p.rect.isProvided()) - { - LLRect comment_rect = getRect(); - comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight()); - comment_rect.stretch(-getBorderWidth()); - text_p.rect(comment_rect); - } - text_p.border_visible(false); - - if (!text_p.follows.isProvided()) - { - text_p.follows.flags(FOLLOWS_ALL); - } - mNoItemsCommentTextbox = LLUICtrlFactory::create(text_p, this); - } + mBorderThickness = getBorderWidth(); + + LLRect scroll_rect = getRect(); + LLRect items_rect; + + setItemsNoScrollWidth(scroll_rect.getWidth()); + items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0); + + LLPanel::Params pp; + pp.rect(items_rect); + mItemsPanel = LLUICtrlFactory::create (pp); + addChild(mItemsPanel); + + //we don't need to stretch in vertical direction on reshaping by a parent + //no bottom following! + mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + + LLViewBorder::Params params; + params.name("scroll border"); + params.rect(getLastSelectedItemRect()); + params.visible(false); + params.bevel_style(LLViewBorder::BEVEL_IN); + mSelectedItemsBorder = LLUICtrlFactory::create (params); + mItemsPanel->addChild( mSelectedItemsBorder ); + + { + // create textbox for "No Items" comment text + LLTextBox::Params text_p = p.no_items_text; + if (!text_p.rect.isProvided()) + { + LLRect comment_rect = getRect(); + comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight()); + comment_rect.stretch(-getBorderWidth()); + text_p.rect(comment_rect); + } + text_p.border_visible(false); + + if (!text_p.follows.isProvided()) + { + text_p.follows.flags(FOLLOWS_ALL); + } + mNoItemsCommentTextbox = LLUICtrlFactory::create(text_p, this); + } }; LLFlatListView::~LLFlatListView() { - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - mItemsPanel->removeChild((*it)->first); - (*it)->first->die(); - delete *it; - } - mItemPairs.clear(); + 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() { - // Highlight border if a child of this container has keyboard focus - if( mSelectedItemsBorder->getVisible() ) - { - mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); - } - LLScrollContainer::draw(); + // Highlight border if a child of this container has keyboard focus + if( mSelectedItemsBorder->getVisible() ) + { + mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); + } + LLScrollContainer::draw(); } // virtual BOOL LLFlatListView::postBuild() { - setTabStop(true); - return LLScrollContainer::postBuild(); + setTabStop(true); + return LLScrollContainer::postBuild(); } void LLFlatListView::rearrangeItems() { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - setNoItemsCommentVisible(0==size()); + setNoItemsCommentVisible(0==size()); - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - //calculating required height - assuming items can be of different height - //list should accommodate all its items - S32 height = 0; + //calculating required height - assuming items can be of different height + //list should accommodate all its items + S32 height = 0; - S32 invisible_children_count = 0; - pairs_iterator_t it = mItemPairs.begin(); - for (; it != mItemPairs.end(); ++it) - { - LLPanel* item = (*it)->first; + S32 invisible_children_count = 0; + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + LLPanel* item = (*it)->first; - // skip invisible child - if (!item->getVisible()) - { - ++invisible_children_count; - continue; - } + // skip invisible child + if (!item->getVisible()) + { + ++invisible_children_count; + continue; + } - height += item->getRect().getHeight(); - } + height += item->getRect().getHeight(); + } - // add paddings between items, excluding invisible ones - height += mItemPad * (mItemPairs.size() - invisible_children_count - 1); + // add paddings between items, excluding invisible ones + height += mItemPad * (mItemPairs.size() - invisible_children_count - 1); - LLRect rc = mItemsPanel->getRect(); - S32 width = mItemsNoScrollWidth; + LLRect rc = mItemsPanel->getRect(); + S32 width = mItemsNoScrollWidth; - // update width to avoid horizontal scrollbar - if (height > getRect().getHeight() - 2 * mBorderThickness) - width -= scrollbar_size; + // update width to avoid horizontal scrollbar + if (height > getRect().getHeight() - 2 * mBorderThickness) + width -= scrollbar_size; - //changes the bottom, end of the list goes down in the scroll container - rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height); - mItemsPanel->setRect(rc); + //changes the bottom, end of the list goes down in the scroll container + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height); + mItemsPanel->setRect(rc); - //reshaping items - S32 item_new_top = height; - pairs_iterator_t it2, first_it = mItemPairs.begin(); - for (it2 = first_it; it2 != mItemPairs.end(); ++it2) - { - LLPanel* item = (*it2)->first; + //reshaping items + S32 item_new_top = height; + pairs_iterator_t it2, first_it = mItemPairs.begin(); + for (it2 = first_it; it2 != mItemPairs.end(); ++it2) + { + LLPanel* item = (*it2)->first; - // skip invisible child - if (!item->getVisible()) - continue; + // skip invisible child + if (!item->getVisible()) + continue; - LLRect rc = item->getRect(); - rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight()); - item->reshape(rc.getWidth(), rc.getHeight()); - item->setRect(rc); + LLRect rc = item->getRect(); + rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight()); + item->reshape(rc.getWidth(), rc.getHeight()); + item->setRect(rc); - // move top for next item in list - item_new_top -= (rc.getHeight() + mItemPad); - } + // move top for next item in list + item_new_top -= (rc.getHeight() + mItemPad); + } - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) { - if (!item_pair) return; - - if (!item_pair->first) - { - LL_WARNS() << "Attempt to selet an item pair containing null panel item" << LL_ENDL; - return; - } - - setFocus(TRUE); - - bool select_item = !isSelected(item_pair); - - //*TODO find a better place for that enforcing stuff - if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; - - if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) - && mMultipleSelection && !mSelectedItemPairs.empty() ) - { - item_pair_t* last_selected_pair = mSelectedItemPairs.back(); - - // If item_pair is already selected - do nothing - if (last_selected_pair == item_pair) - return; - - bool grab_items = false; - bool reverse = false; - pairs_list_t pairs_to_select; - - // Pick out items from list between last selected and current clicked item_pair. - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - item_pair_t* cur = *iter; - if (cur == last_selected_pair || cur == item_pair) - { - // We've got reverse selection if last grabed item isn't a new selection. - reverse = grab_items && (cur != item_pair); - grab_items = !grab_items; - // Skip last selected and current clicked item pairs. - continue; - } - if (!cur->first->getVisible()) - { - // Skip invisible item pairs. - continue; - } - if (grab_items) - { - pairs_to_select.push_back(cur); - } - } - - if (reverse) - { - pairs_to_select.reverse(); - } - - pairs_to_select.push_back(item_pair); - - for (pairs_iterator_t - iter = pairs_to_select.begin(), - iter_end = pairs_to_select.end(); - iter != iter_end; ++iter) - { - item_pair_t* pair_to_select = *iter; - if (isSelected(pair_to_select)) - { - // Item was already selected but there is a need to keep order from last selected pair to new selection. - // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). - mSelectedItemPairs.remove(pair_to_select); - mSelectedItemPairs.push_back(pair_to_select); - } - else - { - selectItemPair(pair_to_select, true); - } - } - - if (!select_item) - { - // Update last selected item border. - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); - } - return; - } - - //no need to do additional commit on selection reset - if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); - - //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it - if (mask & MASK_CONTROL) - selectItemPair(item_pair, select_item); - else - selectItemPair(item_pair, true); + if (!item_pair) return; + + if (!item_pair->first) + { + LL_WARNS() << "Attempt to selet an item pair containing null panel item" << LL_ENDL; + return; + } + + setFocus(TRUE); + + bool select_item = !isSelected(item_pair); + + //*TODO find a better place for that enforcing stuff + if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; + + if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) + && mMultipleSelection && !mSelectedItemPairs.empty() ) + { + item_pair_t* last_selected_pair = mSelectedItemPairs.back(); + + // If item_pair is already selected - do nothing + if (last_selected_pair == item_pair) + return; + + bool grab_items = false; + bool reverse = false; + pairs_list_t pairs_to_select; + + // Pick out items from list between last selected and current clicked item_pair. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* cur = *iter; + if (cur == last_selected_pair || cur == item_pair) + { + // We've got reverse selection if last grabed item isn't a new selection. + reverse = grab_items && (cur != item_pair); + grab_items = !grab_items; + // Skip last selected and current clicked item pairs. + continue; + } + if (!cur->first->getVisible()) + { + // Skip invisible item pairs. + continue; + } + if (grab_items) + { + pairs_to_select.push_back(cur); + } + } + + if (reverse) + { + pairs_to_select.reverse(); + } + + pairs_to_select.push_back(item_pair); + + for (pairs_iterator_t + iter = pairs_to_select.begin(), + iter_end = pairs_to_select.end(); + iter != iter_end; ++iter) + { + item_pair_t* pair_to_select = *iter; + if (isSelected(pair_to_select)) + { + // Item was already selected but there is a need to keep order from last selected pair to new selection. + // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). + mSelectedItemPairs.remove(pair_to_select); + mSelectedItemPairs.push_back(pair_to_select); + } + else + { + selectItemPair(pair_to_select, true); + } + } + + if (!select_item) + { + // Update last selected item border. + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + } + return; + } + + //no need to do additional commit on selection reset + if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); + + //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it + if (mask & MASK_CONTROL) + selectItemPair(item_pair, select_item); + else + selectItemPair(item_pair, true); } void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask) { - if (!item_pair) - return; + if (!item_pair) + return; - // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on, - // because some of derived classes may have context menu and selected items must be kept. - if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) ) - return; + // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on, + // because some of derived classes may have context menu and selected items must be kept. + if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) ) + return; - // else got same behavior as at onItemMouseClick - onItemMouseClick(item_pair, mask); + // else got same behavior as at onItemMouseClick + onItemMouseClick(item_pair, mask); } BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) { - BOOL reset_selection = (mask != MASK_SHIFT); - BOOL handled = FALSE; - switch (key) - { - case KEY_RETURN: - { - if (mSelectedItemPairs.size() && mask == MASK_NONE) - { - mOnReturnSignal(this, getValue()); - handled = TRUE; - } - break; - } - case KEY_UP: - { - if ( !selectNextItemPair(true, reset_selection) && reset_selection) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - resetSelection(); - } - break; - } - case KEY_DOWN: - { - if ( !selectNextItemPair(false, reset_selection) && reset_selection) - { - // If case we are in accordion tab notify parent to go to the next accordion - if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed - resetSelection(); - } - break; - } - case KEY_ESCAPE: - { - if (mask == MASK_NONE) - { - setFocus(FALSE); // pass focus to the game area (EXT-8357) - } - break; - } - default: - break; - } - - if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) - { - ensureSelectedVisible(); - /* - LLRect visible_rc = getVisibleContentRect(); - LLRect selected_rc = getLastSelectedItemRect(); - - if ( !visible_rc.contains (selected_rc) ) - { - // But scroll in Items panel coordinates - scrollToShowRect(selected_rc); - } - - // In case we are in accordion tab notify parent to show selected rectangle - LLRect screen_rc; - localRectToScreen(selected_rc, &screen_rc); - notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ - - handled = TRUE; - } - - return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); + BOOL reset_selection = (mask != MASK_SHIFT); + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + { + if (mSelectedItemPairs.size() && mask == MASK_NONE) + { + mOnReturnSignal(this, getValue()); + handled = TRUE; + } + break; + } + case KEY_UP: + { + if ( !selectNextItemPair(true, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + resetSelection(); + } + break; + } + case KEY_DOWN: + { + if ( !selectNextItemPair(false, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the next accordion + if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed + resetSelection(); + } + break; + } + case KEY_ESCAPE: + { + if (mask == MASK_NONE) + { + setFocus(FALSE); // pass focus to the game area (EXT-8357) + } + break; + } + default: + break; + } + + if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) + { + ensureSelectedVisible(); + /* + LLRect visible_rc = getVisibleContentRect(); + LLRect selected_rc = getLastSelectedItemRect(); + + if ( !visible_rc.contains (selected_rc) ) + { + // But scroll in Items panel coordinates + scrollToShowRect(selected_rc); + } + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ + + handled = TRUE; + } + + return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); } LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const { - llassert(item); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - if (item_pair->first == item) return item_pair; - } - return NULL; + llassert(item); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (item_pair->first == item) return item_pair; + } + return NULL; } //compares two LLSD's bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2) { - llassert(llsd_1.isDefined()); - llassert(llsd_2.isDefined()); - - if (llsd_1.type() != llsd_2.type()) return false; - - if (!llsd_1.isMap()) - { - if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID(); - - //assumptions that string representaion is enough for other types - return llsd_1.asString() == llsd_2.asString(); - } - - if (llsd_1.size() != llsd_2.size()) return false; - - LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap(); - LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap(); - for (S32 i = 0; i < llsd_1.size(); ++i) - { - if ((*llsd_1_it).first != (*llsd_2_it).first) return false; - if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false; - ++llsd_1_it; - ++llsd_2_it; - } - return true; + llassert(llsd_1.isDefined()); + llassert(llsd_2.isDefined()); + + if (llsd_1.type() != llsd_2.type()) return false; + + if (!llsd_1.isMap()) + { + if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID(); + + //assumptions that string representaion is enough for other types + return llsd_1.asString() == llsd_2.asString(); + } + + if (llsd_1.size() != llsd_2.size()) return false; + + LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap(); + LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap(); + for (S32 i = 0; i < llsd_1.size(); ++i) + { + if ((*llsd_1_it).first != (*llsd_2_it).first) return false; + if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false; + ++llsd_1_it; + ++llsd_2_it; + } + return true; } LLFlatListView::item_pair_t* LLFlatListView::getItemPair(const LLSD& value) const { - llassert(value.isDefined()); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - if (llsds_are_equal(item_pair->second, value)) return item_pair; - } - return NULL; + llassert(value.isDefined()); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (llsds_are_equal(item_pair->second, value)) return item_pair; + } + return NULL; } bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select) { - llassert(item_pair); - - if (!mAllowSelection && select) return false; - - if (isSelected(item_pair) == select) return true; //already in specified selection state - if (select) - { - mSelectedItemPairs.push_back(item_pair); - } - else - { - mSelectedItemPairs.remove(item_pair); - } - - //a way of notifying panel of selection state changes - LLPanel* item = item_pair->first; - item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT); - - if (mCommitOnSelectionChange) - { - onCommit(); - } - - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); - // By default mark it as not consecutive selection - mIsConsecutiveSelection = false; - - return true; + llassert(item_pair); + + if (!mAllowSelection && select) return false; + + if (isSelected(item_pair) == select) return true; //already in specified selection state + if (select) + { + mSelectedItemPairs.push_back(item_pair); + } + else + { + mSelectedItemPairs.remove(item_pair); + } + + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT); + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // By default mark it as not consecutive selection + mIsConsecutiveSelection = false; + + return true; } void LLFlatListView::scrollToShowFirstSelectedItem() { - if (!mSelectedItemPairs.size()) return; + if (!mSelectedItemPairs.size()) return; - LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); + LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); - if (selected_rc.isValid()) - { - scrollToShowRect(selected_rc); - } + if (selected_rc.isValid()) + { + scrollToShowRect(selected_rc); + } } LLRect LLFlatListView::getLastSelectedItemRect() { - if (!mSelectedItemPairs.size()) - { - return LLRect::null; - } + if (!mSelectedItemPairs.size()) + { + return LLRect::null; + } - return mSelectedItemPairs.back()->first->getRect(); + return mSelectedItemPairs.back()->first->getRect(); } -void LLFlatListView::selectFirstItem () +void LLFlatListView::selectFirstItem () { - // No items - no actions! - if (0 == size()) return; - - // Select first visible item - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - // skip invisible items - if ( (*iter)->first->getVisible() ) - { - selectItemPair(*iter, true); - ensureSelectedVisible(); - break; - } - } + // No items - no actions! + if (0 == size()) return; + + // Select first visible item + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + // skip invisible items + if ( (*iter)->first->getVisible() ) + { + selectItemPair(*iter, true); + ensureSelectedVisible(); + break; + } + } } -void LLFlatListView::selectLastItem () +void LLFlatListView::selectLastItem () { - // No items - no actions! - if (0 == size()) return; - - // Select last visible item - for (pairs_list_t::reverse_iterator - r_iter = mItemPairs.rbegin(), - r_iter_end = mItemPairs.rend(); - r_iter != r_iter_end; ++r_iter) - { - // skip invisible items - if ( (*r_iter)->first->getVisible() ) - { - selectItemPair(*r_iter, true); - ensureSelectedVisible(); - break; - } - } + // No items - no actions! + if (0 == size()) return; + + // Select last visible item + for (pairs_list_t::reverse_iterator + r_iter = mItemPairs.rbegin(), + r_iter_end = mItemPairs.rend(); + r_iter != r_iter_end; ++r_iter) + { + // skip invisible items + if ( (*r_iter)->first->getVisible() ) + { + selectItemPair(*r_iter, true); + ensureSelectedVisible(); + break; + } + } } void LLFlatListView::ensureSelectedVisible() { - LLRect selected_rc = getLastSelectedItemRect(); + LLRect selected_rc = getLastSelectedItemRect(); - if ( selected_rc.isValid() ) - { - scrollToShowRect(selected_rc); - } + if ( selected_rc.isValid() ) + { + scrollToShowRect(selected_rc); + } } // virtual bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection) { - // No items - no actions! - if ( 0 == size() ) - return false; - - if (!mIsConsecutiveSelection) - { - // Leave only one item selected if list has not consecutive selection - if (mSelectedItemPairs.size() && !reset_selection) - { - item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); - resetSelection(); - selectItemPair (cur_sel_pair, true); - } - } - - if ( mSelectedItemPairs.size() ) - { - item_pair_t* to_sel_pair = NULL; - item_pair_t* cur_sel_pair = NULL; - - // Take the last selected pair - cur_sel_pair = mSelectedItemPairs.back(); - // Bases on given direction choose next item to select - if ( is_up_direction ) - { - // Find current selected item position in mItemPairs list - pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); - - for (;++sel_it != mItemPairs.rend();) - { - // skip invisible items - if ( (*sel_it)->first->getVisible() ) - { - to_sel_pair = *sel_it; - break; - } - } - } - else - { - // Find current selected item position in mItemPairs list - pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); - - for (;++sel_it != mItemPairs.end();) - { - // skip invisible items - if ( (*sel_it)->first->getVisible() ) - { - to_sel_pair = *sel_it; - break; - } - } - } - - if ( to_sel_pair ) - { - bool select = true; - if ( reset_selection ) - { - // Reset current selection if we were asked about it - resetSelection(); - } - else - { - // If item already selected and no reset request than we should deselect last selected item. - select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); - } - // Select/Deselect next item - selectItemPair(select ? to_sel_pair : cur_sel_pair, select); - // Mark it as consecutive selection - mIsConsecutiveSelection = true; - return true; - } - } - else - { - // If there weren't selected items then choose the first one bases on given direction - // Force selection to first item - if (is_up_direction) - selectLastItem(); - else - selectFirstItem(); - // Mark it as consecutive selection - mIsConsecutiveSelection = true; - return true; - } - - return false; + // No items - no actions! + if ( 0 == size() ) + return false; + + if (!mIsConsecutiveSelection) + { + // Leave only one item selected if list has not consecutive selection + if (mSelectedItemPairs.size() && !reset_selection) + { + item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); + resetSelection(); + selectItemPair (cur_sel_pair, true); + } + } + + if ( mSelectedItemPairs.size() ) + { + item_pair_t* to_sel_pair = NULL; + item_pair_t* cur_sel_pair = NULL; + + // Take the last selected pair + cur_sel_pair = mSelectedItemPairs.back(); + // Bases on given direction choose next item to select + if ( is_up_direction ) + { + // Find current selected item position in mItemPairs list + pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); + + for (;++sel_it != mItemPairs.rend();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + else + { + // Find current selected item position in mItemPairs list + pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); + + for (;++sel_it != mItemPairs.end();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + + if ( to_sel_pair ) + { + bool select = true; + if ( reset_selection ) + { + // Reset current selection if we were asked about it + resetSelection(); + } + else + { + // If item already selected and no reset request than we should deselect last selected item. + select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); + } + // Select/Deselect next item + selectItemPair(select ? to_sel_pair : cur_sel_pair, select); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + } + else + { + // If there weren't selected items then choose the first one bases on given direction + // Force selection to first item + if (is_up_direction) + selectLastItem(); + else + selectFirstItem(); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + + return false; } BOOL LLFlatListView::canSelectAll() const { - return 0 != size() && mAllowSelection && mMultipleSelection; + return 0 != size() && mAllowSelection && mMultipleSelection; } void LLFlatListView::selectAll() { - if (!mAllowSelection || !mMultipleSelection) - return; - - mSelectedItemPairs.clear(); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - mSelectedItemPairs.push_back(item_pair); - //a way of notifying panel of selection state changes - LLPanel* item = item_pair->first; - item->setValue(SELECTED_EVENT); - } - - if (mCommitOnSelectionChange) - { - onCommit(); - } - - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + if (!mAllowSelection || !mMultipleSelection) + return; + + mSelectedItemPairs.clear(); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + mSelectedItemPairs.push_back(item_pair); + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(SELECTED_EVENT); + } + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } bool LLFlatListView::isSelected(item_pair_t* item_pair) const { - llassert(item_pair); + llassert(item_pair); - pairs_const_iterator_t it_end = mSelectedItemPairs.end(); - return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end; + pairs_const_iterator_t it_end = mSelectedItemPairs.end(); + return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end; } bool LLFlatListView::removeItemPair(item_pair_t* item_pair, bool rearrange) { - llassert(item_pair); - - bool deleted = false; - bool selection_changed = false; - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* _item_pair = *it; - if (_item_pair == item_pair) - { - mItemPairs.erase(it); - deleted = true; - break; - } - } - - if (!deleted) return false; - - for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - item_pair_t* selected_item_pair = *it; - if (selected_item_pair == item_pair) - { - it = mSelectedItemPairs.erase(it); - selection_changed = true; - break; - } - } - - mItemsPanel->removeChild(item_pair->first); - item_pair->first->die(); - delete item_pair; - - if (rearrange) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - } - - if (selection_changed && mCommitOnSelectionChange) - { - onCommit(); - } - - return true; + llassert(item_pair); + + bool deleted = false; + bool selection_changed = false; + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* _item_pair = *it; + if (_item_pair == item_pair) + { + mItemPairs.erase(it); + deleted = true; + break; + } + } + + if (!deleted) return false; + + for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* selected_item_pair = *it; + if (selected_item_pair == item_pair) + { + it = mSelectedItemPairs.erase(it); + selection_changed = true; + break; + } + } + + mItemsPanel->removeChild(item_pair->first); + item_pair->first->die(); + delete item_pair; + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + + if (selection_changed && mCommitOnSelectionChange) + { + onCommit(); + } + + return true; } void LLFlatListView::notifyParentItemsRectChanged() { - S32 comment_height = 0; + S32 comment_height = 0; - // take into account comment text height if exists - if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible()) - { - // top text padding inside the textbox is included into the height - comment_height = mNoItemsCommentTextbox->getTextPixelHeight(); + // take into account comment text height if exists + if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible()) + { + // top text padding inside the textbox is included into the height + comment_height = mNoItemsCommentTextbox->getTextPixelHeight(); - // take into account a distance from parent's top border to textbox's top - comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop; - } + // take into account a distance from parent's top border to textbox's top + comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop; + } - LLRect req_rect = getItemsRect(); + LLRect req_rect = getItemsRect(); - // get maximum of items total height and comment text height - req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height)); + // get maximum of items total height and comment text height + req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height)); - // take into account border size. - req_rect.stretch(getBorderWidth()); + // take into account border size. + req_rect.stretch(getBorderWidth()); - if (req_rect == mPrevNotifyParentRect) - return; + if (req_rect == mPrevNotifyParentRect) + return; - mPrevNotifyParentRect = req_rect; + mPrevNotifyParentRect = req_rect; - LLSD params; - params["action"] = "size_changes"; - params["width"] = req_rect.getWidth(); - params["height"] = req_rect.getHeight(); + LLSD params; + params["action"] = "size_changes"; + params["width"] = req_rect.getWidth(); + params["height"] = req_rect.getHeight(); - if (getParent()) // dummy widgets don't have a parent - getParent()->notifyParent(params); + if (getParent()) // dummy widgets don't have a parent + getParent()->notifyParent(params); } void LLFlatListView::setNoItemsCommentVisible(bool visible) const { - if (mNoItemsCommentTextbox) - { - mSelectedItemsBorder->setVisible(!visible); - mNoItemsCommentTextbox->setVisible(visible); - } + if (mNoItemsCommentTextbox) + { + mSelectedItemsBorder->setVisible(!visible); + mNoItemsCommentTextbox->setVisible(visible); + } } void LLFlatListView::getItems(std::vector& items) const { - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - items.clear(); - for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - items.push_back((*it)->first); - } + items.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + items.push_back((*it)->first); + } } void LLFlatListView::getValues(std::vector& values) const { - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - values.clear(); - for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - values.push_back((*it)->second); - } + values.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + values.push_back((*it)->second); + } } // virtual void LLFlatListView::onFocusReceived() { - if (size()) - { - mSelectedItemsBorder->setVisible(TRUE); - } - gEditMenuHandler = this; + if (size()) + { + mSelectedItemsBorder->setVisible(TRUE); + } + gEditMenuHandler = this; } // virtual void LLFlatListView::onFocusLost() { - mSelectedItemsBorder->setVisible(FALSE); - // Route menu back to the default - if (gEditMenuHandler == this) - { - gEditMenuHandler = NULL; - } + mSelectedItemsBorder->setVisible(FALSE); + // Route menu back to the default + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } } -//virtual +//virtual S32 LLFlatListView::notify(const LLSD& info) { - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - return 1; - } - else if (str_action == "select_last") - { - setFocus(true); - selectLastItem(); - return 1; - } - } - else if (info.has("rearrange")) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - return 1; - } - - return 0; + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + return 1; + } + else if (str_action == "select_last") + { + setFocus(true); + selectLastItem(); + return 1; + } + } + else if (info.has("rearrange")) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + return 1; + } + + return 0; } void LLFlatListView::detachItems(std::vector& detached_items) { - LLSD action; - action.with("detach", LLSD()); - // Clear detached_items list - detached_items.clear(); - // Go through items and detach valid items, remove them from items panel - // and add to detached_items. - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - LLPanel* pItem = (*iter)->first; - if (1 == pItem->notify(action)) - { - selectItemPair((*iter), false); - mItemsPanel->removeChild(pItem); - detached_items.push_back(pItem); - } - iter++; - } - if (!detached_items.empty()) - { - // Some items were detached, clean ourself from unusable memory - if (detached_items.size() == mItemPairs.size()) - { - // This way will be faster if all items were disconnected - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - (*iter)->first = NULL; - delete *iter; - iter++; - } - mItemPairs.clear(); - // Also set items panel height to zero. - // Reshape it to allow reshaping of non-item children. - LLRect rc = mItemsPanel->getRect(); - rc.mBottom = rc.mTop; - mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); - mItemsPanel->setRect(rc); - setNoItemsCommentVisible(true); - } - else - { - std::vector::const_iterator - detached_iter = detached_items.begin(), - detached_iter_end = detached_items.end(); - while (detached_iter < detached_iter_end) - { - LLPanel* pDetachedItem = *detached_iter; - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - item_pair_t* item_pair = *iter; - if (item_pair->first == pDetachedItem) - { - mItemPairs.erase(iter); - item_pair->first = NULL; - delete item_pair; - break; - } - iter++; - } - detached_iter++; - } - rearrangeItems(); - } - notifyParentItemsRectChanged(); - } + LLSD action; + action.with("detach", LLSD()); + // Clear detached_items list + detached_items.clear(); + // Go through items and detach valid items, remove them from items panel + // and add to detached_items. + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + LLPanel* pItem = (*iter)->first; + if (1 == pItem->notify(action)) + { + selectItemPair((*iter), false); + mItemsPanel->removeChild(pItem); + detached_items.push_back(pItem); + } + iter++; + } + if (!detached_items.empty()) + { + // Some items were detached, clean ourself from unusable memory + if (detached_items.size() == mItemPairs.size()) + { + // This way will be faster if all items were disconnected + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + (*iter)->first = NULL; + delete *iter; + iter++; + } + mItemPairs.clear(); + // Also set items panel height to zero. + // Reshape it to allow reshaping of non-item children. + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + setNoItemsCommentVisible(true); + } + else + { + std::vector::const_iterator + detached_iter = detached_items.begin(), + detached_iter_end = detached_items.end(); + while (detached_iter < detached_iter_end) + { + LLPanel* pDetachedItem = *detached_iter; + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + item_pair_t* item_pair = *iter; + if (item_pair->first == pDetachedItem) + { + mItemPairs.erase(iter); + item_pair->first = NULL; + delete item_pair; + break; + } + iter++; + } + detached_iter++; + } + rearrangeItems(); + } + notifyParentItemsRectChanged(); + } } @@ -1324,7 +1324,7 @@ LLFlatListViewEx::Params::Params() } LLFlatListViewEx::LLFlatListViewEx(const Params& p) -: LLFlatListView(p) +: LLFlatListView(p) , mNoFilteredItemsMsg(p.no_filtered_items_msg) , mNoItemsMsg(p.no_items_msg) , mForceShowingUnmatchedItems(false) @@ -1334,41 +1334,41 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p) void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) { - bool items_filtered = !filter_string.empty(); - if (items_filtered) - { - // items were filtered - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(filter_string); - std::string text = mNoFilteredItemsMsg; - LLStringUtil::format(text, args); - setNoItemsCommentText(text); - } - else - { - // list does not contain any items at all - setNoItemsCommentText(mNoItemsMsg); - } + bool items_filtered = !filter_string.empty(); + if (items_filtered) + { + // items were filtered + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = mNoFilteredItemsMsg; + LLStringUtil::format(text, args); + setNoItemsCommentText(text); + } + else + { + // list does not contain any items at all + setNoItemsCommentText(mNoItemsMsg); + } } bool LLFlatListViewEx::getForceShowingUnmatchedItems() { - return mForceShowingUnmatchedItems; + return mForceShowingUnmatchedItems; } void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) { - mForceShowingUnmatchedItems = show; + mForceShowingUnmatchedItems = show; } void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) { - if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) - { - mFilterSubString = filter_str; - updateNoItemsMessage(mFilterSubString); - filterItems(false, notify_parent); - } + if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) + { + mFilterSubString = filter_str; + updateNoItemsMessage(mFilterSubString); + filterItems(false, notify_parent); + } } bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) @@ -1376,49 +1376,49 @@ bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) if (!item) return false; - BOOL visible = TRUE; - - // 0 signifies that filter is matched, - // i.e. we don't hide items that don't support 'match_filter' action, separators etc. - if (0 == item->notify(action)) - { - mHasMatchedItems = true; - } - else - { - // TODO: implement (re)storing of current selection. - if (!mForceShowingUnmatchedItems) - { - selectItem(item, false); - visible = FALSE; - } - } - - if (item->getVisible() != visible) - { - item->setVisible(visible); - return true; - } - - return false; + BOOL visible = TRUE; + + // 0 signifies that filter is matched, + // i.e. we don't hide items that don't support 'match_filter' action, separators etc. + if (0 == item->notify(action)) + { + mHasMatchedItems = true; + } + else + { + // TODO: implement (re)storing of current selection. + if (!mForceShowingUnmatchedItems) + { + selectItem(item, false); + visible = FALSE; + } + } + + if (item->getVisible() != visible) + { + item->setVisible(visible); + return true; + } + + return false; } void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { - std::string cur_filter = mFilterSubString; - LLStringUtil::toUpper(cur_filter); + std::string cur_filter = mFilterSubString; + LLStringUtil::toUpper(cur_filter); - LLSD action; - action.with("match_filter", cur_filter); + LLSD action; + action.with("match_filter", cur_filter); - mHasMatchedItems = false; - bool visibility_changed = false; - pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); - while (iter != iter_end) - { - LLPanel* pItem = (*(iter++))->first; - visibility_changed |= updateItemVisibility(pItem, action); - } + mHasMatchedItems = false; + bool visibility_changed = false; + pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); + while (iter != iter_end) + { + LLPanel* pItem = (*(iter++))->first; + visibility_changed |= updateItemVisibility(pItem, action); + } if (re_sort) { @@ -1433,7 +1433,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) bool LLFlatListViewEx::hasMatchedItems() { - return mHasMatchedItems; + return mHasMatchedItems; } //EOF diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index adb0e3e553..ba269a7d78 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -1,25 +1,25 @@ -/** +/** * @file llflatlistview.h * @brief LLFlatListView base class and extension to support messages for several cases of an empty list. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,14 +37,14 @@ * LLSD can be associated with each added item, it can keep data from an item in digested form. * Associated LLSD's can be of any type (singular, a map etc.). * Items (LLPanel's subclasses) can be of different height. - * The list is LLPanel created in itself and grows in height while new items are added. - * + * The list is LLPanel created in itself and grows in height while new items are added. + * * The control can manage selection of its items when the flag "allow_select" is set. Also ability to select - * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag + * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag * is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items) * since any item of the list was selected. * - * Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to + * Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to * manage the list of pick items. * * ASSUMPTIONS AND STUFF @@ -54,392 +54,392 @@ */ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler { - LOG_CLASS(LLFlatListView); + LOG_CLASS(LLFlatListView); public: - /** - * Abstract comparator for comparing flat list items in a form of LLPanel - */ - class ItemComparator - { - public: - ItemComparator() {}; - virtual ~ItemComparator() {}; - - /** Returns true if item1 < item2, false otherwise */ - virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0; - }; - - /** - * Represents reverse comparator which acts as a decorator for a comparator that need to be reversed - */ - class ItemReverseComparator : public ItemComparator - { - public: - ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {}; - virtual ~ItemReverseComparator() {}; - - virtual bool compare(const LLPanel* item1, const LLPanel* item2) const - { - return mComparator.compare(item2, item1); - } - - private: - const ItemComparator& mComparator; - }; - - - struct Params : public LLInitParam::Block - { - /** turning on/off selection support */ - Optional allow_select; - - /** turning on/off multiple selection (works while clicking and holding CTRL)*/ - Optional multi_select; - - /** don't allow to deselect all selected items (for mouse events on items only) */ - Optional keep_one_selected; - - /** try to keep selection visible after reshape */ - Optional keep_selection_visible_on_reshape; - - /** padding between items */ - Optional item_pad; - - /** textbox with info message when list is empty*/ - Optional no_items_text; - - Params(); - }; - - // disable traversal when finding widget to hand focus off to - /*virtual*/ BOOL canFocusChildren() const { return FALSE; } - - /** - * Connects callback to signal called when Return key is pressed. - */ - boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } - - /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */ - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - - /** Returns full rect of child panel */ - const LLRect& getItemsRect() const; - - LLRect getRequiredRect() { return getItemsRect(); } - - /** Returns distance between items */ - const S32 getItemsPad() { return mItemPad; } - - /** - * Adds and item and LLSD value associated with it to the list at specified position - * @return true if the item was added, false otherwise - */ - virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true); - - /** - * Insert item_to_add along with associated value to the list right after the after_item. - * @return true if the item was successfully added, false otherwise - */ - virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null); - - /** - * Remove specified item - * @return true if the item was removed, false otherwise - */ - virtual bool removeItem(LLPanel* item, bool rearrange = true); - - /** - * Remove an item specified by value - * @return true if the item was removed, false otherwise - */ - virtual bool removeItemByValue(const LLSD& value, bool rearrange = true); - - /** - * Remove an item specified by uuid - * @return true if the item was removed, false otherwise - */ - virtual bool removeItemByUUID(const LLUUID& uuid, bool rearrange = true); - - /** - * Get an item by value - * @return the item as LLPanel if associated with value, NULL otherwise - */ - virtual LLPanel* getItemByValue(const LLSD& value) const; - - template - T* getTypedItemByValue(const LLSD& value) const - { - return dynamic_cast(getItemByValue(value)); - } - - /** - * Select or deselect specified item based on select - * @return true if succeed, false otherwise - */ - virtual bool selectItem(LLPanel* item, bool select = true); - - /** - * Select or deselect an item by associated value based on select - * @return true if succeed, false otherwise - */ - virtual bool selectItemByValue(const LLSD& value, bool select = true); - - /** - * Select or deselect an item by associated uuid based on select - * @return true if succeed, false otherwise - */ - virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true); - - /** - * Get all panels stored in the list. - */ - virtual void getItems(std::vector& items) const; - - /** - * Get all items values. - */ - virtual void getValues(std::vector& values) const; - - /** - * Get LLSD associated with the first selected item - */ - virtual LLSD getSelectedValue() const; - - /** - * Get LLSD's associated with selected items. - * @param selected_values std::vector being populated with LLSD associated with selected items - */ - virtual void getSelectedValues(std::vector& selected_values) const; - - - /** - * Get LLUUID associated with selected item - * @return LLUUID if such was associated with selected item - */ - virtual LLUUID getSelectedUUID() const; - - /** - * Get LLUUIDs associated with selected items - * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items - */ - virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const; - - /** Get the top selected item */ - virtual LLPanel* getSelectedItem() const; - - /** - * Get selected items - * @param selected_items An std::vector being populated with pointers to selected items - */ - virtual void getSelectedItems(std::vector& selected_items) const; - - - /** - * Resets selection of items. - * - * It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true" - * argument for current Flat List. - * @param no_commit_on_deselection - if true onCommit callback will not be called - */ - virtual void resetSelection(bool no_commit_on_deselection = false); - - /** - * Sets comment text which will be shown in the list is it is empty. - * - * Textbox to hold passed text is created while this method is called at the first time. - * - * @param comment_text - string to be shown as a comment. - */ - void setNoItemsCommentText( const std::string& comment_text); - - /** Turn on/off multiple selection support */ - void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; } - - /** Turn on/off selection support */ - void setAllowSelection(bool can_select) { mAllowSelection = can_select; } - - /** Sets flag whether onCommit should be fired if selection was changed */ - // FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly. - void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; } - - /** Get number of selected items in the list */ - U32 numSelected() const {return mSelectedItemPairs.size(); } - - /** Get number of (visible) items in the list */ - U32 size(const bool only_visible_items = true) const; - - /** Removes all items from the list */ - virtual void clear(); - - /** - * Removes all items that can be detached from the list but doesn't destroy - * them, caller responsible to manage items after they are detached. - * Detachable item should accept "detach" action via notify() method, - * where it disconnect all callbacks, does other valuable routines and - * return 1. - */ - void detachItems(std::vector& detached_items); - - /** - * Set comparator to use for future sorts. - * - * This class does NOT manage lifetime of the comparator - * but assumes that the comparator is always alive. - */ - void setComparator(const ItemComparator* comp) { mItemComparator = comp; } - void sort(); - - bool updateValue(const LLSD& old_value, const LLSD& new_value); - - void scrollToShowFirstSelectedItem(); - - void selectFirstItem (); - void selectLastItem (); - - virtual S32 notify(const LLSD& info) ; - - virtual ~LLFlatListView(); + /** + * Abstract comparator for comparing flat list items in a form of LLPanel + */ + class ItemComparator + { + public: + ItemComparator() {}; + virtual ~ItemComparator() {}; + + /** Returns true if item1 < item2, false otherwise */ + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0; + }; + + /** + * Represents reverse comparator which acts as a decorator for a comparator that need to be reversed + */ + class ItemReverseComparator : public ItemComparator + { + public: + ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {}; + virtual ~ItemReverseComparator() {}; + + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const + { + return mComparator.compare(item2, item1); + } + + private: + const ItemComparator& mComparator; + }; + + + struct Params : public LLInitParam::Block + { + /** turning on/off selection support */ + Optional allow_select; + + /** turning on/off multiple selection (works while clicking and holding CTRL)*/ + Optional multi_select; + + /** don't allow to deselect all selected items (for mouse events on items only) */ + Optional keep_one_selected; + + /** try to keep selection visible after reshape */ + Optional keep_selection_visible_on_reshape; + + /** padding between items */ + Optional item_pad; + + /** textbox with info message when list is empty*/ + Optional no_items_text; + + Params(); + }; + + // disable traversal when finding widget to hand focus off to + /*virtual*/ BOOL canFocusChildren() const { return FALSE; } + + /** + * Connects callback to signal called when Return key is pressed. + */ + boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } + + /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */ + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + /** Returns full rect of child panel */ + const LLRect& getItemsRect() const; + + LLRect getRequiredRect() { return getItemsRect(); } + + /** Returns distance between items */ + const S32 getItemsPad() { return mItemPad; } + + /** + * Adds and item and LLSD value associated with it to the list at specified position + * @return true if the item was added, false otherwise + */ + virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true); + + /** + * Insert item_to_add along with associated value to the list right after the after_item. + * @return true if the item was successfully added, false otherwise + */ + virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null); + + /** + * Remove specified item + * @return true if the item was removed, false otherwise + */ + virtual bool removeItem(LLPanel* item, bool rearrange = true); + + /** + * Remove an item specified by value + * @return true if the item was removed, false otherwise + */ + virtual bool removeItemByValue(const LLSD& value, bool rearrange = true); + + /** + * Remove an item specified by uuid + * @return true if the item was removed, false otherwise + */ + virtual bool removeItemByUUID(const LLUUID& uuid, bool rearrange = true); + + /** + * Get an item by value + * @return the item as LLPanel if associated with value, NULL otherwise + */ + virtual LLPanel* getItemByValue(const LLSD& value) const; + + template + T* getTypedItemByValue(const LLSD& value) const + { + return dynamic_cast(getItemByValue(value)); + } + + /** + * Select or deselect specified item based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItem(LLPanel* item, bool select = true); + + /** + * Select or deselect an item by associated value based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItemByValue(const LLSD& value, bool select = true); + + /** + * Select or deselect an item by associated uuid based on select + * @return true if succeed, false otherwise + */ + virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true); + + /** + * Get all panels stored in the list. + */ + virtual void getItems(std::vector& items) const; + + /** + * Get all items values. + */ + virtual void getValues(std::vector& values) const; + + /** + * Get LLSD associated with the first selected item + */ + virtual LLSD getSelectedValue() const; + + /** + * Get LLSD's associated with selected items. + * @param selected_values std::vector being populated with LLSD associated with selected items + */ + virtual void getSelectedValues(std::vector& selected_values) const; + + + /** + * Get LLUUID associated with selected item + * @return LLUUID if such was associated with selected item + */ + virtual LLUUID getSelectedUUID() const; + + /** + * Get LLUUIDs associated with selected items + * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items + */ + virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const; + + /** Get the top selected item */ + virtual LLPanel* getSelectedItem() const; + + /** + * Get selected items + * @param selected_items An std::vector being populated with pointers to selected items + */ + virtual void getSelectedItems(std::vector& selected_items) const; + + + /** + * Resets selection of items. + * + * It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true" + * argument for current Flat List. + * @param no_commit_on_deselection - if true onCommit callback will not be called + */ + virtual void resetSelection(bool no_commit_on_deselection = false); + + /** + * Sets comment text which will be shown in the list is it is empty. + * + * Textbox to hold passed text is created while this method is called at the first time. + * + * @param comment_text - string to be shown as a comment. + */ + void setNoItemsCommentText( const std::string& comment_text); + + /** Turn on/off multiple selection support */ + void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; } + + /** Turn on/off selection support */ + void setAllowSelection(bool can_select) { mAllowSelection = can_select; } + + /** Sets flag whether onCommit should be fired if selection was changed */ + // FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly. + void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; } + + /** Get number of selected items in the list */ + U32 numSelected() const {return mSelectedItemPairs.size(); } + + /** Get number of (visible) items in the list */ + U32 size(const bool only_visible_items = true) const; + + /** Removes all items from the list */ + virtual void clear(); + + /** + * Removes all items that can be detached from the list but doesn't destroy + * them, caller responsible to manage items after they are detached. + * Detachable item should accept "detach" action via notify() method, + * where it disconnect all callbacks, does other valuable routines and + * return 1. + */ + void detachItems(std::vector& detached_items); + + /** + * Set comparator to use for future sorts. + * + * This class does NOT manage lifetime of the comparator + * but assumes that the comparator is always alive. + */ + void setComparator(const ItemComparator* comp) { mItemComparator = comp; } + void sort(); + + bool updateValue(const LLSD& old_value, const LLSD& new_value); + + void scrollToShowFirstSelectedItem(); + + void selectFirstItem (); + void selectLastItem (); + + virtual S32 notify(const LLSD& info) ; + + virtual ~LLFlatListView(); protected: - /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ - typedef std::pair item_pair_t; + /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ + typedef std::pair item_pair_t; - typedef std::list pairs_list_t; - typedef pairs_list_t::iterator pairs_iterator_t; - typedef pairs_list_t::const_iterator pairs_const_iterator_t; + typedef std::list pairs_list_t; + typedef pairs_list_t::iterator pairs_iterator_t; + typedef pairs_list_t::const_iterator pairs_const_iterator_t; - /** An adapter for a ItemComparator */ - struct ComparatorAdaptor - { - ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {}; + /** An adapter for a ItemComparator */ + struct ComparatorAdaptor + { + ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {}; - bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2) - { - return mComparator.compare(item_pair1->first, item_pair2->first); - } + bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2) + { + return mComparator.compare(item_pair1->first, item_pair2->first); + } - const ItemComparator& mComparator; - }; + const ItemComparator& mComparator; + }; - friend class LLUICtrlFactory; - LLFlatListView(const LLFlatListView::Params& p); + friend class LLUICtrlFactory; + LLFlatListView(const LLFlatListView::Params& p); - /** Manage selection on mouse events */ - void onItemMouseClick(item_pair_t* item_pair, MASK mask); + /** Manage selection on mouse events */ + void onItemMouseClick(item_pair_t* item_pair, MASK mask); - void onItemRightMouseClick(item_pair_t* item_pair, MASK mask); + void onItemRightMouseClick(item_pair_t* item_pair, MASK mask); - /** - * Updates position of items. - * It does not take into account invisible items. - */ - virtual void rearrangeItems(); + /** + * Updates position of items. + * It does not take into account invisible items. + */ + virtual void rearrangeItems(); - virtual item_pair_t* getItemPair(LLPanel* item) const; + virtual item_pair_t* getItemPair(LLPanel* item) const; - virtual item_pair_t* getItemPair(const LLSD& value) const; + virtual item_pair_t* getItemPair(const LLSD& value) const; - virtual bool selectItemPair(item_pair_t* item_pair, bool select); + virtual bool selectItemPair(item_pair_t* item_pair, bool select); - virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); + virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); - virtual BOOL canSelectAll() const; - virtual void selectAll(); + virtual BOOL canSelectAll() const; + virtual void selectAll(); - virtual bool isSelected(item_pair_t* item_pair) const; + virtual bool isSelected(item_pair_t* item_pair) const; - virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange); + virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange); - bool addItemPairs(pairs_list_t panel_list, bool rearrange = true); + bool addItemPairs(pairs_list_t panel_list, bool rearrange = true); - /** - * Notify parent about changed size of internal controls with "size_changes" action - * - * Size includes Items Rect width and either Items Rect height or comment text height. - * Comment text height is included if comment text is set and visible. - * List border size is also included into notified size. - */ - void notifyParentItemsRectChanged(); + /** + * Notify parent about changed size of internal controls with "size_changes" action + * + * Size includes Items Rect width and either Items Rect height or comment text height. + * Comment text height is included if comment text is set and visible. + * List border size is also included into notified size. + */ + void notifyParentItemsRectChanged(); - virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL postBuild(); + virtual BOOL postBuild(); - virtual void onFocusReceived(); + virtual void onFocusReceived(); - virtual void onFocusLost(); + virtual void onFocusLost(); - virtual void draw(); + virtual void draw(); - LLRect getLastSelectedItemRect(); + LLRect getLastSelectedItemRect(); - void ensureSelectedVisible(); + void ensureSelectedVisible(); - const pairs_list_t& getItemPairs() { return mItemPairs; } + const pairs_list_t& getItemPairs() { return mItemPairs; } private: - void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;} + void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;} - void setNoItemsCommentVisible(bool visible) const; + void setNoItemsCommentVisible(bool visible) const; protected: - /** Comparator to use when sorting the list. */ - const ItemComparator* mItemComparator; + /** Comparator to use when sorting the list. */ + const ItemComparator* mItemComparator; private: - LLPanel* mItemsPanel; + LLPanel* mItemsPanel; - S32 mItemsNoScrollWidth; + S32 mItemsNoScrollWidth; - S32 mBorderThickness; + S32 mBorderThickness; - /** Items padding */ - S32 mItemPad; + /** Items padding */ + S32 mItemPad; - /** Selection support flag */ - bool mAllowSelection; + /** Selection support flag */ + bool mAllowSelection; - /** Multiselection support flag, ignored if selection is not supported */ - bool mMultipleSelection; + /** Multiselection support flag, ignored if selection is not supported */ + bool mMultipleSelection; - /** - * Flag specified whether onCommit be called if selection is changed in the list. - * - * Can be ignored in the resetSelection() method. - * @see resetSelection() - */ - bool mCommitOnSelectionChange; + /** + * Flag specified whether onCommit be called if selection is changed in the list. + * + * Can be ignored in the resetSelection() method. + * @see resetSelection() + */ + bool mCommitOnSelectionChange; - bool mKeepOneItemSelected; + bool mKeepOneItemSelected; - bool mIsConsecutiveSelection; + bool mIsConsecutiveSelection; - bool mKeepSelectionVisibleOnReshape; + bool mKeepSelectionVisibleOnReshape; - /** All pairs of the list */ - pairs_list_t mItemPairs; + /** All pairs of the list */ + pairs_list_t mItemPairs; - /** Selected pairs for faster access */ - pairs_list_t mSelectedItemPairs; + /** Selected pairs for faster access */ + pairs_list_t mSelectedItemPairs; - /** - * Rectangle contained previous size of items parent notified last time. - * Is used to reduce amount of parentNotify() calls if size was not changed. - */ - LLRect mPrevNotifyParentRect; + /** + * Rectangle contained previous size of items parent notified last time. + * Is used to reduce amount of parentNotify() calls if size was not changed. + */ + LLRect mPrevNotifyParentRect; - LLTextBox* mNoItemsCommentTextbox; + LLTextBox* mNoItemsCommentTextbox; - LLViewBorder* mSelectedItemsBorder; + LLViewBorder* mSelectedItemsBorder; - commit_signal_t mOnReturnSignal; + commit_signal_t mOnReturnSignal; }; /** @@ -457,79 +457,79 @@ private: class LLFlatListViewEx : public LLFlatListView { public: - LOG_CLASS(LLFlatListViewEx); - - struct Params : public LLInitParam::Block - { - /** - * Contains a message for empty list when it does not contain any items at all. - */ - Optional no_items_msg; - - /** - * Contains a message for empty list when its items are removed by filtering. - */ - Optional no_filtered_items_msg; - Params(); - }; - - // *WORKAROUND: two methods to overload appropriate Params due to localization issue: - // no_items_msg & no_filtered_items_msg attributes are not defined as translatable in VLT. See EXT-5931 - void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; } - void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; } - - bool getForceShowingUnmatchedItems(); - - void setForceShowingUnmatchedItems(bool show); - - /** - * Sets up new filter string and filters the list. - */ - void setFilterSubString(const std::string& filter_str, bool notify_parent); - std::string getFilterSubString() { return mFilterSubString; } - - /** - * Filters the list, rearranges and notifies parent about shape changes. - * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. - */ - void filterItems(bool re_sort, bool notify_parent); - - /** - * Returns true if last call of filterItems() found at least one matching item - */ - bool hasMatchedItems(); + LOG_CLASS(LLFlatListViewEx); + + struct Params : public LLInitParam::Block + { + /** + * Contains a message for empty list when it does not contain any items at all. + */ + Optional no_items_msg; + + /** + * Contains a message for empty list when its items are removed by filtering. + */ + Optional no_filtered_items_msg; + Params(); + }; + + // *WORKAROUND: two methods to overload appropriate Params due to localization issue: + // no_items_msg & no_filtered_items_msg attributes are not defined as translatable in VLT. See EXT-5931 + void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; } + void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; } + + bool getForceShowingUnmatchedItems(); + + void setForceShowingUnmatchedItems(bool show); + + /** + * Sets up new filter string and filters the list. + */ + void setFilterSubString(const std::string& filter_str, bool notify_parent); + std::string getFilterSubString() { return mFilterSubString; } + + /** + * Filters the list, rearranges and notifies parent about shape changes. + * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. + */ + void filterItems(bool re_sort, bool notify_parent); + + /** + * Returns true if last call of filterItems() found at least one matching item + */ + bool hasMatchedItems(); protected: - LLFlatListViewEx(const Params& p); - - /** - * Applies a message for empty list depend on passed argument. - * - * @param filter_string - if is not empty, message for filtered items will be set, otherwise for - * completely empty list. Value of filter string will be passed as search_term in SLURL. - */ - void updateNoItemsMessage(const std::string& filter_string); - - /** - * Applies visibility acording to action and LLFlatListView settings. - * - * @param item - item we are changing - * @param item - action - parameters to determin visibility from - */ - bool updateItemVisibility(LLPanel* item, const LLSD &action); + LLFlatListViewEx(const Params& p); + + /** + * Applies a message for empty list depend on passed argument. + * + * @param filter_string - if is not empty, message for filtered items will be set, otherwise for + * completely empty list. Value of filter string will be passed as search_term in SLURL. + */ + void updateNoItemsMessage(const std::string& filter_string); + + /** + * Applies visibility acording to action and LLFlatListView settings. + * + * @param item - item we are changing + * @param item - action - parameters to determin visibility from + */ + bool updateItemVisibility(LLPanel* item, const LLSD &action); private: - std::string mNoFilteredItemsMsg; - std::string mNoItemsMsg; - std::string mFilterSubString; - /** - * Show list items that don't match current filter - */ - bool mForceShowingUnmatchedItems; - /** - * True if last call of filterItems() found at least one matching item - */ - bool mHasMatchedItems; + std::string mNoFilteredItemsMsg; + std::string mNoItemsMsg; + std::string mFilterSubString; + /** + * Show list items that don't match current filter + */ + bool mForceShowingUnmatchedItems; + /** + * True if last call of filterItems() found at least one matching item + */ + bool mHasMatchedItems; }; #endif diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index c7b04c905c..96d9e31f4c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfloater.cpp * @brief LLFloater base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,7 +44,7 @@ #include "llresizebar.h" #include "llresizehandle.h" #include "llkeyboard.h" -#include "llmenugl.h" // MENU_BAR_HEIGHT +#include "llmenugl.h" // MENU_BAR_HEIGHT #include "llmodaldialog.h" #include "lltextbox.h" #include "llresmgr.h" @@ -70,23 +70,23 @@ const F32 LLFloater::CONTEXT_CONE_FADE_TIME = 0.08f; namespace LLInitParam { - void TypeValues::declareValues() - { - declare("relative", LLFloaterEnums::POSITIONING_RELATIVE); - declare("cascading", LLFloaterEnums::POSITIONING_CASCADING); - declare("centered", LLFloaterEnums::POSITIONING_CENTERED); - declare("specified", LLFloaterEnums::POSITIONING_SPECIFIED); - } + void TypeValues::declareValues() + { + declare("relative", LLFloaterEnums::POSITIONING_RELATIVE); + declare("cascading", LLFloaterEnums::POSITIONING_CASCADING); + declare("centered", LLFloaterEnums::POSITIONING_CENTERED); + declare("specified", LLFloaterEnums::POSITIONING_SPECIFIED); + } } -std::string LLFloater::sButtonNames[BUTTON_COUNT] = +std::string LLFloater::sButtonNames[BUTTON_COUNT] = { - "llfloater_close_btn", //BUTTON_CLOSE - "llfloater_restore_btn", //BUTTON_RESTORE - "llfloater_minimize_btn", //BUTTON_MINIMIZE - "llfloater_tear_off_btn", //BUTTON_TEAR_OFF - "llfloater_dock_btn", //BUTTON_DOCK - "llfloater_help_btn" //BUTTON_HELP + "llfloater_close_btn", //BUTTON_CLOSE + "llfloater_restore_btn", //BUTTON_RESTORE + "llfloater_minimize_btn", //BUTTON_MINIMIZE + "llfloater_tear_off_btn", //BUTTON_TEAR_OFF + "llfloater_dock_btn", //BUTTON_DOCK + "llfloater_help_btn" //BUTTON_HELP }; std::string LLFloater::sButtonToolTips[BUTTON_COUNT]; @@ -94,29 +94,29 @@ std::string LLFloater::sButtonToolTips[BUTTON_COUNT]; std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]= { #ifdef LL_DARWIN - "BUTTON_CLOSE_DARWIN", //"Close (Cmd-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_DARWIN", //"Close (Cmd-W)", //BUTTON_CLOSE #else - "BUTTON_CLOSE_WIN", //"Close (Ctrl-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_WIN", //"Close (Ctrl-W)", //BUTTON_CLOSE #endif - "BUTTON_RESTORE", //"Restore", //BUTTON_RESTORE - "BUTTON_MINIMIZE", //"Minimize", //BUTTON_MINIMIZE - "BUTTON_TEAR_OFF", //"Tear Off", //BUTTON_TEAR_OFF - "BUTTON_DOCK", - "BUTTON_HELP" + "BUTTON_RESTORE", //"Restore", //BUTTON_RESTORE + "BUTTON_MINIMIZE", //"Minimize", //BUTTON_MINIMIZE + "BUTTON_TEAR_OFF", //"Tear Off", //BUTTON_TEAR_OFF + "BUTTON_DOCK", + "BUTTON_HELP" }; LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = { - LLFloater::onClickClose, //BUTTON_CLOSE - LLFloater::onClickMinimize, //BUTTON_RESTORE - LLFloater::onClickMinimize, //BUTTON_MINIMIZE - LLFloater::onClickTearOff, //BUTTON_TEAR_OFF - LLFloater::onClickDock, //BUTTON_DOCK - LLFloater::onClickHelp //BUTTON_HELP + LLFloater::onClickClose, //BUTTON_CLOSE + LLFloater::onClickMinimize, //BUTTON_RESTORE + LLFloater::onClickMinimize, //BUTTON_MINIMIZE + LLFloater::onClickTearOff, //BUTTON_TEAR_OFF + LLFloater::onClickDock, //BUTTON_DOCK + LLFloater::onClickHelp //BUTTON_HELP }; LLMultiFloater* LLFloater::sHostp = NULL; -BOOL LLFloater::sQuitting = FALSE; // Flag to prevent storing visibility controls while quitting +BOOL LLFloater::sQuitting = FALSE; // Flag to prevent storing visibility controls while quitting LLFloaterView* gFloaterView = NULL; @@ -133,108 +133,108 @@ LLFloaterView* gFloaterView = NULL; //static bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b) { - if (a.type() != b.type()) - { - //LL_ERRS() << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << LL_ENDL; - return false; - } - else if (a.isUndefined()) - return false; - else if (a.isInteger()) - return a.asInteger() < b.asInteger(); - else if (a.isReal()) - return a.asReal() < b.asReal(); - else if (a.isString()) - return a.asString() < b.asString(); - else if (a.isUUID()) - return a.asUUID() < b.asUUID(); - else if (a.isDate()) - return a.asDate() < b.asDate(); - else if (a.isURI()) - return a.asString() < b.asString(); // compare URIs as strings - else if (a.isBoolean()) - return a.asBoolean() < b.asBoolean(); - else - return false; // no valid operation for Binary + if (a.type() != b.type()) + { + //LL_ERRS() << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << LL_ENDL; + return false; + } + else if (a.isUndefined()) + return false; + else if (a.isInteger()) + return a.asInteger() < b.asInteger(); + else if (a.isReal()) + return a.asReal() < b.asReal(); + else if (a.isString()) + return a.asString() < b.asString(); + else if (a.isUUID()) + return a.asUUID() < b.asUUID(); + else if (a.isDate()) + return a.asDate() < b.asDate(); + else if (a.isURI()) + return a.asString() < b.asString(); // compare URIs as strings + else if (a.isBoolean()) + return a.asBoolean() < b.asBoolean(); + else + return false; // no valid operation for Binary } |*==========================================================================*/ bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b) { - return llsd_equals(a, b); + return llsd_equals(a, b); } //************************************ LLFloater::Params::Params() -: title("title"), - short_title("short_title"), - single_instance("single_instance", false), - reuse_instance("reuse_instance", false), - can_resize("can_resize", false), - can_minimize("can_minimize", true), - can_close("can_close", true), - can_drag_on_left("can_drag_on_left", false), - can_tear_off("can_tear_off", true), - save_dock_state("save_dock_state", false), - save_rect("save_rect", false), - save_visibility("save_visibility", false), - can_dock("can_dock", false), - show_title("show_title", true), - auto_close("auto_close", false), - positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE), - header_height("header_height", 0), - legacy_header_height("legacy_header_height", 0), - close_image("close_image"), - restore_image("restore_image"), - minimize_image("minimize_image"), - tear_off_image("tear_off_image"), - dock_image("dock_image"), - help_image("help_image"), - close_pressed_image("close_pressed_image"), - restore_pressed_image("restore_pressed_image"), - minimize_pressed_image("minimize_pressed_image"), - tear_off_pressed_image("tear_off_pressed_image"), - dock_pressed_image("dock_pressed_image"), - help_pressed_image("help_pressed_image"), - open_callback("open_callback"), - close_callback("close_callback"), - follows("follows"), - rel_x("rel_x", 0), - rel_y("rel_y", 0) -{ - changeDefault(visible, false); -} - - -//static +: title("title"), + short_title("short_title"), + single_instance("single_instance", false), + reuse_instance("reuse_instance", false), + can_resize("can_resize", false), + can_minimize("can_minimize", true), + can_close("can_close", true), + can_drag_on_left("can_drag_on_left", false), + can_tear_off("can_tear_off", true), + save_dock_state("save_dock_state", false), + save_rect("save_rect", false), + save_visibility("save_visibility", false), + can_dock("can_dock", false), + show_title("show_title", true), + auto_close("auto_close", false), + positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE), + header_height("header_height", 0), + legacy_header_height("legacy_header_height", 0), + close_image("close_image"), + restore_image("restore_image"), + minimize_image("minimize_image"), + tear_off_image("tear_off_image"), + dock_image("dock_image"), + help_image("help_image"), + close_pressed_image("close_pressed_image"), + restore_pressed_image("restore_pressed_image"), + minimize_pressed_image("minimize_pressed_image"), + tear_off_pressed_image("tear_off_pressed_image"), + dock_pressed_image("dock_pressed_image"), + help_pressed_image("help_pressed_image"), + open_callback("open_callback"), + close_callback("close_callback"), + follows("follows"), + rel_x("rel_x", 0), + rel_y("rel_y", 0) +{ + changeDefault(visible, false); +} + + +//static const LLFloater::Params& LLFloater::getDefaultParams() { - return LLUICtrlFactory::getDefaultParams(); + return LLUICtrlFactory::getDefaultParams(); } //static void LLFloater::initClass() { - // translate tooltips for floater buttons - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - sButtonToolTips[i] = LLTrans::getString( sButtonToolTipsIndex[i] ); - } + // translate tooltips for floater buttons + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + sButtonToolTips[i] = LLTrans::getString( sButtonToolTipsIndex[i] ); + } LLControlVariable* ctrl = LLUI::getInstance()->mSettingGroups["config"]->getControl("ActiveFloaterTransparency").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLFloater::updateActiveFloaterTransparency)); - updateActiveFloaterTransparency(); - } + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloater::updateActiveFloaterTransparency)); + updateActiveFloaterTransparency(); + } ctrl = LLUI::getInstance()->mSettingGroups["config"]->getControl("InactiveFloaterTransparency").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLFloater::updateInactiveFloaterTransparency)); - updateInactiveFloaterTransparency(); - } + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloater::updateInactiveFloaterTransparency)); + updateInactiveFloaterTransparency(); + } } @@ -242,142 +242,142 @@ void LLFloater::initClass() static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater"); LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) -: LLPanel(), // intentionally do not pass params here, see initFromParams - mDragHandle(NULL), - mTitle(p.title), - mShortTitle(p.short_title), - mSingleInstance(p.single_instance), - mReuseInstance(p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance), // reuse single-instance floaters by default - mKey(key), - mCanTearOff(p.can_tear_off), - mCanMinimize(p.can_minimize), - mCanClose(p.can_close), - mDragOnLeft(p.can_drag_on_left), - mResizable(p.can_resize), - mAutoClose(p.auto_close), - mPositioning(p.positioning), - mMinWidth(p.min_width), - mMinHeight(p.min_height), - mHeaderHeight(p.header_height), - mLegacyHeaderHeight(p.legacy_header_height), - mDefaultRectForGroup(true), - mMinimized(FALSE), - mForeground(FALSE), - mFirstLook(TRUE), - mButtonScale(1.0f), - mAutoFocus(TRUE), // automatically take focus when opened - mCanDock(false), - mDocked(false), - mTornOff(false), - mHasBeenDraggedWhileMinimized(FALSE), - mPreviousMinimizedBottom(0), - mPreviousMinimizedLeft(0), - mDefaultRelativeX(p.rel_x), - mDefaultRelativeY(p.rel_y), - mMinimizeSignal(NULL) -// mNotificationContext(NULL) -{ - mPosition.setFloater(*this); -// mNotificationContext = new LLFloaterNotificationContext(getHandle()); - - // Clicks stop here. - setMouseOpaque(TRUE); - - // Floaters always draw their background, unlike every other panel. - setBackgroundVisible(TRUE); - - // Floaters start not minimized. When minimized, they save their - // prior rectangle to be used on restore. - mExpandedRect.set(0,0,0,0); - - memset(mButtonsEnabled, 0, BUTTON_COUNT * sizeof(bool)); - memset(mButtons, 0, BUTTON_COUNT * sizeof(LLButton*)); - - addDragHandle(); - addResizeCtrls(); - - initFromParams(p); - - initFloater(p); +: LLPanel(), // intentionally do not pass params here, see initFromParams + mDragHandle(NULL), + mTitle(p.title), + mShortTitle(p.short_title), + mSingleInstance(p.single_instance), + mReuseInstance(p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance), // reuse single-instance floaters by default + mKey(key), + mCanTearOff(p.can_tear_off), + mCanMinimize(p.can_minimize), + mCanClose(p.can_close), + mDragOnLeft(p.can_drag_on_left), + mResizable(p.can_resize), + mAutoClose(p.auto_close), + mPositioning(p.positioning), + mMinWidth(p.min_width), + mMinHeight(p.min_height), + mHeaderHeight(p.header_height), + mLegacyHeaderHeight(p.legacy_header_height), + mDefaultRectForGroup(true), + mMinimized(FALSE), + mForeground(FALSE), + mFirstLook(TRUE), + mButtonScale(1.0f), + mAutoFocus(TRUE), // automatically take focus when opened + mCanDock(false), + mDocked(false), + mTornOff(false), + mHasBeenDraggedWhileMinimized(FALSE), + mPreviousMinimizedBottom(0), + mPreviousMinimizedLeft(0), + mDefaultRelativeX(p.rel_x), + mDefaultRelativeY(p.rel_y), + mMinimizeSignal(NULL) +// mNotificationContext(NULL) +{ + mPosition.setFloater(*this); +// mNotificationContext = new LLFloaterNotificationContext(getHandle()); + + // Clicks stop here. + setMouseOpaque(TRUE); + + // Floaters always draw their background, unlike every other panel. + setBackgroundVisible(TRUE); + + // Floaters start not minimized. When minimized, they save their + // prior rectangle to be used on restore. + mExpandedRect.set(0,0,0,0); + + memset(mButtonsEnabled, 0, BUTTON_COUNT * sizeof(bool)); + memset(mButtons, 0, BUTTON_COUNT * sizeof(LLButton*)); + + addDragHandle(); + addResizeCtrls(); + + initFromParams(p); + + initFloater(p); } // Note: Floaters constructed from XML call init() twice! void LLFloater::initFloater(const Params& p) { - // Close button. - if (mCanClose) - { - mButtonsEnabled[BUTTON_CLOSE] = TRUE; - } + // Close button. + if (mCanClose) + { + mButtonsEnabled[BUTTON_CLOSE] = TRUE; + } + + // Help button: '?' + //SL-14050 Disable all Help question marks + mButtonsEnabled[BUTTON_HELP] = FALSE; - // Help button: '?' - //SL-14050 Disable all Help question marks - mButtonsEnabled[BUTTON_HELP] = FALSE; - - // Minimize button only for top draggers - if ( !mDragOnLeft && mCanMinimize ) - { - mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; - } + // Minimize button only for top draggers + if ( !mDragOnLeft && mCanMinimize ) + { + mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; + } - if(mCanDock) - { - mButtonsEnabled[BUTTON_DOCK] = TRUE; - } + if(mCanDock) + { + mButtonsEnabled[BUTTON_DOCK] = TRUE; + } - buildButtons(p); + buildButtons(p); - // Floaters are created in the invisible state - setVisible(FALSE); + // Floaters are created in the invisible state + setVisible(FALSE); - if (!getParent()) - { - gFloaterView->addChild(this); - } + if (!getParent()) + { + gFloaterView->addChild(this); + } } void LLFloater::addDragHandle() { - if (!mDragHandle) - { - if (mDragOnLeft) - { - LLDragHandleLeft::Params p; - p.name("drag"); - p.follows.flags(FOLLOWS_ALL); - p.label(mTitle); - mDragHandle = LLUICtrlFactory::create(p); - } - else // drag on top - { - LLDragHandleTop::Params p; - p.name("Drag Handle"); - p.follows.flags(FOLLOWS_ALL); - p.label(mTitle); - mDragHandle = LLUICtrlFactory::create(p); - } - addChild(mDragHandle); - } - layoutDragHandle(); - applyTitle(); + if (!mDragHandle) + { + if (mDragOnLeft) + { + LLDragHandleLeft::Params p; + p.name("drag"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + else // drag on top + { + LLDragHandleTop::Params p; + p.name("Drag Handle"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + addChild(mDragHandle); + } + layoutDragHandle(); + applyTitle(); } void LLFloater::layoutDragHandle() { - static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); - S32 close_box_size = mCanClose ? floater_close_box_size : 0; - - LLRect rect; - if (mDragOnLeft) - { - rect.setLeftTopAndSize(0, 0, DRAG_HANDLE_WIDTH, getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); - } - else // drag on top - { - rect = getLocalRect(); - } - mDragHandle->setShape(rect); - updateTitleButtons(); + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + S32 close_box_size = mCanClose ? floater_close_box_size : 0; + + LLRect rect; + if (mDragOnLeft) + { + rect.setLeftTopAndSize(0, 0, DRAG_HANDLE_WIDTH, getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); + } + else // drag on top + { + rect = getLocalRect(); + } + mDragHandle->setShape(rect); + updateTitleButtons(); } // static @@ -395,120 +395,120 @@ void LLFloater::updateInactiveFloaterTransparency() } void LLFloater::addResizeCtrls() -{ - // Resize bars (sides) - LLResizeBar::Params p; - p.name("resizebar_left"); - p.resizing_view(this); - p.min_size(mMinWidth); - p.side(LLResizeBar::LEFT); - mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create(p); - addChild( mResizeBar[LLResizeBar::LEFT] ); - - p.name("resizebar_top"); - p.min_size(mMinHeight); - p.side(LLResizeBar::TOP); - - mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create(p); - addChild( mResizeBar[LLResizeBar::TOP] ); - - p.name("resizebar_right"); - p.min_size(mMinWidth); - p.side(LLResizeBar::RIGHT); - mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create(p); - addChild( mResizeBar[LLResizeBar::RIGHT] ); - - p.name("resizebar_bottom"); - p.min_size(mMinHeight); - p.side(LLResizeBar::BOTTOM); - mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create(p); - addChild( mResizeBar[LLResizeBar::BOTTOM] ); - - // Resize handles (corners) - LLResizeHandle::Params handle_p; - // handles must not be mouse-opaque, otherwise they block hover events - // to other buttons like the close box. JC - handle_p.mouse_opaque(false); - handle_p.min_width(mMinWidth); - handle_p.min_height(mMinHeight); - handle_p.corner(LLResizeHandle::RIGHT_BOTTOM); - mResizeHandle[0] = LLUICtrlFactory::create(handle_p); - addChild(mResizeHandle[0]); - - handle_p.corner(LLResizeHandle::RIGHT_TOP); - mResizeHandle[1] = LLUICtrlFactory::create(handle_p); - addChild(mResizeHandle[1]); - - handle_p.corner(LLResizeHandle::LEFT_BOTTOM); - mResizeHandle[2] = LLUICtrlFactory::create(handle_p); - addChild(mResizeHandle[2]); - - handle_p.corner(LLResizeHandle::LEFT_TOP); - mResizeHandle[3] = LLUICtrlFactory::create(handle_p); - addChild(mResizeHandle[3]); - - layoutResizeCtrls(); +{ + // Resize bars (sides) + LLResizeBar::Params p; + p.name("resizebar_left"); + p.resizing_view(this); + p.min_size(mMinWidth); + p.side(LLResizeBar::LEFT); + mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::LEFT] ); + + p.name("resizebar_top"); + p.min_size(mMinHeight); + p.side(LLResizeBar::TOP); + + mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::TOP] ); + + p.name("resizebar_right"); + p.min_size(mMinWidth); + p.side(LLResizeBar::RIGHT); + mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::RIGHT] ); + + p.name("resizebar_bottom"); + p.min_size(mMinHeight); + p.side(LLResizeBar::BOTTOM); + mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::BOTTOM] ); + + // Resize handles (corners) + LLResizeHandle::Params handle_p; + // handles must not be mouse-opaque, otherwise they block hover events + // to other buttons like the close box. JC + handle_p.mouse_opaque(false); + handle_p.min_width(mMinWidth); + handle_p.min_height(mMinHeight); + handle_p.corner(LLResizeHandle::RIGHT_BOTTOM); + mResizeHandle[0] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[0]); + + handle_p.corner(LLResizeHandle::RIGHT_TOP); + mResizeHandle[1] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[1]); + + handle_p.corner(LLResizeHandle::LEFT_BOTTOM); + mResizeHandle[2] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[2]); + + handle_p.corner(LLResizeHandle::LEFT_TOP); + mResizeHandle[3] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[3]); + + layoutResizeCtrls(); } void LLFloater::layoutResizeCtrls() { - LLRect rect; + LLRect rect; - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); - mResizeBar[LLResizeBar::LEFT]->setRect(rect); + // Resize bars (sides) + const S32 RESIZE_BAR_THICKNESS = 3; + rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); + mResizeBar[LLResizeBar::LEFT]->setRect(rect); - rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS); - mResizeBar[LLResizeBar::TOP]->setRect(rect); + rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS); + mResizeBar[LLResizeBar::TOP]->setRect(rect); - rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0); - mResizeBar[LLResizeBar::RIGHT]->setRect(rect); + rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0); + mResizeBar[LLResizeBar::RIGHT]->setRect(rect); - rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0); - mResizeBar[LLResizeBar::BOTTOM]->setRect(rect); + rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0); + mResizeBar[LLResizeBar::BOTTOM]->setRect(rect); - // Resize handles (corners) - rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0); - mResizeHandle[0]->setRect(rect); + // Resize handles (corners) + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0); + mResizeHandle[0]->setRect(rect); - rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT); - mResizeHandle[1]->setRect(rect); - - rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); - mResizeHandle[2]->setRect(rect); + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT); + mResizeHandle[1]->setRect(rect); - rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ); - mResizeHandle[3]->setRect(rect); + rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); + mResizeHandle[2]->setRect(rect); + + rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ); + mResizeHandle[3]->setRect(rect); } void LLFloater::enableResizeCtrls(bool enable, bool width, bool height) { - mResizeBar[LLResizeBar::LEFT]->setVisible(enable && width); - mResizeBar[LLResizeBar::LEFT]->setEnabled(enable && width); + mResizeBar[LLResizeBar::LEFT]->setVisible(enable && width); + mResizeBar[LLResizeBar::LEFT]->setEnabled(enable && width); + + mResizeBar[LLResizeBar::TOP]->setVisible(enable && height); + mResizeBar[LLResizeBar::TOP]->setEnabled(enable && height); - mResizeBar[LLResizeBar::TOP]->setVisible(enable && height); - mResizeBar[LLResizeBar::TOP]->setEnabled(enable && height); - - mResizeBar[LLResizeBar::RIGHT]->setVisible(enable && width); - mResizeBar[LLResizeBar::RIGHT]->setEnabled(enable && width); - - mResizeBar[LLResizeBar::BOTTOM]->setVisible(enable && height); - mResizeBar[LLResizeBar::BOTTOM]->setEnabled(enable && height); + mResizeBar[LLResizeBar::RIGHT]->setVisible(enable && width); + mResizeBar[LLResizeBar::RIGHT]->setEnabled(enable && width); - for (S32 i = 0; i < 4; ++i) - { - mResizeHandle[i]->setVisible(enable && width && height); - mResizeHandle[i]->setEnabled(enable && width && height); - } + mResizeBar[LLResizeBar::BOTTOM]->setVisible(enable && height); + mResizeBar[LLResizeBar::BOTTOM]->setEnabled(enable && height); + + for (S32 i = 0; i < 4; ++i) + { + mResizeHandle[i]->setVisible(enable && width && height); + mResizeHandle[i]->setEnabled(enable && width && height); + } } void LLFloater::destroy() { - // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before - // it was deleted via LLMortician::updateClass(). See EXT-8458. - LLFloaterReg::removeInstance(mInstanceName, mKey); - die(); + // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before + // it was deleted via LLMortician::updateClass(). See EXT-8458. + LLFloaterReg::removeInstance(mInstanceName, mKey); + die(); } // virtual @@ -520,250 +520,250 @@ LLFloater::~LLFloater() // in case of single instance we can remove new one by accident LLFloaterReg::removeInstance(mInstanceName, mKey); } - - if( gFocusMgr.childHasKeyboardFocus(this)) - { - // Just in case we might still have focus here, release it. - releaseFocus(); - } - // This is important so that floaters with persistent rects (i.e., those - // created with rect control rather than an LLRect) are restored in their - // correct, non-minimized positions. - setMinimized( FALSE ); + if( gFocusMgr.childHasKeyboardFocus(this)) + { + // Just in case we might still have focus here, release it. + releaseFocus(); + } + + // This is important so that floaters with persistent rects (i.e., those + // created with rect control rather than an LLRect) are restored in their + // correct, non-minimized positions. + setMinimized( FALSE ); - delete mDragHandle; - for (S32 i = 0; i < 4; i++) - { - delete mResizeBar[i]; - delete mResizeHandle[i]; - } + delete mDragHandle; + for (S32 i = 0; i < 4; i++) + { + delete mResizeBar[i]; + delete mResizeHandle[i]; + } - setVisible(false); // We're not visible if we're destroyed - storeVisibilityControl(); - storeDockStateControl(); - delete mMinimizeSignal; + setVisible(false); // We're not visible if we're destroyed + storeVisibilityControl(); + storeDockStateControl(); + delete mMinimizeSignal; } void LLFloater::storeRectControl() { - if (!mRectControl.empty()) - { - getControlGroup()->setRect( mRectControl, getRect() ); - } - if (!mPosXControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) - { - getControlGroup()->setF32( mPosXControl, mPosition.mX ); - } - if (!mPosYControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) - { - getControlGroup()->setF32( mPosYControl, mPosition.mY ); - } + if (!mRectControl.empty()) + { + getControlGroup()->setRect( mRectControl, getRect() ); + } + if (!mPosXControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosXControl, mPosition.mX ); + } + if (!mPosYControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosYControl, mPosition.mY ); + } } void LLFloater::storeVisibilityControl() { - if( !sQuitting && mVisibilityControl.size() > 1 ) - { - getControlGroup()->setBOOL( mVisibilityControl, getVisible() ); - } + if( !sQuitting && mVisibilityControl.size() > 1 ) + { + getControlGroup()->setBOOL( mVisibilityControl, getVisible() ); + } } void LLFloater::storeDockStateControl() { - if( !sQuitting && mDocStateControl.size() > 1 ) - { - getControlGroup()->setBOOL( mDocStateControl, isDocked() ); - } + if( !sQuitting && mDocStateControl.size() > 1 ) + { + getControlGroup()->setBOOL( mDocStateControl, isDocked() ); + } } // static std::string LLFloater::getControlName(const std::string& name, const LLSD& key) { - std::string ctrl_name = name; + std::string ctrl_name = name; - // Add the key to the control name if appropriate. - if (key.isString() && !key.asString().empty()) - { - ctrl_name += "_" + key.asString(); - } + // Add the key to the control name if appropriate. + if (key.isString() && !key.asString().empty()) + { + ctrl_name += "_" + key.asString(); + } - return ctrl_name; + return ctrl_name; } // static -LLControlGroup* LLFloater::getControlGroup() +LLControlGroup* LLFloater::getControlGroup() { - // Floater size, position, visibility, etc are saved in per-account settings. - return LLUI::getInstance()->mSettingGroups["account"]; + // Floater size, position, visibility, etc are saved in per-account settings. + return LLUI::getInstance()->mSettingGroups["account"]; } void LLFloater::setVisible( BOOL visible ) { - LLPanel::setVisible(visible); // calls onVisibilityChange() - if( visible && mFirstLook ) - { - mFirstLook = FALSE; - } + LLPanel::setVisible(visible); // calls onVisibilityChange() + if( visible && mFirstLook ) + { + mFirstLook = FALSE; + } - if( !visible ) - { - LLUI::getInstance()->removePopup(this); + if( !visible ) + { + LLUI::getInstance()->removePopup(this); - if( gFocusMgr.childHasMouseCapture( this ) ) - { - gFocusMgr.setMouseCapture(NULL); - } - } + if( gFocusMgr.childHasMouseCapture( this ) ) + { + gFocusMgr.setMouseCapture(NULL); + } + } - for(handle_set_iter_t dependent_it = mDependents.begin(); - dependent_it != mDependents.end(); ) - { - LLFloater* floaterp = dependent_it->get(); + for(handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); ) + { + LLFloater* floaterp = dependent_it->get(); - if (floaterp) - { - floaterp->setVisible(visible); - } - ++dependent_it; - } + if (floaterp) + { + floaterp->setVisible(visible); + } + ++dependent_it; + } - storeVisibilityControl(); + storeVisibilityControl(); } void LLFloater::setIsSingleInstance(BOOL is_single_instance) { - mSingleInstance = is_single_instance; - if (!mIsReuseInitialized) - { - mReuseInstance = is_single_instance; // reuse single-instance floaters by default - } + mSingleInstance = is_single_instance; + if (!mIsReuseInitialized) + { + mReuseInstance = is_single_instance; // reuse single-instance floaters by default + } } // virtual void LLFloater::onVisibilityChange ( BOOL new_visibility ) { - if (new_visibility) - { - if (getHost()) - getHost()->setFloaterFlashing(this, FALSE); - } - LLPanel::onVisibilityChange ( new_visibility ); + if (new_visibility) + { + if (getHost()) + getHost()->setFloaterFlashing(this, FALSE); + } + LLPanel::onVisibilityChange ( new_visibility ); } void LLFloater::openFloater(const LLSD& key) { LL_INFOS() << "Opening floater " << getName() << " full path: " << getPathname() << LL_ENDL; - LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), true,"floater"); // Last param is event subtype or empty string - - mKey = key; // in case we need to open ourselves again - - if (getSoundFlags() != SILENT - // don't play open sound for hosted (tabbed) windows - && !getHost() - && !getFloaterHost() - && (!getVisible() || isMinimized())) - { - make_ui_sound("UISndWindowOpen"); - } - - //RN: for now, we don't allow rehosting from one multifloater to another - // just need to fix the bugs - if (getFloaterHost() != NULL && getHost() == NULL) - { - // needs a host - // only select tabs if window they are hosted in is visible - getFloaterHost()->addFloater(this, getFloaterHost()->getVisible()); - } - - if (getHost() != NULL) - { - getHost()->setMinimized(FALSE); - getHost()->setVisibleAndFrontmost(mAutoFocus && !getIsChrome()); - getHost()->showFloater(this); - } - else - { - LLFloater* floater_to_stack = LLFloaterReg::getLastFloaterInGroup(mInstanceName); - if (!floater_to_stack) - { - floater_to_stack = LLFloaterReg::getLastFloaterCascading(); - } - applyControlsAndPosition(floater_to_stack); - setMinimized(FALSE); - setVisibleAndFrontmost(mAutoFocus && !getIsChrome()); - } - - mOpenSignal(this, key); - onOpen(key); - - dirtyRect(); + LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), true,"floater"); // Last param is event subtype or empty string + + mKey = key; // in case we need to open ourselves again + + if (getSoundFlags() != SILENT + // don't play open sound for hosted (tabbed) windows + && !getHost() + && !getFloaterHost() + && (!getVisible() || isMinimized())) + { + make_ui_sound("UISndWindowOpen"); + } + + //RN: for now, we don't allow rehosting from one multifloater to another + // just need to fix the bugs + if (getFloaterHost() != NULL && getHost() == NULL) + { + // needs a host + // only select tabs if window they are hosted in is visible + getFloaterHost()->addFloater(this, getFloaterHost()->getVisible()); + } + + if (getHost() != NULL) + { + getHost()->setMinimized(FALSE); + getHost()->setVisibleAndFrontmost(mAutoFocus && !getIsChrome()); + getHost()->showFloater(this); + } + else + { + LLFloater* floater_to_stack = LLFloaterReg::getLastFloaterInGroup(mInstanceName); + if (!floater_to_stack) + { + floater_to_stack = LLFloaterReg::getLastFloaterCascading(); + } + applyControlsAndPosition(floater_to_stack); + setMinimized(FALSE); + setVisibleAndFrontmost(mAutoFocus && !getIsChrome()); + } + + mOpenSignal(this, key); + onOpen(key); + + dirtyRect(); } void LLFloater::closeFloater(bool app_quitting) { - LL_INFOS() << "Closing floater " << getName() << LL_ENDL; - LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), false,"floater"); // Last param is event subtype or empty string - if (app_quitting) - { - LLFloater::sQuitting = true; - } - - // Always unminimize before trying to close. - // Most of the time the user will never see this state. - setMinimized(FALSE); - - if (canClose()) - { - if (getHost()) - { - ((LLMultiFloater*)getHost())->removeFloater(this); - gFloaterView->addChild(this); - } - - if (getSoundFlags() != SILENT - && getVisible() - && !getHost() - && !app_quitting) - { - make_ui_sound("UISndWindowClose"); - } - - gFocusMgr.clearLastFocusForGroup(this); - - if (hasFocus()) - { - // Do this early, so UI controls will commit before the - // window is taken down. - releaseFocus(); - - // give focus to dependee floater if it exists, and we had focus first - if (isDependent()) - { - LLFloater* dependee = mDependeeHandle.get(); - if (dependee && !dependee->isDead()) - { - dependee->setFocus(TRUE); - } - } - } - - - //If floater is a dependent, remove it from parent (dependee) + LL_INFOS() << "Closing floater " << getName() << LL_ENDL; + LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), false,"floater"); // Last param is event subtype or empty string + if (app_quitting) + { + LLFloater::sQuitting = true; + } + + // Always unminimize before trying to close. + // Most of the time the user will never see this state. + setMinimized(FALSE); + + if (canClose()) + { + if (getHost()) + { + ((LLMultiFloater*)getHost())->removeFloater(this); + gFloaterView->addChild(this); + } + + if (getSoundFlags() != SILENT + && getVisible() + && !getHost() + && !app_quitting) + { + make_ui_sound("UISndWindowClose"); + } + + gFocusMgr.clearLastFocusForGroup(this); + + if (hasFocus()) + { + // Do this early, so UI controls will commit before the + // window is taken down. + releaseFocus(); + + // give focus to dependee floater if it exists, and we had focus first + if (isDependent()) + { + LLFloater* dependee = mDependeeHandle.get(); + if (dependee && !dependee->isDead()) + { + dependee->setFocus(TRUE); + } + } + } + + + //If floater is a dependent, remove it from parent (dependee) LLFloater* dependee = mDependeeHandle.get(); if (dependee) { dependee->removeDependentFloater(this); } - // now close dependent floater - while(mDependents.size() > 0) - { + // now close dependent floater + while(mDependents.size() > 0) + { handle_set_iter_t dependent_it = mDependents.begin(); - LLFloater* floaterp = dependent_it->get(); + LLFloater* floaterp = dependent_it->get(); // normally removeDependentFloater will do this, but in // case floaterp is somehow invalid or orphaned, erase now mDependents.erase(dependent_it); @@ -772,62 +772,62 @@ void LLFloater::closeFloater(bool app_quitting) floaterp->mDependeeHandle = LLHandle(); floaterp->closeFloater(app_quitting); } - } - - cleanupHandles(); - - dirtyRect(); - - // Close callbacks - onClose(app_quitting); - mCloseSignal(this, LLSD(app_quitting)); - - // Hide or Destroy - if (mSingleInstance) - { - // Hide the instance - if (getHost()) - { - getHost()->setVisible(FALSE); - } - else - { - setVisible(FALSE); - if (!mReuseInstance) - { - destroy(); - } - } - } - else - { - setVisible(FALSE); // hide before destroying (so onVisibilityChange() gets called) - if (!mReuseInstance) - { - destroy(); - } - } - } + } + + cleanupHandles(); + + dirtyRect(); + + // Close callbacks + onClose(app_quitting); + mCloseSignal(this, LLSD(app_quitting)); + + // Hide or Destroy + if (mSingleInstance) + { + // Hide the instance + if (getHost()) + { + getHost()->setVisible(FALSE); + } + else + { + setVisible(FALSE); + if (!mReuseInstance) + { + destroy(); + } + } + } + else + { + setVisible(FALSE); // hide before destroying (so onVisibilityChange() gets called) + if (!mReuseInstance) + { + destroy(); + } + } + } } /*virtual*/ void LLFloater::closeHostedFloater() { - // When toggling *visibility*, close the host instead of the floater when hosted - if (getHost()) - { - getHost()->closeFloater(); - } - else - { - closeFloater(); - } + // When toggling *visibility*, close the host instead of the floater when hosted + if (getHost()) + { + getHost()->closeFloater(); + } + else + { + closeFloater(); + } } /*virtual*/ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLPanel::reshape(width, height, called_from_parent); + LLPanel::reshape(width, height, called_from_parent); } // virtual @@ -850,725 +850,725 @@ void LLFloater::translate(S32 x, S32 y) void LLFloater::releaseFocus() { - LLUI::getInstance()->removePopup(this); + LLUI::getInstance()->removePopup(this); - setFocus(FALSE); + setFocus(FALSE); - if( gFocusMgr.childHasMouseCapture( this ) ) - { - gFocusMgr.setMouseCapture(NULL); - } + if( gFocusMgr.childHasMouseCapture( this ) ) + { + gFocusMgr.setMouseCapture(NULL); + } } void LLFloater::setResizeLimits( S32 min_width, S32 min_height ) { - mMinWidth = min_width; - mMinHeight = min_height; - - for( S32 i = 0; i < 4; i++ ) - { - if( mResizeBar[i] ) - { - if (i == LLResizeBar::LEFT || i == LLResizeBar::RIGHT) - { - mResizeBar[i]->setResizeLimits( min_width, S32_MAX ); - } - else - { - mResizeBar[i]->setResizeLimits( min_height, S32_MAX ); - } - } - if( mResizeHandle[i] ) - { - mResizeHandle[i]->setResizeLimits( min_width, min_height ); - } - } + mMinWidth = min_width; + mMinHeight = min_height; + + for( S32 i = 0; i < 4; i++ ) + { + if( mResizeBar[i] ) + { + if (i == LLResizeBar::LEFT || i == LLResizeBar::RIGHT) + { + mResizeBar[i]->setResizeLimits( min_width, S32_MAX ); + } + else + { + mResizeBar[i]->setResizeLimits( min_height, S32_MAX ); + } + } + if( mResizeHandle[i] ) + { + mResizeHandle[i]->setResizeLimits( min_width, min_height ); + } + } } void LLFloater::center() { - if(getHost()) - { - // hosted floaters can't move - return; - } - centerWithin(gFloaterView->getRect()); + if(getHost()) + { + // hosted floaters can't move + return; + } + centerWithin(gFloaterView->getRect()); } LLMultiFloater* LLFloater::getHost() -{ - return (LLMultiFloater*)mHostHandle.get(); +{ + return (LLMultiFloater*)mHostHandle.get(); } void LLFloater::applyControlsAndPosition(LLFloater* other) { - if (!applyDockState()) - { - if (!applyRectControl()) - { - applyPositioning(other, true); - } - } + if (!applyDockState()) + { + if (!applyRectControl()) + { + applyPositioning(other, true); + } + } } bool LLFloater::applyRectControl() { - bool saved_rect = false; - - LLRect screen_rect = calcScreenRect(); - mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); - - LLFloater* last_in_group = LLFloaterReg::getLastFloaterInGroup(mInstanceName); - if (last_in_group && last_in_group != this) - { - // other floaters in our group, position ourselves relative to them and don't save the rect - if (mDefaultRectForGroup) - { - mRectControl.clear(); - } - mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; - } - else - { - bool rect_specified = false; - if (!mRectControl.empty()) - { - // If we have a saved rect, use it - const LLRect& rect = getControlGroup()->getRect(mRectControl); - if (rect.notEmpty()) saved_rect = true; - if (saved_rect) - { - setOrigin(rect.mLeft, rect.mBottom); - - if (mResizable) - { - reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); - } - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - LLRect screen_rect = calcScreenRect(); - mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); - rect_specified = true; - } - } - - LLControlVariablePtr x_control = getControlGroup()->getControl(mPosXControl); - LLControlVariablePtr y_control = getControlGroup()->getControl(mPosYControl); - if (x_control.notNull() - && y_control.notNull() - && !x_control->isDefault() - && !y_control->isDefault()) - { - mPosition.mX = x_control->getValue().asReal(); - mPosition.mY = y_control->getValue().asReal(); - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - applyRelativePosition(); - - saved_rect = true; - } - else if ((mDefaultRelativeX != 0) && (mDefaultRelativeY != 0)) - { - mPosition.mX = mDefaultRelativeX; - mPosition.mY = mDefaultRelativeY; - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - applyRelativePosition(); - - saved_rect = true; - } - - // remember updated position - if (rect_specified) - { - storeRectControl(); - } - } - - if (saved_rect) - { - // propagate any derived positioning data back to settings file - storeRectControl(); - } - - - return saved_rect; + bool saved_rect = false; + + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + + LLFloater* last_in_group = LLFloaterReg::getLastFloaterInGroup(mInstanceName); + if (last_in_group && last_in_group != this) + { + // other floaters in our group, position ourselves relative to them and don't save the rect + if (mDefaultRectForGroup) + { + mRectControl.clear(); + } + mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; + } + else + { + bool rect_specified = false; + if (!mRectControl.empty()) + { + // If we have a saved rect, use it + const LLRect& rect = getControlGroup()->getRect(mRectControl); + if (rect.notEmpty()) saved_rect = true; + if (saved_rect) + { + setOrigin(rect.mLeft, rect.mBottom); + + if (mResizable) + { + reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + rect_specified = true; + } + } + + LLControlVariablePtr x_control = getControlGroup()->getControl(mPosXControl); + LLControlVariablePtr y_control = getControlGroup()->getControl(mPosYControl); + if (x_control.notNull() + && y_control.notNull() + && !x_control->isDefault() + && !y_control->isDefault()) + { + mPosition.mX = x_control->getValue().asReal(); + mPosition.mY = y_control->getValue().asReal(); + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + applyRelativePosition(); + + saved_rect = true; + } + else if ((mDefaultRelativeX != 0) && (mDefaultRelativeY != 0)) + { + mPosition.mX = mDefaultRelativeX; + mPosition.mY = mDefaultRelativeY; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + applyRelativePosition(); + + saved_rect = true; + } + + // remember updated position + if (rect_specified) + { + storeRectControl(); + } + } + + if (saved_rect) + { + // propagate any derived positioning data back to settings file + storeRectControl(); + } + + + return saved_rect; } bool LLFloater::applyDockState() { - bool docked = false; + bool docked = false; - if (mDocStateControl.size() > 1) - { - docked = getControlGroup()->getBOOL(mDocStateControl); - setDocked(docked); - } + if (mDocStateControl.size() > 1) + { + docked = getControlGroup()->getBOOL(mDocStateControl); + setDocked(docked); + } - return docked; + return docked; } void LLFloater::applyPositioning(LLFloater* other, bool on_open) { - // Otherwise position according to the positioning code - switch (mPositioning) - { - case LLFloaterEnums::POSITIONING_CENTERED: - center(); - break; - - case LLFloaterEnums::POSITIONING_SPECIFIED: - break; - - case LLFloaterEnums::POSITIONING_CASCADING: - if (!on_open) - { - applyRelativePosition(); - } - // fall through - case LLFloaterEnums::POSITIONING_CASCADE_GROUP: - if (on_open) - { - if (other != NULL && other != this) - { - stackWith(*other); - } - else - { - static const U32 CASCADING_FLOATER_HOFFSET = 0; - static const U32 CASCADING_FLOATER_VOFFSET = 0; - - const LLRect& snap_rect = gFloaterView->getSnapRect(); - - const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; - const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; - - S32 rect_height = getRect().getHeight(); - setOrigin(horizontal_offset, vertical_offset - rect_height); - - translate(snap_rect.mLeft, snap_rect.mBottom); - } - setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); - } - break; - - case LLFloaterEnums::POSITIONING_RELATIVE: - { - applyRelativePosition(); - - break; - } - default: - // Do nothing - break; - } + // Otherwise position according to the positioning code + switch (mPositioning) + { + case LLFloaterEnums::POSITIONING_CENTERED: + center(); + break; + + case LLFloaterEnums::POSITIONING_SPECIFIED: + break; + + case LLFloaterEnums::POSITIONING_CASCADING: + if (!on_open) + { + applyRelativePosition(); + } + // fall through + case LLFloaterEnums::POSITIONING_CASCADE_GROUP: + if (on_open) + { + if (other != NULL && other != this) + { + stackWith(*other); + } + else + { + static const U32 CASCADING_FLOATER_HOFFSET = 0; + static const U32 CASCADING_FLOATER_VOFFSET = 0; + + const LLRect& snap_rect = gFloaterView->getSnapRect(); + + const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; + const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; + + S32 rect_height = getRect().getHeight(); + setOrigin(horizontal_offset, vertical_offset - rect_height); + + translate(snap_rect.mLeft, snap_rect.mBottom); + } + setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); + } + break; + + case LLFloaterEnums::POSITIONING_RELATIVE: + { + applyRelativePosition(); + + break; + } + default: + // Do nothing + break; + } } void LLFloater::applyTitle() { - if (!mDragHandle) - { - return; - } + if (!mDragHandle) + { + return; + } - if (isMinimized() && !mShortTitle.empty()) - { - mDragHandle->setTitle( mShortTitle ); - } - else - { - mDragHandle->setTitle ( mTitle ); - } + if (isMinimized() && !mShortTitle.empty()) + { + mDragHandle->setTitle( mShortTitle ); + } + else + { + mDragHandle->setTitle ( mTitle ); + } - if (getHost()) - { - getHost()->updateFloaterTitle(this); - } + if (getHost()) + { + getHost()->updateFloaterTitle(this); + } } std::string LLFloater::getCurrentTitle() const { - return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; + return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; } void LLFloater::setTitle( const std::string& title ) { - mTitle = title; - applyTitle(); + mTitle = title; + applyTitle(); } std::string LLFloater::getTitle() const { - if (mTitle.empty()) - { - return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; - } - else - { - return mTitle; - } + if (mTitle.empty()) + { + return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; + } + else + { + return mTitle; + } } void LLFloater::setShortTitle( const std::string& short_title ) { - mShortTitle = short_title; - applyTitle(); + mShortTitle = short_title; + applyTitle(); } std::string LLFloater::getShortTitle() const { - if (mShortTitle.empty()) - { - return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; - } - else - { - return mShortTitle; - } + if (mShortTitle.empty()) + { + return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null; + } + else + { + return mShortTitle; + } } BOOL LLFloater::canSnapTo(const LLView* other_view) { - if (NULL == other_view) - { - LL_WARNS() << "other_view is NULL" << LL_ENDL; - return FALSE; - } + if (NULL == other_view) + { + LL_WARNS() << "other_view is NULL" << LL_ENDL; + return FALSE; + } - if (other_view != getParent()) - { - const LLFloater* other_floaterp = dynamic_cast(other_view); - if (other_floaterp - && other_floaterp->getSnapTarget() == getHandle() - && mDependents.find(other_floaterp->getHandle()) != mDependents.end()) - { - // this is a dependent that is already snapped to us, so don't snap back to it - return FALSE; - } - } + if (other_view != getParent()) + { + const LLFloater* other_floaterp = dynamic_cast(other_view); + if (other_floaterp + && other_floaterp->getSnapTarget() == getHandle() + && mDependents.find(other_floaterp->getHandle()) != mDependents.end()) + { + // this is a dependent that is already snapped to us, so don't snap back to it + return FALSE; + } + } - return LLPanel::canSnapTo(other_view); + return LLPanel::canSnapTo(other_view); } void LLFloater::setSnappedTo(const LLView* snap_view) { - if (!snap_view || snap_view == getParent()) - { - clearSnapTarget(); - } - else - { - //RN: assume it's a floater as it must be a sibling to our parent floater - const LLFloater* floaterp = dynamic_cast(snap_view); - if (floaterp) - { - setSnapTarget(floaterp->getHandle()); - } - } + if (!snap_view || snap_view == getParent()) + { + clearSnapTarget(); + } + else + { + //RN: assume it's a floater as it must be a sibling to our parent floater + const LLFloater* floaterp = dynamic_cast(snap_view); + if (floaterp) + { + setSnapTarget(floaterp->getHandle()); + } + } } void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) { - const LLRect old_rect = getRect(); - LLView::handleReshape(new_rect, by_user); - - if (by_user && !getHost()) - { - LLFloaterView * floaterVp = dynamic_cast(getParent()); - if (floaterVp) - { - floaterVp->adjustToFitScreen(this, !isMinimized()); - } - } - - // if not minimized, adjust all snapped dependents to new shape - if (!isMinimized()) - { - if (by_user) - { - if (isDocked()) - { - setDocked( false, false); - } - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - LLRect screen_rect = calcScreenRect(); - mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); - } - storeRectControl(); - - // gather all snapped dependents - for(handle_set_iter_t dependent_it = mDependents.begin(); - dependent_it != mDependents.end(); ++dependent_it) - { - LLFloater* floaterp = dependent_it->get(); - // is a dependent snapped to us? - if (floaterp && floaterp->getSnapTarget() == getHandle()) - { - S32 delta_x = 0; - S32 delta_y = 0; - // check to see if it snapped to right or top, and move if dependee floater is resizing - LLRect dependent_rect = floaterp->getRect(); - if (dependent_rect.mLeft - getRect().mLeft >= old_rect.getWidth() || // dependent on my right? - dependent_rect.mRight == getRect().mLeft + old_rect.getWidth()) // dependent aligned with my right - { - // was snapped directly onto right side or aligned with it - delta_x += new_rect.getWidth() - old_rect.getWidth(); - } - if (dependent_rect.mBottom - getRect().mBottom >= old_rect.getHeight() || - dependent_rect.mTop == getRect().mBottom + old_rect.getHeight()) - { - // was snapped directly onto top side or aligned with it - delta_y += new_rect.getHeight() - old_rect.getHeight(); - } - - // take translation of dependee floater into account as well - delta_x += new_rect.mLeft - old_rect.mLeft; - delta_y += new_rect.mBottom - old_rect.mBottom; - - dependent_rect.translate(delta_x, delta_y); - floaterp->setShape(dependent_rect, by_user); - } - } - } - else - { - // If minimized, and origin has changed, set - // mHasBeenDraggedWhileMinimized to TRUE - if ((new_rect.mLeft != old_rect.mLeft) || - (new_rect.mBottom != old_rect.mBottom)) - { - mHasBeenDraggedWhileMinimized = TRUE; - } - } -} + const LLRect old_rect = getRect(); + LLView::handleReshape(new_rect, by_user); -void LLFloater::setMinimized(BOOL minimize) -{ - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); - - if (minimize == mMinimized) return; - - if (mMinimizeSignal) - { - (*mMinimizeSignal)(this, LLSD(minimize)); - } - - if (minimize) - { - // minimized flag should be turned on before release focus - mMinimized = TRUE; - mExpandedRect = getRect(); - - // If the floater has been dragged while minimized in the - // past, then locate it at its previous minimized location. - // Otherwise, ask the view for a minimize position. - if (mHasBeenDraggedWhileMinimized) - { - setOrigin(mPreviousMinimizedLeft, mPreviousMinimizedBottom); - } - else - { - S32 left, bottom; - gFloaterView->getMinimizePosition(&left, &bottom); - setOrigin( left, bottom ); - } - - if (mButtonsEnabled[BUTTON_MINIMIZE]) - { - mButtonsEnabled[BUTTON_MINIMIZE] = FALSE; - mButtonsEnabled[BUTTON_RESTORE] = TRUE; - } - - setBorderVisible(TRUE); - - for(handle_set_iter_t dependent_it = mDependents.begin(); - dependent_it != mDependents.end(); - ++dependent_it) - { - LLFloater* floaterp = dependent_it->get(); - if (floaterp) - { - if (floaterp->isMinimizeable()) - { - floaterp->setMinimized(TRUE); - } - else if (!floaterp->isMinimized()) - { - floaterp->setVisible(FALSE); - } - } - } - - // Lose keyboard focus when minimized - releaseFocus(); - - for (S32 i = 0; i < 4; i++) - { - if (mResizeBar[i] != NULL) - { - mResizeBar[i]->setEnabled(FALSE); - } - if (mResizeHandle[i] != NULL) - { - mResizeHandle[i]->setEnabled(FALSE); - } - } - - // Reshape *after* setting mMinimized - reshape( minimized_width, floater_header_size, TRUE); - } - else - { - // If this window has been dragged while minimized (at any time), - // remember its position for the next time it's minimized. - if (mHasBeenDraggedWhileMinimized) - { - const LLRect& currentRect = getRect(); - mPreviousMinimizedLeft = currentRect.mLeft; - mPreviousMinimizedBottom = currentRect.mBottom; - } - - setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom ); - if (mButtonsEnabled[BUTTON_RESTORE]) - { - mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; - mButtonsEnabled[BUTTON_RESTORE] = FALSE; - } - - // show dependent floater - for(handle_set_iter_t dependent_it = mDependents.begin(); - dependent_it != mDependents.end(); - ++dependent_it) - { - LLFloater* floaterp = dependent_it->get(); - if (floaterp) - { - floaterp->setMinimized(FALSE); - floaterp->setVisible(TRUE); - } - } - - for (S32 i = 0; i < 4; i++) - { - if (mResizeBar[i] != NULL) - { - mResizeBar[i]->setEnabled(isResizable()); - } - if (mResizeHandle[i] != NULL) - { - mResizeHandle[i]->setEnabled(isResizable()); - } - } - - mMinimized = FALSE; - setFrontmost(); - // Reshape *after* setting mMinimized - reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); - } - - make_ui_sound("UISndWindowClose"); - updateTitleButtons(); - applyTitle (); -} + if (by_user && !getHost()) + { + LLFloaterView * floaterVp = dynamic_cast(getParent()); + if (floaterVp) + { + floaterVp->adjustToFitScreen(this, !isMinimized()); + } + } -void LLFloater::setFocus( BOOL b ) + // if not minimized, adjust all snapped dependents to new shape + if (!isMinimized()) + { + if (by_user) + { + if (isDocked()) + { + setDocked( false, false); + } + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + } + storeRectControl(); + + // gather all snapped dependents + for(handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); ++dependent_it) + { + LLFloater* floaterp = dependent_it->get(); + // is a dependent snapped to us? + if (floaterp && floaterp->getSnapTarget() == getHandle()) + { + S32 delta_x = 0; + S32 delta_y = 0; + // check to see if it snapped to right or top, and move if dependee floater is resizing + LLRect dependent_rect = floaterp->getRect(); + if (dependent_rect.mLeft - getRect().mLeft >= old_rect.getWidth() || // dependent on my right? + dependent_rect.mRight == getRect().mLeft + old_rect.getWidth()) // dependent aligned with my right + { + // was snapped directly onto right side or aligned with it + delta_x += new_rect.getWidth() - old_rect.getWidth(); + } + if (dependent_rect.mBottom - getRect().mBottom >= old_rect.getHeight() || + dependent_rect.mTop == getRect().mBottom + old_rect.getHeight()) + { + // was snapped directly onto top side or aligned with it + delta_y += new_rect.getHeight() - old_rect.getHeight(); + } + + // take translation of dependee floater into account as well + delta_x += new_rect.mLeft - old_rect.mLeft; + delta_y += new_rect.mBottom - old_rect.mBottom; + + dependent_rect.translate(delta_x, delta_y); + floaterp->setShape(dependent_rect, by_user); + } + } + } + else + { + // If minimized, and origin has changed, set + // mHasBeenDraggedWhileMinimized to TRUE + if ((new_rect.mLeft != old_rect.mLeft) || + (new_rect.mBottom != old_rect.mBottom)) + { + mHasBeenDraggedWhileMinimized = TRUE; + } + } +} + +void LLFloater::setMinimized(BOOL minimize) +{ + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); + + if (minimize == mMinimized) return; + + if (mMinimizeSignal) + { + (*mMinimizeSignal)(this, LLSD(minimize)); + } + + if (minimize) + { + // minimized flag should be turned on before release focus + mMinimized = TRUE; + mExpandedRect = getRect(); + + // If the floater has been dragged while minimized in the + // past, then locate it at its previous minimized location. + // Otherwise, ask the view for a minimize position. + if (mHasBeenDraggedWhileMinimized) + { + setOrigin(mPreviousMinimizedLeft, mPreviousMinimizedBottom); + } + else + { + S32 left, bottom; + gFloaterView->getMinimizePosition(&left, &bottom); + setOrigin( left, bottom ); + } + + if (mButtonsEnabled[BUTTON_MINIMIZE]) + { + mButtonsEnabled[BUTTON_MINIMIZE] = FALSE; + mButtonsEnabled[BUTTON_RESTORE] = TRUE; + } + + setBorderVisible(TRUE); + + for(handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); + ++dependent_it) + { + LLFloater* floaterp = dependent_it->get(); + if (floaterp) + { + if (floaterp->isMinimizeable()) + { + floaterp->setMinimized(TRUE); + } + else if (!floaterp->isMinimized()) + { + floaterp->setVisible(FALSE); + } + } + } + + // Lose keyboard focus when minimized + releaseFocus(); + + for (S32 i = 0; i < 4; i++) + { + if (mResizeBar[i] != NULL) + { + mResizeBar[i]->setEnabled(FALSE); + } + if (mResizeHandle[i] != NULL) + { + mResizeHandle[i]->setEnabled(FALSE); + } + } + + // Reshape *after* setting mMinimized + reshape( minimized_width, floater_header_size, TRUE); + } + else + { + // If this window has been dragged while minimized (at any time), + // remember its position for the next time it's minimized. + if (mHasBeenDraggedWhileMinimized) + { + const LLRect& currentRect = getRect(); + mPreviousMinimizedLeft = currentRect.mLeft; + mPreviousMinimizedBottom = currentRect.mBottom; + } + + setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom ); + if (mButtonsEnabled[BUTTON_RESTORE]) + { + mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; + mButtonsEnabled[BUTTON_RESTORE] = FALSE; + } + + // show dependent floater + for(handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); + ++dependent_it) + { + LLFloater* floaterp = dependent_it->get(); + if (floaterp) + { + floaterp->setMinimized(FALSE); + floaterp->setVisible(TRUE); + } + } + + for (S32 i = 0; i < 4; i++) + { + if (mResizeBar[i] != NULL) + { + mResizeBar[i]->setEnabled(isResizable()); + } + if (mResizeHandle[i] != NULL) + { + mResizeHandle[i]->setEnabled(isResizable()); + } + } + + mMinimized = FALSE; + setFrontmost(); + // Reshape *after* setting mMinimized + reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); + } + + make_ui_sound("UISndWindowClose"); + updateTitleButtons(); + applyTitle (); +} + +void LLFloater::setFocus( BOOL b ) { - if (b && getIsChrome()) - { - return; - } - LLView* last_focus = gFocusMgr.getLastFocusForGroup(this); - // a descendent already has focus - BOOL child_had_focus = hasFocus(); - - // give focus to first valid descendent - LLPanel::setFocus(b); - - if (b) - { - // only push focused floaters to front of stack if not in midst of ctrl-tab cycle - LLFloaterView * parent = dynamic_cast(getParent()); - if (!getHost() && parent && !parent->getCycleMode()) - { - if (!isFrontmost()) - { - setFrontmost(); - } - } - - // when getting focus, delegate to last descendent which had focus - if (last_focus && !child_had_focus && - last_focus->isInEnabledChain() && - last_focus->isInVisibleChain()) - { - // *FIX: should handle case where focus doesn't stick - last_focus->setFocus(TRUE); - } - } - updateTransparency(b ? TT_ACTIVE : TT_INACTIVE); + if (b && getIsChrome()) + { + return; + } + LLView* last_focus = gFocusMgr.getLastFocusForGroup(this); + // a descendent already has focus + BOOL child_had_focus = hasFocus(); + + // give focus to first valid descendent + LLPanel::setFocus(b); + + if (b) + { + // only push focused floaters to front of stack if not in midst of ctrl-tab cycle + LLFloaterView * parent = dynamic_cast(getParent()); + if (!getHost() && parent && !parent->getCycleMode()) + { + if (!isFrontmost()) + { + setFrontmost(); + } + } + + // when getting focus, delegate to last descendent which had focus + if (last_focus && !child_had_focus && + last_focus->isInEnabledChain() && + last_focus->isInVisibleChain()) + { + // *FIX: should handle case where focus doesn't stick + last_focus->setFocus(TRUE); + } + } + updateTransparency(b ? TT_ACTIVE : TT_INACTIVE); } // virtual void LLFloater::setRect(const LLRect &rect) { - LLPanel::setRect(rect); - layoutDragHandle(); - layoutResizeCtrls(); + LLPanel::setRect(rect); + layoutDragHandle(); + layoutResizeCtrls(); } // virtual void LLFloater::setIsChrome(BOOL is_chrome) { - // chrome floaters don't take focus at all - if (is_chrome) - { - // remove focus if we're changing to chrome - setFocus(FALSE); - // can't Ctrl-Tab to "chrome" floaters - setFocusRoot(FALSE); - mButtons[BUTTON_CLOSE]->setToolTip(LLStringExplicit(getButtonTooltip(Params(), BUTTON_CLOSE, is_chrome))); - } - - LLPanel::setIsChrome(is_chrome); + // chrome floaters don't take focus at all + if (is_chrome) + { + // remove focus if we're changing to chrome + setFocus(FALSE); + // can't Ctrl-Tab to "chrome" floaters + setFocusRoot(FALSE); + mButtons[BUTTON_CLOSE]->setToolTip(LLStringExplicit(getButtonTooltip(Params(), BUTTON_CLOSE, is_chrome))); + } + + LLPanel::setIsChrome(is_chrome); } // Change the draw style to account for the foreground state. void LLFloater::setForeground(BOOL front) { - if (front != mForeground) - { - mForeground = front; - if (mDragHandle) - mDragHandle->setForeground( front ); + if (front != mForeground) + { + mForeground = front; + if (mDragHandle) + mDragHandle->setForeground( front ); - if (!front) - { - releaseFocus(); - } + if (!front) + { + releaseFocus(); + } - setBackgroundOpaque( front ); - } + setBackgroundOpaque( front ); + } } void LLFloater::cleanupHandles() { - // remove handles to non-existent dependents - for(handle_set_iter_t dependent_it = mDependents.begin(); - dependent_it != mDependents.end(); ) - { - LLFloater* floaterp = dependent_it->get(); - if (!floaterp) - { + // remove handles to non-existent dependents + for(handle_set_iter_t dependent_it = mDependents.begin(); + dependent_it != mDependents.end(); ) + { + LLFloater* floaterp = dependent_it->get(); + if (!floaterp) + { dependent_it = mDependents.erase(dependent_it); - } - else - { - ++dependent_it; - } - } + } + else + { + ++dependent_it; + } + } } void LLFloater::setHost(LLMultiFloater* host) { - if (mHostHandle.isDead() && host) - { - // make buttons smaller for hosted windows to differentiate from parent - mButtonScale = 0.9f; - - // add tear off button - if (mCanTearOff) - { - mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE; - } - } - else if (!mHostHandle.isDead() && !host) - { - mButtonScale = 1.f; - //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; - } - if (host) - { - mHostHandle = host->getHandle(); - mLastHostHandle = host->getHandle(); - } - else - { - mHostHandle.markDead(); - } - - updateTitleButtons(); + if (mHostHandle.isDead() && host) + { + // make buttons smaller for hosted windows to differentiate from parent + mButtonScale = 0.9f; + + // add tear off button + if (mCanTearOff) + { + mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE; + } + } + else if (!mHostHandle.isDead() && !host) + { + mButtonScale = 1.f; + //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; + } + if (host) + { + mHostHandle = host->getHandle(); + mLastHostHandle = host->getHandle(); + } + else + { + mHostHandle.markDead(); + } + + updateTitleButtons(); } void LLFloater::moveResizeHandlesToFront() { - for( S32 i = 0; i < 4; i++ ) - { - if( mResizeBar[i] ) - { - sendChildToFront(mResizeBar[i]); - } - } + for( S32 i = 0; i < 4; i++ ) + { + if( mResizeBar[i] ) + { + sendChildToFront(mResizeBar[i]); + } + } - for( S32 i = 0; i < 4; i++ ) - { - if( mResizeHandle[i] ) - { - sendChildToFront(mResizeHandle[i]); - } - } + for( S32 i = 0; i < 4; i++ ) + { + if( mResizeHandle[i] ) + { + sendChildToFront(mResizeHandle[i]); + } + } } /*virtual*/ BOOL LLFloater::isFrontmost() { - LLFloaterView* floater_view = getParentByType(); - return getVisible() - && (floater_view - && floater_view->getFrontmost() == this); + LLFloaterView* floater_view = getParentByType(); + return getVisible() + && (floater_view + && floater_view->getFrontmost() == this); } void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition, BOOL resize) { - mDependents.insert(floaterp->getHandle()); - floaterp->mDependeeHandle = getHandle(); - - if (reposition) - { - LLRect rect = gFloaterView->findNeighboringPosition(this, floaterp); - if (resize) - { - const LLRect& base = getRect(); - if (rect.mTop == base.mTop) - rect.mBottom = base.mBottom; - else if (rect.mLeft == base.mLeft) - rect.mRight = base.mRight; - floaterp->reshape(rect.getWidth(), rect.getHeight(), FALSE); - } - floaterp->setRect(rect); - floaterp->setSnapTarget(getHandle()); - } - gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE); - if (floaterp->isFrontmost()) - { - // make sure to bring self and sibling floaters to front - gFloaterView->bringToFront(floaterp, floaterp->getAutoFocus() && !getIsChrome()); - } + mDependents.insert(floaterp->getHandle()); + floaterp->mDependeeHandle = getHandle(); + + if (reposition) + { + LLRect rect = gFloaterView->findNeighboringPosition(this, floaterp); + if (resize) + { + const LLRect& base = getRect(); + if (rect.mTop == base.mTop) + rect.mBottom = base.mBottom; + else if (rect.mLeft == base.mLeft) + rect.mRight = base.mRight; + floaterp->reshape(rect.getWidth(), rect.getHeight(), FALSE); + } + floaterp->setRect(rect); + floaterp->setSnapTarget(getHandle()); + } + gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE); + if (floaterp->isFrontmost()) + { + // make sure to bring self and sibling floaters to front + gFloaterView->bringToFront(floaterp, floaterp->getAutoFocus() && !getIsChrome()); + } } void LLFloater::addDependentFloater(LLHandle dependent, BOOL reposition, BOOL resize) { - LLFloater* dependent_floaterp = dependent.get(); - if(dependent_floaterp) - { - addDependentFloater(dependent_floaterp, reposition, resize); - } + LLFloater* dependent_floaterp = dependent.get(); + if(dependent_floaterp) + { + addDependentFloater(dependent_floaterp, reposition, resize); + } } void LLFloater::removeDependentFloater(LLFloater* floaterp) { - mDependents.erase(floaterp->getHandle()); - floaterp->mDependeeHandle = LLHandle(); + mDependents.erase(floaterp->getHandle()); + floaterp->mDependeeHandle = LLHandle(); } void LLFloater::fitWithDependentsOnScreen(const LLRect& left, const LLRect& bottom, const LLRect& right, const LLRect& constraint, S32 min_overlap_pixels) @@ -1584,11 +1584,11 @@ void LLFloater::fitWithDependentsOnScreen(const LLRect& left, const LLRect& bott } } - S32 delta_left = left.notEmpty() ? left.mRight - total_rect.mRight : 0; - S32 delta_bottom = bottom.notEmpty() ? bottom.mTop - total_rect.mTop : 0; - S32 delta_right = right.notEmpty() ? right.mLeft - total_rect.mLeft : 0; + S32 delta_left = left.notEmpty() ? left.mRight - total_rect.mRight : 0; + S32 delta_bottom = bottom.notEmpty() ? bottom.mTop - total_rect.mTop : 0; + S32 delta_right = right.notEmpty() ? right.mLeft - total_rect.mLeft : 0; - // move floater with dependings fully onscreen + // move floater with dependings fully onscreen mTranslateWithDependents = true; if (translateRectIntoRect(total_rect, constraint, min_overlap_pixels)) { @@ -1611,111 +1611,111 @@ void LLFloater::fitWithDependentsOnScreen(const LLRect& left, const LLRect& bott BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index) { - if( mButtonsEnabled[index] ) - { - LLButton* my_butt = mButtons[index]; - S32 local_x = x - my_butt->getRect().mLeft; - S32 local_y = y - my_butt->getRect().mBottom; + if( mButtonsEnabled[index] ) + { + LLButton* my_butt = mButtons[index]; + S32 local_x = x - my_butt->getRect().mLeft; + S32 local_y = y - my_butt->getRect().mBottom; - if ( - my_butt->pointInView(local_x, local_y) && - my_butt->handleMouseDown(local_x, local_y, mask)) - { - // the button handled it - return TRUE; - } - } - return FALSE; + if ( + my_butt->pointInView(local_x, local_y) && + my_butt->handleMouseDown(local_x, local_y, mask)) + { + // the button handled it + return TRUE; + } + } + return FALSE; } BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks) { - LLPanel::handleScrollWheel(x,y,clicks); - return TRUE;//always + LLPanel::handleScrollWheel(x,y,clicks); + return TRUE;//always } // virtual BOOL LLFloater::handleMouseUp(S32 x, S32 y, MASK mask) { - LL_DEBUGS() << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << LL_ENDL; - BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView - if (handled) { - LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); - } - return handled; + LL_DEBUGS() << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << LL_ENDL; + BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + } + return handled; } // virtual BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) { - if( mMinimized ) - { - // Offer the click to titlebar buttons. - // Note: this block and the offerClickToButton helper method can be removed - // because the parent container will handle it for us but we'll keep it here - // for safety until after reworking the panel code to manage hidden children. - if(offerClickToButton(x, y, mask, BUTTON_CLOSE)) return TRUE; - if(offerClickToButton(x, y, mask, BUTTON_RESTORE)) return TRUE; - if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE; - if(offerClickToButton(x, y, mask, BUTTON_DOCK)) return TRUE; - - setFrontmost(TRUE, FALSE); - // Otherwise pass to drag handle for movement - return mDragHandle->handleMouseDown(x, y, mask); - } - else - { - bringToFront( x, y ); - BOOL handled = LLPanel::handleMouseDown( x, y, mask ); - if (handled) { - LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); - } - return handled; - } + if( mMinimized ) + { + // Offer the click to titlebar buttons. + // Note: this block and the offerClickToButton helper method can be removed + // because the parent container will handle it for us but we'll keep it here + // for safety until after reworking the panel code to manage hidden children. + if(offerClickToButton(x, y, mask, BUTTON_CLOSE)) return TRUE; + if(offerClickToButton(x, y, mask, BUTTON_RESTORE)) return TRUE; + if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE; + if(offerClickToButton(x, y, mask, BUTTON_DOCK)) return TRUE; + + setFrontmost(TRUE, FALSE); + // Otherwise pass to drag handle for movement + return mDragHandle->handleMouseDown(x, y, mask); + } + else + { + bringToFront( x, y ); + BOOL handled = LLPanel::handleMouseDown( x, y, mask ); + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + } + return handled; + } } // virtual BOOL LLFloater::handleRightMouseDown(S32 x, S32 y, MASK mask) { - BOOL was_minimized = mMinimized; - bringToFront( x, y ); - return was_minimized || LLPanel::handleRightMouseDown( x, y, mask ); + BOOL was_minimized = mMinimized; + bringToFront( x, y ); + return was_minimized || LLPanel::handleRightMouseDown( x, y, mask ); } BOOL LLFloater::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - bringToFront( x, y ); - return LLPanel::handleMiddleMouseDown( x, y, mask ); + bringToFront( x, y ); + return LLPanel::handleMiddleMouseDown( x, y, mask ); } // virtual BOOL LLFloater::handleDoubleClick(S32 x, S32 y, MASK mask) { - BOOL was_minimized = mMinimized; - setMinimized(FALSE); - return was_minimized || LLPanel::handleDoubleClick(x, y, mask); + BOOL was_minimized = mMinimized; + setMinimized(FALSE); + return was_minimized || LLPanel::handleDoubleClick(x, y, mask); } // virtual void LLFloater::bringToFront( S32 x, S32 y ) { - if (getVisible() && pointInView(x, y)) - { - LLMultiFloater* hostp = getHost(); - if (hostp) - { - hostp->showFloater(this); - } - else - { - LLFloaterView* parent = dynamic_cast( getParent() ); - if (parent) - { - parent->bringToFront(this, !getIsChrome()); - } - } - } + if (getVisible() && pointInView(x, y)) + { + LLMultiFloater* hostp = getHost(); + if (hostp) + { + hostp->showFloater(this); + } + else + { + LLFloaterView* parent = dynamic_cast( getParent() ); + if (parent) + { + parent->bringToFront(this, !getIsChrome()); + } + } + } } // virtual @@ -1730,494 +1730,494 @@ void LLFloater::goneFromFront() // virtual void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key) { - LLUIUsage::instance().logFloater(getInstanceName()); - LLMultiFloater* hostp = getHost(); - if (hostp) - { - hostp->setVisible(TRUE); - hostp->setFrontmost(take_focus); - } - else - { - setVisible(TRUE); - setFrontmost(take_focus); - } + LLUIUsage::instance().logFloater(getInstanceName()); + LLMultiFloater* hostp = getHost(); + if (hostp) + { + hostp->setVisible(TRUE); + hostp->setFrontmost(take_focus); + } + else + { + setVisible(TRUE); + setFrontmost(take_focus); + } } void LLFloater::setFrontmost(BOOL take_focus, BOOL restore) { - LLMultiFloater* hostp = getHost(); - if (hostp) - { - // this will bring the host floater to the front and select - // the appropriate panel - hostp->showFloater(this); - } - else - { - // there are more than one floater view - // so we need to query our parent directly - LLFloaterView * parent = dynamic_cast( getParent() ); - if (parent) - { - parent->bringToFront(this, take_focus, restore); - } - - // Make sure to set the appropriate transparency type (STORM-732). - updateTransparency(hasFocus() || getIsChrome() ? TT_ACTIVE : TT_INACTIVE); - } + LLMultiFloater* hostp = getHost(); + if (hostp) + { + // this will bring the host floater to the front and select + // the appropriate panel + hostp->showFloater(this); + } + else + { + // there are more than one floater view + // so we need to query our parent directly + LLFloaterView * parent = dynamic_cast( getParent() ); + if (parent) + { + parent->bringToFront(this, take_focus, restore); + } + + // Make sure to set the appropriate transparency type (STORM-732). + updateTransparency(hasFocus() || getIsChrome() ? TT_ACTIVE : TT_INACTIVE); + } } void LLFloater::setCanDock(bool b) { - if(b != mCanDock) - { - mCanDock = b; - if(mCanDock) - { - mButtonsEnabled[BUTTON_DOCK] = !mDocked; - } - else - { - mButtonsEnabled[BUTTON_DOCK] = FALSE; - } - } - updateTitleButtons(); + if(b != mCanDock) + { + mCanDock = b; + if(mCanDock) + { + mButtonsEnabled[BUTTON_DOCK] = !mDocked; + } + else + { + mButtonsEnabled[BUTTON_DOCK] = FALSE; + } + } + updateTitleButtons(); } void LLFloater::setDocked(bool docked, bool pop_on_undock) { - if(docked != mDocked && mCanDock) - { - mDocked = docked; - mButtonsEnabled[BUTTON_DOCK] = !mDocked; + if(docked != mDocked && mCanDock) + { + mDocked = docked; + mButtonsEnabled[BUTTON_DOCK] = !mDocked; + + if (mDocked) + { + setMinimized(FALSE); + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + } - if (mDocked) - { - setMinimized(FALSE); - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - } + updateTitleButtons(); - updateTitleButtons(); + storeDockStateControl(); + } - storeDockStateControl(); - } - } // static void LLFloater::onClickMinimize(LLFloater* self) { - if (!self) - return; - self->setMinimized( !self->isMinimized() ); + if (!self) + return; + self->setMinimized( !self->isMinimized() ); } void LLFloater::onClickTearOff(LLFloater* self) { - if (!self) - return; - S32 floater_header_size = self->mHeaderHeight; - LLMultiFloater* host_floater = self->getHost(); - if (host_floater) //Tear off - { - LLRect new_rect; - host_floater->removeFloater(self); - // reparent to floater view - gFloaterView->addChild(self); - - self->openFloater(self->getKey()); - if (self->mSaveRect && !self->mRectControl.empty()) - { - self->applyRectControl(); - } - else - { // only force position for floaters that don't have that data saved - new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); - self->setRect(new_rect); - } - gFloaterView->adjustToFitScreen(self, FALSE); - // give focus to new window to keep continuity for the user - self->setFocus(TRUE); - self->setTornOff(true); - } - else //Attach to parent. - { - LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get(); - if (new_host) - { - if (self->mSaveRect) - { + if (!self) + return; + S32 floater_header_size = self->mHeaderHeight; + LLMultiFloater* host_floater = self->getHost(); + if (host_floater) //Tear off + { + LLRect new_rect; + host_floater->removeFloater(self); + // reparent to floater view + gFloaterView->addChild(self); + + self->openFloater(self->getKey()); + if (self->mSaveRect && !self->mRectControl.empty()) + { + self->applyRectControl(); + } + else + { // only force position for floaters that don't have that data saved + new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); + self->setRect(new_rect); + } + gFloaterView->adjustToFitScreen(self, FALSE); + // give focus to new window to keep continuity for the user + self->setFocus(TRUE); + self->setTornOff(true); + } + else //Attach to parent. + { + LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get(); + if (new_host) + { + if (self->mSaveRect) + { LLRect screen_rect = self->calcScreenRect(); self->mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); - self->storeRectControl(); - } - self->setMinimized(FALSE); // to reenable minimize button if it was minimized - new_host->showFloater(self); - // make sure host is visible - new_host->openFloater(new_host->getKey()); - } - self->setTornOff(false); - } - self->updateTitleButtons(); + self->storeRectControl(); + } + self->setMinimized(FALSE); // to reenable minimize button if it was minimized + new_host->showFloater(self); + // make sure host is visible + new_host->openFloater(new_host->getKey()); + } + self->setTornOff(false); + } + self->updateTitleButtons(); self->setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); } // static void LLFloater::onClickDock(LLFloater* self) { - if(self && self->mCanDock) - { - self->setDocked(!self->mDocked, true); - } + if(self && self->mCanDock) + { + self->setDocked(!self->mDocked, true); + } } // static void LLFloater::onClickHelp( LLFloater* self ) { - if (self && LLUI::getInstance()->mHelpImpl) - { - // find the current help context for this floater - std::string help_topic; - if (self->findHelpTopic(help_topic)) - { - LLUI::getInstance()->mHelpImpl->showTopic(help_topic); - } - } + if (self && LLUI::getInstance()->mHelpImpl) + { + // find the current help context for this floater + std::string help_topic; + if (self->findHelpTopic(help_topic)) + { + LLUI::getInstance()->mHelpImpl->showTopic(help_topic); + } + } } void LLFloater::initRectControl() { - // save_rect and save_visibility only apply to registered floaters - if (mSaveRect) - { - std::string ctrl_name = getControlName(mInstanceName, mKey); - mRectControl = LLFloaterReg::declareRectControl(ctrl_name); - mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); - mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); - } + // save_rect and save_visibility only apply to registered floaters + if (mSaveRect) + { + std::string ctrl_name = getControlName(mInstanceName, mKey); + mRectControl = LLFloaterReg::declareRectControl(ctrl_name); + mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); + mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); + } } // static void LLFloater::closeFrontmostFloater() { - LLFloater* floater_to_close = gFloaterView->getFrontmostClosableFloater(); - if(floater_to_close) - { - floater_to_close->closeFloater(); - } + LLFloater* floater_to_close = gFloaterView->getFrontmostClosableFloater(); + if(floater_to_close) + { + floater_to_close->closeFloater(); + } - // if nothing took focus after closing focused floater - // give it to next floater (to allow closing multiple windows via keyboard in rapid succession) - if (gFocusMgr.getKeyboardFocus() == NULL) - { - // HACK: use gFloaterView directly in case we are using Ctrl-W to close snapshot window - // which sits in gSnapshotFloaterView, and needs to pass focus on to normal floater view - gFloaterView->focusFrontFloater(); - } + // if nothing took focus after closing focused floater + // give it to next floater (to allow closing multiple windows via keyboard in rapid succession) + if (gFocusMgr.getKeyboardFocus() == NULL) + { + // HACK: use gFloaterView directly in case we are using Ctrl-W to close snapshot window + // which sits in gSnapshotFloaterView, and needs to pass focus on to normal floater view + gFloaterView->focusFrontFloater(); + } } // static void LLFloater::onClickClose( LLFloater* self ) { - if (!self) - return; - self->onClickCloseBtn(); + if (!self) + return; + self->onClickCloseBtn(); } void LLFloater::onClickCloseBtn(bool app_quitting) { - closeFloater(false); + closeFloater(false); } // virtual void LLFloater::draw() { - const F32 alpha = getCurrentTransparency(); - - // draw background - if( isBackgroundVisible() ) - { - drawShadow(this); - - S32 left = LLPANEL_BORDER_WIDTH; - S32 top = getRect().getHeight() - LLPANEL_BORDER_WIDTH; - S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH; - S32 bottom = LLPANEL_BORDER_WIDTH; - - LLUIImage* image = NULL; - LLColor4 color; - LLColor4 overlay_color; - if (isBackgroundOpaque()) - { - // NOTE: image may not be set - image = getBackgroundImage(); - color = getBackgroundColor(); - overlay_color = getBackgroundImageOverlay(); - } - else - { - image = getTransparentImage(); - color = getTransparentColor(); - overlay_color = getTransparentImageOverlay(); - } - - if (image) - { - // We're using images for this floater's backgrounds - image->draw(getLocalRect(), overlay_color % alpha); - } - else - { - // We're not using images, use old-school flat colors - gl_rect_2d( left, top, right, bottom, color % alpha ); - - // draw highlight on title bar to indicate focus. RDW - if(hasFocus() - && !getIsChrome() - && !getCurrentTitle().empty()) - { - static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor"); - - const LLFontGL* font = LLFontGL::getFontSansSerif(); - LLRect r = getRect(); - gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1, - titlebar_focus_color % alpha, 0, TRUE); - } - } - } - - LLPanel::updateDefaultBtn(); - - if( getDefaultButton() ) - { - if (hasFocus() && getDefaultButton()->getEnabled()) - { - LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); - // is this button a direct descendent and not a nested widget (e.g. checkbox)? - BOOL focus_is_child_button = dynamic_cast(focus_ctrl) != NULL && dynamic_cast(focus_ctrl)->getParent() == this; - // only enable default button when current focus is not a button - getDefaultButton()->setBorderEnabled(!focus_is_child_button); - } - else - { - getDefaultButton()->setBorderEnabled(FALSE); - } - } - if (isMinimized()) - { - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - drawChild(mButtons[i]); - } - drawChild(mDragHandle, 0, 0, TRUE); - } - else - { - // don't call LLPanel::draw() since we've implemented custom background rendering - LLView::draw(); - } - - // update tearoff button for torn off floaters - // when last host goes away - if (mCanTearOff && !getHost()) - { - LLFloater* old_host = mLastHostHandle.get(); - if (!old_host) - { - setCanTearOff(FALSE); - } - } -} - -void LLFloater::drawShadow(LLPanel* panel) -{ - S32 left = LLPANEL_BORDER_WIDTH; - S32 top = panel->getRect().getHeight() - LLPANEL_BORDER_WIDTH; - S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH; - S32 bottom = LLPANEL_BORDER_WIDTH; - - static LLUICachedControl shadow_offset_S32 ("DropShadowFloater", 0); - static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow"); - LLColor4 shadow_color = shadow_color_cached; - F32 shadow_offset = (F32)shadow_offset_S32; - - if (!panel->isBackgroundOpaque()) - { - shadow_offset *= 0.2f; - shadow_color.mV[VALPHA] *= 0.5f; - } - gl_drop_shadow(left, top, right, bottom, - shadow_color % getCurrentTransparency(), - ll_round(shadow_offset)); -} + const F32 alpha = getCurrentTransparency(); -void LLFloater::updateTransparency(LLView* view, ETypeTransparency transparency_type) -{ - if (!view) return; - child_list_t children = *view->getChildList(); - child_list_t::iterator it = children.begin(); + // draw background + if( isBackgroundVisible() ) + { + drawShadow(this); - LLUICtrl* ctrl = dynamic_cast(view); - if (ctrl) - { - ctrl->setTransparencyType(transparency_type); - } + S32 left = LLPANEL_BORDER_WIDTH; + S32 top = getRect().getHeight() - LLPANEL_BORDER_WIDTH; + S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH; + S32 bottom = LLPANEL_BORDER_WIDTH; - for(; it != children.end(); ++it) - { - updateTransparency(*it, transparency_type); - } -} + LLUIImage* image = NULL; + LLColor4 color; + LLColor4 overlay_color; + if (isBackgroundOpaque()) + { + // NOTE: image may not be set + image = getBackgroundImage(); + color = getBackgroundColor(); + overlay_color = getBackgroundImageOverlay(); + } + else + { + image = getTransparentImage(); + color = getTransparentColor(); + overlay_color = getTransparentImageOverlay(); + } -void LLFloater::updateTransparency(ETypeTransparency transparency_type) -{ - updateTransparency(this, transparency_type); -} + if (image) + { + // We're using images for this floater's backgrounds + image->draw(getLocalRect(), overlay_color % alpha); + } + else + { + // We're not using images, use old-school flat colors + gl_rect_2d( left, top, right, bottom, color % alpha ); -void LLFloater::setCanMinimize(BOOL can_minimize) -{ - // if removing minimize/restore button programmatically, - // go ahead and unminimize floater - mCanMinimize = can_minimize; - if (!can_minimize) - { - setMinimized(FALSE); - } + // draw highlight on title bar to indicate focus. RDW + if(hasFocus() + && !getIsChrome() + && !getCurrentTitle().empty()) + { + static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor"); - mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); - mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLRect r = getRect(); + gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1, + titlebar_focus_color % alpha, 0, TRUE); + } + } + } - updateTitleButtons(); -} + LLPanel::updateDefaultBtn(); -void LLFloater::setCanClose(BOOL can_close) -{ - mCanClose = can_close; - mButtonsEnabled[BUTTON_CLOSE] = can_close; + if( getDefaultButton() ) + { + if (hasFocus() && getDefaultButton()->getEnabled()) + { + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); + // is this button a direct descendent and not a nested widget (e.g. checkbox)? + BOOL focus_is_child_button = dynamic_cast(focus_ctrl) != NULL && dynamic_cast(focus_ctrl)->getParent() == this; + // only enable default button when current focus is not a button + getDefaultButton()->setBorderEnabled(!focus_is_child_button); + } + else + { + getDefaultButton()->setBorderEnabled(FALSE); + } + } + if (isMinimized()) + { + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + drawChild(mButtons[i]); + } + drawChild(mDragHandle, 0, 0, TRUE); + } + else + { + // don't call LLPanel::draw() since we've implemented custom background rendering + LLView::draw(); + } - updateTitleButtons(); + // update tearoff button for torn off floaters + // when last host goes away + if (mCanTearOff && !getHost()) + { + LLFloater* old_host = mLastHostHandle.get(); + if (!old_host) + { + setCanTearOff(FALSE); + } + } } -void LLFloater::setCanTearOff(BOOL can_tear_off) +void LLFloater::drawShadow(LLPanel* panel) { - mCanTearOff = can_tear_off; - mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead(); + S32 left = LLPANEL_BORDER_WIDTH; + S32 top = panel->getRect().getHeight() - LLPANEL_BORDER_WIDTH; + S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH; + S32 bottom = LLPANEL_BORDER_WIDTH; - updateTitleButtons(); -} + static LLUICachedControl shadow_offset_S32 ("DropShadowFloater", 0); + static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow"); + LLColor4 shadow_color = shadow_color_cached; + F32 shadow_offset = (F32)shadow_offset_S32; + + if (!panel->isBackgroundOpaque()) + { + shadow_offset *= 0.2f; + shadow_color.mV[VALPHA] *= 0.5f; + } + gl_drop_shadow(left, top, right, bottom, + shadow_color % getCurrentTransparency(), + ll_round(shadow_offset)); +} + +void LLFloater::updateTransparency(LLView* view, ETypeTransparency transparency_type) +{ + if (!view) return; + child_list_t children = *view->getChildList(); + child_list_t::iterator it = children.begin(); + + LLUICtrl* ctrl = dynamic_cast(view); + if (ctrl) + { + ctrl->setTransparencyType(transparency_type); + } + + for(; it != children.end(); ++it) + { + updateTransparency(*it, transparency_type); + } +} + +void LLFloater::updateTransparency(ETypeTransparency transparency_type) +{ + updateTransparency(this, transparency_type); +} + +void LLFloater::setCanMinimize(BOOL can_minimize) +{ + // if removing minimize/restore button programmatically, + // go ahead and unminimize floater + mCanMinimize = can_minimize; + if (!can_minimize) + { + setMinimized(FALSE); + } + + mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); + mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); + + updateTitleButtons(); +} + +void LLFloater::setCanClose(BOOL can_close) +{ + mCanClose = can_close; + mButtonsEnabled[BUTTON_CLOSE] = can_close; + + updateTitleButtons(); +} + +void LLFloater::setCanTearOff(BOOL can_tear_off) +{ + mCanTearOff = can_tear_off; + mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead(); + + updateTitleButtons(); +} void LLFloater::setCanResize(BOOL can_resize) { - mResizable = can_resize; - enableResizeCtrls(can_resize); + mResizable = can_resize; + enableResizeCtrls(can_resize); } void LLFloater::setCanDrag(BOOL can_drag) { - // if we delete drag handle, we no longer have access to the floater's title - // so just enable/disable it - if (!can_drag && mDragHandle->getEnabled()) - { - mDragHandle->setEnabled(FALSE); - } - else if (can_drag && !mDragHandle->getEnabled()) - { - mDragHandle->setEnabled(TRUE); - } + // if we delete drag handle, we no longer have access to the floater's title + // so just enable/disable it + if (!can_drag && mDragHandle->getEnabled()) + { + mDragHandle->setEnabled(FALSE); + } + else if (can_drag && !mDragHandle->getEnabled()) + { + mDragHandle->setEnabled(TRUE); + } } bool LLFloater::getCanDrag() { - return mDragHandle->getEnabled(); + return mDragHandle->getEnabled(); } void LLFloater::updateTitleButtons() { - static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); - static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); - LLRect buttons_rect; - S32 button_count = 0; - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (!mButtons[i]) - { - continue; - } - - bool enabled = mButtonsEnabled[i]; - if (i == BUTTON_HELP) - { - // don't show the help button if the floater is minimized - // or if it is a docked tear-off floater - if (isMinimized() || (mButtonsEnabled[BUTTON_TEAR_OFF] && ! mTornOff)) - { - enabled = false; - } - } - if (i == BUTTON_CLOSE && mButtonScale != 1.f) - { - //*HACK: always render close button for hosted floaters so - //that users don't accidentally hit the button when - //closing multiple windows in the chatterbox - enabled = true; - } - - mButtons[i]->setEnabled(enabled); - - if (enabled) - { - button_count++; - - LLRect btn_rect; - if (mDragOnLeft) - { - btn_rect.setLeftTopAndSize( - LLPANEL_BORDER_WIDTH, - getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * button_count, - ll_round((F32)floater_close_box_size * mButtonScale), - ll_round((F32)floater_close_box_size * mButtonScale)); - } - else - { - btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * button_count, - getRect().getHeight() - close_box_from_top, - ll_round((F32)floater_close_box_size * mButtonScale), - ll_round((F32)floater_close_box_size * mButtonScale)); - } - - // first time here, init 'buttons_rect' - if(1 == button_count) - { - buttons_rect = btn_rect; - } - else - { - // if mDragOnLeft=true then buttons are on top-left side vertically aligned - // title is not displayed in this case, calculating 'buttons_rect' for future use - mDragOnLeft ? buttons_rect.mBottom -= btn_rect.mBottom : - buttons_rect.mLeft = btn_rect.mLeft; - } - mButtons[i]->setRect(btn_rect); - mButtons[i]->setVisible(TRUE); - // the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater - mButtons[i]->setTabStop(i == BUTTON_RESTORE); - } - else - { - mButtons[i]->setVisible(FALSE); - } - } - if (mDragHandle) - { - localRectToOtherView(buttons_rect, &buttons_rect, mDragHandle); - mDragHandle->setButtonsRect(buttons_rect); - } + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); + LLRect buttons_rect; + S32 button_count = 0; + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (!mButtons[i]) + { + continue; + } + + bool enabled = mButtonsEnabled[i]; + if (i == BUTTON_HELP) + { + // don't show the help button if the floater is minimized + // or if it is a docked tear-off floater + if (isMinimized() || (mButtonsEnabled[BUTTON_TEAR_OFF] && ! mTornOff)) + { + enabled = false; + } + } + if (i == BUTTON_CLOSE && mButtonScale != 1.f) + { + //*HACK: always render close button for hosted floaters so + //that users don't accidentally hit the button when + //closing multiple windows in the chatterbox + enabled = true; + } + + mButtons[i]->setEnabled(enabled); + + if (enabled) + { + button_count++; + + LLRect btn_rect; + if (mDragOnLeft) + { + btn_rect.setLeftTopAndSize( + LLPANEL_BORDER_WIDTH, + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * button_count, + ll_round((F32)floater_close_box_size * mButtonScale), + ll_round((F32)floater_close_box_size * mButtonScale)); + } + else + { + btn_rect.setLeftTopAndSize( + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * button_count, + getRect().getHeight() - close_box_from_top, + ll_round((F32)floater_close_box_size * mButtonScale), + ll_round((F32)floater_close_box_size * mButtonScale)); + } + + // first time here, init 'buttons_rect' + if(1 == button_count) + { + buttons_rect = btn_rect; + } + else + { + // if mDragOnLeft=true then buttons are on top-left side vertically aligned + // title is not displayed in this case, calculating 'buttons_rect' for future use + mDragOnLeft ? buttons_rect.mBottom -= btn_rect.mBottom : + buttons_rect.mLeft = btn_rect.mLeft; + } + mButtons[i]->setRect(btn_rect); + mButtons[i]->setVisible(TRUE); + // the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater + mButtons[i]->setTabStop(i == BUTTON_RESTORE); + } + else + { + mButtons[i]->setVisible(FALSE); + } + } + if (mDragHandle) + { + localRectToOtherView(buttons_rect, &buttons_rect, mDragHandle); + mDragHandle->setButtonsRect(buttons_rect); + } } void LLFloater::drawConeToOwner(F32 &context_cone_opacity, @@ -2286,115 +2286,115 @@ void LLFloater::drawConeToOwner(F32 &context_cone_opacity, void LLFloater::buildButtons(const Params& floater_params) { - static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); - static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (mButtons[i]) - { - removeChild(mButtons[i]); - delete mButtons[i]; - mButtons[i] = NULL; - } - - LLRect btn_rect; - if (mDragOnLeft) - { - btn_rect.setLeftTopAndSize( - LLPANEL_BORDER_WIDTH, - getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * (i + 1), - ll_round(floater_close_box_size * mButtonScale), - ll_round(floater_close_box_size * mButtonScale)); - } - else - { - btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * (i + 1), - getRect().getHeight() - close_box_from_top, - ll_round(floater_close_box_size * mButtonScale), - ll_round(floater_close_box_size * mButtonScale)); - } - - LLButton::Params p; - p.name(sButtonNames[i]); - p.rect(btn_rect); - p.image_unselected = getButtonImage(floater_params, (EFloaterButton)i); - // Selected, no matter if hovered or not, is "pressed" - LLUIImage* pressed_image = getButtonPressedImage(floater_params, (EFloaterButton)i); - p.image_selected = pressed_image; - p.image_hover_selected = pressed_image; - // Use a glow effect when the user hovers over the button - // These icons are really small, need glow amount increased - p.hover_glow_amount( 0.33f ); - p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); - p.tab_stop(false); - p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); - p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i, getIsChrome()); - p.scale_image(true); - p.chrome(true); - - LLButton* buttonp = LLUICtrlFactory::create(p); - addChild(buttonp); - mButtons[i] = buttonp; - } - - updateTitleButtons(); + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (mButtons[i]) + { + removeChild(mButtons[i]); + delete mButtons[i]; + mButtons[i] = NULL; + } + + LLRect btn_rect; + if (mDragOnLeft) + { + btn_rect.setLeftTopAndSize( + LLPANEL_BORDER_WIDTH, + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * (i + 1), + ll_round(floater_close_box_size * mButtonScale), + ll_round(floater_close_box_size * mButtonScale)); + } + else + { + btn_rect.setLeftTopAndSize( + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * (i + 1), + getRect().getHeight() - close_box_from_top, + ll_round(floater_close_box_size * mButtonScale), + ll_round(floater_close_box_size * mButtonScale)); + } + + LLButton::Params p; + p.name(sButtonNames[i]); + p.rect(btn_rect); + p.image_unselected = getButtonImage(floater_params, (EFloaterButton)i); + // Selected, no matter if hovered or not, is "pressed" + LLUIImage* pressed_image = getButtonPressedImage(floater_params, (EFloaterButton)i); + p.image_selected = pressed_image; + p.image_hover_selected = pressed_image; + // Use a glow effect when the user hovers over the button + // These icons are really small, need glow amount increased + p.hover_glow_amount( 0.33f ); + p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); + p.tab_stop(false); + p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); + p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i, getIsChrome()); + p.scale_image(true); + p.chrome(true); + + LLButton* buttonp = LLUICtrlFactory::create(p); + addChild(buttonp); + mButtons[i] = buttonp; + } + + updateTitleButtons(); } // static LLUIImage* LLFloater::getButtonImage(const Params& p, EFloaterButton e) { - switch(e) - { - default: - case BUTTON_CLOSE: - return p.close_image; - case BUTTON_RESTORE: - return p.restore_image; - case BUTTON_MINIMIZE: - return p.minimize_image; - case BUTTON_TEAR_OFF: - return p.tear_off_image; - case BUTTON_DOCK: - return p.dock_image; - case BUTTON_HELP: - return p.help_image; - } + switch(e) + { + default: + case BUTTON_CLOSE: + return p.close_image; + case BUTTON_RESTORE: + return p.restore_image; + case BUTTON_MINIMIZE: + return p.minimize_image; + case BUTTON_TEAR_OFF: + return p.tear_off_image; + case BUTTON_DOCK: + return p.dock_image; + case BUTTON_HELP: + return p.help_image; + } } // static LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e) { - switch(e) - { - default: - case BUTTON_CLOSE: - return p.close_pressed_image; - case BUTTON_RESTORE: - return p.restore_pressed_image; - case BUTTON_MINIMIZE: - return p.minimize_pressed_image; - case BUTTON_TEAR_OFF: - return p.tear_off_pressed_image; - case BUTTON_DOCK: - return p.dock_pressed_image; - case BUTTON_HELP: - return p.help_pressed_image; - } + switch(e) + { + default: + case BUTTON_CLOSE: + return p.close_pressed_image; + case BUTTON_RESTORE: + return p.restore_pressed_image; + case BUTTON_MINIMIZE: + return p.minimize_pressed_image; + case BUTTON_TEAR_OFF: + return p.tear_off_pressed_image; + case BUTTON_DOCK: + return p.dock_pressed_image; + case BUTTON_HELP: + return p.help_pressed_image; + } } // static std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome) { - // EXT-4081 (Lag Meter: Ctrl+W does not close floater) - // If floater is chrome set 'Close' text for close button's tooltip - if(is_chrome && BUTTON_CLOSE == e) - { - static std::string close_tooltip_chrome = LLTrans::getString("BUTTON_CLOSE_CHROME"); - return close_tooltip_chrome; - } - // TODO: per-floater localizable tooltips set in XML - return sButtonToolTips[e]; + // EXT-4081 (Lag Meter: Ctrl+W does not close floater) + // If floater is chrome set 'Close' text for close button's tooltip + if(is_chrome && BUTTON_CLOSE == e) + { + static std::string close_tooltip_chrome = LLTrans::getString("BUTTON_CLOSE_CHROME"); + return close_tooltip_chrome; + } + // TODO: per-floater localizable tooltips set in XML + return sButtonToolTips[e]; } ///////////////////////////////////////////////////// @@ -2403,1095 +2403,1095 @@ std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e, bool static LLDefaultChildRegistry::Register r("floater_view"); LLFloaterView::LLFloaterView (const Params& p) -: LLUICtrl (p), - mFocusCycleMode(FALSE), - mMinimizePositionVOffset(0), - mSnapOffsetBottom(0), - mSnapOffsetRight(0) +: LLUICtrl (p), + mFocusCycleMode(FALSE), + mMinimizePositionVOffset(0), + mSnapOffsetBottom(0), + mSnapOffsetRight(0) { - mSnapView = getHandle(); + mSnapView = getHandle(); } // By default, adjust vertical. void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLView::reshape(width, height, called_from_parent); - - mLastSnapRect = getSnapRect(); - - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - LLFloater* floaterp = dynamic_cast(viewp); - if (floaterp->isDependent()) - { - // dependents are moved with their "dependee" - continue; - } - - if (!floaterp->isMinimized() && floaterp->getCanDrag()) - { - LLRect old_rect = floaterp->getRect(); - floaterp->applyPositioning(NULL, false); - LLRect new_rect = floaterp->getRect(); - - //LLRect r = floaterp->getRect(); - - //// Compute absolute distance from each edge of screen - //S32 left_offset = llabs(r.mLeft - 0); - //S32 right_offset = llabs(old_right - r.mRight); - - //S32 top_offset = llabs(old_top - r.mTop); - //S32 bottom_offset = llabs(r.mBottom - 0); - - S32 translate_x = new_rect.mLeft - old_rect.mLeft; - S32 translate_y = new_rect.mBottom - old_rect.mBottom; - - //if (left_offset > right_offset) - //{ - // translate_x = new_right - old_right; - //} - - //if (top_offset < bottom_offset) - //{ - // translate_y = new_top - old_top; - //} - - // don't reposition immovable floaters - //if (floaterp->getCanDrag()) - //{ - // floaterp->translate(translate_x, translate_y); - //} - for (LLHandle dependent_floater : floaterp->mDependents) - { - if (dependent_floater.get()) - { - dependent_floater.get()->translate(translate_x, translate_y); - } - } - } - } + LLView::reshape(width, height, called_from_parent); + + mLastSnapRect = getSnapRect(); + + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + LLFloater* floaterp = dynamic_cast(viewp); + if (floaterp->isDependent()) + { + // dependents are moved with their "dependee" + continue; + } + + if (!floaterp->isMinimized() && floaterp->getCanDrag()) + { + LLRect old_rect = floaterp->getRect(); + floaterp->applyPositioning(NULL, false); + LLRect new_rect = floaterp->getRect(); + + //LLRect r = floaterp->getRect(); + + //// Compute absolute distance from each edge of screen + //S32 left_offset = llabs(r.mLeft - 0); + //S32 right_offset = llabs(old_right - r.mRight); + + //S32 top_offset = llabs(old_top - r.mTop); + //S32 bottom_offset = llabs(r.mBottom - 0); + + S32 translate_x = new_rect.mLeft - old_rect.mLeft; + S32 translate_y = new_rect.mBottom - old_rect.mBottom; + + //if (left_offset > right_offset) + //{ + // translate_x = new_right - old_right; + //} + + //if (top_offset < bottom_offset) + //{ + // translate_y = new_top - old_top; + //} + + // don't reposition immovable floaters + //if (floaterp->getCanDrag()) + //{ + // floaterp->translate(translate_x, translate_y); + //} + for (LLHandle dependent_floater : floaterp->mDependents) + { + if (dependent_floater.get()) + { + dependent_floater.get()->translate(translate_x, translate_y); + } + } + } + } } void LLFloaterView::restoreAll() { - // make sure all subwindows aren't minimized - for (auto child : *getChildList()) - { - LLFloater* floaterp = dynamic_cast(child); - if (floaterp) - { - floaterp->setMinimized(FALSE); - } - } + // make sure all subwindows aren't minimized + for (auto child : *getChildList()) + { + LLFloater* floaterp = dynamic_cast(child); + if (floaterp) + { + floaterp->setMinimized(FALSE); + } + } - // *FIX: make sure dependents are restored + // *FIX: make sure dependents are restored - // children then deleted by default view constructor + // children then deleted by default view constructor } LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ) { - LLRect base_rect = reference_floater->getRect(); - LLRect::tCoordType width = neighbor->getRect().getWidth(); - LLRect::tCoordType height = neighbor->getRect().getHeight(); - LLRect new_rect = neighbor->getRect(); - - LLRect expanded_base_rect = base_rect; - expanded_base_rect.stretch(10); - for(LLFloater::handle_set_iter_t dependent_it = reference_floater->mDependents.begin(); - dependent_it != reference_floater->mDependents.end(); ++dependent_it) - { - LLFloater* sibling = dependent_it->get(); - // check for dependents within 10 pixels of base floater - if (sibling && - sibling != neighbor && - sibling->getVisible() && - expanded_base_rect.overlaps(sibling->getRect())) - { - base_rect.unionWith(sibling->getRect()); - } - } - - LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft); - LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight); - LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop); - LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom); - - // find position for floater in following order - // right->left->bottom->top - for (S32 i = 0; i < 5; i++) - { - if (right_margin > width) - { - new_rect.translate(base_rect.mRight - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mTop); - return new_rect; - } - else if (left_margin > width) - { - new_rect.translate(base_rect.mLeft - neighbor->getRect().mRight, base_rect.mTop - neighbor->getRect().mTop); - return new_rect; - } - else if (bottom_margin > height) - { - new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mBottom - neighbor->getRect().mTop); - return new_rect; - } - else if (top_margin > height) - { - new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mBottom); - return new_rect; - } - - // keep growing margins to find "best" fit - left_margin += 20; - right_margin += 20; - top_margin += 20; - bottom_margin += 20; - } - - // didn't find anything, return initial rect - return new_rect; + LLRect base_rect = reference_floater->getRect(); + LLRect::tCoordType width = neighbor->getRect().getWidth(); + LLRect::tCoordType height = neighbor->getRect().getHeight(); + LLRect new_rect = neighbor->getRect(); + + LLRect expanded_base_rect = base_rect; + expanded_base_rect.stretch(10); + for(LLFloater::handle_set_iter_t dependent_it = reference_floater->mDependents.begin(); + dependent_it != reference_floater->mDependents.end(); ++dependent_it) + { + LLFloater* sibling = dependent_it->get(); + // check for dependents within 10 pixels of base floater + if (sibling && + sibling != neighbor && + sibling->getVisible() && + expanded_base_rect.overlaps(sibling->getRect())) + { + base_rect.unionWith(sibling->getRect()); + } + } + + LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft); + LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight); + LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop); + LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom); + + // find position for floater in following order + // right->left->bottom->top + for (S32 i = 0; i < 5; i++) + { + if (right_margin > width) + { + new_rect.translate(base_rect.mRight - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mTop); + return new_rect; + } + else if (left_margin > width) + { + new_rect.translate(base_rect.mLeft - neighbor->getRect().mRight, base_rect.mTop - neighbor->getRect().mTop); + return new_rect; + } + else if (bottom_margin > height) + { + new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mBottom - neighbor->getRect().mTop); + return new_rect; + } + else if (top_margin > height) + { + new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mBottom); + return new_rect; + } + + // keep growing margins to find "best" fit + left_margin += 20; + right_margin += 20; + top_margin += 20; + bottom_margin += 20; + } + + // didn't find anything, return initial rect + return new_rect; } void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore) { - if (!child) - return; + if (!child) + return; LLFloater* front_child = mFrontChildHandle.get(); - if (front_child == child) - { - if (give_focus && child->canFocusStealFrontmost() && !gFocusMgr.childHasKeyboardFocus(child)) - { - child->setFocus(TRUE); - } - return; - } - - if (front_child && front_child->getVisible()) - { + if (front_child == child) + { + if (give_focus && child->canFocusStealFrontmost() && !gFocusMgr.childHasKeyboardFocus(child)) + { + child->setFocus(TRUE); + } + return; + } + + if (front_child && front_child->getVisible()) + { front_child->goneFromFront(); - } + } mFrontChildHandle = child->getHandle(); - // *TODO: make this respect floater's mAutoFocus value, instead of - // using parameter - if (child->getHost()) - { - // this floater is hosted elsewhere and hence not one of our children, abort - return; - } - std::vector floaters_to_move; - // Look at all floaters...tab - for (child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it) - { - LLFloater* floater = dynamic_cast(*child_it); - - // ...but if I'm a dependent floater... - if (floater && child->isDependent()) - { - // ...look for floaters that have me as a dependent... - LLFloater::handle_set_iter_t found_dependent = floater->mDependents.find(child->getHandle()); - - if (found_dependent != floater->mDependents.end()) - { - // ...and make sure all children of that floater (including me) are brought to front... - for (LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); - dependent_it != floater->mDependents.end(); ++dependent_it) - { - LLFloater* sibling = dependent_it->get(); - if (sibling) - { - floaters_to_move.push_back(sibling); - } - } - //...before bringing my parent to the front... - floaters_to_move.push_back(floater); - } - } - } - - std::vector::iterator floater_it; - for(floater_it = floaters_to_move.begin(); floater_it != floaters_to_move.end(); ++floater_it) - { - LLFloater* floaterp = *floater_it; - sendChildToFront(floaterp); - - // always unminimize dependee, but allow dependents to stay minimized - if (!floaterp->isDependent()) - { - floaterp->setMinimized(FALSE); - } - } - floaters_to_move.clear(); - - // ...then bringing my own dependents to the front... - for (LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin(); - dependent_it != child->mDependents.end(); ++dependent_it) - { - LLFloater* dependent = dependent_it->get(); - if (dependent) - { - sendChildToFront(dependent); - } - } - - // ...and finally bringing myself to front - // (do this last, so that I'm left in front at end of this call) - if (*beginChild() != child) - { - sendChildToFront(child); - } - - if(restore) - { - child->setMinimized(FALSE); - } - - if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) - { - child->setFocus(TRUE); - // floater did not take focus, so relinquish focus to world - if (!child->hasFocus()) - { - gFocusMgr.setKeyboardFocus(NULL); - } - } + // *TODO: make this respect floater's mAutoFocus value, instead of + // using parameter + if (child->getHost()) + { + // this floater is hosted elsewhere and hence not one of our children, abort + return; + } + std::vector floaters_to_move; + // Look at all floaters...tab + for (child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it) + { + LLFloater* floater = dynamic_cast(*child_it); + + // ...but if I'm a dependent floater... + if (floater && child->isDependent()) + { + // ...look for floaters that have me as a dependent... + LLFloater::handle_set_iter_t found_dependent = floater->mDependents.find(child->getHandle()); + + if (found_dependent != floater->mDependents.end()) + { + // ...and make sure all children of that floater (including me) are brought to front... + for (LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); + dependent_it != floater->mDependents.end(); ++dependent_it) + { + LLFloater* sibling = dependent_it->get(); + if (sibling) + { + floaters_to_move.push_back(sibling); + } + } + //...before bringing my parent to the front... + floaters_to_move.push_back(floater); + } + } + } + + std::vector::iterator floater_it; + for(floater_it = floaters_to_move.begin(); floater_it != floaters_to_move.end(); ++floater_it) + { + LLFloater* floaterp = *floater_it; + sendChildToFront(floaterp); + + // always unminimize dependee, but allow dependents to stay minimized + if (!floaterp->isDependent()) + { + floaterp->setMinimized(FALSE); + } + } + floaters_to_move.clear(); + + // ...then bringing my own dependents to the front... + for (LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin(); + dependent_it != child->mDependents.end(); ++dependent_it) + { + LLFloater* dependent = dependent_it->get(); + if (dependent) + { + sendChildToFront(dependent); + } + } + + // ...and finally bringing myself to front + // (do this last, so that I'm left in front at end of this call) + if (*beginChild() != child) + { + sendChildToFront(child); + } + + if(restore) + { + child->setMinimized(FALSE); + } + + if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) + { + child->setFocus(TRUE); + // floater did not take focus, so relinquish focus to world + if (!child->hasFocus()) + { + gFocusMgr.setKeyboardFocus(NULL); + } + } } void LLFloaterView::highlightFocusedFloater() { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLFloater *floater = (LLFloater *)(*child_it); - - // skip dependent floaters, as we'll handle them in a batch along with their dependee(?) - if (floater->isDependent()) - { - continue; - } - - BOOL floater_or_dependent_has_focus = gFocusMgr.childHasKeyboardFocus(floater); - for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); - dependent_it != floater->mDependents.end(); - ++dependent_it) - { - LLFloater* dependent_floaterp = dependent_it->get(); - if (dependent_floaterp && gFocusMgr.childHasKeyboardFocus(dependent_floaterp)) - { - floater_or_dependent_has_focus = TRUE; - } - } - - // now set this floater and all its dependents - floater->setForeground(floater_or_dependent_has_focus); - - for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); - dependent_it != floater->mDependents.end(); ) - { - LLFloater* dependent_floaterp = dependent_it->get(); - if (dependent_floaterp) - { - dependent_floaterp->setForeground(floater_or_dependent_has_focus); - } - ++dependent_it; - } - - floater->cleanupHandles(); - } + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLFloater *floater = (LLFloater *)(*child_it); + + // skip dependent floaters, as we'll handle them in a batch along with their dependee(?) + if (floater->isDependent()) + { + continue; + } + + BOOL floater_or_dependent_has_focus = gFocusMgr.childHasKeyboardFocus(floater); + for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); + dependent_it != floater->mDependents.end(); + ++dependent_it) + { + LLFloater* dependent_floaterp = dependent_it->get(); + if (dependent_floaterp && gFocusMgr.childHasKeyboardFocus(dependent_floaterp)) + { + floater_or_dependent_has_focus = TRUE; + } + } + + // now set this floater and all its dependents + floater->setForeground(floater_or_dependent_has_focus); + + for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); + dependent_it != floater->mDependents.end(); ) + { + LLFloater* dependent_floaterp = dependent_it->get(); + if (dependent_floaterp) + { + dependent_floaterp->setForeground(floater_or_dependent_has_focus); + } + ++dependent_it; + } + + floater->cleanupHandles(); + } } LLFloater* LLFloaterView::getFrontmostClosableFloater() { - child_list_const_iter_t child_it; - LLFloater* frontmost_floater = NULL; + child_list_const_iter_t child_it; + LLFloater* frontmost_floater = NULL; - for ( child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - frontmost_floater = (LLFloater *)(*child_it); + for ( child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + frontmost_floater = (LLFloater *)(*child_it); - if (frontmost_floater->isInVisibleChain() && frontmost_floater->isCloseable()) - { - return frontmost_floater; - } - } + if (frontmost_floater->isInVisibleChain() && frontmost_floater->isCloseable()) + { + return frontmost_floater; + } + } - return NULL; + return NULL; } void LLFloaterView::unhighlightFocusedFloater() { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLFloater *floater = (LLFloater *)(*child_it); + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLFloater *floater = (LLFloater *)(*child_it); - floater->setForeground(FALSE); - } + floater->setForeground(FALSE); + } } void LLFloaterView::focusFrontFloater() { - LLFloater* floaterp = getFrontmost(); - if (floaterp) - { - floaterp->setFocus(TRUE); - } + LLFloater* floaterp = getFrontmost(); + if (floaterp) + { + floaterp->setFocus(TRUE); + } } void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) { - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); - LLRect snap_rect_local = getLocalSnapRect(); - snap_rect_local.mTop += mMinimizePositionVOffset; - for(S32 col = snap_rect_local.mLeft; - col < snap_rect_local.getWidth() - minimized_width; - col += minimized_width) - { - for(S32 row = snap_rect_local.mTop - floater_header_size; - row > floater_header_size; - row -= floater_header_size ) //loop rows - { - - bool foundGap = TRUE; - for(child_list_const_iter_t child_it = getChildList()->begin(); - child_it != getChildList()->end(); - ++child_it) //loop floaters - { - // Examine minimized children. - LLFloater* floater = dynamic_cast(*child_it); - if(floater->isMinimized()) - { - LLRect r = floater->getRect(); - if((r.mBottom < (row + floater_header_size)) - && (r.mBottom > (row - floater_header_size)) - && (r.mLeft < (col + minimized_width)) - && (r.mLeft > (col - minimized_width))) - { - // needs the check for off grid. can't drag, - // but window resize makes them off - foundGap = FALSE; - break; - } - } - } //done floaters - if(foundGap) - { - *left = col; - *bottom = row; - return; //done - } - } //done this col - } - - // crude - stack'em all at 0,0 when screen is full of minimized - // floaters. - *left = snap_rect_local.mLeft; - *bottom = snap_rect_local.mBottom; + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); + LLRect snap_rect_local = getLocalSnapRect(); + snap_rect_local.mTop += mMinimizePositionVOffset; + for(S32 col = snap_rect_local.mLeft; + col < snap_rect_local.getWidth() - minimized_width; + col += minimized_width) + { + for(S32 row = snap_rect_local.mTop - floater_header_size; + row > floater_header_size; + row -= floater_header_size ) //loop rows + { + + bool foundGap = TRUE; + for(child_list_const_iter_t child_it = getChildList()->begin(); + child_it != getChildList()->end(); + ++child_it) //loop floaters + { + // Examine minimized children. + LLFloater* floater = dynamic_cast(*child_it); + if(floater->isMinimized()) + { + LLRect r = floater->getRect(); + if((r.mBottom < (row + floater_header_size)) + && (r.mBottom > (row - floater_header_size)) + && (r.mLeft < (col + minimized_width)) + && (r.mLeft > (col - minimized_width))) + { + // needs the check for off grid. can't drag, + // but window resize makes them off + foundGap = FALSE; + break; + } + } + } //done floaters + if(foundGap) + { + *left = col; + *bottom = row; + return; //done + } + } //done this col + } + + // crude - stack'em all at 0,0 when screen is full of minimized + // floaters. + *left = snap_rect_local.mLeft; + *bottom = snap_rect_local.mBottom; } void LLFloaterView::destroyAllChildren() { - LLView::deleteAllChildren(); + LLView::deleteAllChildren(); } void LLFloaterView::closeAllChildren(bool app_quitting) { - // iterate over a copy of the list, because closing windows will destroy - // some windows on the list. - child_list_t child_list = *(getChildList()); - - for (child_list_const_iter_t it = child_list.begin(); it != child_list.end(); ++it) - { - LLView* viewp = *it; - child_list_const_iter_t exists = std::find(getChildList()->begin(), getChildList()->end(), viewp); - if (exists == getChildList()->end()) - { - // this floater has already been removed - continue; - } - - LLFloater* floaterp = dynamic_cast(viewp); - - // Attempt to close floater. This will cause the "do you want to save" - // dialogs to appear. - // Skip invisible floaters if we're not quitting (STORM-192). - if (floaterp->canClose() && !floaterp->isDead() && - (app_quitting || floaterp->getVisible())) - { - floaterp->closeFloater(app_quitting); - } - } + // iterate over a copy of the list, because closing windows will destroy + // some windows on the list. + child_list_t child_list = *(getChildList()); + + for (child_list_const_iter_t it = child_list.begin(); it != child_list.end(); ++it) + { + LLView* viewp = *it; + child_list_const_iter_t exists = std::find(getChildList()->begin(), getChildList()->end(), viewp); + if (exists == getChildList()->end()) + { + // this floater has already been removed + continue; + } + + LLFloater* floaterp = dynamic_cast(viewp); + + // Attempt to close floater. This will cause the "do you want to save" + // dialogs to appear. + // Skip invisible floaters if we're not quitting (STORM-192). + if (floaterp->canClose() && !floaterp->isDead() && + (app_quitting || floaterp->getVisible())) + { + floaterp->closeFloater(app_quitting); + } + } } void LLFloaterView::hiddenFloaterClosed(LLFloater* floater) { - for (hidden_floaters_t::iterator it = mHiddenFloaters.begin(), end_it = mHiddenFloaters.end(); - it != end_it; - ++it) - { - if (it->first.get() == floater) - { - it->second.disconnect(); - mHiddenFloaters.erase(it); - break; - } - } + for (hidden_floaters_t::iterator it = mHiddenFloaters.begin(), end_it = mHiddenFloaters.end(); + it != end_it; + ++it) + { + if (it->first.get() == floater) + { + it->second.disconnect(); + mHiddenFloaters.erase(it); + break; + } + } } void LLFloaterView::hideAllFloaters() { - child_list_t child_list = *(getChildList()); + child_list_t child_list = *(getChildList()); - for (child_list_iter_t it = child_list.begin(); it != child_list.end(); ++it) - { - LLFloater* floaterp = dynamic_cast(*it); - if (floaterp && floaterp->getVisible()) - { - floaterp->setVisible(false); - boost::signals2::connection connection = floaterp->mCloseSignal.connect(boost::bind(&LLFloaterView::hiddenFloaterClosed, this, floaterp)); - mHiddenFloaters.push_back(std::make_pair(floaterp->getHandle(), connection)); - } - } + for (child_list_iter_t it = child_list.begin(); it != child_list.end(); ++it) + { + LLFloater* floaterp = dynamic_cast(*it); + if (floaterp && floaterp->getVisible()) + { + floaterp->setVisible(false); + boost::signals2::connection connection = floaterp->mCloseSignal.connect(boost::bind(&LLFloaterView::hiddenFloaterClosed, this, floaterp)); + mHiddenFloaters.push_back(std::make_pair(floaterp->getHandle(), connection)); + } + } } void LLFloaterView::showHiddenFloaters() { - for (hidden_floaters_t::iterator it = mHiddenFloaters.begin(), end_it = mHiddenFloaters.end(); - it != end_it; - ++it) - { - LLFloater* floaterp = it->first.get(); - if (floaterp) - { - floaterp->setVisible(true); - } - it->second.disconnect(); - } - mHiddenFloaters.clear(); + for (hidden_floaters_t::iterator it = mHiddenFloaters.begin(), end_it = mHiddenFloaters.end(); + it != end_it; + ++it) + { + LLFloater* floaterp = it->first.get(); + if (floaterp) + { + floaterp->setVisible(true); + } + it->second.disconnect(); + } + mHiddenFloaters.clear(); } BOOL LLFloaterView::allChildrenClosed() { - // see if there are any visible floaters (some floaters "close" - // by setting themselves invisible) - for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) - { - LLFloater* floaterp = dynamic_cast(*it); + // see if there are any visible floaters (some floaters "close" + // by setting themselves invisible) + for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) + { + LLFloater* floaterp = dynamic_cast(*it); - if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable()) - { - return false; - } - } - return true; + if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable()) + { + return false; + } + } + return true; } void LLFloaterView::shiftFloaters(S32 x_offset, S32 y_offset) { - for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) - { - LLFloater* floaterp = dynamic_cast(*it); + for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) + { + LLFloater* floaterp = dynamic_cast(*it); - if (floaterp && floaterp->isMinimized()) - { - floaterp->translate(x_offset, y_offset); - } - } + if (floaterp && floaterp->isMinimized()) + { + floaterp->translate(x_offset, y_offset); + } + } } void LLFloaterView::refresh() { - LLRect snap_rect = getSnapRect(); - if (snap_rect != mLastSnapRect) - { - reshape(getRect().getWidth(), getRect().getHeight(), TRUE); - } + LLRect snap_rect = getSnapRect(); + if (snap_rect != mLastSnapRect) + { + reshape(getRect().getWidth(), getRect().getHeight(), TRUE); + } - // Constrain children to be entirely on the screen - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLFloater* floaterp = dynamic_cast(*child_it); - if (floaterp && floaterp->getVisible() ) - { - // minimized floaters are kept fully onscreen - adjustToFitScreen(floaterp, !floaterp->isMinimized()); - } - } + // Constrain children to be entirely on the screen + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLFloater* floaterp = dynamic_cast(*child_it); + if (floaterp && floaterp->getVisible() ) + { + // minimized floaters are kept fully onscreen + adjustToFitScreen(floaterp, !floaterp->isMinimized()); + } + } } void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars/* = false*/) { - if (floater->getParent() != this) - { - // floater is hosted elsewhere, so ignore - return; - } - - if (floater->getDependee() && - floater->getDependee() == floater->getSnapTarget().get()) - { - // floater depends on other and snaps to it, so ignore - return; - } - - LLRect::tCoordType screen_width = getSnapRect().getWidth(); - LLRect::tCoordType screen_height = getSnapRect().getHeight(); - - // only automatically resize non-minimized, resizable floaters - if( floater->isResizable() && !floater->isMinimized() ) - { - LLRect view_rect = floater->getRect(); - S32 old_width = view_rect.getWidth(); - S32 old_height = view_rect.getHeight(); - S32 min_width; - S32 min_height; - floater->getResizeLimits( &min_width, &min_height ); - - // Make sure floater isn't already smaller than its min height/width? - S32 new_width = llmax( min_width, old_width ); - S32 new_height = llmax( min_height, old_height); - - if((new_width > screen_width) || (new_height > screen_height)) - { - // We have to make this window able to fit on screen - new_width = llmin(new_width, screen_width); - new_height = llmin(new_height, screen_height); - - // ...while respecting minimum width/height - new_width = llmax(new_width, min_width); - new_height = llmax(new_height, min_height); - - LLRect new_rect; - new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height); - - floater->setShape(new_rect); - - if (floater->followsRight()) - { - floater->translate(old_width - new_width, 0); - } - - if (floater->followsTop()) - { - floater->translate(0, old_height - new_height); - } - } - } + if (floater->getParent() != this) + { + // floater is hosted elsewhere, so ignore + return; + } + + if (floater->getDependee() && + floater->getDependee() == floater->getSnapTarget().get()) + { + // floater depends on other and snaps to it, so ignore + return; + } + + LLRect::tCoordType screen_width = getSnapRect().getWidth(); + LLRect::tCoordType screen_height = getSnapRect().getHeight(); + + // only automatically resize non-minimized, resizable floaters + if( floater->isResizable() && !floater->isMinimized() ) + { + LLRect view_rect = floater->getRect(); + S32 old_width = view_rect.getWidth(); + S32 old_height = view_rect.getHeight(); + S32 min_width; + S32 min_height; + floater->getResizeLimits( &min_width, &min_height ); + + // Make sure floater isn't already smaller than its min height/width? + S32 new_width = llmax( min_width, old_width ); + S32 new_height = llmax( min_height, old_height); + + if((new_width > screen_width) || (new_height > screen_height)) + { + // We have to make this window able to fit on screen + new_width = llmin(new_width, screen_width); + new_height = llmin(new_height, screen_height); + + // ...while respecting minimum width/height + new_width = llmax(new_width, min_width); + new_height = llmax(new_height, min_height); + + LLRect new_rect; + new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height); + + floater->setShape(new_rect); + + if (floater->followsRight()) + { + floater->translate(old_width - new_width, 0); + } + + if (floater->followsTop()) + { + floater->translate(0, old_height - new_height); + } + } + } const LLRect& constraint = snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(); S32 min_overlap_pixels = allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX; - floater->fitWithDependentsOnScreen(mToolbarLeftRect, mToolbarBottomRect, mToolbarRightRect, constraint, min_overlap_pixels); + floater->fitWithDependentsOnScreen(mToolbarLeftRect, mToolbarBottomRect, mToolbarRightRect, constraint, min_overlap_pixels); } void LLFloaterView::draw() { - refresh(); + refresh(); - // hide focused floater if in cycle mode, so that it can be drawn on top - LLFloater* focused_floater = getFocusedFloater(); + // hide focused floater if in cycle mode, so that it can be drawn on top + LLFloater* focused_floater = getFocusedFloater(); - if (mFocusCycleMode && focused_floater) - { - child_list_const_iter_t child_it = getChildList()->begin(); - for (;child_it != getChildList()->end(); ++child_it) - { - if ((*child_it) != focused_floater) - { - drawChild(*child_it); - } - } + if (mFocusCycleMode && focused_floater) + { + child_list_const_iter_t child_it = getChildList()->begin(); + for (;child_it != getChildList()->end(); ++child_it) + { + if ((*child_it) != focused_floater) + { + drawChild(*child_it); + } + } - drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET); - } - else - { - LLView::draw(); - } + drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET); + } + else + { + LLView::draw(); + } } LLRect LLFloaterView::getSnapRect() const { - LLRect snap_rect = getLocalRect(); + LLRect snap_rect = getLocalRect(); - LLView* snap_view = mSnapView.get(); - if (snap_view) - { - snap_view->localRectToOtherView(snap_view->getLocalRect(), &snap_rect, this); - } + LLView* snap_view = mSnapView.get(); + if (snap_view) + { + snap_view->localRectToOtherView(snap_view->getLocalRect(), &snap_rect, this); + } - return snap_rect; + return snap_rect; } LLFloater *LLFloaterView::getFocusedFloater() const { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - if ((*child_it)->isCtrl()) - { - LLFloater* ctrlp = dynamic_cast(*child_it); - if ( ctrlp && ctrlp->hasFocus() ) - { - return ctrlp; - } - } - } - return NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + if ((*child_it)->isCtrl()) + { + LLFloater* ctrlp = dynamic_cast(*child_it); + if ( ctrlp && ctrlp->hasFocus() ) + { + return ctrlp; + } + } + } + return NULL; } LLFloater *LLFloaterView::getFrontmost() const { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if ( viewp->getVisible() && !viewp->isDead()) - { - return (LLFloater *)viewp; - } - } - return NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if ( viewp->getVisible() && !viewp->isDead()) + { + return (LLFloater *)viewp; + } + } + return NULL; } LLFloater *LLFloaterView::getBackmost() const { - LLFloater* back_most = NULL; - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if ( viewp->getVisible() ) - { - back_most = (LLFloater *)viewp; - } - } - return back_most; + LLFloater* back_most = NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if ( viewp->getVisible() ) + { + back_most = (LLFloater *)viewp; + } + } + return back_most; } void LLFloaterView::syncFloaterTabOrder() { LLFloater* front_child = mFrontChildHandle.get(); - if (front_child && front_child->getIsChrome()) - return; - - // look for a visible modal dialog, starting from first - LLModalDialog* modal_dialog = NULL; - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLModalDialog* dialog = dynamic_cast(*child_it); - if (dialog && dialog->isModal() && dialog->getVisible()) - { - modal_dialog = dialog; - break; - } - } - - if (modal_dialog) - { - // If we have a visible modal dialog, make sure that it has focus - LLUI::getInstance()->addPopup(modal_dialog); - - if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) ) - { - modal_dialog->setFocus(TRUE); - } - - if( !gFocusMgr.childHasMouseCapture( modal_dialog ) ) - { - gFocusMgr.setMouseCapture( modal_dialog ); - } - } - else - { - // otherwise, make sure the focused floater is in the front of the child list - for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) - { - LLFloater* floaterp = dynamic_cast(*child_it); - if (gFocusMgr.childHasKeyboardFocus(floaterp)) - { + if (front_child && front_child->getIsChrome()) + return; + + // look for a visible modal dialog, starting from first + LLModalDialog* modal_dialog = NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLModalDialog* dialog = dynamic_cast(*child_it); + if (dialog && dialog->isModal() && dialog->getVisible()) + { + modal_dialog = dialog; + break; + } + } + + if (modal_dialog) + { + // If we have a visible modal dialog, make sure that it has focus + LLUI::getInstance()->addPopup(modal_dialog); + + if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) ) + { + modal_dialog->setFocus(TRUE); + } + + if( !gFocusMgr.childHasMouseCapture( modal_dialog ) ) + { + gFocusMgr.setMouseCapture( modal_dialog ); + } + } + else + { + // otherwise, make sure the focused floater is in the front of the child list + for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) + { + LLFloater* floaterp = dynamic_cast(*child_it); + if (gFocusMgr.childHasKeyboardFocus(floaterp)) + { LLFloater* front_child = mFrontChildHandle.get(); if (front_child != floaterp) { // Grab a list of the top floaters that want to stay on top of the focused floater - std::list listTop; - if (front_child && !front_child->canFocusStealFrontmost()) + std::list listTop; + if (front_child && !front_child->canFocusStealFrontmost()) { for (LLView* childp : *getChildList()) { - LLFloater* child_floaterp = static_cast(childp); + LLFloater* child_floaterp = static_cast(childp); if (child_floaterp->canFocusStealFrontmost()) break; - listTop.push_back(child_floaterp); + listTop.push_back(child_floaterp); } } bringToFront(floaterp, FALSE); // Restore top floaters - if (!listTop.empty()) - { - for (LLView* childp : listTop) - { - sendChildToFront(childp); - } + if (!listTop.empty()) + { + for (LLView* childp : listTop) + { + sendChildToFront(childp); + } mFrontChildHandle = listTop.back()->getHandle(); - } + } } - break; - } - } - } + break; + } + } + } } -LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const +LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const { - LLView* parentp = viewp->getParent(); + LLView* parentp = viewp->getParent(); - while(parentp && parentp != this) - { - viewp = parentp; - parentp = parentp->getParent(); - } + while(parentp && parentp != this) + { + viewp = parentp; + parentp = parentp->getParent(); + } - if (parentp == this) - { - return dynamic_cast(viewp); - } + if (parentp == this) + { + return dynamic_cast(viewp); + } - return NULL; + return NULL; } S32 LLFloaterView::getZOrder(LLFloater* child) { - S32 rv = 0; - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if(viewp == child) - { - break; - } - ++rv; - } - return rv; + S32 rv = 0; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if(viewp == child) + { + break; + } + ++rv; + } + return rv; } void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list) { - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *view = *child_iter; - if (skip_list.find(view) == skip_list.end()) - { - view->pushVisible(visible); - } - } + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *view = *child_iter; + if (skip_list.find(view) == skip_list.end()) + { + view->pushVisible(visible); + } + } - LLFloaterReg::blockShowFloaters(true); + LLFloaterReg::blockShowFloaters(true); } void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) { - // make a copy of the list since some floaters change their - // order in the childList when changing visibility. - child_list_t child_list_copy = *getChildList(); + // make a copy of the list since some floaters change their + // order in the childList when changing visibility. + child_list_t child_list_copy = *getChildList(); - for (child_list_const_iter_t child_iter = child_list_copy.begin(); - child_iter != child_list_copy.end(); ++child_iter) - { - LLView *view = *child_iter; - if (skip_list.find(view) == skip_list.end()) - { - view->popVisible(); - } - } + for (child_list_const_iter_t child_iter = child_list_copy.begin(); + child_iter != child_list_copy.end(); ++child_iter) + { + LLView *view = *child_iter; + if (skip_list.find(view) == skip_list.end()) + { + view->popVisible(); + } + } - LLFloaterReg::blockShowFloaters(false); + LLFloaterReg::blockShowFloaters(false); } void LLFloaterView::setToolbarRect(LLToolBarEnums::EToolBarLocation tb, const LLRect& toolbar_rect) { - switch (tb) - { - case LLToolBarEnums::TOOLBAR_LEFT: - mToolbarLeftRect = toolbar_rect; - break; - case LLToolBarEnums::TOOLBAR_BOTTOM: - mToolbarBottomRect = toolbar_rect; - break; - case LLToolBarEnums::TOOLBAR_RIGHT: - mToolbarRightRect = toolbar_rect; - break; - default: - LL_WARNS() << "setToolbarRect() passed odd toolbar number " << (S32) tb << LL_ENDL; - break; - } + switch (tb) + { + case LLToolBarEnums::TOOLBAR_LEFT: + mToolbarLeftRect = toolbar_rect; + break; + case LLToolBarEnums::TOOLBAR_BOTTOM: + mToolbarBottomRect = toolbar_rect; + break; + case LLToolBarEnums::TOOLBAR_RIGHT: + mToolbarRightRect = toolbar_rect; + break; + default: + LL_WARNS() << "setToolbarRect() passed odd toolbar number " << (S32) tb << LL_ENDL; + break; + } } void LLFloater::setInstanceName(const std::string& name) { - if (name != mInstanceName) - { - llassert_always(mInstanceName.empty()); - mInstanceName = name; - if (!mInstanceName.empty()) - { - std::string ctrl_name = getControlName(mInstanceName, mKey); - initRectControl(); - if (!mVisibilityControl.empty()) - { - mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); - } - if(!mDocStateControl.empty()) - { - mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); - } - } + if (name != mInstanceName) + { + llassert_always(mInstanceName.empty()); + mInstanceName = name; + if (!mInstanceName.empty()) + { + std::string ctrl_name = getControlName(mInstanceName, mKey); + initRectControl(); + if (!mVisibilityControl.empty()) + { + mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); + } + if(!mDocStateControl.empty()) + { + mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); + } + } } } void LLFloater::setKey(const LLSD& newkey) { - // Note: We don't have to do anything special with registration when we change keys - mKey = newkey; + // Note: We don't have to do anything special with registration when we change keys + mKey = newkey; } //static void LLFloater::setupParamsForExport(Params& p, LLView* parent) { - // Do rectangle munging to topleft layout first - LLPanel::setupParamsForExport(p, parent); + // Do rectangle munging to topleft layout first + LLPanel::setupParamsForExport(p, parent); - // Copy the rectangle out to apply layout constraints - LLRect rect = p.rect; + // Copy the rectangle out to apply layout constraints + LLRect rect = p.rect; - // Null out other settings - p.rect.left.setProvided(false); - p.rect.top.setProvided(false); - p.rect.right.setProvided(false); - p.rect.bottom.setProvided(false); + // Null out other settings + p.rect.left.setProvided(false); + p.rect.top.setProvided(false); + p.rect.right.setProvided(false); + p.rect.bottom.setProvided(false); - // Explicitly set width/height - p.rect.width.set( rect.getWidth(), true ); - p.rect.height.set( rect.getHeight(), true ); + // Explicitly set width/height + p.rect.width.set( rect.getWidth(), true ); + p.rect.height.set( rect.getHeight(), true ); - // If you can't resize this floater, don't export min_height - // and min_width - bool can_resize = p.can_resize; - if (!can_resize) - { - p.min_height.setProvided(false); - p.min_width.setProvided(false); - } + // If you can't resize this floater, don't export min_height + // and min_width + bool can_resize = p.can_resize; + if (!can_resize) + { + p.min_height.setProvided(false); + p.min_width.setProvided(false); + } } void LLFloater::initFromParams(const LLFloater::Params& p) { - // *NOTE: We have too many classes derived from LLFloater to retrofit them - // all to pass in params via constructors. So we use this method. - - // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible - LLPanel::initFromParams(p); - - // override any follows flags - if (mPositioning != LLFloaterEnums::POSITIONING_SPECIFIED) - { - setFollows(FOLLOWS_NONE); - } - - mTitle = p.title; - mShortTitle = p.short_title; - applyTitle(); - - setCanTearOff(p.can_tear_off); - setCanMinimize(p.can_minimize); - setCanClose(p.can_close); - setCanDock(p.can_dock); - setCanResize(p.can_resize); - setResizeLimits(p.min_width, p.min_height); - - mDragOnLeft = p.can_drag_on_left; - mHeaderHeight = p.header_height; - mLegacyHeaderHeight = p.legacy_header_height; - mSingleInstance = p.single_instance; - mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance; - - mDefaultRelativeX = p.rel_x; - mDefaultRelativeY = p.rel_y; - - mPositioning = p.positioning; - mAutoClose = p.auto_close; - - mSaveRect = p.save_rect; - if (p.save_visibility) - { - mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set - } - if(p.save_dock_state) - { - mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set - } - - // open callback - if (p.open_callback.isProvided()) - { - setOpenCallback(initCommitCallback(p.open_callback)); - } - // close callback - if (p.close_callback.isProvided()) - { - setCloseCallback(initCommitCallback(p.close_callback)); - } - - if (mDragHandle) - { - mDragHandle->setTitleVisible(p.show_title); - } -} - -boost::signals2::connection LLFloater::setMinimizeCallback( const commit_signal_t::slot_type& cb ) -{ - if (!mMinimizeSignal) mMinimizeSignal = new commit_signal_t(); - return mMinimizeSignal->connect(cb); + // *NOTE: We have too many classes derived from LLFloater to retrofit them + // all to pass in params via constructors. So we use this method. + + // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible + LLPanel::initFromParams(p); + + // override any follows flags + if (mPositioning != LLFloaterEnums::POSITIONING_SPECIFIED) + { + setFollows(FOLLOWS_NONE); + } + + mTitle = p.title; + mShortTitle = p.short_title; + applyTitle(); + + setCanTearOff(p.can_tear_off); + setCanMinimize(p.can_minimize); + setCanClose(p.can_close); + setCanDock(p.can_dock); + setCanResize(p.can_resize); + setResizeLimits(p.min_width, p.min_height); + + mDragOnLeft = p.can_drag_on_left; + mHeaderHeight = p.header_height; + mLegacyHeaderHeight = p.legacy_header_height; + mSingleInstance = p.single_instance; + mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance; + + mDefaultRelativeX = p.rel_x; + mDefaultRelativeY = p.rel_y; + + mPositioning = p.positioning; + mAutoClose = p.auto_close; + + mSaveRect = p.save_rect; + if (p.save_visibility) + { + mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set + } + if(p.save_dock_state) + { + mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set + } + + // open callback + if (p.open_callback.isProvided()) + { + setOpenCallback(initCommitCallback(p.open_callback)); + } + // close callback + if (p.close_callback.isProvided()) + { + setCloseCallback(initCommitCallback(p.close_callback)); + } + + if (mDragHandle) + { + mDragHandle->setTitleVisible(p.show_title); + } +} + +boost::signals2::connection LLFloater::setMinimizeCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMinimizeSignal) mMinimizeSignal = new commit_signal_t(); + return mMinimizeSignal->connect(cb); } boost::signals2::connection LLFloater::setOpenCallback( const commit_signal_t::slot_type& cb ) { - return mOpenSignal.connect(cb); + return mOpenSignal.connect(cb); } boost::signals2::connection LLFloater::setCloseCallback( const commit_signal_t::slot_type& cb ) { - return mCloseSignal.connect(cb); + return mCloseSignal.connect(cb); } bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node) { LL_PROFILE_ZONE_SCOPED; - Params default_params(LLUICtrlFactory::getDefaultParams()); - Params params(default_params); - - LLXUIParser parser; - parser.readXUI(node, params, filename); // *TODO: Error checking - - std::string xml_filename = params.filename; - - if (!xml_filename.empty()) - { - LLXMLNodePtr referenced_xml; - - if (output_node) - { - //if we are exporting, we want to export the current xml - //not the referenced xml - Params output_params; - parser.readXUI(node, output_params, LLUICtrlFactory::getInstance()->getCurFileName()); - setupParamsForExport(output_params, parent); - output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); - return TRUE; - } - - LLUICtrlFactory::instance().pushFileName(xml_filename); - - if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml)) - { - LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL; - - return FALSE; - } - - Params referenced_params; - parser.readXUI(referenced_xml, referenced_params, LLUICtrlFactory::getInstance()->getCurFileName()); - params.fillFrom(referenced_params); - - // add children using dimensions from referenced xml for consistent layout - setShape(params.rect); - LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); - - LLUICtrlFactory::instance().popFileName(); - } - - - if (output_node) - { - Params output_params(params); - setupParamsForExport(output_params, parent); - output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); - } - - // Default floater position to top-left corner of screen - // However, some legacy floaters have explicit top or bottom - // coordinates set, so respect their wishes. - if (!params.rect.top.isProvided() && !params.rect.bottom.isProvided()) - { - params.rect.top.set(0); - } - if (!params.rect.left.isProvided() && !params.rect.right.isProvided()) - { - params.rect.left.set(0); - } - params.from_xui = true; - applyXUILayout(params, parent, parent == gFloaterView ? gFloaterView->getSnapRect() : parent->getLocalRect()); - initFromParams(params); - - initFloater(params); - - LLMultiFloater* last_host = LLFloater::getFloaterHost(); - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost((LLMultiFloater*) this); - } - - LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node); - - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost(last_host); - } - - // HACK: When we changed the header height to 25 pixels in Viewer 2, rather - // than re-layout all the floaters we use this value in pixels to make the - // whole floater bigger and change the top-left coordinate for widgets. - // The goal is to eventually set mLegacyHeaderHeight to zero, which would - // make the top-left corner for widget layout the same as the top-left - // corner of the window's content area. James - S32 header_stretch = (mHeaderHeight - mLegacyHeaderHeight); - if (header_stretch > 0) - { - // Stretch the floater vertically, don't move widgets - LLRect rect = getRect(); - rect.mTop += header_stretch; - - // This will also update drag handle, title bar, close box, etc. - setRect(rect); - } - - BOOL result; - result = postBuild(); - - if (!result) - { - LL_ERRS() << "Failed to construct floater " << getName() << LL_ENDL; - } - - applyRectControl(); // If we have a saved rect control, apply it - gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen - - moveResizeHandlesToFront(); - - applyDockState(); - - return true; // *TODO: Error checking + Params default_params(LLUICtrlFactory::getDefaultParams()); + Params params(default_params); + + LLXUIParser parser; + parser.readXUI(node, params, filename); // *TODO: Error checking + + std::string xml_filename = params.filename; + + if (!xml_filename.empty()) + { + LLXMLNodePtr referenced_xml; + + if (output_node) + { + //if we are exporting, we want to export the current xml + //not the referenced xml + Params output_params; + parser.readXUI(node, output_params, LLUICtrlFactory::getInstance()->getCurFileName()); + setupParamsForExport(output_params, parent); + output_node->setName(node->getName()->mString); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); + return TRUE; + } + + LLUICtrlFactory::instance().pushFileName(xml_filename); + + if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml)) + { + LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL; + + return FALSE; + } + + Params referenced_params; + parser.readXUI(referenced_xml, referenced_params, LLUICtrlFactory::getInstance()->getCurFileName()); + params.fillFrom(referenced_params); + + // add children using dimensions from referenced xml for consistent layout + setShape(params.rect); + LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); + + LLUICtrlFactory::instance().popFileName(); + } + + + if (output_node) + { + Params output_params(params); + setupParamsForExport(output_params, parent); + output_node->setName(node->getName()->mString); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); + } + + // Default floater position to top-left corner of screen + // However, some legacy floaters have explicit top or bottom + // coordinates set, so respect their wishes. + if (!params.rect.top.isProvided() && !params.rect.bottom.isProvided()) + { + params.rect.top.set(0); + } + if (!params.rect.left.isProvided() && !params.rect.right.isProvided()) + { + params.rect.left.set(0); + } + params.from_xui = true; + applyXUILayout(params, parent, parent == gFloaterView ? gFloaterView->getSnapRect() : parent->getLocalRect()); + initFromParams(params); + + initFloater(params); + + LLMultiFloater* last_host = LLFloater::getFloaterHost(); + if (node->hasName("multi_floater")) + { + LLFloater::setFloaterHost((LLMultiFloater*) this); + } + + LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node); + + if (node->hasName("multi_floater")) + { + LLFloater::setFloaterHost(last_host); + } + + // HACK: When we changed the header height to 25 pixels in Viewer 2, rather + // than re-layout all the floaters we use this value in pixels to make the + // whole floater bigger and change the top-left coordinate for widgets. + // The goal is to eventually set mLegacyHeaderHeight to zero, which would + // make the top-left corner for widget layout the same as the top-left + // corner of the window's content area. James + S32 header_stretch = (mHeaderHeight - mLegacyHeaderHeight); + if (header_stretch > 0) + { + // Stretch the floater vertically, don't move widgets + LLRect rect = getRect(); + rect.mTop += header_stretch; + + // This will also update drag handle, title bar, close box, etc. + setRect(rect); + } + + BOOL result; + result = postBuild(); + + if (!result) + { + LL_ERRS() << "Failed to construct floater " << getName() << LL_ENDL; + } + + applyRectControl(); // If we have a saved rect control, apply it + gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen + + moveResizeHandlesToFront(); + + applyDockState(); + + return true; // *TODO: Error checking } bool LLFloater::isShown() const @@ -3501,7 +3501,7 @@ bool LLFloater::isShown() const bool LLFloater::isDetachedAndNotMinimized() { - return !getHost() && !isMinimized(); + return !getHost() && !isMinimized(); } /* static */ @@ -3525,211 +3525,211 @@ bool LLFloater::isVisible(const LLFloater* floater) bool LLFloater::buildFromFile(const std::string& filename) { LL_PROFILE_ZONE_SCOPED; - LLXMLNodePtr root; - - if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) - { - LL_WARNS() << "Couldn't find (or parse) floater from: " << filename << LL_ENDL; - return false; - } - - // root must be called floater - if( !(root->hasName("floater") || root->hasName("multi_floater")) ) - { - LL_WARNS() << "Root node should be named floater in: " << filename << LL_ENDL; - return false; - } - - bool res = true; - - LL_DEBUGS() << "Building floater " << filename << LL_ENDL; - LLUICtrlFactory::instance().pushFileName(filename); - { - if (!getFactoryMap().empty()) - { - LLPanel::sFactoryStack.push_front(&getFactoryMap()); - } - - // for local registry callbacks; define in constructor, referenced in XUI or postBuild - getCommitCallbackRegistrar().pushScope(); - getEnableCallbackRegistrar().pushScope(); - - res = initFloaterXML(root, getParent(), filename, NULL); - - setXMLFilename(filename); - - getCommitCallbackRegistrar().popScope(); - getEnableCallbackRegistrar().popScope(); - - if (!getFactoryMap().empty()) - { - LLPanel::sFactoryStack.pop_front(); - } - } - LLUICtrlFactory::instance().popFileName(); - - return res; + LLXMLNodePtr root; + + if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) + { + LL_WARNS() << "Couldn't find (or parse) floater from: " << filename << LL_ENDL; + return false; + } + + // root must be called floater + if( !(root->hasName("floater") || root->hasName("multi_floater")) ) + { + LL_WARNS() << "Root node should be named floater in: " << filename << LL_ENDL; + return false; + } + + bool res = true; + + LL_DEBUGS() << "Building floater " << filename << LL_ENDL; + LLUICtrlFactory::instance().pushFileName(filename); + { + if (!getFactoryMap().empty()) + { + LLPanel::sFactoryStack.push_front(&getFactoryMap()); + } + + // for local registry callbacks; define in constructor, referenced in XUI or postBuild + getCommitCallbackRegistrar().pushScope(); + getEnableCallbackRegistrar().pushScope(); + + res = initFloaterXML(root, getParent(), filename, NULL); + + setXMLFilename(filename); + + getCommitCallbackRegistrar().popScope(); + getEnableCallbackRegistrar().popScope(); + + if (!getFactoryMap().empty()) + { + LLPanel::sFactoryStack.pop_front(); + } + } + LLUICtrlFactory::instance().popFileName(); + + return res; } void LLFloater::stackWith(LLFloater& other) { - static LLUICachedControl floater_offset ("UIFloaterOffset", 16); - - LLRect next_rect; - if (other.getHost()) - { - next_rect = other.getHost()->getRect(); - } - else - { - next_rect = other.getRect(); - } - next_rect.translate(floater_offset, -floater_offset); - - 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()) - { - other.mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; - other.setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); - } + static LLUICachedControl floater_offset ("UIFloaterOffset", 16); + + LLRect next_rect; + if (other.getHost()) + { + next_rect = other.getHost()->getRect(); + } + else + { + next_rect = other.getRect(); + } + next_rect.translate(floater_offset, -floater_offset); + + 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()) + { + other.mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; + other.setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); + } } void LLFloater::applyRelativePosition() { - LLRect snap_rect = gFloaterView->getSnapRect(); - LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); - snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); - LLRect floater_screen_rect = calcScreenRect(); + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + LLRect floater_screen_rect = calcScreenRect(); - LLCoordGL new_center = mPosition.convert(); - LLCoordGL cur_center(floater_screen_rect.getCenterX(), floater_screen_rect.getCenterY()); - translate(new_center.mX - cur_center.mX, new_center.mY - cur_center.mY); + LLCoordGL new_center = mPosition.convert(); + LLCoordGL cur_center(floater_screen_rect.getCenterX(), floater_screen_rect.getCenterY()); + translate(new_center.mX - cur_center.mX, new_center.mY - cur_center.mY); } LLCoordFloater::LLCoordFloater(F32 x, F32 y, LLFloater& floater) -: coord_t((S32)x, (S32)y) +: coord_t((S32)x, (S32)y) { - mFloater = floater.getHandle(); + mFloater = floater.getHandle(); } LLCoordFloater::LLCoordFloater(const LLCoordCommon& other, LLFloater& floater) { - mFloater = floater.getHandle(); - convertFromCommon(other); + mFloater = floater.getHandle(); + convertFromCommon(other); } LLCoordFloater& LLCoordFloater::operator=(const LLCoordFloater& other) { - mFloater = other.mFloater; - coord_t::operator =(other); - return *this; + mFloater = other.mFloater; + coord_t::operator =(other); + return *this; } void LLCoordFloater::setFloater(LLFloater& floater) { - mFloater = floater.getHandle(); + mFloater = floater.getHandle(); } -bool LLCoordFloater::operator==(const LLCoordFloater& other) const -{ - return mX == other.mX && mY == other.mY && mFloater == other.mFloater; +bool LLCoordFloater::operator==(const LLCoordFloater& other) const +{ + return mX == other.mX && mY == other.mY && mFloater == other.mFloater; } LLCoordCommon LL_COORD_FLOATER::convertToCommon() const { - const LLCoordFloater& self = static_cast(LLCoordFloater::getTypedCoords(*this)); - - LLRect snap_rect = gFloaterView->getSnapRect(); - LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); - snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); - - LLFloater* floaterp = mFloater.get(); - S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; - S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; - LLCoordCommon out; - if (self.mX < -0.5f) - { - out.mX = ll_round(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft)); - } - else if (self.mX > 0.5f) - { - out.mX = ll_round(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS)); - } - else - { - out.mX = ll_round(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width)); - } - - if (self.mY < -0.5f) - { - out.mY = ll_round(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom)); - } - else if (self.mY > 0.5f) - { - out.mY = ll_round(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS)); - } - else - { - out.mY = ll_round(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height)); - } - - // return center point instead of lower left - out.mX += floater_width / 2; - out.mY += floater_height / 2; - - return out; + const LLCoordFloater& self = static_cast(LLCoordFloater::getTypedCoords(*this)); + + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + LLFloater* floaterp = mFloater.get(); + S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; + S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; + LLCoordCommon out; + if (self.mX < -0.5f) + { + out.mX = ll_round(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft)); + } + else if (self.mX > 0.5f) + { + out.mX = ll_round(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS)); + } + else + { + out.mX = ll_round(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width)); + } + + if (self.mY < -0.5f) + { + out.mY = ll_round(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom)); + } + else if (self.mY > 0.5f) + { + out.mY = ll_round(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS)); + } + else + { + out.mY = ll_round(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height)); + } + + // return center point instead of lower left + out.mX += floater_width / 2; + out.mY += floater_height / 2; + + return out; } void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from) { - LLCoordFloater& self = static_cast(LLCoordFloater::getTypedCoords(*this)); - LLRect snap_rect = gFloaterView->getSnapRect(); - LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); - snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); - - - LLFloater* floaterp = mFloater.get(); - S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; - S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; - - S32 from_x = from.mX - floater_width / 2; - S32 from_y = from.mY - floater_height / 2; - - if (from_x < snap_rect.mLeft) - { - self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f); - } - else if (from_x + floater_width > snap_rect.mRight) - { - self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); - } - else - { - self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f); - } - - if (from_y < snap_rect.mBottom) - { - self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f); - } - else if (from_y + floater_height > snap_rect.mTop) - { - self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); - } - else - { - self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f); - } + LLCoordFloater& self = static_cast(LLCoordFloater::getTypedCoords(*this)); + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + + LLFloater* floaterp = mFloater.get(); + S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; + S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; + + S32 from_x = from.mX - floater_width / 2; + S32 from_y = from.mY - floater_height / 2; + + if (from_x < snap_rect.mLeft) + { + self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f); + } + else if (from_x + floater_width > snap_rect.mRight) + { + self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); + } + else + { + self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f); + } + + if (from_y < snap_rect.mBottom) + { + self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f); + } + else if (from_y + floater_height > snap_rect.mTop) + { + self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); + } + else + { + self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f); + } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 39957386df..7fcbd5c5ec 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -1,25 +1,25 @@ -/** +/** * @file llfloater.h * @brief LLFloater base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -63,482 +63,482 @@ const BOOL ADJUST_VERTICAL_NO = FALSE; namespace LLFloaterEnums { - enum EOpenPositioning - { - POSITIONING_RELATIVE, - POSITIONING_CASCADING, - POSITIONING_CASCADE_GROUP, - POSITIONING_CENTERED, - POSITIONING_SPECIFIED, - POSITIONING_COUNT - }; + enum EOpenPositioning + { + POSITIONING_RELATIVE, + POSITIONING_CASCADING, + POSITIONING_CASCADE_GROUP, + POSITIONING_CENTERED, + POSITIONING_SPECIFIED, + POSITIONING_COUNT + }; } namespace LLInitParam { - template<> - struct TypeValues : public TypeValuesHelper - { - static void declareValues(); - }; + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; } struct LL_COORD_FLOATER { - typedef F32 value_t; + typedef F32 value_t; - LLCoordCommon convertToCommon() const; - void convertFromCommon(const LLCoordCommon& from); + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); protected: - LLHandle mFloater; + LLHandle mFloater; }; struct LLCoordFloater : LLCoord { - typedef LLCoord coord_t; + typedef LLCoord coord_t; - LLCoordFloater() {} - LLCoordFloater(F32 x, F32 y, LLFloater& floater); - LLCoordFloater(const LLCoordCommon& other, LLFloater& floater); + LLCoordFloater() {} + LLCoordFloater(F32 x, F32 y, LLFloater& floater); + LLCoordFloater(const LLCoordCommon& other, LLFloater& floater); - LLCoordFloater& operator=(const LLCoordCommon& other) - { - convertFromCommon(other); - return *this; - } + LLCoordFloater& operator=(const LLCoordCommon& other) + { + convertFromCommon(other); + return *this; + } - LLCoordFloater& operator=(const LLCoordFloater& other); + LLCoordFloater& operator=(const LLCoordFloater& other); - bool operator==(const LLCoordFloater& other) const; - bool operator!=(const LLCoordFloater& other) const { return !(*this == other); } + bool operator==(const LLCoordFloater& other) const; + bool operator!=(const LLCoordFloater& other) const { return !(*this == other); } - void setFloater(LLFloater& floater); + void setFloater(LLFloater& floater); }; class LLFloater : public LLPanel, public LLInstanceTracker { - friend class LLFloaterView; - friend class LLFloaterReg; - friend class LLMultiFloater; + friend class LLFloaterView; + friend class LLFloaterReg; + friend class LLMultiFloater; public: - struct KeyCompare - { -// static bool compare(const LLSD& a, const LLSD& b); - static bool equate(const LLSD& a, const LLSD& b); + struct KeyCompare + { +// static bool compare(const LLSD& a, const LLSD& b); + static bool equate(const LLSD& a, const LLSD& b); /*==========================================================================*| - bool operator()(const LLSD& a, const LLSD& b) const - { - return compare(a, b); - } + bool operator()(const LLSD& a, const LLSD& b) const + { + return compare(a, b); + } |*==========================================================================*/ - }; - - enum EFloaterButton - { - BUTTON_CLOSE = 0, - BUTTON_RESTORE, - BUTTON_MINIMIZE, - BUTTON_TEAR_OFF, - BUTTON_DOCK, - BUTTON_HELP, - BUTTON_COUNT - }; - - struct Params - : public LLInitParam::Block - { - Optional title, - short_title; - - Optional single_instance, - reuse_instance, - can_resize, - can_minimize, - can_close, - can_drag_on_left, - can_tear_off, - save_rect, - save_visibility, - save_dock_state, - can_dock, - show_title, - auto_close; - - Optional positioning; - - Optional header_height, - legacy_header_height; // HACK see initFromXML() - - Optional rel_x, - rel_y; - - // Images for top-right controls - Optional close_image, - restore_image, - minimize_image, - tear_off_image, - dock_image, - help_image; - Optional close_pressed_image, - restore_pressed_image, - minimize_pressed_image, - tear_off_pressed_image, - dock_pressed_image, - help_pressed_image; - - Optional open_callback, - close_callback; - - Ignored follows; - - Params(); - }; - - // use this to avoid creating your own default LLFloater::Param instance - static const Params& getDefaultParams(); - - // Load translations for tooltips for standard buttons - static void initClass(); - - LLFloater(const LLSD& key, const Params& params = getDefaultParams()); - - virtual ~LLFloater(); - - // Don't export top/left for rect, only height/width - static void setupParamsForExport(Params& p, LLView* parent); - bool buildFromFile(const std::string &filename); - - boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb ); - boost::signals2::connection setOpenCallback( const commit_signal_t::slot_type& cb ); - boost::signals2::connection setCloseCallback( const commit_signal_t::slot_type& cb ); - - void initFromParams(const LLFloater::Params& p); - bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL); - - /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); - /*virtual*/ BOOL canSnapTo(const LLView* other_view); - /*virtual*/ void setSnappedTo(const LLView* snap_view); - /*virtual*/ void setFocus( BOOL b ); - /*virtual*/ void setIsChrome(BOOL is_chrome); - /*virtual*/ void setRect(const LLRect &rect); + }; + + enum EFloaterButton + { + BUTTON_CLOSE = 0, + BUTTON_RESTORE, + BUTTON_MINIMIZE, + BUTTON_TEAR_OFF, + BUTTON_DOCK, + BUTTON_HELP, + BUTTON_COUNT + }; + + struct Params + : public LLInitParam::Block + { + Optional title, + short_title; + + Optional single_instance, + reuse_instance, + can_resize, + can_minimize, + can_close, + can_drag_on_left, + can_tear_off, + save_rect, + save_visibility, + save_dock_state, + can_dock, + show_title, + auto_close; + + Optional positioning; + + Optional header_height, + legacy_header_height; // HACK see initFromXML() + + Optional rel_x, + rel_y; + + // Images for top-right controls + Optional close_image, + restore_image, + minimize_image, + tear_off_image, + dock_image, + help_image; + Optional close_pressed_image, + restore_pressed_image, + minimize_pressed_image, + tear_off_pressed_image, + dock_pressed_image, + help_pressed_image; + + Optional open_callback, + close_callback; + + Ignored follows; + + Params(); + }; + + // use this to avoid creating your own default LLFloater::Param instance + static const Params& getDefaultParams(); + + // Load translations for tooltips for standard buttons + static void initClass(); + + LLFloater(const LLSD& key, const Params& params = getDefaultParams()); + + virtual ~LLFloater(); + + // Don't export top/left for rect, only height/width + static void setupParamsForExport(Params& p, LLView* parent); + bool buildFromFile(const std::string &filename); + + boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setOpenCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setCloseCallback( const commit_signal_t::slot_type& cb ); + + void initFromParams(const LLFloater::Params& p); + bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL); + + /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); + /*virtual*/ BOOL canSnapTo(const LLView* other_view); + /*virtual*/ void setSnappedTo(const LLView* snap_view); + /*virtual*/ void setFocus( BOOL b ); + /*virtual*/ void setIsChrome(BOOL is_chrome); + /*virtual*/ void setRect(const LLRect &rect); void setIsSingleInstance(BOOL is_single_instance); BOOL getIsSingleInstance() { return mSingleInstance; } - void initFloater(const Params& p); - - void openFloater(const LLSD& key = LLSD()); - - // If allowed, close the floater cleanly, releasing focus. - virtual void closeFloater(bool app_quitting = false); - - // Close the floater or its host. Use when hidding or toggling a floater instance. - virtual void closeHostedFloater(); - - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void translate(S32 x, S32 y); - - // Release keyboard and mouse focus - void releaseFocus(); - - // moves to center of gFloaterView - void center(); - - LLMultiFloater* getHost(); - bool isDetachedAndNotMinimized(); - - void applyTitle(); - std::string getCurrentTitle() const; - void setTitle( const std::string& title); - std::string getTitle() const; - void setShortTitle( const std::string& short_title ); - std::string getShortTitle() const; - virtual void setMinimized(BOOL b); - void moveResizeHandlesToFront(); - void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE, BOOL resize = FALSE); - void addDependentFloater(LLHandle dependent_handle, BOOL reposition = TRUE, BOOL resize = FALSE); - LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } - void removeDependentFloater(LLFloater* dependent); - void fitWithDependentsOnScreen(const LLRect& left, const LLRect& bottom, const LLRect& right, const LLRect& constraint, S32 min_overlap_pixels); - BOOL isMinimized() const { return mMinimized; } - /// isShown() differs from getVisible() in that isShown() also considers - /// isMinimized(). isShown() is true only if visible and not minimized. - bool isShown() const; - /// The static isShown() can accept a NULL pointer (which of course - /// returns false). When non-NULL, it calls the non-static isShown(). - static bool isShown(const LLFloater* floater); - static bool isVisible(const LLFloater* floater); - static bool isMinimized(const LLFloater* floater); - BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts - virtual BOOL isFrontmost(); - BOOL isDependent() { return !mDependeeHandle.isDead(); } - void setCanMinimize(BOOL can_minimize); - void setCanClose(BOOL can_close); - void setCanTearOff(BOOL can_tear_off); - virtual void setCanResize(BOOL can_resize); - void setCanDrag(BOOL can_drag); - bool getCanDrag(); - void setHost(LLMultiFloater* host); - BOOL isResizable() const { return mResizable; } - void setResizeLimits( S32 min_width, S32 min_height ); - void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } - - static std::string getControlName(const std::string& name, const LLSD& key); - static LLControlGroup* getControlGroup(); - - bool isMinimizeable() const{ return mCanMinimize; } - bool isCloseable() const{ return mCanClose; } - bool isDragOnLeft() const{ return mDragOnLeft; } - S32 getMinWidth() const{ return mMinWidth; } - S32 getMinHeight() const{ return mMinHeight; } - S32 getHeaderHeight() const { return mHeaderHeight; } - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); - - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask); - - virtual void draw(); - virtual void drawShadow(LLPanel* panel); - - virtual void onOpen(const LLSD& key) {} - virtual void onClose(bool app_quitting) {} - - // This cannot be "const" until all derived floater canClose() - // methods are const as well. JC - virtual BOOL canClose() { return TRUE; } - - /*virtual*/ void setVisible(BOOL visible); // do not override - /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override - - bool canFocusStealFrontmost() const { return mFocusStealsFrontmost; } - void setFocusStealsFrontmost(bool wants_frontmost) { mFocusStealsFrontmost = wants_frontmost; } - - void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE); - virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); - - // Defaults to false. - virtual BOOL canSaveAs() const { return FALSE; } - - virtual void saveAs() {} - - void setSnapTarget(LLHandle handle) { mSnappedTo = handle; } - void clearSnapTarget() { mSnappedTo.markDead(); } - LLHandle getSnapTarget() const { return mSnappedTo; } - - LLHandle getHandle() const { return getDerivedHandle(); } - const LLSD& getKey() { return mKey; } - virtual bool matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } - - const std::string& getInstanceName() { return mInstanceName; } - - bool isDockable() const { return mCanDock; } - void setCanDock(bool b); - - bool isDocked() const { return mDocked; } - virtual void setDocked(bool docked, bool pop_on_undock = true); - - virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } - bool isTornOff() {return mTornOff;} - void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;} - - - // Close the floater returned by getFrontmostClosableFloater() and - // handle refocusing. - static void closeFrontmostFloater(); + void initFloater(const Params& p); + + void openFloater(const LLSD& key = LLSD()); + + // If allowed, close the floater cleanly, releasing focus. + virtual void closeFloater(bool app_quitting = false); + + // Close the floater or its host. Use when hidding or toggling a floater instance. + virtual void closeHostedFloater(); + + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void translate(S32 x, S32 y); + + // Release keyboard and mouse focus + void releaseFocus(); + + // moves to center of gFloaterView + void center(); + + LLMultiFloater* getHost(); + bool isDetachedAndNotMinimized(); + + void applyTitle(); + std::string getCurrentTitle() const; + void setTitle( const std::string& title); + std::string getTitle() const; + void setShortTitle( const std::string& short_title ); + std::string getShortTitle() const; + virtual void setMinimized(BOOL b); + void moveResizeHandlesToFront(); + void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE, BOOL resize = FALSE); + void addDependentFloater(LLHandle dependent_handle, BOOL reposition = TRUE, BOOL resize = FALSE); + LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } + void removeDependentFloater(LLFloater* dependent); + void fitWithDependentsOnScreen(const LLRect& left, const LLRect& bottom, const LLRect& right, const LLRect& constraint, S32 min_overlap_pixels); + BOOL isMinimized() const { return mMinimized; } + /// isShown() differs from getVisible() in that isShown() also considers + /// isMinimized(). isShown() is true only if visible and not minimized. + bool isShown() const; + /// The static isShown() can accept a NULL pointer (which of course + /// returns false). When non-NULL, it calls the non-static isShown(). + static bool isShown(const LLFloater* floater); + static bool isVisible(const LLFloater* floater); + static bool isMinimized(const LLFloater* floater); + BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts + virtual BOOL isFrontmost(); + BOOL isDependent() { return !mDependeeHandle.isDead(); } + void setCanMinimize(BOOL can_minimize); + void setCanClose(BOOL can_close); + void setCanTearOff(BOOL can_tear_off); + virtual void setCanResize(BOOL can_resize); + void setCanDrag(BOOL can_drag); + bool getCanDrag(); + void setHost(LLMultiFloater* host); + BOOL isResizable() const { return mResizable; } + void setResizeLimits( S32 min_width, S32 min_height ); + void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } + + static std::string getControlName(const std::string& name, const LLSD& key); + static LLControlGroup* getControlGroup(); + + bool isMinimizeable() const{ return mCanMinimize; } + bool isCloseable() const{ return mCanClose; } + bool isDragOnLeft() const{ return mDragOnLeft; } + S32 getMinWidth() const{ return mMinWidth; } + S32 getMinHeight() const{ return mMinHeight; } + S32 getHeaderHeight() const { return mHeaderHeight; } + + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); + + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask); + + virtual void draw(); + virtual void drawShadow(LLPanel* panel); + + virtual void onOpen(const LLSD& key) {} + virtual void onClose(bool app_quitting) {} + + // This cannot be "const" until all derived floater canClose() + // methods are const as well. JC + virtual BOOL canClose() { return TRUE; } + + /*virtual*/ void setVisible(BOOL visible); // do not override + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override + + bool canFocusStealFrontmost() const { return mFocusStealsFrontmost; } + void setFocusStealsFrontmost(bool wants_frontmost) { mFocusStealsFrontmost = wants_frontmost; } + + void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE); + virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); + + // Defaults to false. + virtual BOOL canSaveAs() const { return FALSE; } + + virtual void saveAs() {} + + void setSnapTarget(LLHandle handle) { mSnappedTo = handle; } + void clearSnapTarget() { mSnappedTo.markDead(); } + LLHandle getSnapTarget() const { return mSnappedTo; } + + LLHandle getHandle() const { return getDerivedHandle(); } + const LLSD& getKey() { return mKey; } + virtual bool matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } + + const std::string& getInstanceName() { return mInstanceName; } + + bool isDockable() const { return mCanDock; } + void setCanDock(bool b); + + bool isDocked() const { return mDocked; } + virtual void setDocked(bool docked, bool pop_on_undock = true); + + virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } + bool isTornOff() {return mTornOff;} + void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;} + + + // Close the floater returned by getFrontmostClosableFloater() and + // handle refocusing. + static void closeFrontmostFloater(); static bool isQuitRequested() { return sQuitting; } -// LLNotification::Params contextualNotification(const std::string& name) -// { -// return LLNotification::Params(name).context(mNotificationContext); -// } +// LLNotification::Params contextualNotification(const std::string& name) +// { +// return LLNotification::Params(name).context(mNotificationContext); +// } + + static void onClickClose(LLFloater* floater); + static void onClickMinimize(LLFloater* floater); + static void onClickTearOff(LLFloater* floater); + static void onClickDock(LLFloater* floater); + static void onClickHelp(LLFloater* floater); - static void onClickClose(LLFloater* floater); - static void onClickMinimize(LLFloater* floater); - static void onClickTearOff(LLFloater* floater); - static void onClickDock(LLFloater* floater); - static void onClickHelp(LLFloater* floater); + static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } + static LLMultiFloater* getFloaterHost() {return sHostp; } - static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } - static LLMultiFloater* getFloaterHost() {return sHostp; } + void updateTransparency(ETypeTransparency transparency_type); - void updateTransparency(ETypeTransparency transparency_type); - - void enableResizeCtrls(bool enable, bool width = true, bool height = true); + void enableResizeCtrls(bool enable, bool width = true, bool height = true); - bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } + bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } protected: - void applyControlsAndPosition(LLFloater* other); + void applyControlsAndPosition(LLFloater* other); + + void stackWith(LLFloater& other); - void stackWith(LLFloater& other); + virtual void initRectControl(); + virtual bool applyRectControl(); + bool applyDockState(); + void applyPositioning(LLFloater* other, bool on_open); + void applyRelativePosition(); - virtual void initRectControl(); - virtual bool applyRectControl(); - bool applyDockState(); - void applyPositioning(LLFloater* other, bool on_open); - void applyRelativePosition(); + void storeRectControl(); + void storeVisibilityControl(); + void storeDockStateControl(); - void storeRectControl(); - void storeVisibilityControl(); - void storeDockStateControl(); + void setKey(const LLSD& key); + void setInstanceName(const std::string& name); - void setKey(const LLSD& key); - void setInstanceName(const std::string& name); - - virtual void bringToFront(S32 x, S32 y); - virtual void goneFromFront(); - - void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized - const LLRect& getExpandedRect() const { return mExpandedRect; } + virtual void bringToFront(S32 x, S32 y); + virtual void goneFromFront(); - void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened - BOOL getAutoFocus() const { return mAutoFocus; } - LLDragHandle* getDragHandle() const { return mDragHandle; } + void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized + const LLRect& getExpandedRect() const { return mExpandedRect; } - void destroy(); // Don't call this directly. You probably want to call closeFloater() + void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened + BOOL getAutoFocus() const { return mAutoFocus; } + LLDragHandle* getDragHandle() const { return mDragHandle; } - virtual void onClickCloseBtn(bool app_quitting = false); + void destroy(); // Don't call this directly. You probably want to call closeFloater() - virtual void updateTitleButtons(); + virtual void onClickCloseBtn(bool app_quitting = false); - // Draws a cone from this floater to parent floater or view (owner) - // Modifies context_cone_opacity (interpolates according to fade time and returns new value) - void drawConeToOwner(F32 &context_cone_opacity, - F32 max_cone_opacity, - LLView *owner_view, - F32 context_fade_time = CONTEXT_CONE_FADE_TIME, - F32 contex_cone_in_alpha = CONTEXT_CONE_IN_ALPHA, - F32 contex_cone_out_alpha = CONTEXT_CONE_OUT_ALPHA); + virtual void updateTitleButtons(); + + // Draws a cone from this floater to parent floater or view (owner) + // Modifies context_cone_opacity (interpolates according to fade time and returns new value) + void drawConeToOwner(F32 &context_cone_opacity, + F32 max_cone_opacity, + LLView *owner_view, + F32 context_fade_time = CONTEXT_CONE_FADE_TIME, + F32 contex_cone_in_alpha = CONTEXT_CONE_IN_ALPHA, + F32 contex_cone_out_alpha = CONTEXT_CONE_OUT_ALPHA); private: - void setForeground(BOOL b); // called only by floaterview - void cleanupHandles(); // remove handles to dead floaters - void createMinimizeButton(); - void buildButtons(const Params& p); - - // Images and tooltips are named in the XML, but we want to look them - // up by index. - static LLUIImage* getButtonImage(const Params& p, EFloaterButton e); - static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e); - - /** - * @params is_chrome - if floater is Chrome it means that floater will never get focus. - * Therefore it can't be closed with 'Ctrl+W'. So the tooltip text of close button( X ) - * should be 'Close' not 'Close(Ctrl+W)' as for usual floaters. - */ - static std::string getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome); - - BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); - void addResizeCtrls(); - void layoutResizeCtrls(); - void addDragHandle(); - void layoutDragHandle(); // repair layout - - static void updateActiveFloaterTransparency(); - static void updateInactiveFloaterTransparency(); - void updateTransparency(LLView* view, ETypeTransparency transparency_type); + void setForeground(BOOL b); // called only by floaterview + void cleanupHandles(); // remove handles to dead floaters + void createMinimizeButton(); + void buildButtons(const Params& p); + + // Images and tooltips are named in the XML, but we want to look them + // up by index. + static LLUIImage* getButtonImage(const Params& p, EFloaterButton e); + static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e); + + /** + * @params is_chrome - if floater is Chrome it means that floater will never get focus. + * Therefore it can't be closed with 'Ctrl+W'. So the tooltip text of close button( X ) + * should be 'Close' not 'Close(Ctrl+W)' as for usual floaters. + */ + static std::string getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome); + + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); + void addResizeCtrls(); + void layoutResizeCtrls(); + void addDragHandle(); + void layoutDragHandle(); // repair layout + + static void updateActiveFloaterTransparency(); + static void updateInactiveFloaterTransparency(); + void updateTransparency(LLView* view, ETypeTransparency transparency_type); public: - static const F32 CONTEXT_CONE_IN_ALPHA; - static const F32 CONTEXT_CONE_OUT_ALPHA; - static const F32 CONTEXT_CONE_FADE_TIME; + static const F32 CONTEXT_CONE_IN_ALPHA; + static const F32 CONTEXT_CONE_OUT_ALPHA; + static const F32 CONTEXT_CONE_FADE_TIME; - // Called when floater is opened, passes mKey - // Public so external views or floaters can watch for this floater opening - commit_signal_t mOpenSignal; + // Called when floater is opened, passes mKey + // Public so external views or floaters can watch for this floater opening + commit_signal_t mOpenSignal; - // Called when floater is closed, passes app_qitting as LLSD() - // Public so external views or floaters can watch for this floater closing - commit_signal_t mCloseSignal; + // Called when floater is closed, passes app_qitting as LLSD() + // Public so external views or floaters can watch for this floater closing + commit_signal_t mCloseSignal; - commit_signal_t* mMinimizeSignal; + commit_signal_t* mMinimizeSignal; protected: - bool mSaveRect; - bool mDefaultRectForGroup; - std::string mRectControl; - std::string mPosXControl; - std::string mPosYControl; - std::string mVisibilityControl; - std::string mDocStateControl; - LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg - - LLDragHandle* mDragHandle; - LLResizeBar* mResizeBar[4]; - LLResizeHandle* mResizeHandle[4]; - - LLButton* mButtons[BUTTON_COUNT]; + bool mSaveRect; + bool mDefaultRectForGroup; + std::string mRectControl; + std::string mPosXControl; + std::string mPosYControl; + std::string mVisibilityControl; + std::string mDocStateControl; + LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg + + LLDragHandle* mDragHandle; + LLResizeBar* mResizeBar[4]; + LLResizeHandle* mResizeHandle[4]; + + LLButton* mButtons[BUTTON_COUNT]; private: - LLRect mExpandedRect; - - LLUIString mTitle; - LLUIString mShortTitle; - - BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater - bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it + LLRect mExpandedRect; + + LLUIString mTitle; + LLUIString mShortTitle; + + BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater + bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it bool mIsReuseInitialized; // true if mReuseInstance already set from parameters - std::string mInstanceName; // Store the instance name so we can remove ourselves from the list - - BOOL mCanTearOff; - BOOL mCanMinimize; - BOOL mCanClose; - bool mFocusStealsFrontmost = true; // FALSE if we don't want the currently focused floater to cover this floater without user interaction - BOOL mDragOnLeft; - BOOL mResizable; - BOOL mAutoClose; - - LLFloaterEnums::EOpenPositioning mPositioning; - LLCoordFloater mPosition; - - S32 mMinWidth; - S32 mMinHeight; - S32 mHeaderHeight; // height in pixels of header for title, drag bar - S32 mLegacyHeaderHeight;// HACK see initFloaterXML() - - BOOL mMinimized; - BOOL mForeground; - LLHandle mDependeeHandle; - - - BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. - - typedef std::set > handle_set_t; - typedef std::set >::iterator handle_set_iter_t; - handle_set_t mDependents; - bool mTranslateWithDependents { false }; - - bool mButtonsEnabled[BUTTON_COUNT]; - F32 mButtonScale; - BOOL mAutoFocus; - LLHandle mSnappedTo; - - LLHandle mHostHandle; - LLHandle mLastHostHandle; - - bool mCanDock; - bool mDocked; - bool mTornOff; - - static LLMultiFloater* sHostp; - static BOOL sQuitting; - static std::string sButtonNames[BUTTON_COUNT]; - static std::string sButtonToolTips[BUTTON_COUNT]; - static std::string sButtonToolTipsIndex[BUTTON_COUNT]; - - typedef void(*click_callback)(LLFloater*); - static click_callback sButtonCallbacks[BUTTON_COUNT]; - - BOOL mHasBeenDraggedWhileMinimized; - S32 mPreviousMinimizedBottom; - S32 mPreviousMinimizedLeft; - - F32 mDefaultRelativeX; - F32 mDefaultRelativeY; + std::string mInstanceName; // Store the instance name so we can remove ourselves from the list + + BOOL mCanTearOff; + BOOL mCanMinimize; + BOOL mCanClose; + bool mFocusStealsFrontmost = true; // FALSE if we don't want the currently focused floater to cover this floater without user interaction + BOOL mDragOnLeft; + BOOL mResizable; + BOOL mAutoClose; + + LLFloaterEnums::EOpenPositioning mPositioning; + LLCoordFloater mPosition; + + S32 mMinWidth; + S32 mMinHeight; + S32 mHeaderHeight; // height in pixels of header for title, drag bar + S32 mLegacyHeaderHeight;// HACK see initFloaterXML() + + BOOL mMinimized; + BOOL mForeground; + LLHandle mDependeeHandle; + + + BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. + + typedef std::set > handle_set_t; + typedef std::set >::iterator handle_set_iter_t; + handle_set_t mDependents; + bool mTranslateWithDependents { false }; + + bool mButtonsEnabled[BUTTON_COUNT]; + F32 mButtonScale; + BOOL mAutoFocus; + LLHandle mSnappedTo; + + LLHandle mHostHandle; + LLHandle mLastHostHandle; + + bool mCanDock; + bool mDocked; + bool mTornOff; + + static LLMultiFloater* sHostp; + static BOOL sQuitting; + static std::string sButtonNames[BUTTON_COUNT]; + static std::string sButtonToolTips[BUTTON_COUNT]; + static std::string sButtonToolTipsIndex[BUTTON_COUNT]; + + typedef void(*click_callback)(LLFloater*); + static click_callback sButtonCallbacks[BUTTON_COUNT]; + + BOOL mHasBeenDraggedWhileMinimized; + S32 mPreviousMinimizedBottom; + S32 mPreviousMinimizedLeft; + + F32 mDefaultRelativeX; + F32 mDefaultRelativeY; }; @@ -551,78 +551,78 @@ const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; class LLFloaterView : public LLUICtrl { public: - struct Params : public LLInitParam::Block{}; + struct Params : public LLInitParam::Block{}; protected: - LLFloaterView (const Params& p); - friend class LLUICtrlFactory; + LLFloaterView (const Params& p); + friend class LLUICtrlFactory; public: - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void draw(); - /*virtual*/ LLRect getSnapRect() const; - /*virtual*/ void refresh(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void draw(); + /*virtual*/ LLRect getSnapRect() const; + /*virtual*/ void refresh(); - LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); + LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); - // Given a child of gFloaterView, make sure this view can fit entirely onscreen. - void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false); + // Given a child of gFloaterView, make sure this view can fit entirely onscreen. + void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false); - void setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; } - void getMinimizePosition( S32 *left, S32 *bottom); - void restoreAll(); // un-minimize all floaters - typedef std::set skip_list_t; - void pushVisibleAll(BOOL visible, const skip_list_t& skip_list = skip_list_t()); - void popVisibleAll(const skip_list_t& skip_list = skip_list_t()); + void setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; } + void getMinimizePosition( S32 *left, S32 *bottom); + void restoreAll(); // un-minimize all floaters + typedef std::set skip_list_t; + void pushVisibleAll(BOOL visible, const skip_list_t& skip_list = skip_list_t()); + void popVisibleAll(const skip_list_t& skip_list = skip_list_t()); - void setCycleMode(BOOL mode) { mFocusCycleMode = mode; } - BOOL getCycleMode() const { return mFocusCycleMode; } - void bringToFront( LLFloater* child, BOOL give_focus = TRUE, BOOL restore = TRUE ); - void highlightFocusedFloater(); - void unhighlightFocusedFloater(); - void focusFrontFloater(); - void destroyAllChildren(); - // attempt to close all floaters - void closeAllChildren(bool app_quitting); - BOOL allChildrenClosed(); - void shiftFloaters(S32 x_offset, S32 y_offset); + void setCycleMode(BOOL mode) { mFocusCycleMode = mode; } + BOOL getCycleMode() const { return mFocusCycleMode; } + void bringToFront( LLFloater* child, BOOL give_focus = TRUE, BOOL restore = TRUE ); + void highlightFocusedFloater(); + void unhighlightFocusedFloater(); + void focusFrontFloater(); + void destroyAllChildren(); + // attempt to close all floaters + void closeAllChildren(bool app_quitting); + BOOL allChildrenClosed(); + void shiftFloaters(S32 x_offset, S32 y_offset); - void hideAllFloaters(); - void showHiddenFloaters(); + void hideAllFloaters(); + void showHiddenFloaters(); - LLFloater* getFrontmost() const; - LLFloater* getBackmost() const; - LLFloater* getParentFloater(LLView* viewp) const; - LLFloater* getFocusedFloater() const; - void syncFloaterTabOrder(); + LLFloater* getFrontmost() const; + LLFloater* getBackmost() const; + LLFloater* getParentFloater(LLView* viewp) const; + LLFloater* getFocusedFloater() const; + void syncFloaterTabOrder(); - // Returns z order of child provided. 0 is closest, larger numbers - // are deeper in the screen. If there is no such child, the return - // value is not defined. - S32 getZOrder(LLFloater* child); + // Returns z order of child provided. 0 is closest, larger numbers + // are deeper in the screen. If there is no such child, the return + // value is not defined. + S32 getZOrder(LLFloater* child); - void setFloaterSnapView(LLHandle snap_view) {mSnapView = snap_view; } - LLFloater* getFrontmostClosableFloater(); + void setFloaterSnapView(LLHandle snap_view) {mSnapView = snap_view; } + LLFloater* getFrontmostClosableFloater(); - void setToolbarRect(LLToolBarEnums::EToolBarLocation tb, const LLRect& toolbar_rect); + void setToolbarRect(LLToolBarEnums::EToolBarLocation tb, const LLRect& toolbar_rect); private: - void hiddenFloaterClosed(LLFloater* floater); - - LLRect mLastSnapRect; - LLRect mToolbarLeftRect; - LLRect mToolbarBottomRect; - LLRect mToolbarRightRect; - LLHandle mSnapView; - BOOL mFocusCycleMode; - S32 mSnapOffsetBottom; - S32 mSnapOffsetRight; - S32 mMinimizePositionVOffset; - typedef std::vector, boost::signals2::connection> > hidden_floaters_t; - hidden_floaters_t mHiddenFloaters; - LLHandle mFrontChildHandle; + void hiddenFloaterClosed(LLFloater* floater); + + LLRect mLastSnapRect; + LLRect mToolbarLeftRect; + LLRect mToolbarBottomRect; + LLRect mToolbarRightRect; + LLHandle mSnapView; + BOOL mFocusCycleMode; + S32 mSnapOffsetBottom; + S32 mSnapOffsetRight; + S32 mMinimizePositionVOffset; + typedef std::vector, boost::signals2::connection> > hidden_floaters_t; + hidden_floaters_t mHiddenFloaters; + LLHandle mFrontChildHandle; }; // diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index f888d7ff68..989ce12d09 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfloaterreg.cpp * @brief LLFloaterReg Floater Registration Class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,7 +28,7 @@ #include "llfloaterreg.h" -//#include "llagent.h" +//#include "llagent.h" #include "llfloater.h" #include "llmultifloater.h" #include "llfloaterreglistener.h" @@ -51,10 +51,10 @@ static LLFloaterRegListener sFloaterRegListener; //static void LLFloaterReg::add(const std::string& name, const std::string& filename, const LLFloaterBuildFunc& func, const std::string& groupname) { - sBuildMap[name].mFunc = func; - sBuildMap[name].mFile = filename; - sGroupMap[name] = groupname.empty() ? name : groupname; - sGroupMap[groupname] = groupname; // for referencing directly by group name + sBuildMap[name].mFunc = func; + sBuildMap[name].mFile = filename; + sGroupMap[name] = groupname.empty() ? name : groupname; + sGroupMap[groupname] = groupname; // for referencing directly by group name } //static @@ -66,468 +66,468 @@ bool LLFloaterReg::isRegistered(const std::string& name) //static LLFloater* LLFloaterReg::getLastFloaterInGroup(const std::string& name) { - const std::string& groupname = sGroupMap[name]; - if (!groupname.empty()) - { - instance_list_t& list = sInstanceMap[groupname]; - if (!list.empty()) - { - for (instance_list_t::reverse_iterator iter = list.rbegin(); iter != list.rend(); ++iter) - { - LLFloater* inst = *iter; - - if (inst->getVisible() && !inst->isMinimized()) - { - return inst; - } - } - } - } - return NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + if (!list.empty()) + { + for (instance_list_t::reverse_iterator iter = list.rbegin(); iter != list.rend(); ++iter) + { + LLFloater* inst = *iter; + + if (inst->getVisible() && !inst->isMinimized()) + { + return inst; + } + } + } + } + return NULL; } LLFloater* LLFloaterReg::getLastFloaterCascading() { - LLRect candidate_rect; - candidate_rect.mTop = 100000; - LLFloater* candidate_floater = NULL; - - std::map::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); - for( ; it != it_end; ++it) - { - const std::string& group_name = it->second; - - instance_list_t& instances = sInstanceMap[group_name]; - - for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) - { - LLFloater* inst = *iter; - - if (inst->getVisible() - && (inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADING) - || inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADE_GROUP))) - { - if (candidate_rect.mTop > inst->getRect().mTop) - { - candidate_floater = inst; - candidate_rect = inst->getRect(); - } - } - } - } - - return candidate_floater; + LLRect candidate_rect; + candidate_rect.mTop = 100000; + LLFloater* candidate_floater = NULL; + + std::map::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); + for( ; it != it_end; ++it) + { + const std::string& group_name = it->second; + + instance_list_t& instances = sInstanceMap[group_name]; + + for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) + { + LLFloater* inst = *iter; + + if (inst->getVisible() + && (inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADING) + || inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADE_GROUP))) + { + if (candidate_rect.mTop > inst->getRect().mTop) + { + candidate_floater = inst; + candidate_rect = inst->getRect(); + } + } + } + } + + return candidate_floater; } //static LLFloater* LLFloaterReg::findInstance(const std::string& name, const LLSD& key) { - LLFloater* res = NULL; - const std::string& groupname = sGroupMap[name]; - if (!groupname.empty()) - { - instance_list_t& list = sInstanceMap[groupname]; - for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) - { - LLFloater* inst = *iter; - if (inst->matchesKey(key)) - { - res = inst; - break; - } - } - } - return res; + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + break; + } + } + } + return res; } //static -LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) +LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) { - LLFloater* res = findInstance(name, key); - if (!res) - { - const LLFloaterBuildFunc& build_func = sBuildMap[name].mFunc; - const std::string& xui_file = sBuildMap[name].mFile; - if (build_func) - { - const std::string& groupname = sGroupMap[name]; - if (!groupname.empty()) - { - instance_list_t& list = sInstanceMap[groupname]; - - res = build_func(key); - if (!res) - { - LL_WARNS() << "Failed to build floater type: '" << name << "'." << LL_ENDL; - return NULL; - } - bool success = res->buildFromFile(xui_file); - if (!success) - { - LL_WARNS() << "Failed to build floater type: '" << name << "'." << LL_ENDL; - return NULL; - } - - // Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe - if (res->mKey.isUndefined()) - { - res->mKey = key; - } - res->setInstanceName(name); - - LLFloater *last_floater = (list.empty() ? NULL : list.back()); - - res->applyControlsAndPosition(last_floater); - - gFloaterView->adjustToFitScreen(res, false); - - list.push_back(res); - } - } - if (!res) - { - LL_WARNS() << "Floater type: '" << name << "' not registered." << LL_ENDL; - } - } - return res; + LLFloater* res = findInstance(name, key); + if (!res) + { + const LLFloaterBuildFunc& build_func = sBuildMap[name].mFunc; + const std::string& xui_file = sBuildMap[name].mFile; + if (build_func) + { + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + + res = build_func(key); + if (!res) + { + LL_WARNS() << "Failed to build floater type: '" << name << "'." << LL_ENDL; + return NULL; + } + bool success = res->buildFromFile(xui_file); + if (!success) + { + LL_WARNS() << "Failed to build floater type: '" << name << "'." << LL_ENDL; + return NULL; + } + + // Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe + if (res->mKey.isUndefined()) + { + res->mKey = key; + } + res->setInstanceName(name); + + LLFloater *last_floater = (list.empty() ? NULL : list.back()); + + res->applyControlsAndPosition(last_floater); + + gFloaterView->adjustToFitScreen(res, false); + + list.push_back(res); + } + } + if (!res) + { + LL_WARNS() << "Floater type: '" << name << "' not registered." << LL_ENDL; + } + } + return res; } //static LLFloater* LLFloaterReg::removeInstance(const std::string& name, const LLSD& key) { - LLFloater* res = NULL; - const std::string& groupname = sGroupMap[name]; - if (!groupname.empty()) - { - instance_list_t& list = sInstanceMap[groupname]; - for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) - { - LLFloater* inst = *iter; - if (inst->matchesKey(key)) - { - res = inst; - list.erase(iter); - break; - } - } - } - return res; + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + list.erase(iter); + break; + } + } + } + return res; } //static // returns true if the instance existed bool LLFloaterReg::destroyInstance(const std::string& name, const LLSD& key) { - LLFloater* inst = removeInstance(name, key); - if (inst) - { - delete inst; - return true; - } - else - { - return false; - } + LLFloater* inst = removeInstance(name, key); + if (inst) + { + delete inst; + return true; + } + else + { + return false; + } } // Iterators //static LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::string& name) { - instance_map_t::iterator iter = sInstanceMap.find(name); - if (iter != sInstanceMap.end()) - { - return iter->second; - } - else - { - return sNullInstanceList; - } + instance_map_t::iterator iter = sInstanceMap.find(name); + if (iter != sInstanceMap.end()) + { + return iter->second; + } + else + { + return sNullInstanceList; + } } // Visibility Management //static -LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) { - if( sBlockShowFloaters - // see EXT-7090 - && sAlwaysShowableList.find(name) == sAlwaysShowableList.end()) - return 0;// - LLFloater* instance = getInstance(name, key); - if (instance) - { - instance->openFloater(key); - if (focus) - instance->setFocus(TRUE); - } - return instance; + if( sBlockShowFloaters + // see EXT-7090 + && sAlwaysShowableList.find(name) == sAlwaysShowableList.end()) + return 0;// + LLFloater* instance = getInstance(name, key); + if (instance) + { + instance->openFloater(key); + if (focus) + instance->setFocus(TRUE); + } + return instance; } //static // returns true if the instance exists -bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) -{ - LLFloater* instance = findInstance(name, key); - if (instance) - { - instance->closeHostedFloater(); - } - return (instance != NULL); +bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance) + { + instance->closeHostedFloater(); + } + return (instance != NULL); } //static // returns true if the instance is visible when completed bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { - LLFloater* instance = findInstance(name, key); - if (LLFloater::isShown(instance)) - { - instance->closeHostedFloater(); - return false; - } - else - { - return showInstance(name, key, TRUE) ? true : false; - } + LLFloater* instance = findInstance(name, key); + if (LLFloater::isShown(instance)) + { + instance->closeHostedFloater(); + return false; + } + else + { + return showInstance(name, key, TRUE) ? true : false; + } } //static // returns true if the instance exists and is visible (doesnt matter minimized or not) bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key) { - LLFloater* instance = findInstance(name, key); - return LLFloater::isVisible(instance); + LLFloater* instance = findInstance(name, key); + return LLFloater::isVisible(instance); } //static -void LLFloaterReg::showInitialVisibleInstances() +void LLFloaterReg::showInitialVisibleInstances() { - // Iterate through alll registered instance names and show any with a save visible state - for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) - { - const std::string& name = iter->first; - std::string controlname = getVisibilityControlName(name); - if (LLFloater::getControlGroup()->controlExists(controlname)) - { - BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); - if (isvis) - { - showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true - } - } - } + // Iterate through alll registered instance names and show any with a save visible state + for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) + { + const std::string& name = iter->first; + std::string controlname = getVisibilityControlName(name); + if (LLFloater::getControlGroup()->controlExists(controlname)) + { + BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); + if (isvis) + { + showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true + } + } + } } //static void LLFloaterReg::hideVisibleInstances(const std::set& exceptions) { - // Iterate through alll active instances and hide them - for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) - { - const std::string& name = iter->first; - if (exceptions.find(name) != exceptions.end()) - continue; - instance_list_t& list = iter->second; - for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) - { - LLFloater* floater = *iter; - floater->pushVisible(FALSE); - } - } + // Iterate through alll active instances and hide them + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + const std::string& name = iter->first; + if (exceptions.find(name) != exceptions.end()) + continue; + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->pushVisible(FALSE); + } + } } //static void LLFloaterReg::restoreVisibleInstances() { - // Iterate through all active instances and restore visibility - for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) - { - instance_list_t& list = iter->second; - for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) - { - LLFloater* floater = *iter; - floater->popVisible(); - } - } + // Iterate through all active instances and restore visibility + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->popVisible(); + } + } } //static std::string LLFloaterReg::getRectControlName(const std::string& name) { - return std::string("floater_rect_") + getBaseControlName(name); + return std::string("floater_rect_") + getBaseControlName(name); } //static std::string LLFloaterReg::declareRectControl(const std::string& name) { - std::string controlname = getRectControlName(name); - LLFloater::getControlGroup()->declareRect(controlname, LLRect(), - llformat("Window Size for %s", name.c_str()), - LLControlVariable::PERSIST_NONDFT); - return controlname; + std::string controlname = getRectControlName(name); + LLFloater::getControlGroup()->declareRect(controlname, LLRect(), + llformat("Window Size for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); + return controlname; } std::string LLFloaterReg::declarePosXControl(const std::string& name) { - std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_x"; - LLFloater::getControlGroup()->declareF32(controlname, - 10.f, - llformat("Window X Position for %s", name.c_str()), - LLControlVariable::PERSIST_NONDFT); - return controlname; + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_x"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window X Position for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); + return controlname; } std::string LLFloaterReg::declarePosYControl(const std::string& name) { - std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_y"; - LLFloater::getControlGroup()->declareF32(controlname, - 10.f, - llformat("Window Y Position for %s", name.c_str()), - LLControlVariable::PERSIST_NONDFT); + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_y"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window Y Position for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); - return controlname; + return controlname; } //static std::string LLFloaterReg::getVisibilityControlName(const std::string& name) { - return std::string("floater_vis_") + getBaseControlName(name); + return std::string("floater_vis_") + getBaseControlName(name); } -//static +//static std::string LLFloaterReg::getBaseControlName(const std::string& name) { - std::string res(name); - LLStringUtil::replaceChar( res, ' ', '_' ); - return res; + std::string res(name); + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; } //static std::string LLFloaterReg::declareVisibilityControl(const std::string& name) { - std::string controlname = getVisibilityControlName(name); - LLFloater::getControlGroup()->declareBOOL(controlname, FALSE, - llformat("Window Visibility for %s", name.c_str()), - LLControlVariable::PERSIST_NONDFT); - return controlname; + std::string controlname = getVisibilityControlName(name); + LLFloater::getControlGroup()->declareBOOL(controlname, FALSE, + llformat("Window Visibility for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); + return controlname; } //static std::string LLFloaterReg::declareDockStateControl(const std::string& name) { - std::string controlname = getDockStateControlName(name); - LLFloater::getControlGroup()->declareBOOL(controlname, TRUE, - llformat("Window Docking state for %s", name.c_str()), - LLControlVariable::PERSIST_NONDFT); - return controlname; + std::string controlname = getDockStateControlName(name); + LLFloater::getControlGroup()->declareBOOL(controlname, TRUE, + llformat("Window Docking state for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); + return controlname; } //static std::string LLFloaterReg::getDockStateControlName(const std::string& name) { - std::string res = std::string("floater_dock_") + name; - LLStringUtil::replaceChar( res, ' ', '_' ); - return res; + std::string res = std::string("floater_dock_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; } //static void LLFloaterReg::registerControlVariables() { - // Iterate through alll registered instance names and register rect and visibility control variables - for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) - { - const std::string& name = iter->first; - if (LLFloater::getControlGroup()->controlExists(getRectControlName(name))) - { - declareRectControl(name); - } - if (LLFloater::getControlGroup()->controlExists(getVisibilityControlName(name))) - { - declareVisibilityControl(name); - } - } - - const LLSD& exclude_list = LLUI::getInstance()->mSettingGroups["config"]->getLLSD("always_showable_floaters"); - for (LLSD::array_const_iterator iter = exclude_list.beginArray(); - iter != exclude_list.endArray(); - iter++) - { - sAlwaysShowableList.insert(iter->asString()); - } + // Iterate through alll registered instance names and register rect and visibility control variables + for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) + { + const std::string& name = iter->first; + if (LLFloater::getControlGroup()->controlExists(getRectControlName(name))) + { + declareRectControl(name); + } + if (LLFloater::getControlGroup()->controlExists(getVisibilityControlName(name))) + { + declareVisibilityControl(name); + } + } + + const LLSD& exclude_list = LLUI::getInstance()->mSettingGroups["config"]->getLLSD("always_showable_floaters"); + for (LLSD::array_const_iterator iter = exclude_list.beginArray(); + iter != exclude_list.endArray(); + iter++) + { + sAlwaysShowableList.insert(iter->asString()); + } } //static void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key) { - // - // Floaters controlled by the toolbar behave a bit differently from others. - // Namely they have 3-4 states as defined in the design wiki page here: - // https://wiki.lindenlab.com/wiki/FUI_Button_states - // - // The basic idea is this: - // * If the target floater is minimized, this button press will un-minimize it. - // * Else if the target floater is closed open it. - // * Else if the target floater does not have focus, give it focus. - // * Also, if it is not on top, bring it forward when focus is given. - // * Else the target floater is open, close it. - // - std::string name = sdname.asString(); - LLFloater* instance = getInstance(name, key); - - if (!instance) - { - LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL; - return; - } - - // If hosted, we need to take that into account - LLFloater* host = instance->getHost(); - - if (host) - { - if (host->isMinimized() || !host->isShown() || !host->isFrontmost()) - { - host->setMinimized(FALSE); - instance->openFloater(key); - instance->setVisibleAndFrontmost(true, key); - } - else if (!instance->getVisible()) - { - instance->openFloater(key); - instance->setVisibleAndFrontmost(true, key); - instance->setFocus(TRUE); - } - else - { - instance->closeHostedFloater(); - } - } - else - { - if (instance->isMinimized()) - { - instance->setMinimized(FALSE); - instance->setVisibleAndFrontmost(true, key); - } - else if (!instance->isShown()) - { - instance->openFloater(key); - instance->setVisibleAndFrontmost(true, key); - } - else if (!instance->isFrontmost()) - { - instance->setVisibleAndFrontmost(true, key); - } - else - { - instance->closeHostedFloater(); - } - } + // + // Floaters controlled by the toolbar behave a bit differently from others. + // Namely they have 3-4 states as defined in the design wiki page here: + // https://wiki.lindenlab.com/wiki/FUI_Button_states + // + // The basic idea is this: + // * If the target floater is minimized, this button press will un-minimize it. + // * Else if the target floater is closed open it. + // * Else if the target floater does not have focus, give it focus. + // * Also, if it is not on top, bring it forward when focus is given. + // * Else the target floater is open, close it. + // + std::string name = sdname.asString(); + LLFloater* instance = getInstance(name, key); + + if (!instance) + { + LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL; + return; + } + + // If hosted, we need to take that into account + LLFloater* host = instance->getHost(); + + if (host) + { + if (host->isMinimized() || !host->isShown() || !host->isFrontmost()) + { + host->setMinimized(FALSE); + instance->openFloater(key); + instance->setVisibleAndFrontmost(true, key); + } + else if (!instance->getVisible()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(true, key); + instance->setFocus(TRUE); + } + else + { + instance->closeHostedFloater(); + } + } + else + { + if (instance->isMinimized()) + { + instance->setMinimized(FALSE); + instance->setVisibleAndFrontmost(true, key); + } + else if (!instance->isShown()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(true, key); + } + else if (!instance->isFrontmost()) + { + instance->setVisibleAndFrontmost(true, key); + } + else + { + instance->closeHostedFloater(); + } + } } // static @@ -585,25 +585,25 @@ void LLFloaterReg::showInstanceOrBringToFront(const LLSD& sdname, const LLSD& ke // static U32 LLFloaterReg::getVisibleFloaterInstanceCount() { - U32 count = 0; + U32 count = 0; - std::map::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); - for( ; it != it_end; ++it) - { - const std::string& group_name = it->second; + std::map::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); + for( ; it != it_end; ++it) + { + const std::string& group_name = it->second; - instance_list_t& instances = sInstanceMap[group_name]; + instance_list_t& instances = sInstanceMap[group_name]; - for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) - { - LLFloater* inst = *iter; + for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) + { + LLFloater* inst = *iter; - if (inst->getVisible() && !inst->isMinimized()) - { - count++; - } - } - } + if (inst->getVisible() && !inst->isMinimized()) + { + count++; + } + } + } - return count; + return count; } diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index eaa59b1d6f..43f3f7b170 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -1,25 +1,25 @@ -/** +/** * @file llfloaterreg.h * @brief LLFloaterReg Floater Registration Class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,113 +46,113 @@ typedef boost::function LLFloaterBuildFunc; class LLFloaterReg { public: - // We use a list of LLFloater's instead of a set for two reasons: - // 1) With a list we have a predictable ordering, useful for finding the last opened floater of a given type. - // 2) We can change the key of a floater without altering the list. - typedef std::list instance_list_t; - typedef const instance_list_t const_instance_list_t; - typedef std::map instance_map_t; - - struct BuildData - { - LLFloaterBuildFunc mFunc; - std::string mFile; - }; - typedef std::map build_map_t; - + // We use a list of LLFloater's instead of a set for two reasons: + // 1) With a list we have a predictable ordering, useful for finding the last opened floater of a given type. + // 2) We can change the key of a floater without altering the list. + typedef std::list instance_list_t; + typedef const instance_list_t const_instance_list_t; + typedef std::map instance_map_t; + + struct BuildData + { + LLFloaterBuildFunc mFunc; + std::string mFile; + }; + typedef std::map build_map_t; + private: - friend class LLFloaterRegListener; - static instance_list_t sNullInstanceList; - static instance_map_t sInstanceMap; - static build_map_t sBuildMap; - static std::map sGroupMap; - static bool sBlockShowFloaters; - /** - * Defines list of floater names that can be shown despite state of sBlockShowFloaters. - */ - static std::set sAlwaysShowableList; - + friend class LLFloaterRegListener; + static instance_list_t sNullInstanceList; + static instance_map_t sInstanceMap; + static build_map_t sBuildMap; + static std::map sGroupMap; + static bool sBlockShowFloaters; + /** + * Defines list of floater names that can be shown despite state of sBlockShowFloaters. + */ + static std::set sAlwaysShowableList; + public: - // Registration - - // usage: LLFloaterClassRegistry::add("foo", (LLFloaterBuildFunc)&LLFloaterClassRegistry::build); - template - static LLFloater* build(const LLSD& key) - { - T* floater = new T(key); - return floater; - } - - static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func, - const std::string& groupname = LLStringUtil::null); - static bool isRegistered(const std::string& name); - - // Helpers - static LLFloater* getLastFloaterInGroup(const std::string& name); - static LLFloater* getLastFloaterCascading(); - - // Find / get (create) / remove / destroy - static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); - static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); - static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); - static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); - - // Iterators - static const_instance_list_t& getFloaterList(const std::string& name); - - // Visibility Management - // return NULL if instance not found or can't create instance (no builder) - static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); - // Close a floater (may destroy or set invisible) - // return false if can't find instance - static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); - // return true if instance is visible: - static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); - static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); - - static void showInitialVisibleInstances(); - static void hideVisibleInstances(const std::set& exceptions = std::set()); - static void restoreVisibleInstances(); - - // Control Variables - static std::string getRectControlName(const std::string& name); - static std::string declareRectControl(const std::string& name); - static std::string declarePosXControl(const std::string& name); - static std::string declarePosYControl(const std::string& name); - static std::string getVisibilityControlName(const std::string& name); - static std::string declareVisibilityControl(const std::string& name); - static std::string getBaseControlName(const std::string& name); - static std::string declareDockStateControl(const std::string& name); - static std::string getDockStateControlName(const std::string& name); - - static void registerControlVariables(); - - // Callback wrappers - static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); - static void showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); - - // Typed find / get / show - template - static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) - { - return dynamic_cast(findInstance(name, key)); - } - - template - static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) - { - return dynamic_cast(getInstance(name, key)); - } - - template - static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) - { - return dynamic_cast(showInstance(name, key, focus)); - } - - static void blockShowFloaters(bool value) { sBlockShowFloaters = value;} - - static U32 getVisibleFloaterInstanceCount(); + // Registration + + // usage: LLFloaterClassRegistry::add("foo", (LLFloaterBuildFunc)&LLFloaterClassRegistry::build); + template + static LLFloater* build(const LLSD& key) + { + T* floater = new T(key); + return floater; + } + + static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func, + const std::string& groupname = LLStringUtil::null); + static bool isRegistered(const std::string& name); + + // Helpers + static LLFloater* getLastFloaterInGroup(const std::string& name); + static LLFloater* getLastFloaterCascading(); + + // Find / get (create) / remove / destroy + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); + + // Iterators + static const_instance_list_t& getFloaterList(const std::string& name); + + // Visibility Management + // return NULL if instance not found or can't create instance (no builder) + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); + // Close a floater (may destroy or set invisible) + // return false if can't find instance + static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); + // return true if instance is visible: + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); + + static void showInitialVisibleInstances(); + static void hideVisibleInstances(const std::set& exceptions = std::set()); + static void restoreVisibleInstances(); + + // Control Variables + static std::string getRectControlName(const std::string& name); + static std::string declareRectControl(const std::string& name); + static std::string declarePosXControl(const std::string& name); + static std::string declarePosYControl(const std::string& name); + static std::string getVisibilityControlName(const std::string& name); + static std::string declareVisibilityControl(const std::string& name); + static std::string getBaseControlName(const std::string& name); + static std::string declareDockStateControl(const std::string& name); + static std::string getDockStateControlName(const std::string& name); + + static void registerControlVariables(); + + // Callback wrappers + static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); + static void showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); + + // Typed find / get / show + template + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(findInstance(name, key)); + } + + template + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(getInstance(name, key)); + } + + template + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) + { + return dynamic_cast(showInstance(name, key, focus)); + } + + static void blockShowFloaters(bool value) { sBlockShowFloaters = value;} + + static U32 getVisibleFloaterInstanceCount(); }; #endif diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp index 7525b8cab3..aa3d1a1171 100644 --- a/indra/llui/llfloaterreglistener.cpp +++ b/indra/llui/llfloaterreglistener.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2009-08-12 * @brief Implementation for llfloaterreglistener. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index 24311a2dfa..a36072892c 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2009-08-12 * @brief Wrap (subset of) LLFloaterReg API with an event API - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp index 4b3a0a5d21..1d529d09d3 100644 --- a/indra/llui/llflyoutbutton.cpp +++ b/indra/llui/llflyoutbutton.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llflyoutbutton.cpp * @brief LLFlyoutButton base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,44 +34,44 @@ const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; LLFlyoutButton::LLFlyoutButton(const Params& p) -: LLComboBox(p), - mToggleState(FALSE), - mActionButton(NULL) +: LLComboBox(p), + mToggleState(FALSE), + mActionButton(NULL) { - // Always use text box - // Text label button - LLButton::Params bp(p.action_button); - bp.name(p.label); - bp.label(p.label); - bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight()); - bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2)); - bp.follows.flags(FOLLOWS_ALL); + // Always use text box + // Text label button + LLButton::Params bp(p.action_button); + bp.name(p.label); + bp.label(p.label); + bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight()); + bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2)); + bp.follows.flags(FOLLOWS_ALL); - mActionButton = LLUICtrlFactory::create(bp); - addChild(mActionButton); + mActionButton = LLUICtrlFactory::create(bp); + addChild(mActionButton); } void LLFlyoutButton::onActionButtonClick(const LLSD& data) { - // remember last list selection? - mList->deselect(); - onCommit(); + // remember last list selection? + mList->deselect(); + onCommit(); } void LLFlyoutButton::draw() { - mActionButton->setToggleState(mToggleState); - mButton->setToggleState(mToggleState); + mActionButton->setToggleState(mToggleState); + mButton->setToggleState(mToggleState); - //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or - // the label reflects the last selected item, for now we have to manually remove the label - setLabel(LLStringUtil::null); - LLComboBox::draw(); + //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or + // the label reflects the last selected item, for now we have to manually remove the label + setLabel(LLStringUtil::null); + LLComboBox::draw(); } void LLFlyoutButton::setToggleState(BOOL state) { - mToggleState = state; + mToggleState = state; } diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h index 36998eba2e..c217d14ff1 100644 --- a/indra/llui/llflyoutbutton.h +++ b/indra/llui/llflyoutbutton.h @@ -1,25 +1,25 @@ -/** +/** * @file llflyoutbutton.h * @brief LLFlyoutButton base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,32 +37,32 @@ class LLFlyoutButton : public LLComboBox { public: - struct Params : public LLInitParam::Block - { - Optional action_button; - Deprecated allow_text_entry; + struct Params : public LLInitParam::Block + { + Optional action_button; + Deprecated allow_text_entry; - Params() - : action_button("action_button"), - allow_text_entry("allow_text_entry") - { - changeDefault(LLComboBox::Params::allow_text_entry, false); - } + Params() + : action_button("action_button"), + allow_text_entry("allow_text_entry") + { + changeDefault(LLComboBox::Params::allow_text_entry, false); + } - }; + }; protected: - LLFlyoutButton(const Params&); - friend class LLUICtrlFactory; + LLFlyoutButton(const Params&); + friend class LLUICtrlFactory; public: - virtual void draw(); + virtual void draw(); - void setToggleState(BOOL state); + void setToggleState(BOOL state); - void onActionButtonClick(const LLSD& data); + void onActionButtonClick(const LLSD& data); protected: - LLButton* mActionButton; - BOOL mToggleState; + LLButton* mActionButton; + BOOL mToggleState; }; #endif // LL_LLFLYOUTBUTTON_H diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 7b0a6cbdae..2331b34c43 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfocusmgr.cpp * @brief LLFocusMgr base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,38 +33,38 @@ const F32 FOCUS_FADE_TIME = 0.3f; LLFocusableElement::LLFocusableElement() -: mFocusLostCallback(NULL), - mFocusReceivedCallback(NULL), - mFocusChangedCallback(NULL), - mTopLostCallback(NULL) +: mFocusLostCallback(NULL), + mFocusReceivedCallback(NULL), + mFocusChangedCallback(NULL), + mTopLostCallback(NULL) { } // virtual BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - return FALSE; + return FALSE; } // virtual BOOL LLFocusableElement::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) { - return FALSE; + return FALSE; } // virtual BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { - return FALSE; + return FALSE; } -// virtual +// virtual bool LLFocusableElement::wantsKeyUpKeyDown() const { return false; } -//virtual +//virtual bool LLFocusableElement::wantsReturnKey() const { return false; @@ -73,60 +73,60 @@ bool LLFocusableElement::wantsReturnKey() const // virtual LLFocusableElement::~LLFocusableElement() { - delete mFocusLostCallback; - delete mFocusReceivedCallback; - delete mFocusChangedCallback; - delete mTopLostCallback; + delete mFocusLostCallback; + delete mFocusReceivedCallback; + delete mFocusChangedCallback; + delete mTopLostCallback; } void LLFocusableElement::onFocusReceived() { - if (mFocusReceivedCallback) (*mFocusReceivedCallback)(this); - if (mFocusChangedCallback) (*mFocusChangedCallback)(this); + if (mFocusReceivedCallback) (*mFocusReceivedCallback)(this); + if (mFocusChangedCallback) (*mFocusChangedCallback)(this); } void LLFocusableElement::onFocusLost() { - if (mFocusLostCallback) (*mFocusLostCallback)(this); - if (mFocusChangedCallback) (*mFocusChangedCallback)(this); + if (mFocusLostCallback) (*mFocusLostCallback)(this); + if (mFocusChangedCallback) (*mFocusChangedCallback)(this); } void LLFocusableElement::onTopLost() { - if (mTopLostCallback) (*mTopLostCallback)(this); + if (mTopLostCallback) (*mTopLostCallback)(this); } BOOL LLFocusableElement::hasFocus() const { - return gFocusMgr.getKeyboardFocus() == this; + return gFocusMgr.getKeyboardFocus() == this; } void LLFocusableElement::setFocus(BOOL b) { } -boost::signals2::connection LLFocusableElement::setFocusLostCallback( const focus_signal_t::slot_type& cb) -{ - if (!mFocusLostCallback) mFocusLostCallback = new focus_signal_t(); - return mFocusLostCallback->connect(cb); +boost::signals2::connection LLFocusableElement::setFocusLostCallback( const focus_signal_t::slot_type& cb) +{ + if (!mFocusLostCallback) mFocusLostCallback = new focus_signal_t(); + return mFocusLostCallback->connect(cb); } -boost::signals2::connection LLFocusableElement::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) -{ - if (!mFocusReceivedCallback) mFocusReceivedCallback = new focus_signal_t(); - return mFocusReceivedCallback->connect(cb); +boost::signals2::connection LLFocusableElement::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) +{ + if (!mFocusReceivedCallback) mFocusReceivedCallback = new focus_signal_t(); + return mFocusReceivedCallback->connect(cb); } -boost::signals2::connection LLFocusableElement::setFocusChangedCallback(const focus_signal_t::slot_type& cb) +boost::signals2::connection LLFocusableElement::setFocusChangedCallback(const focus_signal_t::slot_type& cb) { - if (!mFocusChangedCallback) mFocusChangedCallback = new focus_signal_t(); - return mFocusChangedCallback->connect(cb); + if (!mFocusChangedCallback) mFocusChangedCallback = new focus_signal_t(); + return mFocusChangedCallback->connect(cb); } -boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_signal_t::slot_type& cb) -{ - if (!mTopLostCallback) mTopLostCallback = new focus_signal_t(); - return mTopLostCallback->connect(cb); +boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_signal_t::slot_type& cb) +{ + if (!mTopLostCallback) mTopLostCallback = new focus_signal_t(); + return mTopLostCallback->connect(cb); } @@ -135,283 +135,283 @@ typedef std::list > view_handle_list_t; typedef std::map, LLHandle > focus_history_map_t; struct LLFocusMgr::Impl { - // caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost - view_handle_list_t mCachedKeyboardFocusList; + // caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost + view_handle_list_t mCachedKeyboardFocusList; - focus_history_map_t mFocusHistory; + focus_history_map_t mFocusHistory; }; LLFocusMgr gFocusMgr; LLFocusMgr::LLFocusMgr() -: mLockedView( NULL ), - mMouseCaptor( NULL ), - mKeyboardFocus( NULL ), - mLastKeyboardFocus( NULL ), - mDefaultKeyboardFocus( NULL ), - mKeystrokesOnly(FALSE), - mTopCtrl( NULL ), - mAppHasFocus(TRUE), // Macs don't seem to notify us that we've gotten focus, so default to true - mImpl(new LLFocusMgr::Impl) +: mLockedView( NULL ), + mMouseCaptor( NULL ), + mKeyboardFocus( NULL ), + mLastKeyboardFocus( NULL ), + mDefaultKeyboardFocus( NULL ), + mKeystrokesOnly(FALSE), + mTopCtrl( NULL ), + mAppHasFocus(TRUE), // Macs don't seem to notify us that we've gotten focus, so default to true + mImpl(new LLFocusMgr::Impl) { } LLFocusMgr::~LLFocusMgr() { - mImpl->mFocusHistory.clear(); - delete mImpl; - mImpl = NULL; + mImpl->mFocusHistory.clear(); + delete mImpl; + mImpl = NULL; } void LLFocusMgr::releaseFocusIfNeeded( LLView* view ) { - if( childHasMouseCapture( view ) ) - { - setMouseCapture( NULL ); - } + if( childHasMouseCapture( view ) ) + { + setMouseCapture( NULL ); + } - if( childHasKeyboardFocus( view )) - { - if (view == mLockedView) - { - mLockedView = NULL; - setKeyboardFocus( NULL ); - } - else - { - setKeyboardFocus( mLockedView ); - } - } + if( childHasKeyboardFocus( view )) + { + if (view == mLockedView) + { + mLockedView = NULL; + setKeyboardFocus( NULL ); + } + else + { + setKeyboardFocus( mLockedView ); + } + } - LLUI::getInstance()->removePopup(view); + LLUI::getInstance()->removePopup(view); } void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only) { - // notes if keyboard focus is changed again (by onFocusLost/onFocusReceived) + // notes if keyboard focus is changed again (by onFocusLost/onFocusReceived) // making the rest of our processing unnecessary since it will already be // handled by the recursive call - static bool focus_dirty; - focus_dirty = false; - - if (mLockedView && - (new_focus == NULL || - (new_focus != mLockedView - && dynamic_cast(new_focus) - && !dynamic_cast(new_focus)->hasAncestor(mLockedView)))) - { - // don't allow focus to go to anything that is not the locked focus - // or one of its descendants - return; - } - - mKeystrokesOnly = keystrokes_only; - - if( new_focus != mKeyboardFocus ) - { - mLastKeyboardFocus = mKeyboardFocus; - mKeyboardFocus = new_focus; - - // list of the focus and it's ancestors - view_handle_list_t old_focus_list = mImpl->mCachedKeyboardFocusList; - view_handle_list_t new_focus_list; - - // walk up the tree to root and add all views to the new_focus_list - for (LLView* ctrl = dynamic_cast(mKeyboardFocus); ctrl; ctrl = ctrl->getParent()) - { - new_focus_list.push_back(ctrl->getHandle()); - } - - // remove all common ancestors since their focus is unchanged - while (!new_focus_list.empty() && - !old_focus_list.empty() && - new_focus_list.back() == old_focus_list.back()) - { - new_focus_list.pop_back(); - old_focus_list.pop_back(); - } - - // walk up the old focus branch calling onFocusLost - // we bubble up the tree to release focus, and back down to add - for (view_handle_list_t::iterator old_focus_iter = old_focus_list.begin(); - old_focus_iter != old_focus_list.end() && !focus_dirty; - old_focus_iter++) - { - LLView* old_focus_view = old_focus_iter->get(); - if (old_focus_view) - { - mImpl->mCachedKeyboardFocusList.pop_front(); - old_focus_view->onFocusLost(); - } - } - - // walk down the new focus branch calling onFocusReceived - for (view_handle_list_t::reverse_iterator new_focus_riter = new_focus_list.rbegin(); - new_focus_riter != new_focus_list.rend() && !focus_dirty; - new_focus_riter++) - { - LLView* new_focus_view = new_focus_riter->get(); - if (new_focus_view) - { + static bool focus_dirty; + focus_dirty = false; + + if (mLockedView && + (new_focus == NULL || + (new_focus != mLockedView + && dynamic_cast(new_focus) + && !dynamic_cast(new_focus)->hasAncestor(mLockedView)))) + { + // don't allow focus to go to anything that is not the locked focus + // or one of its descendants + return; + } + + mKeystrokesOnly = keystrokes_only; + + if( new_focus != mKeyboardFocus ) + { + mLastKeyboardFocus = mKeyboardFocus; + mKeyboardFocus = new_focus; + + // list of the focus and it's ancestors + view_handle_list_t old_focus_list = mImpl->mCachedKeyboardFocusList; + view_handle_list_t new_focus_list; + + // walk up the tree to root and add all views to the new_focus_list + for (LLView* ctrl = dynamic_cast(mKeyboardFocus); ctrl; ctrl = ctrl->getParent()) + { + new_focus_list.push_back(ctrl->getHandle()); + } + + // remove all common ancestors since their focus is unchanged + while (!new_focus_list.empty() && + !old_focus_list.empty() && + new_focus_list.back() == old_focus_list.back()) + { + new_focus_list.pop_back(); + old_focus_list.pop_back(); + } + + // walk up the old focus branch calling onFocusLost + // we bubble up the tree to release focus, and back down to add + for (view_handle_list_t::iterator old_focus_iter = old_focus_list.begin(); + old_focus_iter != old_focus_list.end() && !focus_dirty; + old_focus_iter++) + { + LLView* old_focus_view = old_focus_iter->get(); + if (old_focus_view) + { + mImpl->mCachedKeyboardFocusList.pop_front(); + old_focus_view->onFocusLost(); + } + } + + // walk down the new focus branch calling onFocusReceived + for (view_handle_list_t::reverse_iterator new_focus_riter = new_focus_list.rbegin(); + new_focus_riter != new_focus_list.rend() && !focus_dirty; + new_focus_riter++) + { + LLView* new_focus_view = new_focus_riter->get(); + if (new_focus_view) + { mImpl->mCachedKeyboardFocusList.push_front(new_focus_view->getHandle()); - new_focus_view->onFocusReceived(); - } - } - - // if focus was changed as part of an onFocusLost or onFocusReceived call - // stop iterating on current list since it is now invalid - if (focus_dirty) - { - return; - } - - // If we've got a default keyboard focus, and the caller is - // releasing keyboard focus, move to the default. - if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL) - { - mDefaultKeyboardFocus->setFocus(TRUE); - } - - LLView* focus_subtree = dynamic_cast(mKeyboardFocus); - LLView* viewp = dynamic_cast(mKeyboardFocus); - // find root-most focus root - while(viewp) - { - if (viewp->isFocusRoot()) - { - focus_subtree = viewp; - } - viewp = viewp->getParent(); - } - - - if (focus_subtree) - { - LLView* focused_view = dynamic_cast(mKeyboardFocus); - mImpl->mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle(); - } - } - - if (lock) - { - lockFocus(); - } - - focus_dirty = true; + new_focus_view->onFocusReceived(); + } + } + + // if focus was changed as part of an onFocusLost or onFocusReceived call + // stop iterating on current list since it is now invalid + if (focus_dirty) + { + return; + } + + // If we've got a default keyboard focus, and the caller is + // releasing keyboard focus, move to the default. + if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL) + { + mDefaultKeyboardFocus->setFocus(TRUE); + } + + LLView* focus_subtree = dynamic_cast(mKeyboardFocus); + LLView* viewp = dynamic_cast(mKeyboardFocus); + // find root-most focus root + while(viewp) + { + if (viewp->isFocusRoot()) + { + focus_subtree = viewp; + } + viewp = viewp->getParent(); + } + + + if (focus_subtree) + { + LLView* focused_view = dynamic_cast(mKeyboardFocus); + mImpl->mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle(); + } + } + + if (lock) + { + lockFocus(); + } + + focus_dirty = true; } // Returns TRUE is parent or any descedent of parent has keyboard focus. BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const { - LLView* focus_view = dynamic_cast(mKeyboardFocus); - while( focus_view ) - { - if( focus_view == parent ) - { - return TRUE; - } - focus_view = focus_view->getParent(); - } - return FALSE; + LLView* focus_view = dynamic_cast(mKeyboardFocus); + while( focus_view ) + { + if( focus_view == parent ) + { + return TRUE; + } + focus_view = focus_view->getParent(); + } + return FALSE; } // Returns TRUE is parent or any descedent of parent is the mouse captor. BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const { - if( mMouseCaptor && dynamic_cast(mMouseCaptor) != NULL ) - { - LLView* captor_view = (LLView*)mMouseCaptor; - while( captor_view ) - { - if( captor_view == parent ) - { - return TRUE; - } - captor_view = captor_view->getParent(); - } - } - return FALSE; + if( mMouseCaptor && dynamic_cast(mMouseCaptor) != NULL ) + { + LLView* captor_view = (LLView*)mMouseCaptor; + while( captor_view ) + { + if( captor_view == parent ) + { + return TRUE; + } + captor_view = captor_view->getParent(); + } + } + return FALSE; } void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ) { - // should be ok to unlock here, as you have to know the locked view - // in order to unlock it - if (focus == mLockedView) - { - mLockedView = NULL; - } + // should be ok to unlock here, as you have to know the locked view + // in order to unlock it + if (focus == mLockedView) + { + mLockedView = NULL; + } - if( mKeyboardFocus == focus ) - { - mKeyboardFocus = NULL; - } + if( mKeyboardFocus == focus ) + { + mKeyboardFocus = NULL; + } } bool LLFocusMgr::keyboardFocusHasAccelerators() const { - LLView* focus_view = dynamic_cast(mKeyboardFocus); - while( focus_view ) - { - if(focus_view->hasAccelerators()) - { - return true; - } + LLView* focus_view = dynamic_cast(mKeyboardFocus); + while( focus_view ) + { + if(focus_view->hasAccelerators()) + { + return true; + } - focus_view = focus_view->getParent(); - } - return false; + focus_view = focus_view->getParent(); + } + return false; } void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor ) { - if( new_captor != mMouseCaptor ) - { - LLMouseHandler* old_captor = mMouseCaptor; - mMouseCaptor = new_captor; - - if (LLView::sDebugMouseHandling) - { - if (new_captor) - { - LL_INFOS() << "New mouse captor: " << new_captor->getName() << LL_ENDL; - } - else - { - LL_INFOS() << "New mouse captor: NULL" << LL_ENDL; - } - } - - if( old_captor ) - { - old_captor->onMouseCaptureLost(); - } - - } + if( new_captor != mMouseCaptor ) + { + LLMouseHandler* old_captor = mMouseCaptor; + mMouseCaptor = new_captor; + + if (LLView::sDebugMouseHandling) + { + if (new_captor) + { + LL_INFOS() << "New mouse captor: " << new_captor->getName() << LL_ENDL; + } + else + { + LL_INFOS() << "New mouse captor: NULL" << LL_ENDL; + } + } + + if( old_captor ) + { + old_captor->onMouseCaptureLost(); + } + + } } void LLFocusMgr::removeMouseCaptureWithoutCallback( const LLMouseHandler* captor ) { - if( mMouseCaptor == captor ) - { - mMouseCaptor = NULL; - } + if( mMouseCaptor == captor ) + { + mMouseCaptor = NULL; + } } BOOL LLFocusMgr::childIsTopCtrl( const LLView* parent ) const { - LLView* top_view = (LLView*)mTopCtrl; - while( top_view ) - { - if( top_view == parent ) - { - return TRUE; - } - top_view = top_view->getParent(); - } - return FALSE; + LLView* top_view = (LLView*)mTopCtrl; + while( top_view ) + { + if( top_view == parent ) + { + return TRUE; + } + top_view = top_view->getParent(); + } + return FALSE; } @@ -419,91 +419,91 @@ BOOL LLFocusMgr::childIsTopCtrl( const LLView* parent ) const // set new_top = NULL to release top_view. void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) { - LLUICtrl* old_top = mTopCtrl; - if( new_top != old_top ) - { - mTopCtrl = new_top; + LLUICtrl* old_top = mTopCtrl; + if( new_top != old_top ) + { + mTopCtrl = new_top; - if (old_top) - { - old_top->onTopLost(); - } - } + if (old_top) + { + old_top->onTopLost(); + } + } } void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view ) { - if( mTopCtrl == top_view ) - { - mTopCtrl = NULL; - } + if( mTopCtrl == top_view ) + { + mTopCtrl = NULL; + } } void LLFocusMgr::lockFocus() { - mLockedView = dynamic_cast(mKeyboardFocus); + mLockedView = dynamic_cast(mKeyboardFocus); } void LLFocusMgr::unlockFocus() { - mLockedView = NULL; + mLockedView = NULL; } F32 LLFocusMgr::getFocusFlashAmt() const { - return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f); + return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f); } LLColor4 LLFocusMgr::getFocusColor() const { - static LLUIColor focus_color_cached = LLUIColorTable::instance().getColor("FocusColor"); - LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt()); - // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem) - if (!mAppHasFocus) - { - focus_color.mV[VALPHA] *= 0.4f; - } - return focus_color; + static LLUIColor focus_color_cached = LLUIColorTable::instance().getColor("FocusColor"); + LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt()); + // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem) + if (!mAppHasFocus) + { + focus_color.mV[VALPHA] *= 0.4f; + } + return focus_color; } void LLFocusMgr::triggerFocusFlash() { - mFocusFlashTimer.reset(); + mFocusFlashTimer.reset(); } -void LLFocusMgr::setAppHasFocus(BOOL focus) -{ - if (!mAppHasFocus && focus) - { - triggerFocusFlash(); - } - - // release focus from "top ctrl"s, which generally hides them - if (!focus) - { - LLUI::getInstance()->clearPopups(); - } - mAppHasFocus = focus; +void LLFocusMgr::setAppHasFocus(BOOL focus) +{ + if (!mAppHasFocus && focus) + { + triggerFocusFlash(); + } + + // release focus from "top ctrl"s, which generally hides them + if (!focus) + { + LLUI::getInstance()->clearPopups(); + } + mAppHasFocus = focus; } LLView* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const { - if (subtree_root) - { - focus_history_map_t::const_iterator found_it = mImpl->mFocusHistory.find(subtree_root->getHandle()); - if (found_it != mImpl->mFocusHistory.end()) - { - // found last focus for this subtree - return found_it->second.get(); - } - } - return NULL; + if (subtree_root) + { + focus_history_map_t::const_iterator found_it = mImpl->mFocusHistory.find(subtree_root->getHandle()); + if (found_it != mImpl->mFocusHistory.end()) + { + // found last focus for this subtree + return found_it->second.get(); + } + } + return NULL; } void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root) { - if (subtree_root) - { - mImpl->mFocusHistory.erase(subtree_root->getHandle()); - } + if (subtree_root) + { + mImpl->mFocusHistory.erase(subtree_root->getHandle()); + } } diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 0e3d7d8e59..964897500c 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -1,25 +1,25 @@ -/** +/** * @file llfocusmgr.h * @brief LLFocusMgr base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,117 +40,117 @@ class LLView; // NOTE: the LLFocusableElement class declaration has been moved here from lluictrl.h. class LLFocusableElement { - friend class LLFocusMgr; // allow access to focus change handlers + friend class LLFocusMgr; // allow access to focus change handlers public: - LLFocusableElement(); - virtual ~LLFocusableElement(); + LLFocusableElement(); + virtual ~LLFocusableElement(); + + virtual void setFocus( BOOL b ); + virtual BOOL hasFocus() const; - virtual void setFocus( BOOL b ); - virtual BOOL hasFocus() const; + typedef boost::signals2::signal focus_signal_t; - typedef boost::signals2::signal focus_signal_t; - - boost::signals2::connection setFocusLostCallback( const focus_signal_t::slot_type& cb); - boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); - boost::signals2::connection setFocusChangedCallback(const focus_signal_t::slot_type& cb); - boost::signals2::connection setTopLostCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusLostCallback( const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusChangedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setTopLostCallback(const focus_signal_t::slot_type& cb); - // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus. - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus. + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); /** - * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages - * even for normal character strokes. + * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages + * even for normal character strokes. * Default implementation returns false. */ virtual bool wantsKeyUpKeyDown() const; virtual bool wantsReturnKey() const; - virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere -protected: - virtual void onFocusReceived(); - virtual void onFocusLost(); - focus_signal_t* mFocusLostCallback; - focus_signal_t* mFocusReceivedCallback; - focus_signal_t* mFocusChangedCallback; - focus_signal_t* mTopLostCallback; + virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere +protected: + virtual void onFocusReceived(); + virtual void onFocusLost(); + focus_signal_t* mFocusLostCallback; + focus_signal_t* mFocusReceivedCallback; + focus_signal_t* mFocusChangedCallback; + focus_signal_t* mTopLostCallback; }; class LLFocusMgr { public: - LLFocusMgr(); - ~LLFocusMgr(); - - // Mouse Captor - void setMouseCapture(LLMouseHandler* new_captor); // new_captor = NULL to release the mouse. - LLMouseHandler* getMouseCapture() const { return mMouseCaptor; } - void removeMouseCaptureWithoutCallback( const LLMouseHandler* captor ); - BOOL childHasMouseCapture( const LLView* parent ) const; - - // Keyboard Focus - void setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus. - LLFocusableElement* getKeyboardFocus() const { return mKeyboardFocus; } - LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; } - BOOL childHasKeyboardFocus( const LLView* parent ) const; - void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ); - BOOL getKeystrokesOnly() { return mKeystrokesOnly; } - void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; } - - F32 getFocusFlashAmt() const; - S32 getFocusFlashWidth() const { return ll_round(lerp(1.f, 3.f, getFocusFlashAmt())); } - LLColor4 getFocusColor() const; - void triggerFocusFlash(); - BOOL getAppHasFocus() const { return mAppHasFocus; } - void setAppHasFocus(BOOL focus); - LLView* getLastFocusForGroup(LLView* subtree_root) const; - void clearLastFocusForGroup(LLView* subtree_root); - - // If setKeyboardFocus(NULL) is called, and there is a non-NULL default - // keyboard focus view, focus goes there. JC - void setDefaultKeyboardFocus(LLFocusableElement* default_focus) { mDefaultKeyboardFocus = default_focus; } - LLFocusableElement* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; } - - - // Top View - void setTopCtrl(LLUICtrl* new_top); - LLUICtrl* getTopCtrl() const { return mTopCtrl; } - void removeTopCtrlWithoutCallback( const LLUICtrl* top_view ); - BOOL childIsTopCtrl( const LLView* parent ) const; - - // All Three - void releaseFocusIfNeeded( LLView* top_view ); - void lockFocus(); - void unlockFocus(); - BOOL focusLocked() const { return mLockedView != NULL; } - - bool keyboardFocusHasAccelerators() const; - - struct Impl; + LLFocusMgr(); + ~LLFocusMgr(); + + // Mouse Captor + void setMouseCapture(LLMouseHandler* new_captor); // new_captor = NULL to release the mouse. + LLMouseHandler* getMouseCapture() const { return mMouseCaptor; } + void removeMouseCaptureWithoutCallback( const LLMouseHandler* captor ); + BOOL childHasMouseCapture( const LLView* parent ) const; + + // Keyboard Focus + void setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus. + LLFocusableElement* getKeyboardFocus() const { return mKeyboardFocus; } + LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; } + BOOL childHasKeyboardFocus( const LLView* parent ) const; + void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ); + BOOL getKeystrokesOnly() { return mKeystrokesOnly; } + void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; } + + F32 getFocusFlashAmt() const; + S32 getFocusFlashWidth() const { return ll_round(lerp(1.f, 3.f, getFocusFlashAmt())); } + LLColor4 getFocusColor() const; + void triggerFocusFlash(); + BOOL getAppHasFocus() const { return mAppHasFocus; } + void setAppHasFocus(BOOL focus); + LLView* getLastFocusForGroup(LLView* subtree_root) const; + void clearLastFocusForGroup(LLView* subtree_root); + + // If setKeyboardFocus(NULL) is called, and there is a non-NULL default + // keyboard focus view, focus goes there. JC + void setDefaultKeyboardFocus(LLFocusableElement* default_focus) { mDefaultKeyboardFocus = default_focus; } + LLFocusableElement* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; } + + + // Top View + void setTopCtrl(LLUICtrl* new_top); + LLUICtrl* getTopCtrl() const { return mTopCtrl; } + void removeTopCtrlWithoutCallback( const LLUICtrl* top_view ); + BOOL childIsTopCtrl( const LLView* parent ) const; + + // All Three + void releaseFocusIfNeeded( LLView* top_view ); + void lockFocus(); + void unlockFocus(); + BOOL focusLocked() const { return mLockedView != NULL; } + + bool keyboardFocusHasAccelerators() const; + + struct Impl; private: - LLUICtrl* mLockedView; + LLUICtrl* mLockedView; + + // Mouse Captor + LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object - // Mouse Captor - LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object + // Keyboard Focus + LLFocusableElement* mKeyboardFocus; // Keyboard events are preemptively routed to this object + LLFocusableElement* mLastKeyboardFocus; // who last had focus + LLFocusableElement* mDefaultKeyboardFocus; + BOOL mKeystrokesOnly; - // Keyboard Focus - LLFocusableElement* mKeyboardFocus; // Keyboard events are preemptively routed to this object - LLFocusableElement* mLastKeyboardFocus; // who last had focus - LLFocusableElement* mDefaultKeyboardFocus; - BOOL mKeystrokesOnly; - - // Top View - LLUICtrl* mTopCtrl; + // Top View + LLUICtrl* mTopCtrl; - LLFrameTimer mFocusFlashTimer; + LLFrameTimer mFocusFlashTimer; - BOOL mAppHasFocus; + BOOL mAppHasFocus; - Impl * mImpl; + Impl * mImpl; }; extern LLFocusMgr gFocusMgr; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 650ae9ae75..fa6128cc25 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfolderview.cpp * @brief Implementation of the folder view collection of classes. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -43,7 +43,7 @@ #include "lldbstrings.h" #include "llfocusmgr.h" #include "llfontgl.h" -#include "llgl.h" +#include "llgl.h" #include "llrender.h" // Third-party library includes @@ -63,8 +63,8 @@ const S32 STATUS_TEXT_HPAD = 6; const S32 STATUS_TEXT_VPAD = 8; enum { - SIGNAL_NO_KEYBOARD_FOCUS = 1, - SIGNAL_KEYBOARD_FOCUS = 2 + SIGNAL_NO_KEYBOARD_FOCUS = 1, + SIGNAL_KEYBOARD_FOCUS = 2 }; F32 LLFolderView::sAutoOpenTime = 1.f; @@ -74,28 +74,28 @@ F32 LLFolderView::sAutoOpenTime = 1.f; // Tells all folders in a folderview to close themselves // For efficiency, calls setOpenArrangeRecursively(). // The calling function must then call: -// LLFolderView* root = getRoot(); -// if( root ) -// { -// root->arrange( NULL, NULL ); -// root->scrollToShowSelection(); -// } +// LLFolderView* root = getRoot(); +// if( root ) +// { +// root->arrange( NULL, NULL ); +// root->scrollToShowSelection(); +// } // to patch things up. class LLCloseAllFoldersFunctor : public LLFolderViewFunctor { public: - LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } - virtual ~LLCloseAllFoldersFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); + LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } + virtual ~LLCloseAllFoldersFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); - BOOL mOpen; + BOOL mOpen; }; void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) { - folder->setOpenArrangeRecursively(mOpen); + folder->setOpenArrangeRecursively(mOpen); } // Do nothing. @@ -106,12 +106,12 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) void LLAllDescendentsPassedFilter::doFolder(LLFolderViewFolder* folder) { - mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter()); + mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter()); } void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item) { - mAllDescendentsPassedFilter &= (item) && (item->passedFilter()); + mAllDescendentsPassedFilter &= (item) && (item->passedFilter()); } ///---------------------------------------------------------------------------- @@ -121,215 +121,215 @@ void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item) // virtual const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const { - LLRect rect = LLRect::null; - if (mScrolledView) - { - LLFolderView* folder_view = dynamic_cast(mScrolledView); - if (folder_view) - { - S32 height = folder_view->getRect().getHeight(); + LLRect rect = LLRect::null; + if (mScrolledView) + { + LLFolderView* folder_view = dynamic_cast(mScrolledView); + if (folder_view) + { + S32 height = folder_view->getRect().getHeight(); - rect = mScrolledView->getRect(); - rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); - } - } + rect = mScrolledView->getRect(); + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); + } + } - return rect; + return rect; } LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) -: LLScrollContainer(p) +: LLScrollContainer(p) {} ///---------------------------------------------------------------------------- /// Class LLFolderView ///---------------------------------------------------------------------------- LLFolderView::Params::Params() -: title("title"), - use_label_suffix("use_label_suffix"), - allow_multiselect("allow_multiselect", true), - allow_drag("allow_drag", true), - show_empty_message("show_empty_message", true), - suppress_folder_menu("suppress_folder_menu", false), - use_ellipses("use_ellipses", false), +: title("title"), + use_label_suffix("use_label_suffix"), + allow_multiselect("allow_multiselect", true), + allow_drag("allow_drag", true), + show_empty_message("show_empty_message", true), + suppress_folder_menu("suppress_folder_menu", false), + use_ellipses("use_ellipses", false), options_menu("options_menu", "") { - folder_indentation = -4; + folder_indentation = -4; } // Default constructor 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), - mShowFolderHierarchy(FALSE), - mRenameItem( NULL ), - mNeedsScroll( FALSE ), - mUseLabelSuffix(p.use_label_suffix), - mSuppressFolderMenu(p.suppress_folder_menu), - mPinningSelectedItem(FALSE), - mNeedsAutoSelect( FALSE ), - mAutoSelectOverride(FALSE), - mNeedsAutoRename(FALSE), - mShowSelectionContext(FALSE), - mShowSingleSelection(FALSE), - mArrangeGeneration(0), - mSignalSelectCallback(0), - mMinWidth(0), - mDragAndDropThisFrame(FALSE), - mCallbackRegistrar(NULL), - mEnableRegistrar(NULL), - mUseEllipses(p.use_ellipses), - mDraggingOverItem(NULL), - mStatusTextBox(NULL), - mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model), +: LLFolderViewFolder(p), + mScrollContainer( NULL ), + mPopupMenuHandle(), + mMenuFileName(p.options_menu), + mAllowMultiSelect(p.allow_multiselect), + mAllowDrag(p.allow_drag), + mShowEmptyMessage(p.show_empty_message), + mShowFolderHierarchy(FALSE), + mRenameItem( NULL ), + mNeedsScroll( FALSE ), + mUseLabelSuffix(p.use_label_suffix), + mSuppressFolderMenu(p.suppress_folder_menu), + mPinningSelectedItem(FALSE), + mNeedsAutoSelect( FALSE ), + mAutoSelectOverride(FALSE), + mNeedsAutoRename(FALSE), + mShowSelectionContext(FALSE), + mShowSingleSelection(FALSE), + mArrangeGeneration(0), + mSignalSelectCallback(0), + mMinWidth(0), + mDragAndDropThisFrame(FALSE), + mCallbackRegistrar(NULL), + mEnableRegistrar(NULL), + mUseEllipses(p.use_ellipses), + mDraggingOverItem(NULL), + mStatusTextBox(NULL), + mShowItemLinkOverlays(p.show_item_link_overlays), + mViewModel(p.view_model), mGroupedItemModel(p.grouped_item_model), mForceArrange(false), mSingleFolderMode(false) { LLPanel* panel = p.parent_panel; mParentPanel = panel->getHandle(); - mViewModel->setFolderView(this); - mRoot = this; - - LLRect rect = p.rect; - LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); - setRect( rect ); - reshape(rect.getWidth(), rect.getHeight()); - mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); - mKeyboardSelection = FALSE; - mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0; - - //clear label - // go ahead and render root folder as usual - // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; - - // Escape is handled by reverting the rename, not commiting it (default behavior) - LLLineEditor::Params params; - params.name("ren"); - params.rect(rect); - params.font(getLabelFontForStyle(LLFontGL::NORMAL)); - params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); - params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); - params.commit_on_focus_lost(true); - params.visible(false); - mRenamer = LLUICtrlFactory::create (params); - addChild(mRenamer); - - // Textbox - LLTextBox::Params text_p; - LLFontGL* font = getLabelFontForStyle(mLabelStyle); + mViewModel->setFolderView(this); + mRoot = this; + + LLRect rect = p.rect; + LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); + setRect( rect ); + reshape(rect.getWidth(), rect.getHeight()); + mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); + mKeyboardSelection = FALSE; + mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0; + + //clear label + // go ahead and render root folder as usual + // just make sure the label ("Inventory Folder") never shows up + mLabel = LLStringUtil::null; + + // Escape is handled by reverting the rename, not commiting it (default behavior) + LLLineEditor::Params params; + params.name("ren"); + params.rect(rect); + params.font(getLabelFontForStyle(LLFontGL::NORMAL)); + params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); + params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); + params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); + params.commit_on_focus_lost(true); + params.visible(false); + mRenamer = LLUICtrlFactory::create (params); + addChild(mRenamer); + + // Textbox + LLTextBox::Params text_p; + LLFontGL* font = getLabelFontForStyle(mLabelStyle); //mIconPad, mTextPad are set in folder_view_item.xml - LLRect new_r = LLRect(rect.mLeft + mIconPad, - rect.mTop - mTextPad, - rect.mRight, - rect.mTop - mTextPad - font->getLineHeight()); - text_p.rect(new_r); - text_p.name(std::string(p.name)); - text_p.font(font); - text_p.visible(false); - text_p.parse_urls(true); - text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 - // set text padding the same as in People panel. EXT-7047, EXT-4837 - text_p.h_pad(STATUS_TEXT_HPAD); - text_p.v_pad(STATUS_TEXT_VPAD); - mStatusTextBox = LLUICtrlFactory::create (text_p); - mStatusTextBox->setFollowsLeft(); - mStatusTextBox->setFollowsTop(); - addChild(mStatusTextBox); - - mViewModelItem->openItem(); - - mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. + LLRect new_r = LLRect(rect.mLeft + mIconPad, + rect.mTop - mTextPad, + rect.mRight, + rect.mTop - mTextPad - font->getLineHeight()); + text_p.rect(new_r); + text_p.name(std::string(p.name)); + text_p.font(font); + text_p.visible(false); + text_p.parse_urls(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); + mStatusTextBox = LLUICtrlFactory::create (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + addChild(mStatusTextBox); + + mViewModelItem->openItem(); + + mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. } // Destroys the object LLFolderView::~LLFolderView( void ) { - closeRenamer(); + closeRenamer(); - // The release focus call can potentially call the - // scrollcontainer, which can potentially be called with a partly - // destroyed scollcontainer. Just null it out here, and no worries - // about calling into the invalid scroll container. - // Same with the renamer. - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; + // The release focus call can potentially call the + // scrollcontainer, which can potentially be called with a partly + // destroyed scollcontainer. Just null it out here, and no worries + // about calling into the invalid scroll container. + // Same with the renamer. + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle.markDead(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); - mAutoOpenItems.removeAllNodes(); - clearSelection(); - mItems.clear(); - mFolders.clear(); + mAutoOpenItems.removeAllNodes(); + clearSelection(); + mItems.clear(); + mFolders.clear(); - //mViewModel->setFolderView(NULL); - mViewModel = NULL; + //mViewModel->setFolderView(NULL); + mViewModel = NULL; } BOOL LLFolderView::canFocusChildren() const { - return FALSE; + return FALSE; } void LLFolderView::addFolder( LLFolderViewFolder* folder) { - LLFolderViewFolder::addFolder(folder); + LLFolderViewFolder::addFolder(folder); } void LLFolderView::closeAllFolders() { - // Close all the folders - setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); - arrangeAll(); + // Close all the folders + setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + arrangeAll(); } void LLFolderView::openTopLevelFolders() { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpen(TRUE); - } + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpen(TRUE); + } } // This view grows and shrinks to enclose all of its children items and folders. // *width should be 0 // conform show folder state works S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) - { - mMinWidth = 0; - S32 target_height; + { + mMinWidth = 0; + S32 target_height; - LLFolderViewFolder::arrange(&mMinWidth, &target_height); + LLFolderViewFolder::arrange(&mMinWidth, &target_height); - LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); + LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); - LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) - { - reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); - } + LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) + { + reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); + } - // move item renamer text field to item's new position - updateRenamerPosition(); + // move item renamer text field to item's new position + updateRenamerPosition(); - return ll_round(mTargetHeight); + return ll_round(mTargetHeight); } void LLFolderView::filter( LLFolderViewFilter& filter ) @@ -340,77 +340,77 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100)); // Note: we filter the model, not the view - getViewModelItem()->filter(filter); + getViewModelItem()->filter(filter); } void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLRect scroll_rect; - if (mScrollContainer) - { - LLView::reshape(width, height, called_from_parent); - scroll_rect = mScrollContainer->getContentWindowRect(); - } - width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(ll_round(mCurHeight), scroll_rect.getHeight()); + LLRect scroll_rect; + if (mScrollContainer) + { + LLView::reshape(width, height, called_from_parent); + scroll_rect = mScrollContainer->getContentWindowRect(); + } + width = llmax(mMinWidth, scroll_rect.getWidth()); + height = llmax(ll_round(mCurHeight), scroll_rect.getHeight()); - // Restrict width within scroll container's width - if (mUseEllipses && mScrollContainer) - { - width = scroll_rect.getWidth(); - } - LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, FALSE); + // Restrict width within scroll container's width + if (mUseEllipses && mScrollContainer) + { + width = scroll_rect.getWidth(); + } + LLView::reshape(width, height, called_from_parent); + mReshapeSignal(mSelectedItems, FALSE); } void LLFolderView::addToSelectionList(LLFolderViewItem* item) { - if (item->isSelected()) - { - removeFromSelectionList(item); - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - item->setIsCurSelection(TRUE); - mSelectedItems.push_back(item); + if (item->isSelected()) + { + removeFromSelectionList(item); + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + item->setIsCurSelection(TRUE); + mSelectedItems.push_back(item); } void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) { - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) - { - if (*item_iter == item) - { - item_iter = mSelectedItems.erase(item_iter); - } - else - { - ++item_iter; - } - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(TRUE); - } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) + { + if (*item_iter == item) + { + item_iter = mSelectedItems.erase(item_iter); + } + else + { + ++item_iter; + } + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(TRUE); + } } LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) { - if(mSelectedItems.size()) - { - LLFolderViewItem* itemp = mSelectedItems.back(); - llassert(itemp->getIsCurSelection()); - return itemp; - } - return NULL; + if(mSelectedItems.size()) + { + LLFolderViewItem* itemp = mSelectedItems.back(); + llassert(itemp->getIsCurSelection()); + return itemp; + } + return NULL; } LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) @@ -420,281 +420,281 @@ LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) // Record the selected item and pass it down the hierachy. BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) + BOOL take_keyboard_focus) { - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - if( selection == this ) - { - return FALSE; - } + if( selection == this ) + { + return FALSE; + } - if( selection && take_keyboard_focus) - { - mParentPanel.get()->setFocus(TRUE); - } + if( selection && take_keyboard_focus) + { + mParentPanel.get()->setFocus(TRUE); + } - // clear selection down here because change of keyboard focus can potentially - // affect selection - clearSelection(); + // clear selection down here because change of keyboard focus can potentially + // affect selection + clearSelection(); - if(selection) - { - addToSelectionList(selection); - } + if(selection) + { + addToSelectionList(selection); + } - BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); - if(openitem && selection) - { - selection->getParentFolder()->requestArrange(); - } + BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + if(openitem && selection) + { + selection->getParentFolder()->requestArrange(); + } - llassert(mSelectedItems.size() <= 1); + llassert(mSelectedItems.size() <= 1); - return rv; + return rv; } BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) { - BOOL rv = FALSE; + BOOL rv = FALSE; + + // can't select root folder + if(!selection || selection == this) + { + return FALSE; + } - // can't select root folder - if(!selection || selection == this) - { - return FALSE; - } + if (!mAllowMultiSelect) + { + clearSelection(); + } - if (!mAllowMultiSelect) - { - clearSelection(); - } + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + if (*item_iter == selection) + { + break; + } + } - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - if (*item_iter == selection) - { - break; - } - } + BOOL on_list = (item_iter != mSelectedItems.end()); - BOOL on_list = (item_iter != mSelectedItems.end()); + if(selected && !on_list) + { + addToSelectionList(selection); + } + if(!selected && on_list) + { + removeFromSelectionList(selection); + } - if(selected && !on_list) - { - addToSelectionList(selection); - } - if(!selected && on_list) - { - removeFromSelectionList(selection); - } + rv = LLFolderViewFolder::changeSelection(selection, selected); - rv = LLFolderViewFolder::changeSelection(selection, selected); + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - - return rv; + return rv; } void LLFolderView::sanitizeSelection() { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - // store off current item in case it is automatically deselected - // and we want to preserve context - LLFolderViewItem* original_selected_item = getCurSelectedItem(); - - std::vector items_to_remove; - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewItem* item = *item_iter; - - // ensure that each ancestor is open and potentially passes filtering - BOOL visible = false; - if(item->getViewModelItem() != NULL) - { - visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item - } - // modify with parent open and filters states - LLFolderViewFolder* parent_folder = item->getParentFolder(); - // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - - // deselect item if any ancestor is closed or didn't pass filter requirements. - if (!visible) - { - items_to_remove.push_back(item); - } - - // disallow nested selections (i.e. folder items plus one or more ancestors) - // could check cached mum selections count and only iterate if there are any - // but that may be a premature optimization. - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) - { - LLFolderViewItem* other_item = *other_item_iter; - for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - } - } - - // Don't allow invisible items (such as root folders) to be selected. - if (item == getRoot()) - { - items_to_remove.push_back(item); - } - } - - std::vector::iterator item_it; - for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) - { - changeSelection(*item_it, FALSE); // toggle selection (also removes from list) - } - - // if nothing selected after prior constraints... - if (mSelectedItems.empty()) - { - // ...select first available parent of original selection - LLFolderViewItem* new_selection = NULL; - if (original_selected_item) - { - for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); - parent_folder; - parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible()) - { - // give initial selection to first ancestor folder that potentially passes the filter - if (!new_selection) - { - new_selection = parent_folder; - } - - // if any ancestor folder of original item is closed, move the selection up - // to the highest closed - if (!parent_folder->isOpen()) - { - new_selection = parent_folder; - } - } - } - } - else - { - new_selection = NULL; - } - - if (new_selection) - { - setSelection(new_selection, FALSE, FALSE); - } - } + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + + std::vector items_to_remove; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewItem* item = *item_iter; + + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = false; + if(item->getViewModelItem() != NULL) + { + visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + } + // modify with parent open and filters states + LLFolderViewFolder* parent_folder = item->getParentFolder(); + // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) + { + items_to_remove.push_back(item); + } + + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder == item) + { + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; + } + } + } + + // Don't allow invisible items (such as root folders) to be selected. + if (item == getRoot()) + { + items_to_remove.push_back(item); + } + } + + std::vector::iterator item_it; + for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) + { + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + new_selection = NULL; + } + + if (new_selection) + { + setSelection(new_selection, FALSE, FALSE); + } + } } void LLFolderView::clearSelection() { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) - { - (*item_it)->setUnselected(); - } + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) + { + (*item_it)->setUnselected(); + } - mSelectedItems.clear(); + mSelectedItems.clear(); mNeedsScroll = false; } std::set LLFolderView::getSelectionList() const { - std::set selection; - std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); - return selection; + std::set selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); + return selection; } bool LLFolderView::startDrag() { - std::vector selected_items; - selected_items_t::iterator item_it; + std::vector selected_items; + selected_items_t::iterator item_it; - if (!mSelectedItems.empty()) - { - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - selected_items.push_back((*item_it)->getViewModelItem()); - } + if (!mSelectedItems.empty()) + { + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + selected_items.push_back((*item_it)->getViewModelItem()); + } - return getFolderViewModel()->startDrag(selected_items); - } - return false; + return getFolderViewModel()->startDrag(selected_items); + } + return false; } void LLFolderView::commitRename( const LLSD& data ) { - finishRenamingItem(); - arrange( NULL, NULL ); + finishRenamingItem(); + arrange( NULL, NULL ); } void LLFolderView::draw() { - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - // if cursor has moved off of me during drag and drop - // close all auto opened folders - if (!mDragAndDropThisFrame) - { - closeAutoOpenedFolders(); - } - - static LLCachedControl type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f); - if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size()) - { - mSearchString.clear(); - } - - if (hasVisibleChildren()) - { - mStatusTextBox->setVisible( FALSE ); - } - else if (mShowEmptyMessage) - { - mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); - mStatusTextBox->setVisible( TRUE ); - - // firstly reshape message textbox with current size. This is necessary to - // LLTextBox::getTextPixelHeight works properly - const LLRect local_rect = getLocalRect(); - mStatusTextBox->setShape(local_rect); - - // get preferable text height... - S32 pixel_height = mStatusTextBox->getTextPixelHeight(); - bool height_changed = (local_rect.getHeight() < pixel_height); - if (height_changed) - { - // ... if it does not match current height, lets rearrange current view. - // This will indirectly call ::arrange and reshape of the status textbox. - // We should call this method to also notify parent about required rect. - // See EXT-7564, EXT-7047. - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - - LLUI::popMatrix(); - LLUI::pushMatrix(); - LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); - } - } + //LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + // if cursor has moved off of me during drag and drop + // close all auto opened folders + if (!mDragAndDropThisFrame) + { + closeAutoOpenedFolders(); + } + + static LLCachedControl type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f); + if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size()) + { + mSearchString.clear(); + } + + if (hasVisibleChildren()) + { + mStatusTextBox->setVisible( FALSE ); + } + else if (mShowEmptyMessage) + { + mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); + mStatusTextBox->setVisible( TRUE ); + + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = (local_rect.getHeight() < pixel_height); + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); + } + } if (mRenameItem && mRenamer @@ -707,342 +707,342 @@ void LLFolderView::draw() finishRenamingItem(); } - // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, - // and arrow for the root folder - LLView::draw(); + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, + // and arrow for the root folder + LLView::draw(); - mDragAndDropThisFrame = FALSE; + mDragAndDropThisFrame = FALSE; } void LLFolderView::finishRenamingItem( void ) { - if(!mRenamer) - { - return; - } - if( mRenameItem ) - { - mRenameItem->rename( mRenamer->getText() ); - } + if(!mRenamer) + { + return; + } + if( mRenameItem ) + { + mRenameItem->rename( mRenamer->getText() ); + } - closeRenamer(); + closeRenamer(); - // This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611). - // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. - //scrollToShowSelection(); + // This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611). + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. + //scrollToShowSelection(); } void LLFolderView::closeRenamer( void ) { - if (mRenamer && mRenamer->getVisible()) - { - // Triggers onRenamerLost() that actually closes the renamer. - LLUI::getInstance()->removePopup(mRenamer); - } + if (mRenamer && mRenamer->getVisible()) + { + // Triggers onRenamerLost() that actually closes the renamer. + LLUI::getInstance()->removePopup(mRenamer); + } } void LLFolderView::removeSelectedItems() { - if(getVisible() && getEnabled()) - { - // just in case we're removing the renaming item. - mRenameItem = NULL; - - // create a temporary structure which we will use to remove - // items, since the removal will futz with internal data - // structures. - std::vector items; - S32 count = mSelectedItems.size(); - if(count <= 0) return; - LLFolderViewItem* item = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - item = *item_it; - if (item && item->isRemovable()) - { - items.push_back(item); - } - else - { - LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL; - return; - } - } - - // iterate through the new container. - count = items.size(); - LLUUID new_selection_id; - LLFolderViewItem* item_to_select = getNextUnselectedItem(); - - if(count == 1) - { - LLFolderViewItem* item_to_delete = items[0]; - LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - if(parent) - { - if (item_to_delete->remove()) - { - // change selection on successful delete - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - } - } - arrangeAll(); - } - else if (count > 1) - { - std::vector listeners; - LLFolderViewModelItem* listener; - - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - - listeners.reserve(count); - for(S32 i = 0; i < count; ++i) - { - listener = items[i]->getViewModelItem(); - if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) - { - listeners.push_back(listener); - } - } - listener = static_cast(listeners.at(0)); - if(listener) - { - listener->removeBatch(listeners); - } - } - arrangeAll(); - scrollToShowSelection(); - } + if(getVisible() && getEnabled()) + { + // just in case we're removing the renaming item. + mRenameItem = NULL; + + // create a temporary structure which we will use to remove + // items, since the removal will futz with internal data + // structures. + std::vector items; + S32 count = mSelectedItems.size(); + if(count <= 0) return; + LLFolderViewItem* item = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + item = *item_it; + if (item && item->isRemovable()) + { + items.push_back(item); + } + else + { + LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL; + return; + } + } + + // iterate through the new container. + count = items.size(); + LLUUID new_selection_id; + LLFolderViewItem* item_to_select = getNextUnselectedItem(); + + if(count == 1) + { + LLFolderViewItem* item_to_delete = items[0]; + LLFolderViewFolder* parent = item_to_delete->getParentFolder(); + if(parent) + { + if (item_to_delete->remove()) + { + // change selection on successful delete + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + } + } + arrangeAll(); + } + else if (count > 1) + { + std::vector listeners; + LLFolderViewModelItem* listener; + + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + + listeners.reserve(count); + for(S32 i = 0; i < count; ++i) + { + listener = items[i]->getViewModelItem(); + if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) + { + listeners.push_back(listener); + } + } + listener = static_cast(listeners.at(0)); + if(listener) + { + listener->removeBatch(listeners); + } + } + arrangeAll(); + scrollToShowSelection(); + } } void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { - if ((mAutoOpenItems.check() == item) || - (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || - item->isOpen()) - { - return; - } - - // close auto-opened folders - LLFolderViewFolder* close_item = mAutoOpenItems.check(); - while (close_item && close_item != item->getParentFolder()) - { - mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(FALSE); - close_item = mAutoOpenItems.check(); - } - - item->requestArrange(); - - mAutoOpenItems.push(item); - - item->setOpen(TRUE); + if ((mAutoOpenItems.check() == item) || + (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || + item->isOpen()) + { + return; + } + + // close auto-opened folders + LLFolderViewFolder* close_item = mAutoOpenItems.check(); + while (close_item && close_item != item->getParentFolder()) + { + mAutoOpenItems.pop(); + close_item->setOpenArrangeRecursively(FALSE); + close_item = mAutoOpenItems.check(); + } + + item->requestArrange(); + + 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); + 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() { - while (mAutoOpenItems.check()) - { - LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(FALSE); - } + while (mAutoOpenItems.check()) + { + LLFolderViewFolder* close_item = mAutoOpenItems.pop(); + close_item->setOpen(FALSE); + } - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); } BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) { - if (folder && mAutoOpenCandidate == folder) - { - if (mAutoOpenTimer.getStarted()) - { - if (!mAutoOpenCandidate->isOpen()) - { - mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); - } - if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) - { - autoOpenItem(folder); - mAutoOpenTimer.stop(); - return TRUE; - } - } - return FALSE; - } - - // otherwise new candidate, restart timer - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = folder; - mAutoOpenTimer.start(); - return FALSE; + if (folder && mAutoOpenCandidate == folder) + { + if (mAutoOpenTimer.getStarted()) + { + if (!mAutoOpenCandidate->isOpen()) + { + mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); + } + if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) + { + autoOpenItem(folder); + mAutoOpenTimer.stop(); + return TRUE; + } + } + return FALSE; + } + + // otherwise new candidate, restart timer + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = folder; + mAutoOpenTimer.start(); + return FALSE; } BOOL LLFolderView::canCopy() const { - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - if (!item->getViewModelItem()->isItemCopyable()) - { - return FALSE; - } - } - return TRUE; + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + if (!item->getViewModelItem()->isItemCopyable()) + { + return FALSE; + } + } + return TRUE; } // copy selected item void LLFolderView::copy() { - // *NOTE: total hack to clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->copyToClipboard(); - } - } - } - mSearchString.clear(); + // *NOTE: total hack to clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->copyToClipboard(); + } + } + } + mSearchString.clear(); } BOOL LLFolderView::canCut() const { - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItem* listener = item->getViewModelItem(); + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } - if (!listener || !listener->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + const LLFolderViewModelItem* listener = item->getViewModelItem(); + + if (!listener || !listener->isItemRemovable()) + { + return FALSE; + } + } + return TRUE; } void LLFolderView::cut() { - // clear the inventory clipboard - LLClipboard::instance().reset(); - if(getVisible() && getEnabled() && (mSelectedItems.size() > 0)) - { - // Find out which item will be selected once the selection will be cut - LLFolderViewItem* item_to_select = getNextUnselectedItem(); - - // Get the selection: removeItem() modified mSelectedItems and makes iterating on it unwise - std::set inventory_selected = getSelectionList(); - - // Move each item to the clipboard and out of their folder - for (std::set::iterator item_it = inventory_selected.begin(); item_it != inventory_selected.end(); ++item_it) - { - LLFolderViewItem* item_to_cut = *item_it; - LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); - if (listener) - { - listener->cutToClipboard(); - } - } - - // Update the selection - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - } - mSearchString.clear(); + // clear the inventory clipboard + LLClipboard::instance().reset(); + if(getVisible() && getEnabled() && (mSelectedItems.size() > 0)) + { + // Find out which item will be selected once the selection will be cut + LLFolderViewItem* item_to_select = getNextUnselectedItem(); + + // Get the selection: removeItem() modified mSelectedItems and makes iterating on it unwise + std::set inventory_selected = getSelectionList(); + + // Move each item to the clipboard and out of their folder + for (std::set::iterator item_it = inventory_selected.begin(); item_it != inventory_selected.end(); ++item_it) + { + LLFolderViewItem* item_to_cut = *item_it; + LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); + if (listener) + { + listener->cutToClipboard(); + } + } + + // Update the selection + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + } + mSearchString.clear(); } BOOL LLFolderView::canPaste() const { - if (mSelectedItems.empty()) - { - return FALSE; - } - - if(getVisible() && getEnabled()) - { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); ++item_it) - { - // *TODO: only check folders and parent folders of items - const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItem* listener = item->getViewModelItem(); - if(!listener || !listener->isClipboardPasteable()) - { - const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getViewModelItem(); - if (!listener || !listener->isClipboardPasteable()) - { - return FALSE; - } - } - } - return TRUE; - } - return FALSE; + if (mSelectedItems.empty()) + { + return FALSE; + } + + if(getVisible() && getEnabled()) + { + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); ++item_it) + { + // *TODO: only check folders and parent folders of items + const LLFolderViewItem* item = (*item_it); + const LLFolderViewModelItem* listener = item->getViewModelItem(); + if(!listener || !listener->isClipboardPasteable()) + { + const LLFolderViewFolder* folderp = item->getParentFolder(); + listener = folderp->getViewModelItem(); + if (!listener || !listener->isClipboardPasteable()) + { + return FALSE; + } + } + } + return TRUE; + } + return FALSE; } // paste selected item void LLFolderView::paste() { - if(getVisible() && getEnabled()) - { - // find set of unique folders to paste into - std::set folder_set; - - selected_items_t::iterator selected_it; - for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - LLFolderViewItem* item = *selected_it; - LLFolderViewFolder* folder = dynamic_cast(item); - if (folder == NULL) - { - folder = item->getParentFolder(); - } - folder_set.insert(folder); - } - - std::set::iterator set_iter; - for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) - { - LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); - if(listener && listener->isClipboardPasteable()) - { - listener->pasteFromClipboard(); - } - } - } - mSearchString.clear(); + if(getVisible() && getEnabled()) + { + // find set of unique folders to paste into + std::set folder_set; + + selected_items_t::iterator selected_it; + for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + LLFolderViewItem* item = *selected_it; + LLFolderViewFolder* folder = dynamic_cast(item); + if (folder == NULL) + { + folder = item->getParentFolder(); + } + folder_set.insert(folder); + } + + std::set::iterator set_iter; + for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) + { + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); + if(listener && listener->isClipboardPasteable()) + { + listener->pasteFromClipboard(); + } + } + } + mSearchString.clear(); } // public rename functionality - can only start the process @@ -1050,431 +1050,431 @@ void LLFolderView::startRenamingSelectedItem( void ) { LL_DEBUGS("Inventory") << "Starting inventory renamer" << LL_ENDL; - // make sure selection is visible - scrollToShowSelection(); + // make sure selection is visible + scrollToShowSelection(); - S32 count = mSelectedItems.size(); - LLFolderViewItem* item = NULL; - if(count > 0) - { - item = mSelectedItems.front(); - } - if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && - item->getViewModelItem()->isItemRenameable()) - { - mRenameItem = item; + S32 count = mSelectedItems.size(); + LLFolderViewItem* item = NULL; + if(count > 0) + { + item = mSelectedItems.front(); + } + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) + { + mRenameItem = item; - updateRenamerPosition(); + updateRenamerPosition(); - mRenamer->setText(item->getName()); - mRenamer->selectAll(); - mRenamer->setVisible( TRUE ); - // set focus will fail unless item is visible - mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - LLUI::getInstance()->addPopup(mRenamer); - } + mRenamer->setText(item->getName()); + mRenamer->selectAll(); + mRenamer->setVisible( TRUE ); + // set focus will fail unless item is visible + mRenamer->setFocus( TRUE ); + mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + LLUI::getInstance()->addPopup(mRenamer); + } } BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { - BOOL handled = FALSE; - - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - switch( key ) - { - case KEY_F2: - mSearchString.clear(); - startRenamingSelectedItem(); - handled = TRUE; - break; - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( mRenameItem && mRenamer->getVisible() ) - { - finishRenamingItem(); - mSearchString.clear(); - handled = TRUE; - } - } - break; - - case KEY_ESCAPE: - if( mRenameItem && mRenamer->getVisible() ) - { - closeRenamer(); - handled = TRUE; - } - mSearchString.clear(); - break; - - case KEY_PAGE_UP: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->pageUp(30); - } - handled = TRUE; - break; - - case KEY_PAGE_DOWN: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->pageDown(30); - } - handled = TRUE; - break; - - case KEY_HOME: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->goToTop(); - } - handled = TRUE; - break; - - case KEY_END: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->goToBottom(); - } - break; - - case KEY_DOWN: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - BOOL shift_select = mask & MASK_SHIFT; - // don't shift select down to children of folders (they are implicitly selected through parent) - LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); - - if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - if (shift_select) - { - if (next) - { - if (next->isSelected()) - { - // shrink selection - changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == next->getParentFolder()) - { - // grow selection - changeSelection(next, TRUE); - } - } - } - else - { - if( next ) - { - if (next == last_selected) - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - setSelection( next, FALSE, TRUE ); - } - else - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - } - scrollToShowSelection(); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_UP: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = mSelectedItems.back(); - BOOL shift_select = mask & MASK_SHIFT; - // don't shift select down to children of folders (they are implicitly selected through parent) - LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); - - if (!mKeyboardSelection || (!shift_select && prev == this)) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - if (shift_select) - { - if (prev) - { - if (prev->isSelected()) - { - // shrink selection - changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == prev->getParentFolder()) - { - // grow selection - changeSelection(prev, TRUE); - } - } - } - else - { - if( prev ) - { - if (prev == this) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - - return FALSE; - } - setSelection( prev, FALSE, TRUE ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - - handled = TRUE; - } - break; - - case KEY_RIGHT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( TRUE ); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_LEFT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); + BOOL handled = FALSE; + + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + switch( key ) + { + case KEY_F2: + mSearchString.clear(); + startRenamingSelectedItem(); + handled = TRUE; + break; + + case KEY_RETURN: + if (mask == MASK_NONE) + { + if( mRenameItem && mRenamer->getVisible() ) + { + finishRenamingItem(); + mSearchString.clear(); + handled = TRUE; + } + } + break; + + case KEY_ESCAPE: + if( mRenameItem && mRenamer->getVisible() ) + { + closeRenamer(); + handled = TRUE; + } + mSearchString.clear(); + break; + + case KEY_PAGE_UP: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->pageUp(30); + } + handled = TRUE; + break; + + case KEY_PAGE_DOWN: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->pageDown(30); + } + handled = TRUE; + break; + + case KEY_HOME: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } + handled = TRUE; + break; + + case KEY_END: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->goToBottom(); + } + break; + + case KEY_DOWN: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + BOOL shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); + + if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + if (shift_select) + { + if (next) + { + if (next->isSelected()) + { + // shrink selection + changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == next->getParentFolder()) + { + // grow selection + changeSelection(next, TRUE); + } + } + } + else + { + if( next ) + { + if (next == last_selected) + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + setSelection( next, FALSE, TRUE ); + } + else + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + } + scrollToShowSelection(); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_UP: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = mSelectedItems.back(); + BOOL shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); + + if (!mKeyboardSelection || (!shift_select && prev == this)) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + if (shift_select) + { + if (prev) + { + if (prev->isSelected()) + { + // shrink selection + changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == prev->getParentFolder()) + { + // grow selection + changeSelection(prev, TRUE); + } + } + } + else + { + if( prev ) + { + if (prev == this) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + + return FALSE; + } + setSelection( prev, FALSE, TRUE ); + } + } + scrollToShowSelection(); + mSearchString.clear(); + + handled = TRUE; + } + break; + + case KEY_RIGHT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + last_selected->setOpen( TRUE ); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_LEFT: + 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()) - { - setSelection(parent_folder, FALSE, TRUE); - } - else - { - last_selected->setOpen( FALSE ); - } - mSearchString.clear(); - scrollToShowSelection(); - handled = TRUE; - } - break; - } - - return handled; + LLFolderViewItem* parent_folder = last_selected->getParentFolder(); + if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) + { + setSelection(parent_folder, FALSE, TRUE); + } + else + { + last_selected->setOpen( FALSE ); + } + mSearchString.clear(); + scrollToShowSelection(); + handled = TRUE; + } + break; + } + + return handled; } BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) { - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return FALSE; - } - - if (uni_char > 0x7f) - { - LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; - return FALSE; - } - - BOOL handled = FALSE; - if (mParentPanel.get()->hasFocus()) - { - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - //do text search - if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout")) - { - mSearchString.clear(); - } - mSearchTimer.reset(); - if (mSearchString.size() < 128) - { - mSearchString += uni_char; - } - search(getCurSelectedItem(), mSearchString, FALSE); - - handled = TRUE; - } - - return handled; + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL + { + return FALSE; + } + + if (uni_char > 0x7f) + { + LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; + return FALSE; + } + + BOOL handled = FALSE; + if (mParentPanel.get()->hasFocus()) + { + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + //do text search + if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout")) + { + mSearchString.clear(); + } + mSearchTimer.reset(); + if (mSearchString.size() < 128) + { + mSearchString += uni_char; + } + search(getCurSelectedItem(), mSearchString, FALSE); + + handled = TRUE; + } + + return handled; } BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) { - mKeyboardSelection = FALSE; - mSearchString.clear(); + mKeyboardSelection = FALSE; + mSearchString.clear(); - mParentPanel.get()->setFocus(TRUE); + mParentPanel.get()->setFocus(TRUE); - LLEditMenuHandler::gEditMenuHandler = this; + LLEditMenuHandler::gEditMenuHandler = this; - return LLView::handleMouseDown( x, y, mask ); + return LLView::handleMouseDown( x, y, mask ); } BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) { - // get first selected item - LLFolderViewItem* search_item = first_item; - - // make sure search string is upper case - std::string upper_case_string = search_string; - LLStringUtil::toUpper(upper_case_string); - - // if nothing selected, select first item in folder - if (!search_item) - { - // start from first item - search_item = getNextFromChild(NULL); - } - - // search over all open nodes for first substring match (with wrapping) - BOOL found = FALSE; - LLFolderViewItem* original_search_item = search_item; - do - { - // wrap at end - if (!search_item) - { - if (backward) - { - search_item = getPreviousFromChild(NULL); - } - else - { - search_item = getNextFromChild(NULL); - } - if (!search_item || search_item == original_search_item) - { - break; - } - } - - std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); - LLStringUtil::toUpper(current_item_label); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); - if (!current_item_label.compare(0, search_string_length, upper_case_string)) - { - found = TRUE; - break; - } - if (backward) - { - search_item = search_item->getPreviousOpenNode(); - } - else - { - search_item = search_item->getNextOpenNode(); - } - - } while(search_item != original_search_item); - - - if (found) - { - setSelection(search_item, FALSE, TRUE); - scrollToShowSelection(); - } - - return found; + // get first selected item + LLFolderViewItem* search_item = first_item; + + // make sure search string is upper case + std::string upper_case_string = search_string; + LLStringUtil::toUpper(upper_case_string); + + // if nothing selected, select first item in folder + if (!search_item) + { + // start from first item + search_item = getNextFromChild(NULL); + } + + // search over all open nodes for first substring match (with wrapping) + BOOL found = FALSE; + LLFolderViewItem* original_search_item = search_item; + do + { + // wrap at end + if (!search_item) + { + if (backward) + { + search_item = getPreviousFromChild(NULL); + } + else + { + search_item = getNextFromChild(NULL); + } + if (!search_item || search_item == original_search_item) + { + break; + } + } + + std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); + LLStringUtil::toUpper(current_item_label); + S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + if (!current_item_label.compare(0, search_string_length, upper_case_string)) + { + found = TRUE; + break; + } + if (backward) + { + search_item = search_item->getPreviousOpenNode(); + } + else + { + search_item = search_item->getNextOpenNode(); + } + + } while(search_item != original_search_item); + + + if (found) + { + setSelection(search_item, FALSE, TRUE); + scrollToShowSelection(); + } + + return found; } BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) { - // skip LLFolderViewFolder::handleDoubleClick() - return LLView::handleDoubleClick( x, y, mask ); + // skip LLFolderViewFolder::handleDoubleClick() + return LLView::handleDoubleClick( x, y, mask ); } BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - // all user operations move keyboard focus to inventory - // this way, we know when to stop auto-updating a search - mParentPanel.get()->setFocus(TRUE); - - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); - - LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); - if (!menu) - { - if (mCallbackRegistrar) - { - mCallbackRegistrar->pushScope(); - } - if (mEnableRegistrar) - { - mEnableRegistrar->pushScope(); - } - llassert(LLMenuGL::sMenuContainer != NULL); - menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - if (mEnableRegistrar) - { - mEnableRegistrar->popScope(); - } - if (mCallbackRegistrar) - { - mCallbackRegistrar->popScope(); - } - } + // all user operations move keyboard focus to inventory + // this way, we know when to stop auto-updating a search + mParentPanel.get()->setFocus(TRUE); + + BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + S32 count = mSelectedItems.size(); + + LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); + if (!menu) + { + if (mCallbackRegistrar) + { + mCallbackRegistrar->pushScope(); + } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } + if (mCallbackRegistrar) + { + mCallbackRegistrar->popScope(); + } + } BOOL item_clicked = FALSE; for (selected_items_t::iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) @@ -1485,207 +1485,207 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) { clearSelection(); } - bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if (menu && (mSingleFolderMode || (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(); - } - } - else - { - if (menu && menu->getVisible()) - { - menu->setVisible(FALSE); - } - setSelection(NULL, FALSE, TRUE); - } - return handled; + bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); + if (menu && (mSingleFolderMode || (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(); + } + } + else + { + if (menu && menu->getVisible()) + { + menu->setVisible(FALSE); + } + setSelection(NULL, FALSE, TRUE); + } + return handled; } // Add "--no options--" if the menu is completely blank. BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const { - const std::string nooptions_str = "--no options--"; - LLView *nooptions_item = NULL; - - const LLView::child_list_t *list = menu->getChildList(); - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) - { - LLView *menu_item = (*itor); - if (menu_item->getVisible()) - { - return FALSE; - } - std::string name = menu_item->getName(); - if (menu_item->getName() == nooptions_str) - { - nooptions_item = menu_item; - } - } - if (nooptions_item) - { - nooptions_item->setVisible(TRUE); - nooptions_item->setEnabled(FALSE); - return TRUE; - } - return FALSE; + const std::string nooptions_str = "--no options--"; + LLView *nooptions_item = NULL; + + const LLView::child_list_t *list = menu->getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + if (menu_item->getVisible()) + { + return FALSE; + } + std::string name = menu_item->getName(); + if (menu_item->getName() == nooptions_str) + { + nooptions_item = menu_item; + } + } + if (nooptions_item) + { + nooptions_item->setVisible(TRUE); + nooptions_item->setEnabled(FALSE); + return TRUE; + } + return FALSE; } BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) { - return LLView::handleHover( x, y, mask ); + return LLView::handleHover( x, y, mask ); } LLFolderViewItem* LLFolderView::getHoveredItem() const { - return dynamic_cast(mHoveredItem.get()); + return dynamic_cast(mHoveredItem.get()); } void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) { - if (mHoveredItem.get() != itemp) - { - if (itemp) - mHoveredItem = itemp->getHandle(); - else - mHoveredItem.markDead(); - } + 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, - EAcceptance* accept, - std::string& tooltip_msg) -{ - mDragAndDropThisFrame = TRUE; - // have children handle it first - BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); - - // when drop is not handled by child, it should be handled - // by the folder which is the hierarchy root. - if (!handled) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + mDragAndDropThisFrame = TRUE; + // have children handle it first + BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + // when drop is not handled by child, it should be handled + // by the folder which is the hierarchy root. + if (!handled) + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } - return handled; + return handled; } void LLFolderView::deleteAllChildren() { - closeRenamer(); - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle.markDead(); - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - clearSelection(); - LLView::deleteAllChildren(); + closeRenamer(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + clearSelection(); + LLView::deleteAllChildren(); } void LLFolderView::scrollToShowSelection() { - if ( mSelectedItems.size() ) - { - mNeedsScroll = TRUE; - } + if ( mSelectedItems.size() ) + { + mNeedsScroll = TRUE; + } } // If the parent is scroll container, scroll it to make the selection // is maximally visible. void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) { - if (!mScrollContainer) return; - - // don't scroll to items when mouse is being used to scroll/drag and drop - if (gFocusMgr.childHasMouseCapture(mScrollContainer)) - { - mNeedsScroll = FALSE; - return; - } - - // if item exists and is in visible portion of parent folder... - if(item) - { - LLRect local_rect = item->getLocalRect(); - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); - // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder - S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight(); - - // get portion of item that we want to see... - LLRect item_local_rect = LLRect(item->getIndentation(), - local_rect.getHeight(), + if (!mScrollContainer) return; + + // don't scroll to items when mouse is being used to scroll/drag and drop + if (gFocusMgr.childHasMouseCapture(mScrollContainer)) + { + mNeedsScroll = FALSE; + return; + } + + // if item exists and is in visible portion of parent folder... + if(item) + { + LLRect local_rect = item->getLocalRect(); + S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); + S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight(); + + // get portion of item that we want to see... + LLRect item_local_rect = LLRect(item->getIndentation(), + local_rect.getHeight(), //+40 is supposed to include few first characters - llmin(item->getLabelXPos() - item->getIndentation() + 40, local_rect.getWidth()), - llmax(0, local_rect.getHeight() - max_height_to_show)); + llmin(item->getLabelXPos() - item->getIndentation() + 40, local_rect.getWidth()), + llmax(0, local_rect.getHeight() - max_height_to_show)); - LLRect item_doc_rect; + LLRect item_doc_rect; - item->localRectToOtherView(item_local_rect, &item_doc_rect, this); + item->localRectToOtherView(item_local_rect, &item_doc_rect, this); - mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); + mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - } + } } LLRect LLFolderView::getVisibleRect() { - S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); - S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); - LLRect visible_rect; - visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); - return visible_rect; + S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); + S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); + LLRect visible_rect; + visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); + return visible_rect; } BOOL LLFolderView::getShowSelectionContext() { - if (mShowSelectionContext) - { - return TRUE; - } - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - return TRUE; - } - return FALSE; + if (mShowSelectionContext) + { + return TRUE; + } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + return TRUE; + } + return FALSE; } void LLFolderView::setShowSingleSelection(bool show) { - if (show != mShowSingleSelection) - { - mMultiSelectionFadeTimer.reset(); - mShowSingleSelection = show; - } + if (show != mShowSingleSelection) + { + mMultiSelectionFadeTimer.reset(); + mShowSingleSelection = show; + } } static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); @@ -1693,71 +1693,71 @@ static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); // Main idle routine void LLFolderView::update() { - // If this is associated with the user's inventory, don't do anything - // until that inventory is loaded up. - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_INVENTORY); - + // If this is associated with the user's inventory, don't do anything + // until that inventory is loaded up. + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_INVENTORY); + // If there's no model, the view is in suspended state (being deleted) and shouldn't be updated if (getFolderViewModel() == NULL) { return; } - LLFolderViewFilter& filter_object = getFolderViewModel()->getFilter(); + LLFolderViewFilter& filter_object = getFolderViewModel()->getFilter(); - if (filter_object.isModified() && filter_object.isNotDefault() && mParentPanel.get()->getVisible()) - { - mNeedsAutoSelect = TRUE; - } - - // Filter to determine visibility before arranging - filter(filter_object); - - // Clear the modified setting on the filter only if the filter finished after running the filter process - // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items + if (filter_object.isModified() && filter_object.isNotDefault() && mParentPanel.get()->getVisible()) + { + mNeedsAutoSelect = TRUE; + } + + // Filter to determine visibility before arranging + filter(filter_object); + + // Clear the modified setting on the filter only if the filter finished after running the filter process + // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items bool filter_modified = filter_object.isModified(); if (filter_modified && (!filter_object.isTimedOut())) - { - filter_object.clearModified(); - } - - // automatically show matching items, and select first one if we had a selection - if (mNeedsAutoSelect) - { - // select new item only if a filtered item not currently selected and there was a selection - LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLSelectFirstFilteredItem functor; - applyFunctorRecursively(functor); - } - - // Open filtered folders for folder views with mAutoSelectOverride=TRUE. - // Used by LLPlacesFolderView. - if (filter_object.showAllResults()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLOpenFilteredFolders functor; - applyFunctorRecursively(functor); - } - - scrollToShowSelection(); - } - - BOOL filter_finished = mViewModel->contentsReady() - && (getViewModelItem()->passedFilter() - || ( getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration() - && !filter_modified)); - if (filter_finished - || gFocusMgr.childHasKeyboardFocus(mParentPanel.get()) - || gFocusMgr.childHasMouseCapture(mParentPanel.get())) - { - // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process - mNeedsAutoSelect = FALSE; - } + { + filter_object.clearModified(); + } + + // automatically show matching items, and select first one if we had a selection + if (mNeedsAutoSelect) + { + // select new item only if a filtered item not currently selected and there was a selection + LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); + if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLSelectFirstFilteredItem functor; + applyFunctorRecursively(functor); + } + + // Open filtered folders for folder views with mAutoSelectOverride=TRUE. + // Used by LLPlacesFolderView. + if (filter_object.showAllResults()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLOpenFilteredFolders functor; + applyFunctorRecursively(functor); + } + + scrollToShowSelection(); + } + + BOOL filter_finished = mViewModel->contentsReady() + && (getViewModelItem()->passedFilter() + || ( getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration() + && !filter_modified)); + if (filter_finished + || gFocusMgr.childHasKeyboardFocus(mParentPanel.get()) + || gFocusMgr.childHasMouseCapture(mParentPanel.get())) + { + // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process + mNeedsAutoSelect = FALSE; + } BOOL is_visible = isInVisibleChain() || mForceArrange; @@ -1776,71 +1776,71 @@ void LLFolderView::update() } } - // during filtering process, try to pin selected item's location on screen - // this will happen when searching your inventory and when new items arrive - if (!filter_finished) - { - // calculate rectangle to pin item to at start of animated rearrange - if (!mPinningSelectedItem && !mSelectedItems.empty()) - { - // lets pin it! - mPinningSelectedItem = TRUE; + // during filtering process, try to pin selected item's location on screen + // this will happen when searching your inventory and when new items arrive + if (!filter_finished) + { + // calculate rectangle to pin item to at start of animated rearrange + if (!mPinningSelectedItem && !mSelectedItems.empty()) + { + // lets pin it! + mPinningSelectedItem = TRUE; - //Computes visible area - const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); - LLFolderViewItem* selected_item = mSelectedItems.back(); + //Computes visible area + const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); + LLFolderViewItem* selected_item = mSelectedItems.back(); //Computes location of selected content, content outside visible area will be scrolled to using below code - LLRect item_rect; - selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); - + LLRect item_rect; + selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); + //Computes intersected region of the selected content and visible area LLRect overlap_rect(item_rect); overlap_rect.intersectWith(visible_content_rect); //Don't scroll when the selected content exists within the visible area - if (overlap_rect.getHeight() >= selected_item->getItemHeight()) - { - // then attempt to keep it in same place on screen - mScrollConstraintRect = item_rect; - mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); - } + if (overlap_rect.getHeight() >= selected_item->getItemHeight()) + { + // then attempt to keep it in same place on screen + mScrollConstraintRect = item_rect; + mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); + } //Scroll because the selected content is outside the visible area - else - { - // otherwise we just want it onscreen somewhere - LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - } - } - else - { - // stop pinning selected item after folders stop rearranging - if (!needsArrange()) - { - mPinningSelectedItem = FALSE; - } - } - - LLRect constraint_rect; - if (mPinningSelectedItem) - { - // use last known constraint rect for pinned item - constraint_rect = mScrollConstraintRect; - } - else - { - // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - - if (mSelectedItems.size() && mNeedsScroll) - { + else + { + // otherwise we just want it onscreen somewhere + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + } + } + else + { + // stop pinning selected item after folders stop rearranging + if (!needsArrange()) + { + mPinningSelectedItem = FALSE; + } + } + + LLRect constraint_rect; + if (mPinningSelectedItem) + { + // use last known constraint rect for pinned item + constraint_rect = mScrollConstraintRect; + } + else + { + // during normal use (page up/page down, etc), just try to fit item on screen + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + + if (mSelectedItems.size() && mNeedsScroll) + { LLFolderViewItem* scroll_to_item = mSelectedItems.back(); - scrollToShowItem(scroll_to_item, constraint_rect); - // continue scrolling until animated layout change is done + scrollToShowItem(scroll_to_item, constraint_rect); + // continue scrolling until animated layout change is done bool selected_filter_finished = getRoot()->getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration(); if (selected_filter_finished && scroll_to_item && scroll_to_item->getViewModelItem()) { @@ -1858,7 +1858,7 @@ void LLFolderView::update() mNeedsScroll = FALSE; } } - } + } if (mSelectedItems.size()) { @@ -1886,182 +1886,182 @@ void LLFolderView::update() void LLFolderView::dumpSelectionInformation() { - LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_NEWLINE - << "****************************************" << LL_ENDL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - LL_INFOS() << " " << (*item_it)->getName() << LL_ENDL; - } - LL_INFOS() << "****************************************" << LL_ENDL; + LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_NEWLINE + << "****************************************" << LL_ENDL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + LL_INFOS() << " " << (*item_it)->getName() << LL_ENDL; + } + LL_INFOS() << "****************************************" << LL_ENDL; } void LLFolderView::updateRenamerPosition() { - if(mRenameItem) - { - // See also LLFolderViewItem::draw() - S32 x = mRenameItem->getLabelXPos(); - S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenameItem->localPointToScreen( x, y, &x, &y ); - screenPointToLocal( x, y, &x, &y ); - mRenamer->setOrigin( x, y ); - - LLRect scroller_rect(0, 0, (S32)LLUI::getInstance()->getWindowSize().mV[VX], 0); - if (mScrollContainer) - { - scroller_rect = mScrollContainer->getContentWindowRect(); - } + if(mRenameItem) + { + // See also LLFolderViewItem::draw() + S32 x = mRenameItem->getLabelXPos(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenameItem->localPointToScreen( x, y, &x, &y ); + screenPointToLocal( x, y, &x, &y ); + mRenamer->setOrigin( x, y ); + + LLRect scroller_rect(0, 0, (S32)LLUI::getInstance()->getWindowSize().mV[VX], 0); + if (mScrollContainer) + { + scroller_rect = mScrollContainer->getContentWindowRect(); + } - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenamer->reshape( width, height, TRUE ); - } + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenamer->reshape( width, height, TRUE ); + } } // Update visibility and availability (i.e. enabled/disabled) of context menu items. void LLFolderView::updateMenuOptions(LLMenuGL* menu) { - const LLView::child_list_t *list = menu->getChildList(); - - LLView::child_list_t::const_iterator menu_itor; - for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) - { - (*menu_itor)->setVisible(FALSE); - (*menu_itor)->pushVisible(TRUE); - (*menu_itor)->setEnabled(TRUE); - } - - // Successively filter out invalid options - U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); - U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; - for (selected_items_t::iterator item_itor = mSelectedItems.begin(); - item_itor != mSelectedItems.end(); - ++item_itor) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->buildContextMenu(*menu, flags); - flags = multi_select_flag; - } + const LLView::child_list_t *list = menu->getChildList(); + + LLView::child_list_t::const_iterator menu_itor; + for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) + { + (*menu_itor)->setVisible(FALSE); + (*menu_itor)->pushVisible(TRUE); + (*menu_itor)->setEnabled(TRUE); + } + + // Successively filter out invalid options + U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); + U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; + for (selected_items_t::iterator item_itor = mSelectedItems.begin(); + item_itor != mSelectedItems.end(); + ++item_itor) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->buildContextMenu(*menu, flags); + 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. + // 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. if (getFolderViewGroupedItemModel()) { getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); } - addNoOptions(menu); + addNoOptions(menu); } // Refresh the context menu (that is already shown). void LLFolderView::updateMenu() { - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - updateMenuOptions(menu); - menu->needsArrange(); // update menu height if needed - } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + updateMenuOptions(menu); + menu->needsArrange(); // update menu height if needed + } } bool LLFolderView::isFolderSelected() { - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewFolder* folder = dynamic_cast(*item_iter); - if (folder != NULL) - { - return true; - } - } - return false; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewFolder* folder = dynamic_cast(*item_iter); + if (folder != NULL) + { + return true; + } + } + return false; } bool LLFolderView::selectFirstItem() { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();++iter) - { - LLFolderViewFolder* folder = (*iter ); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getNextFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();++iter) + { + LLFolderViewFolder* folder = (*iter ); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getNextFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; } bool LLFolderView::selectLastItem() { - for(items_t::reverse_iterator iit = mItems.rbegin(); - iit != mItems.rend(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();++iter) - { - LLFolderViewFolder* folder = (*iter); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; -} - - -S32 LLFolderView::notify(const LLSD& info) -{ - if(info.has("action")) - { - std::string str_action = info["action"]; - if(str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - scrollToShowSelection(); - return 1; - - } - else if(str_action == "select_last") - { - setFocus(true); - selectLastItem(); - scrollToShowSelection(); - return 1; - } - } - return 0; + for(items_t::reverse_iterator iit = mItems.rbegin(); + iit != mItems.rend(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + for (folders_t::reverse_iterator iter = mFolders.rbegin(); + iter != mFolders.rend();++iter) + { + LLFolderViewFolder* folder = (*iter); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} + + +S32 LLFolderView::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + scrollToShowSelection(); + return 1; + + } + else if(str_action == "select_last") + { + setFocus(true); + selectLastItem(); + scrollToShowSelection(); + return 1; + } + } + return 0; } @@ -2071,46 +2071,46 @@ S32 LLFolderView::notify(const LLSD& info) void LLFolderView::onRenamerLost() { - if (mRenamer && mRenamer->getVisible()) - { - mRenamer->setVisible(FALSE); + if (mRenamer && mRenamer->getVisible()) + { + mRenamer->setVisible(FALSE); - // will commit current name (which could be same as original name) - mRenamer->setFocus(FALSE); - } + // will commit current name (which could be same as original name) + mRenamer->setFocus(FALSE); + } - if( mRenameItem ) - { - setSelection( mRenameItem, TRUE ); - mRenameItem = NULL; - } + if( mRenameItem ) + { + setSelection( mRenameItem, TRUE ); + mRenameItem = NULL; + } } LLFolderViewItem* LLFolderView::getNextUnselectedItem() { - LLFolderViewItem* last_item = *mSelectedItems.rbegin(); - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isInSelection())) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } - return new_selection; + LLFolderViewItem* last_item = *mSelectedItems.rbegin(); + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && (new_selection->isInSelection())) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + return new_selection; } S32 LLFolderView::getItemHeight() const { - if(!hasVisibleChildren()) + if(!hasVisibleChildren()) { - //We need to display status textbox, let's reserve some place for it - return llmax(0, mStatusTextBox->getTextPixelHeight()); + //We need to display status textbox, let's reserve some place for it + return llmax(0, mStatusTextBox->getTextPixelHeight()); } - return 0; + return 0; } diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 5f8a173889..1ad7e9f58c 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -1,25 +1,25 @@ -/** +/** * @file llfolderview.h * @brief Definition of the folder view collection of classes. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,7 +35,7 @@ #ifndef LL_LLFOLDERVIEW_H #define LL_LLFOLDERVIEW_H -#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder +#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder #include "lluictrl.h" #include "v4color.h" @@ -66,290 +66,290 @@ class LLTextBox; class LLFolderViewScrollContainer : public LLScrollContainer { public: - /*virtual*/ ~LLFolderViewScrollContainer() {}; - /*virtual*/ const LLRect getScrolledViewRect() const; + /*virtual*/ ~LLFolderViewScrollContainer() {}; + /*virtual*/ const LLRect getScrolledViewRect() const; protected: - LLFolderViewScrollContainer(const LLScrollContainer::Params& p); - friend class LLUICtrlFactory; + LLFolderViewScrollContainer(const LLScrollContainer::Params& p); + friend class LLUICtrlFactory; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderView // -// The LLFolderView represents the root level folder view object. +// The LLFolderView represents the root level folder view object. // It manages the screen region of the folder view. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler { public: - struct Params : public LLInitParam::Block - { - Mandatory parent_panel; - Optional title; - Optional use_label_suffix, - allow_multiselect, - allow_drag, - show_empty_message, - use_ellipses, - show_item_link_overlays, - suppress_folder_menu; - Mandatory view_model; - Optional grouped_item_model; + struct Params : public LLInitParam::Block + { + Mandatory parent_panel; + Optional title; + Optional use_label_suffix, + allow_multiselect, + allow_drag, + show_empty_message, + use_ellipses, + show_item_link_overlays, + suppress_folder_menu; + Mandatory view_model; + Optional grouped_item_model; Mandatory options_menu; - Params(); - }; + Params(); + }; - friend class LLFolderViewScrollContainer; + friend class LLFolderViewScrollContainer; typedef folder_view_item_deque selected_items_t; - LLFolderView(const Params&); - virtual ~LLFolderView( void ); + LLFolderView(const Params&); + virtual ~LLFolderView( void ); - virtual BOOL canFocusChildren() const; + virtual BOOL canFocusChildren() const; - virtual const LLFolderView* getRoot() const { return this; } - virtual LLFolderView* getRoot() { return this; } + virtual const LLFolderView* getRoot() const { return this; } + virtual LLFolderView* getRoot() { return this; } - LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } - const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } + LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; } const LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() const { return mGroupedItemModel; } - - typedef boost::signals2::signal& items, BOOL user_action)> signal_t; - void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } - void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - - bool getAllowMultiSelect() { return mAllowMultiSelect; } - bool getAllowDrag() { return mAllowDrag; } + + typedef boost::signals2::signal& items, BOOL user_action)> signal_t; + void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } + void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } + + 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(); + // Close all folders in the view + void closeAllFolders(); + void openTopLevelFolders(); - virtual void addFolder( LLFolderViewFolder* folder); + virtual void addFolder( LLFolderViewFolder* folder); - // 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() const; + // 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() const; - void arrangeAll() { mArrangeGeneration++; } - S32 getArrangeGeneration() { return mArrangeGeneration; } + void arrangeAll() { mArrangeGeneration++; } + S32 getArrangeGeneration() { return mArrangeGeneration; } - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); - void clearHoveredItem() { setHoveredItem(nullptr); } - LLFolderViewItem* getHoveredItem() const; - void setHoveredItem(LLFolderViewItem* itemp); + void clearHoveredItem() { setHoveredItem(nullptr); } + LLFolderViewItem* getHoveredItem() const; + void setHoveredItem(LLFolderViewItem* itemp); - // Get the last selected item - virtual LLFolderViewItem* getCurSelectedItem( void ); + // Get the last selected item + virtual LLFolderViewItem* getCurSelectedItem( void ); selected_items_t& getSelectedItems( void ); - // Record the selected item and pass it down the hierarchy. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // This method is used to toggle the selection of an item. Walks - // children, and keeps track of selected objects. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - virtual std::set getSelectionList() const; - - // Make sure if ancestor is selected, descendants are not - void sanitizeSelection(); - virtual void clearSelection(); - void addToSelectionList(LLFolderViewItem* item); - void removeFromSelectionList(LLFolderViewItem* item); - - bool startDrag(); - void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } - void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } - LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - - // Deletion functionality - void removeSelectedItems(); - - void autoOpenItem(LLFolderViewFolder* item); - void closeAutoOpenedFolders(); - BOOL autoOpenTest(LLFolderViewFolder* item); - BOOL isOpen() const { return TRUE; } // root folder always open - - // Copy & paste - virtual BOOL canCopy() const; - virtual void copy(); - - virtual BOOL canCut() const; - virtual void cut(); - - virtual BOOL canPaste() const; - virtual void paste(); - - LLFolderViewItem* getNextUnselectedItem(); - - // Public rename functionality - can only start the process - void startRenamingSelectedItem( void ); - - // LLView functionality - ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); - /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); - /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } - virtual void draw(); - virtual void deleteAllChildren(); + // Record the selected item and pass it down the hierarchy. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus = TRUE); + + // This method is used to toggle the selection of an item. Walks + // children, and keeps track of selected objects. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + virtual std::set getSelectionList() const; + + // Make sure if ancestor is selected, descendants are not + void sanitizeSelection(); + virtual void clearSelection(); + void addToSelectionList(LLFolderViewItem* item); + void removeFromSelectionList(LLFolderViewItem* item); + + bool startDrag(); + void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } + void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } + LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } + + // Deletion functionality + void removeSelectedItems(); + + void autoOpenItem(LLFolderViewFolder* item); + void closeAutoOpenedFolders(); + BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open + + // Copy & paste + virtual BOOL canCopy() const; + virtual void copy(); + + virtual BOOL canCut() const; + virtual void cut(); + + virtual BOOL canPaste() const; + virtual void paste(); + + LLFolderViewItem* getNextUnselectedItem(); + + // Public rename functionality - can only start the process + void startRenamingSelectedItem( void ); + + // LLView functionality + ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); + /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } + virtual void draw(); + virtual void deleteAllChildren(); void stopAutoScollining() {mNeedsScroll = false;} - void scrollToShowSelection(); - void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); - void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } - LLRect getVisibleRect(); + void scrollToShowSelection(); + void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); + void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } + LLRect getVisibleRect(); - BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); - void setShowSelectionContext(bool show) { mShowSelectionContext = show; } - BOOL getShowSelectionContext(); - void setShowSingleSelection(bool show); - BOOL getShowSingleSelection() { return mShowSingleSelection; } - F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } - bool getUseEllipses() { return mUseEllipses; } - S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); + void setShowSelectionContext(bool show) { mShowSelectionContext = show; } + BOOL getShowSelectionContext(); + void setShowSingleSelection(bool show); + BOOL getShowSingleSelection() { return mShowSingleSelection; } + F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } + bool getUseEllipses() { return mUseEllipses; } + S32 getSelectedCount() { return (S32)mSelectedItems.size(); } - void update(); // needs to be called periodically (e.g. once per frame) + void update(); // needs to be called periodically (e.g. once per frame) - BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } - BOOL needsAutoRename() { return mNeedsAutoRename; } - void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } - void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } - void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } + BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } + BOOL needsAutoRename() { return mNeedsAutoRename; } + void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } + void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } + void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } - bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + bool showItemLinkOverlays() { return mShowItemLinkOverlays; } - void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } + 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(); + LLPanel* getParentPanel() { return mParentPanel.get(); } + // DEBUG only + void dumpSelectionInformation(); + + virtual S32 notify(const LLSD& info) ; - virtual S32 notify(const LLSD& info) ; + void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; } - void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; } - - bool useLabelSuffix() { return mUseLabelSuffix; } - virtual void updateMenu(); + bool useLabelSuffix() { return mUseLabelSuffix; } + virtual void updateMenu(); - void finishRenamingItem( void ); + void finishRenamingItem( void ); // Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem. - LLHandle getHandle() const { return getDerivedHandle(); } - + LLHandle getHandle() const { return getDerivedHandle(); } + private: - void updateMenuOptions(LLMenuGL* menu); - void updateRenamerPosition(); + void updateMenuOptions(LLMenuGL* menu); + void updateRenamerPosition(); protected: - LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. + LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. + + void commitRename( const LLSD& data ); + void onRenamerLost(); - void commitRename( const LLSD& data ); - void onRenamerLost(); + void closeRenamer( void ); - void closeRenamer( void ); + bool isFolderSelected(); - bool isFolderSelected(); + bool selectFirstItem(); + bool selectLastItem(); - bool selectFirstItem(); - bool selectLastItem(); - - BOOL addNoOptions(LLMenuGL* menu) const; + BOOL addNoOptions(LLMenuGL* menu) const; protected: - LLHandle mPopupMenuHandle; - std::string mMenuFileName; - - LLHandle mHoveredItem; - selected_items_t mSelectedItems; - bool mKeyboardSelection, - mAllowMultiSelect, - mAllowDrag, - mShowEmptyMessage, - mShowFolderHierarchy, - mNeedsScroll, - mPinningSelectedItem, - mNeedsAutoSelect, - mAutoSelectOverride, - mNeedsAutoRename, - mUseLabelSuffix, - mDragAndDropThisFrame, - mShowItemLinkOverlays, - mShowSelectionContext, - mShowSingleSelection, - mSuppressFolderMenu, + LLHandle mPopupMenuHandle; + std::string mMenuFileName; + + LLHandle mHoveredItem; + selected_items_t mSelectedItems; + bool mKeyboardSelection, + mAllowMultiSelect, + mAllowDrag, + mShowEmptyMessage, + mShowFolderHierarchy, + mNeedsScroll, + mPinningSelectedItem, + mNeedsAutoSelect, + mAutoSelectOverride, + mNeedsAutoRename, + mUseLabelSuffix, + mDragAndDropThisFrame, + mShowItemLinkOverlays, + mShowSelectionContext, + mShowSingleSelection, + mSuppressFolderMenu, mSingleFolderMode; - // Renaming variables and methods - LLFolderViewItem* mRenameItem; // The item currently being renamed - LLLineEditor* mRenamer; - - LLRect mScrollConstraintRect; - - LLDepthStack mAutoOpenItems; - LLFolderViewFolder* mAutoOpenCandidate; - LLFrameTimer mAutoOpenTimer; - LLFrameTimer mSearchTimer; - std::string mSearchString; - LLFrameTimer mMultiSelectionFadeTimer; - S32 mArrangeGeneration; - - signal_t mSelectSignal; - signal_t mReshapeSignal; - S32 mSignalSelectCallback; - S32 mMinWidth; - - LLHandle mParentPanel; - - LLFolderViewModelInterface* mViewModel; + // Renaming variables and methods + LLFolderViewItem* mRenameItem; // The item currently being renamed + LLLineEditor* mRenamer; + + LLRect mScrollConstraintRect; + + LLDepthStack mAutoOpenItems; + LLFolderViewFolder* mAutoOpenCandidate; + LLFrameTimer mAutoOpenTimer; + LLFrameTimer mSearchTimer; + std::string mSearchString; + LLFrameTimer mMultiSelectionFadeTimer; + S32 mArrangeGeneration; + + signal_t mSelectSignal; + signal_t mReshapeSignal; + S32 mSignalSelectCallback; + S32 mMinWidth; + + LLHandle mParentPanel; + + LLFolderViewModelInterface* mViewModel; LLFolderViewGroupedItemModel* mGroupedItemModel; - /** - * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. - * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. - */ - bool mUseEllipses; // See EXT-719 + /** + * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. + * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. + */ + bool mUseEllipses; // See EXT-719 - /** - * Contains item under mouse pointer while dragging - */ - LLFolderViewItem* mDraggingOverItem; // See EXT-719 + /** + * Contains item under mouse pointer while dragging + */ + LLFolderViewItem* mDraggingOverItem; // See EXT-719 - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; bool mForceArrange; - + public: - static F32 sAutoOpenTime; - LLTextBox* mStatusTextBox; + static F32 sAutoOpenTime; + LLTextBox* mStatusTextBox; }; @@ -365,9 +365,9 @@ public: class LLFolderViewFunctor { public: - virtual ~LLFolderViewFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder) = 0; - virtual void doItem(LLFolderViewItem* item) = 0; + virtual ~LLFolderViewFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder) = 0; + virtual void doItem(LLFolderViewItem* item) = 0; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -375,67 +375,67 @@ public: // // This will select the first *item* found in the hierarchy. If no item can be // selected, the first matching folder will. -// Since doFolder() is done first but we prioritize item selection, we let the +// Since doFolder() is done first but we prioritize item selection, we let the // first filtered folder set the selection and raise a folder flag. -// The selection might be overridden by the first filtered item in doItem() +// The selection might be overridden by the first filtered item in doItem() // which checks an item flag. Since doFolder() checks the item flag too, the first // item will still be selected if items were to be done first and folders second. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLSelectFirstFilteredItem : public LLFolderViewFunctor { public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE), mFolderSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected || mFolderSelected; } + LLSelectFirstFilteredItem() : mItemSelected(FALSE), mFolderSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected || mFolderSelected; } protected: - BOOL mItemSelected; - BOOL mFolderSelected; + BOOL mItemSelected; + BOOL mFolderSelected; }; class LLOpenFilteredFolders : public LLFolderViewFunctor { public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); }; class LLSaveFolderState : public LLFolderViewFunctor { public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } protected: - std::set mOpenFolders; - BOOL mApply; + std::set mOpenFolders; + BOOL mApply; }; class LLOpenFoldersWithSelection : public LLFolderViewFunctor { public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); }; class LLAllDescendentsPassedFilter : public LLFolderViewFunctor { public: - LLAllDescendentsPassedFilter() : mAllDescendentsPassedFilter(true) {} - /*virtual*/ ~LLAllDescendentsPassedFilter() {} - /*virtual*/ void doFolder(LLFolderViewFolder* folder); - /*virtual*/ void doItem(LLFolderViewItem* item); - bool allDescendentsPassedFilter() const { return mAllDescendentsPassedFilter; } + LLAllDescendentsPassedFilter() : mAllDescendentsPassedFilter(true) {} + /*virtual*/ ~LLAllDescendentsPassedFilter() {} + /*virtual*/ void doFolder(LLFolderViewFolder* folder); + /*virtual*/ void doItem(LLFolderViewItem* item); + bool allDescendentsPassedFilter() const { return mAllDescendentsPassedFilter; } protected: - bool mAllDescendentsPassedFilter; + bool mAllDescendentsPassedFilter; }; // Flags for buildContextMenu() diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 2bd14f6f6a..40bb6832d4 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfolderviewitem.cpp * @brief Items and folders that can appear in a hierarchical folder view * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,7 +35,7 @@ #include "llcallbacklist.h" #include "llcriticaldamp.h" #include "llclipboard.h" -#include "llfocusmgr.h" // gFocusMgr +#include "llfocusmgr.h" // gFocusMgr #include "lltrans.h" #include "llwindow.h" @@ -45,7 +45,7 @@ static LLDefaultChildRegistry::Register r("folder_view_item"); -// statics +// statics std::map LLFolderViewItem::sFonts; // map of styles to fonts bool LLFolderViewItem::sColorSetInitialized = false; @@ -69,18 +69,18 @@ const LLColor4U DEFAULT_WHITE(255, 255, 255); //static LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) { - LLFontGL* rtn = sFonts[style]; - if (!rtn) // grab label font with this style, lazily - { - LLFontDescriptor labelfontdesc("SansSerif", "Small", style); - rtn = LLFontGL::getFont(labelfontdesc); - if (!rtn) - { - rtn = LLFontGL::getFontDefault(); - } - sFonts[style] = rtn; - } - return rtn; + LLFontGL* rtn = sFonts[style]; + if (!rtn) // grab label font with this style, lazily + { + LLFontDescriptor labelfontdesc("SansSerif", "Small", style); + rtn = LLFontGL::getFont(labelfontdesc); + if (!rtn) + { + rtn = LLFontGL::getFontDefault(); + } + sFonts[style] = rtn; + } + return rtn; } //static @@ -91,24 +91,24 @@ void LLFolderViewItem::initClass() //static void LLFolderViewItem::cleanupClass() { - sFonts.clear(); + sFonts.clear(); } // NOTE: Optimize this, we call it a *lot* when opening a large inventory LLFolderViewItem::Params::Params() -: root(), - listener(), - folder_arrow_image("folder_arrow_image"), - folder_indentation("folder_indentation"), - selection_image("selection_image"), - item_height("item_height"), - item_top_pad("item_top_pad"), - creation_date(), +: root(), + listener(), + folder_arrow_image("folder_arrow_image"), + folder_indentation("folder_indentation"), + selection_image("selection_image"), + item_height("item_height"), + item_top_pad("item_top_pad"), + creation_date(), allow_wear("allow_wear", true), allow_drop("allow_drop", true), - font_color("font_color"), - font_highlight_color("font_highlight_color"), + font_color("font_color"), + font_highlight_color("font_highlight_color"), left_pad("left_pad", 0), icon_pad("icon_pad", 0), icon_width("icon_width", 0), @@ -122,32 +122,32 @@ LLFolderViewItem::Params::Params() // Default constructor LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) -: LLView(p), - mLabelWidth(0), - mLabelWidthDirty(false), +: LLView(p), + mLabelWidth(0), + mLabelWidthDirty(false), mSuffixNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), - mParentFolder( NULL ), - mIsSelected( FALSE ), - mIsCurSelection( FALSE ), - mSelectPending(FALSE), - mIsItemCut(false), - mCutGeneration(0), - mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(FALSE), + mParentFolder( NULL ), + mIsSelected( FALSE ), + mIsCurSelection( FALSE ), + mSelectPending(FALSE), + mIsItemCut(false), + mCutGeneration(0), + mLabelStyle( LLFontGL::NORMAL ), + mHasVisibleChildren(FALSE), mLocalIndentation(p.folder_indentation), - mIndentation(0), - mItemHeight(p.item_height), - mControlLabelRotation(0.f), - mDragAndDropTarget(FALSE), - mLabel(p.name), - mRoot(p.root), - mViewModelItem(p.listener), - mIsMouseOverTitle(false), - mAllowWear(p.allow_wear), + mIndentation(0), + mItemHeight(p.item_height), + mControlLabelRotation(0.f), + mDragAndDropTarget(FALSE), + mLabel(p.name), + mRoot(p.root), + mViewModelItem(p.listener), + mIsMouseOverTitle(false), + mAllowWear(p.allow_wear), mAllowDrop(p.allow_drop), - mFontColor(p.font_color), - mFontHighlightColor(p.font_highlight_color), + mFontColor(p.font_color), + mFontHighlightColor(p.font_highlight_color), mLeftPad(p.left_pad), mIconPad(p.icon_pad), mIconWidth(p.icon_width), @@ -158,30 +158,30 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mMaxFolderItemOverlap(p.max_folder_item_overlap), mDoubleClickOverride(p.double_click_override) { - if (!sColorSetInitialized) - { - sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); - sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - 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("InventoryItemLinkColor", DEFAULT_WHITE); - sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - sColorSetInitialized = true; - } - - if (mViewModelItem) - { - mViewModelItem->setFolderViewItem(this); - } + if (!sColorSetInitialized) + { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + 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("InventoryItemLinkColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } + + if (mViewModelItem) + { + mViewModelItem->setFolderViewItem(this); + } } // Destroys the object LLFolderViewItem::~LLFolderViewItem() { - mViewModelItem = NULL; + mViewModelItem = NULL; gFocusMgr.removeKeyboardFocusWithoutCallback(this); } @@ -207,99 +207,99 @@ BOOL LLFolderViewItem::postBuild() // while LLFolderViewItem::arrange() updates visual part mSuffixNeedsRefresh = true; mLabelWidthDirty = true; - return TRUE; + return TRUE; } LLFolderView* LLFolderViewItem::getRoot() { - return mRoot; + return mRoot; } const LLFolderView* LLFolderViewItem::getRoot() const { - return mRoot; + return mRoot; } // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) { - LLFolderViewItem* root = this; - while( root->mParentFolder ) - { - if( root->mParentFolder == potential_ancestor ) - { - return TRUE; - } - root = root->mParentFolder; - } - return FALSE; + LLFolderViewItem* root = this; + while( root->mParentFolder ) + { + if( root->mParentFolder == potential_ancestor ) + { + return TRUE; + } + root = root->mParentFolder; + } + return FALSE; } LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) { - if (!mParentFolder) - { - return NULL; - } + if (!mParentFolder) + { + return NULL; + } - LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit last item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } + LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit last item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } - return itemp; + return itemp; } LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) { - if (!mParentFolder) - { - return NULL; - } + if (!mParentFolder) + { + return NULL; + } - LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); + LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - // Skip over items that are invisible or are hidden from the UI. - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit first item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } + // Skip over items that are invisible or are hidden from the UI. + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit first item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } - return itemp; + return itemp; } -BOOL LLFolderViewItem::passedFilter(S32 filter_generation) +BOOL LLFolderViewItem::passedFilter(S32 filter_generation) { - return getViewModelItem()->passedFilter(filter_generation); + return getViewModelItem()->passedFilter(filter_generation); } BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) { - if (filter_generation < 0) - { - filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); - } - LLFolderViewModelItem* model = getViewModelItem(); - BOOL visible = model->passedFilter(filter_generation); - if (model->getMarkedDirtyGeneration() >= filter_generation) - { - // unsure visibility state - // retaining previous visibility until item is updated or filter generation changes - visible |= getVisible(); - } - return visible; + if (filter_generation < 0) + { + filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); + } + LLFolderViewModelItem* model = getViewModelItem(); + BOOL visible = model->passedFilter(filter_generation); + if (model->getMarkedDirtyGeneration() >= filter_generation) + { + // unsure visibility state + // retaining previous visibility until item is updated or filter generation changes + visible |= getVisible(); + } + return visible; } void LLFolderViewItem::refresh() @@ -331,21 +331,21 @@ void LLFolderViewItem::refresh() void LLFolderViewItem::refreshSuffix() { - LLFolderViewModelItem const* vmi = getViewModelItem(); + LLFolderViewModelItem const* vmi = getViewModelItem(); // icons are slightly expensive to get, can be optimized // see LLInventoryIcon::getIcon() - mIcon = vmi->getIcon(); + mIcon = vmi->getIcon(); mIconOpen = vmi->getIconOpen(); mIconOverlay = vmi->getIconOverlay(); - if (mRoot->useLabelSuffix()) - { + if (mRoot->useLabelSuffix()) + { // Very Expensive! // Can do a number of expensive checks, like checking active motions, wearables or friend list mLabelStyle = vmi->getLabelStyle(); mLabelSuffix = vmi->getLabelSuffix(); - } + } mLabelWidthDirty = true; mSuffixNeedsRefresh = false; @@ -353,39 +353,39 @@ void LLFolderViewItem::refreshSuffix() // Utility function for LLFolderView void LLFolderViewItem::arrangeAndSet(BOOL set_selection, - BOOL take_keyboard_focus) + BOOL take_keyboard_focus) { - LLFolderView* root = getRoot(); - if (getParentFolder()) - { - getParentFolder()->requestArrange(); - } - if(set_selection) - { - getRoot()->setSelection(this, TRUE, take_keyboard_focus); - if(root) - { - root->scrollToShowSelection(); - } - } + LLFolderView* root = getRoot(); + if (getParentFolder()) + { + getParentFolder()->requestArrange(); + } + if(set_selection) + { + getRoot()->setSelection(this, TRUE, take_keyboard_focus); + if(root) + { + root->scrollToShowSelection(); + } + } } std::set LLFolderViewItem::getSelectionList() const { - std::set selection; - return selection; + std::set selection; + return selection; } // addToFolder() returns TRUE if it succeeds. FALSE otherwise void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - folder->addItem(this); + folder->addItem(this); - // Compute indentation since parent folder changed - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; + // Compute indentation since parent folder changed + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; } @@ -393,38 +393,38 @@ void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) // makes sure that this view and its children are the right size. S32 LLFolderViewItem::arrange( S32* width, S32* height ) { - // Only indent deeper items in hierarchy - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; - if (mLabelWidthDirty) - { + // Only indent deeper items in hierarchy + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; + if (mLabelWidthDirty) + { if (mSuffixNeedsRefresh) { // Expensive. But despite refreshing label, // it is purely visual, so it is fine to do at our laisure refreshSuffix(); } - mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight; - mLabelWidthDirty = false; - } + mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight; + mLabelWidthDirty = false; + } - *width = llmax(*width, mLabelWidth); + *width = llmax(*width, mLabelWidth); - // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 - bool use_ellipses = getRoot()->getUseEllipses(); - if (use_ellipses) - { - // limit to set rect to avoid horizontal scrollbar - *width = llmin(*width, getRoot()->getRect().getWidth()); - } - *height = getItemHeight(); - return *height; + // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 + bool use_ellipses = getRoot()->getUseEllipses(); + if (use_ellipses) + { + // limit to set rect to avoid horizontal scrollbar + *width = llmin(*width, getRoot()->getRect().getWidth()); + } + *height = getItemHeight(); + return *height; } S32 LLFolderViewItem::getItemHeight() const { - return mItemHeight; + return mItemHeight; } S32 LLFolderViewItem::getLabelXPos() @@ -449,68 +449,68 @@ S32 LLFolderViewItem::getTextPad() // together. BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) { - if (selection == this && !mIsSelected) - { - selectItem(); - } - else if (mIsSelected) // Deselect everything else. - { - deselectItem(); - } - return mIsSelected; + if (selection == this && !mIsSelected) + { + selectItem(); + } + else if (mIsSelected) // Deselect everything else. + { + deselectItem(); + } + return mIsSelected; } BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) { - if (selection == this) - { - if (mIsSelected) - { - deselectItem(); - } - else - { - selectItem(); - } - return TRUE; - } - return FALSE; + if (selection == this) + { + if (mIsSelected) + { + deselectItem(); + } + else + { + selectItem(); + } + return TRUE; + } + return FALSE; } void LLFolderViewItem::deselectItem(void) { - mIsSelected = FALSE; + mIsSelected = FALSE; } void LLFolderViewItem::selectItem(void) { - if (mIsSelected == FALSE) - { - mIsSelected = TRUE; - getViewModelItem()->selectItem(); - } + if (mIsSelected == FALSE) + { + mIsSelected = TRUE; + getViewModelItem()->selectItem(); + } } BOOL LLFolderViewItem::isMovable() { - return getViewModelItem()->isItemMovable(); + return getViewModelItem()->isItemMovable(); } BOOL LLFolderViewItem::isRemovable() { - return getViewModelItem()->isItemRemovable(); + return getViewModelItem()->isItemRemovable(); } void LLFolderViewItem::destroyView() { - getRoot()->removeFromSelectionList(this); + getRoot()->removeFromSelectionList(this); - if (mParentFolder) - { - // removeView deletes me - mParentFolder->extractItem(this); - } - delete this; + if (mParentFolder) + { + // removeView deletes me + mParentFolder->extractItem(this); + } + delete this; } // Call through to the viewed object and return true if it can be @@ -518,250 +518,250 @@ void LLFolderViewItem::destroyView() //BOOL LLFolderViewItem::removeRecursively(BOOL single_item) BOOL LLFolderViewItem::remove() { - if(!isRemovable()) - { - return FALSE; - } - return getViewModelItem()->removeItem(); + if(!isRemovable()) + { + return FALSE; + } + return getViewModelItem()->removeItem(); } // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - getViewModelItem()->buildContextMenu(menu, flags); + getViewModelItem()->buildContextMenu(menu, flags); } void LLFolderViewItem::openItem( void ) { - if (mAllowWear || !getViewModelItem()->isItemWearable()) - { - getViewModelItem()->openItem(); - } + if (mAllowWear || !getViewModelItem()->isItemWearable()) + { + getViewModelItem()->openItem(); + } } void LLFolderViewItem::rename(const std::string& new_name) { - if( !new_name.empty() ) - { - getViewModelItem()->renameItem(new_name); - } + if( !new_name.empty() ) + { + getViewModelItem()->renameItem(new_name); + } } const std::string& LLFolderViewItem::getName( void ) const { - static const std::string noName(""); - return getViewModelItem() ? getViewModelItem()->getName() : noName; + static const std::string noName(""); + return getViewModelItem() ? getViewModelItem()->getName() : noName; } // LLView functionality BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - if(!mIsSelected) - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - return TRUE; + if(!mIsSelected) + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + return TRUE; } BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { - if (LLView::childrenHandleMouseDown(x, y, mask)) - { - return TRUE; - } - - // No handler needed for focus lost since this class has no - // state that depends on it. - gFocusMgr.setMouseCapture( this ); - - if (!mIsSelected) - { - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - } - else - { - // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. - // This is necessary so we maintain selection consistent when starting a drag. - mSelectPending = TRUE; - } - - mDragStartX = x; - mDragStartY = y; - return TRUE; + if (LLView::childrenHandleMouseDown(x, y, mask)) + { + return TRUE; + } + + // No handler needed for focus lost since this class has no + // state that depends on it. + gFocusMgr.setMouseCapture( this ); + + if (!mIsSelected) + { + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + } + else + { + // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. + // This is necessary so we maintain selection consistent when starting a drag. + mSelectPending = TRUE; + } + + mDragStartX = x; + mDragStartY = y; + return TRUE; } BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { - static LLCachedControl drag_and_drop_threshold(*LLUI::getInstance()->mSettingGroups["config"],"DragAndDropDistanceThreshold", 3); - - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - if( hasMouseCapture() && isMovable() ) - { - LLFolderView* root = getRoot(); - - if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() - && root->getAllowDrag() - && root->getCurSelectedItem() - && root->startDrag()) - { - // RN: when starting drag and drop, clear out last auto-open - root->autoOpenTest(NULL); - root->setShowSelectionContext(TRUE); - - // Release keyboard focus, so that if stuff is dropped into the - // world, pressing the delete key won't blow away the inventory - // item. - gFocusMgr.setKeyboardFocus(NULL); - - getWindow()->setCursor(UI_CURSOR_ARROW); - } - else if (x != mDragStartX || y != mDragStartY) - { - getWindow()->setCursor(UI_CURSOR_NOLOCKED); - } - - root->clearHoveredItem(); - return TRUE; - } - else - { - LLFolderView* pRoot = getRoot(); - pRoot->setHoveredItem(this); - pRoot->setShowSelectionContext(FALSE); - getWindow()->setCursor(UI_CURSOR_ARROW); - // let parent handle this then... - return FALSE; - } + static LLCachedControl drag_and_drop_threshold(*LLUI::getInstance()->mSettingGroups["config"],"DragAndDropDistanceThreshold", 3); + + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + if( hasMouseCapture() && isMovable() ) + { + LLFolderView* root = getRoot(); + + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() + && root->getAllowDrag() + && root->getCurSelectedItem() + && root->startDrag()) + { + // RN: when starting drag and drop, clear out last auto-open + root->autoOpenTest(NULL); + root->setShowSelectionContext(TRUE); + + // Release keyboard focus, so that if stuff is dropped into the + // world, pressing the delete key won't blow away the inventory + // item. + gFocusMgr.setKeyboardFocus(NULL); + + getWindow()->setCursor(UI_CURSOR_ARROW); + } + else if (x != mDragStartX || y != mDragStartY) + { + getWindow()->setCursor(UI_CURSOR_NOLOCKED); + } + + root->clearHoveredItem(); + return TRUE; + } + else + { + LLFolderView* pRoot = getRoot(); + pRoot->setHoveredItem(this); + pRoot->setShowSelectionContext(FALSE); + getWindow()->setCursor(UI_CURSOR_ARROW); + // let parent handle this then... + return FALSE; + } } BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - openItem(); - return TRUE; + openItem(); + return TRUE; } BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) { - if (LLView::childrenHandleMouseUp(x, y, mask)) - { - return TRUE; - } - - // if mouse hasn't moved since mouse down... - if ( pointInView(x, y) && mSelectPending ) - { - //...then select - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - } - - mSelectPending = FALSE; - - if( hasMouseCapture() ) - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(FALSE); - } - gFocusMgr.setMouseCapture( NULL ); - } - return TRUE; + if (LLView::childrenHandleMouseUp(x, y, mask)) + { + return TRUE; + } + + // if mouse hasn't moved since mouse down... + if ( pointInView(x, y) && mSelectPending ) + { + //...then select + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + } + + mSelectPending = FALSE; + + if( hasMouseCapture() ) + { + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } + gFocusMgr.setMouseCapture( NULL ); + } + return TRUE; } void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) { - mIsMouseOverTitle = false; + 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(); - } + // 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, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = FALSE; - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - if(mParentFolder && !handled) - { - // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. - mRoot->setDraggingOverItem(this); - handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - mRoot->setDraggingOverItem(NULL); - } - if (handled) - { - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewItem" << LL_ENDL; - } - - return handled; + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + if(mParentFolder && !handled) + { + // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. + mRoot->setDraggingOverItem(this); + handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + mRoot->setDraggingOverItem(NULL); + } + if (handled) + { + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewItem" << LL_ENDL; + } + + return handled; } void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color) { - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - const S32 TOP_PAD = default_params.item_top_pad; + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + const S32 TOP_PAD = default_params.item_top_pad; - if (hasVisibleChildren() || !isFolderComplete()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, - mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color); - } + if (hasVisibleChildren() || !isFolderComplete()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, + mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color); + } } /*virtual*/ bool LLFolderViewItem::isHighlightAllowed() { - return mIsSelected; + return mIsSelected; } /*virtual*/ bool LLFolderViewItem::isHighlightActive() { - return mIsCurSelection; + return mIsCurSelection; } /*virtual*/ bool LLFolderViewItem::isFadeItem() @@ -777,31 +777,31 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsItemCut; } -void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, +void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { const S32 focus_top = getRect().getHeight(); const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; - - // Determine which background color to use for highlighting - LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); + + // Determine which background color to use for highlighting + LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); //--------------------------------------------------------------------------------// // Draw highlight for selected items - // Note: Always render "current" item or flashing item, only render other selected - // items if mShowSingleSelection is FALSE. + // Note: Always render "current" item or flashing item, only render other selected + // items if mShowSingleSelection is FALSE. // - if (isHighlightAllowed()) - + if (isHighlightAllowed()) + { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Highlight for selected but not current items + + // Highlight for selected but not current items if (!isHighlightActive() && !isFlashing()) { - LLColor4 bg_color = bgColor; + LLColor4 bg_color = bgColor; // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); if (getRoot() && getRoot()->getShowSingleSelection()) @@ -814,25 +814,25 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo // fading in bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, hasKeyboardFocus); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); } - // Highlight for currently selected or flashing item + // Highlight for currently selected or flashing item if (isHighlightActive()) { - // Background - gl_rect_2d(FOCUS_LEFT, + // Background + gl_rect_2d(FOCUS_LEFT, focus_top, getRect().getWidth() - 2, focus_bottom, bgColor, hasKeyboardFocus); - // Outline - gl_rect_2d(FOCUS_LEFT, - focus_top, + // Outline + gl_rect_2d(FOCUS_LEFT, + focus_top, getRect().getWidth() - 2, focus_bottom, focusOutlineColor, FALSE); @@ -858,7 +858,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo else if (mIsMouseOverTitle) { gl_rect_2d(FOCUS_LEFT, - focus_top, + focus_top, getRect().getWidth() - 2, focus_bottom, mouseOverColor, FALSE); @@ -870,8 +870,8 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo if (mDragAndDropTarget) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, + gl_rect_2d(FOCUS_LEFT, + focus_top, getRect().getWidth() - 2, focus_bottom, bgColor, FALSE); @@ -902,10 +902,10 @@ void LLFolderViewItem::draw() const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const Params& default_params = LLUICtrlFactory::getDefaultParams(); - const S32 TOP_PAD = default_params.item_top_pad; - - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + const Params& default_params = LLUICtrlFactory::getDefaultParams(); + const S32 TOP_PAD = default_params.item_top_pad; + + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); getViewModelItem()->update(); @@ -916,52 +916,52 @@ void LLFolderViewItem::draw() drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + mArrowSize + mTextPad; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - if (mIconOverlay && getRoot()->showItemLinkOverlays()) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - //--------------------------------------------------------------------------------// - // Exit if no label to draw - // - if (mLabel.empty()) - { - return; - } - - std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; - F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - F32 text_left = (F32)getLabelXPos(); - std::string combined_string = mLabel + mLabelSuffix; + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + mArrowSize + mTextPad; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + { + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + } + else if (mIcon) + { + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + if (mIconOverlay && getRoot()->showItemLinkOverlays()) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + //--------------------------------------------------------------------------------// + // Exit if no label to draw + // + if (mLabel.empty()) + { + return; + } + + std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + 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) - { + if (filter_string_length > 0) + { 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 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); } else { @@ -996,19 +996,19 @@ void LLFolderViewItem::draw() } drawLabel(font, text_left, y, color, right_x); - //--------------------------------------------------------------------------------// - // Draw label suffix - // - if (!mLabelSuffix.empty()) - { + //--------------------------------------------------------------------------------// + // Draw label suffix + // + if (!mLabelSuffix.empty()) + { 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); - } + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x); + } - //--------------------------------------------------------------------------------// - // Highlight string match - // + //--------------------------------------------------------------------------------// + // Highlight string match + // if (filter_string_length > 0) { if(mLabelSuffix.empty() || (font == suffix_font)) @@ -1030,7 +1030,7 @@ void LLFolderViewItem::draw() sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, label_filter_length, S32_MAX, &right_x); } - + S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; if(suffix_filter_length > 0) { @@ -1052,17 +1052,17 @@ void LLFolderViewItem::draw() const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const { - return getRoot()->getFolderViewModel(); + return getRoot()->getFolderViewModel(); } - + LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) { - return getRoot()->getFolderViewModel(); + return getRoot()->getFolderViewModel(); } bool LLFolderViewItem::isInSelection() const { - return mIsSelected || (mParentFolder && mParentFolder->isInSelection()); + return mIsSelected || (mParentFolder && mParentFolder->isInSelection()); } @@ -1071,58 +1071,58 @@ bool LLFolderViewItem::isInSelection() const /// Class LLFolderViewFolder ///---------------------------------------------------------------------------- -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), - mIsOpen(FALSE), - mExpanderHighlighted(FALSE), - mCurHeight(0.f), - mTargetHeight(0.f), - mAutoOpenCountdown(0.f), - mIsFolderComplete(false), // folder might have children that are not loaded yet. - mAreChildrenInited(false), // folder might have children that are not built yet. - mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0) +LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): + LLFolderViewItem( p ), + mIsOpen(FALSE), + mExpanderHighlighted(FALSE), + mCurHeight(0.f), + mTargetHeight(0.f), + mAutoOpenCountdown(0.f), + mIsFolderComplete(false), // folder might have children that are not loaded yet. + mAreChildrenInited(false), // folder might have children that are not built yet. + mLastArrangeGeneration( -1 ), + mLastCalculatedWidth(0) { } void LLFolderViewFolder::updateLabelRotation() { - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); - } + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); + } } // Destroys the object LLFolderViewFolder::~LLFolderViewFolder( void ) { - // The LLView base class takes care of object destruction. make sure that we - // don't have mouse or keyboard focus - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + // The LLView base class takes care of object destruction. make sure that we + // don't have mouse or keyboard focus + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() } // addToFolder() returns TRUE if it succeeds. FALSE otherwise void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { - folder->addFolder(this); + folder->addFolder(this); - // Compute indentation since parent folder changed - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; + // Compute indentation since parent folder changed + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; - if(isOpen() && folder->isOpen()) - { - requestArrange(); - } + if(isOpen() && folder->isOpen()) + { + requestArrange(); + } } static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); @@ -1136,701 +1136,701 @@ static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); // * Makes sure that this view and its children are the right size S32 LLFolderViewFolder::arrange( S32* width, S32* height ) { - // Sort before laying out contents + // Sort before laying out contents // Note that we sort from the root (CHUI-849) if (mAreChildrenInited) { getRoot()->getFolderViewModel()->sort(this); } - LL_RECORD_BLOCK_TIME(FTM_ARRANGE); - - // evaluate mHasVisibleChildren - mHasVisibleChildren = false; - if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter()) - { - // We have to verify that there's at least one child that's not filtered out - bool found = false; - // Try the items first - for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - found = itemp->isPotentiallyVisible(); - if (found) - break; - } - if (!found) - { - // If no item found, try the folders - for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - found = folderp->isPotentiallyVisible(); - if (found) - break; - } - } - - mHasVisibleChildren = found; - } - if (!mIsFolderComplete && mAreChildrenInited) - { - mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); - } - - - - // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height ); - - // clamp existing animated height so as to never get smaller than a single item - mCurHeight = llmax((F32)*height, mCurHeight); - - // initialize running height value as height of single item in case we have no children - F32 running_height = (F32)*height; - F32 target_height = (F32)*height; - - // are my children visible? - if (needsArrange()) - { - // set last arrange generation first, in case children are animating - // and need to be arranged again - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (isOpen()) - { - // Add sizes of children - S32 parent_item_height = getRect().getHeight(); - - for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - folderp->setVisible(folderp->isPotentiallyVisible()); - - if (folderp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - ll_round(running_height); - - target_height += folderp->arrange( &child_width, &child_height ); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); - } - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->isPotentiallyVisible()); - - if (itemp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - ll_round(running_height); - - target_height += itemp->arrange( &child_width, &child_height ); - // don't change width, as this item is as wide as its parent folder by construction - itemp->reshape( itemp->getRect().getWidth(), child_height); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); - } - } - } - - mTargetHeight = target_height; - // cache this width so next time we can just return it - mLastCalculatedWidth = *width; - } - else - { - // just use existing width - *width = mLastCalculatedWidth; - } - - // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) - { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - - requestArrange(); - - // hide child elements that fall out of current animated height - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - // number of pixels that bottom of folder label is from top of parent folder - if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > ll_round(mCurHeight) + mMaxFolderItemOverlap) - { - // hide if beyond current folder height - (*fit)->setVisible(FALSE); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - // number of pixels that bottom of item label is from top of parent folder - if (getRect().getHeight() - (*iit)->getRect().mBottom - > ll_round(mCurHeight) + mMaxFolderItemOverlap) - { - (*iit)->setVisible(FALSE); - } - } - } - else - { - mCurHeight = mTargetHeight; - } - - // don't change width as this item is already as wide as its parent folder - reshape(getRect().getWidth(),ll_round(mCurHeight)); - - // pass current height value back to parent - *height = ll_round(mCurHeight); - - return ll_round(mTargetHeight); -} - -BOOL LLFolderViewFolder::needsArrange() -{ - return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); -} + LL_RECORD_BLOCK_TIME(FTM_ARRANGE); -bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) -{ - return getViewModelItem()->descendantsPassedFilter(filter_generation); -} + // evaluate mHasVisibleChildren + mHasVisibleChildren = false; + if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter()) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = itemp->isPotentiallyVisible(); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = folderp->isPotentiallyVisible(); + if (found) + break; + } + } -// Passes selection information on to children and record selection -// information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - BOOL rv = FALSE; - if (selection == this) - { - if (!isSelected()) - { - selectItem(); - } - rv = TRUE; - } - else - { - if (isSelected()) - { - deselectItem(); - } - rv = FALSE; - } - BOOL child_selected = FALSE; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - if(openitem && child_selected && !mSingleFolderMode) - { - setOpenArrangeRecursively(TRUE); - } - return rv; -} + mHasVisibleChildren = found; + } + if (!mIsFolderComplete && mAreChildrenInited) + { + mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); + } -// This method is used to change the selection of an item. -// Recursively traverse all children; if 'selection' is 'this' then change -// the select status if necessary. -// Returns TRUE if the selection state of this folder, or of a child, was changed. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - if(selection == this) - { - if (isSelected() != selected) - { - rv = TRUE; - if (selected) - { - selectItem(); - } - else - { - deselectItem(); - } - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - return rv; -} -LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) -{ - if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; - - std::deque item_a_ancestors; - - LLFolderViewFolder* parent = item_a->getParentFolder(); - while(parent) - { - item_a_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - std::deque item_b_ancestors; - - parent = item_b->getParentFolder(); - while(parent) - { - item_b_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - LLFolderViewFolder* common_ancestor = item_a->getRoot(); - - while(item_a_ancestors.size() > item_b_ancestors.size()) - { - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - } - - while(item_b_ancestors.size() > item_a_ancestors.size()) - { - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - while(item_a_ancestors.size()) - { - common_ancestor = item_a_ancestors.front(); - - if (item_a_ancestors.front() == item_b_ancestors.front()) - { - // which came first, sibling a or sibling b? - for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - - for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - break; - } - - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - return NULL; -} -void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) -{ - bool selecting = start == NULL; - if (reverse) - { - for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } - else - { - for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } -} + // calculate height as a single item (without any children), and reshapes rectangle to match + LLFolderViewItem::arrange( width, height ); -void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) -{ - if (getRoot()->getAllowMultiSelect() == FALSE) return; - - LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); - if (cur_selected_item == NULL) - { - cur_selected_item = new_selection; - } - - - bool reverse = false; - LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); - if (!common_ancestor) return; - - LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; - LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); - - std::vector items_to_select_forward; - - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); - - last_selected_item_from_cur = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - std::vector items_to_select_reverse; - - LLFolderViewItem* last_selected_item_from_new = new_selection; - cur_folder = new_selection->getParentFolder(); - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); - - last_selected_item_from_new = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); - - for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); - it != end_it; - ++it) - { - items_to_select_forward.push_back(*it); - } - - LLFolderView* root = getRoot(); - - BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected - - // array always go from 'will be selected' to ' will be unselected', iterate - // in opposite direction to simplify identification of 'point of origin' in - // case it is in the list we are working with - for (std::vector::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - BOOL selected = item->isSelected(); - if (!selection_reverse && selected) - { - // it is our 'point of origin' where we shift/expand from - // don't deselect it - selection_reverse = TRUE; - } - else - { - root->changeSelection(item, !selected); - } - } - - if (selection_reverse) - { - // at some point we reversed selection, first element should be deselected - root->changeSelection(last_selected_item_from_cur, FALSE); - } - - // element we expand to should always be selected - root->changeSelection(new_selection, TRUE); -} + // clamp existing animated height so as to never get smaller than a single item + mCurHeight = llmax((F32)*height, mCurHeight); + // initialize running height value as height of single item in case we have no children + F32 running_height = (F32)*height; + F32 target_height = (F32)*height; -void LLFolderViewFolder::destroyView() -{ - while (!mItems.empty()) + // are my children visible? + if (needsArrange()) { - LLFolderViewItem *itemp = mItems.back(); - mItems.pop_back(); - itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems - } + // set last arrange generation first, in case children are animating + // and need to be arranged again + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + if (isOpen()) + { + // Add sizes of children + S32 parent_item_height = getRect().getHeight(); - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - mFolders.pop_back(); - folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders - } + for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + folderp->setVisible(folderp->isPotentiallyVisible()); - LLFolderViewItem::destroyView(); -} + if (folderp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - ll_round(running_height); -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model ) -{ - if (item->isSelected()) - getRoot()->clearSelection(); - items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); - if(it == mItems.end()) - { - // This is an evil downcast. However, it's only doing - // pointer comparison to find if (which it should be ) the - // item is in the container, so it's pretty safe. - LLFolderViewFolder* f = static_cast(item); - folders_t::iterator ft; - ft = std::find(mFolders.begin(), mFolders.end(), f); - if (ft != mFolders.end()) - { - mFolders.erase(ft); - } - } - else - { - mItems.erase(it); - } - //item has been removed, need to update filter - if (deparent_model) + target_height += folderp->arrange( &child_width, &child_height ); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); + } + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + itemp->setVisible(itemp->isPotentiallyVisible()); + + if (itemp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - ll_round(running_height); + + target_height += itemp->arrange( &child_width, &child_height ); + // don't change width, as this item is as wide as its parent folder by construction + itemp->reshape( itemp->getRect().getWidth(), child_height); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); + } + } + } + + mTargetHeight = target_height; + // cache this width so next time we can just return it + mLastCalculatedWidth = *width; + } + else { - // in some cases model does not belong to parent view, is shared between views - getViewModelItem()->removeChild(item->getViewModelItem()); + // just use existing width + *width = mLastCalculatedWidth; } - //because an item is going away regardless of filter status, force rearrange - requestArrange(); - removeChild(item); -} -BOOL LLFolderViewFolder::isMovable() -{ - if( !(getViewModelItem()->isItemMovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return FALSE; - } - } - return TRUE; -} + // animate current height towards target height + if (llabs(mCurHeight - mTargetHeight) > 1.f) + { + mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + requestArrange(); -BOOL LLFolderViewFolder::isRemovable() -{ - if( !(getViewModelItem()->isItemRemovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return FALSE; - } - } - return TRUE; -} + // hide child elements that fall out of current animated height + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // number of pixels that bottom of folder label is from top of parent folder + if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() + > ll_round(mCurHeight) + mMaxFolderItemOverlap) + { + // hide if beyond current folder height + (*fit)->setVisible(FALSE); + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + // number of pixels that bottom of item label is from top of parent folder + if (getRect().getHeight() - (*iit)->getRect().mBottom + > ll_round(mCurHeight) + mMaxFolderItemOverlap) + { + (*iit)->setVisible(FALSE); + } + } + } + else + { + mCurHeight = mTargetHeight; + } + + // don't change width as this item is already as wide as its parent folder + reshape(getRect().getWidth(),ll_round(mCurHeight)); + + // pass current height value back to parent + *height = ll_round(mCurHeight); + + return ll_round(mTargetHeight); +} + +BOOL LLFolderViewFolder::needsArrange() +{ + return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); +} + +bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) +{ + return getViewModelItem()->descendantsPassedFilter(filter_generation); +} + +// Passes selection information on to children and record selection +// information if necessary. +BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + BOOL rv = FALSE; + if (selection == this) + { + if (!isSelected()) + { + selectItem(); + } + rv = TRUE; + } + else + { + if (isSelected()) + { + deselectItem(); + } + rv = FALSE; + } + BOOL child_selected = FALSE; + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + if(openitem && child_selected && !mSingleFolderMode) + { + setOpenArrangeRecursively(TRUE); + } + return rv; +} + +// This method is used to change the selection of an item. +// Recursively traverse all children; if 'selection' is 'this' then change +// the select status if necessary. +// Returns TRUE if the selection state of this folder, or of a child, was changed. +BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + if(selection == this) + { + if (isSelected() != selected) + { + rv = TRUE; + if (selected) + { + selectItem(); + } + else + { + deselectItem(); + } + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + return rv; +} + +LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) +{ + if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; + + std::deque item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) + { + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + std::deque item_b_ancestors; + + parent = item_b->getParentFolder(); + while(parent) + { + item_b_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + LLFolderViewFolder* common_ancestor = item_a->getRoot(); + + while(item_a_ancestors.size() > item_b_ancestors.size()) + { + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + } + + while(item_b_ancestors.size() > item_a_ancestors.size()) + { + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + while(item_a_ancestors.size()) + { + common_ancestor = item_a_ancestors.front(); + + if (item_a_ancestors.front() == item_b_ancestors.front()) + { + // which came first, sibling a or sibling b? + for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + + for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + break; + } + + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + return NULL; +} + +void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) +{ + bool selecting = start == NULL; + if (reverse) + { + for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } + else + { + for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } +} + +void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) +{ + if (getRoot()->getAllowMultiSelect() == FALSE) return; + + LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); + if (cur_selected_item == NULL) + { + cur_selected_item = new_selection; + } + + + bool reverse = false; + LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); + if (!common_ancestor) return; + + LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; + LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); + + std::vector items_to_select_forward; + + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); + + last_selected_item_from_cur = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + std::vector items_to_select_reverse; + + LLFolderViewItem* last_selected_item_from_new = new_selection; + cur_folder = new_selection->getParentFolder(); + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); + + last_selected_item_from_new = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); + + for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); + it != end_it; + ++it) + { + items_to_select_forward.push_back(*it); + } + + LLFolderView* root = getRoot(); + + BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected + + // array always go from 'will be selected' to ' will be unselected', iterate + // in opposite direction to simplify identification of 'point of origin' in + // case it is in the list we are working with + for (std::vector::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + BOOL selected = item->isSelected(); + if (!selection_reverse && selected) + { + // it is our 'point of origin' where we shift/expand from + // don't deselect it + selection_reverse = TRUE; + } + else + { + root->changeSelection(item, !selected); + } + } + + if (selection_reverse) + { + // at some point we reversed selection, first element should be deselected + root->changeSelection(last_selected_item_from_cur, FALSE); + } + + // element we expand to should always be selected + root->changeSelection(new_selection, TRUE); +} + + +void LLFolderViewFolder::destroyView() +{ + while (!mItems.empty()) + { + LLFolderViewItem *itemp = mItems.back(); + mItems.pop_back(); + itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems + } + + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + mFolders.pop_back(); + folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders + } + + LLFolderViewItem::destroyView(); +} + +// extractItem() removes the specified item from the folder, but +// doesn't delete it. +void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model ) +{ + if (item->isSelected()) + getRoot()->clearSelection(); + items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); + if(it == mItems.end()) + { + // This is an evil downcast. However, it's only doing + // pointer comparison to find if (which it should be ) the + // item is in the container, so it's pretty safe. + LLFolderViewFolder* f = static_cast(item); + folders_t::iterator ft; + ft = std::find(mFolders.begin(), mFolders.end(), f); + if (ft != mFolders.end()) + { + mFolders.erase(ft); + } + } + else + { + mItems.erase(it); + } + //item has been removed, need to update filter + if (deparent_model) + { + // in some cases model does not belong to parent view, is shared between views + getViewModelItem()->removeChild(item->getViewModelItem()); + } + //because an item is going away regardless of filter status, force rearrange + requestArrange(); + removeChild(item); +} + +BOOL LLFolderViewFolder::isMovable() +{ + if( !(getViewModelItem()->isItemMovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) + { + return FALSE; + } + } + return TRUE; +} + + +BOOL LLFolderViewFolder::isRemovable() +{ + if( !(getViewModelItem()->isItemRemovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) + { + return FALSE; + } + } + return TRUE; +} void LLFolderViewFolder::destroyRoot() { delete this; } -// this is an internal method used for adding items to folders. +// this is an internal method used for adding items to folders. void LLFolderViewFolder::addItem(LLFolderViewItem* item) { - if (item->getParentFolder()) - { - item->getParentFolder()->extractItem(item); - } - item->setParentFolder(this); - - mItems.push_back(item); - - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(FALSE); - - addChild(item); - - // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it - // Note: this happens when models are created before views or shared between views - if (!item->getViewModelItem()->hasParent()) - { - getViewModelItem()->addChild(item->getViewModelItem()); - } -} - -// this is an internal method used for adding items to folders. + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + + mItems.push_back(item); + + item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); + item->setVisible(FALSE); + + addChild(item); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!item->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(item->getViewModelItem()); + } +} + +// this is an internal method used for adding items to folders. void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) { - if (folder->mParentFolder) - { - folder->mParentFolder->extractItem(folder); - } - folder->mParentFolder = this; - mFolders.push_back(folder); - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - // rearrange all descendants too, as our indentation level might have changed - //folder->requestArrange(); - //requestSort(); - - addChild(folder); - - // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it - // Note: this happens when models are created before views or shared between views - if (!folder->getViewModelItem()->hasParent()) - { - getViewModelItem()->addChild(folder->getViewModelItem()); - } + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; + mFolders.push_back(folder); + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(FALSE); + // rearrange all descendants too, as our indentation level might have changed + //folder->requestArrange(); + //requestSort(); + + addChild(folder); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!folder->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(folder->getViewModelItem()); + } } void LLFolderViewFolder::requestArrange() @@ -1845,7 +1845,7 @@ void LLFolderViewFolder::requestArrange() void LLFolderViewFolder::toggleOpen() { - setOpen(!isOpen()); + setOpen(!isOpen()); } // Force a folder open or closed @@ -1868,223 +1868,223 @@ void LLFolderViewFolder::setOpen(BOOL openitem) void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) { - BOOL was_open = isOpen(); - mIsOpen = openitem; - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - // openItem() will request content, it won't be incomplete - mIsFolderComplete = true; - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } - - if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ - } - } - if (mParentFolder - && (recurse == RECURSE_UP - || recurse == RECURSE_UP_DOWN)) - { - mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); - } - - if (was_open != isOpen()) - { - requestArrange(); - } + BOOL was_open = isOpen(); + mIsOpen = openitem; + if(!was_open && openitem) + { + getViewModelItem()->openItem(); + // openItem() will request content, it won't be incomplete + mIsFolderComplete = true; + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); + } + + if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ + } + } + if (mParentFolder + && (recurse == RECURSE_UP + || recurse == RECURSE_UP_DOWN)) + { + mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); + } + + if (was_open != isOpen()) + { + requestArrange(); + } } BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } - // drag and drop to child item, so clear pending auto-opens - getRoot()->autoOpenTest(NULL); + // drag and drop to child item, so clear pending auto-opens + getRoot()->autoOpenTest(NULL); - return TRUE; + return TRUE; } void LLFolderViewFolder::openItem( void ) { - toggleOpen(); + toggleOpen(); } void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - functor.doItem((*fit)); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + functor.doItem((*fit)); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } } void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) { - functor.doFolder(this); + functor.doFolder(this); - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } } // LLView functionality BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - BOOL handled = FALSE; + BOOL handled = FALSE; - if (isOpen()) - { - handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); - } + if (isOpen()) + { + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); + } - if (!handled) - { - handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + if (!handled) + { + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewFolder" << LL_ENDL; - } + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewFolder" << LL_ENDL; + } - return TRUE; + return TRUE; } BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { if (!mAllowDrop) { - *accept = ACCEPT_NO; + *accept = ACCEPT_NO; tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); return TRUE; } - - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - getRoot()->autoOpenTest(this); - } - - return TRUE; + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return TRUE; } BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; + BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - } - if (!handled) - { - handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); - } - return handled; + if( isOpen() ) + { + handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; + } + if (!handled) + { + handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); + } + return handled; } BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) { - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - BOOL handled = LLView::handleHover(x, y, mask); + BOOL handled = LLView::handleHover(x, y, mask); - if (!handled) - { - // this doesn't do child processing - handled = LLFolderViewItem::handleHover(x, y, mask); - } + if (!handled) + { + // this doesn't do child processing + handled = LLFolderViewItem::handleHover(x, y, mask); + } - return handled; + return handled; } BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleMouseDown(x,y,mask) != NULL; - } - if( !handled ) - { - if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + BOOL handled = FALSE; + if( isOpen() ) + { + handled = childrenHandleMouseDown(x,y,mask) != NULL; + } + if( !handled ) + { + if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) && !mSingleFolderMode) - { - toggleOpen(); - handled = TRUE; - } - else - { - // do normal selection logic - handled = LLFolderViewItem::handleMouseDown(x, y, mask); - } - } + { + toggleOpen(); + handled = TRUE; + } + else + { + // do normal selection logic + handled = LLFolderViewItem::handleMouseDown(x, y, mask); + } + } - return handled; + return handled; } BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; + BOOL handled = FALSE; if(mSingleFolderMode) { static LLUICachedControl double_click_new_window("SingleModeDoubleClickOpenWindow", false); @@ -2104,12 +2104,12 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) return TRUE; } - if( isOpen() ) - { - handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - } - if( !handled ) - { + if( isOpen() ) + { + handled = childrenHandleDoubleClick( x, y, mask ) != NULL; + } + if( !handled ) + { if(mDoubleClickOverride) { static LLUICachedControl double_click_action("MultiModeDoubleClickFolder", false); @@ -2124,245 +2124,245 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) return TRUE; } } - if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) - { - // don't select when user double-clicks plus sign - // so as not to contradict single-click behavior - toggleOpen(); - } - else - { - getRoot()->setSelection(this, FALSE); - toggleOpen(); - } - handled = TRUE; - } - return handled; + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + { + // don't select when user double-clicks plus sign + // so as not to contradict single-click behavior + toggleOpen(); + } + else + { + getRoot()->setSelection(this, FALSE); + toggleOpen(); + } + handled = TRUE; + } + return handled; } void LLFolderViewFolder::draw() { - updateLabelRotation(); + updateLabelRotation(); - LLFolderViewItem::draw(); + LLFolderViewItem::draw(); - // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) - { - LLView::draw(); - } + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) + { + LLView::draw(); + } - mExpanderHighlighted = FALSE; + mExpanderHighlighted = FALSE; } // this does prefix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) { - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at beginning - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::iterator fit = mFolders.begin(); - folders_t::iterator fend = mFolders.end(); - - items_t::iterator iit = mItems.begin(); - items_t::iterator iend = mItems.end(); - - // if not trivially starting at the beginning, we have to find the current item - if (!found_item) - { - // first, look among folders, since they are always above items - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // if we are on downwards traversal - if (include_children && (*fit)->isOpen()) - { - // look for first descendant - return (*fit)->getNextFromChild(NULL, TRUE); - } - // otherwise advance to next folder - ++fit; - include_children = TRUE; - break; - } - } - - // didn't find in folders? Check items... - if (!found_item) - { - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found folder, continue through folders - // searching for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - // turn on downwards traversal for next folder - ++fit; - } - - if (fit != fend) - { - result = (*fit); - } - else - { - // otherwise, scan for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - // check to see if we have a valid item - if (iit != iend) - { - result = (*iit); - } - } - - if( !result && mParentFolder ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, FALSE); - } - - return result; + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at beginning + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::iterator fit = mFolders.begin(); + folders_t::iterator fend = mFolders.end(); + + items_t::iterator iit = mItems.begin(); + items_t::iterator iend = mItems.end(); + + // if not trivially starting at the beginning, we have to find the current item + if (!found_item) + { + // first, look among folders, since they are always above items + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // if we are on downwards traversal + if (include_children && (*fit)->isOpen()) + { + // look for first descendant + return (*fit)->getNextFromChild(NULL, TRUE); + } + // otherwise advance to next folder + ++fit; + include_children = TRUE; + break; + } + } + + // didn't find in folders? Check items... + if (!found_item) + { + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found folder, continue through folders + // searching for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + // turn on downwards traversal for next folder + ++fit; + } + + if (fit != fend) + { + result = (*fit); + } + else + { + // otherwise, scan for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + // check to see if we have a valid item + if (iit != iend) + { + result = (*iit); + } + } + + if( !result && mParentFolder ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // and skip children for this folder, as we've already discounted them + result = mParentFolder->getNextFromChild(this, FALSE); + } + + return result; } // this does postfix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) { - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at end - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::reverse_iterator fit = mFolders.rbegin(); - folders_t::reverse_iterator fend = mFolders.rend(); - - items_t::reverse_iterator iit = mItems.rbegin(); - items_t::reverse_iterator iend = mItems.rend(); - - // if not trivially starting at the end, we have to find the current item - if (!found_item) - { - // first, look among items, since they are always below the folders - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - - // didn't find in items? Check folders... - if (!found_item) - { - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // point to next folder - ++fit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found item, continue through items - // searching for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - if (iit != iend) - { - // we found an appropriate item - result = (*iit); - } - else - { - // otherwise, scan for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - ++fit; - } - - // check to see if we have a valid folder - if (fit != fend) - { - // try selecting child element of this folder - if ((*fit)->isOpen() && include_children) - { - result = (*fit)->getPreviousFromChild(NULL); - } - else - { - result = (*fit); - } - } - } - - if( !result ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // which gets back to this folder, which will only be visited if it is a valid, visible item - result = this; - } - - return result; + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at end + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::reverse_iterator fit = mFolders.rbegin(); + folders_t::reverse_iterator fend = mFolders.rend(); + + items_t::reverse_iterator iit = mItems.rbegin(); + items_t::reverse_iterator iend = mItems.rend(); + + // if not trivially starting at the end, we have to find the current item + if (!found_item) + { + // first, look among items, since they are always below the folders + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + + // didn't find in items? Check folders... + if (!found_item) + { + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // point to next folder + ++fit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found item, continue through items + // searching for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + if (iit != iend) + { + // we found an appropriate item + result = (*iit); + } + else + { + // otherwise, scan for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + ++fit; + } + + // check to see if we have a valid folder + if (fit != fend) + { + // try selecting child element of this folder + if ((*fit)->isOpen() && include_children) + { + result = (*fit)->getPreviousFromChild(NULL); + } + else + { + result = (*fit); + } + } + } + + if( !result ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // which gets back to this folder, which will only be visited if it is a valid, visible item + result = this; + } + + return result; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 5c2a1ecff0..351613e387 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -1,25 +1,25 @@ -/** +/** * @file llfolderviewitem.h * @brief Items and folders that can appear in a hierarchical folder view * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,24 +47,24 @@ class LLFolderViewModelInterface; class LLFolderViewItem : public LLView { public: - struct Params : public LLInitParam::Block - { - Optional folder_arrow_image, - selection_image; - Mandatory root; - Mandatory listener; - - Optional folder_indentation, // pixels - item_height, - item_top_pad; - - Optional creation_date; - Optional allow_wear; - Optional allow_drop; - - Optional font_color; - Optional font_highlight_color; - + struct Params : public LLInitParam::Block + { + Optional folder_arrow_image, + selection_image; + Mandatory root; + Mandatory listener; + + Optional folder_indentation, // pixels + item_height, + item_top_pad; + + Optional creation_date; + Optional allow_wear; + Optional allow_drop; + + Optional font_color; + Optional font_highlight_color; + Optional left_pad, icon_pad, icon_width, @@ -74,38 +74,38 @@ public: max_folder_item_overlap; Optional single_folder_mode, double_click_override; - Params(); - }; + Params(); + }; - static const S32 DEFAULT_LABEL_PADDING_RIGHT = 4; - // animation parameters - static const F32 FOLDER_CLOSE_TIME_CONSTANT, - FOLDER_OPEN_TIME_CONSTANT; + static const S32 DEFAULT_LABEL_PADDING_RIGHT = 4; + // animation parameters + static const F32 FOLDER_CLOSE_TIME_CONSTANT, + FOLDER_OPEN_TIME_CONSTANT; protected: - friend class LLUICtrlFactory; - friend class LLFolderViewModelItem; + friend class LLUICtrlFactory; + friend class LLFolderViewModelItem; - LLFolderViewItem(const Params& p); + LLFolderViewItem(const Params& p); - std::string mLabel; - S32 mLabelWidth; - bool mLabelWidthDirty; + std::string mLabel; + S32 mLabelWidth; + bool mLabelWidthDirty; S32 mLabelPaddingRight; - LLFolderViewFolder* mParentFolder; - LLPointer mViewModelItem; - LLFontGL::StyleFlags mLabelStyle; - std::string mLabelSuffix; - bool mSuffixNeedsRefresh; //suffix and icons - LLUIImagePtr mIcon, - mIconOpen, - mIconOverlay; + LLFolderViewFolder* mParentFolder; + LLPointer mViewModelItem; + LLFontGL::StyleFlags mLabelStyle; + std::string mLabelSuffix; + bool mSuffixNeedsRefresh; //suffix and icons + LLUIImagePtr mIcon, + mIconOpen, + mIconOverlay; S32 mLocalIndentation; - S32 mIndentation; - S32 mItemHeight; - S32 mDragStartX, - mDragStartY; + S32 mIndentation; + S32 mItemHeight; + S32 mDragStartX, + mDragStartY; S32 mLeftPad, mIconPad, @@ -115,163 +115,163 @@ protected: mArrowSize, mMaxFolderItemOverlap; - F32 mControlLabelRotation; - LLFolderView* mRoot; - bool mHasVisibleChildren, - mIsCurSelection, - mDragAndDropTarget, - mIsMouseOverTitle, - mAllowWear, + F32 mControlLabelRotation; + LLFolderView* mRoot; + bool mHasVisibleChildren, + mIsCurSelection, + mDragAndDropTarget, + mIsMouseOverTitle, + mAllowWear, mAllowDrop, mSingleFolderMode, mDoubleClickOverride, - mSelectPending, - mIsItemCut; - - S32 mCutGeneration; - - LLUIColor mFontColor; - LLUIColor mFontHighlightColor; - - // For now assuming all colors are the same in derived classes. - static bool sColorSetInitialized; - static LLUIColor sFgColor; - static LLUIColor sFgDisabledColor; - static LLUIColor sHighlightBgColor; - static LLUIColor sFlashBgColor; - static LLUIColor sFocusOutlineColor; - static LLUIColor sMouseOverColor; - static LLUIColor sFilterBGColor; - static LLUIColor sFilterTextColor; - static LLUIColor sSuffixColor; - static LLUIColor sSearchStatusColor; - - // this is an internal method used for adding items to folders. A - // no-op at this level, but reimplemented in derived classes. - virtual void addItem(LLFolderViewItem*) { } - virtual void addFolder(LLFolderViewFolder*) { } - virtual bool isHighlightAllowed(); - virtual bool isHighlightActive(); - virtual bool isFadeItem(); - virtual bool isFlashing() { return false; } - virtual void setFlashState(bool) { } - - static LLFontGL* getLabelFontForStyle(U8 style); - - BOOL mIsSelected; + mSelectPending, + mIsItemCut; + + S32 mCutGeneration; + + LLUIColor mFontColor; + LLUIColor mFontHighlightColor; + + // For now assuming all colors are the same in derived classes. + static bool sColorSetInitialized; + static LLUIColor sFgColor; + static LLUIColor sFgDisabledColor; + static LLUIColor sHighlightBgColor; + static LLUIColor sFlashBgColor; + static LLUIColor sFocusOutlineColor; + static LLUIColor sMouseOverColor; + static LLUIColor sFilterBGColor; + static LLUIColor sFilterTextColor; + static LLUIColor sSuffixColor; + static LLUIColor sSearchStatusColor; + + // this is an internal method used for adding items to folders. A + // no-op at this level, but reimplemented in derived classes. + virtual void addItem(LLFolderViewItem*) { } + virtual void addFolder(LLFolderViewFolder*) { } + virtual bool isHighlightAllowed(); + virtual bool isHighlightActive(); + virtual bool isFadeItem(); + virtual bool isFlashing() { return false; } + virtual void setFlashState(bool) { } + + static LLFontGL* getLabelFontForStyle(U8 style); + + BOOL mIsSelected; public: - static void initClass(); - static void cleanupClass(); + static void initClass(); + static void cleanupClass(); - BOOL postBuild(); + BOOL postBuild(); - virtual void openItem( void ); + virtual void openItem( void ); - void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); + void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); - virtual ~LLFolderViewItem( void ); + virtual ~LLFolderViewItem( void ); - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual void addToFolder(LLFolderViewFolder* folder); + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual void addToFolder(LLFolderViewFolder* folder); - // 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() const; + // 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() const; virtual S32 getLabelXPos(); S32 getIconPad(); S32 getTextPad(); - // If 'selection' is 'this' then note that otherwise ignore. - // Returns TRUE if this item ends up being selected. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + // If 'selection' is 'this' then note that otherwise ignore. + // Returns TRUE if this item ends up being selected. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - // This method is used to set the selection state of an item. - // If 'selection' is 'this' then note selection. - // Returns TRUE if the selection state of this item was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + // This method is used to set the selection state of an item. + // If 'selection' is 'this' then note selection. + // Returns TRUE if the selection state of this item was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - // this method is used to deselect this element - void deselectItem(); + // this method is used to deselect this element + void deselectItem(); - // this method is used to select this element - virtual void selectItem(); + // this method is used to select this element + virtual void selectItem(); - // gets multiple-element selection - virtual std::set getSelectionList() const; + // gets multiple-element selection + virtual std::set getSelectionList() const; - // Returns true is this object and all of its children can be removed (deleted by user) - virtual BOOL isRemovable(); + // Returns true is this object and all of its children can be removed (deleted by user) + virtual BOOL isRemovable(); - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); - // destroys this item recursively - virtual void destroyView(); + // destroys this item recursively + virtual void destroyView(); - BOOL isSelected() const { return mIsSelected; } - bool isInSelection() const; + BOOL isSelected() const { return mIsSelected; } + bool isInSelection() const; - void setUnselected() { mIsSelected = FALSE; } + void setUnselected() { mIsSelected = FALSE; } - void setIsCurSelection(BOOL select) { mIsCurSelection = select; } + void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - BOOL getIsCurSelection() const { return mIsCurSelection; } + BOOL getIsCurSelection() const { return mIsCurSelection; } - BOOL hasVisibleChildren() const { return mHasVisibleChildren; } + BOOL hasVisibleChildren() const { return mHasVisibleChildren; } - // true if object can't have children - virtual bool isFolderComplete() { return true; } + // true if object can't have children + virtual bool isFolderComplete() { return true; } // true if object can't have children virtual bool areChildrenInited() { return true; } virtual void setChildrenInited(bool inited) { } - // Call through to the viewed object and return true if it can be - // removed. Returns true if it's removed. - //virtual BOOL removeRecursively(BOOL single_item); - BOOL remove(); + // Call through to the viewed object and return true if it can be + // removed. Returns true if it's removed. + //virtual BOOL removeRecursively(BOOL single_item); + BOOL remove(); - // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(class LLMenuGL& menu, U32 flags); + // Build an appropriate context menu for the item. Flags unused. + void buildContextMenu(class LLMenuGL& menu, U32 flags); - // This method returns the actual name of the thing being - // viewed. This method will ask the viewed object itself. - const std::string& getName( void ) const; + // This method returns the actual name of the thing being + // viewed. This method will ask the viewed object itself. + const std::string& getName( void ) const; - // This method returns the label displayed on the view. This - // method was primarily added to allow sorting on the folder - // contents possible before the entire view has been constructed. - const std::string& getLabel() const { return mLabel; } + // This method returns the label displayed on the view. This + // method was primarily added to allow sorting on the folder + // contents possible before the entire view has been constructed. + const std::string& getLabel() const { return mLabel; } - LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } - const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } + const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } - void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } + void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } - LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } - LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } + const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } + LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } - const LLFolderViewModelInterface* getFolderViewModel( void ) const; - LLFolderViewModelInterface* getFolderViewModel( void ); + const LLFolderViewModelInterface* getFolderViewModel( void ) const; + LLFolderViewModelInterface* getFolderViewModel( void ); - // just rename the object. - void rename(const std::string& new_name); + // just rename the object. + void rename(const std::string& new_name); - // Show children - virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } + // Show children + virtual void setOpen(BOOL open = TRUE) {}; + virtual BOOL isOpen() const { return FALSE; } - virtual LLFolderView* getRoot(); - virtual const LLFolderView* getRoot() const; - BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() const { return mIndentation; } + virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; + BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); + S32 getIndentation() const { return mIndentation; } - virtual BOOL passedFilter(S32 filter_generation = -1); - virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); + virtual BOOL passedFilter(S32 filter_generation = -1); + virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); // refresh information from the object being viewed. // refreshes label, suffixes and sets icons. Expensive! @@ -279,34 +279,34 @@ public: virtual void refresh(); // refreshes suffixes and sets icons. Expensive! // Does not need filter update - virtual void refreshSuffix(); + 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 ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + // LLView functionality + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); - //virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return LLView::findChildView(name, recurse); } + //virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return LLView::findChildView(name, recurse); } - // virtual void handleDropped(); - virtual void draw(); - void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); + // virtual void handleDropped(); + virtual void draw(); + void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); private: - static std::map sFonts; // map of styles to fonts + static std::map sFonts; // map of styles to fonts }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -320,79 +320,79 @@ private: class LLFolderViewFolder : public LLFolderViewItem { protected: - LLFolderViewFolder( const LLFolderViewItem::Params& ); - friend class LLUICtrlFactory; + LLFolderViewFolder( const LLFolderViewItem::Params& ); + friend class LLUICtrlFactory; - void updateLabelRotation(); - virtual bool isCollapsed() { return FALSE; } + void updateLabelRotation(); + virtual bool isCollapsed() { return FALSE; } public: - typedef std::list items_t; - typedef std::list folders_t; + typedef std::list items_t; + typedef std::list folders_t; protected: - items_t mItems; - folders_t mFolders; - - BOOL mIsOpen; - BOOL mExpanderHighlighted; - F32 mCurHeight; - F32 mTargetHeight; - F32 mAutoOpenCountdown; - S32 mLastArrangeGeneration; - S32 mLastCalculatedWidth; - bool mIsFolderComplete; // indicates that some children were not loaded/added yet - bool mAreChildrenInited; // indicates that no children were initialized + items_t mItems; + folders_t mFolders; + + BOOL mIsOpen; + BOOL mExpanderHighlighted; + F32 mCurHeight; + F32 mTargetHeight; + F32 mAutoOpenCountdown; + S32 mLastArrangeGeneration; + S32 mLastCalculatedWidth; + bool mIsFolderComplete; // indicates that some children were not loaded/added yet + bool mAreChildrenInited; // indicates that no children were initialized public: - typedef enum e_recurse_type - { - RECURSE_NO, - RECURSE_UP, - RECURSE_DOWN, - RECURSE_UP_DOWN - } ERecurseType; + typedef enum e_recurse_type + { + RECURSE_NO, + RECURSE_UP, + RECURSE_DOWN, + RECURSE_UP_DOWN + } ERecurseType; - virtual ~LLFolderViewFolder( void ); + virtual ~LLFolderViewFolder( void ); - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual void addToFolder(LLFolderViewFolder* folder); + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual void addToFolder(LLFolderViewFolder* folder); - // 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 ); + // 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 ); - BOOL needsArrange(); + BOOL needsArrange(); - bool descendantsPassedFilter(S32 filter_generation = -1); + bool descendantsPassedFilter(S32 filter_generation = -1); - // Passes selection information on to children and record - // selection information if necessary. - // Returns TRUE if this object (or a child) ends up being selected. - // If 'openitem' is TRUE then folders are opened up along the way to the selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); + // Passes selection information on to children and record + // selection information if necessary. + // Returns TRUE if this object (or a child) ends up being selected. + // If 'openitem' is TRUE then folders are opened up along the way to the selection. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); - // This method is used to change the selection of an item. - // Recursively traverse all children; if 'selection' is 'this' then change - // the select status if necessary. - // Returns TRUE if the selection state of this folder, or of a child, was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + // This method is used to change the selection of an item. + // Recursively traverse all children; if 'selection' is 'this' then change + // the select status if necessary. + // Returns TRUE if the selection state of this folder, or of a child, was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - // this method is used to group select items - void extendSelectionTo(LLFolderViewItem* selection); + // this method is used to group select items + void extendSelectionTo(LLFolderViewItem* selection); - // Returns true is this object and all of its children can be removed. - virtual BOOL isRemovable(); + // Returns true is this object and all of its children can be removed. + virtual BOOL isRemovable(); - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); - // destroys this folder, and all children - virtual void destroyView(); + // destroys this folder, and all children + virtual void destroyView(); void destroyRoot(); // whether known children are fully loaded (arrange sets to true) @@ -402,89 +402,89 @@ public: virtual bool areChildrenInited() { return mAreChildrenInited; } virtual void setChildrenInited(bool inited) { mAreChildrenInited = inited; } - // extractItem() removes the specified item from the folder, but - // doesn't delete it. - virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true); - - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } - - // folders can be opened. This will usually be called by internal - // methods. - virtual void toggleOpen(); - - // Force a folder open or closed - virtual void setOpen(BOOL openitem = TRUE); - - // Called when a child is refreshed. - virtual void requestArrange(); - - // internal method which doesn't update the entire view. This - // method was written because the list iterators destroy the state - // of other iterations, thus, we can't arrange while iterating - // through the children (such as when setting which is selected. - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); - - // Get the current state of the folder. - virtual BOOL isOpen() const { return mIsOpen; } - - // special case if an object is dropped on the child. - BOOL handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - - // Just apply this functor to the folder's immediate children. - void applyFunctorToChildren(LLFolderViewFunctor& functor); - // apply this functor to the folder's descendants. - void applyFunctorRecursively(LLFolderViewFunctor& functor); - - virtual void openItem( void ); - - // LLView functionality - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - BOOL handleDragAndDropToThisFolder(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - virtual void draw(); - - folders_t::iterator getFoldersBegin() { return mFolders.begin(); } - folders_t::iterator getFoldersEnd() { return mFolders.end(); } - folders_t::size_type getFoldersCount() const { return mFolders.size(); } - - items_t::const_iterator getItemsBegin() const { return mItems.begin(); } - items_t::const_iterator getItemsEnd() const { return mItems.end(); } - items_t::size_type getItemsCount() const { return mItems.size(); } - - LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); - void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items); - - // internal functions for tracking folders and items separately - // use addToFolder() virtual method to ensure folders are always added to mFolders - // and not mItems - void addItem(LLFolderViewItem* item); - void addFolder( LLFolderViewFolder* folder); - - //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead - template void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } - template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } + // extractItem() removes the specified item from the folder, but + // doesn't delete it. + virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true); + + // This function is called by a child that needs to be resorted. + void resort(LLFolderViewItem* item); + + void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } + + // folders can be opened. This will usually be called by internal + // methods. + virtual void toggleOpen(); + + // Force a folder open or closed + virtual void setOpen(BOOL openitem = TRUE); + + // Called when a child is refreshed. + virtual void requestArrange(); + + // internal method which doesn't update the entire view. This + // method was written because the list iterators destroy the state + // of other iterations, thus, we can't arrange while iterating + // through the children (such as when setting which is selected. + virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); + + // Get the current state of the folder. + virtual BOOL isOpen() const { return mIsOpen; } + + // special case if an object is dropped on the child. + BOOL handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + + // Just apply this functor to the folder's immediate children. + void applyFunctorToChildren(LLFolderViewFunctor& functor); + // apply this functor to the folder's descendants. + void applyFunctorRecursively(LLFolderViewFunctor& functor); + + virtual void openItem( void ); + + // LLView functionality + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + virtual void draw(); + + folders_t::iterator getFoldersBegin() { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() { return mFolders.end(); } + folders_t::size_type getFoldersCount() const { return mFolders.size(); } + + items_t::const_iterator getItemsBegin() const { return mItems.begin(); } + items_t::const_iterator getItemsEnd() const { return mItems.end(); } + items_t::size_type getItemsCount() const { return mItems.size(); } + + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); + void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items); + + // internal functions for tracking folders and items separately + // use addToFolder() virtual method to ensure folders are always added to mFolders + // and not mItems + void addItem(LLFolderViewItem* item); + void addFolder( LLFolderViewFolder* folder); + + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } + template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } }; typedef std::deque folder_view_item_deque; diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index f217b743a0..c7ed65bdfa 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfolderviewmodel.cpp * @brief Implementation of the view model collection of classes. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,19 +31,19 @@ bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) { - return item->getSortVersion() < mTargetSortVersion; + return item->getSortVersion() < mTargetSortVersion; } std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder) { - if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration()) - { - return LLTrans::getString("Searching"); - } - else - { - return getFilter().getEmptyLookupMessage(is_empty_folder); - } + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration()) + { + return LLTrans::getString("Searching"); + } + else + { + return getFilter().getEmptyLookupMessage(is_empty_folder); + } } void LLFolderViewModelCommon::filter() @@ -55,15 +55,15 @@ void LLFolderViewModelCommon::filter() bool LLFolderViewModelItemCommon::hasFilterStringMatch() { - return mStringMatchOffsetFilter != std::string::npos; + return mStringMatchOffsetFilter != std::string::npos; } std::string::size_type LLFolderViewModelItemCommon::getFilterStringOffset() { - return mStringMatchOffsetFilter; + return mStringMatchOffsetFilter; } std::string::size_type LLFolderViewModelItemCommon::getFilterStringSize() { - return mRootViewModel.getFilter().getFilterStringSize(); + return mRootViewModel.getFilter().getFilterStringSize(); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 551a60e097..53ae2bd97f 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -1,41 +1,41 @@ -/** +/** * @file llfolderviewmodel.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLFOLDERVIEWMODEL_H #define LLFOLDERVIEWMODEL_H -#include "llfontgl.h" // just for StyleFlags enum +#include "llfontgl.h" // just for StyleFlags enum #include "llfolderview.h" // These are grouping of inventory types. // Order matters when sorting system folders to the top. enum EInventorySortGroup { - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM }; class LLFontGL; @@ -49,85 +49,85 @@ class LLFolderViewFolder; class LLFolderViewFilter { public: - enum EFilterModified - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - }; + enum EFilterModified + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + }; public: - LLFolderViewFilter() {} - virtual ~LLFolderViewFilter() {} - - // +-------------------------------------------------------------------+ - // + Execution And Results - // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewModelItem* item) = 0; - virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; - - virtual void setEmptyLookupMessage(const std::string& message) = 0; - virtual std::string getEmptyLookupMessage(bool is_empty_folder = false) const = 0; - - virtual bool showAllResults() const = 0; - - virtual std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const = 0; - virtual std::string::size_type getFilterStringSize() const = 0; - // +-------------------------------------------------------------------+ - // + Status - // +-------------------------------------------------------------------+ - virtual bool isActive() const = 0; - virtual bool isModified() const = 0; - virtual void clearModified() = 0; - virtual const std::string& getName() const = 0; - virtual const std::string& getFilterText() = 0; - //RN: this is public to allow system to externally force a global refilter - virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; - - // +-------------------------------------------------------------------+ - // + Time - // +-------------------------------------------------------------------+ - virtual void resetTime(S32 timeout) = 0; + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewModelItem* item) = 0; + virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + virtual std::string getEmptyLookupMessage(bool is_empty_folder = false) const = 0; + + virtual bool showAllResults() const = 0; + + virtual std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const = 0; + virtual std::string::size_type getFilterStringSize() const = 0; + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Time + // +-------------------------------------------------------------------+ + virtual void resetTime(S32 timeout) = 0; virtual bool isTimedOut() = 0; - - // +-------------------------------------------------------------------+ - // + Default - // +-------------------------------------------------------------------+ - virtual bool isDefault() const = 0; - virtual bool isNotDefault() const = 0; - virtual void markDefault() = 0; - virtual void resetDefault() = 0; - - // +-------------------------------------------------------------------+ - // + Generation - // +-------------------------------------------------------------------+ - virtual S32 getCurrentGeneration() const = 0; - virtual S32 getFirstSuccessGeneration() const = 0; - virtual S32 getFirstRequiredGeneration() const = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual bool isDefault() const = 0; + virtual bool isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; }; class LLFolderViewModelInterface { public: - LLFolderViewModelInterface() - {} + LLFolderViewModelInterface() + {} - virtual ~LLFolderViewModelInterface() {} - virtual void requestSortAll() = 0; + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; - virtual bool contentsReady() = 0; - virtual bool isFolderComplete(class LLFolderViewFolder*) = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter& getFilter() = 0; - virtual const LLFolderViewFilter& getFilter() const = 0; - virtual std::string getStatusText(bool is_empty_folder = false) = 0; + virtual bool contentsReady() = 0; + virtual bool isFolderComplete(class LLFolderViewFolder*) = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter& getFilter() = 0; + virtual const LLFolderViewFilter& getFilter() const = 0; + virtual std::string getStatusText(bool is_empty_folder = false) = 0; - virtual bool startDrag(std::vector& items) = 0; + virtual bool startDrag(std::vector& items) = 0; }; // This is an abstract base class that users of the folderview classes @@ -135,96 +135,96 @@ public: class LLFolderViewModelItem : public LLRefCount { public: - LLFolderViewModelItem() - {} + LLFolderViewModelItem() + {} - virtual ~LLFolderViewModelItem() { } + virtual ~LLFolderViewModelItem() { } - virtual void update() {} //called when drawing - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const std::string& getSearchableName() const = 0; + virtual void update() {} //called when drawing + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + virtual const std::string& getSearchableName() const = 0; - virtual std::string getSearchableDescription() const = 0; - virtual std::string getSearchableCreatorName()const = 0; - virtual std::string getSearchableUUIDString() const = 0; + virtual std::string getSearchableDescription() const = 0; + virtual std::string getSearchableCreatorName()const = 0; + virtual std::string getSearchableUUIDString() const = 0; - virtual LLPointer getIcon() const = 0; - virtual LLPointer getIconOpen() const { return getIcon(); } - virtual LLPointer getIconOverlay() const { return NULL; } + virtual LLPointer getIcon() const = 0; + virtual LLPointer getIconOpen() const { return getIcon(); } + virtual LLPointer getIconOverlay() const { return NULL; } - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; - virtual void openItem( void ) = 0; - virtual void closeItem( void ) = 0; - virtual void selectItem(void) = 0; + 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; } - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - - virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder - virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(std::vector& batch) = 0; - - virtual bool isItemCopyable(bool can_copy_as_link = true) const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() = 0; - virtual bool isCutToClipboard() { return false; }; - - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - - virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - - virtual bool filter( LLFolderViewFilter& filter) = 0; - virtual bool passedFilter(S32 filter_generation = -1) = 0; - virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; - virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; - virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0; - virtual void dirtyFilter() = 0; - virtual void dirtyDescendantsFilter() = 0; - virtual bool hasFilterStringMatch() = 0; - virtual std::string::size_type getFilterStringOffset() = 0; - virtual std::string::size_type getFilterStringSize() = 0; - - virtual S32 getLastFilterGeneration() const = 0; - virtual S32 getMarkedDirtyGeneration() const = 0; - - virtual bool hasChildren() const = 0; - virtual void addChild(LLFolderViewModelItem* child) = 0; - virtual void removeChild(LLFolderViewModelItem* child) = 0; - virtual void clearChildren() = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; - - virtual void requestSort() = 0; - virtual S32 getSortVersion() = 0; - virtual void setSortVersion(S32 version) = 0; - virtual void setParent(LLFolderViewModelItem* parent) = 0; - virtual bool hasParent() = 0; + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(std::vector& batch) = 0; + + virtual bool isItemCopyable(bool can_copy_as_link = true) const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual BOOL cutToClipboard() = 0; + virtual bool isCutToClipboard() { return false; }; + + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + + virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + + virtual bool filter( LLFolderViewFilter& filter) = 0; + virtual bool passedFilter(S32 filter_generation = -1) = 0; + virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; + virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; + virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0; + virtual void dirtyFilter() = 0; + virtual void dirtyDescendantsFilter() = 0; + virtual bool hasFilterStringMatch() = 0; + virtual std::string::size_type getFilterStringOffset() = 0; + virtual std::string::size_type getFilterStringSize() = 0; + + virtual S32 getLastFilterGeneration() const = 0; + virtual S32 getMarkedDirtyGeneration() const = 0; + + virtual bool hasChildren() const = 0; + virtual void addChild(LLFolderViewModelItem* child) = 0; + virtual void removeChild(LLFolderViewModelItem* child) = 0; + virtual void clearChildren() = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; + virtual void setParent(LLFolderViewModelItem* parent) = 0; + virtual bool hasParent() = 0; protected: - friend class LLFolderViewItem; - virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; + friend class LLFolderViewItem; + virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; }; @@ -232,151 +232,151 @@ protected: class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: - LLFolderViewModelItemCommon(LLFolderViewModelInterface& root_view_model) - : mSortVersion(-1), - mPassedFilter(true), - mPassedFolderFilter(true), - mStringMatchOffsetFilter(std::string::npos), - mStringFilterSize(0), - mFolderViewItem(NULL), - mLastFilterGeneration(-1), - mLastFolderFilterGeneration(-1), - mMarkedDirtyGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mParent(NULL), - mRootViewModel(root_view_model) - { - mChildren.clear(); - } - - void requestSort() { mSortVersion = -1; } - S32 getSortVersion() { return mSortVersion; } - void setSortVersion(S32 version) { mSortVersion = version;} - - S32 getLastFilterGeneration() const { return mLastFilterGeneration; } - S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } - S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } - void dirtyFilter() - { - if(mMarkedDirtyGeneration < 0) - { - mMarkedDirtyGeneration = mLastFilterGeneration; - } - mLastFilterGeneration = -1; - mLastFolderFilterGeneration = -1; - - // bubble up dirty flag all the way to root - if (mParent) - { - mParent->dirtyFilter(); - } - } - void dirtyDescendantsFilter() - { - mMostFilteredDescendantGeneration = -1; - if (mParent) - { - mParent->dirtyDescendantsFilter(); - } - } - bool hasFilterStringMatch(); - std::string::size_type getFilterStringOffset(); - std::string::size_type getFilterStringSize(); - - typedef std::list child_list_t; - - virtual void addChild(LLFolderViewModelItem* child) - { - mChildren.push_back(child); - child->setParent(this); - dirtyFilter(); - requestSort(); - } - virtual void removeChild(LLFolderViewModelItem* child) - { - mChildren.remove(child); - child->setParent(NULL); - dirtyDescendantsFilter(); - dirtyFilter(); - } - - virtual void clearChildren() - { - // We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest - std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); }); - mChildren.clear(); - dirtyDescendantsFilter(); - dirtyFilter(); - } - - child_list_t::const_iterator getChildrenBegin() const { return mChildren.begin(); } - child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } - child_list_t::size_type getChildrenCount() const { return mChildren.size(); } - - void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) - { - mPassedFilter = passed; - mLastFilterGeneration = filter_generation; - mStringMatchOffsetFilter = string_offset; - mStringFilterSize = string_size; - mMarkedDirtyGeneration = -1; - } - - void setPassedFolderFilter(bool passed, S32 filter_generation) - { - mPassedFolderFilter = passed; - mLastFolderFilterGeneration = filter_generation; - } - - virtual bool potentiallyVisible() - { - return passedFilter() // we've passed the filter - || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet - || descendantsPassedFilter(); - } - - virtual bool passedFilter(S32 filter_generation = -1) - { - if (filter_generation < 0) + LLFolderViewModelItemCommon(LLFolderViewModelInterface& root_view_model) + : mSortVersion(-1), + mPassedFilter(true), + mPassedFolderFilter(true), + mStringMatchOffsetFilter(std::string::npos), + mStringFilterSize(0), + mFolderViewItem(NULL), + mLastFilterGeneration(-1), + mLastFolderFilterGeneration(-1), + mMarkedDirtyGeneration(-1), + mMostFilteredDescendantGeneration(-1), + mParent(NULL), + mRootViewModel(root_view_model) + { + mChildren.clear(); + } + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = version;} + + S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } + S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } + void dirtyFilter() + { + if(mMarkedDirtyGeneration < 0) { - filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); + mMarkedDirtyGeneration = mLastFilterGeneration; } - bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation); - bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation); - return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation)); - } - - virtual bool descendantsPassedFilter(S32 filter_generation = -1) - { - if (filter_generation < 0) + mLastFilterGeneration = -1; + mLastFolderFilterGeneration = -1; + + // bubble up dirty flag all the way to root + if (mParent) + { + mParent->dirtyFilter(); + } + } + void dirtyDescendantsFilter() + { + mMostFilteredDescendantGeneration = -1; + if (mParent) + { + mParent->dirtyDescendantsFilter(); + } + } + bool hasFilterStringMatch(); + std::string::size_type getFilterStringOffset(); + std::string::size_type getFilterStringSize(); + + typedef std::list child_list_t; + + virtual void addChild(LLFolderViewModelItem* child) + { + mChildren.push_back(child); + child->setParent(this); + dirtyFilter(); + requestSort(); + } + virtual void removeChild(LLFolderViewModelItem* child) + { + mChildren.remove(child); + child->setParent(NULL); + dirtyDescendantsFilter(); + dirtyFilter(); + } + + virtual void clearChildren() + { + // We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest + std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); }); + mChildren.clear(); + dirtyDescendantsFilter(); + dirtyFilter(); + } + + child_list_t::const_iterator getChildrenBegin() const { return mChildren.begin(); } + child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } + child_list_t::size_type getChildrenCount() const { return mChildren.size(); } + + void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) + { + mPassedFilter = passed; + mLastFilterGeneration = filter_generation; + mStringMatchOffsetFilter = string_offset; + mStringFilterSize = string_size; + mMarkedDirtyGeneration = -1; + } + + void setPassedFolderFilter(bool passed, S32 filter_generation) + { + mPassedFolderFilter = passed; + mLastFolderFilterGeneration = filter_generation; + } + + virtual bool potentiallyVisible() + { + return passedFilter() // we've passed the filter + || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet + || descendantsPassedFilter(); + } + + virtual bool passedFilter(S32 filter_generation = -1) + { + if (filter_generation < 0) { filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); } - return mMostFilteredDescendantGeneration >= filter_generation; - } + bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation); + bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation); + return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation)); + } + + virtual bool descendantsPassedFilter(S32 filter_generation = -1) + { + if (filter_generation < 0) + { + filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); + } + return mMostFilteredDescendantGeneration >= filter_generation; + } protected: - virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - virtual bool hasParent() { return mParent != NULL; } - - S32 mSortVersion; - bool mPassedFilter; - bool mPassedFolderFilter; - std::string::size_type mStringMatchOffsetFilter; - std::string::size_type mStringFilterSize; - - S32 mLastFilterGeneration, - mLastFolderFilterGeneration, - mMostFilteredDescendantGeneration, - mMarkedDirtyGeneration; - - child_list_t mChildren; - LLFolderViewModelItem* mParent; - LLFolderViewModelInterface& mRootViewModel; - - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} - LLFolderViewItem* mFolderViewItem; + virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + virtual bool hasParent() { return mParent != NULL; } + + S32 mSortVersion; + bool mPassedFilter; + bool mPassedFolderFilter; + std::string::size_type mStringMatchOffsetFilter; + std::string::size_type mStringFilterSize; + + S32 mLastFilterGeneration, + mLastFolderFilterGeneration, + mMostFilteredDescendantGeneration, + mMarkedDirtyGeneration; + + child_list_t mChildren; + LLFolderViewModelItem* mParent; + LLFolderViewModelInterface& mRootViewModel; + + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; }; @@ -384,26 +384,26 @@ protected: class LLFolderViewModelCommon : public LLFolderViewModelInterface { public: - LLFolderViewModelCommon() - : mTargetSortVersion(0), - mFolderView(NULL) - {} + LLFolderViewModelCommon() + : mTargetSortVersion(0), + mFolderView(NULL) + {} - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - virtual std::string getStatusText(bool is_empty_folder = false); - virtual void filter(); + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + virtual std::string getStatusText(bool is_empty_folder = false); + virtual void filter(); - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} protected: - bool needsSort(class LLFolderViewModelItem* item); + bool needsSort(class LLFolderViewModelItem* item); - S32 mTargetSortVersion; - LLFolderView* mFolderView; + S32 mTargetSortVersion; + LLFolderView* mFolderView; }; @@ -411,64 +411,64 @@ template (a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - const SortType& mSorter; - }; - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + LLFolderViewModel(SortType* sorter, FilterType* filter) + : mSorter(sorter), + mFilter(filter) + {} + + virtual ~LLFolderViewModel() {} + + virtual SortType& getSorter() { return *mSorter; } + virtual const SortType& getSorter() const { return *mSorter; } + 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.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. + virtual bool contentsReady() { return true; } + virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; } + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } protected: - std::unique_ptr mSorter; - std::unique_ptr mFilter; + std::unique_ptr mSorter; + std::unique_ptr mFilter; }; #endif // LLFOLDERVIEWMODEL_H diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index e43974bc52..da5570d922 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,93 +47,93 @@ * across restarts of the viewer; we couldn't store functors that way. * Using this registry, systems that require a functor to be maintained * long term can register it at system startup, and then pass in the - * functor by name. + * functor by name. */ template class LLFunctorRegistry : public LLSingleton > { - LLSINGLETON(LLFunctorRegistry); - LOG_CLASS(LLFunctorRegistry); + LLSINGLETON(LLFunctorRegistry); + LOG_CLASS(LLFunctorRegistry); public: - typedef FUNCTOR_TYPE ResponseFunctor; - typedef typename std::map FunctorMap; - - bool registerFunctor(const std::string& name, ResponseFunctor f) - { - bool retval = true; - if (mMap.count(name) == 0) - { - mMap[name] = f; - } - else - { - LL_ERRS() << "attempt to store duplicate name '" << name << "' in LLFunctorRegistry. NOT ADDED." << LL_ENDL; - retval = false; - } - - return retval; - } - - bool unregisterFunctor(const std::string& name) - { - if (mMap.count(name) == 0) - { - LL_WARNS() << "trying to remove '" << name << "' from LLFunctorRegistry but it's not there." << LL_ENDL; - return false; - } - mMap.erase(name); - return true; - } - - FUNCTOR_TYPE getFunctor(const std::string& name) - { - if (mMap.count(name) != 0) - { - return mMap[name]; - } - else - { - LL_DEBUGS() << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << LL_ENDL; - return mMap[LOGFUNCTOR]; - } - } - - const std::string LOGFUNCTOR; - const std::string DONOTHING; - + typedef FUNCTOR_TYPE ResponseFunctor; + typedef typename std::map FunctorMap; + + bool registerFunctor(const std::string& name, ResponseFunctor f) + { + bool retval = true; + if (mMap.count(name) == 0) + { + mMap[name] = f; + } + else + { + LL_ERRS() << "attempt to store duplicate name '" << name << "' in LLFunctorRegistry. NOT ADDED." << LL_ENDL; + retval = false; + } + + return retval; + } + + bool unregisterFunctor(const std::string& name) + { + if (mMap.count(name) == 0) + { + LL_WARNS() << "trying to remove '" << name << "' from LLFunctorRegistry but it's not there." << LL_ENDL; + return false; + } + mMap.erase(name); + return true; + } + + FUNCTOR_TYPE getFunctor(const std::string& name) + { + if (mMap.count(name) != 0) + { + return mMap[name]; + } + else + { + LL_DEBUGS() << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << LL_ENDL; + return mMap[LOGFUNCTOR]; + } + } + + const std::string LOGFUNCTOR; + const std::string DONOTHING; + private: - static void log_functor(const LLSD& notification, const LLSD& payload) - { - LL_DEBUGS() << "log_functor called with payload: " << payload << LL_ENDL; - } + static void log_functor(const LLSD& notification, const LLSD& payload) + { + LL_DEBUGS() << "log_functor called with payload: " << payload << LL_ENDL; + } - static void do_nothing(const LLSD& notification, const LLSD& payload) - { - // what the sign sez - } + static void do_nothing(const LLSD& notification, const LLSD& payload) + { + // what the sign sez + } - FunctorMap mMap; + FunctorMap mMap; }; template LLFunctorRegistry::LLFunctorRegistry() : - LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") + LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") { - mMap[LOGFUNCTOR] = log_functor; - mMap[DONOTHING] = do_nothing; + mMap[LOGFUNCTOR] = log_functor; + mMap[DONOTHING] = do_nothing; } template class LLFunctorRegistration { public: - LLFunctorRegistration(const std::string& name, FUNCTOR_TYPE functor) - { - LLFunctorRegistry::instance().registerFunctor(name, functor); - } + LLFunctorRegistration(const std::string& name, FUNCTOR_TYPE functor) + { + LLFunctorRegistry::instance().registerFunctor(name, functor); + } }; #endif//LL_LLFUNCTORREGISTRY_H diff --git a/indra/llui/llhelp.h b/indra/llui/llhelp.h index 1726347a78..829a080655 100644 --- a/indra/llui/llhelp.h +++ b/indra/llui/llhelp.h @@ -1,4 +1,4 @@ -/** +/** * @file llhelp.h * @brief Abstract interface to the Help system * @author Tofu Linden @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,14 +31,14 @@ class LLHelp { public: - virtual void showTopic(const std::string &topic) = 0; - virtual std::string getURL(const std::string &topic) = 0; - // return default (fallback) topic name suitable for showTopic() - virtual std::string defaultTopic() = 0; - // return topic to use before the user logs in - virtual std::string preLoginTopic() = 0; - // return topic to use for the top-level help, invoked by F1 - virtual std::string f1HelpTopic() = 0; + virtual void showTopic(const std::string &topic) = 0; + virtual std::string getURL(const std::string &topic) = 0; + // return default (fallback) topic name suitable for showTopic() + virtual std::string defaultTopic() = 0; + // return topic to use before the user logs in + virtual std::string preLoginTopic() = 0; + // return topic to use for the top-level help, invoked by F1 + virtual std::string f1HelpTopic() = 0; }; #endif // headerguard diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 2791377a5e..38c869cd59 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lliconctrl.cpp * @brief LLIconCtrl base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,7 +28,7 @@ #include "lliconctrl.h" -// Linden library includes +// Linden library includes // Project includes #include "llcontrol.h" @@ -42,48 +42,48 @@ static LLDefaultChildRegistry::Register r("icon"); LLIconCtrl::Params::Params() -: image("image_name"), - color("color"), - use_draw_context_alpha("use_draw_context_alpha", true), +: 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) + scale_image("scale_image"), + min_width("min_width", 0), + min_height("min_height", 0) {} LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) -: LLUICtrl(p), - mColor(p.color()), - mImagep(p.image), - mUseDrawContextAlpha(p.use_draw_context_alpha), +: LLUICtrl(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), - mMaxWidth(0), - mMaxHeight(0) + mPriority(0), + mMinWidth(p.min_width), + mMinHeight(p.min_height), + mMaxWidth(0), + mMaxHeight(0) { - if (mImagep.notNull()) - { - LLUICtrl::setValue(mImagep->getName()); - } + if (mImagep.notNull()) + { + LLUICtrl::setValue(mImagep->getName()); + } } LLIconCtrl::~LLIconCtrl() { - mImagep = NULL; + mImagep = NULL; } void LLIconCtrl::draw() { - if( mImagep.notNull() ) - { - const F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - mImagep->draw(getLocalRect(), mColor.get() % alpha ); - } + if( mImagep.notNull() ) + { + const F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); + mImagep->draw(getLocalRect(), mColor.get() % alpha ); + } - LLUICtrl::draw(); + LLUICtrl::draw(); } BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask) @@ -98,18 +98,18 @@ BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask) void LLIconCtrl::onVisibilityChange(BOOL new_visibility) { - LLUICtrl::onVisibilityChange(new_visibility); - if (mPriority == LLGLTexture::BOOST_ICON) - { - if (new_visibility) - { - loadImage(getValue(), mPriority); - } - else - { - mImagep = nullptr; - } - } + LLUICtrl::onVisibilityChange(new_visibility); + if (mPriority == LLGLTexture::BOOST_ICON) + { + if (new_visibility) + { + loadImage(getValue(), mPriority); + } + else + { + mImagep = nullptr; + } + } } // virtual @@ -121,35 +121,35 @@ void LLIconCtrl::setValue(const LLSD& value) void LLIconCtrl::setValue(const LLSD& value, S32 priority) { - LLSD tvalue(value); - if (value.isString() && LLUUID::validate(value.asString())) - { - //RN: support UUIDs masquerading as strings - tvalue = LLSD(LLUUID(value.asString())); - } - LLUICtrl::setValue(tvalue); - - loadImage(tvalue, priority); + LLSD tvalue(value); + if (value.isString() && LLUUID::validate(value.asString())) + { + //RN: support UUIDs masquerading as strings + tvalue = LLSD(LLUUID(value.asString())); + } + LLUICtrl::setValue(tvalue); + + loadImage(tvalue, priority); } void LLIconCtrl::loadImage(const LLSD& tvalue, S32 priority) { - if(mPriority == LLGLTexture::BOOST_ICON && !getVisible()) return; + if(mPriority == LLGLTexture::BOOST_ICON && !getVisible()) return; - if (tvalue.isUUID()) - { + if (tvalue.isUUID()) + { mImagep = LLUI::getUIImageByID(tvalue.asUUID(), priority); - } - else - { + } + else + { mImagep = LLUI::getUIImage(tvalue.asString(), priority); - } + } - if(mImagep.notNull() - && mImagep->getImage().notNull() - && mMinWidth - && mMinHeight) - { + if(mImagep.notNull() + && mImagep->getImage().notNull() + && mMinWidth + && mMinHeight) + { S32 desired_draw_width = llmax(mMinWidth, mImagep->getWidth()); S32 desired_draw_height = llmax(mMinHeight, mImagep->getHeight()); if (mMaxWidth && mMaxHeight) @@ -159,15 +159,15 @@ void LLIconCtrl::loadImage(const LLSD& tvalue, S32 priority) } mImagep->getImage()->setKnownDrawSize(desired_draw_width, desired_draw_height); - } + } } std::string LLIconCtrl::getImageName() const { - if (getValue().isString()) - return getValue().asString(); - else - return std::string(); + if (getValue().isString()) + return getValue().asString(); + else + return std::string(); } diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index e983d63a01..240fe3a74c 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -1,25 +1,25 @@ -/** +/** * @file lliconctrl.h * @brief LLIconCtrl base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,62 +46,62 @@ class LLIconCtrl : public LLUICtrl { public: - struct Params : public LLInitParam::Block - { - Optional image; - Optional color; - Optional use_draw_context_alpha, + struct Params : public LLInitParam::Block + { + Optional image; + Optional color; + Optional use_draw_context_alpha, interactable; - Optional min_width, - min_height; - Ignored scale_image; + Optional min_width, + min_height; + Ignored scale_image; - Params(); - }; + Params(); + }; protected: - LLIconCtrl(const Params&); - friend class LLUICtrlFactory; + LLIconCtrl(const Params&); + friend class LLUICtrlFactory; - void setValue(const LLSD& value, S32 priority); + void setValue(const LLSD& value, S32 priority); public: - virtual ~LLIconCtrl(); + virtual ~LLIconCtrl(); - // llview overrides - virtual void draw(); + // llview overrides + virtual void draw(); // llview overrides virtual BOOL handleHover(S32 x, S32 y, MASK mask); - // lluictrl overrides - void onVisibilityChange(BOOL new_visibility); - virtual void setValue(const LLSD& value ); + // lluictrl overrides + void onVisibilityChange(BOOL new_visibility); + virtual void setValue(const LLSD& value ); + + std::string getImageName() const; - std::string getImageName() const; + void setColor(const LLColor4& color) { mColor = color; } + void setImage(LLPointer image) { mImagep = image; } + const LLPointer getImage() { return mImagep; } - void setColor(const LLColor4& color) { mColor = color; } - void setImage(LLPointer image) { mImagep = image; } - const LLPointer getImage() { return mImagep; } - protected: - S32 mPriority; + S32 mPriority; - //the output size of the icon image if set. - S32 mMinWidth, - mMinHeight, - mMaxWidth, - mMaxHeight; + //the output size of the icon image if set. + S32 mMinWidth, + mMinHeight, + mMaxWidth, + mMaxHeight; - // If set to true (default), use the draw context transparency. - // If false, will use transparency returned by getCurrentTransparency(). See STORM-698. - bool mUseDrawContextAlpha; + // 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: - void loadImage(const LLSD& value, S32 priority); + void loadImage(const LLSD& value, S32 priority); - LLUIColor mColor; - LLPointer mImagep; + LLUIColor mColor; + LLPointer mImagep; }; #endif diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 341ddb83f3..1ac1e41727 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -36,443 +36,443 @@ inline bool LLKeywordToken::isHead(const llwchar* s) const { - // strncmp is much faster than string compare - bool res = true; - const llwchar* t = mToken.c_str(); - S32 len = mToken.size(); - for (S32 i=0; isecond.get("type").asString() + " " + argsIt->first; - if (argsCount-- > 1) - { - argString += ", "; - } - } - } - else - { - LL_WARNS("SyntaxLSL") << "Argument array comtains a non-map element!" << LL_ENDL; - } - } - } - else if (!arguments.isUndefined()) - { - LL_WARNS("SyntaxLSL") << "Not an array! Invalid arguments LLSD passed to function." << arguments << LL_ENDL; - } - return argString; + std::string argString = ""; + + if (arguments.isArray()) + { + U32 argsCount = arguments.size(); + LLSD::array_iterator arrayIt = arguments.beginArray(); + for ( ; arrayIt != arguments.endArray(); ++arrayIt) + { + LLSD& args = (*arrayIt); + if (args.isMap()) + { + LLSD::map_iterator argsIt = args.beginMap(); + for ( ; argsIt != args.endMap(); ++argsIt) + { + argString += argsIt->second.get("type").asString() + " " + argsIt->first; + if (argsCount-- > 1) + { + argString += ", "; + } + } + } + else + { + LL_WARNS("SyntaxLSL") << "Argument array comtains a non-map element!" << LL_ENDL; + } + } + } + else if (!arguments.isUndefined()) + { + LL_WARNS("SyntaxLSL") << "Not an array! Invalid arguments LLSD passed to function." << arguments << LL_ENDL; + } + return argString; } std::string LLKeywords::getAttribute(const std::string& key) { - attribute_iterator_t it = mAttributes.find(key); - return (it != mAttributes.end()) ? it->second : ""; + attribute_iterator_t it = mAttributes.find(key); + return (it != mAttributes.end()) ? it->second : ""; } LLColor4 LLKeywords::getColorGroup(const std::string& key_in) { - std::string color_group = "ScriptText"; - if (key_in == "functions") - { - color_group = "SyntaxLslFunction"; - } - else if (key_in == "controls") - { - color_group = "SyntaxLslControlFlow"; - } - else if (key_in == "events") - { - color_group = "SyntaxLslEvent"; - } - else if (key_in == "types") - { - color_group = "SyntaxLslDataType"; - } - else if (key_in == "misc-flow-label") - { - color_group = "SyntaxLslControlFlow"; - } - else if (key_in =="deprecated") - { - color_group = "SyntaxLslDeprecated"; - } - else if (key_in =="god-mode") - { - color_group = "SyntaxLslGodMode"; - } - else if (key_in == "constants" - || key_in == "constants-integer" - || key_in == "constants-float" - || key_in == "constants-string" - || key_in == "constants-key" - || key_in == "constants-rotation" - || key_in == "constants-vector") - { - color_group = "SyntaxLslConstant"; - } - else - { - LL_WARNS("SyntaxLSL") << "Color key '" << key_in << "' not recognized." << LL_ENDL; - } - - return LLUIColorTable::instance().getColor(color_group); + std::string color_group = "ScriptText"; + if (key_in == "functions") + { + color_group = "SyntaxLslFunction"; + } + else if (key_in == "controls") + { + color_group = "SyntaxLslControlFlow"; + } + else if (key_in == "events") + { + color_group = "SyntaxLslEvent"; + } + else if (key_in == "types") + { + color_group = "SyntaxLslDataType"; + } + else if (key_in == "misc-flow-label") + { + color_group = "SyntaxLslControlFlow"; + } + else if (key_in =="deprecated") + { + color_group = "SyntaxLslDeprecated"; + } + else if (key_in =="god-mode") + { + color_group = "SyntaxLslGodMode"; + } + else if (key_in == "constants" + || key_in == "constants-integer" + || key_in == "constants-float" + || key_in == "constants-string" + || key_in == "constants-key" + || key_in == "constants-rotation" + || key_in == "constants-vector") + { + color_group = "SyntaxLslConstant"; + } + else + { + LL_WARNS("SyntaxLSL") << "Color key '" << key_in << "' not recognized." << LL_ENDL; + } + + return LLUIColorTable::instance().getColor(color_group); } void LLKeywords::initialize(LLSD SyntaxXML) { - mSyntax = SyntaxXML; - mLoaded = true; + mSyntax = SyntaxXML; + mLoaded = true; } void LLKeywords::processTokens() { - if (!mLoaded) - { - return; - } - - // Add 'standard' stuff: Quotes, Comments, Strings, Labels, etc. before processing the LLSD - std::string delimiter; - addToken(LLKeywordToken::TT_LABEL, "@", getColorGroup("misc-flow-label"), "Label\nTarget for jump statement", delimiter ); - addToken(LLKeywordToken::TT_ONE_SIDED_DELIMITER, "//", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (single-line)\nNon-functional commentary or disabled code", delimiter ); - addToken(LLKeywordToken::TT_TWO_SIDED_DELIMITER, "/*", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (multi-line)\nNon-functional commentary or disabled code", "*/" ); - addToken(LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS, "\"", LLUIColorTable::instance().getColor("SyntaxLslStringLiteral"), "String literal", "\"" ); - - LLSD::map_iterator itr = mSyntax.beginMap(); - for ( ; itr != mSyntax.endMap(); ++itr) - { - if (itr->first == "llsd-lsl-syntax-version") - { - // Skip over version key. - } - else - { - if (itr->second.isMap()) - { - processTokensGroup(itr->second, itr->first); - } - else - { - LL_WARNS("LSL-Tokens-Processing") << "Map for " + itr->first + " entries is missing! Ignoring." << LL_ENDL; - } - } - } - LL_INFOS("SyntaxLSL") << "Finished processing tokens." << LL_ENDL; + if (!mLoaded) + { + return; + } + + // Add 'standard' stuff: Quotes, Comments, Strings, Labels, etc. before processing the LLSD + std::string delimiter; + addToken(LLKeywordToken::TT_LABEL, "@", getColorGroup("misc-flow-label"), "Label\nTarget for jump statement", delimiter ); + addToken(LLKeywordToken::TT_ONE_SIDED_DELIMITER, "//", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (single-line)\nNon-functional commentary or disabled code", delimiter ); + addToken(LLKeywordToken::TT_TWO_SIDED_DELIMITER, "/*", LLUIColorTable::instance().getColor("SyntaxLslComment"), "Comment (multi-line)\nNon-functional commentary or disabled code", "*/" ); + addToken(LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS, "\"", LLUIColorTable::instance().getColor("SyntaxLslStringLiteral"), "String literal", "\"" ); + + LLSD::map_iterator itr = mSyntax.beginMap(); + for ( ; itr != mSyntax.endMap(); ++itr) + { + if (itr->first == "llsd-lsl-syntax-version") + { + // Skip over version key. + } + else + { + if (itr->second.isMap()) + { + processTokensGroup(itr->second, itr->first); + } + else + { + LL_WARNS("LSL-Tokens-Processing") << "Map for " + itr->first + " entries is missing! Ignoring." << LL_ENDL; + } + } + } + LL_INFOS("SyntaxLSL") << "Finished processing tokens." << LL_ENDL; } void LLKeywords::processTokensGroup(const LLSD& tokens, const std::string& group) { - LLColor4 color; - LLColor4 color_group; - LLColor4 color_deprecated = getColorGroup("deprecated"); - LLColor4 color_god_mode = getColorGroup("god-mode"); - - LLKeywordToken::ETokenType token_type = LLKeywordToken::TT_UNKNOWN; - // If a new token type is added here, it must also be added to the 'addToken' method - if (group == "constants") - { - token_type = LLKeywordToken::TT_CONSTANT; - } - else if (group == "controls") - { - token_type = LLKeywordToken::TT_CONTROL; - } - else if (group == "events") - { - token_type = LLKeywordToken::TT_EVENT; - } - else if (group == "functions") - { - token_type = LLKeywordToken::TT_FUNCTION; - } - else if (group == "label") - { - token_type = LLKeywordToken::TT_LABEL; - } - else if (group == "types") - { - token_type = LLKeywordToken::TT_TYPE; - } - - color_group = getColorGroup(group); - LL_DEBUGS("SyntaxLSL") << "Group: '" << group << "', using color: '" << color_group << "'" << LL_ENDL; - - if (tokens.isMap()) - { - LLSD::map_const_iterator outer_itr = tokens.beginMap(); - for ( ; outer_itr != tokens.endMap(); ++outer_itr ) - { - if (outer_itr->second.isMap()) - { - mAttributes.clear(); - LLSD arguments = LLSD(); - LLSD::map_const_iterator inner_itr = outer_itr->second.beginMap(); - for ( ; inner_itr != outer_itr->second.endMap(); ++inner_itr ) - { - if (inner_itr->first == "arguments") - { - if (inner_itr->second.isArray()) - { - arguments = inner_itr->second; - } - } - else if (!inner_itr->second.isMap() && !inner_itr->second.isArray()) - { - mAttributes[inner_itr->first] = inner_itr->second.asString(); - } - else - { - LL_WARNS("SyntaxLSL") << "Not a valid attribute: " << inner_itr->first << LL_ENDL; - } - } - - std::string tooltip = ""; - switch (token_type) - { - case LLKeywordToken::TT_CONSTANT: - if (getAttribute("type").length() > 0) - { - color_group = getColorGroup(group + "-" + getAttribute("type")); - } - else - { - color_group = getColorGroup(group); - } - tooltip = "Type: " + getAttribute("type") + ", Value: " + getAttribute("value"); - break; - case LLKeywordToken::TT_EVENT: - tooltip = outer_itr->first + "(" + getArguments(arguments) + ")"; - break; - case LLKeywordToken::TT_FUNCTION: - tooltip = getAttribute("return") + " " + outer_itr->first + "(" + getArguments(arguments) + ");"; - tooltip.append("\nEnergy: "); - tooltip.append(getAttribute("energy").empty() ? "0.0" : getAttribute("energy")); - if (!getAttribute("sleep").empty()) - { - tooltip += ", Sleep: " + getAttribute("sleep"); - } - default: - break; - } - - if (!getAttribute("tooltip").empty()) - { - if (!tooltip.empty()) - { - tooltip.append("\n"); - } - tooltip.append(getAttribute("tooltip")); - } - - color = getAttribute("deprecated") == "true" ? color_deprecated : color_group; - - if (getAttribute("god-mode") == "true") - { - color = color_god_mode; - } - - addToken(token_type, outer_itr->first, color, tooltip); - } - } - } - else if (tokens.isArray()) // Currently nothing should need this, but it's here for completeness - { - LL_INFOS("SyntaxLSL") << "Curious, shouldn't be an array here; adding all using color " << color << LL_ENDL; - for (S32 count = 0; count < tokens.size(); ++count) - { - addToken(token_type, tokens[count], color, ""); - } - } - else - { - LL_WARNS("SyntaxLSL") << "Invalid map/array passed: '" << tokens << "'" << LL_ENDL; - } + LLColor4 color; + LLColor4 color_group; + LLColor4 color_deprecated = getColorGroup("deprecated"); + LLColor4 color_god_mode = getColorGroup("god-mode"); + + LLKeywordToken::ETokenType token_type = LLKeywordToken::TT_UNKNOWN; + // If a new token type is added here, it must also be added to the 'addToken' method + if (group == "constants") + { + token_type = LLKeywordToken::TT_CONSTANT; + } + else if (group == "controls") + { + token_type = LLKeywordToken::TT_CONTROL; + } + else if (group == "events") + { + token_type = LLKeywordToken::TT_EVENT; + } + else if (group == "functions") + { + token_type = LLKeywordToken::TT_FUNCTION; + } + else if (group == "label") + { + token_type = LLKeywordToken::TT_LABEL; + } + else if (group == "types") + { + token_type = LLKeywordToken::TT_TYPE; + } + + color_group = getColorGroup(group); + LL_DEBUGS("SyntaxLSL") << "Group: '" << group << "', using color: '" << color_group << "'" << LL_ENDL; + + if (tokens.isMap()) + { + LLSD::map_const_iterator outer_itr = tokens.beginMap(); + for ( ; outer_itr != tokens.endMap(); ++outer_itr ) + { + if (outer_itr->second.isMap()) + { + mAttributes.clear(); + LLSD arguments = LLSD(); + LLSD::map_const_iterator inner_itr = outer_itr->second.beginMap(); + for ( ; inner_itr != outer_itr->second.endMap(); ++inner_itr ) + { + if (inner_itr->first == "arguments") + { + if (inner_itr->second.isArray()) + { + arguments = inner_itr->second; + } + } + else if (!inner_itr->second.isMap() && !inner_itr->second.isArray()) + { + mAttributes[inner_itr->first] = inner_itr->second.asString(); + } + else + { + LL_WARNS("SyntaxLSL") << "Not a valid attribute: " << inner_itr->first << LL_ENDL; + } + } + + std::string tooltip = ""; + switch (token_type) + { + case LLKeywordToken::TT_CONSTANT: + if (getAttribute("type").length() > 0) + { + color_group = getColorGroup(group + "-" + getAttribute("type")); + } + else + { + color_group = getColorGroup(group); + } + tooltip = "Type: " + getAttribute("type") + ", Value: " + getAttribute("value"); + break; + case LLKeywordToken::TT_EVENT: + tooltip = outer_itr->first + "(" + getArguments(arguments) + ")"; + break; + case LLKeywordToken::TT_FUNCTION: + tooltip = getAttribute("return") + " " + outer_itr->first + "(" + getArguments(arguments) + ");"; + tooltip.append("\nEnergy: "); + tooltip.append(getAttribute("energy").empty() ? "0.0" : getAttribute("energy")); + if (!getAttribute("sleep").empty()) + { + tooltip += ", Sleep: " + getAttribute("sleep"); + } + default: + break; + } + + if (!getAttribute("tooltip").empty()) + { + if (!tooltip.empty()) + { + tooltip.append("\n"); + } + tooltip.append(getAttribute("tooltip")); + } + + color = getAttribute("deprecated") == "true" ? color_deprecated : color_group; + + if (getAttribute("god-mode") == "true") + { + color = color_god_mode; + } + + addToken(token_type, outer_itr->first, color, tooltip); + } + } + } + else if (tokens.isArray()) // Currently nothing should need this, but it's here for completeness + { + LL_INFOS("SyntaxLSL") << "Curious, shouldn't be an array here; adding all using color " << color << LL_ENDL; + for (S32 count = 0; count < tokens.size(); ++count) + { + addToken(token_type, tokens[count], color, ""); + } + } + else + { + LL_WARNS("SyntaxLSL") << "Invalid map/array passed: '" << tokens << "'" << LL_ENDL; + } } LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other) { - if(other.mOwner) - { - copyData(other.mData, other.mLength); - } - else - { - mOwner = false; - mLength = other.mLength; - mData = other.mData; - } + if(other.mOwner) + { + copyData(other.mData, other.mLength); + } + else + { + mOwner = false; + mLength = other.mLength; + mData = other.mData; + } } LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str) { - copyData(str.data(), str.size()); + copyData(str.data(), str.size()); } LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length) -: mData(start) -, mLength(length) -, mOwner(false) +: mData(start) +, mLength(length) +, mOwner(false) { } LLKeywords::WStringMapIndex::~WStringMapIndex() { - if (mOwner) - { - delete[] mData; - } + if (mOwner) + { + delete[] mData; + } } void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length) { - llwchar *data = new llwchar[length]; - memcpy((void*)data, (const void*)start, length * sizeof(llwchar)); + llwchar *data = new llwchar[length]; + memcpy((void*)data, (const void*)start, length * sizeof(llwchar)); - mOwner = true; - mLength = length; - mData = data; + mOwner = true; + mLength = length; + mData = data; } bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const { - // NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not. - // The comparison only needs to strictly order all possible strings, and be stable. - - bool result = false; - const llwchar* self_iter = mData; - const llwchar* self_end = mData + mLength; - const llwchar* other_iter = other.mData; - const llwchar* other_end = other.mData + other.mLength; - - while(true) - { - if(other_iter >= other_end) - { - // We've hit the end of other. - // This covers two cases: other being shorter than self, or the strings being equal. - // In either case, we want to return false. - result = false; - break; - } - else if(self_iter >= self_end) - { - // self is shorter than other. - result = true; - break; - } - else if(*self_iter != *other_iter) - { - // The current character differs. The strings are not equal. - result = *self_iter < *other_iter; - break; - } - - self_iter++; - other_iter++; - } - - return result; + // NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not. + // The comparison only needs to strictly order all possible strings, and be stable. + + bool result = false; + const llwchar* self_iter = mData; + const llwchar* self_end = mData + mLength; + const llwchar* other_iter = other.mData; + const llwchar* other_end = other.mData + other.mLength; + + while(true) + { + if(other_iter >= other_end) + { + // We've hit the end of other. + // This covers two cases: other being shorter than self, or the strings being equal. + // In either case, we want to return false. + result = false; + break; + } + else if(self_iter >= self_end) + { + // self is shorter than other. + result = true; + break; + } + else if(*self_iter != *other_iter) + { + // The current character differs. The strings are not equal. + result = *self_iter < *other_iter; + break; + } + + self_iter++; + other_iter++; + } + + return result; } LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring"); @@ -481,333 +481,333 @@ LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring"); // create a list of color segments. void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, LLTextEditor& editor, LLStyleConstSP style) { - LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); - seg_list->clear(); - - if( wtext.empty() ) - { - return; - } - - S32 text_len = wtext.size() + 1; - - seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) ); - - const llwchar* base = wtext.c_str(); - const llwchar* cur = base; - while( *cur ) - { - if( *cur == '\n' || cur == base ) - { - if( *cur == '\n' ) - { - LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base); - text_segment->setToken( 0 ); - insertSegment( *seg_list, text_segment, text_len, style, editor); - cur++; - if( !*cur || *cur == '\n' ) - { - continue; - } - } - - // Skip white space - while( *cur && iswspace(*cur) && (*cur != '\n') ) - { - cur++; - } - if( !*cur || *cur == '\n' ) - { - continue; - } - - // cur is now at the first non-whitespace character of a new line - - // Line start tokens - { - BOOL line_done = FALSE; - for (token_list_t::iterator iter = mLineTokenList.begin(); - iter != mLineTokenList.end(); ++iter) - { - LLKeywordToken* cur_token = *iter; - if( cur_token->isHead( cur ) ) - { - S32 seg_start = cur - base; - while( *cur && *cur != '\n' ) - { - // skip the rest of the line - cur++; - } - S32 seg_end = cur - base; - - //create segments from seg_start to seg_end - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); - line_done = TRUE; // to break out of second loop. - break; - } - } - - if( line_done ) - { - continue; - } - } - } - - // Skip white space - while( *cur && iswspace(*cur) && (*cur != '\n') ) - { - cur++; - } - - while( *cur && *cur != '\n' ) - { - // Check against delimiters - { - S32 seg_start = 0; - LLKeywordToken* cur_delimiter = NULL; - for (token_list_t::iterator iter = mDelimiterTokenList.begin(); - iter != mDelimiterTokenList.end(); ++iter) - { - LLKeywordToken* delimiter = *iter; - if( delimiter->isHead( cur ) ) - { - cur_delimiter = delimiter; - break; - } - } - - if( cur_delimiter ) - { - S32 between_delimiters = 0; - S32 seg_end = 0; - - seg_start = cur - base; - cur += cur_delimiter->getLengthHead(); - - LLKeywordToken::ETokenType type = cur_delimiter->getType(); - if( type == LLKeywordToken::TT_TWO_SIDED_DELIMITER || type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS ) - { - while( *cur && !cur_delimiter->isTail(cur)) - { - // Check for an escape sequence. - if (type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS && *cur == '\\') - { - // Count the number of backslashes. - S32 num_backslashes = 0; - while (*cur == '\\') - { - num_backslashes++; - between_delimiters++; - cur++; - } - // If the next character is the end delimiter? - if (cur_delimiter->isTail(cur)) - { - // If there was an odd number of backslashes, then this delimiter - // does not end the sequence. - if (num_backslashes % 2 == 1) - { - between_delimiters++; - cur++; - } - else - { - // This is an end delimiter. - break; - } - } - } - else - { - between_delimiters++; - cur++; - } - } - - if( *cur ) - { - cur += cur_delimiter->getLengthHead(); - seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead() + cur_delimiter->getLengthTail(); - } - else - { - // eof - seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); - } - } - else - { - llassert( cur_delimiter->getType() == LLKeywordToken::TT_ONE_SIDED_DELIMITER ); - // Left side is the delimiter. Right side is eol or eof. - while( *cur && ('\n' != *cur) ) - { - between_delimiters++; - cur++; - } - seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); - } - - insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, style, editor); - /* - LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); - text_segment->setToken( cur_delimiter ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); - */ - // Note: we don't increment cur, since the end of one delimited seg may be immediately - // followed by the start of another one. - continue; - } - } - - // check against words - llwchar prev = cur > base ? *(cur-1) : 0; - if( !iswalnum( prev ) && (prev != '_') ) - { - const llwchar* p = cur; - while( iswalnum( *p ) || (*p == '_') ) - { - p++; - } - S32 seg_len = p - cur; - if( seg_len > 0 ) - { - WStringMapIndex word( cur, seg_len ); - word_token_map_t::iterator map_iter = mWordTokenMap.find(word); - if( map_iter != mWordTokenMap.end() ) - { - LLKeywordToken* cur_token = map_iter->second; - S32 seg_start = cur - base; - S32 seg_end = seg_start + seg_len; - - // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; - - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); - } - cur += seg_len; - continue; - } - } - - if( *cur && *cur != '\n' ) - { - cur++; - } - } - } + LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); + seg_list->clear(); + + if( wtext.empty() ) + { + return; + } + + S32 text_len = wtext.size() + 1; + + seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) ); + + const llwchar* base = wtext.c_str(); + const llwchar* cur = base; + while( *cur ) + { + if( *cur == '\n' || cur == base ) + { + if( *cur == '\n' ) + { + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base); + text_segment->setToken( 0 ); + insertSegment( *seg_list, text_segment, text_len, style, editor); + cur++; + if( !*cur || *cur == '\n' ) + { + continue; + } + } + + // Skip white space + while( *cur && iswspace(*cur) && (*cur != '\n') ) + { + cur++; + } + if( !*cur || *cur == '\n' ) + { + continue; + } + + // cur is now at the first non-whitespace character of a new line + + // Line start tokens + { + BOOL line_done = FALSE; + for (token_list_t::iterator iter = mLineTokenList.begin(); + iter != mLineTokenList.end(); ++iter) + { + LLKeywordToken* cur_token = *iter; + if( cur_token->isHead( cur ) ) + { + S32 seg_start = cur - base; + while( *cur && *cur != '\n' ) + { + // skip the rest of the line + cur++; + } + S32 seg_end = cur - base; + + //create segments from seg_start to seg_end + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); + line_done = TRUE; // to break out of second loop. + break; + } + } + + if( line_done ) + { + continue; + } + } + } + + // Skip white space + while( *cur && iswspace(*cur) && (*cur != '\n') ) + { + cur++; + } + + while( *cur && *cur != '\n' ) + { + // Check against delimiters + { + S32 seg_start = 0; + LLKeywordToken* cur_delimiter = NULL; + for (token_list_t::iterator iter = mDelimiterTokenList.begin(); + iter != mDelimiterTokenList.end(); ++iter) + { + LLKeywordToken* delimiter = *iter; + if( delimiter->isHead( cur ) ) + { + cur_delimiter = delimiter; + break; + } + } + + if( cur_delimiter ) + { + S32 between_delimiters = 0; + S32 seg_end = 0; + + seg_start = cur - base; + cur += cur_delimiter->getLengthHead(); + + LLKeywordToken::ETokenType type = cur_delimiter->getType(); + if( type == LLKeywordToken::TT_TWO_SIDED_DELIMITER || type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS ) + { + while( *cur && !cur_delimiter->isTail(cur)) + { + // Check for an escape sequence. + if (type == LLKeywordToken::TT_DOUBLE_QUOTATION_MARKS && *cur == '\\') + { + // Count the number of backslashes. + S32 num_backslashes = 0; + while (*cur == '\\') + { + num_backslashes++; + between_delimiters++; + cur++; + } + // If the next character is the end delimiter? + if (cur_delimiter->isTail(cur)) + { + // If there was an odd number of backslashes, then this delimiter + // does not end the sequence. + if (num_backslashes % 2 == 1) + { + between_delimiters++; + cur++; + } + else + { + // This is an end delimiter. + break; + } + } + } + else + { + between_delimiters++; + cur++; + } + } + + if( *cur ) + { + cur += cur_delimiter->getLengthHead(); + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead() + cur_delimiter->getLengthTail(); + } + else + { + // eof + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); + } + } + else + { + llassert( cur_delimiter->getType() == LLKeywordToken::TT_ONE_SIDED_DELIMITER ); + // Left side is the delimiter. Right side is eol or eof. + while( *cur && ('\n' != *cur) ) + { + between_delimiters++; + cur++; + } + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); + } + + insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, style, editor); + /* + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); + text_segment->setToken( cur_delimiter ); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + */ + // Note: we don't increment cur, since the end of one delimited seg may be immediately + // followed by the start of another one. + continue; + } + } + + // check against words + llwchar prev = cur > base ? *(cur-1) : 0; + if( !iswalnum( prev ) && (prev != '_') ) + { + const llwchar* p = cur; + while( iswalnum( *p ) || (*p == '_') ) + { + p++; + } + S32 seg_len = p - cur; + if( seg_len > 0 ) + { + WStringMapIndex word( cur, seg_len ); + word_token_map_t::iterator map_iter = mWordTokenMap.find(word); + if( map_iter != mWordTokenMap.end() ) + { + LLKeywordToken* cur_token = map_iter->second; + S32 seg_start = cur - base; + S32 seg_end = seg_start + seg_len; + + // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; + + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); + } + cur += seg_len; + continue; + } + } + + if( *cur && *cur != '\n' ) + { + cur++; + } + } + } } void LLKeywords::insertSegments(const LLWString& wtext, std::vector& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, LLStyleConstSP style, LLTextEditor& editor ) { - std::string::size_type pos = wtext.find('\n',seg_start); - + std::string::size_type pos = wtext.find('\n',seg_start); + LLStyleConstSP cur_token_style = new LLStyle(LLStyle::Params().font(style->getFont()).color(cur_token->getColor())); - while (pos!=-1 && pos < (std::string::size_type)seg_end) - { - if (pos!=seg_start) - { + while (pos!=-1 && pos < (std::string::size_type)seg_end) + { + if (pos!=seg_start) + { LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, pos, editor); - text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, style, editor); - } + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, style, editor); + } - LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, pos); - text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, style, editor); + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, pos); + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, style, editor); - seg_start = pos+1; - pos = wtext.find('\n',seg_start); - } + seg_start = pos+1; + pos = wtext.find('\n',seg_start); + } - LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, seg_end, editor); - text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, style, editor); + LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, seg_end, editor); + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, style, editor); } void LLKeywords::insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) { - LLTextSegmentPtr last = seg_list.back(); - S32 new_seg_end = new_segment->getEnd(); - - if( new_segment->getStart() == last->getStart() ) - { - seg_list.pop_back(); - } - else - { - last->setEnd( new_segment->getStart() ); - } - seg_list.push_back( new_segment ); - - if( new_seg_end < text_len ) - { - seg_list.push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); - } + LLTextSegmentPtr last = seg_list.back(); + S32 new_seg_end = new_segment->getEnd(); + + if( new_segment->getStart() == last->getStart() ) + { + seg_list.pop_back(); + } + else + { + last->setEnd( new_segment->getStart() ); + } + seg_list.push_back( new_segment ); + + if( new_seg_end < text_len ) + { + seg_list.push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); + } } void LLKeywords::insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ) { - LLTextSegmentPtr last = seg_list.back(); - S32 new_seg_end = new_segment->getEnd(); - - if( new_segment->getStart() == last->getStart() ) - { - seg_list.pop_back(); - } - else - { - last->setEnd( new_segment->getStart() ); - } - seg_list.push_back( new_segment ); - - if( new_seg_end < text_len ) - { - seg_list.push_back( new LLNormalTextSegment( style, new_seg_end, text_len, editor ) ); - } + LLTextSegmentPtr last = seg_list.back(); + S32 new_seg_end = new_segment->getEnd(); + + if( new_segment->getStart() == last->getStart() ) + { + seg_list.pop_back(); + } + else + { + last->setEnd( new_segment->getStart() ); + } + seg_list.push_back( new_segment ); + + if( new_seg_end < text_len ) + { + seg_list.push_back( new LLNormalTextSegment( style, new_seg_end, text_len, editor ) ); + } } #ifdef _DEBUG void LLKeywords::dump() { - LL_INFOS() << "LLKeywords" << LL_ENDL; - - - LL_INFOS() << "LLKeywords::sWordTokenMap" << LL_ENDL; - word_token_map_t::iterator word_token_iter = mWordTokenMap.begin(); - while( word_token_iter != mWordTokenMap.end() ) - { - LLKeywordToken* word_token = word_token_iter->second; - word_token->dump(); - ++word_token_iter; - } - - LL_INFOS() << "LLKeywords::sLineTokenList" << LL_ENDL; - for (token_list_t::iterator iter = mLineTokenList.begin(); - iter != mLineTokenList.end(); ++iter) - { - LLKeywordToken* line_token = *iter; - line_token->dump(); - } - - - LL_INFOS() << "LLKeywords::sDelimiterTokenList" << LL_ENDL; - for (token_list_t::iterator iter = mDelimiterTokenList.begin(); - iter != mDelimiterTokenList.end(); ++iter) - { - LLKeywordToken* delimiter_token = *iter; - delimiter_token->dump(); - } + LL_INFOS() << "LLKeywords" << LL_ENDL; + + + LL_INFOS() << "LLKeywords::sWordTokenMap" << LL_ENDL; + word_token_map_t::iterator word_token_iter = mWordTokenMap.begin(); + while( word_token_iter != mWordTokenMap.end() ) + { + LLKeywordToken* word_token = word_token_iter->second; + word_token->dump(); + ++word_token_iter; + } + + LL_INFOS() << "LLKeywords::sLineTokenList" << LL_ENDL; + for (token_list_t::iterator iter = mLineTokenList.begin(); + iter != mLineTokenList.end(); ++iter) + { + LLKeywordToken* line_token = *iter; + line_token->dump(); + } + + + LL_INFOS() << "LLKeywords::sDelimiterTokenList" << LL_ENDL; + for (token_list_t::iterator iter = mDelimiterTokenList.begin(); + iter != mDelimiterTokenList.end(); ++iter) + { + LLKeywordToken* delimiter_token = *iter; + delimiter_token->dump(); + } } void LLKeywordToken::dump() { - LL_INFOS() << "[" << - mColor.mV[VX] << ", " << - mColor.mV[VY] << ", " << - mColor.mV[VZ] << "] [" << - wstring_to_utf8str(mToken) << "]" << - LL_ENDL; + LL_INFOS() << "[" << + mColor.mV[VX] << ", " << + mColor.mV[VY] << ", " << + mColor.mV[VZ] << "] [" << + wstring_to_utf8str(mToken) << "]" << + LL_ENDL; } #endif // DEBUG diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 2410fe7d5a..9dcdea121b 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -44,162 +44,162 @@ typedef LLPointer LLTextSegmentPtr; class LLKeywordToken { public: - /** - * @brief Types of tokens/delimters being parsed. - * - * @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered. - * - TT_WORD are keywords in the normal sense, i.e. constants, events, etc. - * - TT_LINE are for entire lines (currently only flow control labels use this). - * - TT_ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL. - * - TT_TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with. - * - TT_DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close. - */ - typedef enum e_token_type - { - TT_UNKNOWN, - TT_WORD, - TT_LINE, - TT_TWO_SIDED_DELIMITER, - TT_ONE_SIDED_DELIMITER, - TT_DOUBLE_QUOTATION_MARKS, - // Following constants are more specific versions of the preceding ones - TT_CONSTANT, // WORD - TT_CONTROL, // WORD - TT_EVENT, // WORD - TT_FUNCTION, // WORD - TT_LABEL, // LINE - TT_SECTION, // WORD - TT_TYPE // WORD - } ETokenType; - - LLKeywordToken( ETokenType type, const LLColor4& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter ) - : - mType( type ), - mToken( token ), - mColor( color ), - mToolTip( tool_tip ), - mDelimiter( delimiter ) // right delimiter - { - } - - S32 getLengthHead() const { return mToken.size(); } - S32 getLengthTail() const { return mDelimiter.size(); } - bool isHead(const llwchar* s) const; - bool isTail(const llwchar* s) const; - const LLWString& getToken() const { return mToken; } - const LLColor4& getColor() const { return mColor; } - ETokenType getType() const { return mType; } - const LLWString& getToolTip() const { return mToolTip; } - const LLWString& getDelimiter() const { return mDelimiter; } + /** + * @brief Types of tokens/delimters being parsed. + * + * @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered. + * - TT_WORD are keywords in the normal sense, i.e. constants, events, etc. + * - TT_LINE are for entire lines (currently only flow control labels use this). + * - TT_ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL. + * - TT_TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with. + * - TT_DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close. + */ + typedef enum e_token_type + { + TT_UNKNOWN, + TT_WORD, + TT_LINE, + TT_TWO_SIDED_DELIMITER, + TT_ONE_SIDED_DELIMITER, + TT_DOUBLE_QUOTATION_MARKS, + // Following constants are more specific versions of the preceding ones + TT_CONSTANT, // WORD + TT_CONTROL, // WORD + TT_EVENT, // WORD + TT_FUNCTION, // WORD + TT_LABEL, // LINE + TT_SECTION, // WORD + TT_TYPE // WORD + } ETokenType; + + LLKeywordToken( ETokenType type, const LLColor4& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter ) + : + mType( type ), + mToken( token ), + mColor( color ), + mToolTip( tool_tip ), + mDelimiter( delimiter ) // right delimiter + { + } + + S32 getLengthHead() const { return mToken.size(); } + S32 getLengthTail() const { return mDelimiter.size(); } + bool isHead(const llwchar* s) const; + bool isTail(const llwchar* s) const; + const LLWString& getToken() const { return mToken; } + const LLColor4& getColor() const { return mColor; } + ETokenType getType() const { return mType; } + const LLWString& getToolTip() const { return mToolTip; } + const LLWString& getDelimiter() const { return mDelimiter; } #ifdef _DEBUG - void dump(); + void dump(); #endif private: - ETokenType mType; - LLWString mToken; - LLColor4 mColor; - LLWString mToolTip; - LLWString mDelimiter; + ETokenType mType; + LLWString mToken; + LLColor4 mColor; + LLWString mToolTip; + LLWString mDelimiter; }; class LLKeywords { public: - LLKeywords(); - ~LLKeywords(); + LLKeywords(); + ~LLKeywords(); - void clearLoaded() { mLoaded = false; } - LLColor4 getColorGroup(const std::string& key_in); - bool isLoaded() const { return mLoaded; } + void clearLoaded() { mLoaded = false; } + LLColor4 getColorGroup(const std::string& key_in); + bool isLoaded() const { return mLoaded; } - void findSegments(std::vector *seg_list, - const LLWString& text, - class LLTextEditor& editor, + void findSegments(std::vector *seg_list, + const LLWString& text, + class LLTextEditor& editor, LLStyleConstSP style); - void initialize(LLSD SyntaxXML); - void processTokens(); - - // Add the token as described - void addToken(LLKeywordToken::ETokenType type, - const std::string& key, - const LLColor4& color, - const std::string& tool_tip = LLStringUtil::null, - const std::string& delimiter = LLStringUtil::null); - - // This class is here as a performance optimization. - // The word token map used to be defined as std::map. - // This worked, but caused a performance bottleneck due to memory allocation and string copies - // because it's not possible to search such a map without creating an LLWString. - // Using this class as the map index instead allows us to search using segments of an existing - // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments(). - class WStringMapIndex - { - public: - // copy constructor - WStringMapIndex(const WStringMapIndex& other); - // constructor from a string (copies the string's data into the new object) - WStringMapIndex(const LLWString& str); - // constructor from pointer and length - // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object! - WStringMapIndex(const llwchar *start, size_t length); - ~WStringMapIndex(); - bool operator<(const WStringMapIndex &other) const; - private: - void copyData(const llwchar *start, size_t length); - const llwchar *mData; - size_t mLength; - bool mOwner; - - - LLColor4 mColor; - }; - - typedef std::map word_token_map_t; - typedef word_token_map_t::const_iterator keyword_iterator_t; - keyword_iterator_t begin() const { return mWordTokenMap.begin(); } - keyword_iterator_t end() const { return mWordTokenMap.end(); } - - typedef std::map group_color_map_t; - typedef group_color_map_t::const_iterator color_iterator_t; - group_color_map_t mColorGroupMap; + void initialize(LLSD SyntaxXML); + void processTokens(); + + // Add the token as described + void addToken(LLKeywordToken::ETokenType type, + const std::string& key, + const LLColor4& color, + const std::string& tool_tip = LLStringUtil::null, + const std::string& delimiter = LLStringUtil::null); + + // This class is here as a performance optimization. + // The word token map used to be defined as std::map. + // This worked, but caused a performance bottleneck due to memory allocation and string copies + // because it's not possible to search such a map without creating an LLWString. + // Using this class as the map index instead allows us to search using segments of an existing + // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments(). + class WStringMapIndex + { + public: + // copy constructor + WStringMapIndex(const WStringMapIndex& other); + // constructor from a string (copies the string's data into the new object) + WStringMapIndex(const LLWString& str); + // constructor from pointer and length + // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object! + WStringMapIndex(const llwchar *start, size_t length); + ~WStringMapIndex(); + bool operator<(const WStringMapIndex &other) const; + private: + void copyData(const llwchar *start, size_t length); + const llwchar *mData; + size_t mLength; + bool mOwner; + + + LLColor4 mColor; + }; + + typedef std::map word_token_map_t; + typedef word_token_map_t::const_iterator keyword_iterator_t; + keyword_iterator_t begin() const { return mWordTokenMap.begin(); } + keyword_iterator_t end() const { return mWordTokenMap.end(); } + + typedef std::map group_color_map_t; + typedef group_color_map_t::const_iterator color_iterator_t; + group_color_map_t mColorGroupMap; #ifdef _DEBUG - void dump(); + void dump(); #endif protected: - void processTokensGroup(const LLSD& Tokens, const std::string& Group); - void insertSegment(std::vector& seg_list, - LLTextSegmentPtr new_segment, - S32 text_len, - const LLColor4 &defaultColor, - class LLTextEditor& editor); - void insertSegments(const LLWString& wtext, - std::vector& seg_list, - LLKeywordToken* token, - S32 text_len, - S32 seg_start, - S32 seg_end, - LLStyleConstSP style, - LLTextEditor& editor); + void processTokensGroup(const LLSD& Tokens, const std::string& Group); + void insertSegment(std::vector& seg_list, + LLTextSegmentPtr new_segment, + S32 text_len, + const LLColor4 &defaultColor, + class LLTextEditor& editor); + void insertSegments(const LLWString& wtext, + std::vector& seg_list, + LLKeywordToken* token, + S32 text_len, + S32 seg_start, + S32 seg_end, + LLStyleConstSP style, + LLTextEditor& editor); void insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ); - bool mLoaded; - LLSD mSyntax; - word_token_map_t mWordTokenMap; - typedef std::deque token_list_t; - token_list_t mLineTokenList; - token_list_t mDelimiterTokenList; + bool mLoaded; + LLSD mSyntax; + word_token_map_t mWordTokenMap; + typedef std::deque token_list_t; + token_list_t mLineTokenList; + token_list_t mDelimiterTokenList; - typedef std::map element_attributes_t; - typedef element_attributes_t::const_iterator attribute_iterator_t; - element_attributes_t mAttributes; - std::string getAttribute(const std::string& key); + typedef std::map element_attributes_t; + typedef element_attributes_t::const_iterator attribute_iterator_t; + element_attributes_t mAttributes; + std::string getAttribute(const std::string& key); - std::string getArguments(LLSD& arguments); + std::string getArguments(LLSD& arguments); }; #endif // LL_LLKEYWORDS_H diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 2769a96875..13d6faa673 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lllayoutstack.cpp * @brief LLLayout class - dynamic stacking of UI elements * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,159 +45,159 @@ static LLLayoutStack::LayoutStackRegistry::Register register_layo // // LLLayoutPanel // -LLLayoutPanel::Params::Params() -: expanded_min_dim("expanded_min_dim", 0), - min_dim("min_dim", -1), - user_resize("user_resize", false), - auto_resize("auto_resize", true) +LLLayoutPanel::Params::Params() +: expanded_min_dim("expanded_min_dim", 0), + min_dim("min_dim", -1), + user_resize("user_resize", false), + auto_resize("auto_resize", true) { - addSynonym(min_dim, "min_width"); - addSynonym(min_dim, "min_height"); + addSynonym(min_dim, "min_width"); + addSynonym(min_dim, "min_height"); } -LLLayoutPanel::LLLayoutPanel(const Params& p) -: LLPanel(p), - mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim), - mMinDim(p.min_dim), - mAutoResize(p.auto_resize), - mUserResize(p.user_resize), - mCollapsed(FALSE), - mCollapseAmt(0.f), - mVisibleAmt(1.f), // default to fully visible - mResizeBar(NULL), - mFractionalSize(0.f), - mTargetDim(0), - mIgnoreReshape(false), - mOrientation(LLLayoutStack::HORIZONTAL) +LLLayoutPanel::LLLayoutPanel(const Params& p) +: LLPanel(p), + mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim), + mMinDim(p.min_dim), + mAutoResize(p.auto_resize), + mUserResize(p.user_resize), + mCollapsed(FALSE), + mCollapseAmt(0.f), + mVisibleAmt(1.f), // default to fully visible + mResizeBar(NULL), + mFractionalSize(0.f), + mTargetDim(0), + mIgnoreReshape(false), + mOrientation(LLLayoutStack::HORIZONTAL) { - // panels initialized as hidden should not start out partially visible - if (!getVisible()) - { - mVisibleAmt = 0.f; - } + // panels initialized as hidden should not start out partially visible + if (!getVisible()) + { + mVisibleAmt = 0.f; + } } void LLLayoutPanel::initFromParams(const Params& p) { - LLPanel::initFromParams(p); - setFollowsNone(); + LLPanel::initFromParams(p); + setFollowsNone(); } LLLayoutPanel::~LLLayoutPanel() { - // probably not necessary, but... - delete mResizeBar; - mResizeBar = NULL; + // probably not necessary, but... + delete mResizeBar; + mResizeBar = NULL; gFocusMgr.removeKeyboardFocusWithoutCallback(this); } F32 LLLayoutPanel::getAutoResizeFactor() const { - return mVisibleAmt * (1.f - mCollapseAmt); + return mVisibleAmt * (1.f - mCollapseAmt); } - + F32 LLLayoutPanel::getVisibleAmount() const { - return mVisibleAmt; + return mVisibleAmt; } S32 LLLayoutPanel::getLayoutDim() const { - return ll_round((F32)((mOrientation == LLLayoutStack::HORIZONTAL) - ? getRect().getWidth() - : getRect().getHeight())); + return ll_round((F32)((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight())); } S32 LLLayoutPanel::getTargetDim() const { - return mTargetDim; + return mTargetDim; } void LLLayoutPanel::setTargetDim(S32 value) { - LLRect new_rect(getRect()); - if (mOrientation == LLLayoutStack::HORIZONTAL) - { - new_rect.mRight = new_rect.mLeft + value; - } - else - { - new_rect.mTop = new_rect.mBottom + value; - } - setShape(new_rect, true); + LLRect new_rect(getRect()); + if (mOrientation == LLLayoutStack::HORIZONTAL) + { + new_rect.mRight = new_rect.mLeft + value; + } + else + { + new_rect.mTop = new_rect.mBottom + value; + } + setShape(new_rect, true); } S32 LLLayoutPanel::getVisibleDim() const { - F32 min_dim = getRelevantMinDim(); - return ll_round(mVisibleAmt - * (min_dim - + (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); + F32 min_dim = getRelevantMinDim(); + return ll_round(mVisibleAmt + * (min_dim + + (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); } - + void LLLayoutPanel::setOrientation( LLView::EOrientation orientation ) { - mOrientation = orientation; - S32 layout_dim = ll_round((F32)((mOrientation == LLLayoutStack::HORIZONTAL) - ? getRect().getWidth() - : getRect().getHeight())); - - if (mAutoResize == FALSE - && mUserResize == TRUE - && mMinDim == -1 ) - { - setMinDim(layout_dim); - } - mTargetDim = llmax(layout_dim, getMinDim()); + mOrientation = orientation; + S32 layout_dim = ll_round((F32)((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight())); + + if (mAutoResize == FALSE + && mUserResize == TRUE + && mMinDim == -1 ) + { + setMinDim(layout_dim); + } + mTargetDim = llmax(layout_dim, getMinDim()); } - + void LLLayoutPanel::setVisible( BOOL visible ) { - if (visible != getVisible()) - { - LLLayoutStack* stackp = dynamic_cast(getParent()); - if (stackp) - { - stackp->mNeedsLayout = true; - } - } - LLPanel::setVisible(visible); + if (visible != getVisible()) + { + LLLayoutStack* stackp = dynamic_cast(getParent()); + if (stackp) + { + stackp->mNeedsLayout = true; + } + } + LLPanel::setVisible(visible); } void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ ) { - if (width == getRect().getWidth() && height == getRect().getHeight() && !LLView::sForceReshape) return; - - if (!mIgnoreReshape && mAutoResize == false) - { - mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height; - LLLayoutStack* stackp = dynamic_cast(getParent()); - if (stackp) - { - stackp->mNeedsLayout = true; - } - } - LLPanel::reshape(width, height, called_from_parent); + if (width == getRect().getWidth() && height == getRect().getHeight() && !LLView::sForceReshape) return; + + if (!mIgnoreReshape && mAutoResize == false) + { + mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height; + LLLayoutStack* stackp = dynamic_cast(getParent()); + if (stackp) + { + stackp->mNeedsLayout = true; + } + } + LLPanel::reshape(width, height, called_from_parent); } void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) { - LLLayoutStack* stackp = dynamic_cast(getParent()); - if (stackp) - { - if (by_user) - { // tell layout stack to account for new shape - - // make sure that panels have already been auto resized - stackp->updateLayout(); - // now apply requested size to panel - stackp->updatePanelRect(this, new_rect); - } - stackp->mNeedsLayout = true; - } - LLPanel::handleReshape(new_rect, by_user); + LLLayoutStack* stackp = dynamic_cast(getParent()); + if (stackp) + { + if (by_user) + { // tell layout stack to account for new shape + + // make sure that panels have already been auto resized + stackp->updateLayout(); + // now apply requested size to panel + stackp->updatePanelRect(this, new_rect); + } + stackp->mNeedsLayout = true; + } + LLPanel::handleReshape(new_rect, by_user); } // @@ -205,85 +205,85 @@ void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) // LLLayoutStack::Params::Params() -: orientation("orientation"), - animate("animate", true), - clip("clip", true), - open_time_constant("open_time_constant", 0.02f), - close_time_constant("close_time_constant", 0.03f), - resize_bar_overlap("resize_bar_overlap", 1), - border_size("border_size", LLCachedControl(*LLUI::getInstance()->mSettingGroups["config"], "UIResizeBarHeight", 0)), - show_drag_handle("show_drag_handle", false), - 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), +: orientation("orientation"), + animate("animate", true), + clip("clip", true), + open_time_constant("open_time_constant", 0.02f), + close_time_constant("close_time_constant", 0.03f), + resize_bar_overlap("resize_bar_overlap", 1), + border_size("border_size", LLCachedControl(*LLUI::getInstance()->mSettingGroups["config"], "UIResizeBarHeight", 0)), + show_drag_handle("show_drag_handle", false), + 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_color("drag_handle_color", LLUIColorTable::instance().getColor("ResizebarBody")) { - addSynonym(border_size, "drag_handle_gap"); + addSynonym(border_size, "drag_handle_gap"); } -LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) -: LLView(p), - mPanelSpacing(p.border_size), - mOrientation(p.orientation), - mAnimate(p.animate), - mAnimatedThisFrame(false), - mNeedsLayout(true), - mClip(p.clip), - mOpenTimeConstant(p.open_time_constant), - mCloseTimeConstant(p.close_time_constant), - mResizeBarOverlap(p.resize_bar_overlap), - mShowDragHandle(p.show_drag_handle), - mDragHandleFirstIndent(p.drag_handle_first_indent), - mDragHandleSecondIndent(p.drag_handle_second_indent), - mDragHandleThickness(p.drag_handle_thickness), - mDragHandleShift(p.drag_handle_shift), +LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) +: LLView(p), + mPanelSpacing(p.border_size), + mOrientation(p.orientation), + mAnimate(p.animate), + mAnimatedThisFrame(false), + mNeedsLayout(true), + mClip(p.clip), + mOpenTimeConstant(p.open_time_constant), + mCloseTimeConstant(p.close_time_constant), + mResizeBarOverlap(p.resize_bar_overlap), + mShowDragHandle(p.show_drag_handle), + mDragHandleFirstIndent(p.drag_handle_first_indent), + mDragHandleSecondIndent(p.drag_handle_second_indent), + mDragHandleThickness(p.drag_handle_thickness), + mDragHandleShift(p.drag_handle_shift), mDragHandleColor(p.drag_handle_color()) { } LLLayoutStack::~LLLayoutStack() { - e_panel_list_t panels = mPanels; // copy list of panel pointers - mPanels.clear(); // clear so that removeChild() calls don't cause trouble - std::for_each(panels.begin(), panels.end(), DeletePointer()); + e_panel_list_t panels = mPanels; // copy list of panel pointers + mPanels.clear(); // clear so that removeChild() calls don't cause trouble + std::for_each(panels.begin(), panels.end(), DeletePointer()); } void LLLayoutStack::draw() { - updateLayout(); - - // always clip to stack itself - LLLocalClipRect clip(getLocalRect()); - for (LLLayoutPanel* panelp : mPanels) - { - if ((!panelp->getVisible() || panelp->mCollapsed) - && (panelp->mVisibleAmt < 0.001f || !mAnimate)) - { - // essentially invisible - continue; - } - // clip to layout rectangle, not bounding rectangle - LLRect clip_rect = panelp->getRect(); - // scale clipping rectangle by visible amount - if (mOrientation == HORIZONTAL) - { - clip_rect.mRight = clip_rect.mLeft + panelp->getVisibleDim(); - } - else - { - clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim(); - } - - {LLLocalClipRect clip(clip_rect, mClip); - // only force drawing invisible children if visible amount is non-zero - drawChild(panelp, 0, 0, !clip_rect.isEmpty()); - } - if (panelp->getResizeBar()->getVisible()) - { - drawChild(panelp->getResizeBar()); - } - } + updateLayout(); + + // always clip to stack itself + LLLocalClipRect clip(getLocalRect()); + for (LLLayoutPanel* panelp : mPanels) + { + if ((!panelp->getVisible() || panelp->mCollapsed) + && (panelp->mVisibleAmt < 0.001f || !mAnimate)) + { + // essentially invisible + continue; + } + // clip to layout rectangle, not bounding rectangle + LLRect clip_rect = panelp->getRect(); + // scale clipping rectangle by visible amount + if (mOrientation == HORIZONTAL) + { + clip_rect.mRight = clip_rect.mLeft + panelp->getVisibleDim(); + } + else + { + clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim(); + } + + {LLLocalClipRect clip(clip_rect, mClip); + // only force drawing invisible children if visible amount is non-zero + drawChild(panelp, 0, 0, !clip_rect.isEmpty()); + } + if (panelp->getResizeBar()->getVisible()) + { + drawChild(panelp->getResizeBar()); + } + } } void LLLayoutStack::deleteAllChildren() @@ -299,15 +299,15 @@ void LLLayoutStack::deleteAllChildren() void LLLayoutStack::removeChild(LLView* view) { - LLLayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast(view)); + LLLayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast(view)); - if (embedded_panelp) - { - mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); + if (embedded_panelp) + { + mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); LLView::removeChild(view); - updateFractionalSizes(); - mNeedsLayout = true; - } + updateFractionalSizes(); + mNeedsLayout = true; + } else { LLView::removeChild(view); @@ -316,215 +316,215 @@ void LLLayoutStack::removeChild(LLView* view) BOOL LLLayoutStack::postBuild() { - updateLayout(); - return TRUE; + updateLayout(); + return TRUE; } bool LLLayoutStack::addChild(LLView* child, S32 tab_group) { - LLLayoutPanel* panelp = dynamic_cast(child); - if (panelp) - { - panelp->setOrientation(mOrientation); - mPanels.push_back(panelp); - createResizeBar(panelp); - mNeedsLayout = true; - } - BOOL result = LLView::addChild(child, tab_group); - - updateFractionalSizes(); - return result; + LLLayoutPanel* panelp = dynamic_cast(child); + if (panelp) + { + panelp->setOrientation(mOrientation); + mPanels.push_back(panelp); + createResizeBar(panelp); + mNeedsLayout = true; + } + BOOL result = LLView::addChild(child, tab_group); + + updateFractionalSizes(); + return result; } void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) { - addChild(panel); - - // panel starts off invisible (collapsed) - if (animate == ANIMATE) - { - panel->mVisibleAmt = 0.f; - panel->setVisible(TRUE); - } + addChild(panel); + + // panel starts off invisible (collapsed) + if (animate == ANIMATE) + { + panel->mVisibleAmt = 0.f; + panel->setVisible(TRUE); + } } void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) { - LLLayoutPanel* panel_container = findEmbeddedPanel(panel); - if (!panel_container) return; + LLLayoutPanel* panel_container = findEmbeddedPanel(panel); + if (!panel_container) return; - panel_container->mCollapsed = collapsed; - mNeedsLayout = true; + panel_container->mCollapsed = collapsed; + mNeedsLayout = true; } class LLImagePanel : public LLPanel { public: - struct Params : public LLInitParam::Block - { - Optional horizontal; - Params() : horizontal("horizontal", false) {} - }; - LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {} - virtual ~LLImagePanel() {} - - void draw() - { - const LLRect& parent_rect = getParent()->getRect(); - const LLRect& rect = getRect(); - LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2 - , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom); - LLLocalClipRect clip(clip_rect); - LLPanel::draw(); - } + struct Params : public LLInitParam::Block + { + Optional horizontal; + Params() : horizontal("horizontal", false) {} + }; + LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {} + virtual ~LLImagePanel() {} + + void draw() + { + const LLRect& parent_rect = getParent()->getRect(); + const LLRect& rect = getRect(); + LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2 + , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom); + LLLocalClipRect clip(clip_rect); + LLPanel::draw(); + } private: - bool mHorizontal; + bool mHorizontal; }; void LLLayoutStack::updateLayout() -{ +{ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - if (!mNeedsLayout) return; - - bool continue_animating = animatePanels(); - F32 total_visible_fraction = 0.f; - S32 space_to_distribute = (mOrientation == HORIZONTAL) - ? getRect().getWidth() - : getRect().getHeight(); - - // first, assign minimum dimensions - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - panelp->mTargetDim = panelp->getRelevantMinDim(); - } - space_to_distribute -= panelp->getVisibleDim() + ll_round((F32)mPanelSpacing * panelp->getVisibleAmount()); - total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); - } - - llassert(total_visible_fraction < 1.05f); - - // don't need spacing after last panel - if (!mPanels.empty()) - { - space_to_distribute += ll_round(F32(mPanelSpacing) * mPanels.back()->getVisibleAmount()); - } - - S32 remaining_space = space_to_distribute; - if (space_to_distribute > 0 && total_visible_fraction > 0.f) - { // give space proportionally to visible auto resize panels - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction); - S32 delta = ll_round((F32)space_to_distribute * fraction_to_distribute); - panelp->mTargetDim += delta; - remaining_space -= delta; - } - } - } - - // distribute any left over pixels to non-collapsed, visible panels - for (LLLayoutPanel* panelp : mPanels) - { - if (remaining_space == 0) break; - - if (panelp->mAutoResize - && !panelp->mCollapsed - && panelp->getVisible()) - { - S32 space_for_panel = remaining_space > 0 ? 1 : -1; - panelp->mTargetDim += space_for_panel; - remaining_space -= space_for_panel; - } - } - - F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); - - for (LLLayoutPanel* panelp : mPanels) - { - F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); - - LLRect panel_rect; - if (mOrientation == HORIZONTAL) - { - panel_rect.setLeftTopAndSize(ll_round(cur_pos), - getRect().getHeight(), - ll_round(panel_dim), - getRect().getHeight()); - } - else - { - panel_rect.setLeftTopAndSize(0, - ll_round(cur_pos), - getRect().getWidth(), - ll_round(panel_dim)); - } - - LLRect resize_bar_rect(panel_rect); - F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); - F32 panel_visible_dim = panelp->getVisibleDim(); - S32 panel_spacing_round = (S32)(ll_round(panel_spacing)); - - if (mOrientation == HORIZONTAL) - { - cur_pos += panel_visible_dim + panel_spacing; - - if (mShowDragHandle && panel_spacing_round > mDragHandleThickness) - { - resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift; - resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness; - } - else - { - resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; - resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap; - } - - if (mShowDragHandle) - { - resize_bar_rect.mBottom += mDragHandleSecondIndent; - resize_bar_rect.mTop -= mDragHandleFirstIndent; - } - - } - else //VERTICAL - { - cur_pos -= panel_visible_dim + panel_spacing; - - if (mShowDragHandle && panel_spacing_round > mDragHandleThickness) - { - resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift; - resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness; - } - else - { - resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; - resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap; - } - - if (mShowDragHandle) - { - resize_bar_rect.mLeft += mDragHandleFirstIndent; - resize_bar_rect.mRight -= mDragHandleSecondIndent; - } - } - - panelp->setIgnoreReshape(true); - panelp->setShape(panel_rect); - panelp->setIgnoreReshape(false); - panelp->mResizeBar->setShape(resize_bar_rect); - } - - updateResizeBarLimits(); - - // clear animation flag at end, since panel resizes will set it - // and leave it set if there is any animation in progress - mNeedsLayout = continue_animating; + if (!mNeedsLayout) return; + + bool continue_animating = animatePanels(); + F32 total_visible_fraction = 0.f; + S32 space_to_distribute = (mOrientation == HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight(); + + // first, assign minimum dimensions + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + panelp->mTargetDim = panelp->getRelevantMinDim(); + } + space_to_distribute -= panelp->getVisibleDim() + ll_round((F32)mPanelSpacing * panelp->getVisibleAmount()); + total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); + } + + llassert(total_visible_fraction < 1.05f); + + // don't need spacing after last panel + if (!mPanels.empty()) + { + space_to_distribute += ll_round(F32(mPanelSpacing) * mPanels.back()->getVisibleAmount()); + } + + S32 remaining_space = space_to_distribute; + if (space_to_distribute > 0 && total_visible_fraction > 0.f) + { // give space proportionally to visible auto resize panels + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction); + S32 delta = ll_round((F32)space_to_distribute * fraction_to_distribute); + panelp->mTargetDim += delta; + remaining_space -= delta; + } + } + } + + // distribute any left over pixels to non-collapsed, visible panels + for (LLLayoutPanel* panelp : mPanels) + { + if (remaining_space == 0) break; + + if (panelp->mAutoResize + && !panelp->mCollapsed + && panelp->getVisible()) + { + S32 space_for_panel = remaining_space > 0 ? 1 : -1; + panelp->mTargetDim += space_for_panel; + remaining_space -= space_for_panel; + } + } + + F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); + + for (LLLayoutPanel* panelp : mPanels) + { + F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); + + LLRect panel_rect; + if (mOrientation == HORIZONTAL) + { + panel_rect.setLeftTopAndSize(ll_round(cur_pos), + getRect().getHeight(), + ll_round(panel_dim), + getRect().getHeight()); + } + else + { + panel_rect.setLeftTopAndSize(0, + ll_round(cur_pos), + getRect().getWidth(), + ll_round(panel_dim)); + } + + LLRect resize_bar_rect(panel_rect); + F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); + F32 panel_visible_dim = panelp->getVisibleDim(); + S32 panel_spacing_round = (S32)(ll_round(panel_spacing)); + + if (mOrientation == HORIZONTAL) + { + cur_pos += panel_visible_dim + panel_spacing; + + if (mShowDragHandle && panel_spacing_round > mDragHandleThickness) + { + resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift; + resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness; + } + else + { + resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; + resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap; + } + + if (mShowDragHandle) + { + resize_bar_rect.mBottom += mDragHandleSecondIndent; + resize_bar_rect.mTop -= mDragHandleFirstIndent; + } + + } + else //VERTICAL + { + cur_pos -= panel_visible_dim + panel_spacing; + + if (mShowDragHandle && panel_spacing_round > mDragHandleThickness) + { + resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift; + resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness; + } + else + { + resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; + resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap; + } + + if (mShowDragHandle) + { + resize_bar_rect.mLeft += mDragHandleFirstIndent; + resize_bar_rect.mRight -= mDragHandleSecondIndent; + } + } + + panelp->setIgnoreReshape(true); + panelp->setShape(panel_rect); + panelp->setIgnoreReshape(false); + panelp->mResizeBar->setShape(resize_bar_rect); + } + + updateResizeBarLimits(); + + // clear animation flag at end, since panel resizes will set it + // and leave it set if there is any animation in progress + mNeedsLayout = continue_animating; } // end LLLayoutStack::updateLayout void LLLayoutStack::setPanelSpacing(S32 val) @@ -538,487 +538,487 @@ void LLLayoutStack::setPanelSpacing(S32 val) LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const { - if (!panelp) return NULL; - - for (LLLayoutPanel* p : mPanels) - { - if (p == panelp) - { - return p; - } - } - return NULL; + if (!panelp) return NULL; + + for (LLLayoutPanel* p : mPanels) + { + if (p == panelp) + { + return p; + } + } + return NULL; } LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const { - LLLayoutPanel* result = NULL; - - for (LLLayoutPanel* p : mPanels) - { - if (p->getName() == name) - { - result = p; - break; - } - } - - return result; + LLLayoutPanel* result = NULL; + + for (LLLayoutPanel* p : mPanels) + { + if (p->getName() == name) + { + result = p; + break; + } + } + + return result; } void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) { - for (LLLayoutPanel* lp : mPanels) - { - if (lp->mResizeBar == NULL) - { - LLResizeBar::Params resize_params; - resize_params.name("resize"); - resize_params.resizing_view(lp); - resize_params.min_size(lp->getRelevantMinDim()); - resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM); - resize_params.snapping_enabled(false); - LLResizeBar* resize_bar = LLUICtrlFactory::create(resize_params); - lp->mResizeBar = resize_bar; - - if (mShowDragHandle) - { - LLPanel::Params resize_bar_bg_panel_p; - resize_bar_bg_panel_p.name = "resize_handle_bg_panel"; - resize_bar_bg_panel_p.rect = lp->mResizeBar->getLocalRect(); - 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 = 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"); - resize_bar_bg_panel_p.border.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); - - LLPanel* resize_bar_bg_panel = LLUICtrlFactory::create(resize_bar_bg_panel_p); - - LLIconCtrl::Params icon_p; - icon_p.name = "resize_handle_image"; - icon_p.rect = lp->mResizeBar->getLocalRect(); - icon_p.follows.flags = FOLLOWS_ALL; - icon_p.image = LLUI::getUIImage(mOrientation == HORIZONTAL ? "Vertical Drag Handle" : "Horizontal Drag Handle"); - resize_bar_bg_panel->addChild(LLUICtrlFactory::create(icon_p)); - - lp->mResizeBar->addChild(resize_bar_bg_panel); - } - - /*if (mShowDragHandle) - { - LLViewBorder::Params border_params; - border_params.border_thickness = 1; - border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight"); - border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); - - addBorder(border_params); - setBorderVisible(TRUE); - - LLImagePanel::Params image_panel; - mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle"); - image_panel.bg_alpha_image = mDragHandleImage; - image_panel.background_visible = true; - image_panel.horizontal = (LLResizeBar::BOTTOM == mSide); - mImagePanel = LLUICtrlFactory::create(image_panel); - setImagePanel(mImagePanel); - }*/ - - //if (mShowDragHandle) - //{ - // setBackgroundVisible(TRUE); - // setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody")); - //} - - /*if (mShowDragHandle) - { - S32 image_width = mDragHandleImage->getTextureWidth(); - S32 image_height = mDragHandleImage->getTextureHeight(); - const LLRect& panel_rect = getRect(); - S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1; - S32 image_bottom = (panel_rect.getHeight() - image_height) / 2; - mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom)); - }*/ - LLView::addChild(resize_bar, 0); - } - } - // bring all resize bars to the front so that they are clickable even over the panels - // with a bit of overlap - for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLResizeBar* resize_barp = (*panel_it)->mResizeBar; - sendChildToFront(resize_barp); - } + for (LLLayoutPanel* lp : mPanels) + { + if (lp->mResizeBar == NULL) + { + LLResizeBar::Params resize_params; + resize_params.name("resize"); + resize_params.resizing_view(lp); + resize_params.min_size(lp->getRelevantMinDim()); + resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM); + resize_params.snapping_enabled(false); + LLResizeBar* resize_bar = LLUICtrlFactory::create(resize_params); + lp->mResizeBar = resize_bar; + + if (mShowDragHandle) + { + LLPanel::Params resize_bar_bg_panel_p; + resize_bar_bg_panel_p.name = "resize_handle_bg_panel"; + resize_bar_bg_panel_p.rect = lp->mResizeBar->getLocalRect(); + 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 = 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"); + resize_bar_bg_panel_p.border.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); + + LLPanel* resize_bar_bg_panel = LLUICtrlFactory::create(resize_bar_bg_panel_p); + + LLIconCtrl::Params icon_p; + icon_p.name = "resize_handle_image"; + icon_p.rect = lp->mResizeBar->getLocalRect(); + icon_p.follows.flags = FOLLOWS_ALL; + icon_p.image = LLUI::getUIImage(mOrientation == HORIZONTAL ? "Vertical Drag Handle" : "Horizontal Drag Handle"); + resize_bar_bg_panel->addChild(LLUICtrlFactory::create(icon_p)); + + lp->mResizeBar->addChild(resize_bar_bg_panel); + } + + /*if (mShowDragHandle) + { + LLViewBorder::Params border_params; + border_params.border_thickness = 1; + border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight"); + border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); + + addBorder(border_params); + setBorderVisible(TRUE); + + LLImagePanel::Params image_panel; + mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle"); + image_panel.bg_alpha_image = mDragHandleImage; + image_panel.background_visible = true; + image_panel.horizontal = (LLResizeBar::BOTTOM == mSide); + mImagePanel = LLUICtrlFactory::create(image_panel); + setImagePanel(mImagePanel); + }*/ + + //if (mShowDragHandle) + //{ + // setBackgroundVisible(TRUE); + // setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody")); + //} + + /*if (mShowDragHandle) + { + S32 image_width = mDragHandleImage->getTextureWidth(); + S32 image_height = mDragHandleImage->getTextureHeight(); + const LLRect& panel_rect = getRect(); + S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1; + S32 image_bottom = (panel_rect.getHeight() - image_height) / 2; + mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom)); + }*/ + LLView::addChild(resize_bar, 0); + } + } + // bring all resize bars to the front so that they are clickable even over the panels + // with a bit of overlap + for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + { + LLResizeBar* resize_barp = (*panel_it)->mResizeBar; + sendChildToFront(resize_barp); + } } // update layout stack animations, etc. once per frame // NOTE: we use this to size world view based on animating UI, *before* we draw the UI // we might still need to call updateLayout during UI draw phase, in case UI elements // are resizing themselves dynamically -//static +//static void LLLayoutStack::updateClass() { - for (auto& layout : instance_snapshot()) - { - layout.updateLayout(); - layout.mAnimatedThisFrame = false; - } + for (auto& layout : instance_snapshot()) + { + layout.updateLayout(); + layout.mAnimatedThisFrame = false; + } } void LLLayoutStack::updateFractionalSizes() { - F32 total_resizable_dim = 0.f; - - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - total_resizable_dim += llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); - } - } - - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); - panelp->mFractionalSize = panel_resizable_dim > 0.f - ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) - : MIN_FRACTIONAL_SIZE; - llassert(!llisnan(panelp->mFractionalSize)); - } - } - - normalizeFractionalSizes(); + F32 total_resizable_dim = 0.f; + + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + total_resizable_dim += llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); + } + } + + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); + panelp->mFractionalSize = panel_resizable_dim > 0.f + ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) + : MIN_FRACTIONAL_SIZE; + llassert(!llisnan(panelp->mFractionalSize)); + } + } + + normalizeFractionalSizes(); } void LLLayoutStack::normalizeFractionalSizes() { - S32 num_auto_resize_panels = 0; - F32 total_fractional_size = 0.f; - - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - total_fractional_size += panelp->mFractionalSize; - num_auto_resize_panels++; - } - } - - if (total_fractional_size == 0.f) - { // equal distribution - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - panelp->mFractionalSize = MAX_FRACTIONAL_SIZE / (F32)num_auto_resize_panels; - } - } - } - else - { // renormalize - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->mAutoResize) - { - panelp->mFractionalSize /= total_fractional_size; - } - } - } + S32 num_auto_resize_panels = 0; + F32 total_fractional_size = 0.f; + + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + total_fractional_size += panelp->mFractionalSize; + num_auto_resize_panels++; + } + } + + if (total_fractional_size == 0.f) + { // equal distribution + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize = MAX_FRACTIONAL_SIZE / (F32)num_auto_resize_panels; + } + } + } + else + { // renormalize + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize /= total_fractional_size; + } + } + } } bool LLLayoutStack::animatePanels() { - bool continue_animating = false; - - // - // animate visibility - // - for (LLLayoutPanel* panelp : mPanels) - { - if (panelp->getVisible()) - { - if (mAnimate && panelp->mVisibleAmt < 1.f) - { - if (!mAnimatedThisFrame) - { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLSmoothInterpolation::getInterpolant(mOpenTimeConstant)); - if (panelp->mVisibleAmt > 0.99f) - { - panelp->mVisibleAmt = 1.f; - } - } - - mAnimatedThisFrame = true; - continue_animating = true; - } - else - { - if (panelp->mVisibleAmt != 1.f) - { - panelp->mVisibleAmt = 1.f; - mAnimatedThisFrame = true; - } - } - } - else // not visible - { - if (mAnimate && panelp->mVisibleAmt > 0.f) - { - if (!mAnimatedThisFrame) - { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); - if (panelp->mVisibleAmt < 0.001f) - { - panelp->mVisibleAmt = 0.f; - } - } - - continue_animating = true; - mAnimatedThisFrame = true; - } - else - { - if (panelp->mVisibleAmt != 0.f) - { - panelp->mVisibleAmt = 0.f; - mAnimatedThisFrame = true; - } - } - } - - F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; - if (panelp->mCollapseAmt != collapse_state) - { - if (mAnimate) - { - if (!mAnimatedThisFrame) - { - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); - } - - if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) - { - panelp->mCollapseAmt = collapse_state; - } - - mAnimatedThisFrame = true; - continue_animating = true; - } - else - { - panelp->mCollapseAmt = collapse_state; - mAnimatedThisFrame = true; - } - } - } - - if (mAnimatedThisFrame) mNeedsLayout = true; - return continue_animating; + bool continue_animating = false; + + // + // animate visibility + // + for (LLLayoutPanel* panelp : mPanels) + { + if (panelp->getVisible()) + { + if (mAnimate && panelp->mVisibleAmt < 1.f) + { + if (!mAnimatedThisFrame) + { + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLSmoothInterpolation::getInterpolant(mOpenTimeConstant)); + if (panelp->mVisibleAmt > 0.99f) + { + panelp->mVisibleAmt = 1.f; + } + } + + mAnimatedThisFrame = true; + continue_animating = true; + } + else + { + if (panelp->mVisibleAmt != 1.f) + { + panelp->mVisibleAmt = 1.f; + mAnimatedThisFrame = true; + } + } + } + else // not visible + { + if (mAnimate && panelp->mVisibleAmt > 0.f) + { + if (!mAnimatedThisFrame) + { + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); + if (panelp->mVisibleAmt < 0.001f) + { + panelp->mVisibleAmt = 0.f; + } + } + + continue_animating = true; + mAnimatedThisFrame = true; + } + else + { + if (panelp->mVisibleAmt != 0.f) + { + panelp->mVisibleAmt = 0.f; + mAnimatedThisFrame = true; + } + } + } + + F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; + if (panelp->mCollapseAmt != collapse_state) + { + if (mAnimate) + { + if (!mAnimatedThisFrame) + { + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); + } + + if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) + { + panelp->mCollapseAmt = collapse_state; + } + + mAnimatedThisFrame = true; + continue_animating = true; + } + else + { + panelp->mCollapseAmt = collapse_state; + mAnimatedThisFrame = true; + } + } + } + + if (mAnimatedThisFrame) mNeedsLayout = true; + return continue_animating; } void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) { - S32 new_dim = (mOrientation == HORIZONTAL) - ? new_rect.getWidth() - : new_rect.getHeight(); - S32 delta_panel_dim = new_dim - resized_panel->getVisibleDim(); - if (delta_panel_dim == 0) return; - - F32 total_visible_fraction = 0.f; - F32 delta_auto_resize_headroom = 0.f; - F32 old_auto_resize_headroom = 0.f; - - LLLayoutPanel* other_resize_panel = NULL; - LLLayoutPanel* following_panel = NULL; - - BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) // Should replace this when C++20 reverse view adaptor becomes available... - { - if (panelp->mAutoResize) - { - old_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); - if (panelp->getVisible() && !panelp->mCollapsed) - { - total_visible_fraction += panelp->mFractionalSize; - } - } - - if (panelp == resized_panel) - { - other_resize_panel = following_panel; - } - - if (panelp->getVisible() && !panelp->mCollapsed) - { - following_panel = panelp; - } - } - - if (resized_panel->mAutoResize) - { - if (!other_resize_panel || !other_resize_panel->mAutoResize) - { - delta_auto_resize_headroom += delta_panel_dim; - } - } - else - { - if (!other_resize_panel || other_resize_panel->mAutoResize) - { - delta_auto_resize_headroom -= delta_panel_dim; - } - } - - F32 fraction_given_up = 0.f; - F32 fraction_remaining = 1.f; - F32 new_auto_resize_headroom = old_auto_resize_headroom + delta_auto_resize_headroom; - - enum - { - BEFORE_RESIZED_PANEL, - RESIZED_PANEL, - NEXT_PANEL, - AFTER_RESIZED_PANEL - } which_panel = BEFORE_RESIZED_PANEL; - - for (LLLayoutPanel* panelp : mPanels) - { - if (!panelp->getVisible() || panelp->mCollapsed) - { - if (panelp->mAutoResize) - { - fraction_remaining -= panelp->mFractionalSize; - } - continue; - } - - if (panelp == resized_panel) - { - which_panel = RESIZED_PANEL; - } - - switch(which_panel) - { - case BEFORE_RESIZED_PANEL: - if (panelp->mAutoResize) - { // freeze current size as fraction of overall auto_resize space - F32 fractional_adjustment_factor = new_auto_resize_headroom == 0.f - ? 1.f - : old_auto_resize_headroom / new_auto_resize_headroom; - F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, - MIN_FRACTIONAL_SIZE, - MAX_FRACTIONAL_SIZE); - fraction_given_up -= new_fractional_size - panelp->mFractionalSize; - fraction_remaining -= panelp->mFractionalSize; - panelp->mFractionalSize = new_fractional_size; - llassert(!llisnan(panelp->mFractionalSize)); - } - else - { - // leave non auto-resize panels alone - } - break; - case RESIZED_PANEL: - if (panelp->mAutoResize) - { // freeze new size as fraction - F32 new_fractional_size = (new_auto_resize_headroom == 0.f) - ? MAX_FRACTIONAL_SIZE - : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); - fraction_given_up -= new_fractional_size - panelp->mFractionalSize; - fraction_remaining -= panelp->mFractionalSize; - panelp->mFractionalSize = new_fractional_size; - llassert(!llisnan(panelp->mFractionalSize)); - } - else - { // freeze new size as original size - panelp->mTargetDim = new_dim; - } - which_panel = NEXT_PANEL; - break; - case NEXT_PANEL: - if (panelp->mAutoResize) - { - fraction_remaining -= panelp->mFractionalSize; - if (resized_panel->mAutoResize) - { - panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); - fraction_given_up = 0.f; - } - else - { - if (new_auto_resize_headroom < 1.f) - { - new_auto_resize_headroom = 1.f; - } - - F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) - / new_auto_resize_headroom, - MIN_FRACTIONAL_SIZE, - MAX_FRACTIONAL_SIZE); - fraction_given_up -= new_fractional_size - panelp->mFractionalSize; - panelp->mFractionalSize = new_fractional_size; - } - } - else - { - panelp->mTargetDim -= delta_panel_dim; - } - which_panel = AFTER_RESIZED_PANEL; - break; - case AFTER_RESIZED_PANEL: - if (panelp->mAutoResize && fraction_given_up != 0.f) - { - panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up, - MIN_FRACTIONAL_SIZE, - MAX_FRACTIONAL_SIZE); - } - break; - default: - break; - } - } - updateLayout(); - //normalizeFractionalSizes(); + S32 new_dim = (mOrientation == HORIZONTAL) + ? new_rect.getWidth() + : new_rect.getHeight(); + S32 delta_panel_dim = new_dim - resized_panel->getVisibleDim(); + if (delta_panel_dim == 0) return; + + F32 total_visible_fraction = 0.f; + F32 delta_auto_resize_headroom = 0.f; + F32 old_auto_resize_headroom = 0.f; + + LLLayoutPanel* other_resize_panel = NULL; + LLLayoutPanel* following_panel = NULL; + + BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) // Should replace this when C++20 reverse view adaptor becomes available... + { + if (panelp->mAutoResize) + { + old_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); + if (panelp->getVisible() && !panelp->mCollapsed) + { + total_visible_fraction += panelp->mFractionalSize; + } + } + + if (panelp == resized_panel) + { + other_resize_panel = following_panel; + } + + if (panelp->getVisible() && !panelp->mCollapsed) + { + following_panel = panelp; + } + } + + if (resized_panel->mAutoResize) + { + if (!other_resize_panel || !other_resize_panel->mAutoResize) + { + delta_auto_resize_headroom += delta_panel_dim; + } + } + else + { + if (!other_resize_panel || other_resize_panel->mAutoResize) + { + delta_auto_resize_headroom -= delta_panel_dim; + } + } + + F32 fraction_given_up = 0.f; + F32 fraction_remaining = 1.f; + F32 new_auto_resize_headroom = old_auto_resize_headroom + delta_auto_resize_headroom; + + enum + { + BEFORE_RESIZED_PANEL, + RESIZED_PANEL, + NEXT_PANEL, + AFTER_RESIZED_PANEL + } which_panel = BEFORE_RESIZED_PANEL; + + for (LLLayoutPanel* panelp : mPanels) + { + if (!panelp->getVisible() || panelp->mCollapsed) + { + if (panelp->mAutoResize) + { + fraction_remaining -= panelp->mFractionalSize; + } + continue; + } + + if (panelp == resized_panel) + { + which_panel = RESIZED_PANEL; + } + + switch(which_panel) + { + case BEFORE_RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze current size as fraction of overall auto_resize space + F32 fractional_adjustment_factor = new_auto_resize_headroom == 0.f + ? 1.f + : old_auto_resize_headroom / new_auto_resize_headroom; + F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + llassert(!llisnan(panelp->mFractionalSize)); + } + else + { + // leave non auto-resize panels alone + } + break; + case RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze new size as fraction + F32 new_fractional_size = (new_auto_resize_headroom == 0.f) + ? MAX_FRACTIONAL_SIZE + : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + llassert(!llisnan(panelp->mFractionalSize)); + } + else + { // freeze new size as original size + panelp->mTargetDim = new_dim; + } + which_panel = NEXT_PANEL; + break; + case NEXT_PANEL: + if (panelp->mAutoResize) + { + fraction_remaining -= panelp->mFractionalSize; + if (resized_panel->mAutoResize) + { + panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + fraction_given_up = 0.f; + } + else + { + if (new_auto_resize_headroom < 1.f) + { + new_auto_resize_headroom = 1.f; + } + + F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) + / new_auto_resize_headroom, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + } + } + else + { + panelp->mTargetDim -= delta_panel_dim; + } + which_panel = AFTER_RESIZED_PANEL; + break; + case AFTER_RESIZED_PANEL: + if (panelp->mAutoResize && fraction_given_up != 0.f) + { + panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); + } + break; + default: + break; + } + } + updateLayout(); + //normalizeFractionalSizes(); } void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) { - mNeedsLayout = true; - LLView::reshape(width, height, called_from_parent); + mNeedsLayout = true; + LLView::reshape(width, height, called_from_parent); } void LLLayoutStack::updateResizeBarLimits() { - LLLayoutPanel* previous_visible_panelp{ nullptr }; - BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels) // Should replace this when C++20 reverse view adaptor becomes available... - { - if (!visible_panelp->getVisible() || visible_panelp->mCollapsed) - { - visible_panelp->mResizeBar->setVisible(FALSE); - continue; - } - - // toggle resize bars based on panel visibility, resizability, etc - if (previous_visible_panelp - && (visible_panelp->mUserResize || previous_visible_panelp->mUserResize) // one of the pair is user resizable - && (visible_panelp->mAutoResize || visible_panelp->mUserResize) // current panel is resizable - && (previous_visible_panelp->mAutoResize || previous_visible_panelp->mUserResize)) // previous panel is resizable - { - visible_panelp->mResizeBar->setVisible(TRUE); - S32 previous_panel_headroom = previous_visible_panelp->getVisibleDim() - previous_visible_panelp->getRelevantMinDim(); - visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), - visible_panelp->getVisibleDim() + previous_panel_headroom); - } - else - { - visible_panelp->mResizeBar->setVisible(FALSE); - } - - previous_visible_panelp = visible_panelp; - } + LLLayoutPanel* previous_visible_panelp{ nullptr }; + BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels) // Should replace this when C++20 reverse view adaptor becomes available... + { + if (!visible_panelp->getVisible() || visible_panelp->mCollapsed) + { + visible_panelp->mResizeBar->setVisible(FALSE); + continue; + } + + // toggle resize bars based on panel visibility, resizability, etc + if (previous_visible_panelp + && (visible_panelp->mUserResize || previous_visible_panelp->mUserResize) // one of the pair is user resizable + && (visible_panelp->mAutoResize || visible_panelp->mUserResize) // current panel is resizable + && (previous_visible_panelp->mAutoResize || previous_visible_panelp->mUserResize)) // previous panel is resizable + { + visible_panelp->mResizeBar->setVisible(TRUE); + S32 previous_panel_headroom = previous_visible_panelp->getVisibleDim() - previous_visible_panelp->getRelevantMinDim(); + visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), + visible_panelp->getVisibleDim() + previous_panel_headroom); + } + else + { + visible_panelp->mResizeBar->setVisible(FALSE); + } + + previous_visible_panelp = visible_panelp; + } } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 000b919ae7..884850285a 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -1,4 +1,4 @@ -/** +/** * @file lllayoutstack.h * @author Richard Nelson * @brief LLLayout class - dynamic stacking of UI elements @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Reshasearch, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,98 +39,98 @@ class LLLayoutStack : public LLView, public LLInstanceTracker { public: - struct LayoutStackRegistry : public LLChildRegistry - { - LLSINGLETON_EMPTY_CTOR(LayoutStackRegistry); - }; - - struct Params : public LLInitParam::Block - { - Mandatory orientation; - Optional border_size; - Optional animate, - clip; - Optional open_time_constant, - close_time_constant; - Optional resize_bar_overlap; - Optional show_drag_handle; - Optional drag_handle_first_indent; - Optional drag_handle_second_indent; - Optional drag_handle_thickness; - Optional drag_handle_shift; + struct LayoutStackRegistry : public LLChildRegistry + { + LLSINGLETON_EMPTY_CTOR(LayoutStackRegistry); + }; + + struct Params : public LLInitParam::Block + { + Mandatory orientation; + Optional border_size; + Optional animate, + clip; + Optional open_time_constant, + close_time_constant; + Optional resize_bar_overlap; + Optional show_drag_handle; + Optional drag_handle_first_indent; + Optional drag_handle_second_indent; + Optional drag_handle_thickness; + Optional drag_handle_shift; Optional drag_handle_color; - Params(); - }; + Params(); + }; - typedef LayoutStackRegistry child_registry_t; + typedef LayoutStackRegistry child_registry_t; - virtual ~LLLayoutStack(); + virtual ~LLLayoutStack(); - /*virtual*/ void draw(); + /*virtual*/ void draw(); /*virtual*/ void deleteAllChildren(); - /*virtual*/ void removeChild(LLView*); - /*virtual*/ BOOL postBuild(); - /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void removeChild(LLView*); + /*virtual*/ BOOL postBuild(); + /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - typedef enum e_animate - { - NO_ANIMATE, - ANIMATE - } EAnimate; + typedef enum e_animate + { + NO_ANIMATE, + ANIMATE + } EAnimate; - void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); - void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE); - S32 getNumPanels() { return mPanels.size(); } + void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); + void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE); + S32 getNumPanels() { return mPanels.size(); } - void updateLayout(); + void updateLayout(); - S32 getPanelSpacing() const { return mPanelSpacing; } + S32 getPanelSpacing() const { return mPanelSpacing; } void setPanelSpacing(S32 val); - - static void updateClass(); + + static void updateClass(); protected: - LLLayoutStack(const Params&); - friend class LLUICtrlFactory; - friend class LLLayoutPanel; + LLLayoutStack(const Params&); + friend class LLUICtrlFactory; + friend class LLLayoutPanel; private: - void updateResizeBarLimits(); - bool animatePanels(); - void createResizeBar(LLLayoutPanel* panel); - - const EOrientation mOrientation; - - typedef std::vector e_panel_list_t; - e_panel_list_t mPanels; - - LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const; - LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; - void updateFractionalSizes(); - void normalizeFractionalSizes(); - void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); - - S32 mPanelSpacing; - - // true if we already applied animation this frame - bool mAnimatedThisFrame; - bool mAnimate; - bool mClip; - F32 mOpenTimeConstant; - F32 mCloseTimeConstant; - bool mNeedsLayout; - S32 mResizeBarOverlap; - bool mShowDragHandle; - S32 mDragHandleFirstIndent; - S32 mDragHandleSecondIndent; - S32 mDragHandleThickness; - S32 mDragHandleShift; + void updateResizeBarLimits(); + bool animatePanels(); + void createResizeBar(LLLayoutPanel* panel); + + const EOrientation mOrientation; + + typedef std::vector e_panel_list_t; + e_panel_list_t mPanels; + + LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const; + LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; + void updateFractionalSizes(); + void normalizeFractionalSizes(); + void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); + + S32 mPanelSpacing; + + // true if we already applied animation this frame + bool mAnimatedThisFrame; + bool mAnimate; + bool mClip; + F32 mOpenTimeConstant; + F32 mCloseTimeConstant; + bool mNeedsLayout; + S32 mResizeBarOverlap; + bool mShowDragHandle; + S32 mDragHandleFirstIndent; + S32 mDragHandleSecondIndent; + S32 mDragHandleThickness; + S32 mDragHandleShift; LLUIColor mDragHandleColor; }; // end class LLLayoutStack @@ -140,76 +140,76 @@ class LLLayoutPanel : public LLPanel friend class LLLayoutStack; friend class LLUICtrlFactory; public: - struct Params : public LLInitParam::Block - { - Optional expanded_min_dim, - min_dim; - Optional user_resize, - auto_resize; + struct Params : public LLInitParam::Block + { + Optional expanded_min_dim, + min_dim; + Optional user_resize, + auto_resize; + + Params(); + }; + + ~LLLayoutPanel(); + + void initFromParams(const Params& p); + + void handleReshape(const LLRect& new_rect, bool by_user); - Params(); - }; + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - ~LLLayoutPanel(); - void initFromParams(const Params& p); + void setVisible(BOOL visible); - void handleReshape(const LLRect& new_rect, bool by_user); + S32 getLayoutDim() const; + S32 getTargetDim() const; + void setTargetDim(S32 value); + S32 getMinDim() const { return llmax(0, mMinDim); } + void setMinDim(S32 value) { mMinDim = value; } - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - + S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); } + void setExpandedMinDim(S32 value) { mExpandedMinDim = value; } - void setVisible(BOOL visible); + S32 getRelevantMinDim() const + { + S32 min_dim = mMinDim; - S32 getLayoutDim() const; - S32 getTargetDim() const; - void setTargetDim(S32 value); - S32 getMinDim() const { return llmax(0, mMinDim); } - void setMinDim(S32 value) { mMinDim = value; } + if (!mCollapsed) + { + min_dim = getExpandedMinDim(); + } - S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); } - void setExpandedMinDim(S32 value) { mExpandedMinDim = value; } - - S32 getRelevantMinDim() const - { - S32 min_dim = mMinDim; - - if (!mCollapsed) - { - min_dim = getExpandedMinDim(); - } - - return min_dim; - } + return min_dim; + } - F32 getAutoResizeFactor() const; - F32 getVisibleAmount() const; - S32 getVisibleDim() const; - LLResizeBar* getResizeBar() { return mResizeBar; } + F32 getAutoResizeFactor() const; + F32 getVisibleAmount() const; + S32 getVisibleDim() const; + LLResizeBar* getResizeBar() { return mResizeBar; } - bool isCollapsed() const { return mCollapsed;} + bool isCollapsed() const { return mCollapsed;} - void setOrientation(LLView::EOrientation orientation); - void storeOriginalDim(); + void setOrientation(LLView::EOrientation orientation); + void storeOriginalDim(); - void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } + void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } protected: - LLLayoutPanel(const Params& p); - - const bool mAutoResize; - const bool mUserResize; - - S32 mExpandedMinDim; - S32 mMinDim; - bool mCollapsed; - F32 mVisibleAmt; - F32 mCollapseAmt; - F32 mFractionalSize; - S32 mTargetDim; - bool mIgnoreReshape; - LLView::EOrientation mOrientation; - class LLResizeBar* mResizeBar; + LLLayoutPanel(const Params& p); + + const bool mAutoResize; + const bool mUserResize; + + S32 mExpandedMinDim; + S32 mMinDim; + bool mCollapsed; + F32 mVisibleAmt; + F32 mCollapseAmt; + F32 mFractionalSize; + S32 mTargetDim; + bool mIgnoreReshape; + LLView::EOrientation mOrientation; + class LLResizeBar* mResizeBar; }; diff --git a/indra/llui/lllazyvalue.h b/indra/llui/lllazyvalue.h index 0fc95d9efa..622e69ce95 100644 --- a/indra/llui/lllazyvalue.h +++ b/indra/llui/lllazyvalue.h @@ -1,4 +1,4 @@ -/** +/** * @file lllazyvalue.h * @brief generic functor/value abstraction for lazy evaluation of a value * parsing construction parameters from xml and LLSD @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,48 +35,48 @@ template class LLLazyValue { public: - typedef typename boost::add_reference::type>::type T_const_ref; - typedef typename boost::function function_type; + typedef typename boost::add_reference::type>::type T_const_ref; + typedef typename boost::function function_type; public: - LLLazyValue(const function_type& value) - : mValueGetter(value) - {} - LLLazyValue(T_const_ref value) - : mValue(value) - {} - LLLazyValue() - : mValue() - {} + LLLazyValue(const function_type& value) + : mValueGetter(value) + {} + LLLazyValue(T_const_ref value) + : mValue(value) + {} + LLLazyValue() + : mValue() + {} - void set(const LLLazyValue& val) - { - mValueGetter = val.mValueGetter; - } + void set(const LLLazyValue& val) + { + mValueGetter = val.mValueGetter; + } - void set(T_const_ref val) - { - mValue = val; - mValueGetter = NULL; - } + void set(T_const_ref val) + { + mValue = val; + mValueGetter = NULL; + } - T_const_ref get() const - { - if (!mValueGetter.empty()) - { - return mValueGetter(); - } - return mValue; - } + T_const_ref get() const + { + if (!mValueGetter.empty()) + { + return mValueGetter(); + } + return mValue; + } - bool isUsingFunction() const - { - return mValueGetter != NULL; - } + bool isUsingFunction() const + { + return mValueGetter != NULL; + } private: - function_type mValueGetter; - T mValue; + function_type mValueGetter; + T mValue; }; #endif // LL_LAZY_VALUE_H diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 453fa29e7c..eefba0d186 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lllineeditor.cpp * @brief LLLineEditor base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -27,7 +27,7 @@ // Text editor widget to let users enter a single line. #include "linden_common.h" - + #define LLLINEEDITOR_CPP #include "lllineeditor.h" @@ -61,12 +61,12 @@ // Constants // -const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds -const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing -const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing +const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds +const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing +const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing const F32 AUTO_SCROLL_TIME = 0.05f; -const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? -const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on +const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET @@ -74,109 +74,109 @@ static LLDefaultChildRegistry::Register r1("line_editor"); // Compiler optimization, generate extern template template class LLLineEditor* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; // // Member functions // LLLineEditor::Params::Params() -: max_length(""), +: max_length(""), keystroke_callback("keystroke_callback"), - prevalidate_callback("prevalidate_callback"), - prevalidate_input_callback("prevalidate_input_callback"), - background_image("background_image"), - background_image_disabled("background_image_disabled"), - background_image_focused("background_image_focused"), - bg_image_always_focused("bg_image_always_focused", false), - show_label_focused("show_label_focused", false), - select_on_focus("select_on_focus", false), - revert_on_esc("revert_on_esc", true), - spellcheck("spellcheck", false), - commit_on_focus_lost("commit_on_focus_lost", true), - ignore_tab("ignore_tab", true), - is_password("is_password", false), - cursor_color("cursor_color"), - use_bg_color("use_bg_color", false), - bg_color("bg_color"), - text_color("text_color"), - text_readonly_color("text_readonly_color"), - text_tentative_color("text_tentative_color"), - highlight_color("highlight_color"), - preedit_bg_color("preedit_bg_color"), - border(""), - bg_visible("bg_visible"), - text_pad_left("text_pad_left"), - text_pad_right("text_pad_right"), - default_text("default_text") -{ - changeDefault(mouse_opaque, true); - addSynonym(select_on_focus, "select_all_on_focus_received"); - addSynonym(border, "border"); - addSynonym(label, "watermark_text"); - addSynonym(max_length.chars, "max_length"); + prevalidate_callback("prevalidate_callback"), + prevalidate_input_callback("prevalidate_input_callback"), + background_image("background_image"), + background_image_disabled("background_image_disabled"), + background_image_focused("background_image_focused"), + bg_image_always_focused("bg_image_always_focused", false), + show_label_focused("show_label_focused", false), + select_on_focus("select_on_focus", false), + revert_on_esc("revert_on_esc", true), + spellcheck("spellcheck", false), + commit_on_focus_lost("commit_on_focus_lost", true), + ignore_tab("ignore_tab", true), + is_password("is_password", false), + cursor_color("cursor_color"), + use_bg_color("use_bg_color", false), + bg_color("bg_color"), + text_color("text_color"), + text_readonly_color("text_readonly_color"), + text_tentative_color("text_tentative_color"), + highlight_color("highlight_color"), + preedit_bg_color("preedit_bg_color"), + border(""), + bg_visible("bg_visible"), + text_pad_left("text_pad_left"), + text_pad_right("text_pad_right"), + default_text("default_text") +{ + changeDefault(mouse_opaque, true); + addSynonym(select_on_focus, "select_all_on_focus_received"); + addSynonym(border, "border"); + addSynonym(label, "watermark_text"); + addSynonym(max_length.chars, "max_length"); } LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) -: LLUICtrl(p), - mMaxLengthBytes(p.max_length.bytes), - mMaxLengthChars(p.max_length.chars), - mCursorPos( 0 ), - mScrollHPos( 0 ), - mTextPadLeft(p.text_pad_left), - mTextPadRight(p.text_pad_right), - mTextLeftEdge(0), // computed in updateTextPadding() below - mTextRightEdge(0), // computed in updateTextPadding() below - mCommitOnFocusLost( p.commit_on_focus_lost ), - mKeystrokeOnEsc(FALSE), - mRevertOnEsc( p.revert_on_esc ), - mKeystrokeCallback( p.keystroke_callback() ), - mIsSelecting( FALSE ), - mSelectionStart( 0 ), - mSelectionEnd( 0 ), - mLastSelectionX(-1), - mLastSelectionY(-1), - mLastSelectionStart(-1), - mLastSelectionEnd(-1), - mBorderThickness( 0 ), - mIgnoreArrowKeys( FALSE ), - mIgnoreTab( p.ignore_tab ), - mDrawAsterixes( p.is_password ), - mSpellCheck( p.spellcheck ), - mSpellCheckStart(-1), - mSpellCheckEnd(-1), - mSelectAllonFocusReceived( p.select_on_focus ), - mSelectAllonCommit( TRUE ), - mPassDelete(FALSE), - mReadOnly(FALSE), - mBgImage( p.background_image ), - mBgImageDisabled( p.background_image_disabled ), - mBgImageFocused( p.background_image_focused ), - mShowImageFocused( p.bg_image_always_focused ), - mShowLabelFocused( p.show_label_focused ), - mUseBgColor(p.use_bg_color), - mHaveHistory(FALSE), - mReplaceNewlinesWithSpaces( TRUE ), - mLabel(p.label), - mCursorColor(p.cursor_color()), - mBgColor(p.bg_color()), - mFgColor(p.text_color()), - mReadOnlyFgColor(p.text_readonly_color()), - mTentativeFgColor(p.text_tentative_color()), - mHighlightColor(p.highlight_color()), - mPreeditBgColor(p.preedit_bg_color()), - mGLFont(p.font), - mContextMenuHandle(), +: LLUICtrl(p), + mMaxLengthBytes(p.max_length.bytes), + mMaxLengthChars(p.max_length.chars), + mCursorPos( 0 ), + mScrollHPos( 0 ), + mTextPadLeft(p.text_pad_left), + mTextPadRight(p.text_pad_right), + mTextLeftEdge(0), // computed in updateTextPadding() below + mTextRightEdge(0), // computed in updateTextPadding() below + mCommitOnFocusLost( p.commit_on_focus_lost ), + mKeystrokeOnEsc(FALSE), + mRevertOnEsc( p.revert_on_esc ), + mKeystrokeCallback( p.keystroke_callback() ), + mIsSelecting( FALSE ), + mSelectionStart( 0 ), + mSelectionEnd( 0 ), + mLastSelectionX(-1), + mLastSelectionY(-1), + mLastSelectionStart(-1), + mLastSelectionEnd(-1), + mBorderThickness( 0 ), + mIgnoreArrowKeys( FALSE ), + mIgnoreTab( p.ignore_tab ), + mDrawAsterixes( p.is_password ), + mSpellCheck( p.spellcheck ), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), + mSelectAllonFocusReceived( p.select_on_focus ), + mSelectAllonCommit( TRUE ), + mPassDelete(FALSE), + mReadOnly(FALSE), + mBgImage( p.background_image ), + mBgImageDisabled( p.background_image_disabled ), + mBgImageFocused( p.background_image_focused ), + mShowImageFocused( p.bg_image_always_focused ), + mShowLabelFocused( p.show_label_focused ), + mUseBgColor(p.use_bg_color), + mHaveHistory(FALSE), + mReplaceNewlinesWithSpaces( TRUE ), + mLabel(p.label), + mCursorColor(p.cursor_color()), + mBgColor(p.bg_color()), + mFgColor(p.text_color()), + mReadOnlyFgColor(p.text_readonly_color()), + mTentativeFgColor(p.text_tentative_color()), + mHighlightColor(p.highlight_color()), + mPreeditBgColor(p.preedit_bg_color()), + mGLFont(p.font), + mContextMenuHandle(), mShowContextMenu(true) { - llassert( mMaxLengthBytes > 0 ); + llassert( mMaxLengthBytes > 0 ); - LLUICtrl::setEnabled(TRUE); - setEnabled(p.enabled); + LLUICtrl::setEnabled(TRUE); + setEnabled(p.enabled); - mScrollTimer.reset(); - mTripleClickTimer.reset(); - setText(p.default_text()); + mScrollTimer.reset(); + mTripleClickTimer.reset(); + setText(p.default_text()); if (p.initial_value.isProvided() && !p.control_name.isProvided()) @@ -186,209 +186,209 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) setText(p.initial_value.getValue().asString(), false); } - // Initialize current history line iterator - mCurrentHistoryLine = mLineHistory.begin(); - - LLRect border_rect(getLocalRect()); - // adjust for gl line drawing glitch - border_rect.mTop -= 1; - border_rect.mRight -=1; - LLViewBorder::Params border_p(p.border); - border_p.rect = border_rect; - border_p.follows.flags = FOLLOWS_ALL; - border_p.bevel_style = LLViewBorder::BEVEL_IN; - mBorder = LLUICtrlFactory::create(border_p); - addChild( mBorder ); - - // clamp text padding to current editor size - updateTextPadding(); - setCursor(mText.length()); - - if (mSpellCheck) - { - LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLLineEditor::onSpellCheckSettingsChange, this)); - } - mSpellCheckTimer.reset(); + // Initialize current history line iterator + mCurrentHistoryLine = mLineHistory.begin(); + + LLRect border_rect(getLocalRect()); + // adjust for gl line drawing glitch + border_rect.mTop -= 1; + border_rect.mRight -=1; + LLViewBorder::Params border_p(p.border); + border_p.rect = border_rect; + border_p.follows.flags = FOLLOWS_ALL; + border_p.bevel_style = LLViewBorder::BEVEL_IN; + mBorder = LLUICtrlFactory::create(border_p); + addChild( mBorder ); + + // clamp text padding to current editor size + updateTextPadding(); + setCursor(mText.length()); + + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLLineEditor::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); - setPrevalidateInput(p.prevalidate_input_callback()); - setPrevalidate(p.prevalidate_callback()); + setPrevalidateInput(p.prevalidate_input_callback()); + setPrevalidate(p.prevalidate_callback()); } - + LLLineEditor::~LLLineEditor() { - mCommitOnFocusLost = FALSE; - + mCommitOnFocusLost = FALSE; + // Make sure no context menu linger around once the widget is deleted - LLContextMenu* menu = static_cast(mContextMenuHandle.get()); - if (menu) - { + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (menu) + { menu->hide(); } - setContextMenu(NULL); + setContextMenu(NULL); - // calls onCommit() while LLLineEditor still valid - gFocusMgr.releaseFocusIfNeeded( this ); + // calls onCommit() while LLLineEditor still valid + gFocusMgr.releaseFocusIfNeeded( this ); } void LLLineEditor::initFromParams(const LLLineEditor::Params& params) { - LLUICtrl::initFromParams(params); - LLUICtrl::setEnabled(TRUE); - setEnabled(params.enabled); + LLUICtrl::initFromParams(params); + LLUICtrl::setEnabled(TRUE); + setEnabled(params.enabled); } void LLLineEditor::onFocusReceived() { - gEditMenuHandler = this; - LLUICtrl::onFocusReceived(); - updateAllowingLanguageInput(); + gEditMenuHandler = this; + LLUICtrl::onFocusReceived(); + updateAllowingLanguageInput(); } void LLLineEditor::onFocusLost() { - // The call to updateAllowLanguageInput() - // when loosing the keyboard focus *may* - // indirectly invoke handleUnicodeCharHere(), - // so it must be called before onCommit. - updateAllowingLanguageInput(); + // The call to updateAllowLanguageInput() + // when loosing the keyboard focus *may* + // indirectly invoke handleUnicodeCharHere(), + // so it must be called before onCommit. + updateAllowingLanguageInput(); - if( mCommitOnFocusLost && mText.getString() != mPrevText) - { - onCommit(); - } + if( mCommitOnFocusLost && mText.getString() != mPrevText) + { + onCommit(); + } - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } + if( gEditMenuHandler == this ) + { + gEditMenuHandler = NULL; + } - getWindow()->showCursorFromMouseMove(); + getWindow()->showCursorFromMouseMove(); - LLUICtrl::onFocusLost(); + LLUICtrl::onFocusLost(); } // virtual void LLLineEditor::onCommit() { - // put current line into the line history - updateHistory(); + // put current line into the line history + updateHistory(); - setControlValue(getValue()); - LLUICtrl::onCommit(); - resetDirty(); + setControlValue(getValue()); + LLUICtrl::onCommit(); + resetDirty(); - // Selection on commit needs to be turned off when evaluating maths - // expressions, to allow indication of the error position - if (mSelectAllonCommit) selectAll(); + // Selection on commit needs to be turned off when evaluating maths + // expressions, to allow indication of the error position + if (mSelectAllonCommit) selectAll(); } // Returns TRUE if user changed value at all // virtual BOOL LLLineEditor::isDirty() const { - return mText.getString() != mPrevText; + return mText.getString() != mPrevText; } // Clear dirty state // virtual void LLLineEditor::resetDirty() { - mPrevText = mText.getString(); -} + mPrevText = mText.getString(); +} // assumes UTF8 text // virtual void LLLineEditor::setValue(const LLSD& value ) { - setText(value.asString()); + setText(value.asString()); } //virtual LLSD LLLineEditor::getValue() const { - return LLSD(getText()); + return LLSD(getText()); } // line history support void LLLineEditor::updateHistory() { - // On history enabled line editors, remember committed line and - // reset current history line number. - // Be sure only to remember lines that are not empty and that are - // different from the last on the list. - if( mHaveHistory && getLength() ) - { - if( !mLineHistory.empty() ) - { - // When not empty, last line of history should always be blank. - if( mLineHistory.back().empty() ) - { - // discard the empty line - mLineHistory.pop_back(); - } - else - { - LL_WARNS("") << "Last line of history was not blank." << LL_ENDL; - } - } - - // Add text to history, ignoring duplicates - if( mLineHistory.empty() || getText() != mLineHistory.back() ) - { - mLineHistory.push_back( getText() ); - } - - // Restore the blank line and set mCurrentHistoryLine to point at it - mLineHistory.push_back( "" ); - mCurrentHistoryLine = mLineHistory.end() - 1; - } + // On history enabled line editors, remember committed line and + // reset current history line number. + // Be sure only to remember lines that are not empty and that are + // different from the last on the list. + if( mHaveHistory && getLength() ) + { + if( !mLineHistory.empty() ) + { + // When not empty, last line of history should always be blank. + if( mLineHistory.back().empty() ) + { + // discard the empty line + mLineHistory.pop_back(); + } + else + { + LL_WARNS("") << "Last line of history was not blank." << LL_ENDL; + } + } + + // Add text to history, ignoring duplicates + if( mLineHistory.empty() || getText() != mLineHistory.back() ) + { + mLineHistory.push_back( getText() ); + } + + // Restore the blank line and set mCurrentHistoryLine to point at it + mLineHistory.push_back( "" ); + mCurrentHistoryLine = mLineHistory.end() - 1; + } } void LLLineEditor::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLUICtrl::reshape(width, height, called_from_parent); - updateTextPadding(); // For clamping side-effect. - setCursor(mCursorPos); // For clamping side-effect. + LLUICtrl::reshape(width, height, called_from_parent); + updateTextPadding(); // For clamping side-effect. + setCursor(mCursorPos); // For clamping side-effect. } void LLLineEditor::setEnabled(BOOL enabled) { - mReadOnly = !enabled; - setTabStop(!mReadOnly); - updateAllowingLanguageInput(); + mReadOnly = !enabled; + setTabStop(!mReadOnly); + updateAllowingLanguageInput(); } void LLLineEditor::setMaxTextLength(S32 max_text_length) { - S32 max_len = llmax(0, max_text_length); - mMaxLengthBytes = max_len; -} + S32 max_len = llmax(0, max_text_length); + mMaxLengthBytes = max_len; +} void LLLineEditor::setMaxTextChars(S32 max_text_chars) { - S32 max_chars = llmax(0, max_text_chars); - mMaxLengthChars = max_chars; -} + S32 max_chars = llmax(0, max_text_chars); + mMaxLengthChars = max_chars; +} void LLLineEditor::getTextPadding(S32 *left, S32 *right) { - *left = mTextPadLeft; - *right = mTextPadRight; + *left = mTextPadLeft; + *right = mTextPadRight; } void LLLineEditor::setTextPadding(S32 left, S32 right) { - mTextPadLeft = left; - mTextPadRight = right; - updateTextPadding(); + mTextPadLeft = left; + mTextPadRight = right; + updateTextPadding(); } void LLLineEditor::updateTextPadding() { - mTextLeftEdge = llclamp(mTextPadLeft, 0, getRect().getWidth()); - mTextRightEdge = getRect().getWidth() - llclamp(mTextPadRight, 0, getRect().getWidth()); + mTextLeftEdge = llclamp(mTextPadLeft, 0, getRect().getWidth()); + mTextRightEdge = getRect().getWidth() - llclamp(mTextPadRight, 0, getRect().getWidth()); } @@ -399,1347 +399,1347 @@ void LLLineEditor::setText(const LLStringExplicit &new_text) void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit) { - // If new text is identical, don't copy and don't move insertion point - if (mText.getString() == new_text) - { - return; - } - - // Check to see if entire field is selected. - S32 len = mText.length(); - BOOL all_selected = (len > 0) - && (( mSelectionStart == 0 && mSelectionEnd == len ) - || ( mSelectionStart == len && mSelectionEnd == 0 )); - - // Do safe truncation so we don't split multi-byte characters - // also consider entire string selected when mSelectAllonFocusReceived is set on an empty, focused line editor - all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived); - - std::string truncated_utf8 = new_text; - if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) - { - truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes); - } - mText.assign(truncated_utf8); - - if (use_size_limit && mMaxLengthChars) - { - mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars)); - } - - if (all_selected) - { - // ...keep whole thing selected - selectAll(); - } - else - { - // try to preserve insertion point, but deselect text - deselect(); - } - setCursor(llmin((S32)mText.length(), getCursor())); - - // Set current history line to end of history. - if (mLineHistory.empty()) - { - mCurrentHistoryLine = mLineHistory.end(); - } - else - { - mCurrentHistoryLine = mLineHistory.end() - 1; - } - - mPrevText = mText; + // If new text is identical, don't copy and don't move insertion point + if (mText.getString() == new_text) + { + return; + } + + // Check to see if entire field is selected. + S32 len = mText.length(); + BOOL all_selected = (len > 0) + && (( mSelectionStart == 0 && mSelectionEnd == len ) + || ( mSelectionStart == len && mSelectionEnd == 0 )); + + // Do safe truncation so we don't split multi-byte characters + // also consider entire string selected when mSelectAllonFocusReceived is set on an empty, focused line editor + all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived); + + std::string truncated_utf8 = new_text; + if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) + { + truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes); + } + mText.assign(truncated_utf8); + + if (use_size_limit && mMaxLengthChars) + { + mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars)); + } + + if (all_selected) + { + // ...keep whole thing selected + selectAll(); + } + else + { + // try to preserve insertion point, but deselect text + deselect(); + } + setCursor(llmin((S32)mText.length(), getCursor())); + + // Set current history line to end of history. + if (mLineHistory.empty()) + { + mCurrentHistoryLine = mLineHistory.end(); + } + else + { + mCurrentHistoryLine = mLineHistory.end() - 1; + } + + mPrevText = mText; } // Picks a new cursor position based on the actual screen size of text being drawn. void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x ) { - S32 cursor_pos = calcCursorPos(local_mouse_x); + S32 cursor_pos = calcCursorPos(local_mouse_x); - S32 left_pos = llmin( mSelectionStart, cursor_pos ); - S32 length = llabs( mSelectionStart - cursor_pos ); - const LLWString& substr = mText.getWString().substr(left_pos, length); + S32 left_pos = llmin( mSelectionStart, cursor_pos ); + S32 length = llabs( mSelectionStart - cursor_pos ); + const LLWString& substr = mText.getWString().substr(left_pos, length); - if (mIsSelecting && !prevalidateInput(substr)) - return; + if (mIsSelecting && !prevalidateInput(substr)) + return; - setCursor(cursor_pos); + setCursor(cursor_pos); } void LLLineEditor::setCursor( S32 pos ) { - S32 old_cursor_pos = getCursor(); - mCursorPos = llclamp( pos, 0, mText.length()); - - // position of end of next character after cursor - S32 pixels_after_scroll = findPixelNearestPos(); - if( pixels_after_scroll > mTextRightEdge ) - { - S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); - S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left))); - // character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters) - // or first character if cursor is at beginning - S32 new_last_visible_char = llmax(0, getCursor() - 1); - S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), new_last_visible_char); - if (old_cursor_pos == last_visible_char) - { - mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); - } - else - { - mScrollHPos = min_scroll; - } - } - else if (getCursor() < mScrollHPos) - { - if (old_cursor_pos == mScrollHPos) - { - mScrollHPos = llmax(0, llmin(getCursor(), mScrollHPos - SCROLL_INCREMENT_DEL)); - } - else - { - mScrollHPos = getCursor(); - } - } + S32 old_cursor_pos = getCursor(); + mCursorPos = llclamp( pos, 0, mText.length()); + + // position of end of next character after cursor + S32 pixels_after_scroll = findPixelNearestPos(); + if( pixels_after_scroll > mTextRightEdge ) + { + S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); + S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left))); + // character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters) + // or first character if cursor is at beginning + S32 new_last_visible_char = llmax(0, getCursor() - 1); + S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), new_last_visible_char); + if (old_cursor_pos == last_visible_char) + { + mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); + } + else + { + mScrollHPos = min_scroll; + } + } + else if (getCursor() < mScrollHPos) + { + if (old_cursor_pos == mScrollHPos) + { + mScrollHPos = llmax(0, llmin(getCursor(), mScrollHPos - SCROLL_INCREMENT_DEL)); + } + else + { + mScrollHPos = getCursor(); + } + } } void LLLineEditor::setCursorToEnd() { - setCursor(mText.length()); - deselect(); + setCursor(mText.length()); + deselect(); } void LLLineEditor::resetScrollPosition() { - mScrollHPos = 0; - // make sure cursor says in visible range - setCursor(getCursor()); + mScrollHPos = 0; + // make sure cursor says in visible range + setCursor(getCursor()); } BOOL LLLineEditor::canDeselect() const { - return hasSelection(); + return hasSelection(); } void LLLineEditor::deselect() { - mSelectionStart = 0; - mSelectionEnd = 0; - mIsSelecting = FALSE; + mSelectionStart = 0; + mSelectionEnd = 0; + mIsSelecting = FALSE; } void LLLineEditor::startSelection() { - mIsSelecting = TRUE; - mSelectionStart = getCursor(); - mSelectionEnd = getCursor(); + mIsSelecting = TRUE; + mSelectionStart = getCursor(); + mSelectionEnd = getCursor(); } void LLLineEditor::endSelection() { - if( mIsSelecting ) - { - mIsSelecting = FALSE; - mSelectionEnd = getCursor(); - } + if( mIsSelecting ) + { + mIsSelecting = FALSE; + mSelectionEnd = getCursor(); + } } BOOL LLLineEditor::canSelectAll() const { - return TRUE; + return TRUE; } void LLLineEditor::selectAll() { - if (!prevalidateInput(mText.getWString())) - { - return; - } + if (!prevalidateInput(mText.getWString())) + { + return; + } - mSelectionStart = mText.length(); - mSelectionEnd = 0; - setCursor(mSelectionEnd); - //mScrollHPos = 0; - mIsSelecting = TRUE; - updatePrimary(); + mSelectionStart = mText.length(); + mSelectionEnd = 0; + setCursor(mSelectionEnd); + //mScrollHPos = 0; + mIsSelecting = TRUE; + updatePrimary(); } bool LLLineEditor::getSpellCheck() const { - return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); } const std::string& LLLineEditor::getSuggestion(U32 index) const { - return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; } U32 LLLineEditor::getSuggestionCount() const { - return mSuggestionList.size(); + return mSuggestionList.size(); } void LLLineEditor::replaceWithSuggestion(U32 index) { - for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) - { - if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) - { - deselect(); + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); - // Delete the misspelled word - mText.erase(it->first, it->second - it->first); + // Delete the misspelled word + mText.erase(it->first, it->second - it->first); - // Insert the suggestion in its place - LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); - mText.insert(it->first, suggestion); - setCursor(it->first + (S32)suggestion.length()); + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + mText.insert(it->first, suggestion); + setCursor(it->first + (S32)suggestion.length()); - break; - } - } - mSpellCheckStart = mSpellCheckEnd = -1; + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; } void LLLineEditor::addToDictionary() { - if (canAddToDictionary()) - { - LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); - } + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } } bool LLLineEditor::canAddToDictionary() const { - return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); } void LLLineEditor::addToIgnore() { - if (canAddToIgnore()) - { - LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); - } + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } } bool LLLineEditor::canAddToIgnore() const { - return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); } std::string LLLineEditor::getMisspelledWord(U32 pos) const { - for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) - { - if ( (it->first <= pos) && (it->second >= pos) ) - { - return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); - } - } - return LLStringUtil::null; + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); + } + } + return LLStringUtil::null; } bool LLLineEditor::isMisspelledWord(U32 pos) const { - for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) - { - if ( (it->first <= pos) && (it->second >= pos) ) - { - return true; - } - } - return false; + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return true; + } + } + return false; } void LLLineEditor::onSpellCheckSettingsChange() { - // Recheck the spelling on every change - mMisspellRanges.clear(); - mSpellCheckStart = mSpellCheckEnd = -1; + // Recheck the spelling on every change + mMisspellRanges.clear(); + mSpellCheckStart = mSpellCheckEnd = -1; } BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { - setFocus( TRUE ); - mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); - - if (mSelectionEnd == 0 && mSelectionStart == mText.length()) - { - // if everything is selected, handle this as a normal click to change insertion point - handleMouseDown(x, y, mask); - } - else - { - const LLWString& wtext = mText.getWString(); - - BOOL doSelectAll = TRUE; - - // Select the word we're on - if( LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) - { - S32 old_selection_start = mLastSelectionStart; - S32 old_selection_end = mLastSelectionEnd; - - // Select word the cursor is over - while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[mCursorPos-1] )) - { // Find the start of the word - mCursorPos--; - } - startSelection(); - - while ((mCursorPos < (S32)wtext.length()) && LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) - { // Find the end of the word - mCursorPos++; - } - mSelectionEnd = mCursorPos; - - // If nothing changed, then the word was already selected. Select the whole line. - doSelectAll = (old_selection_start == mSelectionStart) && - (old_selection_end == mSelectionEnd); - } - - if ( doSelectAll ) - { // Select everything - selectAll(); - } - } - - // We don't want handleMouseUp() to "finish" the selection (and thereby - // set mSelectionEnd to where the mouse is), so we finish the selection - // here. - mIsSelecting = FALSE; - - // delay cursor flashing - mKeystrokeTimer.reset(); - - // take selection to 'primary' clipboard - updatePrimary(); - - return TRUE; + setFocus( TRUE ); + mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); + + if (mSelectionEnd == 0 && mSelectionStart == mText.length()) + { + // if everything is selected, handle this as a normal click to change insertion point + handleMouseDown(x, y, mask); + } + else + { + const LLWString& wtext = mText.getWString(); + + BOOL doSelectAll = TRUE; + + // Select the word we're on + if( LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) + { + S32 old_selection_start = mLastSelectionStart; + S32 old_selection_end = mLastSelectionEnd; + + // Select word the cursor is over + while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[mCursorPos-1] )) + { // Find the start of the word + mCursorPos--; + } + startSelection(); + + while ((mCursorPos < (S32)wtext.length()) && LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) + { // Find the end of the word + mCursorPos++; + } + mSelectionEnd = mCursorPos; + + // If nothing changed, then the word was already selected. Select the whole line. + doSelectAll = (old_selection_start == mSelectionStart) && + (old_selection_end == mSelectionEnd); + } + + if ( doSelectAll ) + { // Select everything + selectAll(); + } + } + + // We don't want handleMouseUp() to "finish" the selection (and thereby + // set mSelectionEnd to where the mouse is), so we finish the selection + // here. + mIsSelecting = FALSE; + + // delay cursor flashing + mKeystrokeTimer.reset(); + + // take selection to 'primary' clipboard + updatePrimary(); + + return TRUE; } BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask) { - // Check first whether the "clear search" button wants to deal with this. - if(childrenHandleMouseDown(x, y, mask) != NULL) - { - return TRUE; - } - - if (!mSelectAllonFocusReceived - || gFocusMgr.getKeyboardFocus() == this) - { - mLastSelectionStart = -1; - mLastSelectionStart = -1; - - if (mask & MASK_SHIFT) - { - // assume we're starting a drag select - mIsSelecting = TRUE; - - // Handle selection extension - S32 old_cursor_pos = getCursor(); - setCursorAtLocalPos(x); - - if (hasSelection()) - { - /* Mac-like behavior - extend selection towards the cursor - if (getCursor() < mSelectionStart - && getCursor() < mSelectionEnd) - { - // ...left of selection - mSelectionStart = llmax(mSelectionStart, mSelectionEnd); - mSelectionEnd = getCursor(); - } - else if (getCursor() > mSelectionStart - && getCursor() > mSelectionEnd) - { - // ...right of selection - mSelectionStart = llmin(mSelectionStart, mSelectionEnd); - mSelectionEnd = getCursor(); - } - else - { - mSelectionEnd = getCursor(); - } - */ - // Windows behavior - mSelectionEnd = getCursor(); - } - else - { - mSelectionStart = old_cursor_pos; - mSelectionEnd = getCursor(); - } - } - else - { - if (mTripleClickTimer.hasExpired()) - { - // Save selection for word/line selecting on double-click - mLastSelectionStart = mSelectionStart; - mLastSelectionEnd = mSelectionEnd; - - // Move cursor and deselect for regular click - setCursorAtLocalPos( x ); - deselect(); - startSelection(); - } - else // handle triple click - { - selectAll(); - // We don't want handleMouseUp() to "finish" the selection (and thereby - // set mSelectionEnd to where the mouse is), so we finish the selection - // here. - mIsSelecting = FALSE; - } - } - - gFocusMgr.setMouseCapture( this ); - } - - setFocus(TRUE); - - // delay cursor flashing - mKeystrokeTimer.reset(); - - if (mMouseDownSignal) - (*mMouseDownSignal)(this,x,y,mask); - - return TRUE; + // Check first whether the "clear search" button wants to deal with this. + if(childrenHandleMouseDown(x, y, mask) != NULL) + { + return TRUE; + } + + if (!mSelectAllonFocusReceived + || gFocusMgr.getKeyboardFocus() == this) + { + mLastSelectionStart = -1; + mLastSelectionStart = -1; + + if (mask & MASK_SHIFT) + { + // assume we're starting a drag select + mIsSelecting = TRUE; + + // Handle selection extension + S32 old_cursor_pos = getCursor(); + setCursorAtLocalPos(x); + + if (hasSelection()) + { + /* Mac-like behavior - extend selection towards the cursor + if (getCursor() < mSelectionStart + && getCursor() < mSelectionEnd) + { + // ...left of selection + mSelectionStart = llmax(mSelectionStart, mSelectionEnd); + mSelectionEnd = getCursor(); + } + else if (getCursor() > mSelectionStart + && getCursor() > mSelectionEnd) + { + // ...right of selection + mSelectionStart = llmin(mSelectionStart, mSelectionEnd); + mSelectionEnd = getCursor(); + } + else + { + mSelectionEnd = getCursor(); + } + */ + // Windows behavior + mSelectionEnd = getCursor(); + } + else + { + mSelectionStart = old_cursor_pos; + mSelectionEnd = getCursor(); + } + } + else + { + if (mTripleClickTimer.hasExpired()) + { + // Save selection for word/line selecting on double-click + mLastSelectionStart = mSelectionStart; + mLastSelectionEnd = mSelectionEnd; + + // Move cursor and deselect for regular click + setCursorAtLocalPos( x ); + deselect(); + startSelection(); + } + else // handle triple click + { + selectAll(); + // We don't want handleMouseUp() to "finish" the selection (and thereby + // set mSelectionEnd to where the mouse is), so we finish the selection + // here. + mIsSelecting = FALSE; + } + } + + gFocusMgr.setMouseCapture( this ); + } + + setFocus(TRUE); + + // delay cursor flashing + mKeystrokeTimer.reset(); + + if (mMouseDownSignal) + (*mMouseDownSignal)(this,x,y,mask); + + return TRUE; } BOOL LLLineEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { // LL_INFOS() << "MiddleMouseDown" << LL_ENDL; - setFocus( TRUE ); - if( canPastePrimary() ) - { - setCursorAtLocalPos(x); - pastePrimary(); - } - return TRUE; + setFocus( TRUE ); + if( canPastePrimary() ) + { + setCursorAtLocalPos(x); + pastePrimary(); + } + return TRUE; } BOOL LLLineEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { - setFocus(TRUE); + setFocus(TRUE); if (!LLUICtrl::handleRightMouseDown(x, y, mask) && getShowContextMenu()) - { - showContextMenu(x, y); - } - return TRUE; + { + showContextMenu(x, y); + } + return TRUE; } BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - // Check first whether the "clear search" button wants to deal with this. - if(!hasMouseCapture()) - { - if(childrenHandleHover(x, y, mask) != NULL) - { - return TRUE; - } - } - - if( (hasMouseCapture()) && mIsSelecting ) - { - if (x != mLastSelectionX || y != mLastSelectionY) - { - mLastSelectionX = x; - mLastSelectionY = y; - } - // Scroll if mouse cursor outside of bounds - if (mScrollTimer.hasExpired()) - { - S32 increment = ll_round(mScrollTimer.getElapsedTimeF32() / AUTO_SCROLL_TIME); - mScrollTimer.reset(); - mScrollTimer.setTimerExpirySec(AUTO_SCROLL_TIME); - if( (x < mTextLeftEdge) && (mScrollHPos > 0 ) ) - { - // Scroll to the left - mScrollHPos = llclamp(mScrollHPos - increment, 0, mText.length()); - } - else - if( (x > mTextRightEdge) && (mCursorPos < (S32)mText.length()) ) - { - // If scrolling one pixel would make a difference... - S32 pixels_after_scrolling_one_char = findPixelNearestPos(1); - if( pixels_after_scrolling_one_char >= mTextRightEdge ) - { - // ...scroll to the right - mScrollHPos = llclamp(mScrollHPos + increment, 0, mText.length()); - } - } - } - - setCursorAtLocalPos( x ); - mSelectionEnd = getCursor(); - - // delay cursor flashing - mKeystrokeTimer.reset(); - - getWindow()->setCursor(UI_CURSOR_IBEAM); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; - handled = TRUE; - } - - if( !handled ) - { - getWindow()->setCursor(UI_CURSOR_IBEAM); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; - handled = TRUE; - } - - return handled; + BOOL handled = FALSE; + // Check first whether the "clear search" button wants to deal with this. + if(!hasMouseCapture()) + { + if(childrenHandleHover(x, y, mask) != NULL) + { + return TRUE; + } + } + + if( (hasMouseCapture()) && mIsSelecting ) + { + if (x != mLastSelectionX || y != mLastSelectionY) + { + mLastSelectionX = x; + mLastSelectionY = y; + } + // Scroll if mouse cursor outside of bounds + if (mScrollTimer.hasExpired()) + { + S32 increment = ll_round(mScrollTimer.getElapsedTimeF32() / AUTO_SCROLL_TIME); + mScrollTimer.reset(); + mScrollTimer.setTimerExpirySec(AUTO_SCROLL_TIME); + if( (x < mTextLeftEdge) && (mScrollHPos > 0 ) ) + { + // Scroll to the left + mScrollHPos = llclamp(mScrollHPos - increment, 0, mText.length()); + } + else + if( (x > mTextRightEdge) && (mCursorPos < (S32)mText.length()) ) + { + // If scrolling one pixel would make a difference... + S32 pixels_after_scrolling_one_char = findPixelNearestPos(1); + if( pixels_after_scrolling_one_char >= mTextRightEdge ) + { + // ...scroll to the right + mScrollHPos = llclamp(mScrollHPos + increment, 0, mText.length()); + } + } + } + + setCursorAtLocalPos( x ); + mSelectionEnd = getCursor(); + + // delay cursor flashing + mKeystrokeTimer.reset(); + + getWindow()->setCursor(UI_CURSOR_IBEAM); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; + handled = TRUE; + } + + if( !handled ) + { + getWindow()->setCursor(UI_CURSOR_IBEAM); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; + handled = TRUE; + } + + return handled; } BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; + BOOL handled = FALSE; - if( hasMouseCapture() ) - { - gFocusMgr.setMouseCapture( NULL ); - handled = TRUE; - } + if( hasMouseCapture() ) + { + gFocusMgr.setMouseCapture( NULL ); + handled = TRUE; + } - // Check first whether the "clear search" button wants to deal with this. - if(!handled && childrenHandleMouseUp(x, y, mask) != NULL) - { - return TRUE; - } + // Check first whether the "clear search" button wants to deal with this. + if(!handled && childrenHandleMouseUp(x, y, mask) != NULL) + { + return TRUE; + } + + if( mIsSelecting ) + { + setCursorAtLocalPos( x ); + mSelectionEnd = getCursor(); - if( mIsSelecting ) - { - setCursorAtLocalPos( x ); - mSelectionEnd = getCursor(); + handled = TRUE; + } - handled = TRUE; - } + if( handled ) + { + // delay cursor flashing + mKeystrokeTimer.reset(); - if( handled ) - { - // delay cursor flashing - mKeystrokeTimer.reset(); + // take selection to 'primary' clipboard + updatePrimary(); + } - // take selection to 'primary' clipboard - updatePrimary(); - } - - // We won't call LLUICtrl::handleMouseUp to avoid double calls of childrenHandleMouseUp().Just invoke the signal manually. - if (mMouseUpSignal) - (*mMouseUpSignal)(this,x,y, mask); - return handled; + // We won't call LLUICtrl::handleMouseUp to avoid double calls of childrenHandleMouseUp().Just invoke the signal manually. + if (mMouseUpSignal) + (*mMouseUpSignal)(this,x,y, mask); + return handled; } // Remove a single character from the text void LLLineEditor::removeChar() { - if( getCursor() > 0 ) - { - if (!prevalidateInput(mText.getWString().substr(getCursor()-1, 1))) - return; + if( getCursor() > 0 ) + { + if (!prevalidateInput(mText.getWString().substr(getCursor()-1, 1))) + return; - mText.erase(getCursor() - 1, 1); + mText.erase(getCursor() - 1, 1); - setCursor(getCursor() - 1); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } + setCursor(getCursor() - 1); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } } void LLLineEditor::addChar(const llwchar uni_char) { - llwchar new_c = uni_char; - if (hasSelection()) - { - deleteSelection(); - } - else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - if (!prevalidateInput(mText.getWString().substr(getCursor(), 1))) - return; - - mText.erase(getCursor(), 1); - } - - S32 cur_bytes = mText.getString().size(); - - S32 new_bytes = wchar_utf8_length(new_c); - - BOOL allow_char = TRUE; - - // Check byte length limit - if ((new_bytes + cur_bytes) > mMaxLengthBytes) - { - allow_char = FALSE; - } - else if (mMaxLengthChars) - { - S32 wide_chars = mText.getWString().size(); - if ((wide_chars + 1) > mMaxLengthChars) - { - allow_char = FALSE; - } - } - - if (allow_char) - { - // Will we need to scroll? - LLWString w_buf; - w_buf.assign(1, new_c); - - mText.insert(getCursor(), w_buf); - setCursor(getCursor() + 1); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - - getWindow()->hideCursorUntilMouseMove(); + llwchar new_c = uni_char; + if (hasSelection()) + { + deleteSelection(); + } + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + if (!prevalidateInput(mText.getWString().substr(getCursor(), 1))) + return; + + mText.erase(getCursor(), 1); + } + + S32 cur_bytes = mText.getString().size(); + + S32 new_bytes = wchar_utf8_length(new_c); + + BOOL allow_char = TRUE; + + // Check byte length limit + if ((new_bytes + cur_bytes) > mMaxLengthBytes) + { + allow_char = FALSE; + } + else if (mMaxLengthChars) + { + S32 wide_chars = mText.getWString().size(); + if ((wide_chars + 1) > mMaxLengthChars) + { + allow_char = FALSE; + } + } + + if (allow_char) + { + // Will we need to scroll? + LLWString w_buf; + w_buf.assign(1, new_c); + + mText.insert(getCursor(), w_buf); + setCursor(getCursor() + 1); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + + getWindow()->hideCursorUntilMouseMove(); } // Extends the selection box to the new cursor position void LLLineEditor::extendSelection( S32 new_cursor_pos ) { - if( !mIsSelecting ) - { - startSelection(); - } - - S32 left_pos = llmin( mSelectionStart, new_cursor_pos ); - S32 selection_length = llabs( mSelectionStart - new_cursor_pos ); - const LLWString& selection = mText.getWString().substr(left_pos, selection_length); + if( !mIsSelecting ) + { + startSelection(); + } - if (!prevalidateInput(selection)) - return; + S32 left_pos = llmin( mSelectionStart, new_cursor_pos ); + S32 selection_length = llabs( mSelectionStart - new_cursor_pos ); + const LLWString& selection = mText.getWString().substr(left_pos, selection_length); - setCursor(new_cursor_pos); - mSelectionEnd = getCursor(); + if (!prevalidateInput(selection)) + return; + + setCursor(new_cursor_pos); + mSelectionEnd = getCursor(); } void LLLineEditor::setSelection(S32 start, S32 end) { - S32 len = mText.length(); + S32 len = mText.length(); - mIsSelecting = TRUE; + mIsSelecting = TRUE; - // JC, yes, this seems odd, but I think you have to presume a - // selection dragged from the end towards the start. - mSelectionStart = llclamp(end, 0, len); - mSelectionEnd = llclamp(start, 0, len); - setCursor(start); + // JC, yes, this seems odd, but I think you have to presume a + // selection dragged from the end towards the start. + mSelectionStart = llclamp(end, 0, len); + mSelectionEnd = llclamp(start, 0, len); + setCursor(start); } void LLLineEditor::setDrawAsterixes(BOOL b) { - mDrawAsterixes = b; - updateAllowingLanguageInput(); + mDrawAsterixes = b; + updateAllowingLanguageInput(); } S32 LLLineEditor::prevWordPos(S32 cursorPos) const { - const LLWString& wtext = mText.getWString(); - while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') ) - { - cursorPos--; - } - while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) - { - cursorPos--; - } - return cursorPos; + const LLWString& wtext = mText.getWString(); + while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') ) + { + cursorPos--; + } + while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) + { + cursorPos--; + } + return cursorPos; } S32 LLLineEditor::nextWordPos(S32 cursorPos) const { - const LLWString& wtext = mText.getWString(); - while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) - { - cursorPos++; - } - while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) - { - cursorPos++; - } - return cursorPos; + const LLWString& wtext = mText.getWString(); + while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) + { + cursorPos++; + } + while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) + { + cursorPos++; + } + return cursorPos; } BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) { - BOOL handled = FALSE; - - if( mask & MASK_SHIFT ) - { - handled = TRUE; - - switch( key ) - { - case KEY_LEFT: - if( 0 < getCursor() ) - { - S32 cursorPos = getCursor() - 1; - if( mask & MASK_CONTROL ) - { - cursorPos = prevWordPos(cursorPos); - } - extendSelection( cursorPos ); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - break; - - case KEY_RIGHT: - if( getCursor() < mText.length()) - { - S32 cursorPos = getCursor() + 1; - if( mask & MASK_CONTROL ) - { - cursorPos = nextWordPos(cursorPos); - } - extendSelection( cursorPos ); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - break; - - case KEY_PAGE_UP: - case KEY_HOME: - extendSelection( 0 ); - break; - - case KEY_PAGE_DOWN: - case KEY_END: - { - S32 len = mText.length(); - if( len ) - { - extendSelection( len ); - } - break; - } - - default: - handled = FALSE; - break; - } - } - - if(handled) - { - // take selection to 'primary' clipboard - updatePrimary(); - } - - return handled; + BOOL handled = FALSE; + + if( mask & MASK_SHIFT ) + { + handled = TRUE; + + switch( key ) + { + case KEY_LEFT: + if( 0 < getCursor() ) + { + S32 cursorPos = getCursor() - 1; + if( mask & MASK_CONTROL ) + { + cursorPos = prevWordPos(cursorPos); + } + extendSelection( cursorPos ); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + break; + + case KEY_RIGHT: + if( getCursor() < mText.length()) + { + S32 cursorPos = getCursor() + 1; + if( mask & MASK_CONTROL ) + { + cursorPos = nextWordPos(cursorPos); + } + extendSelection( cursorPos ); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + break; + + case KEY_PAGE_UP: + case KEY_HOME: + extendSelection( 0 ); + break; + + case KEY_PAGE_DOWN: + case KEY_END: + { + S32 len = mText.length(); + if( len ) + { + extendSelection( len ); + } + break; + } + + default: + handled = FALSE; + break; + } + } + + if(handled) + { + // take selection to 'primary' clipboard + updatePrimary(); + } + + return handled; } void LLLineEditor::deleteSelection() { - if( !mReadOnly && hasSelection() ) - { - S32 left_pos, selection_length; - getSelectionRange(&left_pos, &selection_length); - const LLWString& selection = mText.getWString().substr(left_pos, selection_length); + if( !mReadOnly && hasSelection() ) + { + S32 left_pos, selection_length; + getSelectionRange(&left_pos, &selection_length); + const LLWString& selection = mText.getWString().substr(left_pos, selection_length); - if (!prevalidateInput(selection)) - return; + if (!prevalidateInput(selection)) + return; - mText.erase(left_pos, selection_length); - deselect(); - setCursor(left_pos); - } + mText.erase(left_pos, selection_length); + deselect(); + setCursor(left_pos); + } } BOOL LLLineEditor::canCut() const { - return !mReadOnly && !mDrawAsterixes && hasSelection(); + return !mReadOnly && !mDrawAsterixes && hasSelection(); } // cut selection to clipboard void LLLineEditor::cut() { - if( canCut() ) - { - S32 left_pos, length; - getSelectionRange(&left_pos, &length); - const LLWString& selection = mText.getWString().substr(left_pos, length); - - if (!prevalidateInput(selection)) - return; - - // Prepare for possible rollback - LLLineEditorRollback rollback( this ); - - LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); - deleteSelection(); - - // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) - { - rollback.doRollback( this ); - LLUI::getInstance()->reportBadKeystroke(); - } - else - { - onKeystroke(); - } - } + if( canCut() ) + { + S32 left_pos, length; + getSelectionRange(&left_pos, &length); + const LLWString& selection = mText.getWString().substr(left_pos, length); + + if (!prevalidateInput(selection)) + return; + + // Prepare for possible rollback + LLLineEditorRollback rollback( this ); + + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); + deleteSelection(); + + // Validate new string and rollback the if needed. + BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); + if( need_to_rollback ) + { + rollback.doRollback( this ); + LLUI::getInstance()->reportBadKeystroke(); + } + else + { + onKeystroke(); + } + } } BOOL LLLineEditor::canCopy() const { - return !mDrawAsterixes && hasSelection(); + return !mDrawAsterixes && hasSelection(); } // copy selection to clipboard void LLLineEditor::copy() { - if( canCopy() ) - { - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); - } + if( canCopy() ) + { + S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); + } } BOOL LLLineEditor::canPaste() const { - return !mReadOnly && LLClipboard::instance().isTextAvailable(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } void LLLineEditor::paste() { - bool is_primary = false; - pasteHelper(is_primary); + bool is_primary = false; + pasteHelper(is_primary); } void LLLineEditor::pastePrimary() { - bool is_primary = true; - pasteHelper(is_primary); + bool is_primary = true; + pasteHelper(is_primary); } // paste from primary (is_primary==true) or clipboard (is_primary==false) void LLLineEditor::pasteHelper(bool is_primary) { - bool can_paste_it; - if (is_primary) - { - can_paste_it = canPastePrimary(); - } - else - { - can_paste_it = canPaste(); - } - - if (can_paste_it) - { - LLWString paste; - LLClipboard::instance().pasteFromClipboard(paste, is_primary); - - if (!paste.empty()) - { - if (!prevalidateInput(paste)) - return; - - // Prepare for possible rollback - LLLineEditorRollback rollback(this); - - // Delete any selected characters - if ((!is_primary) && hasSelection()) - { - deleteSelection(); - } - - // Clean up string (replace tabs and returns and remove characters that our fonts don't support.) - LLWString clean_string(paste); - LLWStringUtil::replaceTabsWithSpaces(clean_string, 1); - //clean_string = wstring_detabify(paste, 1); - LLWStringUtil::replaceChar(clean_string, '\n', mReplaceNewlinesWithSpaces ? ' ' : 182); // 182 == paragraph character - - // Insert the string - - // Check to see that the size isn't going to be larger than the max number of bytes - U32 available_bytes = mMaxLengthBytes - wstring_utf8_length(mText); - - if ( available_bytes < (U32) wstring_utf8_length(clean_string) ) - { // Doesn't all fit - llwchar current_symbol = clean_string[0]; - U32 wchars_that_fit = 0; - U32 total_bytes = wchar_utf8_length(current_symbol); - - //loop over the "wide" characters (symbols) - //and check to see how large (in bytes) each symbol is. - while ( total_bytes <= available_bytes ) - { - //while we still have available bytes - //"accept" the current symbol and check the size - //of the next one - current_symbol = clean_string[++wchars_that_fit]; - total_bytes += wchar_utf8_length(current_symbol); - } - // Truncate the clean string at the limit of what will fit - clean_string = clean_string.substr(0, wchars_that_fit); - LLUI::getInstance()->reportBadKeystroke(); - } - - if (mMaxLengthChars) - { - U32 available_chars = mMaxLengthChars - mText.getWString().size(); - - if (available_chars < clean_string.size()) - { - clean_string = clean_string.substr(0, available_chars); - } - - LLUI::getInstance()->reportBadKeystroke(); - } - - mText.insert(getCursor(), clean_string); - setCursor( getCursor() + (S32)clean_string.length() ); - deselect(); - - // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) - { - rollback.doRollback( this ); - LLUI::getInstance()->reportBadKeystroke(); - } - else - { - onKeystroke(); - } - } - } + bool can_paste_it; + if (is_primary) + { + can_paste_it = canPastePrimary(); + } + else + { + can_paste_it = canPaste(); + } + + if (can_paste_it) + { + LLWString paste; + LLClipboard::instance().pasteFromClipboard(paste, is_primary); + + if (!paste.empty()) + { + if (!prevalidateInput(paste)) + return; + + // Prepare for possible rollback + LLLineEditorRollback rollback(this); + + // Delete any selected characters + if ((!is_primary) && hasSelection()) + { + deleteSelection(); + } + + // Clean up string (replace tabs and returns and remove characters that our fonts don't support.) + LLWString clean_string(paste); + LLWStringUtil::replaceTabsWithSpaces(clean_string, 1); + //clean_string = wstring_detabify(paste, 1); + LLWStringUtil::replaceChar(clean_string, '\n', mReplaceNewlinesWithSpaces ? ' ' : 182); // 182 == paragraph character + + // Insert the string + + // Check to see that the size isn't going to be larger than the max number of bytes + U32 available_bytes = mMaxLengthBytes - wstring_utf8_length(mText); + + if ( available_bytes < (U32) wstring_utf8_length(clean_string) ) + { // Doesn't all fit + llwchar current_symbol = clean_string[0]; + U32 wchars_that_fit = 0; + U32 total_bytes = wchar_utf8_length(current_symbol); + + //loop over the "wide" characters (symbols) + //and check to see how large (in bytes) each symbol is. + while ( total_bytes <= available_bytes ) + { + //while we still have available bytes + //"accept" the current symbol and check the size + //of the next one + current_symbol = clean_string[++wchars_that_fit]; + total_bytes += wchar_utf8_length(current_symbol); + } + // Truncate the clean string at the limit of what will fit + clean_string = clean_string.substr(0, wchars_that_fit); + LLUI::getInstance()->reportBadKeystroke(); + } + + if (mMaxLengthChars) + { + U32 available_chars = mMaxLengthChars - mText.getWString().size(); + + if (available_chars < clean_string.size()) + { + clean_string = clean_string.substr(0, available_chars); + } + + LLUI::getInstance()->reportBadKeystroke(); + } + + mText.insert(getCursor(), clean_string); + setCursor( getCursor() + (S32)clean_string.length() ); + deselect(); + + // Validate new string and rollback the if needed. + BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); + if( need_to_rollback ) + { + rollback.doRollback( this ); + LLUI::getInstance()->reportBadKeystroke(); + } + else + { + onKeystroke(); + } + } + } } // copy selection to primary void LLLineEditor::copyPrimary() { - if( canCopy() ) - { - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length, true); - } + if( canCopy() ) + { + S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length, true); + } } BOOL LLLineEditor::canPastePrimary() const { - return !mReadOnly && LLClipboard::instance().isTextAvailable(true); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLLineEditor::updatePrimary() { - if(canCopy() ) - { - copyPrimary(); - } -} - -BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) -{ - BOOL handled = FALSE; - - switch( key ) - { - case KEY_INSERT: - if (mask == MASK_NONE) - { - gKeyboard->toggleInsertMode(); - } - - handled = TRUE; - break; - - case KEY_BACKSPACE: - if (!mReadOnly) - { - //LL_INFOS() << "Handling backspace" << LL_ENDL; - if( hasSelection() ) - { - deleteSelection(); - } - else - if( 0 < getCursor() ) - { - removeChar(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - } - handled = TRUE; - break; - - case KEY_PAGE_UP: - case KEY_HOME: - if (!mIgnoreArrowKeys) - { - setCursor(0); - handled = TRUE; - } - break; - - case KEY_PAGE_DOWN: - case KEY_END: - if (!mIgnoreArrowKeys) - { - S32 len = mText.length(); - if( len ) - { - setCursor(len); - } - handled = TRUE; - } - break; - - case KEY_LEFT: - if (mIgnoreArrowKeys && mask == MASK_NONE) - break; - if ((mask & MASK_ALT) == 0) - { - if( hasSelection() ) - { - setCursor(llmin( getCursor() - 1, mSelectionStart, mSelectionEnd )); - } - else - if( 0 < getCursor() ) - { - S32 cursorPos = getCursor() - 1; - if( mask & MASK_CONTROL ) - { - cursorPos = prevWordPos(cursorPos); - } - setCursor(cursorPos); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - case KEY_RIGHT: - if (mIgnoreArrowKeys && mask == MASK_NONE) - break; - if ((mask & MASK_ALT) == 0) - { - if (hasSelection()) - { - setCursor(llmax(getCursor() + 1, mSelectionStart, mSelectionEnd)); - } - else - if (getCursor() < mText.length()) - { - S32 cursorPos = getCursor() + 1; - if( mask & MASK_CONTROL ) - { - cursorPos = nextWordPos(cursorPos); - } - setCursor(cursorPos); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - // handle ctrl-uparrow if we have a history enabled line editor. - case KEY_UP: - if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) ) - { - if( mCurrentHistoryLine > mLineHistory.begin() ) - { - mText.assign( *(--mCurrentHistoryLine) ); - setCursorToEnd(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - // handle [ctrl]-downarrow if we have a history enabled line editor - case KEY_DOWN: - if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) ) - { - if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 ) - { - mText.assign( *(++mCurrentHistoryLine) ); - setCursorToEnd(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - handled = TRUE; - } - break; - - case KEY_RETURN: - // store sent line in history - updateHistory(); - break; - - case KEY_ESCAPE: - if (mRevertOnEsc && mText.getString() != mPrevText) - { - setText(mPrevText); - // Note, don't set handled, still want to loose focus (won't commit becase text is now unchanged) - if (mKeystrokeOnEsc) - { - onKeystroke(); - } - } - break; - - default: - break; - } - - return handled; + if(canCopy() ) + { + copyPrimary(); + } +} + +BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) +{ + BOOL handled = FALSE; + + switch( key ) + { + case KEY_INSERT: + if (mask == MASK_NONE) + { + gKeyboard->toggleInsertMode(); + } + + handled = TRUE; + break; + + case KEY_BACKSPACE: + if (!mReadOnly) + { + //LL_INFOS() << "Handling backspace" << LL_ENDL; + if( hasSelection() ) + { + deleteSelection(); + } + else + if( 0 < getCursor() ) + { + removeChar(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + } + handled = TRUE; + break; + + case KEY_PAGE_UP: + case KEY_HOME: + if (!mIgnoreArrowKeys) + { + setCursor(0); + handled = TRUE; + } + break; + + case KEY_PAGE_DOWN: + case KEY_END: + if (!mIgnoreArrowKeys) + { + S32 len = mText.length(); + if( len ) + { + setCursor(len); + } + handled = TRUE; + } + break; + + case KEY_LEFT: + if (mIgnoreArrowKeys && mask == MASK_NONE) + break; + if ((mask & MASK_ALT) == 0) + { + if( hasSelection() ) + { + setCursor(llmin( getCursor() - 1, mSelectionStart, mSelectionEnd )); + } + else + if( 0 < getCursor() ) + { + S32 cursorPos = getCursor() - 1; + if( mask & MASK_CONTROL ) + { + cursorPos = prevWordPos(cursorPos); + } + setCursor(cursorPos); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + case KEY_RIGHT: + if (mIgnoreArrowKeys && mask == MASK_NONE) + break; + if ((mask & MASK_ALT) == 0) + { + if (hasSelection()) + { + setCursor(llmax(getCursor() + 1, mSelectionStart, mSelectionEnd)); + } + else + if (getCursor() < mText.length()) + { + S32 cursorPos = getCursor() + 1; + if( mask & MASK_CONTROL ) + { + cursorPos = nextWordPos(cursorPos); + } + setCursor(cursorPos); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + // handle ctrl-uparrow if we have a history enabled line editor. + case KEY_UP: + if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) ) + { + if( mCurrentHistoryLine > mLineHistory.begin() ) + { + mText.assign( *(--mCurrentHistoryLine) ); + setCursorToEnd(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + // handle [ctrl]-downarrow if we have a history enabled line editor + case KEY_DOWN: + if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) ) + { + if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 ) + { + mText.assign( *(++mCurrentHistoryLine) ); + setCursorToEnd(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + handled = TRUE; + } + break; + + case KEY_RETURN: + // store sent line in history + updateHistory(); + break; + + case KEY_ESCAPE: + if (mRevertOnEsc && mText.getString() != mPrevText) + { + setText(mPrevText); + // Note, don't set handled, still want to loose focus (won't commit becase text is now unchanged) + if (mKeystrokeOnEsc) + { + onKeystroke(); + } + } + break; + + default: + break; + } + + return handled; } BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) { - BOOL handled = FALSE; - BOOL selection_modified = FALSE; - - if ( gFocusMgr.getKeyboardFocus() == this ) - { - LLLineEditorRollback rollback( this ); - - if( !handled ) - { - handled = handleSelectionKey( key, mask ); - selection_modified = handled; - } - - // Handle most keys only if the text editor is writeable. - if ( !mReadOnly ) - { - if( !handled ) - { - handled = handleSpecialKey( key, mask ); - } - } - - if( handled ) - { - mKeystrokeTimer.reset(); - - // Most keystrokes will make the selection box go away, but not all will. - if( !selection_modified && - KEY_SHIFT != key && - KEY_CONTROL != key && - KEY_ALT != key && - KEY_CAPSLOCK != key) - { - deselect(); - } - - BOOL need_to_rollback = FALSE; - - // If read-only, don't allow changes - need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText())); - - // Validate new string and rollback the keystroke if needed. - need_to_rollback |= (mPrevalidateFunc && !mPrevalidateFunc(mText.getWString())); - - if (need_to_rollback) - { - rollback.doRollback(this); - - LLUI::getInstance()->reportBadKeystroke(); - } - - // Notify owner if requested - if (!need_to_rollback && handled) - { - onKeystroke(); - if ( (!selection_modified) && (KEY_BACKSPACE == key) ) - { - mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); - } - } - } - } - - return handled; + BOOL handled = FALSE; + BOOL selection_modified = FALSE; + + if ( gFocusMgr.getKeyboardFocus() == this ) + { + LLLineEditorRollback rollback( this ); + + if( !handled ) + { + handled = handleSelectionKey( key, mask ); + selection_modified = handled; + } + + // Handle most keys only if the text editor is writeable. + if ( !mReadOnly ) + { + if( !handled ) + { + handled = handleSpecialKey( key, mask ); + } + } + + if( handled ) + { + mKeystrokeTimer.reset(); + + // Most keystrokes will make the selection box go away, but not all will. + if( !selection_modified && + KEY_SHIFT != key && + KEY_CONTROL != key && + KEY_ALT != key && + KEY_CAPSLOCK != key) + { + deselect(); + } + + BOOL need_to_rollback = FALSE; + + // If read-only, don't allow changes + need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText())); + + // Validate new string and rollback the keystroke if needed. + need_to_rollback |= (mPrevalidateFunc && !mPrevalidateFunc(mText.getWString())); + + if (need_to_rollback) + { + rollback.doRollback(this); + + LLUI::getInstance()->reportBadKeystroke(); + } + + // Notify owner if requested + if (!need_to_rollback && handled) + { + onKeystroke(); + if ( (!selection_modified) && (KEY_BACKSPACE == key) ) + { + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + } + } + } + } + + return handled; } BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) { - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return FALSE; - } + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL + { + return FALSE; + } - BOOL handled = FALSE; + BOOL handled = FALSE; - if ( (gFocusMgr.getKeyboardFocus() == this) && getVisible() && !mReadOnly) - { - handled = TRUE; + if ( (gFocusMgr.getKeyboardFocus() == this) && getVisible() && !mReadOnly) + { + handled = TRUE; - LLLineEditorRollback rollback( this ); + LLLineEditorRollback rollback( this ); - { - LLWString u_char; - u_char.assign(1, uni_char); - if (!prevalidateInput(u_char)) - return handled; - } + { + LLWString u_char; + u_char.assign(1, uni_char); + if (!prevalidateInput(u_char)) + return handled; + } - addChar(uni_char); + addChar(uni_char); - mKeystrokeTimer.reset(); + mKeystrokeTimer.reset(); - deselect(); + deselect(); - BOOL need_to_rollback = FALSE; + BOOL need_to_rollback = FALSE; - // Validate new string and rollback the keystroke if needed. - need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); + // Validate new string and rollback the keystroke if needed. + need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) - { - rollback.doRollback( this ); + if( need_to_rollback ) + { + rollback.doRollback( this ); - LLUI::getInstance()->reportBadKeystroke(); - } + LLUI::getInstance()->reportBadKeystroke(); + } - // Notify owner if requested - if( !need_to_rollback && handled ) - { - // HACK! The only usage of this callback doesn't do anything with the character. - // We'll have to do something about this if something ever changes! - Doug - onKeystroke(); + // Notify owner if requested + if( !need_to_rollback && handled ) + { + // HACK! The only usage of this callback doesn't do anything with the character. + // We'll have to do something about this if something ever changes! - Doug + onKeystroke(); - mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); - } - } - return handled; + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + } + } + return handled; } BOOL LLLineEditor::canDoDelete() const { - return ( !mReadOnly && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) ); + return ( !mReadOnly && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) ); } void LLLineEditor::doDelete() { - if (canDoDelete() && mText.length() > 0) - { - // Prepare for possible rollback - LLLineEditorRollback rollback( this ); - - if (hasSelection()) - { - deleteSelection(); - } - else if ( getCursor() < mText.length()) - { - const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1); - - if (!prevalidateInput(text_to_delete)) - { - onKeystroke(); - return; - } - setCursor(getCursor() + 1); - removeChar(); - } - - // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) - { - rollback.doRollback( this ); - LLUI::getInstance()->reportBadKeystroke(); - } - else - { - onKeystroke(); - - mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); - } - } + if (canDoDelete() && mText.length() > 0) + { + // Prepare for possible rollback + LLLineEditorRollback rollback( this ); + + if (hasSelection()) + { + deleteSelection(); + } + else if ( getCursor() < mText.length()) + { + const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1); + + if (!prevalidateInput(text_to_delete)) + { + onKeystroke(); + return; + } + setCursor(getCursor() + 1); + removeChar(); + } + + // Validate new string and rollback the if needed. + BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); + if( need_to_rollback ) + { + rollback.doRollback( this ); + LLUI::getInstance()->reportBadKeystroke(); + } + else + { + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + } + } } void LLLineEditor::drawBackground() { - F32 alpha = getCurrentTransparency(); - if (mUseBgColor) - { - gl_rect_2d(getLocalRect(), mBgColor % alpha, TRUE); - } - else - { - bool has_focus = hasFocus(); - LLUIImage* image; - if (mReadOnly) - { - image = mBgImageDisabled; - } - else if (has_focus || mShowImageFocused) - { - image = mBgImageFocused; - } - else - { - image = mBgImage; - } - - if (!image) return; - // optionally draw programmatic border - if (has_focus) - { - LLColor4 tmp_color = gFocusMgr.getFocusColor(); - tmp_color.setAlpha(alpha); - image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), - tmp_color, - gFocusMgr.getFocusFlashWidth()); - } - LLColor4 tmp_color = UI_VERTEX_COLOR; - tmp_color.setAlpha(alpha); - image->draw(getLocalRect(), tmp_color); - } -} - -//virtual + F32 alpha = getCurrentTransparency(); + if (mUseBgColor) + { + gl_rect_2d(getLocalRect(), mBgColor % alpha, TRUE); + } + else + { + bool has_focus = hasFocus(); + LLUIImage* image; + if (mReadOnly) + { + image = mBgImageDisabled; + } + else if (has_focus || mShowImageFocused) + { + image = mBgImageFocused; + } + else + { + image = mBgImage; + } + + if (!image) return; + // optionally draw programmatic border + if (has_focus) + { + LLColor4 tmp_color = gFocusMgr.getFocusColor(); + tmp_color.setAlpha(alpha); + image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), + tmp_color, + gFocusMgr.getFocusFlashWidth()); + } + LLColor4 tmp_color = UI_VERTEX_COLOR; + tmp_color.setAlpha(alpha); + image->draw(getLocalRect(), tmp_color); + } +} + +//virtual const std::string LLLineEditor::getToolTip() const { if (sDebugUnicode) @@ -1752,950 +1752,950 @@ const std::string LLLineEditor::getToolTip() const return LLUICtrl::getToolTip(); } -//virtual +//virtual void LLLineEditor::draw() { - F32 alpha = getDrawContext().mAlpha; - S32 text_len = mText.length(); - static LLUICachedControl lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0); - static LLUICachedControl preedit_marker_brightness ("UIPreeditMarkerBrightness", 0); - static LLUICachedControl preedit_marker_gap ("UIPreeditMarkerGap", 0); - static LLUICachedControl preedit_marker_position ("UIPreeditMarkerPosition", 0); - static LLUICachedControl preedit_marker_thickness ("UIPreeditMarkerThickness", 0); - static LLUICachedControl preedit_standout_brightness ("UIPreeditStandoutBrightness", 0); - static LLUICachedControl preedit_standout_gap ("UIPreeditStandoutGap", 0); - static LLUICachedControl preedit_standout_position ("UIPreeditStandoutPosition", 0); - static LLUICachedControl preedit_standout_thickness ("UIPreeditStandoutThickness", 0); - - std::string saved_text; - if (mDrawAsterixes) - { - saved_text = mText.getString(); - std::string text; - for (S32 i = 0; i < mText.length(); i++) - { - text += PASSWORD_ASTERISK; - } - mText = text; - } - - // draw rectangle for the background - LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - background.stretch( -mBorderThickness ); - - S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2; - if (mSpellCheck) - { - lineeditor_v_pad += 1; - } - - drawBackground(); - - // draw text - - // With viewer-2 art files, input region is 2 pixels up - S32 cursor_bottom = background.mBottom + 2; - S32 cursor_top = background.mTop - 1; - - LLColor4 text_color; - if (!mReadOnly) - { - if (!getTentative()) - { - text_color = mFgColor.get(); - } - else - { - text_color = mTentativeFgColor.get(); - } - } - else - { - text_color = mReadOnlyFgColor.get(); - } - text_color.setAlpha(alpha); - LLColor4 label_color = mTentativeFgColor.get(); - label_color.setAlpha(alpha); - - if (hasPreeditString()) - { - // Draw preedit markers. This needs to be before drawing letters. - for (U32 i = 0; i < mPreeditStandouts.size(); i++) - { - const S32 preedit_left = mPreeditPositions[i]; - const S32 preedit_right = mPreeditPositions[i + 1]; - if (preedit_right > mScrollHPos) - { - S32 preedit_pixels_left = findPixelNearestPos(llmax(preedit_left, mScrollHPos) - getCursor()); - S32 preedit_pixels_right = llmin(findPixelNearestPos(preedit_right - getCursor()), background.mRight); - if (preedit_pixels_left >= background.mRight) - { - break; - } - if (mPreeditStandouts[i]) - { - gl_rect_2d(preedit_pixels_left + preedit_standout_gap, - background.mBottom + preedit_standout_position, - preedit_pixels_right - preedit_standout_gap - 1, - background.mBottom + preedit_standout_position - preedit_standout_thickness, - (text_color * preedit_standout_brightness - + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/)); - } - else - { - gl_rect_2d(preedit_pixels_left + preedit_marker_gap, - background.mBottom + preedit_marker_position, - preedit_pixels_right - preedit_marker_gap - 1, - background.mBottom + preedit_marker_position - preedit_marker_thickness, - (text_color * preedit_marker_brightness - + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/)); - } - } - } - } - - S32 rendered_text = 0; - F32 rendered_pixels_right = (F32)mTextLeftEdge; - F32 text_bottom = (F32)background.mBottom + (F32)lineeditor_v_pad; - - if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() ) - { - S32 select_left; - S32 select_right; - if (mSelectionStart < mSelectionEnd) - { - select_left = mSelectionStart; - select_right = mSelectionEnd; - } - else - { - select_left = mSelectionEnd; - select_right = mSelectionStart; - } - - if( select_left > mScrollHPos ) - { - // unselected, left side - rendered_text = mGLFont->render( - mText, mScrollHPos, - rendered_pixels_right, text_bottom, - text_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - select_left - mScrollHPos, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right); - } - - if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) - { - LLColor4 color = mHighlightColor; - color.setAlpha(alpha); - // selected middle - S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text); - width = llmin(width, mTextRightEdge - ll_round(rendered_pixels_right)); - gl_rect_2d(ll_round(rendered_pixels_right), cursor_top, ll_round(rendered_pixels_right)+width, cursor_bottom, color); - - LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); - rendered_text += mGLFont->render( - mText, mScrollHPos + rendered_text, - rendered_pixels_right, text_bottom, - tmp_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - select_right - mScrollHPos - rendered_text, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right); - } - - if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) - { - // unselected, right side - rendered_text += mGLFont->render( - mText, mScrollHPos + rendered_text, - rendered_pixels_right, text_bottom, - text_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - S32_MAX, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right); - } - } - else - { - rendered_text = mGLFont->render( - mText, mScrollHPos, - rendered_pixels_right, text_bottom, - text_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - S32_MAX, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right); - } + F32 alpha = getDrawContext().mAlpha; + S32 text_len = mText.length(); + static LLUICachedControl lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0); + static LLUICachedControl preedit_marker_brightness ("UIPreeditMarkerBrightness", 0); + static LLUICachedControl preedit_marker_gap ("UIPreeditMarkerGap", 0); + static LLUICachedControl preedit_marker_position ("UIPreeditMarkerPosition", 0); + static LLUICachedControl preedit_marker_thickness ("UIPreeditMarkerThickness", 0); + static LLUICachedControl preedit_standout_brightness ("UIPreeditStandoutBrightness", 0); + static LLUICachedControl preedit_standout_gap ("UIPreeditStandoutGap", 0); + static LLUICachedControl preedit_standout_position ("UIPreeditStandoutPosition", 0); + static LLUICachedControl preedit_standout_thickness ("UIPreeditStandoutThickness", 0); + + std::string saved_text; + if (mDrawAsterixes) + { + saved_text = mText.getString(); + std::string text; + for (S32 i = 0; i < mText.length(); i++) + { + text += PASSWORD_ASTERISK; + } + mText = text; + } + + // draw rectangle for the background + LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 ); + background.stretch( -mBorderThickness ); + + S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2; + if (mSpellCheck) + { + lineeditor_v_pad += 1; + } + + drawBackground(); + + // draw text + + // With viewer-2 art files, input region is 2 pixels up + S32 cursor_bottom = background.mBottom + 2; + S32 cursor_top = background.mTop - 1; + + LLColor4 text_color; + if (!mReadOnly) + { + if (!getTentative()) + { + text_color = mFgColor.get(); + } + else + { + text_color = mTentativeFgColor.get(); + } + } + else + { + text_color = mReadOnlyFgColor.get(); + } + text_color.setAlpha(alpha); + LLColor4 label_color = mTentativeFgColor.get(); + label_color.setAlpha(alpha); + + if (hasPreeditString()) + { + // Draw preedit markers. This needs to be before drawing letters. + for (U32 i = 0; i < mPreeditStandouts.size(); i++) + { + const S32 preedit_left = mPreeditPositions[i]; + const S32 preedit_right = mPreeditPositions[i + 1]; + if (preedit_right > mScrollHPos) + { + S32 preedit_pixels_left = findPixelNearestPos(llmax(preedit_left, mScrollHPos) - getCursor()); + S32 preedit_pixels_right = llmin(findPixelNearestPos(preedit_right - getCursor()), background.mRight); + if (preedit_pixels_left >= background.mRight) + { + break; + } + if (mPreeditStandouts[i]) + { + gl_rect_2d(preedit_pixels_left + preedit_standout_gap, + background.mBottom + preedit_standout_position, + preedit_pixels_right - preedit_standout_gap - 1, + background.mBottom + preedit_standout_position - preedit_standout_thickness, + (text_color * preedit_standout_brightness + + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/)); + } + else + { + gl_rect_2d(preedit_pixels_left + preedit_marker_gap, + background.mBottom + preedit_marker_position, + preedit_pixels_right - preedit_marker_gap - 1, + background.mBottom + preedit_marker_position - preedit_marker_thickness, + (text_color * preedit_marker_brightness + + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/)); + } + } + } + } + + S32 rendered_text = 0; + F32 rendered_pixels_right = (F32)mTextLeftEdge; + F32 text_bottom = (F32)background.mBottom + (F32)lineeditor_v_pad; + + if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() ) + { + S32 select_left; + S32 select_right; + if (mSelectionStart < mSelectionEnd) + { + select_left = mSelectionStart; + select_right = mSelectionEnd; + } + else + { + select_left = mSelectionEnd; + select_right = mSelectionStart; + } + + if( select_left > mScrollHPos ) + { + // unselected, left side + rendered_text = mGLFont->render( + mText, mScrollHPos, + rendered_pixels_right, text_bottom, + text_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + select_left - mScrollHPos, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right); + } + + if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) + { + LLColor4 color = mHighlightColor; + color.setAlpha(alpha); + // selected middle + S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text); + width = llmin(width, mTextRightEdge - ll_round(rendered_pixels_right)); + gl_rect_2d(ll_round(rendered_pixels_right), cursor_top, ll_round(rendered_pixels_right)+width, cursor_bottom, color); + + LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); + rendered_text += mGLFont->render( + mText, mScrollHPos + rendered_text, + rendered_pixels_right, text_bottom, + tmp_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + select_right - mScrollHPos - rendered_text, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right); + } + + if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) + { + // unselected, right side + rendered_text += mGLFont->render( + mText, mScrollHPos + rendered_text, + rendered_pixels_right, text_bottom, + text_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + S32_MAX, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right); + } + } + else + { + rendered_text = mGLFont->render( + mText, mScrollHPos, + rendered_pixels_right, text_bottom, + text_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + S32_MAX, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right); + } #if 1 // for when we're ready for image art. - mBorder->setVisible(FALSE); // no more programmatic art. + mBorder->setVisible(FALSE); // no more programmatic art. #endif - if ( (getSpellCheck()) && (mText.length() > 2) ) - { - // Calculate start and end indices for the first and last visible word - U32 start = prevWordPos(mScrollHPos), end = nextWordPos(mScrollHPos + rendered_text); - - if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) - { - const LLWString& text = mText.getWString().substr(start, end); - - // Find the start of the first word - U32 word_start = 0, word_end = 0; - while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) - { - word_start++; - } - - // Iterate over all words in the text block and check them one by one - mMisspellRanges.clear(); - while (word_start < text.length()) - { - // Find the end of the current word (special case handling for "'" when it's used as a contraction) - word_end = word_start + 1; - while ( (word_end < text.length()) && - ((LLWStringUtil::isPartOfWord(text[word_end])) || - ((L'\'' == text[word_end]) && (word_end + 1 < text.length()) && - (LLStringOps::isAlnum(text[word_end - 1])) && (LLStringOps::isAlnum(text[word_end + 1])))) ) - { - word_end++; - } - if (word_end > text.length()) - { - break; - } - - // Don't process words shorter than 3 characters - std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start)); - if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) - { - mMisspellRanges.push_back(std::pair(start + word_start, start + word_end)); - } - - // Find the start of the next word - word_start = word_end + 1; - while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) - { - word_start++; - } - } - - mSpellCheckStart = start; - mSpellCheckEnd = end; - } - - // Draw squiggly lines under any (visible) misspelled words - for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) - { - // Skip over words that aren't (partially) visible - if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) - { - continue; - } - - // Skip the current word if the user is still busy editing it - if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) - { - continue; - } - - S32 pxWidth = getRect().getWidth(); - S32 pxStart = findPixelNearestPos(it->first - getCursor()); - if (pxStart > pxWidth) - { - continue; - } - S32 pxEnd = findPixelNearestPos(it->second - getCursor()); - if (pxEnd > pxWidth) - { - pxEnd = pxWidth; - } - - S32 pxBottom = (S32)(text_bottom + mGLFont->getDescenderHeight()); - - gGL.color4ub(255, 0, 0, 200); - while (pxStart + 1 < pxEnd) - { - gl_line_2d(pxStart, pxBottom, pxStart + 2, pxBottom - 2); - if (pxStart + 3 < pxEnd) - { - gl_line_2d(pxStart + 2, pxBottom - 3, pxStart + 4, pxBottom - 1); - } - pxStart += 4; - } - } - } - - // If we're editing... - if( hasFocus()) - { - //mBorder->setVisible(TRUE); // ok, programmer art just this once. - // (Flash the cursor every half second) - if (!mReadOnly && gFocusMgr.getAppHasFocus()) - { - F32 elapsed = mKeystrokeTimer.getElapsedTimeF32(); - if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) ) - { - S32 cursor_left = findPixelNearestPos(); - cursor_left -= lineeditor_cursor_thickness / 2; - S32 cursor_right = cursor_left + lineeditor_cursor_thickness; - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) - { - const LLWString space(utf8str_to_wstring(std::string(" "))); - S32 wswidth = mGLFont->getWidth(space.c_str()); - S32 width = mGLFont->getWidth(mText.getWString().c_str(), getCursor(), 1) + 1; - cursor_right = cursor_left + llmax(wswidth, width); - } - // Use same color as text for the Cursor - gl_rect_2d(cursor_left, cursor_top, - cursor_right, cursor_bottom, text_color); - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) - { - LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); - mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom, - tmp_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - 1); - } - - // Make sure the IME is in the right place - S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position - LLRect screen_pos = calcScreenRect(); - LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad ); - - ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); - getWindow()->setLanguageTextInput( ime_pos ); - } - } - - //draw label if no text is provided - //but we should draw it in a different color - //to give indication that it is not text you typed in - if (0 == mText.length() && (mReadOnly || mShowLabelFocused)) - { - mGLFont->render(mLabel.getWString(), 0, - mTextLeftEdge, (F32)text_bottom, - label_color, - LLFontGL::LEFT, - LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - S32_MAX, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right, FALSE); - } - - - // Draw children (border) - //mBorder->setVisible(TRUE); - mBorder->setKeyboardFocusHighlight( TRUE ); - LLView::draw(); - mBorder->setKeyboardFocusHighlight( FALSE ); - //mBorder->setVisible(FALSE); - } - else // does not have keyboard input - { - // draw label if no text provided - if (0 == mText.length()) - { - mGLFont->render(mLabel.getWString(), 0, - mTextLeftEdge, (F32)text_bottom, - label_color, - LLFontGL::LEFT, - LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - S32_MAX, - mTextRightEdge - ll_round(rendered_pixels_right), - &rendered_pixels_right); - } - // Draw children (border) - LLView::draw(); - } - - if (mDrawAsterixes) - { - mText = saved_text; - } + if ( (getSpellCheck()) && (mText.length() > 2) ) + { + // Calculate start and end indices for the first and last visible word + U32 start = prevWordPos(mScrollHPos), end = nextWordPos(mScrollHPos + rendered_text); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) + { + const LLWString& text = mText.getWString().substr(start, end); + + // Find the start of the first word + U32 word_start = 0, word_end = 0; + while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) + { + word_start++; + } + + // Iterate over all words in the text block and check them one by one + mMisspellRanges.clear(); + while (word_start < text.length()) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < text.length()) && + ((LLWStringUtil::isPartOfWord(text[word_end])) || + ((L'\'' == text[word_end]) && (word_end + 1 < text.length()) && + (LLStringOps::isAlnum(text[word_end - 1])) && (LLStringOps::isAlnum(text[word_end + 1])))) ) + { + word_end++; + } + if (word_end > text.length()) + { + break; + } + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair(start + word_start, start + word_end)); + } + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) + { + word_start++; + } + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + + // Draw squiggly lines under any (visible) misspelled words + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + // Skip over words that aren't (partially) visible + if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) + { + continue; + } + + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + continue; + } + + S32 pxWidth = getRect().getWidth(); + S32 pxStart = findPixelNearestPos(it->first - getCursor()); + if (pxStart > pxWidth) + { + continue; + } + S32 pxEnd = findPixelNearestPos(it->second - getCursor()); + if (pxEnd > pxWidth) + { + pxEnd = pxWidth; + } + + S32 pxBottom = (S32)(text_bottom + mGLFont->getDescenderHeight()); + + gGL.color4ub(255, 0, 0, 200); + while (pxStart + 1 < pxEnd) + { + gl_line_2d(pxStart, pxBottom, pxStart + 2, pxBottom - 2); + if (pxStart + 3 < pxEnd) + { + gl_line_2d(pxStart + 2, pxBottom - 3, pxStart + 4, pxBottom - 1); + } + pxStart += 4; + } + } + } + + // If we're editing... + if( hasFocus()) + { + //mBorder->setVisible(TRUE); // ok, programmer art just this once. + // (Flash the cursor every half second) + if (!mReadOnly && gFocusMgr.getAppHasFocus()) + { + F32 elapsed = mKeystrokeTimer.getElapsedTimeF32(); + if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) ) + { + S32 cursor_left = findPixelNearestPos(); + cursor_left -= lineeditor_cursor_thickness / 2; + S32 cursor_right = cursor_left + lineeditor_cursor_thickness; + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) + { + const LLWString space(utf8str_to_wstring(std::string(" "))); + S32 wswidth = mGLFont->getWidth(space.c_str()); + S32 width = mGLFont->getWidth(mText.getWString().c_str(), getCursor(), 1) + 1; + cursor_right = cursor_left + llmax(wswidth, width); + } + // Use same color as text for the Cursor + gl_rect_2d(cursor_left, cursor_top, + cursor_right, cursor_bottom, text_color); + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) + { + LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); + mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom, + tmp_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + 1); + } + + // Make sure the IME is in the right place + S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position + LLRect screen_pos = calcScreenRect(); + LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad ); + + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); + getWindow()->setLanguageTextInput( ime_pos ); + } + } + + //draw label if no text is provided + //but we should draw it in a different color + //to give indication that it is not text you typed in + if (0 == mText.length() && (mReadOnly || mShowLabelFocused)) + { + mGLFont->render(mLabel.getWString(), 0, + mTextLeftEdge, (F32)text_bottom, + label_color, + LLFontGL::LEFT, + LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + S32_MAX, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right, FALSE); + } + + + // Draw children (border) + //mBorder->setVisible(TRUE); + mBorder->setKeyboardFocusHighlight( TRUE ); + LLView::draw(); + mBorder->setKeyboardFocusHighlight( FALSE ); + //mBorder->setVisible(FALSE); + } + else // does not have keyboard input + { + // draw label if no text provided + if (0 == mText.length()) + { + mGLFont->render(mLabel.getWString(), 0, + mTextLeftEdge, (F32)text_bottom, + label_color, + LLFontGL::LEFT, + LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + S32_MAX, + mTextRightEdge - ll_round(rendered_pixels_right), + &rendered_pixels_right); + } + // Draw children (border) + LLView::draw(); + } + + if (mDrawAsterixes) + { + mText = saved_text; + } } // Returns the local screen space X coordinate associated with the text cursor position. S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const { - S32 dpos = getCursor() - mScrollHPos + cursor_offset; - S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mTextLeftEdge; - return result; + S32 dpos = getCursor() - mScrollHPos + cursor_offset; + S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mTextLeftEdge; + return result; } S32 LLLineEditor::calcCursorPos(S32 mouse_x) { - const llwchar* wtext = mText.getWString().c_str(); - LLWString asterix_text; - if (mDrawAsterixes) - { - for (S32 i = 0; i < mText.length(); i++) - { - asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK); - } - wtext = asterix_text.c_str(); - } - - S32 cur_pos = mScrollHPos + - mGLFont->charFromPixelOffset( - wtext, mScrollHPos, - (F32)(mouse_x - mTextLeftEdge), - (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive - - return cur_pos; + const llwchar* wtext = mText.getWString().c_str(); + LLWString asterix_text; + if (mDrawAsterixes) + { + for (S32 i = 0; i < mText.length(); i++) + { + asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK); + } + wtext = asterix_text.c_str(); + } + + S32 cur_pos = mScrollHPos + + mGLFont->charFromPixelOffset( + wtext, mScrollHPos, + (F32)(mouse_x - mTextLeftEdge), + (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive + + return cur_pos; } //virtual void LLLineEditor::clear() { - mText.clear(); - setCursor(0); + mText.clear(); + setCursor(0); } //virtual void LLLineEditor::onTabInto() { - selectAll(); + selectAll(); LLUICtrl::onTabInto(); } //virtual BOOL LLLineEditor::acceptsTextInput() const { - return TRUE; + return TRUE; } // Start or stop the editor from accepting text-editing keystrokes void LLLineEditor::setFocus( BOOL new_state ) { - BOOL old_state = hasFocus(); - - if (!new_state) - { - getWindow()->allowLanguageTextInput(this, FALSE); - } - - - // getting focus when we didn't have it before, and we want to select all - if (!old_state && new_state && mSelectAllonFocusReceived) - { - selectAll(); - // We don't want handleMouseUp() to "finish" the selection (and thereby - // set mSelectionEnd to where the mouse is), so we finish the selection - // here. - mIsSelecting = FALSE; - } - - if( new_state ) - { - gEditMenuHandler = this; - - // Don't start the cursor flashing right away - mKeystrokeTimer.reset(); - } - else - { - // Not really needed, since loss of keyboard focus should take care of this, - // but limited paranoia is ok. - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } - - endSelection(); - } - - LLUICtrl::setFocus( new_state ); - - if (new_state) - { - // Allow Language Text Input only when this LineEditor has - // no prevalidate function attached. This criterion works - // fine on 1.15.0.2, since all prevalidate func reject any - // non-ASCII characters. I'm not sure on future versions, - // however. - getWindow()->allowLanguageTextInput(this, mPrevalidateFunc == NULL); - } -} - -//virtual + BOOL old_state = hasFocus(); + + if (!new_state) + { + getWindow()->allowLanguageTextInput(this, FALSE); + } + + + // getting focus when we didn't have it before, and we want to select all + if (!old_state && new_state && mSelectAllonFocusReceived) + { + selectAll(); + // We don't want handleMouseUp() to "finish" the selection (and thereby + // set mSelectionEnd to where the mouse is), so we finish the selection + // here. + mIsSelecting = FALSE; + } + + if( new_state ) + { + gEditMenuHandler = this; + + // Don't start the cursor flashing right away + mKeystrokeTimer.reset(); + } + else + { + // Not really needed, since loss of keyboard focus should take care of this, + // but limited paranoia is ok. + if( gEditMenuHandler == this ) + { + gEditMenuHandler = NULL; + } + + endSelection(); + } + + LLUICtrl::setFocus( new_state ); + + if (new_state) + { + // Allow Language Text Input only when this LineEditor has + // no prevalidate function attached. This criterion works + // fine on 1.15.0.2, since all prevalidate func reject any + // non-ASCII characters. I'm not sure on future versions, + // however. + getWindow()->allowLanguageTextInput(this, mPrevalidateFunc == NULL); + } +} + +//virtual void LLLineEditor::setRect(const LLRect& rect) { - LLUICtrl::setRect(rect); - if (mBorder) - { - LLRect border_rect = mBorder->getRect(); - // Scalable UI somehow made these rectangles off-by-one. - // I don't know why. JC - border_rect.setOriginAndSize(border_rect.mLeft, border_rect.mBottom, - rect.getWidth()-1, rect.getHeight()-1); - mBorder->setRect(border_rect); - } + LLUICtrl::setRect(rect); + if (mBorder) + { + LLRect border_rect = mBorder->getRect(); + // Scalable UI somehow made these rectangles off-by-one. + // I don't know why. JC + border_rect.setOriginAndSize(border_rect.mLeft, border_rect.mBottom, + rect.getWidth()-1, rect.getHeight()-1); + mBorder->setRect(border_rect); + } } void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func) { - mPrevalidateFunc = func; - updateAllowingLanguageInput(); + mPrevalidateFunc = func; + updateAllowingLanguageInput(); } void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func) { - mPrevalidateInputFunc = func; - updateAllowingLanguageInput(); + mPrevalidateInputFunc = func; + updateAllowingLanguageInput(); } bool LLLineEditor::prevalidateInput(const LLWString& wstr) { - if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr)) - { - return false; - } + if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr)) + { + return false; + } - return true; + return true; } // static BOOL LLLineEditor::postvalidateFloat(const std::string &str) { - LLLocale locale(LLLocale::USER_LOCALE); - - BOOL success = TRUE; - BOOL has_decimal = FALSE; - BOOL has_digit = FALSE; - - LLWString trimmed = utf8str_to_wstring(str); - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - if( 0 < len ) - { - S32 i = 0; - - // First character can be a negative sign - if( '-' == trimmed[0] ) - { - i++; - } - - // May be a comma or period, depending on the locale - llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint(); - - for( ; i < len; i++ ) - { - if( decimal_point == trimmed[i] ) - { - if( has_decimal ) - { - // can't have two - success = FALSE; - break; - } - else - { - has_decimal = TRUE; - } - } - else - if( LLStringOps::isDigit( trimmed[i] ) ) - { - has_digit = TRUE; - } - else - { - success = FALSE; - break; - } - } - } - - // Gotta have at least one - success = has_digit; - - return success; + LLLocale locale(LLLocale::USER_LOCALE); + + BOOL success = TRUE; + BOOL has_decimal = FALSE; + BOOL has_digit = FALSE; + + LLWString trimmed = utf8str_to_wstring(str); + LLWStringUtil::trim(trimmed); + S32 len = trimmed.length(); + if( 0 < len ) + { + S32 i = 0; + + // First character can be a negative sign + if( '-' == trimmed[0] ) + { + i++; + } + + // May be a comma or period, depending on the locale + llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint(); + + for( ; i < len; i++ ) + { + if( decimal_point == trimmed[i] ) + { + if( has_decimal ) + { + // can't have two + success = FALSE; + break; + } + else + { + has_decimal = TRUE; + } + } + else + if( LLStringOps::isDigit( trimmed[i] ) ) + { + has_digit = TRUE; + } + else + { + success = FALSE; + break; + } + } + } + + // Gotta have at least one + success = has_digit; + + return success; } BOOL LLLineEditor::evaluateFloat() { - bool success; - F32 result = 0.f; - std::string expr = getText(); - LLStringUtil::toUpper(expr); + bool success; + F32 result = 0.f; + std::string expr = getText(); + LLStringUtil::toUpper(expr); - success = LLCalc::getInstance()->evalString(expr, result); + success = LLCalc::getInstance()->evalString(expr, result); - if (!success) - { - // Move the cursor to near the error on failure - setCursor(LLCalc::getInstance()->getLastErrorPos()); - // *TODO: Translated error message indicating the type of error? Select error text? - } - else - { - // Replace the expression with the result - std::string result_str = llformat("%f",result); - setText(result_str); - selectAll(); - } + if (!success) + { + // Move the cursor to near the error on failure + setCursor(LLCalc::getInstance()->getLastErrorPos()); + // *TODO: Translated error message indicating the type of error? Select error text? + } + else + { + // Replace the expression with the result + std::string result_str = llformat("%f",result); + setText(result_str); + selectAll(); + } - return success; + return success; } void LLLineEditor::onMouseCaptureLost() { - endSelection(); + endSelection(); } void LLLineEditor::setSelectAllonFocusReceived(BOOL b) { - mSelectAllonFocusReceived = b; + mSelectAllonFocusReceived = b; } void LLLineEditor::onKeystroke() { - if (mKeystrokeCallback) - { - mKeystrokeCallback(this); - } + if (mKeystrokeCallback) + { + mKeystrokeCallback(this); + } - mSpellCheckStart = mSpellCheckEnd = -1; + mSpellCheckStart = mSpellCheckEnd = -1; } void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data) { - mKeystrokeCallback = boost::bind(callback, _1, user_data); + mKeystrokeCallback = boost::bind(callback, _1, user_data); } BOOL LLLineEditor::setTextArg( const std::string& key, const LLStringExplicit& text ) { - mText.setArg(key, text); - return TRUE; + mText.setArg(key, text); + return TRUE; } BOOL LLLineEditor::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - mLabel.setArg(key, text); - return TRUE; + mLabel.setArg(key, text); + return TRUE; } void LLLineEditor::updateAllowingLanguageInput() { - // Allow Language Text Input only when this LineEditor has - // no prevalidate function attached (as long as other criteria - // common to LLTextEditor). This criterion works - // fine on 1.15.0.2, since all prevalidate func reject any - // non-ASCII characters. I'm not sure on future versions, - // however... - LLWindow* window = getWindow(); - if (!window) - { - // test app, no window available - return; - } - if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL) - { - window->allowLanguageTextInput(this, TRUE); - } - else - { - window->allowLanguageTextInput(this, FALSE); - } + // Allow Language Text Input only when this LineEditor has + // no prevalidate function attached (as long as other criteria + // common to LLTextEditor). This criterion works + // fine on 1.15.0.2, since all prevalidate func reject any + // non-ASCII characters. I'm not sure on future versions, + // however... + LLWindow* window = getWindow(); + if (!window) + { + // test app, no window available + return; + } + if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL) + { + window->allowLanguageTextInput(this, TRUE); + } + else + { + window->allowLanguageTextInput(this, FALSE); + } } BOOL LLLineEditor::hasPreeditString() const { - return (mPreeditPositions.size() > 1); + return (mPreeditPositions.size() > 1); } void LLLineEditor::resetPreedit() { - if (hasSelection()) - { - if (hasPreeditString()) - { - LL_WARNS() << "Preedit and selection!" << LL_ENDL; - deselect(); - } - else - { - deleteSelection(); - } - } - if (hasPreeditString()) - { - const S32 preedit_pos = mPreeditPositions.front(); - mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos); - mText.insert(preedit_pos, mPreeditOverwrittenWString); - setCursor(preedit_pos); - - mPreeditWString.clear(); - mPreeditOverwrittenWString.clear(); - mPreeditPositions.clear(); - - // Don't reset key stroke timer nor invoke keystroke callback, - // because a call to updatePreedit should be follow soon in - // normal course of operation, and timer and callback will be - // maintained there. Doing so here made an odd sound. (VWR-3410) - } + if (hasSelection()) + { + if (hasPreeditString()) + { + LL_WARNS() << "Preedit and selection!" << LL_ENDL; + deselect(); + } + else + { + deleteSelection(); + } + } + if (hasPreeditString()) + { + const S32 preedit_pos = mPreeditPositions.front(); + mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos); + mText.insert(preedit_pos, mPreeditOverwrittenWString); + setCursor(preedit_pos); + + mPreeditWString.clear(); + mPreeditOverwrittenWString.clear(); + mPreeditPositions.clear(); + + // Don't reset key stroke timer nor invoke keystroke callback, + // because a call to updatePreedit should be follow soon in + // normal course of operation, and timer and callback will be + // maintained there. Doing so here made an odd sound. (VWR-3410) + } } void LLLineEditor::updatePreedit(const LLWString &preedit_string, - const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) -{ - // Just in case. - if (mReadOnly) - { - return; - } - - // Note that call to updatePreedit is always preceeded by resetPreedit, - // so we have no existing selection/preedit. - - S32 insert_preedit_at = getCursor(); - - mPreeditWString = preedit_string; - mPreeditPositions.resize(preedit_segment_lengths.size() + 1); - S32 position = insert_preedit_at; - for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++) - { - mPreeditPositions[i] = position; - position += preedit_segment_lengths[i]; - } - mPreeditPositions.back() = position; - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - mPreeditOverwrittenWString.assign( LLWString( mText, insert_preedit_at, mPreeditWString.length() ) ); - mText.erase(insert_preedit_at, mPreeditWString.length()); - } - else - { - mPreeditOverwrittenWString.clear(); - } - mText.insert(insert_preedit_at, mPreeditWString); - - mPreeditStandouts = preedit_standouts; - - setCursor(position); - setCursor(mPreeditPositions.front() + caret_position); - - // Update of the preedit should be caused by some key strokes. - mKeystrokeTimer.reset(); - onKeystroke(); - - mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) +{ + // Just in case. + if (mReadOnly) + { + return; + } + + // Note that call to updatePreedit is always preceeded by resetPreedit, + // so we have no existing selection/preedit. + + S32 insert_preedit_at = getCursor(); + + mPreeditWString = preedit_string; + mPreeditPositions.resize(preedit_segment_lengths.size() + 1); + S32 position = insert_preedit_at; + for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++) + { + mPreeditPositions[i] = position; + position += preedit_segment_lengths[i]; + } + mPreeditPositions.back() = position; + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + mPreeditOverwrittenWString.assign( LLWString( mText, insert_preedit_at, mPreeditWString.length() ) ); + mText.erase(insert_preedit_at, mPreeditWString.length()); + } + else + { + mPreeditOverwrittenWString.clear(); + } + mText.insert(insert_preedit_at, mPreeditWString); + + mPreeditStandouts = preedit_standouts; + + setCursor(position); + setCursor(mPreeditPositions.front() + caret_position); + + // Update of the preedit should be caused by some key strokes. + mKeystrokeTimer.reset(); + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } BOOL LLLineEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const { - if (control) - { - LLRect control_rect_screen; - localRectToScreen(getRect(), &control_rect_screen); - LLUI::getInstance()->screenRectToGL(control_rect_screen, control); - } - - S32 preedit_left_column, preedit_right_column; - if (hasPreeditString()) - { - preedit_left_column = mPreeditPositions.front(); - preedit_right_column = mPreeditPositions.back(); - } - else - { - preedit_left_column = preedit_right_column = getCursor(); - } - if (preedit_right_column < mScrollHPos) - { - // This should not occure... - return FALSE; - } - - const S32 query = (query_offset >= 0 ? preedit_left_column + query_offset : getCursor()); - if (query < mScrollHPos || query < preedit_left_column || query > preedit_right_column) - { - return FALSE; - } - - if (coord) - { - S32 query_local = findPixelNearestPos(query - getCursor()); - S32 query_screen_x, query_screen_y; - localPointToScreen(query_local, getRect().getHeight() / 2, &query_screen_x, &query_screen_y); - LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY); - } - - if (bounds) - { - S32 preedit_left_local = findPixelNearestPos(llmax(preedit_left_column, mScrollHPos) - getCursor()); - S32 preedit_right_local = llmin(findPixelNearestPos(preedit_right_column - getCursor()), getRect().getWidth() - mBorderThickness); - if (preedit_left_local > preedit_right_local) - { - // Is this condition possible? - preedit_right_local = preedit_left_local; - } - - LLRect preedit_rect_local(preedit_left_local, getRect().getHeight(), preedit_right_local, 0); - LLRect preedit_rect_screen; - localRectToScreen(preedit_rect_local, &preedit_rect_screen); - LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds); - } - - return TRUE; + if (control) + { + LLRect control_rect_screen; + localRectToScreen(getRect(), &control_rect_screen); + LLUI::getInstance()->screenRectToGL(control_rect_screen, control); + } + + S32 preedit_left_column, preedit_right_column; + if (hasPreeditString()) + { + preedit_left_column = mPreeditPositions.front(); + preedit_right_column = mPreeditPositions.back(); + } + else + { + preedit_left_column = preedit_right_column = getCursor(); + } + if (preedit_right_column < mScrollHPos) + { + // This should not occure... + return FALSE; + } + + const S32 query = (query_offset >= 0 ? preedit_left_column + query_offset : getCursor()); + if (query < mScrollHPos || query < preedit_left_column || query > preedit_right_column) + { + return FALSE; + } + + if (coord) + { + S32 query_local = findPixelNearestPos(query - getCursor()); + S32 query_screen_x, query_screen_y; + localPointToScreen(query_local, getRect().getHeight() / 2, &query_screen_x, &query_screen_y); + LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY); + } + + if (bounds) + { + S32 preedit_left_local = findPixelNearestPos(llmax(preedit_left_column, mScrollHPos) - getCursor()); + S32 preedit_right_local = llmin(findPixelNearestPos(preedit_right_column - getCursor()), getRect().getWidth() - mBorderThickness); + if (preedit_left_local > preedit_right_local) + { + // Is this condition possible? + preedit_right_local = preedit_left_local; + } + + LLRect preedit_rect_local(preedit_left_local, getRect().getHeight(), preedit_right_local, 0); + LLRect preedit_rect_screen; + localRectToScreen(preedit_rect_local, &preedit_rect_screen); + LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds); + } + + return TRUE; } void LLLineEditor::getPreeditRange(S32 *position, S32 *length) const { - if (hasPreeditString()) - { - *position = mPreeditPositions.front(); - *length = mPreeditPositions.back() - mPreeditPositions.front(); - } - else - { - *position = mCursorPos; - *length = 0; - } + if (hasPreeditString()) + { + *position = mPreeditPositions.front(); + *length = mPreeditPositions.back() - mPreeditPositions.front(); + } + else + { + *position = mCursorPos; + *length = 0; + } } void LLLineEditor::getSelectionRange(S32 *position, S32 *length) const { - if (hasSelection()) - { - *position = llmin(mSelectionStart, mSelectionEnd); - *length = llabs(mSelectionStart - mSelectionEnd); - } - else - { - *position = mCursorPos; - *length = 0; - } + if (hasSelection()) + { + *position = llmin(mSelectionStart, mSelectionEnd); + *length = llabs(mSelectionStart - mSelectionEnd); + } + else + { + *position = mCursorPos; + *length = 0; + } } void LLLineEditor::markAsPreedit(S32 position, S32 length) { - deselect(); - setCursor(position); - if (hasPreeditString()) - { - LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL; - } - mPreeditWString.assign( LLWString( mText.getWString(), position, length ) ); - if (length > 0) - { - mPreeditPositions.resize(2); - mPreeditPositions[0] = position; - mPreeditPositions[1] = position + length; - mPreeditStandouts.resize(1); - mPreeditStandouts[0] = FALSE; - } - else - { - mPreeditPositions.clear(); - mPreeditStandouts.clear(); - } - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - mPreeditOverwrittenWString = mPreeditWString; - } - else - { - mPreeditOverwrittenWString.clear(); - } + deselect(); + setCursor(position); + if (hasPreeditString()) + { + LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL; + } + mPreeditWString.assign( LLWString( mText.getWString(), position, length ) ); + if (length > 0) + { + mPreeditPositions.resize(2); + mPreeditPositions[0] = position; + mPreeditPositions[1] = position + length; + mPreeditStandouts.resize(1); + mPreeditStandouts[0] = FALSE; + } + else + { + mPreeditPositions.clear(); + mPreeditStandouts.clear(); + } + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + mPreeditOverwrittenWString = mPreeditWString; + } + else + { + mPreeditOverwrittenWString.clear(); + } } S32 LLLineEditor::getPreeditFontSize() const { - return ll_round(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); + return ll_round(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace) { - mReplaceNewlinesWithSpaces = replace; + mReplaceNewlinesWithSpaces = replace; } LLWString LLLineEditor::getConvertedText() const { - LLWString text = getWText(); - LLWStringUtil::trim(text); - if (!mReplaceNewlinesWithSpaces) - { - LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. - } - return text; + LLWString text = getWText(); + LLWStringUtil::trim(text); + if (!mReplaceNewlinesWithSpaces) + { + LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. + } + return text; } void LLLineEditor::showContextMenu(S32 x, S32 y) { - LLContextMenu* menu = static_cast(mContextMenuHandle.get()); - if (!menu) - { - llassert(LLMenuGL::sMenuContainer != NULL); - menu = LLUICtrlFactory::createFromFile - ("menu_text_editor.xml", - LLMenuGL::sMenuContainer, - LLMenuHolderGL::child_registry_t::instance()); - setContextMenu(menu); - } - - if (menu) - { - gEditMenuHandler = this; - - S32 screen_x, screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - - setCursorAtLocalPos(x); - if (hasSelection()) - { - if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) - { - deselect(); - } - else - { - setCursor(llmax(mSelectionStart, mSelectionEnd)); - } - } - - bool use_spellcheck = getSpellCheck(), is_misspelled = false; - if (use_spellcheck) - { - mSuggestionList.clear(); - - // If the cursor is on a misspelled word, retrieve suggestions for it - std::string misspelled_word = getMisspelledWord(mCursorPos); - if ((is_misspelled = !misspelled_word.empty()) == true) - { - LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); - } - } - - 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); - } + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (!menu) + { + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::createFromFile + ("menu_text_editor.xml", + LLMenuGL::sMenuContainer, + LLMenuHolderGL::child_registry_t::instance()); + setContextMenu(menu); + } + + if (menu) + { + gEditMenuHandler = this; + + S32 screen_x, screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + setCursorAtLocalPos(x); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursor(llmax(mSelectionStart, mSelectionEnd)); + } + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + 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); + } } void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu) @@ -2715,5 +2715,5 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu) void LLLineEditor::setFont(const LLFontGL* font) { - mGLFont = font; + mGLFont = font; } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 5794b3c35a..65afa54d04 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -1,34 +1,34 @@ -/** +/** * @file lllineeditor.h * @brief Text editor widget to let users enter/edit a single line. * - * Features: - * Text entry of a single line (text, delete, left and right arrow, insert, return). - * Callbacks either on every keystroke or just on the return key. - * Focus (allow multiple text entry widgets) - * Clipboard (cut, copy, and paste) - * Horizontal scrolling to allow strings longer than widget size allows - * Pre-validation (limit which keys can be used) - * Optional line history so previous entries can be recalled by CTRL UP/DOWN + * Features: + * Text entry of a single line (text, delete, left and right arrow, insert, return). + * Callbacks either on every keystroke or just on the return key. + * Focus (allow multiple text entry widgets) + * Clipboard (cut, copy, and paste) + * Horizontal scrolling to allow strings longer than widget size allows + * Pre-validation (limit which keys can be used) + * Optional line history so previous entries can be recalled by CTRL UP/DOWN * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -59,412 +59,412 @@ class LLLineEditor { public: - typedef boost::function keystroke_callback_t; - - struct MaxLength : public LLInitParam::ChoiceBlock - { - Alternative bytes, chars; - - MaxLength() : bytes("max_length_bytes", 254), - chars("max_length_chars", 0) - {} - }; - - struct Params : public LLInitParam::Block - { - Optional default_text; - Optional max_length; - Optional keystroke_callback; - - Optional prevalidate_callback; - Optional prevalidate_input_callback; - - Optional border; - - Optional background_image, - background_image_disabled, - background_image_focused; - - Optional select_on_focus, - revert_on_esc, - spellcheck, - commit_on_focus_lost, - ignore_tab, - bg_image_always_focused, - show_label_focused, - is_password, - use_bg_color; - - // colors - Optional cursor_color, - bg_color, - text_color, - text_readonly_color, - text_tentative_color, - highlight_color, - preedit_bg_color; - - Optional text_pad_left, - text_pad_right; - - Ignored bg_visible; - - Params(); - }; - - void initFromParams(const LLLineEditor::Params& params); + typedef boost::function keystroke_callback_t; + + struct MaxLength : public LLInitParam::ChoiceBlock + { + Alternative bytes, chars; + + MaxLength() : bytes("max_length_bytes", 254), + chars("max_length_chars", 0) + {} + }; + + struct Params : public LLInitParam::Block + { + Optional default_text; + Optional max_length; + Optional keystroke_callback; + + Optional prevalidate_callback; + Optional prevalidate_input_callback; + + Optional border; + + Optional background_image, + background_image_disabled, + background_image_focused; + + Optional select_on_focus, + revert_on_esc, + spellcheck, + commit_on_focus_lost, + ignore_tab, + bg_image_always_focused, + show_label_focused, + is_password, + use_bg_color; + + // colors + Optional cursor_color, + bg_color, + text_color, + text_readonly_color, + text_tentative_color, + highlight_color, + preedit_bg_color; + + Optional text_pad_left, + text_pad_right; + + Ignored bg_visible; + + Params(); + }; + + void initFromParams(const LLLineEditor::Params& params); protected: - LLLineEditor(const Params&); - friend class LLUICtrlFactory; - friend class LLFloaterEditUI; - void showContextMenu(S32 x, S32 y); + LLLineEditor(const Params&); + friend class LLUICtrlFactory; + friend class LLFloaterEditUI; + void showContextMenu(S32 x, S32 y); public: - virtual ~LLLineEditor(); - - // mousehandler overrides - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask) override; - /*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask) override; - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask) override; - /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char) override; - /*virtual*/ void onMouseCaptureLost() override; - - // LLEditMenuHandler overrides - /*virtual*/ void cut() override; - /*virtual*/ BOOL canCut() const override; - /*virtual*/ void copy() override; - /*virtual*/ BOOL canCopy() const override; - /*virtual*/ void paste() override; - /*virtual*/ BOOL canPaste() const override; - - virtual void updatePrimary(); - virtual void copyPrimary(); - virtual void pastePrimary(); - virtual BOOL canPastePrimary() const; - - /*virtual*/ void doDelete() override; - /*virtual*/ BOOL canDoDelete() const override; - - /*virtual*/ void selectAll() override; - /*virtual*/ BOOL canSelectAll() const override; - - /*virtual*/ void deselect() override; - /*virtual*/ BOOL canDeselect() const override; - - // LLSpellCheckMenuHandler overrides - /*virtual*/ bool getSpellCheck() const override; - - /*virtual*/ const std::string& getSuggestion(U32 index) const override; - /*virtual*/ U32 getSuggestionCount() const override; - /*virtual*/ void replaceWithSuggestion(U32 index) override; - - /*virtual*/ void addToDictionary() override; - /*virtual*/ bool canAddToDictionary() const override; - - /*virtual*/ void addToIgnore() override; - /*virtual*/ bool canAddToIgnore() const override; - - // Spell checking helper functions - std::string getMisspelledWord(U32 pos) const; - bool isMisspelledWord(U32 pos) const; - void onSpellCheckSettingsChange(); - - // view overrides - /*virtual*/ const std::string getToolTip() const override; - /*virtual*/ void draw() override; - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; - /*virtual*/ void onFocusReceived() override; - /*virtual*/ void onFocusLost() override; - /*virtual*/ void setEnabled(BOOL enabled) override; - - // UI control overrides - /*virtual*/ void clear() override; - /*virtual*/ void onTabInto() override; - /*virtual*/ void setFocus(BOOL b) override; - /*virtual*/ void setRect(const LLRect& rect) override; - /*virtual*/ BOOL acceptsTextInput() const override; - /*virtual*/ void onCommit() override; - /*virtual*/ BOOL isDirty() const override; // Returns TRUE if user changed value at all - /*virtual*/ void resetDirty() override; // Clear dirty state - - // assumes UTF8 text - /*virtual*/ void setValue(const LLSD& value) override; - /*virtual*/ LLSD getValue() const override; - /*virtual*/ BOOL setTextArg(const std::string& key, const LLStringExplicit& text) override; - /*virtual*/ BOOL setLabelArg(const std::string& key, const LLStringExplicit& text) override; - - void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } - const std::string& getLabel() { return mLabel.getString(); } - - void setText(const LLStringExplicit &new_text); - - const std::string& getText() const { return mText.getString(); } - LLWString getWText() const { return mText.getWString(); } - LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines - - S32 getLength() const { return mText.length(); } - - S32 getCursor() const { return mCursorPos; } - void setCursor( S32 pos ); - void setCursorToEnd(); - - // set scroll to earliest position it can reasonable set - void resetScrollPosition(); - - // Selects characters 'start' to 'end'. - void setSelection(S32 start, S32 end); - /*virtual*/ void getSelectionRange(S32 *position, S32 *length) const override; - - void setCommitOnFocusLost( BOOL b ) { mCommitOnFocusLost = b; } - void setRevertOnEsc( BOOL b ) { mRevertOnEsc = b; } - void setKeystrokeOnEsc(BOOL b) { mKeystrokeOnEsc = b; } - - void setCursorColor(const LLColor4& c) { mCursorColor = c; } - const LLColor4& getCursorColor() const { return mCursorColor.get(); } - - void setFgColor( const LLColor4& c ) { mFgColor = c; } - void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; } - void setTentativeFgColor(const LLColor4& c) { mTentativeFgColor = c; } - - const LLColor4& getFgColor() const { return mFgColor.get(); } - const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); } - const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } - - const LLFontGL* getFont() const { return mGLFont; } - void setFont(const LLFontGL* font); - - void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } - void setIgnoreTab(BOOL b) { mIgnoreTab = b; } - void setPassDelete(BOOL b) { mPassDelete = b; } - void setDrawAsterixes(BOOL b); - - // get the cursor position of the beginning/end of the prev/next word in the text - S32 prevWordPos(S32 cursorPos) const; - S32 nextWordPos(S32 cursorPos) const; - - BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); } - void startSelection(); - void endSelection(); - void extendSelection(S32 new_cursor_pos); - void deleteSelection(); - - void setSelectAllonFocusReceived(BOOL b); - void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; } - - void onKeystroke(); - typedef boost::function callback_t; - void setKeystrokeCallback(callback_t callback, void* user_data); - - void setMaxTextLength(S32 max_text_length); - void setMaxTextChars(S32 max_text_chars); - // Manipulate left and right padding for text - void getTextPadding(S32 *left, S32 *right); - void setTextPadding(S32 left, S32 right); - - // Prevalidation controls which keystrokes can affect the editor - void setPrevalidate( LLTextValidate::validate_func_t func ); - // This method sets callback that prevents from: - // - deleting, selecting, typing, cutting, pasting characters that are not valid. - // Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed - // symbols, before existing text is modified, but setPrevalidate validates line after it was modified. - void setPrevalidateInput(LLTextValidate::validate_func_t func); - static BOOL postvalidateFloat(const std::string &str); - - bool prevalidateInput(const LLWString& wstr); - BOOL evaluateFloat(); - - // line history support: - void setEnableLineHistory( BOOL enabled ) { mHaveHistory = enabled; } // switches line history on or off - void updateHistory(); // stores current line in history - - void setReplaceNewlinesWithSpaces(BOOL replace); - - void resetContextMenu() { setContextMenu(NULL); }; - - void setBgImage(LLPointer image) { mBgImage = image; } - void setBgImageFocused(LLPointer image) { mBgImageFocused = image; } + virtual ~LLLineEditor(); + + // mousehandler overrides + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask) override; + /*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask) override; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask) override; + /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char) override; + /*virtual*/ void onMouseCaptureLost() override; + + // LLEditMenuHandler overrides + /*virtual*/ void cut() override; + /*virtual*/ BOOL canCut() const override; + /*virtual*/ void copy() override; + /*virtual*/ BOOL canCopy() const override; + /*virtual*/ void paste() override; + /*virtual*/ BOOL canPaste() const override; + + virtual void updatePrimary(); + virtual void copyPrimary(); + virtual void pastePrimary(); + virtual BOOL canPastePrimary() const; + + /*virtual*/ void doDelete() override; + /*virtual*/ BOOL canDoDelete() const override; + + /*virtual*/ void selectAll() override; + /*virtual*/ BOOL canSelectAll() const override; + + /*virtual*/ void deselect() override; + /*virtual*/ BOOL canDeselect() const override; + + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const override; + + /*virtual*/ const std::string& getSuggestion(U32 index) const override; + /*virtual*/ U32 getSuggestionCount() const override; + /*virtual*/ void replaceWithSuggestion(U32 index) override; + + /*virtual*/ void addToDictionary() override; + /*virtual*/ bool canAddToDictionary() const override; + + /*virtual*/ void addToIgnore() override; + /*virtual*/ bool canAddToIgnore() const override; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + + // view overrides + /*virtual*/ const std::string getToolTip() const override; + /*virtual*/ void draw() override; + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; + /*virtual*/ void onFocusReceived() override; + /*virtual*/ void onFocusLost() override; + /*virtual*/ void setEnabled(BOOL enabled) override; + + // UI control overrides + /*virtual*/ void clear() override; + /*virtual*/ void onTabInto() override; + /*virtual*/ void setFocus(BOOL b) override; + /*virtual*/ void setRect(const LLRect& rect) override; + /*virtual*/ BOOL acceptsTextInput() const override; + /*virtual*/ void onCommit() override; + /*virtual*/ BOOL isDirty() const override; // Returns TRUE if user changed value at all + /*virtual*/ void resetDirty() override; // Clear dirty state + + // assumes UTF8 text + /*virtual*/ void setValue(const LLSD& value) override; + /*virtual*/ LLSD getValue() const override; + /*virtual*/ BOOL setTextArg(const std::string& key, const LLStringExplicit& text) override; + /*virtual*/ BOOL setLabelArg(const std::string& key, const LLStringExplicit& text) override; + + void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } + const std::string& getLabel() { return mLabel.getString(); } + + void setText(const LLStringExplicit &new_text); + + const std::string& getText() const { return mText.getString(); } + LLWString getWText() const { return mText.getWString(); } + LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines + + S32 getLength() const { return mText.length(); } + + S32 getCursor() const { return mCursorPos; } + void setCursor( S32 pos ); + void setCursorToEnd(); + + // set scroll to earliest position it can reasonable set + void resetScrollPosition(); + + // Selects characters 'start' to 'end'. + void setSelection(S32 start, S32 end); + /*virtual*/ void getSelectionRange(S32 *position, S32 *length) const override; + + void setCommitOnFocusLost( BOOL b ) { mCommitOnFocusLost = b; } + void setRevertOnEsc( BOOL b ) { mRevertOnEsc = b; } + void setKeystrokeOnEsc(BOOL b) { mKeystrokeOnEsc = b; } + + void setCursorColor(const LLColor4& c) { mCursorColor = c; } + const LLColor4& getCursorColor() const { return mCursorColor.get(); } + + void setFgColor( const LLColor4& c ) { mFgColor = c; } + void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; } + void setTentativeFgColor(const LLColor4& c) { mTentativeFgColor = c; } + + const LLColor4& getFgColor() const { return mFgColor.get(); } + const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); } + const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } + + const LLFontGL* getFont() const { return mGLFont; } + void setFont(const LLFontGL* font); + + void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } + void setIgnoreTab(BOOL b) { mIgnoreTab = b; } + void setPassDelete(BOOL b) { mPassDelete = b; } + void setDrawAsterixes(BOOL b); + + // get the cursor position of the beginning/end of the prev/next word in the text + S32 prevWordPos(S32 cursorPos) const; + S32 nextWordPos(S32 cursorPos) const; + + BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); } + void startSelection(); + void endSelection(); + void extendSelection(S32 new_cursor_pos); + void deleteSelection(); + + void setSelectAllonFocusReceived(BOOL b); + void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; } + + void onKeystroke(); + typedef boost::function callback_t; + void setKeystrokeCallback(callback_t callback, void* user_data); + + void setMaxTextLength(S32 max_text_length); + void setMaxTextChars(S32 max_text_chars); + // Manipulate left and right padding for text + void getTextPadding(S32 *left, S32 *right); + void setTextPadding(S32 left, S32 right); + + // Prevalidation controls which keystrokes can affect the editor + void setPrevalidate( LLTextValidate::validate_func_t func ); + // This method sets callback that prevents from: + // - deleting, selecting, typing, cutting, pasting characters that are not valid. + // Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed + // symbols, before existing text is modified, but setPrevalidate validates line after it was modified. + void setPrevalidateInput(LLTextValidate::validate_func_t func); + static BOOL postvalidateFloat(const std::string &str); + + bool prevalidateInput(const LLWString& wstr); + BOOL evaluateFloat(); + + // line history support: + void setEnableLineHistory( BOOL enabled ) { mHaveHistory = enabled; } // switches line history on or off + void updateHistory(); // stores current line in history + + void setReplaceNewlinesWithSpaces(BOOL replace); + + void resetContextMenu() { setContextMenu(NULL); }; + + void setBgImage(LLPointer image) { mBgImage = image; } + void setBgImageFocused(LLPointer image) { mBgImageFocused = image; } void setShowContextMenu(bool show) { mShowContextMenu = show; } bool getShowContextMenu() const { return mShowContextMenu; } private: - // private helper methods - - void pasteHelper(bool is_primary); - - void removeChar(); - void addChar(const llwchar c); - void setCursorAtLocalPos(S32 local_mouse_x); - S32 findPixelNearestPos(S32 cursor_offset = 0) const; - S32 calcCursorPos(S32 mouse_x); - BOOL handleSpecialKey(KEY key, MASK mask); - BOOL handleSelectionKey(KEY key, MASK mask); - BOOL handleControlKey(KEY key, MASK mask); - S32 handleCommitKey(KEY key, MASK mask); - void updateTextPadding(); - - // Draw the background image depending on enabled/focused state. - void drawBackground(); - - // - // private data members - // - void updateAllowingLanguageInput(); - BOOL hasPreeditString() const; - // Implementation (overrides) of LLPreeditor - /*virtual*/ void resetPreedit() override; - /*virtual*/ void updatePreedit(const LLWString &preedit_string, - const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) override; - /*virtual*/ void markAsPreedit(S32 position, S32 length) override; - /*virtual*/ void getPreeditRange(S32 *position, S32 *length) const override; - /*virtual*/ BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const override; - /*virtual*/ S32 getPreeditFontSize() const override; - /*virtual*/ LLWString getPreeditString() const override { return getWText(); } - - void setText(const LLStringExplicit &new_text, bool use_size_limit); - - void setContextMenu(LLContextMenu* new_context_menu); + // private helper methods + + void pasteHelper(bool is_primary); + + void removeChar(); + void addChar(const llwchar c); + void setCursorAtLocalPos(S32 local_mouse_x); + S32 findPixelNearestPos(S32 cursor_offset = 0) const; + S32 calcCursorPos(S32 mouse_x); + BOOL handleSpecialKey(KEY key, MASK mask); + BOOL handleSelectionKey(KEY key, MASK mask); + BOOL handleControlKey(KEY key, MASK mask); + S32 handleCommitKey(KEY key, MASK mask); + void updateTextPadding(); + + // Draw the background image depending on enabled/focused state. + void drawBackground(); + + // + // private data members + // + void updateAllowingLanguageInput(); + BOOL hasPreeditString() const; + // Implementation (overrides) of LLPreeditor + /*virtual*/ void resetPreedit() override; + /*virtual*/ void updatePreedit(const LLWString &preedit_string, + const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) override; + /*virtual*/ void markAsPreedit(S32 position, S32 length) override; + /*virtual*/ void getPreeditRange(S32 *position, S32 *length) const override; + /*virtual*/ BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const override; + /*virtual*/ S32 getPreeditFontSize() const override; + /*virtual*/ LLWString getPreeditString() const override { return getWText(); } + + void setText(const LLStringExplicit &new_text, bool use_size_limit); + + void setContextMenu(LLContextMenu* new_context_menu); protected: - LLUIString mText; // The string being edited. - std::string mPrevText; // Saved string for 'ESC' revert - LLUIString mLabel; // text label that is visible when no user text provided - - // line history support: - BOOL mHaveHistory; // flag for enabled line history - typedef std::vector line_history_t; - line_history_t mLineHistory; // line history storage - line_history_t::iterator mCurrentHistoryLine; // currently browsed history line - - LLViewBorder* mBorder; - const LLFontGL* mGLFont; - S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes - S32 mMaxLengthChars; // Maximum number of characters in the string - S32 mCursorPos; // I-beam is just after the mCursorPos-th character. - S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling. - LLFrameTimer mScrollTimer; - S32 mTextPadLeft; // Used to reserve space before the beginning of the text for children. - S32 mTextPadRight; // Used to reserve space after the end of the text for children. - S32 mTextLeftEdge; // Pixels, cached left edge of text based on left padding and width - S32 mTextRightEdge; // Pixels, cached right edge of text based on right padding and width - - BOOL mCommitOnFocusLost; - BOOL mRevertOnEsc; - BOOL mKeystrokeOnEsc; - - keystroke_callback_t mKeystrokeCallback; - - BOOL mIsSelecting; // Selection for clipboard operations - S32 mSelectionStart; - S32 mSelectionEnd; - S32 mLastSelectionX; - S32 mLastSelectionY; - S32 mLastSelectionStart; - S32 mLastSelectionEnd; - - bool mSpellCheck; - S32 mSpellCheckStart; - S32 mSpellCheckEnd; - LLTimer mSpellCheckTimer; - std::list > mMisspellRanges; - std::vector mSuggestionList; - - LLTextValidate::validate_func_t mPrevalidateFunc; - LLTextValidate::validate_func_t mPrevalidateInputFunc; - - LLFrameTimer mKeystrokeTimer; - LLTimer mTripleClickTimer; - - LLUIColor mCursorColor; - LLUIColor mBgColor; - LLUIColor mFgColor; - LLUIColor mReadOnlyFgColor; - LLUIColor mTentativeFgColor; - LLUIColor mHighlightColor; // background for selected text - LLUIColor mPreeditBgColor; // preedit marker background color - - S32 mBorderThickness; - - BOOL mIgnoreArrowKeys; - BOOL mIgnoreTab; - BOOL mDrawAsterixes; - - BOOL mSelectAllonFocusReceived; - BOOL mSelectAllonCommit; - BOOL mPassDelete; - - BOOL mReadOnly; - - BOOL mShowImageFocused; - BOOL mShowLabelFocused; - - bool mUseBgColor; - - LLWString mPreeditWString; - LLWString mPreeditOverwrittenWString; - std::vector mPreeditPositions; - LLPreeditor::standouts_t mPreeditStandouts; - - LLHandle mContextMenuHandle; + LLUIString mText; // The string being edited. + std::string mPrevText; // Saved string for 'ESC' revert + LLUIString mLabel; // text label that is visible when no user text provided + + // line history support: + BOOL mHaveHistory; // flag for enabled line history + typedef std::vector line_history_t; + line_history_t mLineHistory; // line history storage + line_history_t::iterator mCurrentHistoryLine; // currently browsed history line + + LLViewBorder* mBorder; + const LLFontGL* mGLFont; + S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes + S32 mMaxLengthChars; // Maximum number of characters in the string + S32 mCursorPos; // I-beam is just after the mCursorPos-th character. + S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling. + LLFrameTimer mScrollTimer; + S32 mTextPadLeft; // Used to reserve space before the beginning of the text for children. + S32 mTextPadRight; // Used to reserve space after the end of the text for children. + S32 mTextLeftEdge; // Pixels, cached left edge of text based on left padding and width + S32 mTextRightEdge; // Pixels, cached right edge of text based on right padding and width + + BOOL mCommitOnFocusLost; + BOOL mRevertOnEsc; + BOOL mKeystrokeOnEsc; + + keystroke_callback_t mKeystrokeCallback; + + BOOL mIsSelecting; // Selection for clipboard operations + S32 mSelectionStart; + S32 mSelectionEnd; + S32 mLastSelectionX; + S32 mLastSelectionY; + S32 mLastSelectionStart; + S32 mLastSelectionEnd; + + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list > mMisspellRanges; + std::vector mSuggestionList; + + LLTextValidate::validate_func_t mPrevalidateFunc; + LLTextValidate::validate_func_t mPrevalidateInputFunc; + + LLFrameTimer mKeystrokeTimer; + LLTimer mTripleClickTimer; + + LLUIColor mCursorColor; + LLUIColor mBgColor; + LLUIColor mFgColor; + LLUIColor mReadOnlyFgColor; + LLUIColor mTentativeFgColor; + LLUIColor mHighlightColor; // background for selected text + LLUIColor mPreeditBgColor; // preedit marker background color + + S32 mBorderThickness; + + BOOL mIgnoreArrowKeys; + BOOL mIgnoreTab; + BOOL mDrawAsterixes; + + BOOL mSelectAllonFocusReceived; + BOOL mSelectAllonCommit; + BOOL mPassDelete; + + BOOL mReadOnly; + + BOOL mShowImageFocused; + BOOL mShowLabelFocused; + + bool mUseBgColor; + + LLWString mPreeditWString; + LLWString mPreeditOverwrittenWString; + std::vector mPreeditPositions; + LLPreeditor::standouts_t mPreeditStandouts; + + LLHandle mContextMenuHandle; bool mShowContextMenu; private: - // Instances that by default point to the statics but can be overidden in XML. - LLPointer mBgImage; - LLPointer mBgImageDisabled; - LLPointer mBgImageFocused; - - BOOL mReplaceNewlinesWithSpaces; // if false, will replace pasted newlines with paragraph symbol. - - // private helper class - class LLLineEditorRollback - { - public: - LLLineEditorRollback( LLLineEditor* ed ) - : - mCursorPos( ed->mCursorPos ), - mScrollHPos( ed->mScrollHPos ), - mIsSelecting( ed->mIsSelecting ), - mSelectionStart( ed->mSelectionStart ), - mSelectionEnd( ed->mSelectionEnd ) - { - mText = ed->getText(); - } - - void doRollback( LLLineEditor* ed ) - { - ed->mCursorPos = mCursorPos; - ed->mScrollHPos = mScrollHPos; - ed->mIsSelecting = mIsSelecting; - ed->mSelectionStart = mSelectionStart; - ed->mSelectionEnd = mSelectionEnd; - ed->mText = mText; - ed->mPrevText = mText; - } - - std::string getText() { return mText; } - - private: - std::string mText; - S32 mCursorPos; - S32 mScrollHPos; - BOOL mIsSelecting; - S32 mSelectionStart; - S32 mSelectionEnd; - }; // end class LLLineEditorRollback + // Instances that by default point to the statics but can be overidden in XML. + LLPointer mBgImage; + LLPointer mBgImageDisabled; + LLPointer mBgImageFocused; + + BOOL mReplaceNewlinesWithSpaces; // if false, will replace pasted newlines with paragraph symbol. + + // private helper class + class LLLineEditorRollback + { + public: + LLLineEditorRollback( LLLineEditor* ed ) + : + mCursorPos( ed->mCursorPos ), + mScrollHPos( ed->mScrollHPos ), + mIsSelecting( ed->mIsSelecting ), + mSelectionStart( ed->mSelectionStart ), + mSelectionEnd( ed->mSelectionEnd ) + { + mText = ed->getText(); + } + + void doRollback( LLLineEditor* ed ) + { + ed->mCursorPos = mCursorPos; + ed->mScrollHPos = mScrollHPos; + ed->mIsSelecting = mIsSelecting; + ed->mSelectionStart = mSelectionStart; + ed->mSelectionEnd = mSelectionEnd; + ed->mText = mText; + ed->mPrevText = mText; + } + + std::string getText() { return mText; } + + private: + std::string mText; + S32 mCursorPos; + S32 mScrollHPos; + BOOL mIsSelecting; + S32 mSelectionStart; + S32 mSelectionEnd; + }; // end class LLLineEditorRollback }; // end class LLLineEditor // Build time optimization, generate once in .cpp file #ifndef LLLINEEDITOR_CPP extern template class LLLineEditor* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; #endif #endif // LL_LINEEDITOR_ diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index e8b6b7e43b..70730705e6 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llloadingindicator.cpp * @brief Perpetual loading indicator * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -43,57 +43,57 @@ /////////////////////////////////////////////////////////////////////////////// LLLoadingIndicator::LLLoadingIndicator(const Params& p) -: LLUICtrl(p), - mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f), - mCurImageIdx(0) +: LLUICtrl(p), + mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f), + mCurImageIdx(0) { } void LLLoadingIndicator::initFromParams(const Params& p) { - for (LLUIImage* image : p.images().image) - { - mImages.push_back(image); - } + for (LLUIImage* image : p.images().image) + { + mImages.push_back(image); + } - // Start timer for switching images. - start(); + // Start timer for switching images. + start(); } void LLLoadingIndicator::draw() { - // Time to switch to the next image? - if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired()) - { - // Switch to the next image. - if (!mImages.empty()) - { - mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); - } - - // Restart timer. - start(); - } - - LLUIImagePtr cur_image = mImages.empty() ? LLUIImagePtr(NULL) : mImages[mCurImageIdx]; - - // Draw current image. - if( cur_image.notNull() ) - { - cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); - } - - LLUICtrl::draw(); + // Time to switch to the next image? + if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired()) + { + // Switch to the next image. + if (!mImages.empty()) + { + mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); + } + + // Restart timer. + start(); + } + + LLUIImagePtr cur_image = mImages.empty() ? LLUIImagePtr(NULL) : mImages[mCurImageIdx]; + + // Draw current image. + if( cur_image.notNull() ) + { + cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); + } + + LLUICtrl::draw(); } void LLLoadingIndicator::stop() { - mImageSwitchTimer.stop(); + mImageSwitchTimer.stop(); } void LLLoadingIndicator::start() { - mImageSwitchTimer.start(); - F32 period = 1.0f / (mImages.size() * mImagesPerSec); - mImageSwitchTimer.setTimerExpirySec(period); + mImageSwitchTimer.start(); + F32 period = 1.0f / (mImages.size() * mImagesPerSec); + mImageSwitchTimer.setTimerExpirySec(period); } diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index ffcb329f42..5e824af993 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -1,25 +1,25 @@ -/** +/** * @file llloadingindicator.h * @brief Perpetual loading indicator * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,69 +36,69 @@ /** * Perpetual loading indicator (a la MacOSX or YouTube) - * + * * Number of rotations per second can be overridden * with the "images_per_sec" parameter. - * + * * Can start/stop spinning. - * + * * @see start() * @see stop() */ class LLLoadingIndicator : public LLUICtrl { - LOG_CLASS(LLLoadingIndicator); + LOG_CLASS(LLLoadingIndicator); public: - struct Images : public LLInitParam::Block - { - Multiple image; + struct Images : public LLInitParam::Block + { + Multiple image; - Images() - : image("image") - {} - }; + Images() + : image("image") + {} + }; - struct Params : public LLInitParam::Block - { - Optional images_per_sec; - Optional > images; + struct Params : public LLInitParam::Block + { + Optional images_per_sec; + Optional > images; - Params() - : images_per_sec("images_per_sec", 1.0f), - images("images") - {} - }; + Params() + : images_per_sec("images_per_sec", 1.0f), + images("images") + {} + }; - virtual ~LLLoadingIndicator() {} + virtual ~LLLoadingIndicator() {} - // llview overrides - virtual void draw(); + // llview overrides + virtual void draw(); - /** - * Stop spinning. - */ - void stop(); + /** + * Stop spinning. + */ + void stop(); - /** - * Start spinning. - */ - void start(); + /** + * Start spinning. + */ + void start(); - void reset() { mCurImageIdx = 0; } + void reset() { mCurImageIdx = 0; } private: - LLLoadingIndicator(const Params&); - void initFromParams(const Params&); + LLLoadingIndicator(const Params&); + void initFromParams(const Params&); - friend class LLUICtrlFactory; + friend class LLUICtrlFactory; - F32 mImagesPerSec; - S8 mCurImageIdx; - LLFrameTimer mImageSwitchTimer; + F32 mImagesPerSec; + S8 mCurImageIdx; + LLFrameTimer mImageSwitchTimer; - std::vector mImages; + std::vector mImages; }; #endif // LL_LLLOADINGINDICATOR_H diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index f3a526faeb..f8ccb807e6 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -1,24 +1,24 @@ -/** +/** * @file lllocalcliprect.cpp * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,77 +33,77 @@ LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) -: mScissorState(GL_SCISSOR_TEST), - mEnabled(enabled) +: mScissorState(GL_SCISSOR_TEST), + mEnabled(enabled) { - if (mEnabled) - { - pushClipRect(rect); - mScissorState.setEnabled(!sClipRectStack.empty()); - updateScissorRegion(); - } + if (mEnabled) + { + pushClipRect(rect); + mScissorState.setEnabled(!sClipRectStack.empty()); + updateScissorRegion(); + } } LLScreenClipRect::~LLScreenClipRect() { - if (mEnabled) - { - popClipRect(); - updateScissorRegion(); - } + if (mEnabled) + { + popClipRect(); + updateScissorRegion(); + } } -//static +//static void LLScreenClipRect::pushClipRect(const LLRect& rect) { - LLRect combined_clip_rect = rect; - if (!sClipRectStack.empty()) - { - LLRect top = sClipRectStack.top(); - combined_clip_rect.intersectWith(top); + LLRect combined_clip_rect = rect; + if (!sClipRectStack.empty()) + { + LLRect top = sClipRectStack.top(); + combined_clip_rect.intersectWith(top); - if(combined_clip_rect.isEmpty()) - { - // avoid artifacts where zero area rects show up as lines - combined_clip_rect = LLRect::null; - } - } - sClipRectStack.push(combined_clip_rect); + if(combined_clip_rect.isEmpty()) + { + // avoid artifacts where zero area rects show up as lines + combined_clip_rect = LLRect::null; + } + } + sClipRectStack.push(combined_clip_rect); } -//static +//static void LLScreenClipRect::popClipRect() { - sClipRectStack.pop(); + sClipRectStack.pop(); } //static void LLScreenClipRect::updateScissorRegion() { - if (sClipRectStack.empty()) return; + if (sClipRectStack.empty()) return; - // finish any deferred calls in the old clipping region - gGL.flush(); + // finish any deferred calls in the old clipping region + gGL.flush(); - LLRect rect = sClipRectStack.top(); - stop_glerror(); - S32 x,y,w,h; - x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); - y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); - w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; - h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; - glScissor( x,y,w,h ); - stop_glerror(); + LLRect rect = sClipRectStack.top(); + stop_glerror(); + S32 x,y,w,h; + x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); + y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); + w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; + h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; + glScissor( x,y,w,h ); + stop_glerror(); } //--------------------------------------------------------------------------- // LLLocalClipRect //--------------------------------------------------------------------------- LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */) -: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX, - rect.mTop + LLFontGL::sCurOrigin.mY, - rect.mRight + LLFontGL::sCurOrigin.mX, - rect.mBottom + LLFontGL::sCurOrigin.mY), enabled) +: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX, + rect.mTop + LLFontGL::sCurOrigin.mY, + rect.mRight + LLFontGL::sCurOrigin.mX, + rect.mBottom + LLFontGL::sCurOrigin.mY), enabled) {} LLLocalClipRect::~LLLocalClipRect() diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h index eeeaf2adb6..cb74de7c22 100644 --- a/indra/llui/lllocalcliprect.h +++ b/indra/llui/lllocalcliprect.h @@ -1,24 +1,24 @@ -/** +/** * @file lllocalcliprect.h * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -26,7 +26,7 @@ #define LLLOCALCLIPRECT_H #include "llgl.h" -#include "llrect.h" // can't forward declare, it's templated +#include "llrect.h" // can't forward declare, it's templated #include // Clip rendering to a specific rectangle using GL scissor @@ -38,26 +38,26 @@ class LLScreenClipRect { public: - LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); - virtual ~LLScreenClipRect(); + LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); + virtual ~LLScreenClipRect(); private: - static void pushClipRect(const LLRect& rect); - static void popClipRect(); - static void updateScissorRegion(); + static void pushClipRect(const LLRect& rect); + static void popClipRect(); + static void updateScissorRegion(); private: - LLGLState mScissorState; - BOOL mEnabled; + LLGLState mScissorState; + BOOL mEnabled; - static std::stack sClipRectStack; + static std::stack sClipRectStack; }; class LLLocalClipRect : public LLScreenClipRect { public: - LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); - ~LLLocalClipRect(); + LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); + ~LLLocalClipRect(); }; #endif diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 583704418b..bfc4c089f3 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbutton.cpp * @brief LLButton base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,210 +37,210 @@ static LLDefaultChildRegistry::Register r("menu_button"); void LLMenuButton::MenuPositions::declareValues() { - declare("topleft", MP_TOP_LEFT); - declare("topright", MP_TOP_RIGHT); - declare("bottomleft", MP_BOTTOM_LEFT); - declare("bottomright", MP_BOTTOM_RIGHT); + declare("topleft", MP_TOP_LEFT); + declare("topright", MP_TOP_RIGHT); + declare("bottomleft", MP_BOTTOM_LEFT); + declare("bottomright", MP_BOTTOM_RIGHT); } LLMenuButton::Params::Params() -: menu_filename("menu_filename"), - position("menu_position", MP_BOTTOM_LEFT) +: menu_filename("menu_filename"), + position("menu_position", MP_BOTTOM_LEFT) { - addSynonym(position, "position"); + addSynonym(position, "position"); } LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) -: LLButton(p), - mIsMenuShown(false), - mMenuPosition(p.position), - mOwnMenu(false) +: LLButton(p), + mIsMenuShown(false), + mMenuPosition(p.position), + mOwnMenu(false) { - std::string menu_filename = p.menu_filename; + std::string menu_filename = p.menu_filename; - setMenu(menu_filename, mMenuPosition); - updateMenuOrigin(); + setMenu(menu_filename, mMenuPosition); + updateMenuOrigin(); } LLMenuButton::~LLMenuButton() { - cleanup(); + cleanup(); } boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) { - return LLUICtrl::setMouseDownCallback(cb); + return LLUICtrl::setMouseDownCallback(cb); } void LLMenuButton::hideMenu() { - LLToggleableMenu* menu = getMenu(); - if (menu) - { - menu->setVisible(FALSE); - } + LLToggleableMenu* menu = getMenu(); + if (menu) + { + menu->setVisible(FALSE); + } } LLToggleableMenu* LLMenuButton::getMenu() { - return dynamic_cast(mMenuHandle.get()); + return dynamic_cast(mMenuHandle.get()); } void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) { - if (menu_filename.empty()) - { - return; - } - - llassert(LLMenuGL::sMenuContainer != NULL); - LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - LL_WARNS() << "Error loading menu_button menu" << LL_ENDL; - return; - } - - setMenu(menu, position, true); + if (menu_filename.empty()) + { + return; + } + + llassert(LLMenuGL::sMenuContainer != NULL); + LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + LL_WARNS() << "Error loading menu_button menu" << LL_ENDL; + return; + } + + setMenu(menu, position, true); } void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/) { - if (!menu) return; + if (!menu) return; - cleanup(); // destroy the previous memnu if we own it + cleanup(); // destroy the previous memnu if we own it - mMenuHandle = menu->getHandle(); - mMenuPosition = position; - mOwnMenu = take_ownership; + mMenuHandle = menu->getHandle(); + mMenuPosition = position; + mOwnMenu = take_ownership; - menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); + menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); } BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) { - if (!getMenu()) return FALSE; - - if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) - { - // *HACK: We emit the mouse down signal to fire the callback bound to the - // menu emerging event before actually displaying the menu. See STORM-263. - LLUICtrl::handleMouseDown(-1, -1, MASK_NONE); - - toggleMenu(); - return TRUE; - } - - LLToggleableMenu* menu = getMenu(); - if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) - { - menu->setVisible(FALSE); - return TRUE; - } - - return FALSE; + if (!getMenu()) return FALSE; + + if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) + { + // *HACK: We emit the mouse down signal to fire the callback bound to the + // menu emerging event before actually displaying the menu. See STORM-263. + LLUICtrl::handleMouseDown(-1, -1, MASK_NONE); + + toggleMenu(); + return TRUE; + } + + LLToggleableMenu* menu = getMenu(); + if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) + { + menu->setVisible(FALSE); + return TRUE; + } + + return FALSE; } BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) { - LLButton::handleMouseDown(x, y, mask); + LLButton::handleMouseDown(x, y, mask); + + toggleMenu(); - toggleMenu(); - - return TRUE; + return TRUE; } void LLMenuButton::toggleMenu() { - if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) - { - return; - } - - LLToggleableMenu* menu = getMenu(); - if (!menu) return; - - // Store the button rectangle to toggle menu visibility if a mouse event - // occurred inside or outside the button rect. - menu->setButtonRect(this); - - if (!menu->toggleVisibility() && mIsMenuShown) - { - setForcePressedState(false); - mIsMenuShown = false; - } - else - { - menu->buildDrawLabels(); - menu->arrangeAndClear(); - menu->updateParent(LLMenuGL::sMenuContainer); - - updateMenuOrigin(); - - LLMenuGL::showPopup(getParent(), menu, mX, mY); - - setForcePressedState(true); - mIsMenuShown = true; - } + if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) + { + return; + } + + LLToggleableMenu* menu = getMenu(); + if (!menu) return; + + // Store the button rectangle to toggle menu visibility if a mouse event + // occurred inside or outside the button rect. + menu->setButtonRect(this); + + if (!menu->toggleVisibility() && mIsMenuShown) + { + setForcePressedState(false); + mIsMenuShown = false; + } + else + { + menu->buildDrawLabels(); + menu->arrangeAndClear(); + menu->updateParent(LLMenuGL::sMenuContainer); + + updateMenuOrigin(); + + LLMenuGL::showPopup(getParent(), menu, mX, mY); + + setForcePressedState(true); + mIsMenuShown = true; + } } void LLMenuButton::updateMenuOrigin() { - LLToggleableMenu* menu = getMenu(); - if (!menu) return; - - LLRect rect = getRect(); - - switch (mMenuPosition) - { - case MP_TOP_LEFT: - { - mX = rect.mLeft; - mY = rect.mTop + menu->getRect().getHeight(); - break; - } - case MP_TOP_RIGHT: - { - const LLRect& menu_rect = menu->getRect(); - mX = rect.mRight - menu_rect.getWidth(); - mY = rect.mTop + menu_rect.getHeight(); - break; - } - case MP_BOTTOM_LEFT: - { - mX = rect.mLeft; - mY = rect.mBottom; - break; - } - case MP_BOTTOM_RIGHT: - { - const LLRect& menu_rect = menu->getRect(); - mX = rect.mRight - menu_rect.getWidth(); - mY = rect.mBottom; - break; - } - } + LLToggleableMenu* menu = getMenu(); + if (!menu) return; + + LLRect rect = getRect(); + + switch (mMenuPosition) + { + case MP_TOP_LEFT: + { + mX = rect.mLeft; + mY = rect.mTop + menu->getRect().getHeight(); + break; + } + case MP_TOP_RIGHT: + { + const LLRect& menu_rect = menu->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mTop + menu_rect.getHeight(); + break; + } + case MP_BOTTOM_LEFT: + { + mX = rect.mLeft; + mY = rect.mBottom; + break; + } + case MP_BOTTOM_RIGHT: + { + const LLRect& menu_rect = menu->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mBottom; + break; + } + } } void LLMenuButton::onMenuVisibilityChange(const LLSD& param) { - bool new_visibility = param["visibility"].asBoolean(); - bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean(); - - // Reset the button "pressed" state only if the menu is shown by this particular - // menu button (not any other control) and is not being closed by a click on the button. - if (!new_visibility && !is_closed_by_button_click && mIsMenuShown) - { - setForcePressedState(false); - mIsMenuShown = false; - } + bool new_visibility = param["visibility"].asBoolean(); + bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean(); + + // Reset the button "pressed" state only if the menu is shown by this particular + // menu button (not any other control) and is not being closed by a click on the button. + if (!new_visibility && !is_closed_by_button_click && mIsMenuShown) + { + setForcePressedState(false); + mIsMenuShown = false; + } } void LLMenuButton::cleanup() { - if (mMenuHandle.get() && mOwnMenu) - { - mMenuHandle.get()->die(); - } + if (mMenuHandle.get() && mOwnMenu) + { + mMenuHandle.get()->die(); + } } diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index e42f8f53bd..1039560827 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -1,25 +1,25 @@ -/** +/** * @file llbutton.h * @brief Header for buttons * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,67 +34,67 @@ class LLToggleableMenu; class LLMenuButton : public LLButton { - LOG_CLASS(LLMenuButton); + LOG_CLASS(LLMenuButton); public: - typedef enum e_menu_position - { - MP_TOP_LEFT, - MP_TOP_RIGHT, - MP_BOTTOM_LEFT, - MP_BOTTOM_RIGHT - } EMenuPosition; + typedef enum e_menu_position + { + MP_TOP_LEFT, + MP_TOP_RIGHT, + MP_BOTTOM_LEFT, + MP_BOTTOM_RIGHT + } EMenuPosition; + + struct MenuPositions + : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; + + struct Params + : public LLInitParam::Block + { + // filename for it's toggleable menu + Optional menu_filename; + Optional position; - struct MenuPositions - : public LLInitParam::TypeValuesHelper - { - static void declareValues(); - }; + Params(); + }; - struct Params - : public LLInitParam::Block - { - // filename for it's toggleable menu - Optional menu_filename; - Optional position; - - Params(); - }; - - boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); + boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); - void hideMenu(); + void hideMenu(); - LLToggleableMenu* getMenu(); - void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); - void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false); + LLToggleableMenu* getMenu(); + void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); + void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false); - void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } + void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } protected: - friend class LLUICtrlFactory; - LLMenuButton(const Params&); - ~LLMenuButton(); + friend class LLUICtrlFactory; + LLMenuButton(const Params&); + ~LLMenuButton(); - void toggleMenu(); - void updateMenuOrigin(); + void toggleMenu(); + void updateMenuOrigin(); - void onMenuVisibilityChange(const LLSD& param); + void onMenuVisibilityChange(const LLSD& param); private: - void cleanup(); - - LLHandle mMenuHandle; - bool mIsMenuShown; - EMenuPosition mMenuPosition; - S32 mX; - S32 mY; - bool mOwnMenu; // true if we manage the menu lifetime + void cleanup(); + + LLHandle mMenuHandle; + bool mIsMenuShown; + EMenuPosition mMenuPosition; + S32 mX; + S32 mY; + bool mOwnMenu; // true if we manage the menu lifetime }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7381dc80a8..79d0fbd1b4 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmenugl.cpp * @brief LLMenuItemGL base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -124,229 +124,229 @@ static LLDefaultChildRegistry::Register register_menu_default("menu"); ///============================================================================ LLMenuItemGL::Params::Params() -: shortcut("shortcut"), - jump_key("jump_key", KEY_NONE), - use_mac_ctrl("use_mac_ctrl", false), - allow_key_repeat("allow_key_repeat", false), - rect("rect"), - left("left"), - top("top"), - right("right"), - bottom("bottom"), - width("width"), - height("height"), - bottom_delta("bottom_delta"), - left_delta("left_delta"), - enabled_color("enabled_color"), - disabled_color("disabled_color"), - highlight_bg_color("highlight_bg_color"), - highlight_fg_color("highlight_fg_color") -{ - changeDefault(mouse_opaque, true); +: shortcut("shortcut"), + jump_key("jump_key", KEY_NONE), + use_mac_ctrl("use_mac_ctrl", false), + allow_key_repeat("allow_key_repeat", false), + rect("rect"), + left("left"), + top("top"), + right("right"), + bottom("bottom"), + width("width"), + height("height"), + bottom_delta("bottom_delta"), + left_delta("left_delta"), + enabled_color("enabled_color"), + disabled_color("disabled_color"), + highlight_bg_color("highlight_bg_color"), + highlight_fg_color("highlight_fg_color") +{ + changeDefault(mouse_opaque, true); } // Default constructor LLMenuItemGL::LLMenuItemGL(const LLMenuItemGL::Params& p) -: LLUICtrl(p), - mJumpKey(p.jump_key), - mAllowKeyRepeat(p.allow_key_repeat), - mHighlight( FALSE ), - mGotHover( FALSE ), - mBriefItem( FALSE ), - mDrawTextDisabled( FALSE ), - mFont(p.font), - mAcceleratorKey(KEY_NONE), - mAcceleratorMask(MASK_NONE), - mLabel(p.label.isProvided() ? p.label() : p.name()), - mEnabledColor(p.enabled_color()), - mDisabledColor(p.disabled_color()), - mHighlightBackground(p.highlight_bg_color()), - mHighlightForeground(p.highlight_fg_color()) +: LLUICtrl(p), + mJumpKey(p.jump_key), + mAllowKeyRepeat(p.allow_key_repeat), + mHighlight( FALSE ), + mGotHover( FALSE ), + mBriefItem( FALSE ), + mDrawTextDisabled( FALSE ), + mFont(p.font), + mAcceleratorKey(KEY_NONE), + mAcceleratorMask(MASK_NONE), + mLabel(p.label.isProvided() ? p.label() : p.name()), + mEnabledColor(p.enabled_color()), + mDisabledColor(p.disabled_color()), + mHighlightBackground(p.highlight_bg_color()), + mHighlightForeground(p.highlight_fg_color()) { #ifdef LL_DARWIN - // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd - BOOL useMacCtrl = p.use_mac_ctrl; + // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd + BOOL useMacCtrl = p.use_mac_ctrl; #endif // LL_DARWIN - - std::string shortcut = p.shortcut; - if (shortcut.find("control") != shortcut.npos) - { + + std::string shortcut = p.shortcut; + if (shortcut.find("control") != shortcut.npos) + { #ifdef LL_DARWIN - if ( useMacCtrl ) - { - mAcceleratorMask |= MASK_MAC_CONTROL; - } + if ( useMacCtrl ) + { + mAcceleratorMask |= MASK_MAC_CONTROL; + } #endif // LL_DARWIN - mAcceleratorMask |= MASK_CONTROL; - } - if (shortcut.find("alt") != shortcut.npos) - { - mAcceleratorMask |= MASK_ALT; - } - if (shortcut.find("shift") != shortcut.npos) - { - mAcceleratorMask |= MASK_SHIFT; - } - S32 pipe_pos = shortcut.rfind("|"); - std::string key_str = shortcut.substr(pipe_pos+1); - - LLKeyboard::keyFromString(key_str, &mAcceleratorKey); - - LL_DEBUGS("HotKeys") << "Process short cut key: shortcut: " << shortcut - << ", key str: " << key_str - << ", accelerator mask: " << mAcceleratorMask - << ", accelerator key: " << mAcceleratorKey - << LL_ENDL; + mAcceleratorMask |= MASK_CONTROL; + } + if (shortcut.find("alt") != shortcut.npos) + { + mAcceleratorMask |= MASK_ALT; + } + if (shortcut.find("shift") != shortcut.npos) + { + mAcceleratorMask |= MASK_SHIFT; + } + S32 pipe_pos = shortcut.rfind("|"); + std::string key_str = shortcut.substr(pipe_pos+1); + + LLKeyboard::keyFromString(key_str, &mAcceleratorKey); + + LL_DEBUGS("HotKeys") << "Process short cut key: shortcut: " << shortcut + << ", key str: " << key_str + << ", accelerator mask: " << mAcceleratorMask + << ", accelerator key: " << mAcceleratorKey + << LL_ENDL; } //virtual void LLMenuItemGL::setValue(const LLSD& value) { - setLabel(value.asString()); + setLabel(value.asString()); } //virtual LLSD LLMenuItemGL::getValue() const { - return getLabel(); + return getLabel(); } //virtual bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const { - return (mAcceleratorKey == key) && (mAcceleratorMask == mask); + return (mAcceleratorKey == key) && (mAcceleratorMask == mask); } //virtual BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask) { - if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) - { - onCommit(); - return TRUE; - } - return FALSE; + if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) + { + onCommit(); + return TRUE; + } + return FALSE; } BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask) { - getWindow()->setCursor(UI_CURSOR_ARROW); - return TRUE; + getWindow()->setCursor(UI_CURSOR_ARROW); + return TRUE; } //virtual BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask) { - return LLUICtrl::handleRightMouseDown(x,y,mask); + return LLUICtrl::handleRightMouseDown(x,y,mask); } void LLMenuItemGL::onMouseEnter(S32 x, S32 y, MASK mask) { - setHover(TRUE); - LLUICtrl::onMouseEnter(x,y,mask); + setHover(TRUE); + LLUICtrl::onMouseEnter(x,y,mask); } void LLMenuItemGL::onMouseLeave(S32 x, S32 y, MASK mask) { - setHover(FALSE); - LLUICtrl::onMouseLeave(x,y,mask); + setHover(FALSE); + LLUICtrl::onMouseLeave(x,y,mask); } //virtual BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask) { - // If this event came from a right-click context menu spawn, - // process as a left-click to allow menu items to be hit - if (LLMenuHolderGL::sContextMenuSpawnPos.mX != S32_MAX - || LLMenuHolderGL::sContextMenuSpawnPos.mY != S32_MAX) - { - BOOL handled = handleMouseUp(x, y, mask); - return handled; - } - return LLUICtrl::handleRightMouseUp(x,y,mask); + // If this event came from a right-click context menu spawn, + // process as a left-click to allow menu items to be hit + if (LLMenuHolderGL::sContextMenuSpawnPos.mX != S32_MAX + || LLMenuHolderGL::sContextMenuSpawnPos.mY != S32_MAX) + { + BOOL handled = handleMouseUp(x, y, mask); + return handled; + } + return LLUICtrl::handleRightMouseUp(x,y,mask); } // This function checks to see if the accelerator key is already in use; // if not, it will be added to the list BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) { - LLMenuKeyboardBinding *accelerator = NULL; - - if (mAcceleratorKey != KEY_NONE) - { - std::list::iterator list_it; - for (list_it = listp->begin(); list_it != listp->end(); ++list_it) - { - accelerator = *list_it; - if ((accelerator->mKey == mAcceleratorKey) && (accelerator->mMask == (mAcceleratorMask & MASK_NORMALKEYS))) - { - - // *NOTE: get calling code to throw up warning or route - // warning messages back to app-provided output - // std::string warning; - // warning.append("Duplicate key binding <"); - // appendAcceleratorString( warning ); - // warning.append("> for menu items:\n "); - // warning.append(accelerator->mName); - // warning.append("\n "); - // warning.append(mLabel); - - // LL_WARNS() << warning << LL_ENDL; - // LLAlertDialog::modalAlert(warning); - return FALSE; - } - } - if (!accelerator) - { - accelerator = new LLMenuKeyboardBinding; - if (accelerator) - { - accelerator->mKey = mAcceleratorKey; - accelerator->mMask = (mAcceleratorMask & MASK_NORMALKEYS); -// accelerator->mName = mLabel; - } - listp->push_back(accelerator);//addData(accelerator); - } - } - return TRUE; + LLMenuKeyboardBinding *accelerator = NULL; + + if (mAcceleratorKey != KEY_NONE) + { + std::list::iterator list_it; + for (list_it = listp->begin(); list_it != listp->end(); ++list_it) + { + accelerator = *list_it; + if ((accelerator->mKey == mAcceleratorKey) && (accelerator->mMask == (mAcceleratorMask & MASK_NORMALKEYS))) + { + + // *NOTE: get calling code to throw up warning or route + // warning messages back to app-provided output + // std::string warning; + // warning.append("Duplicate key binding <"); + // appendAcceleratorString( warning ); + // warning.append("> for menu items:\n "); + // warning.append(accelerator->mName); + // warning.append("\n "); + // warning.append(mLabel); + + // LL_WARNS() << warning << LL_ENDL; + // LLAlertDialog::modalAlert(warning); + return FALSE; + } + } + if (!accelerator) + { + accelerator = new LLMenuKeyboardBinding; + if (accelerator) + { + accelerator->mKey = mAcceleratorKey; + accelerator->mMask = (mAcceleratorMask & MASK_NORMALKEYS); +// accelerator->mName = mLabel; + } + listp->push_back(accelerator);//addData(accelerator); + } + } + return TRUE; } // This function appends the character string representation of // the current accelerator key and mask to the provided string. void LLMenuItemGL::appendAcceleratorString( std::string& st ) const { - st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey ); - LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL; + st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey ); + LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL; } void LLMenuItemGL::setJumpKey(KEY key) { - mJumpKey = LLStringOps::toUpper((char)key); + mJumpKey = LLStringOps::toUpper((char)key); } -// virtual -U32 LLMenuItemGL::getNominalHeight( void ) const -{ - return mFont->getLineHeight() + MENU_ITEM_PADDING; +// virtual +U32 LLMenuItemGL::getNominalHeight( void ) const +{ + return mFont->getLineHeight() + MENU_ITEM_PADDING; } //virtual void LLMenuItemGL::setBriefItem(BOOL brief) { - mBriefItem = brief; + mBriefItem = brief; } //virtual BOOL LLMenuItemGL::isBriefItem() const { - return mBriefItem; + return mBriefItem; } // Get the parent menu for this item LLMenuGL* LLMenuItemGL::getMenu() const { - return (LLMenuGL*) getParent(); + return (LLMenuGL*) getParent(); } @@ -355,216 +355,216 @@ LLMenuGL* LLMenuItemGL::getMenu() const // for horizontal arrangement. U32 LLMenuItemGL::getNominalWidth( void ) const { - U32 width; - - if (mBriefItem) - { - width = BRIEF_PAD_PIXELS; - } - else - { - width = PLAIN_PAD_PIXELS; - } - - if( KEY_NONE != mAcceleratorKey ) - { - width += getMenu()->getShortcutPad(); - std::string temp; - appendAcceleratorString( temp ); - width += mFont->getWidth( temp ); - } - width += mFont->getWidth( mLabel.getWString().c_str() ); - return width; + U32 width; + + if (mBriefItem) + { + width = BRIEF_PAD_PIXELS; + } + else + { + width = PLAIN_PAD_PIXELS; + } + + if( KEY_NONE != mAcceleratorKey ) + { + width += getMenu()->getShortcutPad(); + std::string temp; + appendAcceleratorString( temp ); + width += mFont->getWidth( temp ); + } + width += mFont->getWidth( mLabel.getWString().c_str() ); + return width; } // called to rebuild the draw label void LLMenuItemGL::buildDrawLabel( void ) { - mDrawAccelLabel.clear(); - std::string st = mDrawAccelLabel.getString(); - appendAcceleratorString( st ); - mDrawAccelLabel = st; + mDrawAccelLabel.clear(); + std::string st = mDrawAccelLabel.getString(); + appendAcceleratorString( st ); + mDrawAccelLabel = st; } void LLMenuItemGL::onCommit( void ) { - // Check torn-off status to allow left-arrow keyboard navigation back - // to parent menu. - // Also, don't hide if item triggered by keyboard shortcut (and hence - // parent not visible). - if (!getMenu()->getTornOff() - && getMenu()->getVisible()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - LLUICtrl::onCommit(); + // Check torn-off status to allow left-arrow keyboard navigation back + // to parent menu. + // Also, don't hide if item triggered by keyboard shortcut (and hence + // parent not visible). + if (!getMenu()->getTornOff() + && getMenu()->getVisible()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + LLUICtrl::onCommit(); } // set the hover status (called by it's menu) void LLMenuItemGL::setHighlight( BOOL highlight ) { - if (highlight) - { - getMenu()->clearHoverItem(); - } + if (highlight) + { + getMenu()->clearHoverItem(); + } - if (mHighlight != highlight) - { - dirtyRect(); - } + if (mHighlight != highlight) + { + dirtyRect(); + } - mHighlight = highlight; + mHighlight = highlight; } BOOL LLMenuItemGL::handleKeyHere( KEY key, MASK mask ) { - if (getHighlight() && - getMenu()->isOpen()) - { - if (key == KEY_UP) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - getMenu()->highlightPrevItem(this); - return TRUE; - } - else if (key == KEY_DOWN) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - getMenu()->highlightNextItem(this); - return TRUE; - } - else if (key == KEY_RETURN && mask == MASK_NONE) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - onCommit(); - return TRUE; - } - } - - return FALSE; + if (getHighlight() && + getMenu()->isOpen()) + { + if (key == KEY_UP) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + getMenu()->highlightPrevItem(this); + return TRUE; + } + else if (key == KEY_DOWN) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + getMenu()->highlightNextItem(this); + return TRUE; + } + else if (key == KEY_RETURN && mask == MASK_NONE) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + onCommit(); + return TRUE; + } + } + + return FALSE; } BOOL LLMenuItemGL::handleMouseUp( S32 x, S32 y, MASK mask) { - // switch to mouse navigation mode - LLMenuGL::setKeyboardMode(FALSE); + // switch to mouse navigation mode + LLMenuGL::setKeyboardMode(FALSE); - onCommit(); - make_ui_sound("UISndClickRelease"); - return LLView::handleMouseUp(x, y, mask); + onCommit(); + make_ui_sound("UISndClickRelease"); + return LLView::handleMouseUp(x, y, mask); } BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK mask) { - // switch to mouse navigation mode - LLMenuGL::setKeyboardMode(FALSE); + // switch to mouse navigation mode + LLMenuGL::setKeyboardMode(FALSE); - setHighlight(TRUE); - return LLView::handleMouseDown(x, y, mask); + setHighlight(TRUE); + return LLView::handleMouseDown(x, y, mask); } BOOL LLMenuItemGL::handleScrollWheel( S32 x, S32 y, S32 clicks ) { - // If the menu is scrollable let it handle the wheel event. - return !getMenu()->isScrollable(); + // If the menu is scrollable let it handle the wheel event. + return !getMenu()->isScrollable(); } void LLMenuItemGL::draw( void ) { - // *FIX: This can be optimized by using switches. Want to avoid - // that until the functionality is finalized. - - // HACK: Brief items don't highlight. Pie menu takes care of it. JC - // let disabled items be highlighted, just don't draw them as such - if( getEnabled() && getHighlight() && !mBriefItem) - { - gGL.color4fv( mHighlightBackground.get().mV ); - - gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - } - - LLColor4 color; - - if ( getEnabled() && getHighlight() ) - { - color = mHighlightForeground.get(); - } - else if( getEnabled() && !mDrawTextDisabled ) - { - color = mEnabledColor.get(); - } - else - { - color = mDisabledColor.get(); - } - - // Highlight if needed - if( ll::ui::SearchableControl::getHighlighted() ) - color = ll::ui::SearchableControl::getHighlightColor(); - - // Draw the text on top. - if (mBriefItem) - { - mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL); - } - else - { - if( !mDrawBoolLabel.empty() ) - { - mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - if( !mDrawAccelLabel.empty() ) - { - mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, - LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - if( !mDrawBranchLabel.empty() ) - { - mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, - LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - } - - // underline "jump" key only when keyboard navigation has been initiated - if (getMenu()->jumpKeysActive() && LLMenuGL::getKeyboardMode()) - { - std::string upper_case_label = mLabel.getString(); - LLStringUtil::toUpper(upper_case_label); - std::string::size_type offset = upper_case_label.find(mJumpKey); - if (offset != std::string::npos) - { - S32 x_begin = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset); - S32 x_end = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset + 1); - gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1); - } - } + // *FIX: This can be optimized by using switches. Want to avoid + // that until the functionality is finalized. + + // HACK: Brief items don't highlight. Pie menu takes care of it. JC + // let disabled items be highlighted, just don't draw them as such + if( getEnabled() && getHighlight() && !mBriefItem) + { + gGL.color4fv( mHighlightBackground.get().mV ); + + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); + } + + LLColor4 color; + + if ( getEnabled() && getHighlight() ) + { + color = mHighlightForeground.get(); + } + else if( getEnabled() && !mDrawTextDisabled ) + { + color = mEnabledColor.get(); + } + else + { + color = mDisabledColor.get(); + } + + // Highlight if needed + if( ll::ui::SearchableControl::getHighlighted() ) + color = ll::ui::SearchableControl::getHighlightColor(); + + // Draw the text on top. + if (mBriefItem) + { + mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL); + } + else + { + if( !mDrawBoolLabel.empty() ) + { + mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + } + mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + if( !mDrawAccelLabel.empty() ) + { + mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, + LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + } + if( !mDrawBranchLabel.empty() ) + { + mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, + LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + } + } + + // underline "jump" key only when keyboard navigation has been initiated + if (getMenu()->jumpKeysActive() && LLMenuGL::getKeyboardMode()) + { + std::string upper_case_label = mLabel.getString(); + LLStringUtil::toUpper(upper_case_label); + std::string::size_type offset = upper_case_label.find(mJumpKey); + if (offset != std::string::npos) + { + S32 x_begin = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset); + S32 x_end = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset + 1); + gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1); + } + } } BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - mLabel.setArg(key, text); - return TRUE; + mLabel.setArg(key, text); + return TRUE; } void LLMenuItemGL::onVisibilityChange(BOOL new_visibility) { - if (getMenu()) - { - getMenu()->needsArrange(); - } - LLView::onVisibilityChange(new_visibility); + if (getMenu()) + { + getMenu()->needsArrange(); + } + LLView::onVisibilityChange(new_visibility); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -578,7 +578,7 @@ LLMenuItemSeparatorGL::Params::Params() } LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) : - LLMenuItemGL( p ) + LLMenuItemGL( p ) { if (p.on_visible.isProvided()) { @@ -589,15 +589,15 @@ LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params //virtual U32 LLMenuItemSeparatorGL::getNominalHeight( void ) const { - return SEPARATOR_HEIGHT_PIXELS; + return SEPARATOR_HEIGHT_PIXELS; } void LLMenuItemSeparatorGL::draw( void ) { - gGL.color4fv( mDisabledColor.get().mV ); - const S32 y = getRect().getHeight() / 2; - const S32 PAD = 6; - gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); + gGL.color4fv( mDisabledColor.get().mV ); + const S32 y = getRect().getHeight() / 2; + const S32 PAD = 6; + gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); } void LLMenuItemSeparatorGL::buildDrawLabel( void ) @@ -611,48 +611,48 @@ void LLMenuItemSeparatorGL::buildDrawLabel( void ) BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask) { - LLMenuGL* parent_menu = getMenu(); - if (y > getRect().getHeight() / 2) - { - // the menu items are in the child list in bottom up order - LLView* prev_menu_item = parent_menu->findNextSibling(this); - return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; - } - else - { - LLView* next_menu_item = parent_menu->findPrevSibling(this); - return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE; - } -} - -BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask) -{ - LLMenuGL* parent_menu = getMenu(); - if (y > getRect().getHeight() / 2) - { - LLView* prev_menu_item = parent_menu->findNextSibling(this); - return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; - } - else - { - LLView* next_menu_item = parent_menu->findPrevSibling(this); - return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE; - } -} - -BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask) -{ - LLMenuGL* parent_menu = getMenu(); - if (y > getRect().getHeight() / 2) - { - parent_menu->highlightPrevItem(this, FALSE); - return FALSE; - } - else - { - parent_menu->highlightNextItem(this, FALSE); - return FALSE; - } + LLMenuGL* parent_menu = getMenu(); + if (y > getRect().getHeight() / 2) + { + // the menu items are in the child list in bottom up order + LLView* prev_menu_item = parent_menu->findNextSibling(this); + return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; + } + else + { + LLView* next_menu_item = parent_menu->findPrevSibling(this); + return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE; + } +} + +BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask) +{ + LLMenuGL* parent_menu = getMenu(); + if (y > getRect().getHeight() / 2) + { + LLView* prev_menu_item = parent_menu->findNextSibling(this); + return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; + } + else + { + LLView* next_menu_item = parent_menu->findPrevSibling(this); + return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE; + } +} + +BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask) +{ + LLMenuGL* parent_menu = getMenu(); + if (y > getRect().getHeight() / 2) + { + parent_menu->highlightPrevItem(this, FALSE); + return FALSE; + } + else + { + parent_menu->highlightNextItem(this, FALSE); + return FALSE; + } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -662,120 +662,120 @@ BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLMenuItemVerticalSeparatorGL -: public LLMenuItemSeparatorGL +: public LLMenuItemSeparatorGL { public: - LLMenuItemVerticalSeparatorGL( void ); + LLMenuItemVerticalSeparatorGL( void ); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; } + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; } }; LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void ) { - setLabel( VERTICAL_SEPARATOR_LABEL ); + setLabel( VERTICAL_SEPARATOR_LABEL ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemTearOffGL //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p) -: LLMenuItemGL(p) +LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p) +: LLMenuItemGL(p) { } // Returns the first floater ancestor if there is one LLFloater* LLMenuItemTearOffGL::getParentFloater() { - LLView* parent_view = getMenu(); + LLView* parent_view = getMenu(); - while (parent_view) - { - if (dynamic_cast(parent_view)) - { - return dynamic_cast(parent_view); - } + while (parent_view) + { + if (dynamic_cast(parent_view)) + { + return dynamic_cast(parent_view); + } - bool parent_is_menu = dynamic_cast(parent_view) && !dynamic_cast(parent_view); + bool parent_is_menu = dynamic_cast(parent_view) && !dynamic_cast(parent_view); - if (parent_is_menu) - { - // use menu parent - parent_view = dynamic_cast(parent_view)->getParentMenuItem(); - } - else - { - // just use regular view parent - parent_view = parent_view->getParent(); - } - } + if (parent_is_menu) + { + // use menu parent + parent_view = dynamic_cast(parent_view)->getParentMenuItem(); + } + else + { + // just use regular view parent + parent_view = parent_view->getParent(); + } + } - return NULL; + return NULL; } void LLMenuItemTearOffGL::onCommit() { - if (getMenu()->getTornOff()) - { - LLTearOffMenu * torn_off_menu = dynamic_cast(getMenu()->getParent()); - if (torn_off_menu) - { - torn_off_menu->closeFloater(); - } - } - else - { - // transfer keyboard focus and highlight to first real item in list - if (getHighlight()) - { - getMenu()->highlightNextItem(this); - } - - getMenu()->needsArrange(); - - LLFloater* parent_floater = getParentFloater(); - LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu()); - - if (tear_off_menu) - { - if (parent_floater) - { - parent_floater->addDependentFloater(tear_off_menu, FALSE); - } - - // give focus to torn off menu because it will have - // been taken away when parent menu closes - tear_off_menu->setFocus(TRUE); - } - } - LLMenuItemGL::onCommit(); + if (getMenu()->getTornOff()) + { + LLTearOffMenu * torn_off_menu = dynamic_cast(getMenu()->getParent()); + if (torn_off_menu) + { + torn_off_menu->closeFloater(); + } + } + else + { + // transfer keyboard focus and highlight to first real item in list + if (getHighlight()) + { + getMenu()->highlightNextItem(this); + } + + getMenu()->needsArrange(); + + LLFloater* parent_floater = getParentFloater(); + LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu()); + + if (tear_off_menu) + { + if (parent_floater) + { + parent_floater->addDependentFloater(tear_off_menu, FALSE); + } + + // give focus to torn off menu because it will have + // been taken away when parent menu closes + tear_off_menu->setFocus(TRUE); + } + } + LLMenuItemGL::onCommit(); } void LLMenuItemTearOffGL::draw() { - // disabled items can be highlighted, but shouldn't render as such - if( getEnabled() && getHighlight() && !isBriefItem()) - { - gGL.color4fv( mHighlightBackground.get().mV ); - gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - } + // disabled items can be highlighted, but shouldn't render as such + if( getEnabled() && getHighlight() && !isBriefItem()) + { + gGL.color4fv( mHighlightBackground.get().mV ); + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); + } - if (getEnabled()) - { - gGL.color4fv( mEnabledColor.get().mV ); - } - else - { - gGL.color4fv( mDisabledColor.get().mV ); - } - const S32 y = getRect().getHeight() / 3; - const S32 PAD = 6; - gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); - gl_line_2d( PAD, y * 2, getRect().getWidth() - PAD, y * 2 ); + if (getEnabled()) + { + gGL.color4fv( mEnabledColor.get().mV ); + } + else + { + gGL.color4fv( mDisabledColor.get().mV ); + } + const S32 y = getRect().getHeight() / 3; + const S32 PAD = 6; + gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); + gl_line_2d( PAD, y * 2, getRect().getWidth() - PAD, y * 2 ); } -U32 LLMenuItemTearOffGL::getNominalHeight( void ) const -{ - return TEAROFF_SEPARATOR_HEIGHT_PIXELS; +U32 LLMenuItemTearOffGL::getNominalHeight( void ) const +{ + return TEAROFF_SEPARATOR_HEIGHT_PIXELS; } ///============================================================================ @@ -783,104 +783,104 @@ U32 LLMenuItemTearOffGL::getNominalHeight( void ) const ///============================================================================ LLMenuItemCallGL::LLMenuItemCallGL(const LLMenuItemCallGL::Params& p) -: LLMenuItemGL(p) +: LLMenuItemGL(p) { } void LLMenuItemCallGL::initFromParams(const Params& p) { - if (p.on_visible.isProvided()) - { - mVisibleSignal.connect(initEnableCallback(p.on_visible)); - } - if (p.on_enable.isProvided()) - { - setEnableCallback(initEnableCallback(p.on_enable)); - // Set the enabled control variable (for backwards compatability) - if (p.on_enable.control_name.isProvided() && !p.on_enable.control_name().empty()) - { - LLControlVariable* control = findControl(p.on_enable.control_name()); - if (control) - { - setEnabledControlVariable(control); - } - else - { - LL_WARNS() << "Failed to assign 'enabled' control variable to menu " << getName() - << ": control " << p.on_enable.control_name() - << " does not exist." << LL_ENDL; - } - } - } - if (p.on_click.isProvided()) - { - setCommitCallback(initCommitCallback(p.on_click)); - } - - LLUICtrl::initFromParams(p); + if (p.on_visible.isProvided()) + { + mVisibleSignal.connect(initEnableCallback(p.on_visible)); + } + if (p.on_enable.isProvided()) + { + setEnableCallback(initEnableCallback(p.on_enable)); + // Set the enabled control variable (for backwards compatability) + if (p.on_enable.control_name.isProvided() && !p.on_enable.control_name().empty()) + { + LLControlVariable* control = findControl(p.on_enable.control_name()); + if (control) + { + setEnabledControlVariable(control); + } + else + { + LL_WARNS() << "Failed to assign 'enabled' control variable to menu " << getName() + << ": control " << p.on_enable.control_name() + << " does not exist." << LL_ENDL; + } + } + } + if (p.on_click.isProvided()) + { + setCommitCallback(initCommitCallback(p.on_click)); + } + + LLUICtrl::initFromParams(p); } void LLMenuItemCallGL::onCommit( void ) { - // RN: menu item can be deleted in callback, so beware - getMenu()->setItemLastSelected( this ); - - LLMenuItemGL::onCommit(); + // RN: menu item can be deleted in callback, so beware + getMenu()->setItemLastSelected( this ); + + LLMenuItemGL::onCommit(); } void LLMenuItemCallGL::updateEnabled( void ) { - if (mEnableSignal.num_slots() > 0) - { - bool enabled = mEnableSignal(this, LLSD()); - if (mEnabledControlVariable) - { - if (!enabled) - { - // callback overrides control variable; this will call setEnabled() - mEnabledControlVariable->set(false); - } - } - else - { - setEnabled(enabled); - } - } + if (mEnableSignal.num_slots() > 0) + { + bool enabled = mEnableSignal(this, LLSD()); + if (mEnabledControlVariable) + { + if (!enabled) + { + // callback overrides control variable; this will call setEnabled() + mEnabledControlVariable->set(false); + } + } + else + { + setEnabled(enabled); + } + } } void LLMenuItemCallGL::updateVisible( void ) { - if (mVisibleSignal.num_slots() > 0) - { - bool visible = mVisibleSignal(this, LLSD()); - setVisible(visible); - } + if (mVisibleSignal.num_slots() > 0) + { + bool visible = mVisibleSignal(this, LLSD()); + setVisible(visible); + } } void LLMenuItemCallGL::buildDrawLabel( void ) { - updateEnabled(); - updateVisible(); - LLMenuItemGL::buildDrawLabel(); + updateEnabled(); + updateVisible(); + LLMenuItemGL::buildDrawLabel(); } BOOL LLMenuItemCallGL::handleKeyHere( KEY key, MASK mask ) { - return LLMenuItemGL::handleKeyHere(key, mask); + return LLMenuItemGL::handleKeyHere(key, mask); } BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask ) { - if( (!gKeyboard->getKeyRepeated(key) || getAllowKeyRepeat()) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) - { - updateEnabled(); - if (getEnabled()) - { - onCommit(); - return TRUE; - } - } - return FALSE; + if( (!gKeyboard->getKeyRepeated(key) || getAllowKeyRepeat()) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) + { + updateEnabled(); + if (getEnabled()) + { + onCommit(); + return TRUE; + } + } + return FALSE; } // handleRightMouseUp moved into base class LLMenuItemGL so clicks are @@ -890,76 +890,76 @@ BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask ) /// Class LLMenuItemCheckGL ///============================================================================ LLMenuItemCheckGL::LLMenuItemCheckGL (const LLMenuItemCheckGL::Params& p) -: LLMenuItemCallGL(p) +: LLMenuItemCallGL(p) { } void LLMenuItemCheckGL::initFromParams(const Params& p) { - if (p.on_check.isProvided()) - { - setCheckCallback(initEnableCallback(p.on_check)); - // Set the control name (for backwards compatability) - if (p.on_check.control_name.isProvided() && !p.on_check.control_name().empty()) - { - setControlName(p.on_check.control_name()); - } - } - - LLMenuItemCallGL::initFromParams(p); + if (p.on_check.isProvided()) + { + setCheckCallback(initEnableCallback(p.on_check)); + // Set the control name (for backwards compatability) + if (p.on_check.control_name.isProvided() && !p.on_check.control_name().empty()) + { + setControlName(p.on_check.control_name()); + } + } + + LLMenuItemCallGL::initFromParams(p); } void LLMenuItemCheckGL::onCommit( void ) { - LLMenuItemCallGL::onCommit(); + LLMenuItemCallGL::onCommit(); } //virtual void LLMenuItemCheckGL::setValue(const LLSD& value) { - LLUICtrl::setValue(value); - if(value.asBoolean()) - { - mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; - } - else - { - mDrawBoolLabel.clear(); - } + LLUICtrl::setValue(value); + if(value.asBoolean()) + { + mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; + } + else + { + mDrawBoolLabel.clear(); + } } //virtual LLSD LLMenuItemCheckGL::getValue() const { - // Get our boolean value from the view model. - // If we don't override this method then the implementation from - // LLMenuItemGL will return a string. (EXT-8501) - return LLUICtrl::getValue(); + // Get our boolean value from the view model. + // If we don't override this method then the implementation from + // LLMenuItemGL will return a string. (EXT-8501) + return LLUICtrl::getValue(); } // called to rebuild the draw label void LLMenuItemCheckGL::buildDrawLabel( void ) { - // Note: mCheckSignal() returns true if no callbacks are set - bool checked = mCheckSignal(this, LLSD()); - if (mControlVariable) - { - if (!checked) - setControlValue(false); // callback overrides control variable; this will call setValue() - } - else - { - setValue(checked); - } - if(getValue().asBoolean()) - { - mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; - } - else - { - mDrawBoolLabel.clear(); - } - LLMenuItemCallGL::buildDrawLabel(); + // Note: mCheckSignal() returns true if no callbacks are set + bool checked = mCheckSignal(this, LLSD()); + if (mControlVariable) + { + if (!checked) + setControlValue(false); // callback overrides control variable; this will call setValue() + } + else + { + setValue(checked); + } + if(getValue().asBoolean()) + { + mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; + } + else + { + mDrawBoolLabel.clear(); + } + LLMenuItemCallGL::buildDrawLabel(); } ///============================================================================ @@ -968,21 +968,21 @@ void LLMenuItemCheckGL::buildDrawLabel( void ) LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p) : LLMenuItemGL(p) { - LLMenuGL* branch = p.branch; - if (branch) - { - mBranchHandle = branch->getHandle(); - branch->setVisible(FALSE); - branch->setParentMenuItem(this); - } + LLMenuGL* branch = p.branch; + if (branch) + { + mBranchHandle = branch->getHandle(); + branch->setVisible(FALSE); + branch->setParentMenuItem(this); + } } LLMenuItemBranchGL::~LLMenuItemBranchGL() { - if (mBranchHandle.get()) - { - mBranchHandle.get()->die(); - } + if (mBranchHandle.get()) + { + mBranchHandle.get()->die(); + } } @@ -990,348 +990,348 @@ LLMenuItemBranchGL::~LLMenuItemBranchGL() // virtual LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const { - LLMenuGL* branch = getBranch(); - if (branch) - { - if (branch->getName() == name) - { - return branch; - } + LLMenuGL* branch = getBranch(); + if (branch) + { + if (branch->getName() == name) + { + return branch; + } - // Always recurse on branches - return branch->getChildView(name, recurse); - } + // Always recurse on branches + return branch->getChildView(name, recurse); + } - return LLView::getChildView(name, recurse); + return LLView::getChildView(name, recurse); } LLView* LLMenuItemBranchGL::findChildView(const std::string& name, BOOL recurse) const { - LLMenuGL* branch = getBranch(); - if (branch) - { - if (branch->getName() == name) - { - return branch; - } + LLMenuGL* branch = getBranch(); + if (branch) + { + if (branch->getName() == name) + { + return branch; + } - // Always recurse on branches - return branch->findChildView(name, recurse); - } + // Always recurse on branches + return branch->findChildView(name, recurse); + } - return LLView::findChildView(name, recurse); + return LLView::findChildView(name, recurse); } // virtual BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask) { - // switch to mouse navigation mode - LLMenuGL::setKeyboardMode(FALSE); + // switch to mouse navigation mode + LLMenuGL::setKeyboardMode(FALSE); - onCommit(); - make_ui_sound("UISndClickRelease"); - return TRUE; + onCommit(); + make_ui_sound("UISndClickRelease"); + return TRUE; } bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const { - return getBranch() && getBranch()->hasAccelerator(key, mask); + return getBranch() && getBranch()->hasAccelerator(key, mask); } BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask) { - return getBranch() && getBranch()->handleAcceleratorKey(key, mask); + return getBranch() && getBranch()->handleAcceleratorKey(key, mask); } // This function checks to see if the accelerator key is already in use; // if not, it will be added to the list BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list *listp) { - LLMenuGL* branch = getBranch(); - if (!branch) - return FALSE; + LLMenuGL* branch = getBranch(); + if (!branch) + return FALSE; - U32 item_count = branch->getItemCount(); - LLMenuItemGL *item; - - while (item_count--) - { - if ((item = branch->getItem(item_count))) - { - return item->addToAcceleratorList(listp); - } - } + U32 item_count = branch->getItemCount(); + LLMenuItemGL *item; + + while (item_count--) + { + if ((item = branch->getItem(item_count))) + { + return item->addToAcceleratorList(listp); + } + } - return FALSE; + return FALSE; } // called to rebuild the draw label void LLMenuItemBranchGL::buildDrawLabel( void ) { - mDrawAccelLabel.clear(); - std::string st = mDrawAccelLabel; - appendAcceleratorString( st ); - mDrawAccelLabel = st; - mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; + mDrawAccelLabel.clear(); + std::string st = mDrawAccelLabel; + appendAcceleratorString( st ); + mDrawAccelLabel = st; + mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; } void LLMenuItemBranchGL::onCommit( void ) { - openMenu(); + openMenu(); + + // keyboard navigation automatically propagates highlight to sub-menu + // to facilitate fast menu control via jump keys + if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem()) + { + getBranch()->highlightNextItem(NULL); + } - // keyboard navigation automatically propagates highlight to sub-menu - // to facilitate fast menu control via jump keys - if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem()) - { - getBranch()->highlightNextItem(NULL); - } - - LLUICtrl::onCommit(); + LLUICtrl::onCommit(); } BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - BOOL handled = FALSE; - if (getBranch() && called_from_parent) - { - handled = getBranch()->handleKey(key, mask, called_from_parent); - } + BOOL handled = FALSE; + if (getBranch() && called_from_parent) + { + handled = getBranch()->handleKey(key, mask, called_from_parent); + } - if (!handled) - { - handled = LLMenuItemGL::handleKey(key, mask, called_from_parent); - } + if (!handled) + { + handled = LLMenuItemGL::handleKey(key, mask, called_from_parent); + } - return handled; + return handled; } BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { - BOOL handled = FALSE; - if (getBranch() && called_from_parent) - { - handled = getBranch()->handleUnicodeChar(uni_char, TRUE); - } + BOOL handled = FALSE; + if (getBranch() && called_from_parent) + { + handled = getBranch()->handleUnicodeChar(uni_char, TRUE); + } - if (!handled) - { - handled = LLMenuItemGL::handleUnicodeChar(uni_char, called_from_parent); - } + if (!handled) + { + handled = LLMenuItemGL::handleUnicodeChar(uni_char, called_from_parent); + } - return handled; + return handled; } void LLMenuItemBranchGL::setHighlight( BOOL highlight ) { - if (highlight == getHighlight()) - return; - - LLMenuGL* branch = getBranch(); - if (!branch) - return; - - BOOL auto_open = getEnabled() && (!branch->getVisible() || branch->getTornOff()); - // torn off menus don't open sub menus on hover unless they have focus - LLFloater * menu_parent = dynamic_cast(getMenu()->getParent()); - if (getMenu()->getTornOff() && menu_parent && !menu_parent->hasFocus()) - { - auto_open = FALSE; - } - // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus) - if (branch->getTornOff()) - { - auto_open = FALSE; - } - LLMenuItemGL::setHighlight(highlight); - if( highlight ) - { - if(auto_open) - { - openMenu(); - } - } - else - { - if (branch->getTornOff()) - { - LLFloater * branch_parent = dynamic_cast(branch->getParent()); - if (branch_parent) - { - branch_parent->setFocus(FALSE); - } - branch->clearHoverItem(); - } - else - { - branch->setVisible( FALSE ); - } - } + if (highlight == getHighlight()) + return; + + LLMenuGL* branch = getBranch(); + if (!branch) + return; + + BOOL auto_open = getEnabled() && (!branch->getVisible() || branch->getTornOff()); + // torn off menus don't open sub menus on hover unless they have focus + LLFloater * menu_parent = dynamic_cast(getMenu()->getParent()); + if (getMenu()->getTornOff() && menu_parent && !menu_parent->hasFocus()) + { + auto_open = FALSE; + } + // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus) + if (branch->getTornOff()) + { + auto_open = FALSE; + } + LLMenuItemGL::setHighlight(highlight); + if( highlight ) + { + if(auto_open) + { + openMenu(); + } + } + else + { + if (branch->getTornOff()) + { + LLFloater * branch_parent = dynamic_cast(branch->getParent()); + if (branch_parent) + { + branch_parent->setFocus(FALSE); + } + branch->clearHoverItem(); + } + else + { + branch->setVisible( FALSE ); + } + } } void LLMenuItemBranchGL::draw() { - LLMenuItemGL::draw(); - if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff()) - { - setHighlight(TRUE); - } + LLMenuItemGL::draw(); + if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff()) + { + setHighlight(TRUE); + } } void LLMenuItemBranchGL::updateBranchParent(LLView* parentp) { - if (getBranch() && getBranch()->getParent() == NULL) - { - // make the branch menu a sibling of my parent menu - getBranch()->updateParent(parentp); - } + if (getBranch() && getBranch()->getParent() == NULL) + { + // make the branch menu a sibling of my parent menu + getBranch()->updateParent(parentp); + } } void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility ) { - if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff()) - { - getBranch()->setVisible(FALSE); - } - LLMenuItemGL::onVisibilityChange(new_visibility); + if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff()) + { + getBranch()->setVisible(FALSE); + } + LLMenuItemGL::onVisibilityChange(new_visibility); } BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) { - LLMenuGL* branch = getBranch(); - if (!branch) - return LLMenuItemGL::handleKeyHere(key, mask); - - // an item is highlighted, my menu is open, and I have an active sub menu or we are in - // keyboard navigation mode - if (getHighlight() - && getMenu()->isOpen() - && (isActive() || LLMenuGL::getKeyboardMode())) - { - if (branch->getVisible() && key == KEY_LEFT) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - BOOL handled = branch->clearHoverItem(); - if (branch->getTornOff()) - { - LLFloater * branch_parent = dynamic_cast(branch->getParent()); - if (branch_parent) - { - branch_parent->setFocus(FALSE); - } - } - if (handled && getMenu()->getTornOff()) - { - LLFloater * menu_parent = dynamic_cast(getMenu()->getParent()); - if (menu_parent) - { - menu_parent->setFocus(TRUE); - } - } - return handled; - } - - if (key == KEY_RIGHT && !branch->getHighlightedItem()) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - LLMenuItemGL* itemp = branch->highlightNextItem(NULL); - if (itemp) - { - return TRUE; - } - } - } - return LLMenuItemGL::handleKeyHere(key, mask); -} + LLMenuGL* branch = getBranch(); + if (!branch) + return LLMenuItemGL::handleKeyHere(key, mask); -//virtual -BOOL LLMenuItemBranchGL::isActive() const -{ - return isOpen() && getBranch() && getBranch()->getHighlightedItem(); -} + // an item is highlighted, my menu is open, and I have an active sub menu or we are in + // keyboard navigation mode + if (getHighlight() + && getMenu()->isOpen() + && (isActive() || LLMenuGL::getKeyboardMode())) + { + if (branch->getVisible() && key == KEY_LEFT) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); -//virtual + BOOL handled = branch->clearHoverItem(); + if (branch->getTornOff()) + { + LLFloater * branch_parent = dynamic_cast(branch->getParent()); + if (branch_parent) + { + branch_parent->setFocus(FALSE); + } + } + if (handled && getMenu()->getTornOff()) + { + LLFloater * menu_parent = dynamic_cast(getMenu()->getParent()); + if (menu_parent) + { + menu_parent->setFocus(TRUE); + } + } + return handled; + } + + if (key == KEY_RIGHT && !branch->getHighlightedItem()) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + LLMenuItemGL* itemp = branch->highlightNextItem(NULL); + if (itemp) + { + return TRUE; + } + } + } + return LLMenuItemGL::handleKeyHere(key, mask); +} + +//virtual +BOOL LLMenuItemBranchGL::isActive() const +{ + return isOpen() && getBranch() && getBranch()->getHighlightedItem(); +} + +//virtual BOOL LLMenuItemBranchGL::isOpen() const { - return getBranch() && getBranch()->isOpen(); + return getBranch() && getBranch()->isOpen(); } void LLMenuItemBranchGL::openMenu() { - LLMenuGL* branch = getBranch(); - if (!branch) - return; - - if (branch->getTornOff()) - { - LLFloater * branch_parent = dynamic_cast(branch->getParent()); - if (branch_parent) - { - gFloaterView->bringToFront(branch_parent); - // this might not be necessary, as torn off branches don't get focus and hence no highligth - branch->highlightNextItem(NULL); - } - } - else if( !branch->getVisible() ) - { - // get valid rectangle for menus - const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); - - branch->arrange(); - - LLRect branch_rect = branch->getRect(); - // calculate root-view relative position for branch menu - S32 left = getRect().mRight; - S32 top = getRect().mTop - getRect().mBottom; - - localPointToOtherView(left, top, &left, &top, branch->getParent()); - - branch_rect.setLeftTopAndSize( left, top, - branch_rect.getWidth(), branch_rect.getHeight() ); - - if (branch->getCanTearOff()) - { - branch_rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); - } - branch->setRect( branch_rect ); - - // if branch extends outside of menu region change the direction it opens in - S32 x, y; - S32 delta_x = 0; - S32 delta_y = 0; - branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() ); - if( y < menu_region_rect.mBottom ) - { - // open upwards if menu extends past bottom - // adjust by the height of the menu item branch since it is a submenu - if (y + 2 * branch_rect.getHeight() - getRect().getHeight() > menu_region_rect.mTop) - { - // overlaps with top border, align with top - delta_y = menu_region_rect.mTop - y - branch_rect.getHeight(); - } - else - { - delta_y = branch_rect.getHeight() - getRect().getHeight(); - } - } - - if( x + branch_rect.getWidth() > menu_region_rect.mRight ) - { - // move sub-menu over to left side - delta_x = llmax(-x, ( -(branch_rect.getWidth() + getRect().getWidth()))); - } - branch->translate( delta_x, delta_y ); - - branch->setVisible( TRUE ); - branch->getParent()->sendChildToFront(branch); - - dirtyRect(); - } + LLMenuGL* branch = getBranch(); + if (!branch) + return; + + if (branch->getTornOff()) + { + LLFloater * branch_parent = dynamic_cast(branch->getParent()); + if (branch_parent) + { + gFloaterView->bringToFront(branch_parent); + // this might not be necessary, as torn off branches don't get focus and hence no highligth + branch->highlightNextItem(NULL); + } + } + else if( !branch->getVisible() ) + { + // get valid rectangle for menus + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); + + branch->arrange(); + + LLRect branch_rect = branch->getRect(); + // calculate root-view relative position for branch menu + S32 left = getRect().mRight; + S32 top = getRect().mTop - getRect().mBottom; + + localPointToOtherView(left, top, &left, &top, branch->getParent()); + + branch_rect.setLeftTopAndSize( left, top, + branch_rect.getWidth(), branch_rect.getHeight() ); + + if (branch->getCanTearOff()) + { + branch_rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); + } + branch->setRect( branch_rect ); + + // if branch extends outside of menu region change the direction it opens in + S32 x, y; + S32 delta_x = 0; + S32 delta_y = 0; + branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() ); + if( y < menu_region_rect.mBottom ) + { + // open upwards if menu extends past bottom + // adjust by the height of the menu item branch since it is a submenu + if (y + 2 * branch_rect.getHeight() - getRect().getHeight() > menu_region_rect.mTop) + { + // overlaps with top border, align with top + delta_y = menu_region_rect.mTop - y - branch_rect.getHeight(); + } + else + { + delta_y = branch_rect.getHeight() - getRect().getHeight(); + } + } + + if( x + branch_rect.getWidth() > menu_region_rect.mRight ) + { + // move sub-menu over to left side + delta_x = llmax(-x, ( -(branch_rect.getWidth() + getRect().getWidth()))); + } + branch->translate( delta_x, delta_y ); + + branch->setVisible( TRUE ); + branch->getParent()->sendChildToFront(branch); + + dirtyRect(); + } } @@ -1347,39 +1347,39 @@ class LLMenuItemBranchDownGL : public LLMenuItemBranchGL protected: public: - LLMenuItemBranchDownGL( const Params& ); + LLMenuItemBranchDownGL( const Params& ); + + // returns the normal width of this control in pixels - this is + // used for calculating the widest item, as well as for horizontal + // arrangement. + virtual U32 getNominalWidth( void ) const; + + // called to rebuild the draw label + virtual void buildDrawLabel( void ); - // returns the normal width of this control in pixels - this is - // used for calculating the widest item, as well as for horizontal - // arrangement. - virtual U32 getNominalWidth( void ) const; + // handles opening, positioning, and arranging the menu branch associated with this item + virtual void openMenu( void ); - // called to rebuild the draw label - virtual void buildDrawLabel( void ); + // set the hover status (called by it's menu) and if the object is + // active. This is used for behavior transfer. + virtual void setHighlight( BOOL highlight ); - // handles opening, positioning, and arranging the menu branch associated with this item - virtual void openMenu( void ); + virtual BOOL isActive( void ) const; - // set the hover status (called by it's menu) and if the object is - // active. This is used for behavior transfer. - virtual void setHighlight( BOOL highlight ); + // LLView functionality + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual void draw( void ); + virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL isActive( void ) const; + virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - // LLView functionality - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual void draw( void ); - virtual BOOL handleKeyHere(KEY key, MASK mask); - - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - virtual void onFocusLost(); virtual void setFocus(BOOL b); }; LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const Params& p) : - LLMenuItemBranchGL(p) + LLMenuItemBranchGL(p) { } @@ -1388,147 +1388,147 @@ LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const Params& p) : // arrangement. U32 LLMenuItemBranchDownGL::getNominalWidth( void ) const { - U32 width = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS + RIGHT_PAD_PIXELS; - width += getFont()->getWidth( mLabel.getWString().c_str() ); - return width; + U32 width = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS + RIGHT_PAD_PIXELS; + width += getFont()->getWidth( mLabel.getWString().c_str() ); + return width; } // called to rebuild the draw label void LLMenuItemBranchDownGL::buildDrawLabel( void ) { - mDrawAccelLabel.clear(); - std::string st = mDrawAccelLabel; - appendAcceleratorString( st ); - mDrawAccelLabel = st; + mDrawAccelLabel.clear(); + std::string st = mDrawAccelLabel; + appendAcceleratorString( st ); + mDrawAccelLabel = st; } void LLMenuItemBranchDownGL::openMenu( void ) { - LLMenuGL* branch = getBranch(); - if( branch->getVisible() && !branch->getTornOff() ) - { - branch->setVisible( FALSE ); - } - else - { - if (branch->getTornOff()) - { - LLFloater * branch_parent = dynamic_cast(branch->getParent()); - if (branch_parent) - { - gFloaterView->bringToFront(branch_parent); - } - } - else - { - // We're showing the drop-down menu, so patch up its labels/rects - branch->arrange(); - - LLRect rect = branch->getRect(); - S32 left = 0; - S32 top = getRect().mBottom; - localPointToOtherView(left, top, &left, &top, branch->getParent()); - - rect.setLeftTopAndSize( left, top, - rect.getWidth(), rect.getHeight() ); - branch->setRect( rect ); - S32 x = 0; - S32 y = 0; - branch->localPointToScreen( 0, 0, &x, &y ); - S32 delta_x = 0; - - LLCoordScreen window_size; - LLWindow* windowp = getWindow(); - windowp->getSize(&window_size); - - S32 window_width = window_size.mX; - if( x > window_width - rect.getWidth() ) - { - delta_x = (window_width - rect.getWidth()) - x; - } - branch->translate( delta_x, 0 ); - - setHighlight(TRUE); - branch->setVisible( TRUE ); - branch->getParent()->sendChildToFront(branch); - } - } + LLMenuGL* branch = getBranch(); + if( branch->getVisible() && !branch->getTornOff() ) + { + branch->setVisible( FALSE ); + } + else + { + if (branch->getTornOff()) + { + LLFloater * branch_parent = dynamic_cast(branch->getParent()); + if (branch_parent) + { + gFloaterView->bringToFront(branch_parent); + } + } + else + { + // We're showing the drop-down menu, so patch up its labels/rects + branch->arrange(); + + LLRect rect = branch->getRect(); + S32 left = 0; + S32 top = getRect().mBottom; + localPointToOtherView(left, top, &left, &top, branch->getParent()); + + rect.setLeftTopAndSize( left, top, + rect.getWidth(), rect.getHeight() ); + branch->setRect( rect ); + S32 x = 0; + S32 y = 0; + branch->localPointToScreen( 0, 0, &x, &y ); + S32 delta_x = 0; + + LLCoordScreen window_size; + LLWindow* windowp = getWindow(); + windowp->getSize(&window_size); + + S32 window_width = window_size.mX; + if( x > window_width - rect.getWidth() ) + { + delta_x = (window_width - rect.getWidth()) - x; + } + branch->translate( delta_x, 0 ); + + setHighlight(TRUE); + branch->setVisible( TRUE ); + branch->getParent()->sendChildToFront(branch); + } + } } // set the hover status (called by it's menu) void LLMenuItemBranchDownGL::setHighlight( BOOL highlight ) { - if (highlight == getHighlight()) - return; - - //NOTE: Purposely calling all the way to the base to bypass auto-open. - LLMenuItemGL::setHighlight(highlight); - - LLMenuGL* branch = getBranch(); - if (!branch) - return; - - if( !highlight) - { - if (branch->getTornOff()) - { - LLFloater * branch_parent = dynamic_cast(branch->getParent()); - if (branch_parent) - { - branch_parent->setFocus(FALSE); - } - branch->clearHoverItem(); - } - else - { - branch->setVisible( FALSE ); - } - } + if (highlight == getHighlight()) + return; + + //NOTE: Purposely calling all the way to the base to bypass auto-open. + LLMenuItemGL::setHighlight(highlight); + + LLMenuGL* branch = getBranch(); + if (!branch) + return; + + if( !highlight) + { + if (branch->getTornOff()) + { + LLFloater * branch_parent = dynamic_cast(branch->getParent()); + if (branch_parent) + { + branch_parent->setFocus(FALSE); + } + branch->clearHoverItem(); + } + else + { + branch->setVisible( FALSE ); + } + } } BOOL LLMenuItemBranchDownGL::isActive() const { - // for top level menus, being open is sufficient to be considered - // active, because clicking on them with the mouse will open - // them, without moving keyboard focus to them - return isOpen(); + // for top level menus, being open is sufficient to be considered + // active, because clicking on them with the mouse will open + // them, without moving keyboard focus to them + return isOpen(); } BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask ) { - // switch to mouse control mode - LLMenuGL::setKeyboardMode(FALSE); + // switch to mouse control mode + LLMenuGL::setKeyboardMode(FALSE); - if (getVisible() && isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - else - { - onCommit(); - } + if (getVisible() && isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + else + { + onCommit(); + } - make_ui_sound("UISndClick"); - return TRUE; + make_ui_sound("UISndClick"); + return TRUE; } BOOL LLMenuItemBranchDownGL::handleMouseUp( S32 x, S32 y, MASK mask ) { - return TRUE; + return TRUE; } BOOL LLMenuItemBranchDownGL::handleAcceleratorKey(KEY key, MASK mask) { - BOOL branch_visible = getBranch()->getVisible(); - BOOL handled = getBranch()->handleAcceleratorKey(key, mask); - if (handled && !branch_visible && isInVisibleChain()) - { - // flash this menu entry because we triggered an invisible menu item - LLMenuHolderGL::setActivatedItem(this); - } + BOOL branch_visible = getBranch()->getVisible(); + BOOL handled = getBranch()->handleAcceleratorKey(key, mask); + if (handled && !branch_visible && isInVisibleChain()) + { + // flash this menu entry because we triggered an invisible menu item + LLMenuHolderGL::setActivatedItem(this); + } - return handled; + return handled; } void LLMenuItemBranchDownGL::onFocusLost() { @@ -1548,211 +1548,211 @@ void LLMenuItemBranchDownGL::setFocus(BOOL b) BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask) { - BOOL menu_open = getBranch()->getVisible(); - // don't do keyboard navigation of top-level menus unless in keyboard mode, or menu expanded - if (getHighlight() && getMenu()->isOpen() && (isActive() || LLMenuGL::getKeyboardMode())) - { - if (key == KEY_LEFT) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - LLMenuItemGL* itemp = getMenu()->highlightPrevItem(this); - // open new menu only if previous menu was open - if (itemp && itemp->getEnabled() && menu_open) - { - itemp->onCommit(); - } - - return TRUE; - } - else if (key == KEY_RIGHT) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - LLMenuItemGL* itemp = getMenu()->highlightNextItem(this); - // open new menu only if previous menu was open - if (itemp && itemp->getEnabled() && menu_open) - { - itemp->onCommit(); - } - - return TRUE; - } - else if (key == KEY_DOWN) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - if (!isActive()) - { - onCommit(); - } - getBranch()->highlightNextItem(NULL); - return TRUE; - } - else if (key == KEY_UP) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - if (!isActive()) - { - onCommit(); - } - getBranch()->highlightPrevItem(NULL); - return TRUE; - } - } - - return FALSE; + BOOL menu_open = getBranch()->getVisible(); + // don't do keyboard navigation of top-level menus unless in keyboard mode, or menu expanded + if (getHighlight() && getMenu()->isOpen() && (isActive() || LLMenuGL::getKeyboardMode())) + { + if (key == KEY_LEFT) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + LLMenuItemGL* itemp = getMenu()->highlightPrevItem(this); + // open new menu only if previous menu was open + if (itemp && itemp->getEnabled() && menu_open) + { + itemp->onCommit(); + } + + return TRUE; + } + else if (key == KEY_RIGHT) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + LLMenuItemGL* itemp = getMenu()->highlightNextItem(this); + // open new menu only if previous menu was open + if (itemp && itemp->getEnabled() && menu_open) + { + itemp->onCommit(); + } + + return TRUE; + } + else if (key == KEY_DOWN) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + if (!isActive()) + { + onCommit(); + } + getBranch()->highlightNextItem(NULL); + return TRUE; + } + else if (key == KEY_UP) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + if (!isActive()) + { + onCommit(); + } + getBranch()->highlightPrevItem(NULL); + return TRUE; + } + } + + return FALSE; } void LLMenuItemBranchDownGL::draw( void ) { - //FIXME: try removing this - if (getBranch()->getVisible() && !getBranch()->getTornOff()) - { - setHighlight(TRUE); - } - - if( getHighlight() ) - { - gGL.color4fv( mHighlightBackground.get().mV ); - gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - } - - LLColor4 color; - if (getHighlight()) - { - color = mHighlightForeground.get(); - } - else if( getEnabled() ) - { - color = mEnabledColor.get(); - } - else - { - color = mDisabledColor.get(); - } - getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color, - LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL); - - - // underline navigation key only when keyboard navigation has been initiated - if (getMenu()->jumpKeysActive() && LLMenuGL::getKeyboardMode()) - { - std::string upper_case_label = mLabel.getString(); - LLStringUtil::toUpper(upper_case_label); - std::string::size_type offset = upper_case_label.find(getJumpKey()); - if (offset != std::string::npos) - { - S32 x_offset = ll_round((F32)getRect().getWidth() / 2.f - getFont()->getWidthF32(mLabel.getString(), 0, S32_MAX) / 2.f); - S32 x_begin = x_offset + getFont()->getWidth(mLabel, 0, offset); - S32 x_end = x_offset + getFont()->getWidth(mLabel, 0, offset + 1); - gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS); - } - } + //FIXME: try removing this + if (getBranch()->getVisible() && !getBranch()->getTornOff()) + { + setHighlight(TRUE); + } + + if( getHighlight() ) + { + gGL.color4fv( mHighlightBackground.get().mV ); + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); + } + + LLColor4 color; + if (getHighlight()) + { + color = mHighlightForeground.get(); + } + else if( getEnabled() ) + { + color = mEnabledColor.get(); + } + else + { + color = mDisabledColor.get(); + } + getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color, + LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL); + + + // underline navigation key only when keyboard navigation has been initiated + if (getMenu()->jumpKeysActive() && LLMenuGL::getKeyboardMode()) + { + std::string upper_case_label = mLabel.getString(); + LLStringUtil::toUpper(upper_case_label); + std::string::size_type offset = upper_case_label.find(getJumpKey()); + if (offset != std::string::npos) + { + S32 x_offset = ll_round((F32)getRect().getWidth() / 2.f - getFont()->getWidthF32(mLabel.getString(), 0, S32_MAX) / 2.f); + S32 x_begin = x_offset + getFont()->getWidth(mLabel, 0, offset); + S32 x_end = x_offset + getFont()->getWidth(mLabel, 0, offset + 1); + gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS); + } + } } class LLMenuScrollItem : public LLMenuItemCallGL { public: - enum EArrowType - { - ARROW_DOWN, - ARROW_UP - }; - struct ArrowTypes : public LLInitParam::TypeValuesHelper - { - static void declareValues() - { - declare("up", ARROW_UP); - declare("down", ARROW_DOWN); - } - }; - - struct Params : public LLInitParam::Block - { - Optional arrow_type; - Optional scroll_callback; - }; + enum EArrowType + { + ARROW_DOWN, + ARROW_UP + }; + struct ArrowTypes : public LLInitParam::TypeValuesHelper + { + static void declareValues() + { + declare("up", ARROW_UP); + declare("down", ARROW_DOWN); + } + }; + + struct Params : public LLInitParam::Block + { + Optional arrow_type; + Optional scroll_callback; + }; protected: - LLMenuScrollItem(const Params&); - friend class LLUICtrlFactory; + LLMenuScrollItem(const Params&); + friend class LLUICtrlFactory; public: - /*virtual*/ void draw(); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); - /*virtual*/ void setEnabled(BOOL enabled); - virtual void onCommit( void ); + /*virtual*/ void draw(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); + /*virtual*/ void setEnabled(BOOL enabled); + virtual void onCommit( void ); private: - LLButton* mArrowBtn; + LLButton* mArrowBtn; }; LLMenuScrollItem::LLMenuScrollItem(const Params& p) -: LLMenuItemCallGL(p) -{ - std::string icon; - if (p.arrow_type.isProvided() && p.arrow_type == ARROW_UP) - { - icon = "arrow_up.tga"; - } - else - { - icon = "arrow_down.tga"; - } - - LLButton::Params bparams; - - // Disabled the Return key handling by LLMenuScrollItem instead of - // passing the key press to the currently selected menu item. See STORM-385. - bparams.commit_on_return(false); - bparams.mouse_opaque(true); - bparams.scale_image(false); - bparams.click_callback(p.scroll_callback); - bparams.mouse_held_callback(p.scroll_callback); - bparams.follows.flags(FOLLOWS_ALL); - std::string background = "transparent.j2c"; - bparams.image_unselected.name(background); - bparams.image_disabled.name(background); - bparams.image_selected.name(background); - bparams.image_hover_selected.name(background); - bparams.image_disabled_selected.name(background); - bparams.image_hover_unselected.name(background); - bparams.image_overlay.name(icon); - - mArrowBtn = LLUICtrlFactory::create(bparams); - addChild(mArrowBtn); +: LLMenuItemCallGL(p) +{ + std::string icon; + if (p.arrow_type.isProvided() && p.arrow_type == ARROW_UP) + { + icon = "arrow_up.tga"; + } + else + { + icon = "arrow_down.tga"; + } + + LLButton::Params bparams; + + // Disabled the Return key handling by LLMenuScrollItem instead of + // passing the key press to the currently selected menu item. See STORM-385. + bparams.commit_on_return(false); + bparams.mouse_opaque(true); + bparams.scale_image(false); + bparams.click_callback(p.scroll_callback); + bparams.mouse_held_callback(p.scroll_callback); + bparams.follows.flags(FOLLOWS_ALL); + std::string background = "transparent.j2c"; + bparams.image_unselected.name(background); + bparams.image_disabled.name(background); + bparams.image_selected.name(background); + bparams.image_hover_selected.name(background); + bparams.image_disabled_selected.name(background); + bparams.image_hover_unselected.name(background); + bparams.image_overlay.name(icon); + + mArrowBtn = LLUICtrlFactory::create(bparams); + addChild(mArrowBtn); } /*virtual*/ void LLMenuScrollItem::draw() { - LLUICtrl::draw(); + LLUICtrl::draw(); } /*virtual*/ void LLMenuScrollItem::reshape(S32 width, S32 height, BOOL called_from_parent) { - mArrowBtn->reshape(width, height, called_from_parent); - LLView::reshape(width, height, called_from_parent); + mArrowBtn->reshape(width, height, called_from_parent); + LLView::reshape(width, height, called_from_parent); } /*virtual*/ void LLMenuScrollItem::setEnabled(BOOL enabled) { - mArrowBtn->setEnabled(enabled); - LLView::setEnabled(enabled); + mArrowBtn->setEnabled(enabled); + LLView::setEnabled(enabled); } void LLMenuScrollItem::onCommit( void ) { - LLUICtrl::onCommit(); + LLUICtrl::onCommit(); } ///============================================================================ @@ -1760,105 +1760,105 @@ void LLMenuScrollItem::onCommit( void ) ///============================================================================ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p) -: LLUICtrl(p), - mBackgroundColor( p.bg_color() ), - mBgVisible( p.bg_visible ), - mDropShadowed( p.drop_shadow ), - mHasSelection(false), - mHorizontalLayout( p.horizontal_layout ), - mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout - mMaxScrollableItems(p.max_scrollable_items), - mPreferredWidth(p.preferred_width), - mKeepFixedSize( p.keep_fixed_size ), - mLabel (p.label), - mLastMouseX(0), - mLastMouseY(0), - mMouseVelX(0), - mMouseVelY(0), - mTornOff(FALSE), - mTearOffItem(NULL), - mSpilloverBranch(NULL), - mFirstVisibleItem(NULL), - mArrowUpItem(NULL), - mArrowDownItem(NULL), - mSpilloverMenu(NULL), - mJumpKey(p.jump_key), - mCreateJumpKeys(p.create_jump_keys), - mNeedsArrange(FALSE), - mAlwaysShowMenu(FALSE), - mResetScrollPositionOnShow(true), - mShortcutPad(p.shortcut_pad), +: LLUICtrl(p), + mBackgroundColor( p.bg_color() ), + mBgVisible( p.bg_visible ), + mDropShadowed( p.drop_shadow ), + mHasSelection(false), + mHorizontalLayout( p.horizontal_layout ), + mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout + mMaxScrollableItems(p.max_scrollable_items), + mPreferredWidth(p.preferred_width), + mKeepFixedSize( p.keep_fixed_size ), + mLabel (p.label), + mLastMouseX(0), + mLastMouseY(0), + mMouseVelX(0), + mMouseVelY(0), + mTornOff(FALSE), + mTearOffItem(NULL), + mSpilloverBranch(NULL), + mFirstVisibleItem(NULL), + mArrowUpItem(NULL), + mArrowDownItem(NULL), + mSpilloverMenu(NULL), + mJumpKey(p.jump_key), + mCreateJumpKeys(p.create_jump_keys), + mNeedsArrange(FALSE), + mAlwaysShowMenu(FALSE), + mResetScrollPositionOnShow(true), + mShortcutPad(p.shortcut_pad), mFont(p.font) { - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("_"); - tokenizer tokens(p.label(), sep); - tokenizer::iterator token_iter; + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("_"); + tokenizer tokens(p.label(), sep); + tokenizer::iterator token_iter; - S32 token_count = 0; - std::string new_menu_label; - for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - new_menu_label += (*token_iter); - if (token_count > 0) - { - setJumpKey((*token_iter).c_str()[0]); - } - ++token_count; - } - setLabel(new_menu_label); + S32 token_count = 0; + std::string new_menu_label; + for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + new_menu_label += (*token_iter); + if (token_count > 0) + { + setJumpKey((*token_iter).c_str()[0]); + } + ++token_count; + } + setLabel(new_menu_label); - mFadeTimer.stop(); + mFadeTimer.stop(); } void LLMenuGL::initFromParams(const LLMenuGL::Params& p) { - LLUICtrl::initFromParams(p); - setCanTearOff(p.can_tear_off); + LLUICtrl::initFromParams(p); + setCanTearOff(p.can_tear_off); } // Destroys the object LLMenuGL::~LLMenuGL( void ) { - // delete the branch, as it might not be in view hierarchy - // leave the menu, because it is always in view hierarchy - delete mSpilloverBranch; - mJumpKeys.clear(); + // delete the branch, as it might not be in view hierarchy + // leave the menu, because it is always in view hierarchy + delete mSpilloverBranch; + mJumpKeys.clear(); } void LLMenuGL::setCanTearOff(BOOL tear_off) { - if (tear_off && mTearOffItem == NULL) - { - LLMenuItemTearOffGL::Params p; - mTearOffItem = LLUICtrlFactory::create(p); - addChild(mTearOffItem); - } - else if (!tear_off && mTearOffItem != NULL) - { - mItems.remove(mTearOffItem); - removeChild(mTearOffItem); - delete mTearOffItem; - mTearOffItem = NULL; - needsArrange(); - } + if (tear_off && mTearOffItem == NULL) + { + LLMenuItemTearOffGL::Params p; + mTearOffItem = LLUICtrlFactory::create(p); + addChild(mTearOffItem); + } + else if (!tear_off && mTearOffItem != NULL) + { + mItems.remove(mTearOffItem); + removeChild(mTearOffItem); + delete mTearOffItem; + mTearOffItem = NULL; + needsArrange(); + } } bool LLMenuGL::addChild(LLView* view, S32 tab_group) { - LLMenuGL* menup = dynamic_cast(view); - if (menup) - { - return appendMenu(menup); - } - - LLMenuItemGL* itemp = dynamic_cast(view); - if (itemp) - { - return append(itemp); - } - - return false; + LLMenuGL* menup = dynamic_cast(view); + if (menup) + { + return appendMenu(menup); + } + + LLMenuItemGL* itemp = dynamic_cast(view); + if (itemp) + { + return append(itemp); + } + + return false; } // Used in LLContextMenu and in LLTogleableMenu @@ -1866,31 +1866,31 @@ bool LLMenuGL::addChild(LLView* view, S32 tab_group) // Add an item to the context menu branch bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) { - LLContextMenu* context = dynamic_cast(view); - if (context) - { - return appendContextSubMenu(context); - } + LLContextMenu* context = dynamic_cast(view); + if (context) + { + return appendContextSubMenu(context); + } - LLMenuItemSeparatorGL* separator = dynamic_cast(view); - if (separator) - { - return append(separator); - } + LLMenuItemSeparatorGL* separator = dynamic_cast(view); + if (separator) + { + return append(separator); + } + + LLMenuItemGL* item = dynamic_cast(view); + if (item) + { + return append(item); + } - LLMenuItemGL* item = dynamic_cast(view); - if (item) - { - return append(item); - } - - LLMenuGL* menup = dynamic_cast(view); - if (menup) - { - return appendMenu(menup); - } + LLMenuGL* menup = dynamic_cast(view); + if (menup) + { + return appendMenu(menup); + } - return false; + return false; } @@ -1902,882 +1902,882 @@ void LLMenuGL::deleteAllChildren() void LLMenuGL::removeChild( LLView* ctrl) { - // previously a dynamic_cast with if statement to check validity - // unfortunately removeChild is called by ~LLView, and at that point the - // object being deleted is no longer a LLMenuItemGL so a dynamic_cast will fail - LLMenuItemGL* itemp = static_cast(ctrl); + // previously a dynamic_cast with if statement to check validity + // unfortunately removeChild is called by ~LLView, and at that point the + // object being deleted is no longer a LLMenuItemGL so a dynamic_cast will fail + LLMenuItemGL* itemp = static_cast(ctrl); - item_list_t::iterator found_it = std::find(mItems.begin(), mItems.end(), (itemp)); - if (found_it != mItems.end()) - { - mItems.erase(found_it); - } + item_list_t::iterator found_it = std::find(mItems.begin(), mItems.end(), (itemp)); + if (found_it != mItems.end()) + { + mItems.erase(found_it); + } - return LLUICtrl::removeChild(ctrl); + return LLUICtrl::removeChild(ctrl); } BOOL LLMenuGL::postBuild() { - createJumpKeys(); - return LLUICtrl::postBuild(); + createJumpKeys(); + return LLUICtrl::postBuild(); } // are we the childmost active menu and hence our jump keys should be enabled? // or are we a free-standing torn-off menu (which uses jump keys too) BOOL LLMenuGL::jumpKeysActive() { - LLMenuItemGL* highlighted_item = getHighlightedItem(); - BOOL active = getVisible() && getEnabled(); - - if (active) - { - if (getTornOff()) - { - // activation of jump keys on torn off menus controlled by keyboard focus - LLFloater * parent = dynamic_cast(getParent()); - if (parent) - { - active = parent->hasFocus(); - } - } - else - { - // Are we the terminal active menu? - // Yes, if parent menu item deems us to be active (just being visible is sufficient for top-level menus) - // and we don't have a highlighted menu item pointing to an active sub-menu - active = (!getParentMenuItem() || getParentMenuItem()->isActive()) // I have a parent that is active... - && (!highlighted_item || !highlighted_item->isActive()); //... but no child that is active - } - } - - return active; + LLMenuItemGL* highlighted_item = getHighlightedItem(); + BOOL active = getVisible() && getEnabled(); + + if (active) + { + if (getTornOff()) + { + // activation of jump keys on torn off menus controlled by keyboard focus + LLFloater * parent = dynamic_cast(getParent()); + if (parent) + { + active = parent->hasFocus(); + } + } + else + { + // Are we the terminal active menu? + // Yes, if parent menu item deems us to be active (just being visible is sufficient for top-level menus) + // and we don't have a highlighted menu item pointing to an active sub-menu + active = (!getParentMenuItem() || getParentMenuItem()->isActive()) // I have a parent that is active... + && (!highlighted_item || !highlighted_item->isActive()); //... but no child that is active + } + } + + return active; } BOOL LLMenuGL::isOpen() { - if (getTornOff()) - { - LLMenuItemGL* itemp = getHighlightedItem(); - // if we have an open sub-menu, then we are considered part of - // the open menu chain even if we don't have focus - if (itemp && itemp->isOpen()) - { - return TRUE; - } - // otherwise we are only active if we have keyboard focus - LLFloater * parent = dynamic_cast(getParent()); - if (parent) - { - return parent->hasFocus(); - } - return FALSE; - } - else - { - // normally, menus are hidden as soon as the user focuses - // on another menu, so just use the visibility criterion - return getVisible(); - } + if (getTornOff()) + { + LLMenuItemGL* itemp = getHighlightedItem(); + // if we have an open sub-menu, then we are considered part of + // the open menu chain even if we don't have focus + if (itemp && itemp->isOpen()) + { + return TRUE; + } + // otherwise we are only active if we have keyboard focus + LLFloater * parent = dynamic_cast(getParent()); + if (parent) + { + return parent->hasFocus(); + } + return FALSE; + } + else + { + // normally, menus are hidden as soon as the user focuses + // on another menu, so just use the visibility criterion + return getVisible(); + } } bool LLMenuGL::scrollItems(EScrollingDirection direction) { - // Slowing down items scrolling when arrow button is held - if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem) - { - mScrollItemsTimer.setTimerExpirySec(.033f); - } - else - { - return false; - } - - switch (direction) - { - case SD_UP: - { - item_list_t::iterator cur_item_iter; - item_list_t::iterator prev_item_iter; - for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) - { - if( (*cur_item_iter) == mFirstVisibleItem) - { - break; - } - if ((*cur_item_iter)->getVisible()) - { - prev_item_iter = cur_item_iter; - } - } - - if ((*prev_item_iter)->getVisible()) - { - mFirstVisibleItem = *prev_item_iter; - } - break; - } - case SD_DOWN: - { - if (NULL == mFirstVisibleItem) - { - mFirstVisibleItem = *mItems.begin(); - } - - item_list_t::iterator cur_item_iter; - - for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) - { - if( (*cur_item_iter) == mFirstVisibleItem) - { - break; - } - } - - item_list_t::iterator next_item_iter; - - if (cur_item_iter != mItems.end()) - { - for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++) - { - if( (*next_item_iter)->getVisible()) - { - break; - } - } - - if (next_item_iter != mItems.end() && - (*next_item_iter)->getVisible()) - { - mFirstVisibleItem = *next_item_iter; - } - } - break; - } - case SD_BEGIN: - { - mFirstVisibleItem = *mItems.begin(); - break; - } - case SD_END: - { - item_list_t::reverse_iterator first_visible_item_iter = mItems.rend(); - - // Need to scroll through number of actual existing items in menu. - // Otherwise viewer will hang for a time needed to scroll U32_MAX - // times in std::advance(). STORM-659. - size_t nitems = mItems.size(); - U32 scrollable_items = nitems < mMaxScrollableItems ? nitems : mMaxScrollableItems; - - // Advance by mMaxScrollableItems back from the end of the list - // to make the last item visible. - std::advance(first_visible_item_iter, scrollable_items); - mFirstVisibleItem = *first_visible_item_iter; - break; - } - default: - LL_WARNS() << "Unknown scrolling direction: " << direction << LL_ENDL; - } - - mNeedsArrange = TRUE; - arrangeAndClear(); - - return true; -} - -// rearrange the child rects so they fit the shape of the menu. -void LLMenuGL::arrange( void ) -{ - // calculate the height & width, and set our rect based on that - // information. - const LLRect& initial_rect = getRect(); - - U32 width = 0, height = MENU_ITEM_PADDING; - - cleanupSpilloverBranch(); - - if( mItems.size() ) - { - const LLRect menu_region_rect = LLMenuGL::sMenuContainer ? LLMenuGL::sMenuContainer->getMenuRect() : LLRect(0, S32_MAX, S32_MAX, 0); - - // torn off menus are not constrained to the size of the screen - U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth(); - U32 max_height = getTornOff() ? U32_MAX: menu_region_rect.getHeight(); - - // *FIX: create the item first and then ask for its dimensions? - S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate - S32 spillover_item_height = LLFontGL::getFontSansSerif()->getLineHeight() + MENU_ITEM_PADDING; - - // Scrolling support - item_list_t::iterator first_visible_item_iter; - item_list_t::iterator first_hidden_item_iter = mItems.end(); - S32 height_before_first_visible_item = -1; - S32 visible_items_height = 0; - U32 scrollable_items_cnt = 0; - - if (mHorizontalLayout) - { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - // do first so LLMenuGLItemCall can call on_visible to determine if visible - (*item_iter)->buildDrawLabel(); - - if ((*item_iter)->getVisible()) - { - if (!getTornOff() - && *item_iter != mSpilloverBranch - && width + (*item_iter)->getNominalWidth() > max_width - spillover_item_width) - { - // no room for any more items - createSpilloverBranch(); - - std::vector items_to_remove; - std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); - std::vector::iterator spillover_iter; - for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) - { - LLMenuItemGL* itemp = (*spillover_iter); - removeChild(itemp); - mSpilloverMenu->addChild(itemp); - } - - addChild(mSpilloverBranch); - - height = llmax(height, mSpilloverBranch->getNominalHeight()); - width += mSpilloverBranch->getNominalWidth(); - - break; - } - else - { - // track our rect - height = llmax(height, (*item_iter)->getNominalHeight()); - width += (*item_iter)->getNominalWidth(); - } - } - } - } - else - { - for (LLMenuItemGL* itemp : mItems) - { - // do first so LLMenuGLItemCall can call on_visible to determine if visible - itemp->buildDrawLabel(); - } - item_list_t::iterator item_iter; - - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if ((*item_iter)->getVisible()) - { - if (!getTornOff() - && !mScrollable - && *item_iter != mSpilloverBranch - && height + (*item_iter)->getNominalHeight() > max_height - spillover_item_height) - { - // don't show only one item - int visible_items = 0; - item_list_t::iterator count_iter; - for (count_iter = item_iter; count_iter != mItems.end(); ++count_iter) - { - if((*count_iter)->getVisible()) - visible_items++; - } - if (visible_items>1) - { - // no room for any more items - createSpilloverBranch(); - - std::vector items_to_remove; - std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); - std::vector::iterator spillover_iter; - for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) - { - LLMenuItemGL* itemp = (*spillover_iter); - removeChild(itemp); - mSpilloverMenu->addChild(itemp); - } - - - addChild(mSpilloverBranch); - - height += mSpilloverBranch->getNominalHeight(); - width = llmax( width, mSpilloverBranch->getNominalWidth() ); - - break; - } - } - - // track our rect - height += (*item_iter)->getNominalHeight(); - width = llmax( width, (*item_iter)->getNominalWidth() ); - - if (mScrollable) - { - // Determining visible items boundaries - if (NULL == mFirstVisibleItem) - { - mFirstVisibleItem = *item_iter; - } - - if (*item_iter == mFirstVisibleItem) - { - height_before_first_visible_item = height - (*item_iter)->getNominalHeight(); - first_visible_item_iter = item_iter; - scrollable_items_cnt = 0; - } - - if (-1 != height_before_first_visible_item && 0 == visible_items_height && - (++scrollable_items_cnt > mMaxScrollableItems || - height - height_before_first_visible_item > max_height - spillover_item_height * 2 )) - { - first_hidden_item_iter = item_iter; - visible_items_height = height - height_before_first_visible_item - (*item_iter)->getNominalHeight(); - scrollable_items_cnt--; - } - } - } - } - - if (mPreferredWidth < U32_MAX) - width = llmin(mPreferredWidth, max_width); - - if (mScrollable) - { - S32 max_items_height = max_height - spillover_item_height * 2; - - if (visible_items_height == 0) - visible_items_height = height - height_before_first_visible_item; - - // Fix mFirstVisibleItem value, if it doesn't allow to display all items, that can fit - if (visible_items_height < max_items_height && scrollable_items_cnt < mMaxScrollableItems) - { - item_list_t::iterator tmp_iter(first_visible_item_iter); - while (visible_items_height < max_items_height && - scrollable_items_cnt < mMaxScrollableItems && - first_visible_item_iter != mItems.begin()) - { - if ((*first_visible_item_iter)->getVisible()) - { - // It keeps visible item, after first_visible_item_iter - tmp_iter = first_visible_item_iter; - } - - first_visible_item_iter--; - - if ((*first_visible_item_iter)->getVisible()) - { - visible_items_height += (*first_visible_item_iter)->getNominalHeight(); - height_before_first_visible_item -= (*first_visible_item_iter)->getNominalHeight(); - scrollable_items_cnt++; - } - } - - // Roll back one item, that doesn't fit - if (visible_items_height > max_items_height) - { - visible_items_height -= (*first_visible_item_iter)->getNominalHeight(); - height_before_first_visible_item += (*first_visible_item_iter)->getNominalHeight(); - scrollable_items_cnt--; - first_visible_item_iter = tmp_iter; - } - if (!(*first_visible_item_iter)->getVisible()) - { - first_visible_item_iter = tmp_iter; - } - - mFirstVisibleItem = *first_visible_item_iter; - } - } - } - - S32 cur_height = (S32)llmin(max_height, height); - - if (mScrollable && - (height_before_first_visible_item > MENU_ITEM_PADDING || - height_before_first_visible_item + visible_items_height < (S32)height)) - { - // Reserving 2 extra slots for arrow items - cur_height = visible_items_height + spillover_item_height * 2; - } - - setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width, getRect().mTop - cur_height)); - - S32 cur_width = 0; - S32 offset = 0; - if (mScrollable) - { - // No space for all items, creating arrow items - if (height_before_first_visible_item > MENU_ITEM_PADDING || - height_before_first_visible_item + visible_items_height < (S32)height) - { - if (NULL == mArrowUpItem) - { - LLMenuScrollItem::Params item_params; - item_params.name(ARROW_UP); - item_params.arrow_type(LLMenuScrollItem::ARROW_UP); - item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP)); - - mArrowUpItem = LLUICtrlFactory::create(item_params); - LLUICtrl::addChild(mArrowUpItem); - - } - if (NULL == mArrowDownItem) - { - LLMenuScrollItem::Params item_params; - item_params.name(ARROW_DOWN); - item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN); - item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN)); - - mArrowDownItem = LLUICtrlFactory::create(item_params); - LLUICtrl::addChild(mArrowDownItem); - } - - LLRect rect; - mArrowUpItem->setRect(rect.setLeftTopAndSize( 0, cur_height, width, mArrowUpItem->getNominalHeight())); - mArrowUpItem->setVisible(TRUE); - mArrowUpItem->setEnabled(height_before_first_visible_item > MENU_ITEM_PADDING); - mArrowUpItem->reshape(width, mArrowUpItem->getNominalHeight()); - mArrowDownItem->setRect(rect.setLeftTopAndSize( 0, mArrowDownItem->getNominalHeight(), width, mArrowDownItem->getNominalHeight())); - mArrowDownItem->setVisible(TRUE); - mArrowDownItem->setEnabled(height_before_first_visible_item + visible_items_height < (S32)height); - mArrowDownItem->reshape(width, mArrowDownItem->getNominalHeight()); - - cur_height -= mArrowUpItem->getNominalHeight(); - - offset = menu_region_rect.mRight; // This moves items behind visible area - } - else - { - if (NULL != mArrowUpItem) - { - mArrowUpItem->setVisible(FALSE); - } - if (NULL != mArrowDownItem) - { - mArrowDownItem->setVisible(FALSE); - } - } - - } - - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if ((*item_iter)->getVisible()) - { - if (mScrollable) - { - if (item_iter == first_visible_item_iter) - { - offset = 0; - } - else if (item_iter == first_hidden_item_iter) - { - offset = menu_region_rect.mRight; // This moves items behind visible area - } - } - - // setup item rect to hold label - LLRect rect; - if (mHorizontalLayout) - { - rect.setLeftTopAndSize( cur_width, height, (*item_iter)->getNominalWidth(), height); - cur_width += (*item_iter)->getNominalWidth(); - } - else - { - rect.setLeftTopAndSize( 0 + offset, cur_height, width, (*item_iter)->getNominalHeight()); - if (offset == 0) - { - cur_height -= (*item_iter)->getNominalHeight(); - } - } - (*item_iter)->setRect( rect ); - } - } - + // Slowing down items scrolling when arrow button is held + if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem) + { + mScrollItemsTimer.setTimerExpirySec(.033f); + } + else + { + return false; + } - if (getTornOff()) + switch (direction) + { + case SD_UP: + { + item_list_t::iterator cur_item_iter; + item_list_t::iterator prev_item_iter; + for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) { - LLTearOffMenu * torn_off_menu = dynamic_cast(getParent()); - if (torn_off_menu) + if( (*cur_item_iter) == mFirstVisibleItem) { - torn_off_menu->updateSize(); + break; + } + if ((*cur_item_iter)->getVisible()) + { + prev_item_iter = cur_item_iter; } } - } - if (mKeepFixedSize) - { - reshape(initial_rect.getWidth(), initial_rect.getHeight()); - } -} -void LLMenuGL::arrangeAndClear( void ) -{ - if (mNeedsArrange) - { - arrange(); - mNeedsArrange = FALSE; - } -} + if ((*prev_item_iter)->getVisible()) + { + mFirstVisibleItem = *prev_item_iter; + } + break; + } + case SD_DOWN: + { + if (NULL == mFirstVisibleItem) + { + mFirstVisibleItem = *mItems.begin(); + } -void LLMenuGL::createSpilloverBranch() -{ - if (!mSpilloverBranch) - { - // should be NULL but delete anyway - delete mSpilloverMenu; - // technically, you can't tear off spillover menus, but we're passing the handle - // along just to be safe - LLMenuGL::Params p; - std::string label = LLTrans::getString("More"); - p.name("More"); - p.label(label); - p.bg_color(mBackgroundColor); - p.bg_visible(true); - p.can_tear_off(false); - mSpilloverMenu = new LLMenuGL(p); - mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); - - LLMenuItemBranchGL::Params branch_params; - branch_params.name = "More"; - branch_params.label = label; - branch_params.branch = mSpilloverMenu; - branch_params.font.style = "italic"; - branch_params.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); - branch_params.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); - branch_params.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); - - mSpilloverBranch = LLUICtrlFactory::create(branch_params); - } -} + item_list_t::iterator cur_item_iter; -void LLMenuGL::cleanupSpilloverBranch() -{ - if (mSpilloverBranch && mSpilloverBranch->getParent() == this) - { - // head-recursion to propagate items back up to root menu - mSpilloverMenu->cleanupSpilloverBranch(); - - // pop off spillover items - while (mSpilloverMenu->getItemCount()) - { - LLMenuItemGL* itemp = mSpilloverMenu->getItem(0); - mSpilloverMenu->removeChild(itemp); - // put them at the end of our own list - addChild(itemp); - } - - // Delete the branch, and since the branch will delete the menu, - // set the menu* to null. - delete mSpilloverBranch; - mSpilloverBranch = NULL; - mSpilloverMenu = NULL; - } -} + for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++) + { + if( (*cur_item_iter) == mFirstVisibleItem) + { + break; + } + } -void LLMenuGL::createJumpKeys() -{ - if (!mCreateJumpKeys) return; - mCreateJumpKeys = FALSE; - - mJumpKeys.clear(); - - std::set unique_words; - std::set shared_words; - - item_list_t::iterator item_it; - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(" "); - - for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) - { - std::string uppercase_label = (*item_it)->getLabel(); - LLStringUtil::toUpper(uppercase_label); - - tokenizer tokens(uppercase_label, sep); - tokenizer::iterator token_iter; - for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - if (unique_words.find(*token_iter) != unique_words.end()) - { - // this word exists in more than one menu instance - shared_words.insert(*token_iter); - } - else - { - // we have a new word, keep track of it - unique_words.insert(*token_iter); - } - } - } - - // pre-assign specified jump keys - for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) - { - KEY jump_key = (*item_it)->getJumpKey(); - if(jump_key != KEY_NONE) - { - if (mJumpKeys.find(jump_key) == mJumpKeys.end()) - { - mJumpKeys.insert(std::pair(jump_key, (*item_it))); - } - else - { - // this key is already spoken for, - // so we need to reassign it below - (*item_it)->setJumpKey(KEY_NONE); - } - } - } - - for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) - { - // skip over items that already have assigned jump keys - if ((*item_it)->getJumpKey() != KEY_NONE) - { - continue; - } - std::string uppercase_label = (*item_it)->getLabel(); - LLStringUtil::toUpper(uppercase_label); - - tokenizer tokens(uppercase_label, sep); - tokenizer::iterator token_iter; - - BOOL found_key = FALSE; - for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - std::string uppercase_word = *token_iter; - - // this word is not shared with other menu entries... - if (shared_words.find(*token_iter) == shared_words.end()) - { - S32 i; - for(i = 0; i < (S32)uppercase_word.size(); i++) - { - char jump_key = uppercase_word[i]; - - if (LLStringOps::isDigit(jump_key) || (LLStringOps::isUpper(jump_key) && - mJumpKeys.find(jump_key) == mJumpKeys.end())) - { - mJumpKeys.insert(std::pair(jump_key, (*item_it))); - (*item_it)->setJumpKey(jump_key); - found_key = TRUE; - break; - } - } - } - if (found_key) - { - break; - } - } - } -} + item_list_t::iterator next_item_iter; -// remove all items on the menu -void LLMenuGL::empty( void ) -{ - cleanupSpilloverBranch(); + if (cur_item_iter != mItems.end()) + { + for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++) + { + if( (*next_item_iter)->getVisible()) + { + break; + } + } + + if (next_item_iter != mItems.end() && + (*next_item_iter)->getVisible()) + { + mFirstVisibleItem = *next_item_iter; + } + } + break; + } + case SD_BEGIN: + { + mFirstVisibleItem = *mItems.begin(); + break; + } + case SD_END: + { + item_list_t::reverse_iterator first_visible_item_iter = mItems.rend(); + + // Need to scroll through number of actual existing items in menu. + // Otherwise viewer will hang for a time needed to scroll U32_MAX + // times in std::advance(). STORM-659. + size_t nitems = mItems.size(); + U32 scrollable_items = nitems < mMaxScrollableItems ? nitems : mMaxScrollableItems; + + // Advance by mMaxScrollableItems back from the end of the list + // to make the last item visible. + std::advance(first_visible_item_iter, scrollable_items); + mFirstVisibleItem = *first_visible_item_iter; + break; + } + default: + LL_WARNS() << "Unknown scrolling direction: " << direction << LL_ENDL; + } - mItems.clear(); - mFirstVisibleItem = NULL; - mArrowUpItem = NULL; - mArrowDownItem = NULL; + mNeedsArrange = TRUE; + arrangeAndClear(); - deleteAllChildren(); + return true; } -// erase group of items from menu -void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) +// rearrange the child rects so they fit the shape of the menu. +void LLMenuGL::arrange( void ) { - S32 items = mItems.size(); + // calculate the height & width, and set our rect based on that + // information. + const LLRect& initial_rect = getRect(); - if ( items == 0 || begin >= end || begin < 0 || end > items ) - { - return; - } + U32 width = 0, height = MENU_ITEM_PADDING; - item_list_t::iterator start_position = mItems.begin(); - std::advance(start_position, begin); + cleanupSpilloverBranch(); - item_list_t::iterator end_position = mItems.begin(); - std::advance(end_position, end); + if( mItems.size() ) + { + const LLRect menu_region_rect = LLMenuGL::sMenuContainer ? LLMenuGL::sMenuContainer->getMenuRect() : LLRect(0, S32_MAX, S32_MAX, 0); - for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++) - { - LLUICtrl::removeChild(*position_iter); - } + // torn off menus are not constrained to the size of the screen + U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth(); + U32 max_height = getTornOff() ? U32_MAX: menu_region_rect.getHeight(); - mItems.erase(start_position, end_position); + // *FIX: create the item first and then ask for its dimensions? + S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate + S32 spillover_item_height = LLFontGL::getFontSansSerif()->getLineHeight() + MENU_ITEM_PADDING; - if (arrange) - { - needsArrange(); - } -} + // Scrolling support + item_list_t::iterator first_visible_item_iter; + item_list_t::iterator first_hidden_item_iter = mItems.end(); + S32 height_before_first_visible_item = -1; + S32 visible_items_height = 0; + U32 scrollable_items_cnt = 0; -// add new item at position -void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) -{ - LLMenuItemGL * item = dynamic_cast(ctrl); + if (mHorizontalLayout) + { + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + // do first so LLMenuGLItemCall can call on_visible to determine if visible + (*item_iter)->buildDrawLabel(); + + if ((*item_iter)->getVisible()) + { + if (!getTornOff() + && *item_iter != mSpilloverBranch + && width + (*item_iter)->getNominalWidth() > max_width - spillover_item_width) + { + // no room for any more items + createSpilloverBranch(); + + std::vector items_to_remove; + std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); + std::vector::iterator spillover_iter; + for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) + { + LLMenuItemGL* itemp = (*spillover_iter); + removeChild(itemp); + mSpilloverMenu->addChild(itemp); + } + + addChild(mSpilloverBranch); + + height = llmax(height, mSpilloverBranch->getNominalHeight()); + width += mSpilloverBranch->getNominalWidth(); + + break; + } + else + { + // track our rect + height = llmax(height, (*item_iter)->getNominalHeight()); + width += (*item_iter)->getNominalWidth(); + } + } + } + } + else + { + for (LLMenuItemGL* itemp : mItems) + { + // do first so LLMenuGLItemCall can call on_visible to determine if visible + itemp->buildDrawLabel(); + } + item_list_t::iterator item_iter; - if (NULL == item || position < 0 || position >= mItems.size()) - { - return; - } + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if ((*item_iter)->getVisible()) + { + if (!getTornOff() + && !mScrollable + && *item_iter != mSpilloverBranch + && height + (*item_iter)->getNominalHeight() > max_height - spillover_item_height) + { + // don't show only one item + int visible_items = 0; + item_list_t::iterator count_iter; + for (count_iter = item_iter; count_iter != mItems.end(); ++count_iter) + { + if((*count_iter)->getVisible()) + visible_items++; + } + if (visible_items>1) + { + // no room for any more items + createSpilloverBranch(); + + std::vector items_to_remove; + std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); + std::vector::iterator spillover_iter; + for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) + { + LLMenuItemGL* itemp = (*spillover_iter); + removeChild(itemp); + mSpilloverMenu->addChild(itemp); + } + + + addChild(mSpilloverBranch); + + height += mSpilloverBranch->getNominalHeight(); + width = llmax( width, mSpilloverBranch->getNominalWidth() ); + + break; + } + } + + // track our rect + height += (*item_iter)->getNominalHeight(); + width = llmax( width, (*item_iter)->getNominalWidth() ); + + if (mScrollable) + { + // Determining visible items boundaries + if (NULL == mFirstVisibleItem) + { + mFirstVisibleItem = *item_iter; + } + + if (*item_iter == mFirstVisibleItem) + { + height_before_first_visible_item = height - (*item_iter)->getNominalHeight(); + first_visible_item_iter = item_iter; + scrollable_items_cnt = 0; + } + + if (-1 != height_before_first_visible_item && 0 == visible_items_height && + (++scrollable_items_cnt > mMaxScrollableItems || + height - height_before_first_visible_item > max_height - spillover_item_height * 2 )) + { + first_hidden_item_iter = item_iter; + visible_items_height = height - height_before_first_visible_item - (*item_iter)->getNominalHeight(); + scrollable_items_cnt--; + } + } + } + } - item_list_t::iterator position_iter = mItems.begin(); - std::advance(position_iter, position); - mItems.insert(position_iter, item); - LLUICtrl::addChild(item); + if (mPreferredWidth < U32_MAX) + width = llmin(mPreferredWidth, max_width); - if (arrange) - { - needsArrange(); - } + if (mScrollable) + { + S32 max_items_height = max_height - spillover_item_height * 2; + + if (visible_items_height == 0) + visible_items_height = height - height_before_first_visible_item; + + // Fix mFirstVisibleItem value, if it doesn't allow to display all items, that can fit + if (visible_items_height < max_items_height && scrollable_items_cnt < mMaxScrollableItems) + { + item_list_t::iterator tmp_iter(first_visible_item_iter); + while (visible_items_height < max_items_height && + scrollable_items_cnt < mMaxScrollableItems && + first_visible_item_iter != mItems.begin()) + { + if ((*first_visible_item_iter)->getVisible()) + { + // It keeps visible item, after first_visible_item_iter + tmp_iter = first_visible_item_iter; + } + + first_visible_item_iter--; + + if ((*first_visible_item_iter)->getVisible()) + { + visible_items_height += (*first_visible_item_iter)->getNominalHeight(); + height_before_first_visible_item -= (*first_visible_item_iter)->getNominalHeight(); + scrollable_items_cnt++; + } + } + + // Roll back one item, that doesn't fit + if (visible_items_height > max_items_height) + { + visible_items_height -= (*first_visible_item_iter)->getNominalHeight(); + height_before_first_visible_item += (*first_visible_item_iter)->getNominalHeight(); + scrollable_items_cnt--; + first_visible_item_iter = tmp_iter; + } + if (!(*first_visible_item_iter)->getVisible()) + { + first_visible_item_iter = tmp_iter; + } + + mFirstVisibleItem = *first_visible_item_iter; + } + } + } + + S32 cur_height = (S32)llmin(max_height, height); + + if (mScrollable && + (height_before_first_visible_item > MENU_ITEM_PADDING || + height_before_first_visible_item + visible_items_height < (S32)height)) + { + // Reserving 2 extra slots for arrow items + cur_height = visible_items_height + spillover_item_height * 2; + } + + setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width, getRect().mTop - cur_height)); + + S32 cur_width = 0; + S32 offset = 0; + if (mScrollable) + { + // No space for all items, creating arrow items + if (height_before_first_visible_item > MENU_ITEM_PADDING || + height_before_first_visible_item + visible_items_height < (S32)height) + { + if (NULL == mArrowUpItem) + { + LLMenuScrollItem::Params item_params; + item_params.name(ARROW_UP); + item_params.arrow_type(LLMenuScrollItem::ARROW_UP); + item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP)); + + mArrowUpItem = LLUICtrlFactory::create(item_params); + LLUICtrl::addChild(mArrowUpItem); + + } + if (NULL == mArrowDownItem) + { + LLMenuScrollItem::Params item_params; + item_params.name(ARROW_DOWN); + item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN); + item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN)); + + mArrowDownItem = LLUICtrlFactory::create(item_params); + LLUICtrl::addChild(mArrowDownItem); + } + + LLRect rect; + mArrowUpItem->setRect(rect.setLeftTopAndSize( 0, cur_height, width, mArrowUpItem->getNominalHeight())); + mArrowUpItem->setVisible(TRUE); + mArrowUpItem->setEnabled(height_before_first_visible_item > MENU_ITEM_PADDING); + mArrowUpItem->reshape(width, mArrowUpItem->getNominalHeight()); + mArrowDownItem->setRect(rect.setLeftTopAndSize( 0, mArrowDownItem->getNominalHeight(), width, mArrowDownItem->getNominalHeight())); + mArrowDownItem->setVisible(TRUE); + mArrowDownItem->setEnabled(height_before_first_visible_item + visible_items_height < (S32)height); + mArrowDownItem->reshape(width, mArrowDownItem->getNominalHeight()); + + cur_height -= mArrowUpItem->getNominalHeight(); + + offset = menu_region_rect.mRight; // This moves items behind visible area + } + else + { + if (NULL != mArrowUpItem) + { + mArrowUpItem->setVisible(FALSE); + } + if (NULL != mArrowDownItem) + { + mArrowDownItem->setVisible(FALSE); + } + } + + } + + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if ((*item_iter)->getVisible()) + { + if (mScrollable) + { + if (item_iter == first_visible_item_iter) + { + offset = 0; + } + else if (item_iter == first_hidden_item_iter) + { + offset = menu_region_rect.mRight; // This moves items behind visible area + } + } + + // setup item rect to hold label + LLRect rect; + if (mHorizontalLayout) + { + rect.setLeftTopAndSize( cur_width, height, (*item_iter)->getNominalWidth(), height); + cur_width += (*item_iter)->getNominalWidth(); + } + else + { + rect.setLeftTopAndSize( 0 + offset, cur_height, width, (*item_iter)->getNominalHeight()); + if (offset == 0) + { + cur_height -= (*item_iter)->getNominalHeight(); + } + } + (*item_iter)->setRect( rect ); + } + } + + + if (getTornOff()) + { + LLTearOffMenu * torn_off_menu = dynamic_cast(getParent()); + if (torn_off_menu) + { + torn_off_menu->updateSize(); + } + } + } + if (mKeepFixedSize) + { + reshape(initial_rect.getWidth(), initial_rect.getHeight()); + } +} + +void LLMenuGL::arrangeAndClear( void ) +{ + if (mNeedsArrange) + { + arrange(); + mNeedsArrange = FALSE; + } +} + +void LLMenuGL::createSpilloverBranch() +{ + if (!mSpilloverBranch) + { + // should be NULL but delete anyway + delete mSpilloverMenu; + // technically, you can't tear off spillover menus, but we're passing the handle + // along just to be safe + LLMenuGL::Params p; + std::string label = LLTrans::getString("More"); + p.name("More"); + p.label(label); + p.bg_color(mBackgroundColor); + p.bg_visible(true); + p.can_tear_off(false); + mSpilloverMenu = new LLMenuGL(p); + mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); + + LLMenuItemBranchGL::Params branch_params; + branch_params.name = "More"; + branch_params.label = label; + branch_params.branch = mSpilloverMenu; + branch_params.font.style = "italic"; + branch_params.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); + branch_params.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + branch_params.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); + + mSpilloverBranch = LLUICtrlFactory::create(branch_params); + } +} + +void LLMenuGL::cleanupSpilloverBranch() +{ + if (mSpilloverBranch && mSpilloverBranch->getParent() == this) + { + // head-recursion to propagate items back up to root menu + mSpilloverMenu->cleanupSpilloverBranch(); + + // pop off spillover items + while (mSpilloverMenu->getItemCount()) + { + LLMenuItemGL* itemp = mSpilloverMenu->getItem(0); + mSpilloverMenu->removeChild(itemp); + // put them at the end of our own list + addChild(itemp); + } + + // Delete the branch, and since the branch will delete the menu, + // set the menu* to null. + delete mSpilloverBranch; + mSpilloverBranch = NULL; + mSpilloverMenu = NULL; + } +} + +void LLMenuGL::createJumpKeys() +{ + if (!mCreateJumpKeys) return; + mCreateJumpKeys = FALSE; + + mJumpKeys.clear(); + + std::set unique_words; + std::set shared_words; + + item_list_t::iterator item_it; + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + + for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) + { + std::string uppercase_label = (*item_it)->getLabel(); + LLStringUtil::toUpper(uppercase_label); + + tokenizer tokens(uppercase_label, sep); + tokenizer::iterator token_iter; + for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + if (unique_words.find(*token_iter) != unique_words.end()) + { + // this word exists in more than one menu instance + shared_words.insert(*token_iter); + } + else + { + // we have a new word, keep track of it + unique_words.insert(*token_iter); + } + } + } + + // pre-assign specified jump keys + for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) + { + KEY jump_key = (*item_it)->getJumpKey(); + if(jump_key != KEY_NONE) + { + if (mJumpKeys.find(jump_key) == mJumpKeys.end()) + { + mJumpKeys.insert(std::pair(jump_key, (*item_it))); + } + else + { + // this key is already spoken for, + // so we need to reassign it below + (*item_it)->setJumpKey(KEY_NONE); + } + } + } + + for(item_it = mItems.begin(); item_it != mItems.end(); ++item_it) + { + // skip over items that already have assigned jump keys + if ((*item_it)->getJumpKey() != KEY_NONE) + { + continue; + } + std::string uppercase_label = (*item_it)->getLabel(); + LLStringUtil::toUpper(uppercase_label); + + tokenizer tokens(uppercase_label, sep); + tokenizer::iterator token_iter; + + BOOL found_key = FALSE; + for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + std::string uppercase_word = *token_iter; + + // this word is not shared with other menu entries... + if (shared_words.find(*token_iter) == shared_words.end()) + { + S32 i; + for(i = 0; i < (S32)uppercase_word.size(); i++) + { + char jump_key = uppercase_word[i]; + + if (LLStringOps::isDigit(jump_key) || (LLStringOps::isUpper(jump_key) && + mJumpKeys.find(jump_key) == mJumpKeys.end())) + { + mJumpKeys.insert(std::pair(jump_key, (*item_it))); + (*item_it)->setJumpKey(jump_key); + found_key = TRUE; + break; + } + } + } + if (found_key) + { + break; + } + } + } +} + +// remove all items on the menu +void LLMenuGL::empty( void ) +{ + cleanupSpilloverBranch(); + + mItems.clear(); + mFirstVisibleItem = NULL; + mArrowUpItem = NULL; + mArrowDownItem = NULL; + + deleteAllChildren(); +} + +// erase group of items from menu +void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) +{ + S32 items = mItems.size(); + + if ( items == 0 || begin >= end || begin < 0 || end > items ) + { + return; + } + + item_list_t::iterator start_position = mItems.begin(); + std::advance(start_position, begin); + + item_list_t::iterator end_position = mItems.begin(); + std::advance(end_position, end); + + for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++) + { + LLUICtrl::removeChild(*position_iter); + } + + mItems.erase(start_position, end_position); + + if (arrange) + { + needsArrange(); + } +} + +// add new item at position +void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) +{ + LLMenuItemGL * item = dynamic_cast(ctrl); + + if (NULL == item || position < 0 || position >= mItems.size()) + { + return; + } + + item_list_t::iterator position_iter = mItems.begin(); + std::advance(position_iter, position); + mItems.insert(position_iter, item); + LLUICtrl::addChild(item); + + if (arrange) + { + needsArrange(); + } } // Adjust rectangle of the menu void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom) { - setRect(LLRect(left, getRect().mTop, getRect().mRight, bottom)); - needsArrange(); + setRect(LLRect(left, getRect().mTop, getRect().mRight, bottom)); + needsArrange(); } BOOL LLMenuGL::handleJumpKey(KEY key) { - // must perform case-insensitive comparison, so just switch to uppercase input key - key = toupper(key); - navigation_key_map_t::iterator found_it = mJumpKeys.find(key); - if(found_it != mJumpKeys.end() && found_it->second->getEnabled()) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); + // must perform case-insensitive comparison, so just switch to uppercase input key + key = toupper(key); + navigation_key_map_t::iterator found_it = mJumpKeys.find(key); + if(found_it != mJumpKeys.end() && found_it->second->getEnabled()) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); - // force highlight to close old menus and open and sub-menus - found_it->second->setHighlight(TRUE); - found_it->second->onCommit(); + // force highlight to close old menus and open and sub-menus + found_it->second->setHighlight(TRUE); + found_it->second->onCommit(); - } - // if we are navigating the menus, we need to eat the keystroke - // so rest of UI doesn't handle it - return TRUE; + } + // if we are navigating the menus, we need to eat the keystroke + // so rest of UI doesn't handle it + return TRUE; } // Add the menu item to this menu. BOOL LLMenuGL::append( LLMenuItemGL* item ) { - if (!item) return FALSE; - mItems.push_back( item ); - LLUICtrl::addChild(item); - needsArrange(); - return TRUE; + if (!item) return FALSE; + mItems.push_back( item ); + LLUICtrl::addChild(item); + needsArrange(); + return TRUE; } // add a separator to this menu BOOL LLMenuGL::addSeparator() { - LLMenuItemSeparatorGL::Params p; - LLMenuItemGL* separator = LLUICtrlFactory::create(p); - return addChild(separator); + LLMenuItemSeparatorGL::Params p; + LLMenuItemGL* separator = LLUICtrlFactory::create(p); + return addChild(separator); } // add a menu - this will create a cascading menu BOOL LLMenuGL::appendMenu( LLMenuGL* menu ) { - if( menu == this ) - { - LL_ERRS() << "** Attempt to attach menu to itself. This is certainly " - << "a logic error." << LL_ENDL; - } - BOOL success = TRUE; + if( menu == this ) + { + LL_ERRS() << "** Attempt to attach menu to itself. This is certainly " + << "a logic error." << LL_ENDL; + } + BOOL success = TRUE; - LLMenuItemBranchGL::Params p; - p.name = menu->getName(); - p.label = menu->getLabel(); - p.branch = menu; - p.jump_key = menu->getJumpKey(); - p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); - p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); - p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); - p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + LLMenuItemBranchGL::Params p; + p.name = menu->getName(); + p.label = menu->getLabel(); + p.branch = menu; + p.jump_key = menu->getJumpKey(); + p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); + p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); + p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); + p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); - LLMenuItemBranchGL* branch = LLUICtrlFactory::create(p); - success &= append( branch ); + LLMenuItemBranchGL* branch = LLUICtrlFactory::create(p); + success &= append( branch ); - // Inherit colors - menu->setBackgroundColor( mBackgroundColor ); - menu->updateParent(LLMenuGL::sMenuContainer); - return success; + // Inherit colors + menu->setBackgroundColor( mBackgroundColor ); + menu->updateParent(LLMenuGL::sMenuContainer); + return success; } // add a context menu branch BOOL LLMenuGL::appendContextSubMenu(LLMenuGL *menu) { - if (menu == this) - { - LL_ERRS() << "Can't attach a context menu to itself" << LL_ENDL; - } + if (menu == this) + { + LL_ERRS() << "Can't attach a context menu to itself" << LL_ENDL; + } - LLContextMenuBranch *item; - LLContextMenuBranch::Params p; - p.name = menu->getName(); - p.label = menu->getLabel(); - p.branch = (LLContextMenu *)menu; - p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); - p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); - p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); - p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + LLContextMenuBranch *item; + LLContextMenuBranch::Params p; + p.name = menu->getName(); + p.label = menu->getLabel(); + p.branch = (LLContextMenu *)menu; + p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); + p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); + p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); + p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); - item = LLUICtrlFactory::create(p); - LLMenuGL::sMenuContainer->addChild(item->getBranch()); + item = LLUICtrlFactory::create(p); + LLMenuGL::sMenuContainer->addChild(item->getBranch()); - return append( item ); + return append( item ); } void LLMenuGL::setEnabledSubMenus(BOOL enable) { - setEnabled(enable); - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - (*item_iter)->setEnabledSubMenus( enable ); - } + setEnabled(enable); + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + (*item_iter)->setEnabledSubMenus( enable ); + } } // setItemEnabled() - pass the label and the enable flag for a menu // item. TRUE will make sure it's enabled, FALSE will disable it. void LLMenuGL::setItemEnabled( const std::string& name, BOOL enable ) { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if( (*item_iter)->getName() == name ) - { - (*item_iter)->setEnabled( enable ); - (*item_iter)->setEnabledSubMenus( enable ); - break; - } - } + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if( (*item_iter)->getName() == name ) + { + (*item_iter)->setEnabled( enable ); + (*item_iter)->setEnabledSubMenus( enable ); + break; + } + } } void LLMenuGL::setItemVisible( const std::string& name, BOOL visible ) { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if( (*item_iter)->getName() == name ) - { - (*item_iter)->setVisible( visible ); - needsArrange(); - break; - } - } + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if( (*item_iter)->getName() == name ) + { + (*item_iter)->setVisible( visible ); + needsArrange(); + break; + } + } } @@ -2791,46 +2791,46 @@ void LLMenuGL::setItemLabel(const std::string &name, const std::string &label) void LLMenuGL::setItemLastSelected(LLMenuItemGL* item) { - if (getVisible()) - { - LLMenuHolderGL::setActivatedItem(item); - } + if (getVisible()) + { + LLMenuHolderGL::setActivatedItem(item); + } - // update enabled and checkmark status - item->buildDrawLabel(); + // update enabled and checkmark status + item->buildDrawLabel(); } -// Set whether drop shadowed +// Set whether drop shadowed void LLMenuGL::setDropShadowed( const BOOL shadowed ) { - mDropShadowed = shadowed; + mDropShadowed = shadowed; } void LLMenuGL::setTornOff(BOOL torn_off) -{ - mTornOff = torn_off; +{ + mTornOff = torn_off; } U32 LLMenuGL::getItemCount() { - return mItems.size(); + return mItems.size(); } LLMenuItemGL* LLMenuGL::getItem(S32 number) { - if (number >= 0 && number < (S32)mItems.size()) - { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if (number == 0) - { - return (*item_iter); - } - number--; - } - } - return NULL; + if (number >= 0 && number < (S32)mItems.size()) + { + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if (number == 0) + { + return (*item_iter); + } + number--; + } + } + return NULL; } LLMenuItemGL* LLMenuGL::getItem(std::string name) @@ -2848,561 +2848,561 @@ LLMenuItemGL* LLMenuGL::getItem(std::string name) LLMenuItemGL* LLMenuGL::getHighlightedItem() { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - if ((*item_iter)->getHighlight()) - { - return (*item_iter); - } - } - return NULL; + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + if ((*item_iter)->getHighlight()) + { + return (*item_iter); + } + } + return NULL; } LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled) { - if (mItems.empty()) return NULL; - // highlighting first item on a torn off menu is the - // same as giving focus to it - if (!cur_item && getTornOff()) - { - LLFloater * parent = dynamic_cast(getParent()); - if (parent) - { - parent->setFocus(TRUE); - } - } - - // Current item position in the items list - item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item); - - item_list_t::iterator next_item_iter; - if (cur_item_iter == mItems.end()) - { - next_item_iter = mItems.begin(); - } - else - { - next_item_iter = cur_item_iter; - next_item_iter++; - - // First visible item position in the items list - item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem); - - if (next_item_iter == mItems.end()) - { - next_item_iter = mItems.begin(); - - // If current item is the last in the list, the menu is scrolled to the beginning - // and the first item is highlighted. - if (mScrollable && !scrollItems(SD_BEGIN)) - { - return NULL; - } - } - // If current item is the last visible, the menu is scrolled one item down - // and the next item is highlighted. - else if (mScrollable && - (U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems) - { - // Call highlightNextItem() recursively only if the menu was successfully scrolled down. - // If scroll timer hasn't expired yet the menu won't be scrolled and calling - // highlightNextItem() will result in an endless recursion. - if (scrollItems(SD_DOWN)) - { - return highlightNextItem(cur_item, skip_disabled); - } - else - { - return NULL; - } - } - } - - // when first highlighting a menu, skip over tear off menu item - if (mTearOffItem && !cur_item) - { - // we know the first item is the tear off menu item - cur_item_iter = mItems.begin(); - next_item_iter++; - if (next_item_iter == mItems.end()) - { - next_item_iter = mItems.begin(); - } - } - - while(1) - { - // skip separators and disabled/invisible items - if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && !dynamic_cast(*next_item_iter)) - { - if (cur_item) - { - cur_item->setHighlight(FALSE); - } - (*next_item_iter)->setHighlight(TRUE); - return (*next_item_iter); - } - - - if (!skip_disabled || next_item_iter == cur_item_iter) - { - break; - } - - next_item_iter++; - if (next_item_iter == mItems.end()) - { - if (cur_item_iter == mItems.end()) - { - break; - } - next_item_iter = mItems.begin(); - } - } - - return NULL; + if (mItems.empty()) return NULL; + // highlighting first item on a torn off menu is the + // same as giving focus to it + if (!cur_item && getTornOff()) + { + LLFloater * parent = dynamic_cast(getParent()); + if (parent) + { + parent->setFocus(TRUE); + } + } + + // Current item position in the items list + item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item); + + item_list_t::iterator next_item_iter; + if (cur_item_iter == mItems.end()) + { + next_item_iter = mItems.begin(); + } + else + { + next_item_iter = cur_item_iter; + next_item_iter++; + + // First visible item position in the items list + item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem); + + if (next_item_iter == mItems.end()) + { + next_item_iter = mItems.begin(); + + // If current item is the last in the list, the menu is scrolled to the beginning + // and the first item is highlighted. + if (mScrollable && !scrollItems(SD_BEGIN)) + { + return NULL; + } + } + // If current item is the last visible, the menu is scrolled one item down + // and the next item is highlighted. + else if (mScrollable && + (U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems) + { + // Call highlightNextItem() recursively only if the menu was successfully scrolled down. + // If scroll timer hasn't expired yet the menu won't be scrolled and calling + // highlightNextItem() will result in an endless recursion. + if (scrollItems(SD_DOWN)) + { + return highlightNextItem(cur_item, skip_disabled); + } + else + { + return NULL; + } + } + } + + // when first highlighting a menu, skip over tear off menu item + if (mTearOffItem && !cur_item) + { + // we know the first item is the tear off menu item + cur_item_iter = mItems.begin(); + next_item_iter++; + if (next_item_iter == mItems.end()) + { + next_item_iter = mItems.begin(); + } + } + + while(1) + { + // skip separators and disabled/invisible items + if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && !dynamic_cast(*next_item_iter)) + { + if (cur_item) + { + cur_item->setHighlight(FALSE); + } + (*next_item_iter)->setHighlight(TRUE); + return (*next_item_iter); + } + + + if (!skip_disabled || next_item_iter == cur_item_iter) + { + break; + } + + next_item_iter++; + if (next_item_iter == mItems.end()) + { + if (cur_item_iter == mItems.end()) + { + break; + } + next_item_iter = mItems.begin(); + } + } + + return NULL; } LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled) { - if (mItems.empty()) return NULL; - - // highlighting first item on a torn off menu is the - // same as giving focus to it - if (!cur_item && getTornOff()) - { - LLFloater * parent = dynamic_cast(getParent()); - if (parent) - { - parent->setFocus(TRUE); - } - } - - // Current item reverse position from the end of the list - item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item); - - item_list_t::reverse_iterator prev_item_iter; - if (cur_item_iter == mItems.rend()) - { - prev_item_iter = mItems.rbegin(); - } - else - { - prev_item_iter = cur_item_iter; - prev_item_iter++; - - // First visible item reverse position in the items list - item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem); - - if (prev_item_iter == mItems.rend()) - { - prev_item_iter = mItems.rbegin(); - - // If current item is the first in the list, the menu is scrolled to the end - // and the last item is highlighted. - if (mScrollable && !scrollItems(SD_END)) - { - return NULL; - } - } - // If current item is the first visible, the menu is scrolled one item up - // and the previous item is highlighted. - else if (mScrollable && - std::distance(first_visible_item_iter, cur_item_iter) <= 0) - { - // Call highlightNextItem() only if the menu was successfully scrolled up. - // If scroll timer hasn't expired yet the menu won't be scrolled and calling - // highlightNextItem() will result in an endless recursion. - if (scrollItems(SD_UP)) - { - return highlightPrevItem(cur_item, skip_disabled); - } - else - { - return NULL; - } - } - } - - while(1) - { - // skip separators and disabled/invisible items - if ((*prev_item_iter)->getEnabled() && (*prev_item_iter)->getVisible() && (*prev_item_iter)->getName() != SEPARATOR_NAME) - { - (*prev_item_iter)->setHighlight(TRUE); - return (*prev_item_iter); - } - - if (!skip_disabled || prev_item_iter == cur_item_iter) - { - break; - } - - prev_item_iter++; - if (prev_item_iter == mItems.rend()) - { - if (cur_item_iter == mItems.rend()) - { - break; - } - - prev_item_iter = mItems.rbegin(); - } - } - - return NULL; + if (mItems.empty()) return NULL; + + // highlighting first item on a torn off menu is the + // same as giving focus to it + if (!cur_item && getTornOff()) + { + LLFloater * parent = dynamic_cast(getParent()); + if (parent) + { + parent->setFocus(TRUE); + } + } + + // Current item reverse position from the end of the list + item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item); + + item_list_t::reverse_iterator prev_item_iter; + if (cur_item_iter == mItems.rend()) + { + prev_item_iter = mItems.rbegin(); + } + else + { + prev_item_iter = cur_item_iter; + prev_item_iter++; + + // First visible item reverse position in the items list + item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem); + + if (prev_item_iter == mItems.rend()) + { + prev_item_iter = mItems.rbegin(); + + // If current item is the first in the list, the menu is scrolled to the end + // and the last item is highlighted. + if (mScrollable && !scrollItems(SD_END)) + { + return NULL; + } + } + // If current item is the first visible, the menu is scrolled one item up + // and the previous item is highlighted. + else if (mScrollable && + std::distance(first_visible_item_iter, cur_item_iter) <= 0) + { + // Call highlightNextItem() only if the menu was successfully scrolled up. + // If scroll timer hasn't expired yet the menu won't be scrolled and calling + // highlightNextItem() will result in an endless recursion. + if (scrollItems(SD_UP)) + { + return highlightPrevItem(cur_item, skip_disabled); + } + else + { + return NULL; + } + } + } + + while(1) + { + // skip separators and disabled/invisible items + if ((*prev_item_iter)->getEnabled() && (*prev_item_iter)->getVisible() && (*prev_item_iter)->getName() != SEPARATOR_NAME) + { + (*prev_item_iter)->setHighlight(TRUE); + return (*prev_item_iter); + } + + if (!skip_disabled || prev_item_iter == cur_item_iter) + { + break; + } + + prev_item_iter++; + if (prev_item_iter == mItems.rend()) + { + if (cur_item_iter == mItems.rend()) + { + break; + } + + prev_item_iter = mItems.rbegin(); + } + } + + return NULL; } void LLMenuGL::buildDrawLabels() { - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - (*item_iter)->buildDrawLabel(); - } + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + (*item_iter)->buildDrawLabel(); + } } void LLMenuGL::updateParent(LLView* parentp) { - if (getParent()) - { - getParent()->removeChild(this); - } - if (parentp) - { - parentp->addChild(this); - } - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - (*item_iter)->updateBranchParent(parentp); - } + if (getParent()) + { + getParent()->removeChild(this); + } + if (parentp) + { + parentp->addChild(this); + } + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + (*item_iter)->updateBranchParent(parentp); + } } bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const { - if (key == KEY_NONE) - { - return false; - } - // Note: checking this way because mAccelerators seems to be broken - // mAccelerators probably needs to be cleaned up or fixed - // It was used for dupplicate accelerator avoidance. - item_list_t::const_iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - LLMenuItemGL* itemp = *item_iter; - if (itemp->hasAccelerator(key, mask)) - { - return true; - } - } - return false; + if (key == KEY_NONE) + { + return false; + } + // Note: checking this way because mAccelerators seems to be broken + // mAccelerators probably needs to be cleaned up or fixed + // It was used for dupplicate accelerator avoidance. + item_list_t::const_iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + LLMenuItemGL* itemp = *item_iter; + if (itemp->hasAccelerator(key, mask)) + { + return true; + } + } + return false; } BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask) { - // don't handle if not enabled - if(!getEnabled()) - { - return FALSE; - } + // don't handle if not enabled + if(!getEnabled()) + { + return FALSE; + } - // Pass down even if not visible - item_list_t::iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - LLMenuItemGL* itemp = *item_iter; - if (itemp->handleAcceleratorKey(key, mask)) - { - return TRUE; - } - } + // Pass down even if not visible + item_list_t::iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + LLMenuItemGL* itemp = *item_iter; + if (itemp->handleAcceleratorKey(key, mask)) + { + return TRUE; + } + } - return FALSE; + return FALSE; } BOOL LLMenuGL::handleUnicodeCharHere( llwchar uni_char ) { - if (jumpKeysActive()) - { - return handleJumpKey((KEY)uni_char); - } - return FALSE; + if (jumpKeysActive()) + { + return handleJumpKey((KEY)uni_char); + } + return FALSE; } BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask ) { - // leave submenu in place if slope of mouse < MAX_MOUSE_SLOPE_SUB_MENU - BOOL no_mouse_data = mLastMouseX == 0 && mLastMouseY == 0; - S32 mouse_delta_x = no_mouse_data ? 0 : x - mLastMouseX; - S32 mouse_delta_y = no_mouse_data ? 0 : y - mLastMouseY; - LLVector2 mouse_dir((F32)mouse_delta_x, (F32)mouse_delta_y); - mouse_dir.normVec(); - LLVector2 mouse_avg_dir((F32)mMouseVelX, (F32)mMouseVelY); - mouse_avg_dir.normVec(); - F32 interp = 0.5f * (llclamp(mouse_dir * mouse_avg_dir, 0.f, 1.f)); - mMouseVelX = ll_round(lerp((F32)mouse_delta_x, (F32)mMouseVelX, interp)); - mMouseVelY = ll_round(lerp((F32)mouse_delta_y, (F32)mMouseVelY, interp)); - mLastMouseX = x; - mLastMouseY = y; - - // don't change menu focus unless mouse is moving or alt key is not held down - if ((llabs(mMouseVelX) > 0 || - llabs(mMouseVelY) > 0) && - (!mHasSelection || - //(mouse_delta_x == 0 && mouse_delta_y == 0) || - (mMouseVelX < 0) || - llabs((F32)mMouseVelY) / llabs((F32)mMouseVelX) > MAX_MOUSE_SLOPE_SUB_MENU)) - { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (!viewp->pointInView(local_x, local_y) && ((LLMenuItemGL*)viewp)->getHighlight()) - { - // moving mouse always highlights new item - if (mouse_delta_x != 0 || mouse_delta_y != 0) - { - ((LLMenuItemGL*)viewp)->setHighlight(FALSE); - } - } - } - - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - //RN: always call handleHover to track mGotHover status - // but only set highlight when mouse is moving - if( viewp->getVisible() && - //RN: allow disabled items to be highlighted to preserve "active" menus when - // moving mouse through them - //viewp->getEnabled() && - viewp->pointInView(local_x, local_y) && - viewp->handleHover(local_x, local_y, mask)) - { - // moving mouse always highlights new item - if (mouse_delta_x != 0 || mouse_delta_y != 0) - { - ((LLMenuItemGL*)viewp)->setHighlight(TRUE); - LLMenuGL::setKeyboardMode(FALSE); - } - mHasSelection = true; - } - } - } - getWindow()->setCursor(UI_CURSOR_ARROW); - - // *HACK Release the mouse capture - // This is done to release the mouse after the Navigation Bar "Back" or "Forward" button - // drop-down menu is shown. Otherwise any other view won't be able to handle mouse events - // until the user chooses one of the drop-down menu items. - - return TRUE; + // leave submenu in place if slope of mouse < MAX_MOUSE_SLOPE_SUB_MENU + BOOL no_mouse_data = mLastMouseX == 0 && mLastMouseY == 0; + S32 mouse_delta_x = no_mouse_data ? 0 : x - mLastMouseX; + S32 mouse_delta_y = no_mouse_data ? 0 : y - mLastMouseY; + LLVector2 mouse_dir((F32)mouse_delta_x, (F32)mouse_delta_y); + mouse_dir.normVec(); + LLVector2 mouse_avg_dir((F32)mMouseVelX, (F32)mMouseVelY); + mouse_avg_dir.normVec(); + F32 interp = 0.5f * (llclamp(mouse_dir * mouse_avg_dir, 0.f, 1.f)); + mMouseVelX = ll_round(lerp((F32)mouse_delta_x, (F32)mMouseVelX, interp)); + mMouseVelY = ll_round(lerp((F32)mouse_delta_y, (F32)mMouseVelY, interp)); + mLastMouseX = x; + mLastMouseY = y; + + // don't change menu focus unless mouse is moving or alt key is not held down + if ((llabs(mMouseVelX) > 0 || + llabs(mMouseVelY) > 0) && + (!mHasSelection || + //(mouse_delta_x == 0 && mouse_delta_y == 0) || + (mMouseVelX < 0) || + llabs((F32)mMouseVelY) / llabs((F32)mMouseVelX) > MAX_MOUSE_SLOPE_SUB_MENU)) + { + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if (!viewp->pointInView(local_x, local_y) && ((LLMenuItemGL*)viewp)->getHighlight()) + { + // moving mouse always highlights new item + if (mouse_delta_x != 0 || mouse_delta_y != 0) + { + ((LLMenuItemGL*)viewp)->setHighlight(FALSE); + } + } + } + + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + //RN: always call handleHover to track mGotHover status + // but only set highlight when mouse is moving + if( viewp->getVisible() && + //RN: allow disabled items to be highlighted to preserve "active" menus when + // moving mouse through them + //viewp->getEnabled() && + viewp->pointInView(local_x, local_y) && + viewp->handleHover(local_x, local_y, mask)) + { + // moving mouse always highlights new item + if (mouse_delta_x != 0 || mouse_delta_y != 0) + { + ((LLMenuItemGL*)viewp)->setHighlight(TRUE); + LLMenuGL::setKeyboardMode(FALSE); + } + mHasSelection = true; + } + } + } + getWindow()->setCursor(UI_CURSOR_ARROW); + + // *HACK Release the mouse capture + // This is done to release the mouse after the Navigation Bar "Back" or "Forward" button + // drop-down menu is shown. Otherwise any other view won't be able to handle mouse events + // until the user chooses one of the drop-down menu items. + + return TRUE; } BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks ) { - if (!mScrollable) - return blockMouseEvent(x, y); + if (!mScrollable) + return blockMouseEvent(x, y); + + if( clicks > 0 ) + { + while( clicks-- ) + scrollItems(SD_DOWN); + } + else + { + while( clicks++ ) + scrollItems(SD_UP); + } + + return TRUE; +} + + +void LLMenuGL::draw( void ) +{ + if (mNeedsArrange) + { + arrange(); + mNeedsArrange = FALSE; + } + if (mDropShadowed && !mTornOff) + { + static LLUICachedControl drop_shadow_floater ("DropShadowFloater", 0); + static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); + gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, + color_drop_shadow, drop_shadow_floater ); + } + + if( mBgVisible ) + { + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor.get() ); + } + LLView::draw(); +} + +void LLMenuGL::drawBackground(LLMenuItemGL* itemp, F32 alpha) +{ + LLColor4 color = itemp->getHighlightBgColor() % alpha; + gGL.color4fv( color.mV ); + LLRect item_rect = itemp->getRect(); + gl_rect_2d( 0, item_rect.getHeight(), item_rect.getWidth(), 0); +} - if( clicks > 0 ) - { - while( clicks-- ) - scrollItems(SD_DOWN); - } - else - { - while( clicks++ ) - scrollItems(SD_UP); - } +void LLMenuGL::setVisible(BOOL visible) +{ + if (visible != getVisible()) + { + if (!visible) + { + mFadeTimer.start(); + clearHoverItem(); + // reset last known mouse coordinates so + // we don't spoof a mouse move next time we're opened + mLastMouseX = 0; + mLastMouseY = 0; + } + else + { + mHasSelection = true; + mFadeTimer.stop(); + } - return TRUE; + LLView::setVisible(visible); + } } +LLMenuGL* LLMenuGL::findChildMenuByName(const std::string& name, BOOL recurse) const +{ + LLView* view = findChildView(name, recurse); + if (view) + { + LLMenuItemBranchGL* branch = dynamic_cast(view); + if (branch) + { + return branch->getBranch(); + } + + LLMenuGL* menup = dynamic_cast(view); + if (menup) + { + return menup; + } + } + LL_WARNS() << "Child Menu " << name << " not found in menu " << getName() << LL_ENDL; + return NULL; +} + +BOOL LLMenuGL::clearHoverItem() +{ + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLMenuItemGL* itemp = (LLMenuItemGL*)*child_it; + if (itemp->getHighlight()) + { + itemp->setHighlight(FALSE); + return TRUE; + } + } + return FALSE; +} + +void hide_top_view( LLView* view ) +{ + if( view ) view->setVisible( FALSE ); +} + + +// x and y are the desired location for the popup, in the spawning_view's +// coordinate frame, NOT necessarily the mouse location +// static +void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x, S32 mouse_y) +{ + const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size + const S32 CURSOR_WIDTH = 12; + + if (menu->getChildList()->empty()) + { + return; + } + + menu->setVisible( TRUE ); + + if(!menu->getAlwaysShowMenu()) + { + //Do not show menu if all menu items are disabled + BOOL item_enabled = false; + for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin(); + itor != menu->getChildList()->end(); + ++itor) + { + LLView *menu_item = (*itor); + item_enabled = item_enabled || menu_item->getEnabled(); + } + + if(!item_enabled) + { + menu->setVisible( FALSE ); + return; + } + } + + // Resetting scrolling position + if (menu->isScrollable() && menu->isScrollPositionOnShowReset()) + { + menu->mFirstVisibleItem = NULL; + } + + // Fix menu rect if needed. + menu->needsArrange(); + menu->arrangeAndClear(); + + if ((mouse_x == 0) || (mouse_y == 0)) -void LLMenuGL::draw( void ) -{ - if (mNeedsArrange) - { - arrange(); - mNeedsArrange = FALSE; - } - if (mDropShadowed && !mTornOff) - { - static LLUICachedControl drop_shadow_floater ("DropShadowFloater", 0); - static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); - gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, drop_shadow_floater ); - } - - if( mBgVisible ) - { - gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor.get() ); - } - LLView::draw(); -} + { + // Save click point for detecting cursor moves before mouse-up. + // Must be in local coords to compare with mouseUp events. + // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLContextMenu::show() -void LLMenuGL::drawBackground(LLMenuItemGL* itemp, F32 alpha) -{ - LLColor4 color = itemp->getHighlightBgColor() % alpha; - gGL.color4fv( color.mV ); - LLRect item_rect = itemp->getRect(); - gl_rect_2d( 0, item_rect.getHeight(), item_rect.getWidth(), 0); -} + LLUI::getInstance()->getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y); + } -void LLMenuGL::setVisible(BOOL visible) -{ - if (visible != getVisible()) - { - if (!visible) - { - mFadeTimer.start(); - clearHoverItem(); - // reset last known mouse coordinates so - // we don't spoof a mouse move next time we're opened - mLastMouseX = 0; - mLastMouseY = 0; - } - else - { - mHasSelection = true; - mFadeTimer.stop(); - } - - LLView::setVisible(visible); - } -} -LLMenuGL* LLMenuGL::findChildMenuByName(const std::string& name, BOOL recurse) const -{ - LLView* view = findChildView(name, recurse); - if (view) - { - LLMenuItemBranchGL* branch = dynamic_cast(view); - if (branch) - { - return branch->getBranch(); - } - - LLMenuGL* menup = dynamic_cast(view); - if (menup) - { - return menup; - } - } - LL_WARNS() << "Child Menu " << name << " not found in menu " << getName() << LL_ENDL; - return NULL; -} + LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y); -BOOL LLMenuGL::clearHoverItem() -{ - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLMenuItemGL* itemp = (LLMenuItemGL*)*child_it; - if (itemp->getHighlight()) - { - itemp->setHighlight(FALSE); - return TRUE; - } - } - return FALSE; -} + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getRect(); -void hide_top_view( LLView* view ) -{ - if( view ) view->setVisible( FALSE ); -} + const S32 HPAD = 2; + LLRect rect = menu->getRect(); + S32 left = x + HPAD; + S32 top = y; + spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent()); + rect.setLeftTopAndSize( left, top, + rect.getWidth(), rect.getHeight() ); + menu->setRect( rect ); -// x and y are the desired location for the popup, in the spawning_view's -// coordinate frame, NOT necessarily the mouse location -// static -void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x, S32 mouse_y) -{ - const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size - const S32 CURSOR_WIDTH = 12; - - if (menu->getChildList()->empty()) - { - return; - } - - menu->setVisible( TRUE ); - - if(!menu->getAlwaysShowMenu()) - { - //Do not show menu if all menu items are disabled - BOOL item_enabled = false; - for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin(); - itor != menu->getChildList()->end(); - ++itor) - { - LLView *menu_item = (*itor); - item_enabled = item_enabled || menu_item->getEnabled(); - } - - if(!item_enabled) - { - menu->setVisible( FALSE ); - return; - } - } - - // Resetting scrolling position - if (menu->isScrollable() && menu->isScrollPositionOnShowReset()) - { - menu->mFirstVisibleItem = NULL; - } - - // Fix menu rect if needed. - menu->needsArrange(); - menu->arrangeAndClear(); - - if ((mouse_x == 0) || (mouse_y == 0)) - - { - // Save click point for detecting cursor moves before mouse-up. - // Must be in local coords to compare with mouseUp events. - // If the mouse doesn't move, the menu will stay open ala the Mac. - // See also LLContextMenu::show() - - LLUI::getInstance()->getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y); - } - - - LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y); - - const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getRect(); - - const S32 HPAD = 2; - LLRect rect = menu->getRect(); - S32 left = x + HPAD; - S32 top = y; - spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent()); - rect.setLeftTopAndSize( left, top, - rect.getWidth(), rect.getHeight() ); - menu->setRect( rect ); - - - // Adjust context menu to fit onscreen - LLRect mouse_rect; - const S32 MOUSE_CURSOR_PADDING = 5; - mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING, - mouse_y + MOUSE_CURSOR_PADDING, - CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, - CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); - menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect ); - if (menu->getRect().mTop > menu_region_rect.mTop) - { - // not enough space: align with top, ignore exclusion - menu->translateIntoRect( menu_region_rect ); - } - menu->getParent()->sendChildToFront(menu); + // Adjust context menu to fit onscreen + LLRect mouse_rect; + const S32 MOUSE_CURSOR_PADDING = 5; + mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING, + mouse_y + MOUSE_CURSOR_PADDING, + CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, + CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); + menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect ); + if (menu->getRect().mTop > menu_region_rect.mTop) + { + // not enough space: align with top, ignore exclusion + menu->translateIntoRect( menu_region_rect ); + } + menu->getParent()->sendChildToFront(menu); } ///============================================================================ @@ -3412,320 +3412,320 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S3 static LLDefaultChildRegistry::Register r2("menu_bar"); LLMenuBarGL::LLMenuBarGL( const Params& p ) -: LLMenuGL(p), - mAltKeyTrigger(FALSE) +: LLMenuGL(p), + mAltKeyTrigger(FALSE) {} // Default destructor LLMenuBarGL::~LLMenuBarGL() { - std::for_each(mAccelerators.begin(), mAccelerators.end(), DeletePointer()); - mAccelerators.clear(); + std::for_each(mAccelerators.begin(), mAccelerators.end(), DeletePointer()); + mAccelerators.clear(); } BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask) { - if (getHighlightedItem() && mask == MASK_NONE) - { - // unmodified key accelerators are ignored when navigating menu - // (but are used as jump keys so will still work when appropriate menu is up) - return FALSE; - } - BOOL result = LLMenuGL::handleAcceleratorKey(key, mask); - if (result && mask & MASK_ALT) - { - // ALT key used to trigger hotkey, don't use as shortcut to open menu - mAltKeyTrigger = FALSE; - } - - if(!result - && (key == KEY_F10 && mask == MASK_CONTROL) - && !gKeyboard->getKeyRepeated(key) - && isInVisibleChain()) - { - if (getHighlightedItem()) - { - clearHoverItem(); - LLMenuGL::setKeyboardMode(FALSE); - } - else - { - // close menus originating from other menu bars when first opening menu via keyboard - LLMenuGL::sMenuContainer->hideMenus(); - highlightNextItem(NULL); - LLMenuGL::setKeyboardMode(TRUE); - } - return TRUE; - } - - if (result && !getHighlightedItem() && LLMenuGL::sMenuContainer->hasVisibleMenu()) - { - // close menus originating from other menu bars - LLMenuGL::sMenuContainer->hideMenus(); - } - - return result; + if (getHighlightedItem() && mask == MASK_NONE) + { + // unmodified key accelerators are ignored when navigating menu + // (but are used as jump keys so will still work when appropriate menu is up) + return FALSE; + } + BOOL result = LLMenuGL::handleAcceleratorKey(key, mask); + if (result && mask & MASK_ALT) + { + // ALT key used to trigger hotkey, don't use as shortcut to open menu + mAltKeyTrigger = FALSE; + } + + if(!result + && (key == KEY_F10 && mask == MASK_CONTROL) + && !gKeyboard->getKeyRepeated(key) + && isInVisibleChain()) + { + if (getHighlightedItem()) + { + clearHoverItem(); + LLMenuGL::setKeyboardMode(FALSE); + } + else + { + // close menus originating from other menu bars when first opening menu via keyboard + LLMenuGL::sMenuContainer->hideMenus(); + highlightNextItem(NULL); + LLMenuGL::setKeyboardMode(TRUE); + } + return TRUE; + } + + if (result && !getHighlightedItem() && LLMenuGL::sMenuContainer->hasVisibleMenu()) + { + // close menus originating from other menu bars + LLMenuGL::sMenuContainer->hideMenus(); + } + + return result; } BOOL LLMenuBarGL::handleKeyHere(KEY key, MASK mask) { - static LLUICachedControl use_altkey_for_menus ("UseAltKeyForMenus", 0); - if(key == KEY_ALT && !gKeyboard->getKeyRepeated(key) && use_altkey_for_menus) - { - mAltKeyTrigger = TRUE; - } - else // if any key other than ALT hit, clear out waiting for Alt key mode - { - mAltKeyTrigger = FALSE; - } - - if (key == KEY_ESCAPE && mask == MASK_NONE) - { - LLMenuGL::setKeyboardMode(FALSE); - // if any menus are visible, this will return TRUE, stopping further processing of ESCAPE key - return LLMenuGL::sMenuContainer->hideMenus(); - } - - // before processing any other key, check to see if ALT key has triggered menu access - checkMenuTrigger(); - - return LLMenuGL::handleKeyHere(key, mask); + static LLUICachedControl use_altkey_for_menus ("UseAltKeyForMenus", 0); + if(key == KEY_ALT && !gKeyboard->getKeyRepeated(key) && use_altkey_for_menus) + { + mAltKeyTrigger = TRUE; + } + else // if any key other than ALT hit, clear out waiting for Alt key mode + { + mAltKeyTrigger = FALSE; + } + + if (key == KEY_ESCAPE && mask == MASK_NONE) + { + LLMenuGL::setKeyboardMode(FALSE); + // if any menus are visible, this will return TRUE, stopping further processing of ESCAPE key + return LLMenuGL::sMenuContainer->hideMenus(); + } + + // before processing any other key, check to see if ALT key has triggered menu access + checkMenuTrigger(); + + return LLMenuGL::handleKeyHere(key, mask); } BOOL LLMenuBarGL::handleJumpKey(KEY key) { - // perform case-insensitive comparison - key = toupper(key); - navigation_key_map_t::iterator found_it = mJumpKeys.find(key); - if(found_it != mJumpKeys.end() && found_it->second->getEnabled()) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); + // perform case-insensitive comparison + key = toupper(key); + navigation_key_map_t::iterator found_it = mJumpKeys.find(key); + if(found_it != mJumpKeys.end() && found_it->second->getEnabled()) + { + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); - found_it->second->setHighlight(TRUE); - found_it->second->onCommit(); - } - return TRUE; + found_it->second->setHighlight(TRUE); + found_it->second->onCommit(); + } + return TRUE; } BOOL LLMenuBarGL::handleMouseDown(S32 x, S32 y, MASK mask) { - // clicks on menu bar closes existing menus from other contexts but leave - // own menu open so that we get toggle behavior - if (!getHighlightedItem() || !getHighlightedItem()->isActive()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } + // clicks on menu bar closes existing menus from other contexts but leave + // own menu open so that we get toggle behavior + if (!getHighlightedItem() || !getHighlightedItem()->isActive()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } - return LLMenuGL::handleMouseDown(x, y, mask); + return LLMenuGL::handleMouseDown(x, y, mask); } BOOL LLMenuBarGL::handleDoubleClick(S32 x, S32 y, MASK mask) { - return LLMenuGL::handleMouseDown(x, y, mask); + return LLMenuGL::handleMouseDown(x, y, mask); } void LLMenuBarGL::draw() { - LLMenuItemGL* itemp = getHighlightedItem(); - // If we are in mouse-control mode and the mouse cursor is not hovering over - // the current highlighted menu item and it isn't open, then remove the - // highlight. This is done via a polling mechanism here, as we don't receive + LLMenuItemGL* itemp = getHighlightedItem(); + // If we are in mouse-control mode and the mouse cursor is not hovering over + // the current highlighted menu item and it isn't open, then remove the + // highlight. This is done via a polling mechanism here, as we don't receive // notifications when the mouse cursor moves off of us - if (itemp && !itemp->isOpen() && !itemp->getHover() && !LLMenuGL::getKeyboardMode()) - { - clearHoverItem(); - } + if (itemp && !itemp->isOpen() && !itemp->getHover() && !LLMenuGL::getKeyboardMode()) + { + clearHoverItem(); + } - checkMenuTrigger(); + checkMenuTrigger(); - LLMenuGL::draw(); + LLMenuGL::draw(); } void LLMenuBarGL::checkMenuTrigger() { - // has the ALT key been pressed and subsequently released? - if (mAltKeyTrigger && !gKeyboard->getKeyDown(KEY_ALT)) - { - // if alt key was released quickly, treat it as a menu access key - // otherwise it was probably an Alt-zoom or similar action - static LLUICachedControl menu_access_key_time ("MenuAccessKeyTime", 0); - if (gKeyboard->getKeyElapsedTime(KEY_ALT) <= menu_access_key_time || - gKeyboard->getKeyElapsedFrameCount(KEY_ALT) < 2) - { - if (getHighlightedItem()) - { - clearHoverItem(); - } - else - { - // close menus originating from other menu bars - LLMenuGL::sMenuContainer->hideMenus(); - - highlightNextItem(NULL); - LLMenuGL::setKeyboardMode(TRUE); - } - } - mAltKeyTrigger = FALSE; - } + // has the ALT key been pressed and subsequently released? + if (mAltKeyTrigger && !gKeyboard->getKeyDown(KEY_ALT)) + { + // if alt key was released quickly, treat it as a menu access key + // otherwise it was probably an Alt-zoom or similar action + static LLUICachedControl menu_access_key_time ("MenuAccessKeyTime", 0); + if (gKeyboard->getKeyElapsedTime(KEY_ALT) <= menu_access_key_time || + gKeyboard->getKeyElapsedFrameCount(KEY_ALT) < 2) + { + if (getHighlightedItem()) + { + clearHoverItem(); + } + else + { + // close menus originating from other menu bars + LLMenuGL::sMenuContainer->hideMenus(); + + highlightNextItem(NULL); + LLMenuGL::setKeyboardMode(TRUE); + } + } + mAltKeyTrigger = FALSE; + } } BOOL LLMenuBarGL::jumpKeysActive() { - // require user to be in keyboard navigation mode to activate key triggers - // as menu bars are always visible and it is easy to leave the mouse cursor over them - return LLMenuGL::getKeyboardMode() && getHighlightedItem() && LLMenuGL::jumpKeysActive(); + // require user to be in keyboard navigation mode to activate key triggers + // as menu bars are always visible and it is easy to leave the mouse cursor over them + return LLMenuGL::getKeyboardMode() && getHighlightedItem() && LLMenuGL::jumpKeysActive(); } // rearrange the child rects so they fit the shape of the menu bar. void LLMenuBarGL::arrange( void ) { - U32 pos = 0; - LLRect rect( 0, getRect().getHeight(), 0, 0 ); - item_list_t::const_iterator item_iter; - for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) - { - LLMenuItemGL* item = *item_iter; - if (item->getVisible()) - { - rect.mLeft = pos; - pos += item->getNominalWidth(); - rect.mRight = pos; - item->setRect( rect ); - item->buildDrawLabel(); - } - } - reshape(rect.mRight, rect.getHeight()); + U32 pos = 0; + LLRect rect( 0, getRect().getHeight(), 0, 0 ); + item_list_t::const_iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + LLMenuItemGL* item = *item_iter; + if (item->getVisible()) + { + rect.mLeft = pos; + pos += item->getNominalWidth(); + rect.mRight = pos; + item->setRect( rect ); + item->buildDrawLabel(); + } + } + reshape(rect.mRight, rect.getHeight()); } S32 LLMenuBarGL::getRightmostMenuEdge() { - // Find the last visible menu - item_list_t::reverse_iterator item_iter; - for (item_iter = mItems.rbegin(); item_iter != mItems.rend(); ++item_iter) - { - if ((*item_iter)->getVisible()) - { - break; - } - } + // Find the last visible menu + item_list_t::reverse_iterator item_iter; + for (item_iter = mItems.rbegin(); item_iter != mItems.rend(); ++item_iter) + { + if ((*item_iter)->getVisible()) + { + break; + } + } - if (item_iter == mItems.rend()) - { - return 0; - } - return (*item_iter)->getRect().mRight; + if (item_iter == mItems.rend()) + { + return 0; + } + return (*item_iter)->getRect().mRight; } // add a vertical separator to this menu BOOL LLMenuBarGL::addSeparator() { - LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL(); - return append( separator ); + LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL(); + return append( separator ); } // add a menu - this will create a drop down menu. BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu ) { - if( menu == this ) - { - LL_ERRS() << "** Attempt to attach menu to itself. This is certainly " - << "a logic error." << LL_ENDL; - } - - BOOL success = TRUE; - - // *TODO: Hack! Fix this - LLMenuItemBranchDownGL::Params p; - p.name = menu->getName(); - p.label = menu->getLabel(); - p.visible = menu->getVisible(); - p.branch = menu; - p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); - p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); - p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); - p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + if( menu == this ) + { + LL_ERRS() << "** Attempt to attach menu to itself. This is certainly " + << "a logic error." << LL_ENDL; + } + + BOOL success = TRUE; + + // *TODO: Hack! Fix this + LLMenuItemBranchDownGL::Params p; + p.name = menu->getName(); + p.label = menu->getLabel(); + p.visible = menu->getVisible(); + p.branch = menu; + p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); + p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); + p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); + p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); p.font = menu->getFont(); - LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create(p); - success &= branch->addToAcceleratorList(&mAccelerators); - success &= append( branch ); - branch->setJumpKey(branch->getJumpKey()); - menu->updateParent(LLMenuGL::sMenuContainer); - - return success; + LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create(p); + success &= branch->addToAcceleratorList(&mAccelerators); + success &= append( branch ); + branch->setJumpKey(branch->getJumpKey()); + menu->updateParent(LLMenuGL::sMenuContainer); + + return success; } BOOL LLMenuBarGL::handleHover( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; - LLView* active_menu = NULL; - - BOOL no_mouse_data = mLastMouseX == 0 && mLastMouseY == 0; - S32 mouse_delta_x = no_mouse_data ? 0 : x - mLastMouseX; - S32 mouse_delta_y = no_mouse_data ? 0 : y - mLastMouseY; - mMouseVelX = (mMouseVelX / 2) + (mouse_delta_x / 2); - mMouseVelY = (mMouseVelY / 2) + (mouse_delta_y / 2); - mLastMouseX = x; - mLastMouseY = y; - - // if nothing currently selected or mouse has moved since last call, pick menu item via mouse - // otherwise let keyboard control it - if (!getHighlightedItem() || !LLMenuGL::getKeyboardMode() || llabs(mMouseVelX) > 0 || llabs(mMouseVelY) > 0) - { - // find current active menu - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if (((LLMenuItemGL*)viewp)->isOpen()) - { - active_menu = viewp; - } - } - - // check for new active menu - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if( viewp->getVisible() && - viewp->getEnabled() && - viewp->pointInView(local_x, local_y) && - viewp->handleHover(local_x, local_y, mask)) - { - ((LLMenuItemGL*)viewp)->setHighlight(TRUE); - handled = TRUE; - if (active_menu && active_menu != viewp) - { - ((LLMenuItemGL*)viewp)->onCommit(); - LLMenuGL::setKeyboardMode(FALSE); - } - LLMenuGL::setKeyboardMode(FALSE); - } - } - - if (handled) - { - // set hover false on inactive menus - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (!viewp->pointInView(local_x, local_y) && ((LLMenuItemGL*)viewp)->getHighlight()) - { - ((LLMenuItemGL*)viewp)->setHighlight(FALSE); - } - } - } - } - - getWindow()->setCursor(UI_CURSOR_ARROW); - - return TRUE; + BOOL handled = FALSE; + LLView* active_menu = NULL; + + BOOL no_mouse_data = mLastMouseX == 0 && mLastMouseY == 0; + S32 mouse_delta_x = no_mouse_data ? 0 : x - mLastMouseX; + S32 mouse_delta_y = no_mouse_data ? 0 : y - mLastMouseY; + mMouseVelX = (mMouseVelX / 2) + (mouse_delta_x / 2); + mMouseVelY = (mMouseVelY / 2) + (mouse_delta_y / 2); + mLastMouseX = x; + mLastMouseY = y; + + // if nothing currently selected or mouse has moved since last call, pick menu item via mouse + // otherwise let keyboard control it + if (!getHighlightedItem() || !LLMenuGL::getKeyboardMode() || llabs(mMouseVelX) > 0 || llabs(mMouseVelY) > 0) + { + // find current active menu + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if (((LLMenuItemGL*)viewp)->isOpen()) + { + active_menu = viewp; + } + } + + // check for new active menu + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if( viewp->getVisible() && + viewp->getEnabled() && + viewp->pointInView(local_x, local_y) && + viewp->handleHover(local_x, local_y, mask)) + { + ((LLMenuItemGL*)viewp)->setHighlight(TRUE); + handled = TRUE; + if (active_menu && active_menu != viewp) + { + ((LLMenuItemGL*)viewp)->onCommit(); + LLMenuGL::setKeyboardMode(FALSE); + } + LLMenuGL::setKeyboardMode(FALSE); + } + } + + if (handled) + { + // set hover false on inactive menus + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if (!viewp->pointInView(local_x, local_y) && ((LLMenuItemGL*)viewp)->getHighlight()) + { + ((LLMenuItemGL*)viewp)->setHighlight(FALSE); + } + } + } + } + + getWindow()->setCursor(UI_CURSOR_ARROW); + + return TRUE; } ///============================================================================ @@ -3734,237 +3734,237 @@ BOOL LLMenuBarGL::handleHover( S32 x, S32 y, MASK mask ) LLCoordGL LLMenuHolderGL::sContextMenuSpawnPos(S32_MAX, S32_MAX); LLMenuHolderGL::LLMenuHolderGL(const LLMenuHolderGL::Params& p) - : LLPanel(p) + : LLPanel(p) { - sItemActivationTimer.stop(); - mCanHide = TRUE; + sItemActivationTimer.stop(); + mCanHide = TRUE; } void LLMenuHolderGL::draw() { - LLView::draw(); - // now draw last selected item as overlay - LLMenuItemGL* selecteditem = (LLMenuItemGL*)sItemLastSelectedHandle.get(); - if (selecteditem && selecteditem->getVisible() && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) - { - // make sure toggle items, for example, show the proper state when fading out - selecteditem->buildDrawLabel(); - - LLRect item_rect; - selecteditem->localRectToOtherView(selecteditem->getLocalRect(), &item_rect, this); - - F32 interpolant = sItemActivationTimer.getElapsedTimeF32() / ACTIVATE_HIGHLIGHT_TIME; - - LLUI::pushMatrix(); - { - LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom); - selecteditem->getMenu()->drawBackground(selecteditem, interpolant); - selecteditem->draw(); - } - LLUI::popMatrix(); - } + LLView::draw(); + // now draw last selected item as overlay + LLMenuItemGL* selecteditem = (LLMenuItemGL*)sItemLastSelectedHandle.get(); + if (selecteditem && selecteditem->getVisible() && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) + { + // make sure toggle items, for example, show the proper state when fading out + selecteditem->buildDrawLabel(); + + LLRect item_rect; + selecteditem->localRectToOtherView(selecteditem->getLocalRect(), &item_rect, this); + + F32 interpolant = sItemActivationTimer.getElapsedTimeF32() / ACTIVATE_HIGHLIGHT_TIME; + + LLUI::pushMatrix(); + { + LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom); + selecteditem->getMenu()->drawBackground(selecteditem, interpolant); + selecteditem->draw(); + } + LLUI::popMatrix(); + } } BOOL LLMenuHolderGL::handleMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; - if (!handled) - { - LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu(); - LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL; - if (parent_menu && parent_menu->getVisible()) - { - // don't hide menu if parent was hit - LLRect parent_rect; - parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this); - if (!parent_rect.pointInRect(x, y)) - { - // clicked off of menu and parent, hide them all - hideMenus(); - } - } - else - { - // no visible parent, clicked off of menu, hide them all - hideMenus(); - } - } - return handled; + BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; + if (!handled) + { + LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu(); + LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL; + if (parent_menu && parent_menu->getVisible()) + { + // don't hide menu if parent was hit + LLRect parent_rect; + parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this); + if (!parent_rect.pointInRect(x, y)) + { + // clicked off of menu and parent, hide them all + hideMenus(); + } + } + else + { + // no visible parent, clicked off of menu, hide them all + hideMenus(); + } + } + return handled; } BOOL LLMenuHolderGL::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = LLView::childrenHandleRightMouseDown(x, y, mask) != NULL; - if (!handled) - { - // clicked off of menu, hide them all - hideMenus(); - } - return handled; + BOOL handled = LLView::childrenHandleRightMouseDown(x, y, mask) != NULL; + if (!handled) + { + // clicked off of menu, hide them all + hideMenus(); + } + return handled; } -// This occurs when you mouse-down to spawn a context menu, hold the button +// This occurs when you mouse-down to spawn a context menu, hold the button // down, move off the menu, then mouse-up. We want this to close the menu. BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask ) { - const S32 SLOP = 2; - S32 spawn_dx = (x - sContextMenuSpawnPos.mX); - S32 spawn_dy = (y - sContextMenuSpawnPos.mY); - if (-SLOP <= spawn_dx && spawn_dx <= SLOP - && -SLOP <= spawn_dy && spawn_dy <= SLOP) - { - // we're still inside the slop region from spawning this menu - // so interpret the mouse-up as a single-click to show and leave on - // screen - sContextMenuSpawnPos.set(S32_MAX, S32_MAX); - return TRUE; - } - - BOOL handled = LLView::childrenHandleRightMouseUp(x, y, mask) != NULL; - if (!handled) - { - // clicked off of menu, hide them all - hideMenus(); - } - return handled; + const S32 SLOP = 2; + S32 spawn_dx = (x - sContextMenuSpawnPos.mX); + S32 spawn_dy = (y - sContextMenuSpawnPos.mY); + if (-SLOP <= spawn_dx && spawn_dx <= SLOP + && -SLOP <= spawn_dy && spawn_dy <= SLOP) + { + // we're still inside the slop region from spawning this menu + // so interpret the mouse-up as a single-click to show and leave on + // screen + sContextMenuSpawnPos.set(S32_MAX, S32_MAX); + return TRUE; + } + + BOOL handled = LLView::childrenHandleRightMouseUp(x, y, mask) != NULL; + if (!handled) + { + // clicked off of menu, hide them all + hideMenus(); + } + return handled; } BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - BOOL handled = false; - LLMenuGL* const pMenu = dynamic_cast(getVisibleMenu()); - - if (pMenu) - { - //eat TAB key - EXT-7000 - if (key == KEY_TAB && mask == MASK_NONE) - { - return TRUE; - } - - //handle ESCAPE and RETURN key - handled = LLPanel::handleKey(key, mask, called_from_parent); - if (!handled) - { - if (pMenu->getHighlightedItem()) - { - handled = pMenu->handleKey(key, mask, TRUE); - } - else if (mask == MASK_NONE || (key >= KEY_LEFT && key <= KEY_DOWN)) - { - //highlight first enabled one - if(pMenu->highlightNextItem(NULL)) - { - handled = true; - } - } - } - } - - return handled; - + BOOL handled = false; + LLMenuGL* const pMenu = dynamic_cast(getVisibleMenu()); + + if (pMenu) + { + //eat TAB key - EXT-7000 + if (key == KEY_TAB && mask == MASK_NONE) + { + return TRUE; + } + + //handle ESCAPE and RETURN key + handled = LLPanel::handleKey(key, mask, called_from_parent); + if (!handled) + { + if (pMenu->getHighlightedItem()) + { + handled = pMenu->handleKey(key, mask, TRUE); + } + else if (mask == MASK_NONE || (key >= KEY_LEFT && key <= KEY_DOWN)) + { + //highlight first enabled one + if(pMenu->highlightNextItem(NULL)) + { + handled = true; + } + } + } + } + + return handled; + } void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent) { - if (width != getRect().getWidth() || height != getRect().getHeight()) - { - hideMenus(); - } - LLView::reshape(width, height, called_from_parent); + if (width != getRect().getWidth() || height != getRect().getHeight()) + { + hideMenus(); + } + LLView::reshape(width, height, called_from_parent); } LLView* const LLMenuHolderGL::getVisibleMenu() const { - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if (viewp->getVisible() && dynamic_cast(viewp) != NULL) - { - return viewp; - } - } - return NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if (viewp->getVisible() && dynamic_cast(viewp) != NULL) + { + return viewp; + } + } + return NULL; } BOOL LLMenuHolderGL::hideMenus() { - if (!mCanHide) - { - return FALSE; - } - LLMenuGL::setKeyboardMode(FALSE); - BOOL menu_visible = hasVisibleMenu(); - if (menu_visible) - { - // clicked off of menu, hide them all - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) - { - LLView* viewp = *child_it; - if (dynamic_cast(viewp) != NULL && viewp->getVisible()) - { - viewp->setVisible(FALSE); - } - } - } - //if (gFocusMgr.childHasKeyboardFocus(this)) - //{ - // gFocusMgr.setKeyboardFocus(NULL); - //} - - return menu_visible; + if (!mCanHide) + { + return FALSE; + } + LLMenuGL::setKeyboardMode(FALSE); + BOOL menu_visible = hasVisibleMenu(); + if (menu_visible) + { + // clicked off of menu, hide them all + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLView* viewp = *child_it; + if (dynamic_cast(viewp) != NULL && viewp->getVisible()) + { + viewp->setVisible(FALSE); + } + } + } + //if (gFocusMgr.childHasKeyboardFocus(this)) + //{ + // gFocusMgr.setKeyboardFocus(NULL); + //} + + return menu_visible; } void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item) { - sItemLastSelectedHandle = item->getHandle(); - sItemActivationTimer.start(); + sItemLastSelectedHandle = item->getHandle(); + sItemActivationTimer.start(); } ///============================================================================ /// Class LLTearOffMenu ///============================================================================ -LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : - LLFloater(LLSD()), +LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : + LLFloater(LLSD()), mQuitRequested(false) { - S32 floater_header_size = getHeaderHeight(); + S32 floater_header_size = getHeaderHeight(); - setName(menup->getName()); - setTitle(menup->getLabel()); - setCanMinimize(FALSE); - // flag menu as being torn off - menup->setTornOff(TRUE); - // update menu layout as torn off menu (no spillover menus) - menup->needsArrange(); + setName(menup->getName()); + setTitle(menup->getLabel()); + setCanMinimize(FALSE); + // flag menu as being torn off + menup->setTornOff(TRUE); + // update menu layout as torn off menu (no spillover menus) + menup->needsArrange(); - LLRect rect; - menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView); - // make sure this floater is big enough for menu - mTargetHeight = rect.getHeight() + floater_header_size; - reshape(rect.getWidth(), rect.getHeight()); - setRect(rect); + LLRect rect; + menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView); + // make sure this floater is big enough for menu + mTargetHeight = rect.getHeight() + floater_header_size; + reshape(rect.getWidth(), rect.getHeight()); + setRect(rect); - // attach menu to floater - menup->setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); - mOldParent = menup->getParent(); - addChild(menup); - menup->setVisible(TRUE); - LLRect menu_rect = menup->getRect(); - menu_rect.setOriginAndSize( 1, 1, - menu_rect.getWidth(), menu_rect.getHeight()); - menup->setRect(menu_rect); - menup->setDropShadowed(FALSE); + // attach menu to floater + menup->setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); + mOldParent = menup->getParent(); + addChild(menup); + menup->setVisible(TRUE); + LLRect menu_rect = menup->getRect(); + menu_rect.setOriginAndSize( 1, 1, + menu_rect.getWidth(), menu_rect.getHeight()); + menup->setRect(menu_rect); + menup->setDropShadowed(FALSE); - mMenu = menup; + mMenu = menup; - // highlight first item (tear off item will be disabled) - mMenu->highlightNextItem(NULL); + // highlight first item (tear off item will be disabled) + mMenu->highlightNextItem(NULL); - // Can't do this in postBuild() because that is only called for floaters - // constructed from XML. - mCloseSignal.connect(boost::bind(&LLTearOffMenu::closeTearOff, this)); + // Can't do this in postBuild() because that is only called for floaters + // constructed from XML. + mCloseSignal.connect(boost::bind(&LLTearOffMenu::closeTearOff, this)); } LLTearOffMenu::~LLTearOffMenu() @@ -3973,15 +3973,15 @@ LLTearOffMenu::~LLTearOffMenu() void LLTearOffMenu::draw() { - mMenu->setBackgroundVisible(isBackgroundOpaque()); + mMenu->setBackgroundVisible(isBackgroundOpaque()); - if (getRect().getHeight() != mTargetHeight) - { - // animate towards target height + if (getRect().getHeight() != mTargetHeight) + { + // animate towards target height reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), (F32)mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); - } - mMenu->needsArrange(); - LLFloater::draw(); + } + mMenu->needsArrange(); + LLFloater::draw(); } void LLTearOffMenu::onFocusReceived() @@ -3990,81 +3990,81 @@ void LLTearOffMenu::onFocusReceived() { return; } - + // if nothing is highlighted, just highlight first item - if (!mMenu->getHighlightedItem()) - { - mMenu->highlightNextItem(NULL); - } - - // parent menu items get highlights so navigation logic keeps working - LLMenuItemGL* parent_menu_item = mMenu->getParentMenuItem(); - while(parent_menu_item) - { - if (parent_menu_item->getMenu()->getVisible()) - { - parent_menu_item->setHighlight(TRUE); - parent_menu_item = parent_menu_item->getMenu()->getParentMenuItem(); - } - else - { - break; - } - } - LLFloater::onFocusReceived(); + if (!mMenu->getHighlightedItem()) + { + mMenu->highlightNextItem(NULL); + } + + // parent menu items get highlights so navigation logic keeps working + LLMenuItemGL* parent_menu_item = mMenu->getParentMenuItem(); + while(parent_menu_item) + { + if (parent_menu_item->getMenu()->getVisible()) + { + parent_menu_item->setHighlight(TRUE); + parent_menu_item = parent_menu_item->getMenu()->getParentMenuItem(); + } + else + { + break; + } + } + LLFloater::onFocusReceived(); } void LLTearOffMenu::onFocusLost() { - // remove highlight from parent item and our own menu - mMenu->clearHoverItem(); - LLFloater::onFocusLost(); + // remove highlight from parent item and our own menu + mMenu->clearHoverItem(); + LLFloater::onFocusLost(); } BOOL LLTearOffMenu::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { - // pass keystrokes down to menu - return mMenu->handleUnicodeChar(uni_char, TRUE); + // pass keystrokes down to menu + return mMenu->handleUnicodeChar(uni_char, TRUE); } BOOL LLTearOffMenu::handleKeyHere(KEY key, MASK mask) { - if (!mMenu->getHighlightedItem()) - { - if (key == KEY_UP) - { - mMenu->highlightPrevItem(NULL); - return TRUE; - } - else if (key == KEY_DOWN) - { - mMenu->highlightNextItem(NULL); - return TRUE; - } - } - // pass keystrokes down to menu - return mMenu->handleKey(key, mask, TRUE); + if (!mMenu->getHighlightedItem()) + { + if (key == KEY_UP) + { + mMenu->highlightPrevItem(NULL); + return TRUE; + } + else if (key == KEY_DOWN) + { + mMenu->highlightNextItem(NULL); + return TRUE; + } + } + // pass keystrokes down to menu + return mMenu->handleKey(key, mask, TRUE); } void LLTearOffMenu::translate(S32 x, S32 y) { - if (x != 0 && y != 0) - { - // hide open sub-menus by clearing current hover item - mMenu->clearHoverItem(); - } - LLFloater::translate(x, y); + if (x != 0 && y != 0) + { + // hide open sub-menus by clearing current hover item + mMenu->clearHoverItem(); + } + LLFloater::translate(x, y); } //static LLTearOffMenu* LLTearOffMenu::create(LLMenuGL* menup) { - LLTearOffMenu* tearoffp = new LLTearOffMenu(menup); - // keep onscreen - gFloaterView->adjustToFitScreen(tearoffp, FALSE); - tearoffp->openFloater(LLSD()); + LLTearOffMenu* tearoffp = new LLTearOffMenu(menup); + // keep onscreen + gFloaterView->adjustToFitScreen(tearoffp, FALSE); + tearoffp->openFloater(LLSD()); - return tearoffp; + return tearoffp; } void LLTearOffMenu::updateSize() @@ -4094,108 +4094,108 @@ void LLTearOffMenu::updateSize() void LLTearOffMenu::closeTearOff() { - removeChild(mMenu); - mOldParent->addChild(mMenu); - mMenu->clearHoverItem(); - mMenu->setFollowsNone(); - mMenu->setBackgroundVisible(TRUE); - mMenu->setVisible(FALSE); - mMenu->setTornOff(FALSE); - mMenu->setDropShadowed(TRUE); + removeChild(mMenu); + mOldParent->addChild(mMenu); + mMenu->clearHoverItem(); + mMenu->setFollowsNone(); + mMenu->setBackgroundVisible(TRUE); + mMenu->setVisible(FALSE); + mMenu->setTornOff(FALSE); + mMenu->setDropShadowed(TRUE); mQuitRequested = true; } -LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) -: LLMenuItemGL(p) +LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) +: LLMenuItemGL(p) { - LLContextMenu* branch = static_cast(p.branch); - if (branch) - { - mBranch = branch->getHandle(); - branch->hide(); - branch->setParentMenuItem(this); - } + LLContextMenu* branch = static_cast(p.branch); + if (branch) + { + mBranch = branch->getHandle(); + branch->hide(); + branch->setParentMenuItem(this); + } } LLContextMenuBranch::~LLContextMenuBranch() { - if (mBranch.get()) - { - mBranch.get()->die(); - } + 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 = menu->getItemCount(); - U32 i; - BOOL any_enabled = FALSE; - for (i = 0; i < sub_count; i++) - { - LLMenuItemGL* item = menu->getItem(i); - item->buildDrawLabel(); - if (item->getEnabled() && !item->getDrawTextDisabled() ) - { - any_enabled = TRUE; - break; - } - } - setDrawTextDisabled(!any_enabled); - setEnabled(TRUE); - } - - mDrawAccelLabel.clear(); - std::string st = mDrawAccelLabel; - appendAcceleratorString( st ); - mDrawAccelLabel = st; - - mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; -} - -void LLContextMenuBranch::showSubMenu() -{ - auto menu = getBranch(); - if(menu) - { - 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); - } - } + auto menu = getBranch(); + if (menu) + { + // default enablement is this -- if any of the subitems are + // enabled, this item is enabled. JC + U32 sub_count = menu->getItemCount(); + U32 i; + BOOL any_enabled = FALSE; + for (i = 0; i < sub_count; i++) + { + LLMenuItemGL* item = menu->getItem(i); + item->buildDrawLabel(); + if (item->getEnabled() && !item->getDrawTextDisabled() ) + { + any_enabled = TRUE; + break; + } + } + setDrawTextDisabled(!any_enabled); + setEnabled(TRUE); + } + + mDrawAccelLabel.clear(); + std::string st = mDrawAccelLabel; + appendAcceleratorString( st ); + mDrawAccelLabel = st; + + mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; +} + +void LLContextMenuBranch::showSubMenu() +{ + auto menu = getBranch(); + if(menu) + { + 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); + } + } } // onCommit() - do the primary funcationality of the menu item. void LLContextMenuBranch::onCommit( void ) { - showSubMenu(); + showSubMenu(); } void LLContextMenuBranch::setHighlight( BOOL highlight ) { - if (highlight == getHighlight()) return; - LLMenuItemGL::setHighlight(highlight); - auto menu = getBranch(); - if (menu) - { - if (highlight) - { - showSubMenu(); - } - else - { - menu->hide(); - } - } + if (highlight == getHighlight()) return; + LLMenuItemGL::setHighlight(highlight); + auto menu = getBranch(); + if (menu) + { + if (highlight) + { + showSubMenu(); + } + else + { + menu->hide(); + } + } } @@ -4209,140 +4209,140 @@ static MenuRegistry::Register context_menu_register2("context_men LLContextMenu::LLContextMenu(const Params& p) -: LLMenuGL(p), - mHoveredAnyItem(FALSE), - mHoverItem(NULL) +: LLMenuGL(p), + mHoveredAnyItem(FALSE), + mHoverItem(NULL) { - //setBackgroundVisible(TRUE); + //setBackgroundVisible(TRUE); } void LLContextMenu::setVisible(BOOL visible) { - if (!visible) - hide(); + if (!visible) + hide(); } // Takes cursor position in screen space? void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view) { - if (getChildList()->empty()) - { - // nothing to show, so abort - return; - } - // Save click point for detecting cursor moves before mouse-up. - // Must be in local coords to compare with mouseUp events. - // If the mouse doesn't move, the menu will stay open ala the Mac. - // See also LLMenuGL::showPopup() - LLMenuHolderGL::sContextMenuSpawnPos.set(x,y); - - arrangeAndClear(); - - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); - const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); - LLView* parent_view = getParent(); - - // Open upwards if menu extends past bottom - if (y - height < menu_region_rect.mBottom) - { - if (getParentMenuItem()) // Adjust if this is a submenu - { - y += height - getParentMenuItem()->getNominalHeight(); - } - else - { - y += height; - } - } - - // Open out to the left if menu extends past right edge - if (x + width > menu_region_rect.mRight) - { - if (getParentMenuItem()) - { - x -= getParentMenuItem()->getRect().getWidth() + width; - } - else - { - x -= width; - } - } - - S32 local_x, local_y; - parent_view->screenPointToLocal(x, y, &local_x, &local_y); - - LLRect rect; - rect.setLeftTopAndSize(local_x, local_y, width, height); - setRect(rect); - arrange(); - - if (spawning_view) - { - mSpawningViewHandle = spawning_view->getHandle(); - } - else - { - mSpawningViewHandle.markDead(); - } - LLView::setVisible(TRUE); + if (getChildList()->empty()) + { + // nothing to show, so abort + return; + } + // Save click point for detecting cursor moves before mouse-up. + // Must be in local coords to compare with mouseUp events. + // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLMenuGL::showPopup() + LLMenuHolderGL::sContextMenuSpawnPos.set(x,y); + + arrangeAndClear(); + + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); + LLView* parent_view = getParent(); + + // Open upwards if menu extends past bottom + if (y - height < menu_region_rect.mBottom) + { + if (getParentMenuItem()) // Adjust if this is a submenu + { + y += height - getParentMenuItem()->getNominalHeight(); + } + else + { + y += height; + } + } + + // Open out to the left if menu extends past right edge + if (x + width > menu_region_rect.mRight) + { + if (getParentMenuItem()) + { + x -= getParentMenuItem()->getRect().getWidth() + width; + } + else + { + x -= width; + } + } + + S32 local_x, local_y; + parent_view->screenPointToLocal(x, y, &local_x, &local_y); + + LLRect rect; + rect.setLeftTopAndSize(local_x, local_y, width, height); + setRect(rect); + arrange(); + + if (spawning_view) + { + mSpawningViewHandle = spawning_view->getHandle(); + } + else + { + mSpawningViewHandle.markDead(); + } + LLView::setVisible(TRUE); } void LLContextMenu::hide() { - if (!getVisible()) return; + if (!getVisible()) return; - LLView::setVisible(FALSE); + LLView::setVisible(FALSE); - if (mHoverItem) - { - mHoverItem->setHighlight( FALSE ); - } - mHoverItem = NULL; + if (mHoverItem) + { + mHoverItem->setHighlight( FALSE ); + } + mHoverItem = NULL; } BOOL LLContextMenu::handleHover( S32 x, S32 y, MASK mask ) { - LLMenuGL::handleHover(x,y,mask); - - BOOL handled = FALSE; - - LLMenuItemGL *item = getHighlightedItem(); - - if (item && item->getEnabled()) - { - getWindow()->setCursor(UI_CURSOR_ARROW); - handled = TRUE; - - if (item != mHoverItem) - { - if (mHoverItem) - { - mHoverItem->setHighlight( FALSE ); - } - mHoverItem = item; - mHoverItem->setHighlight( TRUE ); - } - mHoveredAnyItem = TRUE; - } - else - { - // clear out our selection - if (mHoverItem) - { - mHoverItem->setHighlight(FALSE); - mHoverItem = NULL; - } - } - - if( !handled && pointInView( x, y ) ) - { - getWindow()->setCursor(UI_CURSOR_ARROW); - handled = TRUE; - } - - return handled; + LLMenuGL::handleHover(x,y,mask); + + BOOL handled = FALSE; + + LLMenuItemGL *item = getHighlightedItem(); + + if (item && item->getEnabled()) + { + getWindow()->setCursor(UI_CURSOR_ARROW); + handled = TRUE; + + if (item != mHoverItem) + { + if (mHoverItem) + { + mHoverItem->setHighlight( FALSE ); + } + mHoverItem = item; + mHoverItem->setHighlight( TRUE ); + } + mHoveredAnyItem = TRUE; + } + else + { + // clear out our selection + if (mHoverItem) + { + mHoverItem->setHighlight(FALSE); + mHoverItem = NULL; + } + } + + if( !handled && pointInView( x, y ) ) + { + getWindow()->setCursor(UI_CURSOR_ARROW); + handled = TRUE; + } + + return handled; } // handleMouseDown and handleMouseUp are handled by LLMenuGL @@ -4350,56 +4350,56 @@ BOOL LLContextMenu::handleHover( S32 x, S32 y, MASK mask ) BOOL LLContextMenu::handleRightMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; + BOOL handled = FALSE; + + // The click was somewhere within our rectangle + LLMenuItemGL *item = getHighlightedItem(); - // The click was somewhere within our rectangle - LLMenuItemGL *item = getHighlightedItem(); + S32 local_x = x - getRect().mLeft; + S32 local_y = y - getRect().mBottom; - S32 local_x = x - getRect().mLeft; - S32 local_y = y - getRect().mBottom; + BOOL clicked_in_menu = pointInView(local_x, local_y) ; - BOOL clicked_in_menu = pointInView(local_x, local_y) ; + // grab mouse if right clicking anywhere within pie (even deadzone in middle), to detect drag outside of pie + if (clicked_in_menu) + { + // capture mouse cursor as if on initial menu show + handled = TRUE; + } - // grab mouse if right clicking anywhere within pie (even deadzone in middle), to detect drag outside of pie - if (clicked_in_menu) - { - // capture mouse cursor as if on initial menu show - handled = TRUE; - } - - if (item) - { - // lie to the item about where the click happened - // to make sure it's within the item's rectangle - if (item->handleMouseDown( 0, 0, mask )) - { - handled = TRUE; - } - } + if (item) + { + // lie to the item about where the click happened + // to make sure it's within the item's rectangle + if (item->handleMouseDown( 0, 0, mask )) + { + handled = TRUE; + } + } - return handled; + return handled; } BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask ) { - S32 local_x = x - getRect().mLeft; - S32 local_y = y - getRect().mBottom; + S32 local_x = x - getRect().mLeft; + S32 local_y = y - getRect().mBottom; + + if (!mHoveredAnyItem && !pointInView(local_x, local_y)) + { + sMenuContainer->hideMenus(); + return TRUE; + } - if (!mHoveredAnyItem && !pointInView(local_x, local_y)) - { - sMenuContainer->hideMenus(); - return TRUE; - } + BOOL result = handleMouseUp( x, y, mask ); + mHoveredAnyItem = FALSE; - BOOL result = handleMouseUp( x, y, mask ); - mHoveredAnyItem = FALSE; - - return result; + return result; } bool LLContextMenu::addChild(LLView* view, S32 tab_group) { - return addContextChild(view, tab_group); + return addContextChild(view, tab_group); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 44ac61f20d..72e041672a 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -1,25 +1,25 @@ -/** +/** * @file llmenugl.h * @brief Declaration of the opengl based menu system. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,183 +45,183 @@ extern S32 MENU_BAR_WIDTH; class LLMenuKeyboardBinding { public: - KEY mKey; - MASK mMask; + KEY mKey; + MASK mMask; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemGL // -// The LLMenuItemGL represents a single menu item in a menu. +// The LLMenuItemGL represents a single menu item in a menu. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl { public: - struct Params : public LLInitParam::Block - { - Optional shortcut; - Optional jump_key; - Optional use_mac_ctrl, - allow_key_repeat; - - Ignored rect, - left, - top, - right, - bottom, - width, - height, - bottom_delta, - left_delta; - - Optional enabled_color, - disabled_color, - highlight_bg_color, - highlight_fg_color; - - - Params(); - }; + struct Params : public LLInitParam::Block + { + Optional shortcut; + Optional jump_key; + Optional use_mac_ctrl, + allow_key_repeat; + + Ignored rect, + left, + top, + right, + bottom, + width, + height, + bottom_delta, + left_delta; + + Optional enabled_color, + disabled_color, + highlight_bg_color, + highlight_fg_color; + + + Params(); + }; protected: - LLMenuItemGL(const Params&); - friend class LLUICtrlFactory; + LLMenuItemGL(const Params&); + friend class LLUICtrlFactory; public: - // LLView overrides - /*virtual*/ void onVisibilityChange(BOOL new_visibility); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - - // LLUICtrl overrides - /*virtual*/ void setValue(const LLSD& value); - /*virtual*/ LLSD getValue() const; - - virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - - LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); } - - void setJumpKey(KEY key); - KEY getJumpKey() const { return mJumpKey; } - - // set the font used by this item. - void setFont(const LLFontGL* font) { mFont = font; } - const LLFontGL* getFont() const { return mFont; } - - // returns the height in pixels for the current font. - virtual U32 getNominalHeight( void ) const; - - // Marks item as not needing space for check marks or accelerator keys - virtual void setBriefItem(BOOL brief); - virtual BOOL isBriefItem() const; - - virtual BOOL addToAcceleratorList(std::list *listp); - void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; } - BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; } - - // change the label - void setLabel( const LLStringExplicit& label ) { mLabel = label; } - std::string getLabel( void ) const { return mLabel.getString(); } - virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - - // Get the parent menu for this item - virtual class LLMenuGL* getMenu() const; - - // returns the normal width of this control in pixels - this is - // used for calculating the widest item, as well as for horizontal - // arrangement. - virtual U32 getNominalWidth( void ) const; - - // buildDrawLabel() - constructs the string used during the draw() - // function. This reduces the overall string manipulation, but can - // lead to visual errors if the state of the object changes - // without the knowledge of the menu item. For example, if a - // boolean being watched is changed outside of the menu item's - // onCommit() function, the draw buffer will not be updated and will - // reflect the wrong value. If this ever becomes an issue, there - // are ways to fix this. - // Returns the enabled state of the item. - virtual void buildDrawLabel( void ); - - // for branching menu items, bring sub menus up to root level of menu hierarchy - virtual void updateBranchParent( LLView* parentp ){}; - - virtual void onCommit( void ); - - virtual void setHighlight( BOOL highlight ); - virtual BOOL getHighlight() const { return mHighlight; } - - // determine if this represents an active sub-menu - virtual BOOL isActive( void ) const { return FALSE; } - - // determine if this represents an open sub-menu - virtual BOOL isOpen( void ) const { return FALSE; } - - virtual void setEnabledSubMenus(BOOL enable){}; - - // LLView Functionality - virtual BOOL handleKeyHere( KEY key, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - - virtual void onMouseEnter(S32 x, S32 y, MASK mask); - virtual void onMouseLeave(S32 x, S32 y, MASK mask); - - virtual void draw( void ); - - BOOL getHover() const { return mGotHover; } - - void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; } - BOOL getDrawTextDisabled() const { return mDrawTextDisabled; } + // LLView overrides + /*virtual*/ void onVisibilityChange(BOOL new_visibility); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + + // LLUICtrl overrides + /*virtual*/ void setValue(const LLSD& value); + /*virtual*/ LLSD getValue() const; + + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; + virtual BOOL handleAcceleratorKey(KEY key, MASK mask); + + LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); } + + void setJumpKey(KEY key); + KEY getJumpKey() const { return mJumpKey; } + + // set the font used by this item. + void setFont(const LLFontGL* font) { mFont = font; } + const LLFontGL* getFont() const { return mFont; } + + // returns the height in pixels for the current font. + virtual U32 getNominalHeight( void ) const; + + // Marks item as not needing space for check marks or accelerator keys + virtual void setBriefItem(BOOL brief); + virtual BOOL isBriefItem() const; + + virtual BOOL addToAcceleratorList(std::list *listp); + void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; } + BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; } + + // change the label + void setLabel( const LLStringExplicit& label ) { mLabel = label; } + std::string getLabel( void ) const { return mLabel.getString(); } + virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + + // Get the parent menu for this item + virtual class LLMenuGL* getMenu() const; + + // returns the normal width of this control in pixels - this is + // used for calculating the widest item, as well as for horizontal + // arrangement. + virtual U32 getNominalWidth( void ) const; + + // buildDrawLabel() - constructs the string used during the draw() + // function. This reduces the overall string manipulation, but can + // lead to visual errors if the state of the object changes + // without the knowledge of the menu item. For example, if a + // boolean being watched is changed outside of the menu item's + // onCommit() function, the draw buffer will not be updated and will + // reflect the wrong value. If this ever becomes an issue, there + // are ways to fix this. + // Returns the enabled state of the item. + virtual void buildDrawLabel( void ); + + // for branching menu items, bring sub menus up to root level of menu hierarchy + virtual void updateBranchParent( LLView* parentp ){}; + + virtual void onCommit( void ); + + virtual void setHighlight( BOOL highlight ); + virtual BOOL getHighlight() const { return mHighlight; } + + // determine if this represents an active sub-menu + virtual BOOL isActive( void ) const { return FALSE; } + + // determine if this represents an open sub-menu + virtual BOOL isOpen( void ) const { return FALSE; } + + virtual void setEnabledSubMenus(BOOL enable){}; + + // LLView Functionality + virtual BOOL handleKeyHere( KEY key, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual void draw( void ); + + BOOL getHover() const { return mGotHover; } + + void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; } + BOOL getDrawTextDisabled() const { return mDrawTextDisabled; } protected: - void setHover(BOOL hover) { mGotHover = hover; } + void setHover(BOOL hover) { mGotHover = hover; } - // This function appends the character string representation of - // the current accelerator key and mask to the provided string. - void appendAcceleratorString( std::string& st ) const; + // This function appends the character string representation of + // the current accelerator key and mask to the provided string. + void appendAcceleratorString( std::string& st ) const; - virtual std::string _getSearchText() const - { - return mLabel.getString(); - } + virtual std::string _getSearchText() const + { + return mLabel.getString(); + } protected: - KEY mAcceleratorKey; - MASK mAcceleratorMask; - // mLabel contains the actual label specified by the user. - LLUIString mLabel; - - // The draw labels contain some of the labels that we draw during - // the draw() routine. This optimizes away some of the string - // manipulation. - LLUIString mDrawBoolLabel; - LLUIString mDrawAccelLabel; - LLUIString mDrawBranchLabel; - - LLUIColor mEnabledColor; - LLUIColor mDisabledColor; - LLUIColor mHighlightBackground; - LLUIColor mHighlightForeground; - - BOOL mHighlight; + KEY mAcceleratorKey; + MASK mAcceleratorMask; + // mLabel contains the actual label specified by the user. + LLUIString mLabel; + + // The draw labels contain some of the labels that we draw during + // the draw() routine. This optimizes away some of the string + // manipulation. + LLUIString mDrawBoolLabel; + LLUIString mDrawAccelLabel; + LLUIString mDrawBranchLabel; + + LLUIColor mEnabledColor; + LLUIColor mDisabledColor; + LLUIColor mHighlightBackground; + LLUIColor mHighlightForeground; + + BOOL mHighlight; private: - // Keyboard and mouse variables - BOOL mAllowKeyRepeat; - BOOL mGotHover; + // Keyboard and mouse variables + BOOL mAllowKeyRepeat; + BOOL mGotHover; - // If true, suppress normal space for check marks on the left and accelerator - // keys on the right. - BOOL mBriefItem; + // If true, suppress normal space for check marks on the left and accelerator + // keys on the right. + BOOL mBriefItem; - // Font for this item - const LLFontGL* mFont; - BOOL mDrawTextDisabled; + // Font for this item + const LLFontGL* mFont; + BOOL mDrawTextDisabled; - KEY mJumpKey; + KEY mJumpKey; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -232,22 +232,22 @@ private: class LLMenuItemSeparatorGL : public LLMenuItemGL { public: - struct Params : public LLInitParam::Block - { + struct Params : public LLInitParam::Block + { Optional on_visible; Params(); - }; + }; LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params()); - /*virtual*/ void draw( void ); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ void draw( void ); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); virtual void buildDrawLabel(); - /*virtual*/ U32 getNominalHeight( void ) const; + /*virtual*/ U32 getNominalHeight( void ) const; private: enable_signal_t mVisibleSignal; @@ -263,49 +263,49 @@ private: class LLMenuItemCallGL : public LLMenuItemGL { public: - struct Params : public LLInitParam::Block - { - Optional on_enable; - Optional on_click; - Optional on_visible; - Params() - : on_enable("on_enable"), - on_click("on_click"), - on_visible("on_visible") - {} - }; + struct Params : public LLInitParam::Block + { + Optional on_enable; + Optional on_click; + Optional on_visible; + Params() + : on_enable("on_enable"), + on_click("on_click"), + on_visible("on_visible") + {} + }; protected: - LLMenuItemCallGL(const Params&); - friend class LLUICtrlFactory; - void updateEnabled( void ); - void updateVisible( void ); + LLMenuItemCallGL(const Params&); + friend class LLUICtrlFactory; + void updateEnabled( void ); + void updateVisible( void ); public: - void initFromParams(const Params& p); - - // called to rebuild the draw label - virtual void buildDrawLabel( void ); - - virtual void onCommit( void ); - - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - virtual BOOL handleKeyHere(KEY key, MASK mask); - - //virtual void draw(); - - boost::signals2::connection setClickCallback( const commit_signal_t::slot_type& cb ) - { - return setCommitCallback(cb); - } - - boost::signals2::connection setEnableCallback( const enable_signal_t::slot_type& cb ) - { - return mEnableSignal.connect(cb); - } - + void initFromParams(const Params& p); + + // called to rebuild the draw label + virtual void buildDrawLabel( void ); + + virtual void onCommit( void ); + + virtual BOOL handleAcceleratorKey(KEY key, MASK mask); + virtual BOOL handleKeyHere(KEY key, MASK mask); + + //virtual void draw(); + + boost::signals2::connection setClickCallback( const commit_signal_t::slot_type& cb ) + { + return setCommitCallback(cb); + } + + boost::signals2::connection setEnableCallback( const enable_signal_t::slot_type& cb ) + { + return mEnableSignal.connect(cb); + } + private: - enable_signal_t mEnableSignal; - enable_signal_t mVisibleSignal; + enable_signal_t mEnableSignal; + enable_signal_t mVisibleSignal; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -318,40 +318,40 @@ private: // EFFICIENT because it may need to be checked a lot. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLMenuItemCheckGL -: public LLMenuItemCallGL +class LLMenuItemCheckGL +: public LLMenuItemCallGL { public: - struct Params : public LLInitParam::Block - { - Optional on_check; - Params() - : on_check("on_check") - {} - }; + struct Params : public LLInitParam::Block + { + Optional on_check; + Params() + : on_check("on_check") + {} + }; protected: - LLMenuItemCheckGL(const Params&); - friend class LLUICtrlFactory; + LLMenuItemCheckGL(const Params&); + friend class LLUICtrlFactory; public: - - void initFromParams(const Params& p); - - virtual void onCommit( void ); - - virtual void setValue(const LLSD& value); - virtual LLSD getValue() const; - - // called to rebuild the draw label - virtual void buildDrawLabel( void ); - - boost::signals2::connection setCheckCallback( const enable_signal_t::slot_type& cb ) - { - return mCheckSignal.connect(cb); - } - + + void initFromParams(const Params& p); + + virtual void onCommit( void ); + + virtual void setValue(const LLSD& value); + virtual LLSD getValue() const; + + // called to rebuild the draw label + virtual void buildDrawLabel( void ); + + boost::signals2::connection setCheckCallback( const enable_signal_t::slot_type& cb ) + { + return mCheckSignal.connect(cb); + } + private: - enable_signal_t mCheckSignal; + enable_signal_t mCheckSignal; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -368,233 +368,233 @@ private: // child widget registry struct MenuRegistry : public LLChildRegistry { - LLSINGLETON_EMPTY_CTOR(MenuRegistry); + LLSINGLETON_EMPTY_CTOR(MenuRegistry); }; -class LLMenuGL -: public LLUICtrl +class LLMenuGL +: public LLUICtrl { public: - struct Params : public LLInitParam::Block - { - Optional jump_key; - Optional horizontal_layout, - can_tear_off, - drop_shadow, - bg_visible, - create_jump_keys, - keep_fixed_size, - scrollable; - Optional max_scrollable_items; - Optional preferred_width; - Optional bg_color; - Optional shortcut_pad; - - Params() - : jump_key("jump_key", KEY_NONE), - horizontal_layout("horizontal_layout"), - can_tear_off("tear_off", false), - drop_shadow("drop_shadow", true), - bg_visible("bg_visible", true), - create_jump_keys("create_jump_keys", false), - keep_fixed_size("keep_fixed_size", false), - bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )), - scrollable("scrollable", false), - max_scrollable_items("max_scrollable_items", U32_MAX), - preferred_width("preferred_width", U32_MAX), - shortcut_pad("shortcut_pad") - { - addSynonym(bg_visible, "opaque"); - addSynonym(bg_color, "color"); - addSynonym(can_tear_off, "can_tear_off"); - } - }; - - // my valid children are contained in MenuRegistry - typedef MenuRegistry child_registry_t; - - void initFromParams(const Params&); - - // textual artwork which menugl-imitators may want to match - static const std::string BOOLEAN_TRUE_PREFIX; - static const std::string BRANCH_SUFFIX; - static const std::string ARROW_UP; - static const std::string ARROW_DOWN; - - // for scrollable menus - typedef enum e_scrolling_direction - { - SD_UP = 0, - SD_DOWN = 1, - SD_BEGIN = 2, - SD_END = 3 - } EScrollingDirection; + struct Params : public LLInitParam::Block + { + Optional jump_key; + Optional horizontal_layout, + can_tear_off, + drop_shadow, + bg_visible, + create_jump_keys, + keep_fixed_size, + scrollable; + Optional max_scrollable_items; + Optional preferred_width; + Optional bg_color; + Optional shortcut_pad; + + Params() + : jump_key("jump_key", KEY_NONE), + horizontal_layout("horizontal_layout"), + can_tear_off("tear_off", false), + drop_shadow("drop_shadow", true), + bg_visible("bg_visible", true), + create_jump_keys("create_jump_keys", false), + keep_fixed_size("keep_fixed_size", false), + bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )), + scrollable("scrollable", false), + max_scrollable_items("max_scrollable_items", U32_MAX), + preferred_width("preferred_width", U32_MAX), + shortcut_pad("shortcut_pad") + { + addSynonym(bg_visible, "opaque"); + addSynonym(bg_color, "color"); + addSynonym(can_tear_off, "can_tear_off"); + } + }; + + // my valid children are contained in MenuRegistry + typedef MenuRegistry child_registry_t; + + void initFromParams(const Params&); + + // textual artwork which menugl-imitators may want to match + static const std::string BOOLEAN_TRUE_PREFIX; + static const std::string BRANCH_SUFFIX; + static const std::string ARROW_UP; + static const std::string ARROW_DOWN; + + // for scrollable menus + typedef enum e_scrolling_direction + { + SD_UP = 0, + SD_DOWN = 1, + SD_BEGIN = 2, + SD_END = 3 + } EScrollingDirection; protected: - LLMenuGL(const LLMenuGL::Params& p); - friend class LLUICtrlFactory; - // let branching menu items use my protected traversal methods - friend class LLMenuItemBranchGL; + LLMenuGL(const LLMenuGL::Params& p); + friend class LLUICtrlFactory; + // let branching menu items use my protected traversal methods + friend class LLMenuItemBranchGL; public: - virtual ~LLMenuGL( void ); - - void parseChildXML(LLXMLNodePtr child, LLView* parent); - - // LLView Functionality - /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char ); - /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - /*virtual*/ void draw( void ); - /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + virtual ~LLMenuGL( void ); + + void parseChildXML(LLXMLNodePtr child, LLView* parent); + + // LLView Functionality + /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char ); + /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + /*virtual*/ void draw( void ); + /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); /*virtual*/ void deleteAllChildren(); - /*virtual*/ void removeChild( LLView* ctrl); - /*virtual*/ BOOL postBuild(); - - virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - - LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const; - - BOOL clearHoverItem(); - - // return the name label - const std::string& getLabel( void ) const { return mLabel.getString(); } - void setLabel(const LLStringExplicit& label) { mLabel = label; } - - // background colors - void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; } - const LLUIColor& getBackgroundColor() const { return mBackgroundColor; } - void setBackgroundVisible( BOOL b ) { mBgVisible = b; } - void setCanTearOff(BOOL tear_off); - - // add a separator to this menu - virtual BOOL addSeparator(); - - // for branching menu items, bring sub menus up to root level of menu hierarchy - virtual void updateParent( LLView* parentp ); - - // setItemEnabled() - pass the name and the enable flag for a - // menu item. TRUE will make sure it's enabled, FALSE will disable - // it. - void setItemEnabled( const std::string& name, BOOL enable ); - - // propagate message to submenus - void setEnabledSubMenus(BOOL enable); - - void setItemVisible( const std::string& name, BOOL visible); + /*virtual*/ void removeChild( LLView* ctrl); + /*virtual*/ BOOL postBuild(); + + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; + virtual BOOL handleAcceleratorKey(KEY key, MASK mask); + + LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const; + + BOOL clearHoverItem(); + + // return the name label + const std::string& getLabel( void ) const { return mLabel.getString(); } + void setLabel(const LLStringExplicit& label) { mLabel = label; } + + // background colors + void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; } + const LLUIColor& getBackgroundColor() const { return mBackgroundColor; } + void setBackgroundVisible( BOOL b ) { mBgVisible = b; } + void setCanTearOff(BOOL tear_off); + + // add a separator to this menu + virtual BOOL addSeparator(); + + // for branching menu items, bring sub menus up to root level of menu hierarchy + virtual void updateParent( LLView* parentp ); + + // setItemEnabled() - pass the name and the enable flag for a + // menu item. TRUE will make sure it's enabled, FALSE will disable + // it. + void setItemEnabled( const std::string& name, BOOL enable ); + + // propagate message to submenus + void setEnabledSubMenus(BOOL enable); + + void setItemVisible( const std::string& name, BOOL visible); void setItemLabel(const std::string &name, const std::string &label); - - // sets the left,bottom corner of menu, useful for popups - void setLeftAndBottom(S32 left, S32 bottom); - virtual BOOL handleJumpKey(KEY key); + // sets the left,bottom corner of menu, useful for popups + void setLeftAndBottom(S32 left, S32 bottom); - virtual BOOL jumpKeysActive(); + virtual BOOL handleJumpKey(KEY key); - virtual BOOL isOpen(); + virtual BOOL jumpKeysActive(); - void needsArrange() { mNeedsArrange = TRUE; } - // Shape this menu to fit the current state of the children, and - // adjust the child rects to fit. This is called automatically - // when you add items. *FIX: We may need to deal with visibility - // arrangement. - virtual void arrange( void ); - void arrangeAndClear( void ); + virtual BOOL isOpen(); - // remove all items on the menu - void empty( void ); + void needsArrange() { mNeedsArrange = TRUE; } + // Shape this menu to fit the current state of the children, and + // adjust the child rects to fit. This is called automatically + // when you add items. *FIX: We may need to deal with visibility + // arrangement. + virtual void arrange( void ); + void arrangeAndClear( void ); - // erase group of items from menu - void erase( S32 begin, S32 end, bool arrange = true ); + // remove all items on the menu + void empty( void ); - // add new item at position - void insert( S32 begin, LLView * ctrl, bool arrange = true ); + // erase group of items from menu + void erase( S32 begin, S32 end, bool arrange = true ); - void setItemLastSelected(LLMenuItemGL* item); // must be in menu - U32 getItemCount(); // number of menu items - LLMenuItemGL* getItem(S32 number); // 0 = first item + // add new item at position + void insert( S32 begin, LLView * ctrl, bool arrange = true ); + + void setItemLastSelected(LLMenuItemGL* item); // must be in menu + U32 getItemCount(); // number of menu items + LLMenuItemGL* getItem(S32 number); // 0 = first item LLMenuItemGL* getItem(std::string name); - LLMenuItemGL* getHighlightedItem(); + LLMenuItemGL* getHighlightedItem(); + + LLMenuItemGL* highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE); + LLMenuItemGL* highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE); - LLMenuItemGL* highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE); - LLMenuItemGL* highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE); + void buildDrawLabels(); + void createJumpKeys(); - void buildDrawLabels(); - void createJumpKeys(); + // Show popup at a specific location, in the spawn_view's coordinate frame + static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x = 0, S32 mouse_y = 0); - // Show popup at a specific location, in the spawn_view's coordinate frame - static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x = 0, S32 mouse_y = 0); + // Whether to drop shadow menu bar + void setDropShadowed( const BOOL shadowed ); - // Whether to drop shadow menu bar - void setDropShadowed( const BOOL shadowed ); + void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); } + LLMenuItemGL* getParentMenuItem() const { return dynamic_cast(mParentMenuItem.get()); } - void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); } - LLMenuItemGL* getParentMenuItem() const { return dynamic_cast(mParentMenuItem.get()); } + void setTornOff(BOOL torn_off); + BOOL getTornOff() { return mTornOff; } - void setTornOff(BOOL torn_off); - BOOL getTornOff() { return mTornOff; } + BOOL getCanTearOff() { return mTearOffItem != NULL; } - BOOL getCanTearOff() { return mTearOffItem != NULL; } + KEY getJumpKey() const { return mJumpKey; } + void setJumpKey(KEY key) { mJumpKey = key; } - KEY getJumpKey() const { return mJumpKey; } - void setJumpKey(KEY key) { mJumpKey = key; } + static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; } + static BOOL getKeyboardMode() { return sKeyboardMode; } - static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; } - static BOOL getKeyboardMode() { return sKeyboardMode; } + S32 getShortcutPad() { return mShortcutPad; } - S32 getShortcutPad() { return mShortcutPad; } + bool scrollItems(EScrollingDirection direction); + BOOL isScrollable() const { return mScrollable; } - bool scrollItems(EScrollingDirection direction); - BOOL isScrollable() const { return mScrollable; } + static class LLMenuHolderGL* sMenuContainer; - static class LLMenuHolderGL* sMenuContainer; - - void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; } - bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; } + void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; } + bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; } - void setAlwaysShowMenu(BOOL show) { mAlwaysShowMenu = show; } - BOOL getAlwaysShowMenu() { return mAlwaysShowMenu; } + void setAlwaysShowMenu(BOOL show) { mAlwaysShowMenu = show; } + BOOL getAlwaysShowMenu() { return mAlwaysShowMenu; } - // add a context menu branch - BOOL appendContextSubMenu(LLMenuGL *menu); + // add a context menu branch + BOOL appendContextSubMenu(LLMenuGL *menu); const LLFontGL *getFont() const { return mFont; } protected: - void createSpilloverBranch(); - void cleanupSpilloverBranch(); - // Add the menu item to this menu. - virtual BOOL append( LLMenuItemGL* item ); - - // add a menu - this will create a cascading menu - virtual BOOL appendMenu( LLMenuGL* menu ); - - // Used in LLContextMenu and in LLTogleableMenu - // to add an item of context menu branch - bool addContextChild(LLView* view, S32 tab_group); - - // TODO: create accessor methods for these? - typedef std::list< LLMenuItemGL* > item_list_t; - item_list_t mItems; - LLMenuItemGL*mFirstVisibleItem; - LLMenuItemGL *mArrowUpItem, *mArrowDownItem; - - typedef std::map navigation_key_map_t; - navigation_key_map_t mJumpKeys; - S32 mLastMouseX; - S32 mLastMouseY; - S32 mMouseVelX; - S32 mMouseVelY; - U32 mMaxScrollableItems; - U32 mPreferredWidth; - BOOL mHorizontalLayout; - BOOL mScrollable; - BOOL mKeepFixedSize; - BOOL mNeedsArrange; + void createSpilloverBranch(); + void cleanupSpilloverBranch(); + // Add the menu item to this menu. + virtual BOOL append( LLMenuItemGL* item ); + + // add a menu - this will create a cascading menu + virtual BOOL appendMenu( LLMenuGL* menu ); + + // Used in LLContextMenu and in LLTogleableMenu + // to add an item of context menu branch + bool addContextChild(LLView* view, S32 tab_group); + + // TODO: create accessor methods for these? + typedef std::list< LLMenuItemGL* > item_list_t; + item_list_t mItems; + LLMenuItemGL*mFirstVisibleItem; + LLMenuItemGL *mArrowUpItem, *mArrowDownItem; + + typedef std::map navigation_key_map_t; + navigation_key_map_t mJumpKeys; + S32 mLastMouseX; + S32 mLastMouseY; + S32 mMouseVelX; + S32 mMouseVelY; + U32 mMaxScrollableItems; + U32 mPreferredWidth; + BOOL mHorizontalLayout; + BOOL mScrollable; + BOOL mKeepFixedSize; + BOOL mNeedsArrange; // Font for top menu items only const LLFontGL* mFont; @@ -602,27 +602,27 @@ public: private: - static LLColor4 sDefaultBackgroundColor; - static BOOL sKeyboardMode; - - BOOL mAlwaysShowMenu; - - LLUIColor mBackgroundColor; - BOOL mBgVisible; - LLHandle mParentMenuItem; - LLUIString mLabel; - BOOL mDropShadowed; // Whether to drop shadow - bool mHasSelection; - LLFrameTimer mFadeTimer; - LLTimer mScrollItemsTimer; - BOOL mTornOff; - class LLMenuItemTearOffGL* mTearOffItem; - class LLMenuItemBranchGL* mSpilloverBranch; - LLMenuGL* mSpilloverMenu; - KEY mJumpKey; - BOOL mCreateJumpKeys; - S32 mShortcutPad; - bool mResetScrollPositionOnShow; + static LLColor4 sDefaultBackgroundColor; + static BOOL sKeyboardMode; + + BOOL mAlwaysShowMenu; + + LLUIColor mBackgroundColor; + BOOL mBgVisible; + LLHandle mParentMenuItem; + LLUIString mLabel; + BOOL mDropShadowed; // Whether to drop shadow + bool mHasSelection; + LLFrameTimer mFadeTimer; + LLTimer mScrollItemsTimer; + BOOL mTornOff; + class LLMenuItemTearOffGL* mTearOffItem; + class LLMenuItemBranchGL* mSpilloverBranch; + LLMenuGL* mSpilloverMenu; + KEY mJumpKey; + BOOL mCreateJumpKeys; + S32 mShortcutPad; + bool mResetScrollPositionOnShow; }; // end class LLMenuGL @@ -637,61 +637,61 @@ private: class LLMenuItemBranchGL : public LLMenuItemGL { public: - struct Params : public LLInitParam::Block - { - Optional branch; - }; + struct Params : public LLInitParam::Block + { + Optional branch; + }; protected: - LLMenuItemBranchGL(const Params&); - friend class LLUICtrlFactory; + LLMenuItemBranchGL(const Params&); + friend class LLUICtrlFactory; public: - virtual ~LLMenuItemBranchGL(); - - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual ~LLMenuItemBranchGL(); - virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - // check if we've used these accelerators already - virtual BOOL addToAcceleratorList(std::list *listp); + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; + virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - // called to rebuild the draw label - virtual void buildDrawLabel( void ); + // check if we've used these accelerators already + virtual BOOL addToAcceleratorList(std::list *listp); - virtual void onCommit( void ); + // called to rebuild the draw label + virtual void buildDrawLabel( void ); - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + virtual void onCommit( void ); - // set the hover status (called by it's menu) and if the object is - // active. This is used for behavior transfer. - virtual void setHighlight( BOOL highlight ); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); - virtual BOOL handleKeyHere(KEY key, MASK mask); + // set the hover status (called by it's menu) and if the object is + // active. This is used for behavior transfer. + virtual void setHighlight( BOOL highlight ); - virtual BOOL isActive() const; + virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL isOpen() const; + virtual BOOL isActive() const; - LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); } + virtual BOOL isOpen() const; - virtual void updateBranchParent( LLView* parentp ); + LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); } - // LLView Functionality - virtual void onVisibilityChange( BOOL curVisibilityIn ); + virtual void updateBranchParent( LLView* parentp ); - virtual void draw(); + // LLView Functionality + virtual void onVisibilityChange( BOOL curVisibilityIn ); - virtual void setEnabledSubMenus(BOOL enabled) { if (getBranch()) getBranch()->setEnabledSubMenus(enabled); } + virtual void draw(); - virtual void openMenu(); + virtual void setEnabledSubMenus(BOOL enabled) { if (getBranch()) getBranch()->setEnabledSubMenus(enabled); } - virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const; - virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const; + virtual void openMenu(); + + virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const; + virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const; private: - LLHandle mBranchHandle; + LLHandle mBranchHandle; }; // end class LLMenuItemBranchGL @@ -704,44 +704,44 @@ class LLContextMenu : public LLMenuGL { public: - struct Params : public LLInitParam::Block - { - Params() - { - changeDefault(visible, false); - } - }; + struct Params : public LLInitParam::Block + { + Params() + { + changeDefault(visible, false); + } + }; protected: - LLContextMenu(const Params& p); - friend class LLUICtrlFactory; + LLContextMenu(const Params& p); + friend class LLUICtrlFactory; public: - virtual ~LLContextMenu() {} + virtual ~LLContextMenu() {} + + // LLView Functionality + // can't set visibility directly, must call show or hide + virtual void setVisible (BOOL visible); - // LLView Functionality - // can't set visibility directly, must call show or hide - virtual void setVisible (BOOL visible); - - virtual void show (S32 x, S32 y, LLView* spawning_view = NULL); - virtual void hide (); + virtual void show (S32 x, S32 y, LLView* spawning_view = NULL); + virtual void hide (); - virtual BOOL handleHover ( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseUp ( S32 x, S32 y, MASK mask ); + virtual BOOL handleHover ( S32 x, S32 y, MASK mask ); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleRightMouseUp ( S32 x, S32 y, MASK mask ); - virtual bool addChild (LLView* view, S32 tab_group = 0); + virtual bool addChild (LLView* view, S32 tab_group = 0); - LLHandle getHandle() { return getDerivedHandle(); } + LLHandle getHandle() { return getDerivedHandle(); } - LLView* getSpawningView() const { return mSpawningViewHandle.get(); } - void setSpawningView(LLHandle spawning_view) { mSpawningViewHandle = spawning_view; } + LLView* getSpawningView() const { return mSpawningViewHandle.get(); } + void setSpawningView(LLHandle spawning_view) { mSpawningViewHandle = spawning_view; } protected: - BOOL mHoveredAnyItem; - LLMenuItemGL* mHoverItem; - LLRootHandle mHandle; - LLHandle mSpawningViewHandle; + BOOL mHoveredAnyItem; + LLMenuItemGL* mHoverItem; + LLRootHandle mHandle; + LLHandle mSpawningViewHandle; }; //----------------------------------------------------------------------------- @@ -751,28 +751,28 @@ protected: class LLContextMenuBranch : public LLMenuItemGL { public: - struct Params : public LLInitParam::Block - { - Mandatory branch; - }; + struct Params : public LLInitParam::Block + { + Mandatory branch; + }; - LLContextMenuBranch(const Params&); + LLContextMenuBranch(const Params&); - virtual ~LLContextMenuBranch(); + virtual ~LLContextMenuBranch(); - // called to rebuild the draw label - virtual void buildDrawLabel( void ); + // called to rebuild the draw label + virtual void buildDrawLabel( void ); - // onCommit() - do the primary funcationality of the menu item. - virtual void onCommit( void ); + // onCommit() - do the primary funcationality of the menu item. + virtual void onCommit( void ); - LLContextMenu* getBranch() { return mBranch.get(); } - void setHighlight( BOOL highlight ); + LLContextMenu* getBranch() { return mBranch.get(); } + void setHighlight( BOOL highlight ); protected: - void showSubMenu(); + void showSubMenu(); - LLHandle mBranch; + LLHandle mBranch; }; @@ -785,42 +785,42 @@ protected: class LLMenuBarGL : public LLMenuGL { public: - struct Params : public LLInitParam::Block - {}; - LLMenuBarGL( const Params& p ); - virtual ~LLMenuBarGL(); + struct Params : public LLInitParam::Block + {}; + LLMenuBarGL( const Params& p ); + virtual ~LLMenuBarGL(); - /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - /*virtual*/ BOOL handleJumpKey(KEY key); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + /*virtual*/ BOOL handleJumpKey(KEY key); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ void draw(); - /*virtual*/ BOOL jumpKeysActive(); + /*virtual*/ void draw(); + /*virtual*/ BOOL jumpKeysActive(); - // add a vertical separator to this menu - virtual BOOL addSeparator(); + // add a vertical separator to this menu + virtual BOOL addSeparator(); - // LLView Functionality - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + // LLView Functionality + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - // Returns x position of rightmost child, usually Help menu - S32 getRightmostMenuEdge(); + // Returns x position of rightmost child, usually Help menu + S32 getRightmostMenuEdge(); - void resetMenuTrigger() { mAltKeyTrigger = FALSE; } + void resetMenuTrigger() { mAltKeyTrigger = FALSE; } private: - // add a menu - this will create a drop down menu. - virtual BOOL appendMenu( LLMenuGL* menu ); - // rearrange the child rects so they fit the shape of the menu - // bar. - virtual void arrange( void ); + // add a menu - this will create a drop down menu. + virtual BOOL appendMenu( LLMenuGL* menu ); + // rearrange the child rects so they fit the shape of the menu + // bar. + virtual void arrange( void ); - void checkMenuTrigger(); + void checkMenuTrigger(); - std::list mAccelerators; - BOOL mAltKeyTrigger; + std::list mAccelerators; + BOOL mAltKeyTrigger; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -831,39 +831,39 @@ private: class LLMenuHolderGL : public LLPanel { public: - struct Params : public LLInitParam::Block - {}; - LLMenuHolderGL(const Params& p); - virtual ~LLMenuHolderGL() {} + struct Params : public LLInitParam::Block + {}; + LLMenuHolderGL(const Params& p); + virtual ~LLMenuHolderGL() {} - virtual BOOL hideMenus(); - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - void setCanHide(BOOL can_hide) { mCanHide = can_hide; } + virtual BOOL hideMenus(); + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + void setCanHide(BOOL can_hide) { mCanHide = can_hide; } - // LLView functionality - virtual void draw(); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + // LLView functionality + virtual void draw(); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - // Close context menus on right mouse up not handled by menus. - /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask ); + // Close context menus on right mouse up not handled by menus. + /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual const LLRect getMenuRect() const { return getLocalRect(); } - LLView*const getVisibleMenu() const; - virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual const LLRect getMenuRect() const { return getLocalRect(); } + LLView*const getVisibleMenu() const; + virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} - static void setActivatedItem(LLMenuItemGL* item); + static void setActivatedItem(LLMenuItemGL* item); - // Need to detect if mouse-up after context menu spawn has moved. - // If not, need to keep the menu up. - static LLCoordGL sContextMenuSpawnPos; + // Need to detect if mouse-up after context menu spawn has moved. + // If not, need to keep the menu up. + static LLCoordGL sContextMenuSpawnPos; private: - static LLHandle sItemLastSelectedHandle; - static LLFrameTimer sItemActivationTimer; + static LLHandle sItemLastSelectedHandle; + static LLFrameTimer sItemActivationTimer; - BOOL mCanHide; + BOOL mCanHide; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -875,26 +875,26 @@ private: class LLTearOffMenu : public LLFloater { public: - static LLTearOffMenu* create(LLMenuGL* menup); - virtual ~LLTearOffMenu(); + static LLTearOffMenu* create(LLMenuGL* menup); + virtual ~LLTearOffMenu(); - virtual void draw(void); - virtual void onFocusReceived(); - virtual void onFocusLost(); - virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); - virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual void translate(S32 x, S32 y); + virtual void draw(void); + virtual void onFocusReceived(); + virtual void onFocusLost(); + virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual void translate(S32 x, S32 y); - void updateSize(); + void updateSize(); private: - LLTearOffMenu(LLMenuGL* menup); - - void closeTearOff(); - - LLView* mOldParent; - LLMenuGL* mMenu; - S32 mTargetHeight; + LLTearOffMenu(LLMenuGL* menup); + + void closeTearOff(); + + LLView* mOldParent; + LLMenuGL* mMenu; + S32 mTargetHeight; bool mQuitRequested; }; @@ -907,16 +907,16 @@ private: class LLMenuItemTearOffGL : public LLMenuItemGL { public: - struct Params : public LLInitParam::Block - {}; + struct Params : public LLInitParam::Block + {}; + + LLMenuItemTearOffGL( const Params& ); - LLMenuItemTearOffGL( const Params& ); - - virtual void onCommit(void); - virtual void draw(void); - virtual U32 getNominalHeight() const; + virtual void onCommit(void); + virtual void draw(void); + virtual U32 getNominalHeight() const; - LLFloater* getParentFloater(); + LLFloater* getParentFloater(); }; @@ -924,13 +924,13 @@ public: class LLEditMenuHandlerMgr { public: - LLEditMenuHandlerMgr& getInstance() { - static LLEditMenuHandlerMgr instance; - return instance; - } - virtual ~LLEditMenuHandlerMgr() {} + LLEditMenuHandlerMgr& getInstance() { + static LLEditMenuHandlerMgr instance; + return instance; + } + virtual ~LLEditMenuHandlerMgr() {} private: - LLEditMenuHandlerMgr() {}; + LLEditMenuHandlerMgr() {}; }; @@ -939,40 +939,40 @@ private: class view_listener_t : public boost::signals2::trackable { public: - virtual bool handleEvent(const LLSD& userdata) = 0; - view_listener_t() { sListeners.insert(this); } - virtual ~view_listener_t() { sListeners.erase(this); } - - static void addEnable(view_listener_t* listener, const std::string& name) - { - LLUICtrl::EnableCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2)); - } - - static void addCommit(view_listener_t* listener, const std::string& name) - { - LLUICtrl::CommitCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2)); - } - - static void addMenu(view_listener_t* listener, const std::string& name) - { - // For now, add to both click and enable registries - addEnable(listener, name); - addCommit(listener, name); - } - - static void cleanup() - { - listener_vector_t listeners(sListeners.begin(), sListeners.end()); - sListeners.clear(); - - std::for_each(listeners.begin(), listeners.end(), DeletePointer()); - listeners.clear(); - } + virtual bool handleEvent(const LLSD& userdata) = 0; + view_listener_t() { sListeners.insert(this); } + virtual ~view_listener_t() { sListeners.erase(this); } + + static void addEnable(view_listener_t* listener, const std::string& name) + { + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2)); + } + + static void addCommit(view_listener_t* listener, const std::string& name) + { + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2)); + } + + static void addMenu(view_listener_t* listener, const std::string& name) + { + // For now, add to both click and enable registries + addEnable(listener, name); + addCommit(listener, name); + } + + static void cleanup() + { + listener_vector_t listeners(sListeners.begin(), sListeners.end()); + sListeners.clear(); + + std::for_each(listeners.begin(), listeners.end(), DeletePointer()); + listeners.clear(); + } private: - typedef std::set listener_map_t; - typedef std::vector listener_vector_t; - static listener_map_t sListeners; + typedef std::set listener_map_t; + typedef std::vector listener_vector_t; + static listener_map_t sListeners; }; #endif // LL_LLMENUGL_H diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 3e5978eb59..b2be33b266 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmodaldialog.cpp * @brief LLModalDialog base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,77 +39,77 @@ std::list LLModalDialog::sModalStack; LLModalDialog::LLModalDialog( const LLSD& key, BOOL modal ) - : LLFloater(key), - mModal( modal ) + : LLFloater(key), + mModal( modal ) { - if (modal) - { - setCanMinimize(FALSE); - setCanClose(FALSE); - } - setVisible( FALSE ); - setBackgroundVisible(TRUE); - setBackgroundOpaque(TRUE); - centerOnScreen(); // default position - mCloseSignal.connect(boost::bind(&LLModalDialog::stopModal, this)); + if (modal) + { + setCanMinimize(FALSE); + setCanClose(FALSE); + } + setVisible( FALSE ); + setBackgroundVisible(TRUE); + setBackgroundOpaque(TRUE); + centerOnScreen(); // default position + mCloseSignal.connect(boost::bind(&LLModalDialog::stopModal, this)); } LLModalDialog::~LLModalDialog() { - // don't unlock focus unless we have it - if (gFocusMgr.childHasKeyboardFocus(this)) - { - gFocusMgr.unlockFocus(); - } - - std::list::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); - if (iter != sModalStack.end()) - { - LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL; - } + // don't unlock focus unless we have it + if (gFocusMgr.childHasKeyboardFocus(this)) + { + gFocusMgr.unlockFocus(); + } + + std::list::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); + if (iter != sModalStack.end()) + { + LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL; + } } // virtual BOOL LLModalDialog::postBuild() { - return LLFloater::postBuild(); + return LLFloater::postBuild(); } // virtual void LLModalDialog::openFloater(const LLSD& key) { - // SJB: Hack! Make sure we don't ever host a modal dialog - LLMultiFloater* thost = LLFloater::getFloaterHost(); - LLFloater::setFloaterHost(NULL); - LLFloater::openFloater(key); - LLFloater::setFloaterHost(thost); + // SJB: Hack! Make sure we don't ever host a modal dialog + LLMultiFloater* thost = LLFloater::getFloaterHost(); + LLFloater::setFloaterHost(NULL); + LLFloater::openFloater(key); + LLFloater::setFloaterHost(thost); } void LLModalDialog::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLFloater::reshape(width, height, called_from_parent); - centerOnScreen(); + LLFloater::reshape(width, height, called_from_parent); + centerOnScreen(); } // virtual void LLModalDialog::onOpen(const LLSD& key) { - if (mModal) - { - // If Modal, Hide the active modal dialog - if (!sModalStack.empty()) - { - LLModalDialog* front = sModalStack.front(); + if (mModal) + { + // If Modal, Hide the active modal dialog + if (!sModalStack.empty()) + { + LLModalDialog* front = sModalStack.front(); if (front != this) { front->setVisible(FALSE); } - } - - // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( this ); - LLUI::getInstance()->addPopup(this); - setFocus(TRUE); + } + + // This is a modal dialog. It sucks up all mouse and keyboard operations. + gFocusMgr.setMouseCapture( this ); + LLUI::getInstance()->addPopup(this); + setFocus(TRUE); std::list::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); if (iter != sModalStack.end()) @@ -119,229 +119,229 @@ void LLModalDialog::onOpen(const LLSD& key) } sModalStack.push_front(this); - } + } } void LLModalDialog::stopModal() { - gFocusMgr.unlockFocus(); - gFocusMgr.releaseFocusIfNeeded( this ); - - if (mModal) - { - std::list::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); - if (iter != sModalStack.end()) - { - sModalStack.erase(iter); - } - else - { - LL_WARNS() << "LLModalDialog::stopModal not in list!" << LL_ENDL; - } - } - if (!sModalStack.empty()) - { - LLModalDialog* front = sModalStack.front(); - front->setVisible(TRUE); - } + gFocusMgr.unlockFocus(); + gFocusMgr.releaseFocusIfNeeded( this ); + + if (mModal) + { + std::list::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); + if (iter != sModalStack.end()) + { + sModalStack.erase(iter); + } + else + { + LL_WARNS() << "LLModalDialog::stopModal not in list!" << LL_ENDL; + } + } + if (!sModalStack.empty()) + { + LLModalDialog* front = sModalStack.front(); + front->setVisible(TRUE); + } } void LLModalDialog::setVisible( BOOL visible ) { - if (mModal) - { - if( visible ) - { - // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( this ); - - // The dialog view is a root view - LLUI::getInstance()->addPopup(this); - setFocus( TRUE ); - } - else - { - gFocusMgr.releaseFocusIfNeeded( this ); - } - } - - LLFloater::setVisible( visible ); + if (mModal) + { + if( visible ) + { + // This is a modal dialog. It sucks up all mouse and keyboard operations. + gFocusMgr.setMouseCapture( this ); + + // The dialog view is a root view + LLUI::getInstance()->addPopup(this); + setFocus( TRUE ); + } + else + { + gFocusMgr.releaseFocusIfNeeded( this ); + } + } + + LLFloater::setVisible( visible ); } BOOL LLModalDialog::handleMouseDown(S32 x, S32 y, MASK mask) { - LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); - if (popup_menu != NULL) - { - S32 mx, my; - LLUI::getInstance()->getMousePositionScreen(&mx, &my); - LLRect menu_screen_rc = popup_menu->calcScreenRect(); - if(!menu_screen_rc.pointInRect(mx, my)) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - } - - if (mModal) - { - if (!LLFloater::handleMouseDown(x, y, mask)) - { - // Click was outside the panel - make_ui_sound("UISndInvalidOp"); - } - } - else - { - LLFloater::handleMouseDown(x, y, mask); - } - - - return TRUE; + LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); + if (popup_menu != NULL) + { + S32 mx, my; + LLUI::getInstance()->getMousePositionScreen(&mx, &my); + LLRect menu_screen_rc = popup_menu->calcScreenRect(); + if(!menu_screen_rc.pointInRect(mx, my)) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + } + + if (mModal) + { + if (!LLFloater::handleMouseDown(x, y, mask)) + { + // Click was outside the panel + make_ui_sound("UISndInvalidOp"); + } + } + else + { + LLFloater::handleMouseDown(x, y, mask); + } + + + return TRUE; } -BOOL LLModalDialog::handleHover(S32 x, S32 y, MASK mask) -{ - if( childrenHandleHover(x, y, mask) == NULL ) - { - getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << LL_ENDL; - } - - LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); - if (popup_menu != NULL) - { - S32 mx, my; - LLUI::getInstance()->getMousePositionScreen(&mx, &my); - LLRect menu_screen_rc = popup_menu->calcScreenRect(); - if(menu_screen_rc.pointInRect(mx, my)) - { - S32 local_x = mx - popup_menu->getRect().mLeft; - S32 local_y = my - popup_menu->getRect().mBottom; - popup_menu->handleHover(local_x, local_y, mask); - gFocusMgr.setMouseCapture(NULL); - } - } - - return TRUE; +BOOL LLModalDialog::handleHover(S32 x, S32 y, MASK mask) +{ + if( childrenHandleHover(x, y, mask) == NULL ) + { + getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << LL_ENDL; + } + + LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); + if (popup_menu != NULL) + { + S32 mx, my; + LLUI::getInstance()->getMousePositionScreen(&mx, &my); + LLRect menu_screen_rc = popup_menu->calcScreenRect(); + if(menu_screen_rc.pointInRect(mx, my)) + { + S32 local_x = mx - popup_menu->getRect().mLeft; + S32 local_y = my - popup_menu->getRect().mBottom; + popup_menu->handleHover(local_x, local_y, mask); + gFocusMgr.setMouseCapture(NULL); + } + } + + return TRUE; } BOOL LLModalDialog::handleMouseUp(S32 x, S32 y, MASK mask) { - childrenHandleMouseUp(x, y, mask); - return TRUE; + childrenHandleMouseUp(x, y, mask); + return TRUE; } BOOL LLModalDialog::handleScrollWheel(S32 x, S32 y, S32 clicks) { - childrenHandleScrollWheel(x, y, clicks); - return TRUE; + childrenHandleScrollWheel(x, y, clicks); + return TRUE; } BOOL LLModalDialog::handleDoubleClick(S32 x, S32 y, MASK mask) { - if (!LLFloater::handleDoubleClick(x, y, mask)) - { - // Click outside the panel - make_ui_sound("UISndInvalidOp"); - } - return TRUE; + if (!LLFloater::handleDoubleClick(x, y, mask)) + { + // Click outside the panel + make_ui_sound("UISndInvalidOp"); + } + return TRUE; } BOOL LLModalDialog::handleRightMouseDown(S32 x, S32 y, MASK mask) { - LLMenuGL::sMenuContainer->hideMenus(); - childrenHandleRightMouseDown(x, y, mask); - return TRUE; + LLMenuGL::sMenuContainer->hideMenus(); + childrenHandleRightMouseDown(x, y, mask); + return TRUE; } BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask ) { - LLFloater::handleKeyHere(key, mask ); - - if (mModal) - { - // Suck up all keystokes except CTRL-Q. - BOOL is_quit = ('Q' == key) && (MASK_CONTROL == mask); - return !is_quit; - } - else - { - // don't process escape key until message box has been on screen a minimal amount of time - // to avoid accidentally destroying the message box when user is hitting escape at the time it appears - BOOL enough_time_elapsed = mVisibleTime.getElapsedTimeF32() > 1.0f; - if (enough_time_elapsed && key == KEY_ESCAPE) - { - closeFloater(); - return TRUE; - } - return FALSE; - } + LLFloater::handleKeyHere(key, mask ); + + if (mModal) + { + // Suck up all keystokes except CTRL-Q. + BOOL is_quit = ('Q' == key) && (MASK_CONTROL == mask); + return !is_quit; + } + else + { + // don't process escape key until message box has been on screen a minimal amount of time + // to avoid accidentally destroying the message box when user is hitting escape at the time it appears + BOOL enough_time_elapsed = mVisibleTime.getElapsedTimeF32() > 1.0f; + if (enough_time_elapsed && key == KEY_ESCAPE) + { + closeFloater(); + return TRUE; + } + return FALSE; + } } // virtual void LLModalDialog::draw() { - static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow"); - static LLUICachedControl shadow_lines ("DropShadowFloater", 0); + static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow"); + static LLUICachedControl shadow_lines ("DropShadowFloater", 0); + + gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0, + shadow_color, shadow_lines); - gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0, - shadow_color, shadow_lines); + LLFloater::draw(); - LLFloater::draw(); - - // Focus retrieval moved to LLFloaterView::refresh() + // Focus retrieval moved to LLFloaterView::refresh() } void LLModalDialog::centerOnScreen() { - LLVector2 window_size = LLUI::getInstance()->getWindowSize(); - centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); + LLVector2 window_size = LLUI::getInstance()->getWindowSize(); + centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); } -// static +// static void LLModalDialog::onAppFocusLost() { - if( !sModalStack.empty() ) - { - LLModalDialog* instance = LLModalDialog::sModalStack.front(); - if( gFocusMgr.childHasMouseCapture( instance ) ) - { - gFocusMgr.setMouseCapture( NULL ); - } - - instance->setFocus(FALSE); - } + if( !sModalStack.empty() ) + { + LLModalDialog* instance = LLModalDialog::sModalStack.front(); + if( gFocusMgr.childHasMouseCapture( instance ) ) + { + gFocusMgr.setMouseCapture( NULL ); + } + + instance->setFocus(FALSE); + } } -// static +// static void LLModalDialog::onAppFocusGained() { - if( !sModalStack.empty() ) - { - LLModalDialog* instance = LLModalDialog::sModalStack.front(); + if( !sModalStack.empty() ) + { + LLModalDialog* instance = LLModalDialog::sModalStack.front(); - // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( instance ); - instance->setFocus(TRUE); - LLUI::getInstance()->addPopup(instance); + // This is a modal dialog. It sucks up all mouse and keyboard operations. + gFocusMgr.setMouseCapture( instance ); + instance->setFocus(TRUE); + LLUI::getInstance()->addPopup(instance); - instance->centerOnScreen(); - } + instance->centerOnScreen(); + } } void LLModalDialog::shutdownModals() { - // This method is only for use during app shutdown. ~LLModalDialog() - // checks sModalStack, and if the dialog instance is still there, it - // crumps with "Attempt to delete dialog while still in sModalStack!" But - // at app shutdown, all bets are off. If the user asks to shut down the - // app, we shouldn't have to care WHAT's open. Put differently, if a modal - // dialog is so crucial that we can't let the user terminate until s/he - // addresses it, we should reject a termination request. The current state - // of affairs is that we accept it, but then produce an LL_ERRS() popup that - // simply makes our software look unreliable. - sModalStack.clear(); + // This method is only for use during app shutdown. ~LLModalDialog() + // checks sModalStack, and if the dialog instance is still there, it + // crumps with "Attempt to delete dialog while still in sModalStack!" But + // at app shutdown, all bets are off. If the user asks to shut down the + // app, we shouldn't have to care WHAT's open. Put differently, if a modal + // dialog is so crucial that we can't let the user terminate until s/he + // addresses it, we should reject a termination request. The current state + // of affairs is that we accept it, but then produce an LL_ERRS() popup that + // simply makes our software look unreliable. + sModalStack.clear(); } diff --git a/indra/llui/llmodaldialog.h b/indra/llui/llmodaldialog.h index f81273b96a..bf729c61bf 100644 --- a/indra/llui/llmodaldialog.h +++ b/indra/llui/llmodaldialog.h @@ -1,25 +1,25 @@ -/** +/** * @file llmodaldialog.h * @brief LLModalDialog base class * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,45 +39,45 @@ class LLModalDialog; class LLModalDialog : public LLFloater { public: - LLModalDialog( const LLSD& key, BOOL modal = true ); - virtual ~LLModalDialog(); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void openFloater(const LLSD& key = LLSD()); - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); - - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void draw(); - - BOOL isModal() const { return mModal; } - void stopModal(); - - static void onAppFocusLost(); - static void onAppFocusGained(); - - static S32 activeCount() { return sModalStack.size(); } - static void shutdownModals(); + LLModalDialog( const LLSD& key, BOOL modal = true ); + virtual ~LLModalDialog(); + + /*virtual*/ BOOL postBuild(); + + /*virtual*/ void openFloater(const LLSD& key = LLSD()); + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); + + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void draw(); + + BOOL isModal() const { return mModal; } + void stopModal(); + + static void onAppFocusLost(); + static void onAppFocusGained(); + + static S32 activeCount() { return sModalStack.size(); } + static void shutdownModals(); protected: - void centerOnScreen(); + void centerOnScreen(); private: - - LLFrameTimer mVisibleTime; - const BOOL mModal; - static std::list sModalStack; // Top of stack is currently being displayed + LLFrameTimer mVisibleTime; + const BOOL mModal; + + static std::list sModalStack; // Top of stack is currently being displayed }; #endif // LL_LLMODALDIALOG_H diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index d1a597511e..17f24a0f87 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmultifloater.cpp * @brief LLFloater that hosts other floaters * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,91 +37,91 @@ // LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) - : LLFloater(key), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(TRUE), - mOrigMinWidth(params.min_width), - mOrigMinHeight(params.min_height) + : LLFloater(key), + mTabContainer(NULL), + mTabPos(LLTabContainer::TOP), + mAutoResize(TRUE), + mOrigMinWidth(params.min_width), + mOrigMinHeight(params.min_height) { } void LLMultiFloater::buildTabContainer() { - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - - LLTabContainer::Params p; - p.name(std::string("Preview Tabs")); - p.rect(LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - floater_header_size, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0)); - p.tab_position(mTabPos); - p.follows.flags(FOLLOWS_ALL); - p.commit_callback.function(boost::bind(&LLMultiFloater::onTabSelected, this)); - - mTabContainer = LLUICtrlFactory::create(p); - addChild(mTabContainer); - - if (isResizable()) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + + LLTabContainer::Params p; + p.name(std::string("Preview Tabs")); + p.rect(LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - floater_header_size, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0)); + p.tab_position(mTabPos); + p.follows.flags(FOLLOWS_ALL); + p.commit_callback.function(boost::bind(&LLMultiFloater::onTabSelected, this)); + + mTabContainer = LLUICtrlFactory::create(p); + addChild(mTabContainer); + + if (isResizable()) + { + mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); + } } void LLMultiFloater::onClose(bool app_quitting) { - if(isMinimized()) - { - setMinimized(FALSE); - } - LLFloater::onClose(app_quitting); + if(isMinimized()) + { + setMinimized(FALSE); + } + LLFloater::onClose(app_quitting); } void LLMultiFloater::draw() { - if (mTabContainer->getTabCount() == 0) - { - //RN: could this potentially crash in draw hierarchy? - closeFloater(); - } - else - { - LLFloater::draw(); - } + if (mTabContainer->getTabCount() == 0) + { + //RN: could this potentially crash in draw hierarchy? + closeFloater(); + } + else + { + LLFloater::draw(); + } } BOOL LLMultiFloater::closeAllFloaters() { - S32 tabToClose = 0; - S32 lastTabCount = mTabContainer->getTabCount(); - while (tabToClose < mTabContainer->getTabCount()) - { - LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose); - first_floater->closeFloater(); - if(lastTabCount == mTabContainer->getTabCount()) - { - //Tab did not actually close, possibly due to a pending Save Confirmation dialog.. - //so try and close the next one in the list... - tabToClose++; - } - else - { - //Tab closed ok. - lastTabCount = mTabContainer->getTabCount(); - } - } - if( mTabContainer->getTabCount() != 0 ) - return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE. - return TRUE; //else all tabs were successfully closed... + S32 tabToClose = 0; + S32 lastTabCount = mTabContainer->getTabCount(); + while (tabToClose < mTabContainer->getTabCount()) + { + LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose); + first_floater->closeFloater(); + if(lastTabCount == mTabContainer->getTabCount()) + { + //Tab did not actually close, possibly due to a pending Save Confirmation dialog.. + //so try and close the next one in the list... + tabToClose++; + } + else + { + //Tab closed ok. + lastTabCount = mTabContainer->getTabCount(); + } + } + if( mTabContainer->getTabCount() != 0 ) + return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE. + return TRUE; //else all tabs were successfully closed... } void LLMultiFloater::growToFit(S32 content_width, S32 content_height) { - static LLUICachedControl tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; - S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2); - S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height); + static LLUICachedControl tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; + S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2); + S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height); if (isMinimized()) { @@ -129,13 +129,13 @@ void LLMultiFloater::growToFit(S32 content_width, S32 content_height) newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height); setExpandedRect(newrect); } - else - { - S32 old_height = getRect().getHeight(); - reshape(new_width, new_height); - // keep top left corner in same position - translate(0, old_height - new_height); - } + else + { + S32 old_height = getRect().getHeight(); + reshape(new_width, new_height); + // keep top left corner in same position + translate(0, old_height - new_height); + } } /** @@ -151,372 +151,372 @@ void LLMultiFloater::growToFit(S32 content_width, S32 content_height) **/ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) { - if (!floaterp) - { - return; - } - - if (!mTabContainer) - { - LL_ERRS() << "Tab Container used without having been initialized." << LL_ENDL; - return; - } - - if (floaterp->getHost() == this) - { - // already hosted by me, remove - // do this so we get updated title, etc. - mFloaterDataMap.erase(floaterp->getHandle()); - mTabContainer->removeTabPanel(floaterp); - } - else if (floaterp->getHost()) - { - // floaterp is hosted by somebody else and - // this is adding it, so remove it from its old host - floaterp->getHost()->removeFloater(floaterp); - } - else if (floaterp->getParent() == gFloaterView) - { - // rehost preview floater as child panel - gFloaterView->removeChild(floaterp); - } - - // store original configuration - LLFloaterData floater_data; - floater_data.mWidth = floaterp->getRect().getWidth(); - floater_data.mHeight = floaterp->getRect().getHeight(); - floater_data.mCanMinimize = floaterp->isMinimizeable(); - floater_data.mCanResize = floaterp->isResizable(); + if (!floaterp) + { + return; + } + + if (!mTabContainer) + { + LL_ERRS() << "Tab Container used without having been initialized." << LL_ENDL; + return; + } + + if (floaterp->getHost() == this) + { + // already hosted by me, remove + // do this so we get updated title, etc. + mFloaterDataMap.erase(floaterp->getHandle()); + mTabContainer->removeTabPanel(floaterp); + } + else if (floaterp->getHost()) + { + // floaterp is hosted by somebody else and + // this is adding it, so remove it from its old host + floaterp->getHost()->removeFloater(floaterp); + } + else if (floaterp->getParent() == gFloaterView) + { + // rehost preview floater as child panel + gFloaterView->removeChild(floaterp); + } + + // store original configuration + LLFloaterData floater_data; + floater_data.mWidth = floaterp->getRect().getWidth(); + floater_data.mHeight = floaterp->getRect().getHeight(); + floater_data.mCanMinimize = floaterp->isMinimizeable(); + floater_data.mCanResize = floaterp->isResizable(); floater_data.mSaveRect = floaterp->mSaveRect; - // remove minimize and close buttons - floaterp->setCanMinimize(FALSE); - floaterp->setCanResize(FALSE); - floaterp->setCanDrag(FALSE); - floaterp->mSaveRect = FALSE; - floaterp->storeRectControl(); - // avoid double rendering of floater background (makes it more opaque) - floaterp->setBackgroundVisible(FALSE); - - if (mAutoResize) - { - growToFit(floater_data.mWidth, floater_data.mHeight); - } - - //add the panel, add it to proper maps - mTabContainer->addTabPanel( - LLTabContainer::TabPanelParams() - .panel(floaterp) - .label(floaterp->getShortTitle()) - .insert_at(insertion_point)); - mFloaterDataMap[floaterp->getHandle()] = floater_data; - - updateResizeLimits(); - - if ( select_added_floater ) - { - mTabContainer->selectTabPanel(floaterp); - } - else - { - // reassert visible tab (hiding new floater if necessary) - mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); - } - - floaterp->setHost(this); - if (isMinimized()) - { - floaterp->setVisible(FALSE); - } - - // Tabs sometimes overlap resize handle - moveResizeHandlesToFront(); + // remove minimize and close buttons + floaterp->setCanMinimize(FALSE); + floaterp->setCanResize(FALSE); + floaterp->setCanDrag(FALSE); + floaterp->mSaveRect = FALSE; + floaterp->storeRectControl(); + // avoid double rendering of floater background (makes it more opaque) + floaterp->setBackgroundVisible(FALSE); + + if (mAutoResize) + { + growToFit(floater_data.mWidth, floater_data.mHeight); + } + + //add the panel, add it to proper maps + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams() + .panel(floaterp) + .label(floaterp->getShortTitle()) + .insert_at(insertion_point)); + mFloaterDataMap[floaterp->getHandle()] = floater_data; + + updateResizeLimits(); + + if ( select_added_floater ) + { + mTabContainer->selectTabPanel(floaterp); + } + else + { + // reassert visible tab (hiding new floater if necessary) + mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); + } + + floaterp->setHost(this); + if (isMinimized()) + { + floaterp->setVisible(FALSE); + } + + // Tabs sometimes overlap resize handle + moveResizeHandlesToFront(); } void LLMultiFloater::updateFloaterTitle(LLFloater* floaterp) { - S32 index = mTabContainer->getIndexForPanel(floaterp); - if (index != -1) - { - mTabContainer->setPanelTitle(index, floaterp->getShortTitle()); - } + S32 index = mTabContainer->getIndexForPanel(floaterp); + if (index != -1) + { + mTabContainer->setPanelTitle(index, floaterp->getShortTitle()); + } } /** - BOOL selectFloater(LLFloater* floaterp) + BOOL selectFloater(LLFloater* floaterp) - If the LLFloater pointed to by floaterp is hosted by this, - then its tab is selected and returns true. Otherwise returns false. + If the LLFloater pointed to by floaterp is hosted by this, + then its tab is selected and returns true. Otherwise returns false. - Affects: mTabContainer + Affects: mTabContainer **/ BOOL LLMultiFloater::selectFloater(LLFloater* floaterp) { - return mTabContainer->selectTabPanel(floaterp); + return mTabContainer->selectTabPanel(floaterp); } // virtual void LLMultiFloater::selectNextFloater() { - mTabContainer->selectNextTab(); + mTabContainer->selectNextTab(); } // virtual void LLMultiFloater::selectPrevFloater() { - mTabContainer->selectPrevTab(); + mTabContainer->selectPrevTab(); } void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point) { - if(!floaterp) return; - // we won't select a panel that already is selected - // it is hard to do this internally to tab container - // as tab selection is handled via index and the tab at a given - // index might have changed - if (floaterp != mTabContainer->getCurrentPanel() && - !mTabContainer->selectTabPanel(floaterp)) - { - addFloater(floaterp, TRUE, insertion_point); - } + if(!floaterp) return; + // we won't select a panel that already is selected + // it is hard to do this internally to tab container + // as tab selection is handled via index and the tab at a given + // index might have changed + if (floaterp != mTabContainer->getCurrentPanel() && + !mTabContainer->selectTabPanel(floaterp)) + { + addFloater(floaterp, TRUE, insertion_point); + } } void LLMultiFloater::removeFloater(LLFloater* floaterp) { - if (!floaterp || floaterp->getHost() != this ) - return; - - floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle()); - if (found_data_it != mFloaterDataMap.end()) - { - LLFloaterData& floater_data = found_data_it->second; - floaterp->setCanMinimize(floater_data.mCanMinimize); - floaterp->mSaveRect = floater_data.mSaveRect; - if (!floater_data.mCanResize) - { - // restore original size - floaterp->reshape(floater_data.mWidth, floater_data.mHeight); - } - floaterp->setCanResize(floater_data.mCanResize); - mFloaterDataMap.erase(found_data_it); - } - mTabContainer->removeTabPanel(floaterp); - floaterp->setBackgroundVisible(TRUE); - floaterp->setCanDrag(TRUE); - floaterp->setHost(NULL); - floaterp->applyRectControl(); - - updateResizeLimits(); - - tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); + if (!floaterp || floaterp->getHost() != this ) + return; + + floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle()); + if (found_data_it != mFloaterDataMap.end()) + { + LLFloaterData& floater_data = found_data_it->second; + floaterp->setCanMinimize(floater_data.mCanMinimize); + floaterp->mSaveRect = floater_data.mSaveRect; + if (!floater_data.mCanResize) + { + // restore original size + floaterp->reshape(floater_data.mWidth, floater_data.mHeight); + } + floaterp->setCanResize(floater_data.mCanResize); + mFloaterDataMap.erase(found_data_it); + } + mTabContainer->removeTabPanel(floaterp); + floaterp->setBackgroundVisible(TRUE); + floaterp->setCanDrag(TRUE); + floaterp->setHost(NULL); + floaterp->applyRectControl(); + + updateResizeLimits(); + + tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); } void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click) { - // default implementation does nothing + // default implementation does nothing } void LLMultiFloater::tabClose() { - if (mTabContainer->getTabCount() == 0) - { - // no more children, close myself - closeFloater(); - } + if (mTabContainer->getTabCount() == 0) + { + // no more children, close myself + closeFloater(); + } } void LLMultiFloater::setVisible(BOOL visible) { - // *FIX: shouldn't have to do this, fix adding to minimized multifloater - LLFloater::setVisible(visible); - - if (mTabContainer) - { - LLPanel* cur_floaterp = mTabContainer->getCurrentPanel(); - - if (cur_floaterp) - { - cur_floaterp->setVisible(visible); - } - - // if no tab selected, and we're being shown, - // select last tab to be added - if (visible && !cur_floaterp) - { - mTabContainer->selectLastTab(); - } - } + // *FIX: shouldn't have to do this, fix adding to minimized multifloater + LLFloater::setVisible(visible); + + if (mTabContainer) + { + LLPanel* cur_floaterp = mTabContainer->getCurrentPanel(); + + if (cur_floaterp) + { + cur_floaterp->setVisible(visible); + } + + // if no tab selected, and we're being shown, + // select last tab to be added + if (visible && !cur_floaterp) + { + mTabContainer->selectLastTab(); + } + } } BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask) { - if (key == 'W' && mask == MASK_CONTROL) - { - LLFloater* floater = getActiveFloater(); - // is user closeable and is system closeable - if (floater && floater->canClose() && floater->isCloseable()) - { - floater->closeFloater(); - - // EXT-5695 (Tabbed IM window loses focus if close any tabs by Ctrl+W) - // bring back focus on tab container if there are any tab left - if(mTabContainer->getTabCount() > 0) - { - mTabContainer->setFocus(TRUE); - } - } - return TRUE; - } - - return LLFloater::handleKeyHere(key, mask); + if (key == 'W' && mask == MASK_CONTROL) + { + LLFloater* floater = getActiveFloater(); + // is user closeable and is system closeable + if (floater && floater->canClose() && floater->isCloseable()) + { + floater->closeFloater(); + + // EXT-5695 (Tabbed IM window loses focus if close any tabs by Ctrl+W) + // bring back focus on tab container if there are any tab left + if(mTabContainer->getTabCount() > 0) + { + mTabContainer->setFocus(TRUE); + } + } + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); } bool LLMultiFloater::addChild(LLView* child, S32 tab_group) { - LLTabContainer* tab_container = dynamic_cast(child); - if (tab_container) - { - // store pointer to tab container - setTabContainer(tab_container); - } - - // then go ahead and add child as usual - return LLFloater::addChild(child, tab_group); + LLTabContainer* tab_container = dynamic_cast(child); + if (tab_container) + { + // store pointer to tab container + setTabContainer(tab_container); + } + + // then go ahead and add child as usual + return LLFloater::addChild(child, tab_group); } LLFloater* LLMultiFloater::getActiveFloater() { - return (LLFloater*)mTabContainer->getCurrentPanel(); + return (LLFloater*)mTabContainer->getCurrentPanel(); } -S32 LLMultiFloater::getFloaterCount() +S32 LLMultiFloater::getFloaterCount() { - return mTabContainer->getTabCount(); + return mTabContainer->getTabCount(); } /** - BOOL isFloaterFlashing(LLFloater* floaterp) + BOOL isFloaterFlashing(LLFloater* floaterp) - Returns true if the LLFloater pointed to by floaterp - is currently in a flashing state and is hosted by this. - False otherwise. + Returns true if the LLFloater pointed to by floaterp + is currently in a flashing state and is hosted by this. + False otherwise. - Requires: floaterp != NULL + Requires: floaterp != NULL **/ BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp) { - if ( floaterp && floaterp->getHost() == this ) - return mTabContainer->getTabPanelFlashing(floaterp); + if ( floaterp && floaterp->getHost() == this ) + return mTabContainer->getTabPanelFlashing(floaterp); - return FALSE; + return FALSE; } /** - BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing) + BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing) - Sets the current flashing state of the LLFloater pointed - to by floaterp to be the BOOL flashing if the LLFloater pointed - to by floaterp is hosted by this. + Sets the current flashing state of the LLFloater pointed + to by floaterp to be the BOOL flashing if the LLFloater pointed + to by floaterp is hosted by this. - Requires: floaterp != NULL + Requires: floaterp != NULL **/ void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing) { - if ( floaterp && floaterp->getHost() == this ) - mTabContainer->setTabPanelFlashing(floaterp, flashing); + if ( floaterp && floaterp->getHost() == this ) + mTabContainer->setTabPanelFlashing(floaterp, flashing); } void LLMultiFloater::onTabSelected() { - LLFloater* floaterp = dynamic_cast(mTabContainer->getCurrentPanel()); - if (floaterp) - { - tabOpen(floaterp, true); - } + LLFloater* floaterp = dynamic_cast(mTabContainer->getCurrentPanel()); + if (floaterp) + { + tabOpen(floaterp, true); + } } void LLMultiFloater::setCanResize(BOOL can_resize) { - LLFloater::setCanResize(can_resize); - if (!mTabContainer) return; - if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - else - { - mTabContainer->setRightTabBtnOffset(0); - } + LLFloater::setCanResize(can_resize); + if (!mTabContainer) return; + if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM) + { + mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); + } + else + { + mTabContainer->setRightTabBtnOffset(0); + } } BOOL LLMultiFloater::postBuild() { - mCloseSignal.connect(boost::bind(&LLMultiFloater::closeAllFloaters, this)); - - // remember any original xml minimum size - getResizeLimits(&mOrigMinWidth, &mOrigMinHeight); - - if (mTabContainer) - { - return TRUE; - } - - mTabContainer = getChild("Preview Tabs"); - - setCanResize(mResizable); - return TRUE; + mCloseSignal.connect(boost::bind(&LLMultiFloater::closeAllFloaters, this)); + + // remember any original xml minimum size + getResizeLimits(&mOrigMinWidth, &mOrigMinHeight); + + if (mTabContainer) + { + return TRUE; + } + + mTabContainer = getChild("Preview Tabs"); + + setCanResize(mResizable); + return TRUE; } void LLMultiFloater::updateResizeLimits() { - // initialize minimum size constraint to the original xml values. - S32 new_min_width = mOrigMinWidth; - S32 new_min_height = mOrigMinHeight; - - computeResizeLimits(new_min_width, new_min_height); - - setResizeLimits(new_min_width, new_min_height); - - S32 cur_height = getRect().getHeight(); - S32 new_width = llmax(getRect().getWidth(), new_min_width); - S32 new_height = llmax(getRect().getHeight(), new_min_height); - - if (isMinimized()) - { - const LLRect& expanded = getExpandedRect(); - LLRect newrect; - newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height)); - setExpandedRect(newrect); - } - else - { - reshape(new_width, new_height); - - // make sure upper left corner doesn't move - translate(0, cur_height - getRect().getHeight()); - - // make sure this window is visible on screen when it has been modified - // (tab added, etc) - gFloaterView->adjustToFitScreen(this, TRUE); - } + // initialize minimum size constraint to the original xml values. + S32 new_min_width = mOrigMinWidth; + S32 new_min_height = mOrigMinHeight; + + computeResizeLimits(new_min_width, new_min_height); + + setResizeLimits(new_min_width, new_min_height); + + S32 cur_height = getRect().getHeight(); + S32 new_width = llmax(getRect().getWidth(), new_min_width); + S32 new_height = llmax(getRect().getHeight(), new_min_height); + + if (isMinimized()) + { + const LLRect& expanded = getExpandedRect(); + LLRect newrect; + newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height)); + setExpandedRect(newrect); + } + else + { + reshape(new_width, new_height); + + // make sure upper left corner doesn't move + translate(0, cur_height - getRect().getHeight()); + + // make sure this window is visible on screen when it has been modified + // (tab added, etc) + gFloaterView->adjustToFitScreen(this, TRUE); + } } void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height) { - static LLUICachedControl tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; - - // possibly increase minimum size constraint due to children's minimums. - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) - { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); - if (floaterp) - { - new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); - new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); - } - } + static LLUICachedControl tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; + + // possibly increase minimum size constraint due to children's minimums. + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); + if (floaterp) + { + new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); + new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); + } + } } diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index c106a62527..f2d83f4449 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -1,25 +1,25 @@ -/** +/** * @file llmultifloater.h * @brief LLFloater that hosts other floaters * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,65 +38,65 @@ class LLMultiFloater : public LLFloater { public: - LLMultiFloater(const LLSD& key, const Params& params = getDefaultParams()); - virtual ~LLMultiFloater() {}; - - void buildTabContainer(); - - virtual BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); - virtual void draw(); - virtual void setVisible(BOOL visible); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); - - virtual void setCanResize(BOOL can_resize); - virtual void growToFit(S32 content_width, S32 content_height); - virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - - virtual void showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - virtual void removeFloater(LLFloater* floaterp); - - virtual void tabOpen(LLFloater* opened_floater, bool from_click); - virtual void tabClose(); - - virtual BOOL selectFloater(LLFloater* floaterp); - virtual void selectNextFloater(); - virtual void selectPrevFloater(); - - virtual LLFloater* getActiveFloater(); - virtual BOOL isFloaterFlashing(LLFloater* floaterp); - virtual S32 getFloaterCount(); - - virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); - virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs - void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } - void onTabSelected(); - - virtual void updateResizeLimits(); - virtual void updateFloaterTitle(LLFloater* floaterp); + LLMultiFloater(const LLSD& key, const Params& params = getDefaultParams()); + virtual ~LLMultiFloater() {}; + + void buildTabContainer(); + + virtual BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + virtual void draw(); + virtual void setVisible(BOOL visible); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + + virtual void setCanResize(BOOL can_resize); + virtual void growToFit(S32 content_width, S32 content_height); + virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + + virtual void showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + virtual void removeFloater(LLFloater* floaterp); + + virtual void tabOpen(LLFloater* opened_floater, bool from_click); + virtual void tabClose(); + + virtual BOOL selectFloater(LLFloater* floaterp); + virtual void selectNextFloater(); + virtual void selectPrevFloater(); + + virtual LLFloater* getActiveFloater(); + virtual BOOL isFloaterFlashing(LLFloater* floaterp); + virtual S32 getFloaterCount(); + + virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); + virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs + void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } + void onTabSelected(); + + virtual void updateResizeLimits(); + virtual void updateFloaterTitle(LLFloater* floaterp); protected: - struct LLFloaterData - { - S32 mWidth; - S32 mHeight; - BOOL mCanMinimize; - BOOL mCanResize; - BOOL mSaveRect; - }; - - LLTabContainer* mTabContainer; - - typedef std::map, LLFloaterData> floater_data_map_t; - floater_data_map_t mFloaterDataMap; - - LLTabContainer::TabPosition mTabPos; - BOOL mAutoResize; - S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late + struct LLFloaterData + { + S32 mWidth; + S32 mHeight; + BOOL mCanMinimize; + BOOL mCanResize; + BOOL mSaveRect; + }; + + LLTabContainer* mTabContainer; + + typedef std::map, LLFloaterData> floater_data_map_t; + floater_data_map_t mFloaterDataMap; + + LLTabContainer::TabPosition mTabPos; + BOOL mAutoResize; + S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late private: - virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height); + virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height); }; #endif // LL_MULTI_FLOATER_H diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 604d246f12..26882ba8ec 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmultisldr.cpp * @brief LLMultiSlider base class * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,7 +32,7 @@ #include "llgl.h" #include "llwindow.h" #include "llfocusmgr.h" -#include "llkeyboard.h" // for the MASK constants +#include "llkeyboard.h" // for the MASK constants #include "llcontrol.h" #include "lluictrlfactory.h" #include "lluiimage.h" @@ -46,74 +46,74 @@ const F32 FLOAT_THRESHOLD = 0.00001f; S32 LLMultiSlider::mNameCounter = 0; LLMultiSlider::SliderParams::SliderParams() -: name("name"), - value("value", 0.f) +: name("name"), + value("value", 0.f) { } LLMultiSlider::Params::Params() -: max_sliders("max_sliders", 1), - allow_overlap("allow_overlap", false), - loop_overlap("loop_overlap", false), - orientation("orientation"), - overlap_threshold("overlap_threshold", 0), - draw_track("draw_track", true), - use_triangle("use_triangle", false), - track_color("track_color"), - thumb_disabled_color("thumb_disabled_color"), - thumb_highlight_color("thumb_highlight_color"), - thumb_outline_color("thumb_outline_color"), - thumb_center_color("thumb_center_color"), - thumb_center_selected_color("thumb_center_selected_color"), - thumb_image("thumb_image"), - triangle_color("triangle_color"), - mouse_down_callback("mouse_down_callback"), - mouse_up_callback("mouse_up_callback"), - thumb_width("thumb_width"), - sliders("slider") +: max_sliders("max_sliders", 1), + allow_overlap("allow_overlap", false), + loop_overlap("loop_overlap", false), + orientation("orientation"), + overlap_threshold("overlap_threshold", 0), + draw_track("draw_track", true), + use_triangle("use_triangle", false), + track_color("track_color"), + thumb_disabled_color("thumb_disabled_color"), + thumb_highlight_color("thumb_highlight_color"), + thumb_outline_color("thumb_outline_color"), + thumb_center_color("thumb_center_color"), + thumb_center_selected_color("thumb_center_selected_color"), + thumb_image("thumb_image"), + triangle_color("triangle_color"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + thumb_width("thumb_width"), + sliders("slider") {} LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) -: LLF32UICtrl(p), - mMouseOffset( 0 ), - mMaxNumSliders(p.max_sliders), - mAllowOverlap(p.allow_overlap), - mLoopOverlap(p.loop_overlap), - mDrawTrack(p.draw_track), - mUseTriangle(p.use_triangle), - mTrackColor(p.track_color()), - mThumbOutlineColor(p.thumb_outline_color()), - mThumbCenterColor(p.thumb_center_color()), - mThumbCenterSelectedColor(p.thumb_center_selected_color()), - mDisabledThumbColor(p.thumb_disabled_color()), - mTriangleColor(p.triangle_color()), - mThumbWidth(p.thumb_width), - mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL), - mMouseDownSignal(NULL), - mMouseUpSignal(NULL) +: LLF32UICtrl(p), + mMouseOffset( 0 ), + mMaxNumSliders(p.max_sliders), + mAllowOverlap(p.allow_overlap), + mLoopOverlap(p.loop_overlap), + mDrawTrack(p.draw_track), + mUseTriangle(p.use_triangle), + mTrackColor(p.track_color()), + mThumbOutlineColor(p.thumb_outline_color()), + mThumbCenterColor(p.thumb_center_color()), + mThumbCenterSelectedColor(p.thumb_center_selected_color()), + mDisabledThumbColor(p.thumb_disabled_color()), + mTriangleColor(p.triangle_color()), + mThumbWidth(p.thumb_width), + mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL), + mMouseDownSignal(NULL), + mMouseUpSignal(NULL) { - mValue = LLSD::emptyMap(); - mCurSlider = LLStringUtil::null; - - if (mOrientation == HORIZONTAL) - { - mDragStartThumbRect = LLRect(0, getRect().getHeight(), p.thumb_width, 0); - } - else - { - mDragStartThumbRect = LLRect(0, p.thumb_width, getRect().getWidth(), 0); - } - - if (p.mouse_down_callback.isProvided()) - { - setMouseDownCallback(initCommitCallback(p.mouse_down_callback)); - } - if (p.mouse_up_callback.isProvided()) - { - setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); - } - - if (p.overlap_threshold.isProvided() && p.overlap_threshold > mIncrement) + mValue = LLSD::emptyMap(); + mCurSlider = LLStringUtil::null; + + if (mOrientation == HORIZONTAL) + { + mDragStartThumbRect = LLRect(0, getRect().getHeight(), p.thumb_width, 0); + } + else + { + mDragStartThumbRect = LLRect(0, p.thumb_width, getRect().getWidth(), 0); + } + + if (p.mouse_down_callback.isProvided()) + { + setMouseDownCallback(initCommitCallback(p.mouse_down_callback)); + } + if (p.mouse_up_callback.isProvided()) + { + setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); + } + + if (p.overlap_threshold.isProvided() && p.overlap_threshold > mIncrement) { mOverlapThreshold = p.overlap_threshold - mIncrement; } @@ -122,32 +122,32 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) mOverlapThreshold = 0; } - for (LLInitParam::ParamIterator::const_iterator it = p.sliders.begin(); - it != p.sliders.end(); - ++it) - { - if (it->name.isProvided()) - { - addSlider(it->value, it->name); - } - else - { - addSlider(it->value); - } - } + for (LLInitParam::ParamIterator::const_iterator it = p.sliders.begin(); + it != p.sliders.end(); + ++it) + { + if (it->name.isProvided()) + { + addSlider(it->value, it->name); + } + else + { + addSlider(it->value); + } + } mRoundedSquareImgp = LLUI::getUIImage("Rounded_Square"); - if (p.thumb_image.isProvided()) - { - mThumbImagep = LLUI::getUIImage(p.thumb_image()); - } - mThumbHighlightColor = p.thumb_highlight_color.isProvided() ? p.thumb_highlight_color() : static_cast(gFocusMgr.getFocusColor()); + if (p.thumb_image.isProvided()) + { + mThumbImagep = LLUI::getUIImage(p.thumb_image()); + } + mThumbHighlightColor = p.thumb_highlight_color.isProvided() ? p.thumb_highlight_color() : static_cast(gFocusMgr.getFocusColor()); } LLMultiSlider::~LLMultiSlider() { - delete mMouseDownSignal; - delete mMouseUpSignal; + delete mMouseDownSignal; + delete mMouseUpSignal; } F32 LLMultiSlider::getNearestIncrement(F32 value) const @@ -163,125 +163,125 @@ F32 LLMultiSlider::getNearestIncrement(F32 value) const void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from_event) { - // exit if not there - if(!mValue.has(name)) { - return; - } + // exit if not there + if(!mValue.has(name)) { + return; + } F32 newValue = getNearestIncrement(value); - // now, make sure no overlap - // if we want that - if(!mAllowOverlap) { - bool hit = false; - - // look at the current spot - // and see if anything is there - LLSD::map_iterator mIt = mValue.beginMap(); - - // increment is our distance between points, use to eliminate round error - F32 threshold = mOverlapThreshold + (mIncrement / 4); - // If loop overlap is enabled, check if we overlap with points 'after' max value (project to lower) - F32 loop_up_check = (mLoopOverlap && (value + threshold) > mMaxValue) ? (value + threshold - mMaxValue + mMinValue) : mMinValue - 1.0f; - // If loop overlap is enabled, check if we overlap with points 'before' min value (project to upper) - F32 loop_down_check = (mLoopOverlap && (value - threshold) < mMinValue) ? (value - threshold - mMinValue + mMaxValue) : mMaxValue + 1.0f; - - for(;mIt != mValue.endMap(); mIt++) - { - F32 locationVal = (F32)mIt->second.asReal(); - // Check nearby values - F32 testVal = locationVal - newValue; - if (testVal > -threshold - && testVal < threshold - && mIt->first != name) - { - hit = true; - break; - } - if (mLoopOverlap) - { - // Check edge overlap values - if (locationVal < loop_up_check) - { - hit = true; - break; - } - if (locationVal > loop_down_check) - { - hit = true; - break; - } - } - } - - // if none found, stop - if(hit) { - return; - } - } - - - // now set it in the map - mValue[name] = newValue; - - // set the control if it's the current slider and not from an event - if (!from_event && name == mCurSlider) - { - setControlValue(mValue); - } - - F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue); - if (mOrientation == HORIZONTAL) - { - S32 left_edge = mThumbWidth/2; - S32 right_edge = getRect().getWidth() - (mThumbWidth/2); - - S32 x = left_edge + S32( t * (right_edge - left_edge) ); - - mThumbRects[name].mLeft = x - (mThumbWidth / 2); - mThumbRects[name].mRight = x + (mThumbWidth / 2); - } - else - { - S32 bottom_edge = mThumbWidth/2; - S32 top_edge = getRect().getHeight() - (mThumbWidth/2); - - S32 x = bottom_edge + S32( t * (top_edge - bottom_edge) ); - - mThumbRects[name].mTop = x + (mThumbWidth / 2); - mThumbRects[name].mBottom = x - (mThumbWidth / 2); - } + // now, make sure no overlap + // if we want that + if(!mAllowOverlap) { + bool hit = false; + + // look at the current spot + // and see if anything is there + LLSD::map_iterator mIt = mValue.beginMap(); + + // increment is our distance between points, use to eliminate round error + F32 threshold = mOverlapThreshold + (mIncrement / 4); + // If loop overlap is enabled, check if we overlap with points 'after' max value (project to lower) + F32 loop_up_check = (mLoopOverlap && (value + threshold) > mMaxValue) ? (value + threshold - mMaxValue + mMinValue) : mMinValue - 1.0f; + // If loop overlap is enabled, check if we overlap with points 'before' min value (project to upper) + F32 loop_down_check = (mLoopOverlap && (value - threshold) < mMinValue) ? (value - threshold - mMinValue + mMaxValue) : mMaxValue + 1.0f; + + for(;mIt != mValue.endMap(); mIt++) + { + F32 locationVal = (F32)mIt->second.asReal(); + // Check nearby values + F32 testVal = locationVal - newValue; + if (testVal > -threshold + && testVal < threshold + && mIt->first != name) + { + hit = true; + break; + } + if (mLoopOverlap) + { + // Check edge overlap values + if (locationVal < loop_up_check) + { + hit = true; + break; + } + if (locationVal > loop_down_check) + { + hit = true; + break; + } + } + } + + // if none found, stop + if(hit) { + return; + } + } + + + // now set it in the map + mValue[name] = newValue; + + // set the control if it's the current slider and not from an event + if (!from_event && name == mCurSlider) + { + setControlValue(mValue); + } + + F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue); + if (mOrientation == HORIZONTAL) + { + S32 left_edge = mThumbWidth/2; + S32 right_edge = getRect().getWidth() - (mThumbWidth/2); + + S32 x = left_edge + S32( t * (right_edge - left_edge) ); + + mThumbRects[name].mLeft = x - (mThumbWidth / 2); + mThumbRects[name].mRight = x + (mThumbWidth / 2); + } + else + { + S32 bottom_edge = mThumbWidth/2; + S32 top_edge = getRect().getHeight() - (mThumbWidth/2); + + S32 x = bottom_edge + S32( t * (top_edge - bottom_edge) ); + + mThumbRects[name].mTop = x + (mThumbWidth / 2); + mThumbRects[name].mBottom = x - (mThumbWidth / 2); + } } void LLMultiSlider::setValue(const LLSD& value) { - // only do if it's a map - if(value.isMap()) { - - // add each value... the first in the map becomes the current - LLSD::map_const_iterator mIt = value.beginMap(); - mCurSlider = mIt->first; - - for(; mIt != value.endMap(); mIt++) { - setSliderValue(mIt->first, (F32)mIt->second.asReal(), TRUE); - } - } + // only do if it's a map + if(value.isMap()) { + + // add each value... the first in the map becomes the current + LLSD::map_const_iterator mIt = value.beginMap(); + mCurSlider = mIt->first; + + for(; mIt != value.endMap(); mIt++) { + setSliderValue(mIt->first, (F32)mIt->second.asReal(), TRUE); + } + } } F32 LLMultiSlider::getSliderValue(const std::string& name) const { - if (mValue.has(name)) - { - return (F32)mValue[name].asReal(); - } - return 0; + if (mValue.has(name)) + { + return (F32)mValue[name].asReal(); + } + return 0; } void LLMultiSlider::setCurSlider(const std::string& name) { - if(mValue.has(name)) { - mCurSlider = name; - } + if(mValue.has(name)) { + mCurSlider = name; + } } F32 LLMultiSlider::getSliderValueFromPos(S32 xpos, S32 ypos) const @@ -337,179 +337,179 @@ void LLMultiSlider::clearSliderThumbImage() void LLMultiSlider::resetCurSlider() { - mCurSlider = LLStringUtil::null; + mCurSlider = LLStringUtil::null; } const std::string& LLMultiSlider::addSlider() { - return addSlider(mInitialValue); + return addSlider(mInitialValue); } const std::string& LLMultiSlider::addSlider(F32 val) { - std::stringstream newName; - F32 initVal = val; - - if(mValue.size() >= mMaxNumSliders) { - return LLStringUtil::null; - } - - // create a new name - newName << "sldr" << mNameCounter; - mNameCounter++; - - bool foundOne = findUnusedValue(initVal); - if(!foundOne) { - return LLStringUtil::null; - } - - // add a new thumb rect - if (mOrientation == HORIZONTAL) - { - mThumbRects[newName.str()] = LLRect(0, getRect().getHeight(), mThumbWidth, 0); - } - else - { - mThumbRects[newName.str()] = LLRect(0, mThumbWidth, getRect().getWidth(), 0); - } - - // add the value and set the current slider to this one - mValue.insert(newName.str(), initVal); - mCurSlider = newName.str(); - - // move the slider - setSliderValue(mCurSlider, initVal, TRUE); - - return mCurSlider; + std::stringstream newName; + F32 initVal = val; + + if(mValue.size() >= mMaxNumSliders) { + return LLStringUtil::null; + } + + // create a new name + newName << "sldr" << mNameCounter; + mNameCounter++; + + bool foundOne = findUnusedValue(initVal); + if(!foundOne) { + return LLStringUtil::null; + } + + // add a new thumb rect + if (mOrientation == HORIZONTAL) + { + mThumbRects[newName.str()] = LLRect(0, getRect().getHeight(), mThumbWidth, 0); + } + else + { + mThumbRects[newName.str()] = LLRect(0, mThumbWidth, getRect().getWidth(), 0); + } + + // add the value and set the current slider to this one + mValue.insert(newName.str(), initVal); + mCurSlider = newName.str(); + + // move the slider + setSliderValue(mCurSlider, initVal, TRUE); + + return mCurSlider; } bool LLMultiSlider::addSlider(F32 val, const std::string& name) { - F32 initVal = val; - - if(mValue.size() >= mMaxNumSliders) { - return false; - } - - bool foundOne = findUnusedValue(initVal); - if(!foundOne) { - return false; - } - - // add a new thumb rect - if (mOrientation == HORIZONTAL) - { - mThumbRects[name] = LLRect(0, getRect().getHeight(), mThumbWidth, 0); - } - else - { - mThumbRects[name] = LLRect(0, mThumbWidth, getRect().getWidth(), 0); - } - - // add the value and set the current slider to this one - mValue.insert(name, initVal); - mCurSlider = name; - - // move the slider - setSliderValue(mCurSlider, initVal, TRUE); - - return true; + F32 initVal = val; + + if(mValue.size() >= mMaxNumSliders) { + return false; + } + + bool foundOne = findUnusedValue(initVal); + if(!foundOne) { + return false; + } + + // add a new thumb rect + if (mOrientation == HORIZONTAL) + { + mThumbRects[name] = LLRect(0, getRect().getHeight(), mThumbWidth, 0); + } + else + { + mThumbRects[name] = LLRect(0, mThumbWidth, getRect().getWidth(), 0); + } + + // add the value and set the current slider to this one + mValue.insert(name, initVal); + mCurSlider = name; + + // move the slider + setSliderValue(mCurSlider, initVal, TRUE); + + return true; } bool LLMultiSlider::findUnusedValue(F32& initVal) { - bool firstTry = true; - - // find the first open slot starting with - // the initial value - while(true) { - - bool hit = false; - - // look at the current spot - // and see if anything is there - F32 threshold = mAllowOverlap ? FLOAT_THRESHOLD : mOverlapThreshold + (mIncrement / 4); - LLSD::map_iterator mIt = mValue.beginMap(); - for(;mIt != mValue.endMap(); mIt++) { - - F32 testVal = (F32)mIt->second.asReal() - initVal; - if(testVal > -threshold && testVal < threshold) - { - hit = true; - break; - } - } - - // if we found one - if(!hit) { - break; - } - - // increment and wrap if need be - initVal += mIncrement; - if(initVal > mMaxValue) { - initVal = mMinValue; - } - - // stop if it's filled - if(initVal == mInitialValue && !firstTry) { - LL_WARNS() << "Whoa! Too many multi slider elements to add one to" << LL_ENDL; - return false; - } - - firstTry = false; - continue; - } - - return true; + bool firstTry = true; + + // find the first open slot starting with + // the initial value + while(true) { + + bool hit = false; + + // look at the current spot + // and see if anything is there + F32 threshold = mAllowOverlap ? FLOAT_THRESHOLD : mOverlapThreshold + (mIncrement / 4); + LLSD::map_iterator mIt = mValue.beginMap(); + for(;mIt != mValue.endMap(); mIt++) { + + F32 testVal = (F32)mIt->second.asReal() - initVal; + if(testVal > -threshold && testVal < threshold) + { + hit = true; + break; + } + } + + // if we found one + if(!hit) { + break; + } + + // increment and wrap if need be + initVal += mIncrement; + if(initVal > mMaxValue) { + initVal = mMinValue; + } + + // stop if it's filled + if(initVal == mInitialValue && !firstTry) { + LL_WARNS() << "Whoa! Too many multi slider elements to add one to" << LL_ENDL; + return false; + } + + firstTry = false; + continue; + } + + return true; } void LLMultiSlider::deleteSlider(const std::string& name) { - // can't delete last slider - if(mValue.size() <= 0) { - return; - } - - // get rid of value from mValue and its thumb rect - mValue.erase(name); - mThumbRects.erase(name); - - // set to the last created - if(mValue.size() > 0) { - std::map::iterator mIt = mThumbRects.end(); - mIt--; - mCurSlider = mIt->first; - } + // can't delete last slider + if(mValue.size() <= 0) { + return; + } + + // get rid of value from mValue and its thumb rect + mValue.erase(name); + mThumbRects.erase(name); + + // set to the last created + if(mValue.size() > 0) { + std::map::iterator mIt = mThumbRects.end(); + mIt--; + mCurSlider = mIt->first; + } } void LLMultiSlider::clear() { - while(mThumbRects.size() > 0 && mValue.size() > 0) { - deleteCurSlider(); - } + while(mThumbRects.size() > 0 && mValue.size() > 0) { + deleteCurSlider(); + } - if (mThumbRects.size() > 0 || mValue.size() > 0) - { - LL_WARNS() << "Failed to fully clear Multi slider" << LL_ENDL; - } + if (mThumbRects.size() > 0 || mValue.size() > 0) + { + LL_WARNS() << "Failed to fully clear Multi slider" << LL_ENDL; + } - LLF32UICtrl::clear(); + LLF32UICtrl::clear(); } BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask) { - if( gFocusMgr.getMouseCapture() == this ) - { - setCurSliderValue(getSliderValueFromPos(x, y)); - onCommit(); - - getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; - } - else - { + if( gFocusMgr.getMouseCapture() == this ) + { + setCurSliderValue(getSliderValueFromPos(x, y)); + onCommit(); + + getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; + } + else + { if (getEnabled()) { mHoverSlider.clear(); @@ -528,116 +528,116 @@ BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask) mHoverSlider.clear(); } - getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; - } - return TRUE; + getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; + } + return TRUE; } BOOL LLMultiSlider::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; + BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) - { - gFocusMgr.setMouseCapture( NULL ); + if( gFocusMgr.getMouseCapture() == this ) + { + gFocusMgr.setMouseCapture( NULL ); - if (mMouseUpSignal) - (*mMouseUpSignal)( this, LLSD() ); + if (mMouseUpSignal) + (*mMouseUpSignal)( this, LLSD() ); - handled = TRUE; - make_ui_sound("UISndClickRelease"); - } - else - { - handled = TRUE; - } + handled = TRUE; + make_ui_sound("UISndClickRelease"); + } + else + { + handled = TRUE; + } - return handled; + return handled; } BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask) { - // only do sticky-focus on non-chrome widgets - if (!getIsChrome()) - { - setFocus(TRUE); - } - if (mMouseDownSignal) - (*mMouseDownSignal)( this, LLSD() ); - - if (MASK_CONTROL & mask) // if CTRL is modifying - { - setCurSliderValue(mInitialValue); - onCommit(); - } - else - { - // scroll through thumbs to see if we have a new one selected and select that one - std::map::iterator mIt = mThumbRects.begin(); - for(; mIt != mThumbRects.end(); mIt++) { - - // check if inside. If so, set current slider and continue - if(mIt->second.pointInRect(x,y)) { - mCurSlider = mIt->first; - break; - } - } - - if (!mCurSlider.empty()) - { - // Find the offset of the actual mouse location from the center of the thumb. - if (mThumbRects[mCurSlider].pointInRect(x,y)) - { - if (mOrientation == HORIZONTAL) - { - mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth / 2) - x; - } - else - { - mMouseOffset = (mThumbRects[mCurSlider].mBottom + mThumbWidth / 2) - y; - } - } - else - { - mMouseOffset = 0; - } - - // Start dragging the thumb - // No handler needed for focus lost since this class has no state that depends on it. - gFocusMgr.setMouseCapture( this ); - mDragStartThumbRect = mThumbRects[mCurSlider]; - } - } - make_ui_sound("UISndClick"); - - return TRUE; + // only do sticky-focus on non-chrome widgets + if (!getIsChrome()) + { + setFocus(TRUE); + } + if (mMouseDownSignal) + (*mMouseDownSignal)( this, LLSD() ); + + if (MASK_CONTROL & mask) // if CTRL is modifying + { + setCurSliderValue(mInitialValue); + onCommit(); + } + else + { + // scroll through thumbs to see if we have a new one selected and select that one + std::map::iterator mIt = mThumbRects.begin(); + for(; mIt != mThumbRects.end(); mIt++) { + + // check if inside. If so, set current slider and continue + if(mIt->second.pointInRect(x,y)) { + mCurSlider = mIt->first; + break; + } + } + + if (!mCurSlider.empty()) + { + // Find the offset of the actual mouse location from the center of the thumb. + if (mThumbRects[mCurSlider].pointInRect(x,y)) + { + if (mOrientation == HORIZONTAL) + { + mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth / 2) - x; + } + else + { + mMouseOffset = (mThumbRects[mCurSlider].mBottom + mThumbWidth / 2) - y; + } + } + else + { + mMouseOffset = 0; + } + + // Start dragging the thumb + // No handler needed for focus lost since this class has no state that depends on it. + gFocusMgr.setMouseCapture( this ); + mDragStartThumbRect = mThumbRects[mCurSlider]; + } + } + make_ui_sound("UISndClick"); + + return TRUE; } -BOOL LLMultiSlider::handleKeyHere(KEY key, MASK mask) +BOOL LLMultiSlider::handleKeyHere(KEY key, MASK mask) { - BOOL handled = FALSE; - switch(key) - { - case KEY_UP: - case KEY_DOWN: - // eat up and down keys to be consistent - handled = TRUE; - break; - case KEY_LEFT: - setCurSliderValue(getCurSliderValue() - getIncrement()); - onCommit(); - handled = TRUE; - break; - case KEY_RIGHT: - setCurSliderValue(getCurSliderValue() + getIncrement()); - onCommit(); - handled = TRUE; - break; - default: - break; - } - return handled; + BOOL handled = FALSE; + switch(key) + { + case KEY_UP: + case KEY_DOWN: + // eat up and down keys to be consistent + handled = TRUE; + break; + case KEY_LEFT: + setCurSliderValue(getCurSliderValue() - getIncrement()); + onCommit(); + handled = TRUE; + break; + case KEY_RIGHT: + setCurSliderValue(getCurSliderValue() + getIncrement()); + onCommit(); + handled = TRUE; + break; + default: + break; + } + return handled; } /*virtual*/ @@ -649,132 +649,132 @@ void LLMultiSlider::onMouseLeave(S32 x, S32 y, MASK mask) void LLMultiSlider::draw() { - static LLUICachedControl extra_triangle_height ("UIExtraTriangleHeight", 0); - static LLUICachedControl extra_triangle_width ("UIExtraTriangleWidth", 0); - LLColor4 curThumbColor; - - std::map::iterator mIt; - std::map::iterator curSldrIt; - std::map::iterator hoverSldrIt; - - // Draw background and thumb. - - // drawing solids requires texturing be disabled - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLRect rect(mDragStartThumbRect); - - F32 opacity = getEnabled() ? 1.f : 0.3f; - - // Track - static LLUICachedControl multi_track_height_width ("UIMultiTrackHeight", 0); - S32 height_offset = 0; - S32 width_offset = 0; - if (mOrientation == HORIZONTAL) - { - height_offset = (getRect().getHeight() - multi_track_height_width) / 2; - } - else - { - width_offset = (getRect().getWidth() - multi_track_height_width) / 2; - } - LLRect track_rect(width_offset, getRect().getHeight() - height_offset, getRect().getWidth() - width_offset, height_offset); - - - if(mDrawTrack) - { - track_rect.stretch(-1); - mRoundedSquareImgp->draw(track_rect, mTrackColor.get() % opacity); - } - - // if we're supposed to use a drawn triangle - // simple gl call for the triangle - if(mUseTriangle) { - - for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) { - - gl_triangle_2d( - mIt->second.mLeft - extra_triangle_width, - mIt->second.mTop + extra_triangle_height, - mIt->second.mRight + extra_triangle_width, - mIt->second.mTop + extra_triangle_height, - mIt->second.mLeft + mIt->second.getWidth() / 2, - mIt->second.mBottom - extra_triangle_height, - mTriangleColor.get() % opacity, TRUE); - } - } - else if (!mRoundedSquareImgp && !mThumbImagep) - { - // draw all the thumbs - curSldrIt = mThumbRects.end(); - hoverSldrIt = mThumbRects.end(); - for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) { - - // choose the color - curThumbColor = mThumbCenterColor.get(); - if(mIt->first == mCurSlider) { - - curSldrIt = mIt; - continue; - } - if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this) - { - // draw last, after current one - hoverSldrIt = mIt; - continue; - } - - // the draw command - gl_rect_2d(mIt->second, curThumbColor, TRUE); - } - - // now draw the current and hover sliders - if(curSldrIt != mThumbRects.end()) - { - gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor.get(), TRUE); - } - - // and draw the drag start - if (gFocusMgr.getMouseCapture() == this) - { - gl_rect_2d(mDragStartThumbRect, mThumbCenterColor.get() % opacity, FALSE); - } - else if (hoverSldrIt != mThumbRects.end()) - { - gl_rect_2d(hoverSldrIt->second, mThumbCenterSelectedColor.get(), TRUE); - } - } - else - { - LLMouseHandler* capture = gFocusMgr.getMouseCapture(); - if (capture == this) - { - // draw drag start (ghost) - if (mThumbImagep) - { - mThumbImagep->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); - } - else - { + static LLUICachedControl extra_triangle_height ("UIExtraTriangleHeight", 0); + static LLUICachedControl extra_triangle_width ("UIExtraTriangleWidth", 0); + LLColor4 curThumbColor; + + std::map::iterator mIt; + std::map::iterator curSldrIt; + std::map::iterator hoverSldrIt; + + // Draw background and thumb. + + // drawing solids requires texturing be disabled + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLRect rect(mDragStartThumbRect); + + F32 opacity = getEnabled() ? 1.f : 0.3f; + + // Track + static LLUICachedControl multi_track_height_width ("UIMultiTrackHeight", 0); + S32 height_offset = 0; + S32 width_offset = 0; + if (mOrientation == HORIZONTAL) + { + height_offset = (getRect().getHeight() - multi_track_height_width) / 2; + } + else + { + width_offset = (getRect().getWidth() - multi_track_height_width) / 2; + } + LLRect track_rect(width_offset, getRect().getHeight() - height_offset, getRect().getWidth() - width_offset, height_offset); + + + if(mDrawTrack) + { + track_rect.stretch(-1); + mRoundedSquareImgp->draw(track_rect, mTrackColor.get() % opacity); + } + + // if we're supposed to use a drawn triangle + // simple gl call for the triangle + if(mUseTriangle) { + + for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) { + + gl_triangle_2d( + mIt->second.mLeft - extra_triangle_width, + mIt->second.mTop + extra_triangle_height, + mIt->second.mRight + extra_triangle_width, + mIt->second.mTop + extra_triangle_height, + mIt->second.mLeft + mIt->second.getWidth() / 2, + mIt->second.mBottom - extra_triangle_height, + mTriangleColor.get() % opacity, TRUE); + } + } + else if (!mRoundedSquareImgp && !mThumbImagep) + { + // draw all the thumbs + curSldrIt = mThumbRects.end(); + hoverSldrIt = mThumbRects.end(); + for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) { + + // choose the color + curThumbColor = mThumbCenterColor.get(); + if(mIt->first == mCurSlider) { + + curSldrIt = mIt; + continue; + } + if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this) + { + // draw last, after current one + hoverSldrIt = mIt; + continue; + } + + // the draw command + gl_rect_2d(mIt->second, curThumbColor, TRUE); + } + + // now draw the current and hover sliders + if(curSldrIt != mThumbRects.end()) + { + gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor.get(), TRUE); + } + + // and draw the drag start + if (gFocusMgr.getMouseCapture() == this) + { + gl_rect_2d(mDragStartThumbRect, mThumbCenterColor.get() % opacity, FALSE); + } + else if (hoverSldrIt != mThumbRects.end()) + { + gl_rect_2d(hoverSldrIt->second, mThumbCenterSelectedColor.get(), TRUE); + } + } + else + { + LLMouseHandler* capture = gFocusMgr.getMouseCapture(); + if (capture == this) + { + // draw drag start (ghost) + if (mThumbImagep) + { + mThumbImagep->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); + } + else + { mRoundedSquareImgp->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); - } - } - - // draw the highlight - if (hasFocus()) - { - if (!mCurSlider.empty()) - { - if (mThumbImagep) - { - mThumbImagep->drawBorder(mThumbRects[mCurSlider], mThumbHighlightColor, gFocusMgr.getFocusFlashWidth()); - } - else - { + } + } + + // draw the highlight + if (hasFocus()) + { + if (!mCurSlider.empty()) + { + if (mThumbImagep) + { + mThumbImagep->drawBorder(mThumbRects[mCurSlider], mThumbHighlightColor, gFocusMgr.getFocusFlashWidth()); + } + else + { mRoundedSquareImgp->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); - } - } - } + } + } + } if (!mHoverSlider.empty()) { if (mThumbImagep) @@ -787,94 +787,94 @@ void LLMultiSlider::draw() } } - // draw the thumbs - curSldrIt = mThumbRects.end(); - hoverSldrIt = mThumbRects.end(); - for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) - { - // choose the color - curThumbColor = mThumbCenterColor.get(); - if(mIt->first == mCurSlider) - { - // don't draw now, draw last - curSldrIt = mIt; - continue; - } - if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this) - { - // don't draw now, draw last, after current one - hoverSldrIt = mIt; - continue; - } - - // the draw command - if (mThumbImagep) - { - if (getEnabled()) - { - mThumbImagep->draw(mIt->second); - } - else - { - mThumbImagep->draw(mIt->second, LLColor4::grey % 0.8f); - } - } - else if (capture == this) - { + // draw the thumbs + curSldrIt = mThumbRects.end(); + hoverSldrIt = mThumbRects.end(); + for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) + { + // choose the color + curThumbColor = mThumbCenterColor.get(); + if(mIt->first == mCurSlider) + { + // don't draw now, draw last + curSldrIt = mIt; + continue; + } + if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this) + { + // don't draw now, draw last, after current one + hoverSldrIt = mIt; + continue; + } + + // the draw command + if (mThumbImagep) + { + if (getEnabled()) + { + mThumbImagep->draw(mIt->second); + } + else + { + mThumbImagep->draw(mIt->second, LLColor4::grey % 0.8f); + } + } + else if (capture == this) + { mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor); - } - else - { + } + else + { mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor % opacity); - } - } - - // draw cur and hover slider last - if(curSldrIt != mThumbRects.end()) - { - if (mThumbImagep) - { - if (getEnabled()) - { - mThumbImagep->draw(curSldrIt->second); - } - else - { - mThumbImagep->draw(curSldrIt->second, LLColor4::grey % 0.8f); - } - } - else if (capture == this) - { + } + } + + // draw cur and hover slider last + if(curSldrIt != mThumbRects.end()) + { + if (mThumbImagep) + { + if (getEnabled()) + { + mThumbImagep->draw(curSldrIt->second); + } + else + { + mThumbImagep->draw(curSldrIt->second, LLColor4::grey % 0.8f); + } + } + else if (capture == this) + { mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get()); - } - else - { + } + else + { mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity); - } - } - if(hoverSldrIt != mThumbRects.end()) - { - if (mThumbImagep) - { - mThumbImagep->draw(hoverSldrIt->second); - } - else - { + } + } + if(hoverSldrIt != mThumbRects.end()) + { + if (mThumbImagep) + { + mThumbImagep->draw(hoverSldrIt->second); + } + else + { mRoundedSquareImgp->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get()); - } - } - } + } + } + } - LLF32UICtrl::draw(); + LLF32UICtrl::draw(); } -boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) -{ - if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); - return mMouseDownSignal->connect(cb); +boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); + return mMouseDownSignal->connect(cb); } -boost::signals2::connection LLMultiSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb ) -{ - if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); - return mMouseUpSignal->connect(cb); +boost::signals2::connection LLMultiSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); + return mMouseUpSignal->connect(cb); } diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index 3cb4b760b0..963c6e5fab 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -1,25 +1,25 @@ -/** +/** * @file llmultislider.h * @brief A simple multislider * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,127 +35,127 @@ class LLUICtrlFactory; class LLMultiSlider : public LLF32UICtrl { public: - struct SliderParams : public LLInitParam::Block - { - Optional name; - Mandatory value; - SliderParams(); - }; - - struct Params : public LLInitParam::Block - { - Optional max_sliders; - - Optional allow_overlap, - loop_overlap, - draw_track, - use_triangle; - - Optional overlap_threshold; - - Optional track_color, - thumb_disabled_color, - thumb_highlight_color, - thumb_outline_color, - thumb_center_color, - thumb_center_selected_color, - triangle_color; - - Optional orientation, - thumb_image; - - Optional mouse_down_callback, - mouse_up_callback; - Optional thumb_width; - - Multiple sliders; - Params(); - }; + struct SliderParams : public LLInitParam::Block + { + Optional name; + Mandatory value; + SliderParams(); + }; + + struct Params : public LLInitParam::Block + { + Optional max_sliders; + + Optional allow_overlap, + loop_overlap, + draw_track, + use_triangle; + + Optional overlap_threshold; + + Optional track_color, + thumb_disabled_color, + thumb_highlight_color, + thumb_outline_color, + thumb_center_color, + thumb_center_selected_color, + triangle_color; + + Optional orientation, + thumb_image; + + Optional mouse_down_callback, + mouse_up_callback; + Optional thumb_width; + + Multiple sliders; + Params(); + }; protected: - LLMultiSlider(const Params&); - friend class LLUICtrlFactory; + LLMultiSlider(const Params&); + friend class LLUICtrlFactory; public: - virtual ~LLMultiSlider(); + virtual ~LLMultiSlider(); // Multi-slider rounds values to nearest increments (bias towards rounding down) - F32 getNearestIncrement(F32 value) const; + F32 getNearestIncrement(F32 value) const; - void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); - F32 getSliderValue(const std::string& name) const; - F32 getSliderValueFromPos(S32 xpos, S32 ypos) const; + void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); + F32 getSliderValue(const std::string& name) const; + F32 getSliderValueFromPos(S32 xpos, S32 ypos) const; LLRect getSliderThumbRect(const std::string& name) const; void setSliderThumbImage(const std::string &name); void clearSliderThumbImage(); - const std::string& getCurSlider() const { return mCurSlider; } - F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } - void setCurSlider(const std::string& name); - void resetCurSlider(); - void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } + const std::string& getCurSlider() const { return mCurSlider; } + F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } + void setCurSlider(const std::string& name); + void resetCurSlider(); + void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } - /*virtual*/ void setValue(const LLSD& value) override; - /*virtual*/ LLSD getValue() const override { return mValue; } + /*virtual*/ void setValue(const LLSD& value) override; + /*virtual*/ LLSD getValue() const override { return mValue; } - boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); - boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); - bool findUnusedValue(F32& initVal); - const std::string& addSlider(); - const std::string& addSlider(F32 val); - bool addSlider(F32 val, const std::string& name); - void deleteSlider(const std::string& name); - void deleteCurSlider() { deleteSlider(mCurSlider); } - /*virtual*/ void clear() override; + bool findUnusedValue(F32& initVal); + const std::string& addSlider(); + const std::string& addSlider(F32 val); + bool addSlider(F32 val, const std::string& name); + void deleteSlider(const std::string& name); + void deleteCurSlider() { deleteSlider(mCurSlider); } + /*virtual*/ void clear() override; - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask) override; - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override; - /*virtual*/ void draw() override; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask) override; + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override; + /*virtual*/ void draw() override; - S32 getMaxNumSliders() { return mMaxNumSliders; } - S32 getCurNumSliders() { return mValue.size(); } - F32 getOverlapThreshold() { return mOverlapThreshold; } - bool canAddSliders() { return mValue.size() < mMaxNumSliders; } + S32 getMaxNumSliders() { return mMaxNumSliders; } + S32 getCurNumSliders() { return mValue.size(); } + F32 getOverlapThreshold() { return mOverlapThreshold; } + bool canAddSliders() { return mValue.size() < mMaxNumSliders; } protected: - LLSD mValue; - std::string mCurSlider; - std::string mHoverSlider; - static S32 mNameCounter; - - S32 mMaxNumSliders; - BOOL mAllowOverlap; - BOOL mLoopOverlap; - F32 mOverlapThreshold; - BOOL mDrawTrack; - BOOL mUseTriangle; /// hacked in toggle to use a triangle - - S32 mMouseOffset; - LLRect mDragStartThumbRect; - S32 mThumbWidth; - - std::map - mThumbRects; - LLUIColor mTrackColor; - LLUIColor mThumbOutlineColor; - LLUIColor mThumbHighlightColor; - LLUIColor mThumbCenterColor; - LLUIColor mThumbCenterSelectedColor; - LLUIColor mDisabledThumbColor; - LLUIColor mTriangleColor; - LLUIImagePtr mThumbImagep; //blimps on the slider, for now no 'disabled' support - LLUIImagePtr mRoundedSquareImgp; //blimps on the slider, for now no 'disabled' support - - const EOrientation mOrientation; - - commit_signal_t* mMouseDownSignal; - commit_signal_t* mMouseUpSignal; + LLSD mValue; + std::string mCurSlider; + std::string mHoverSlider; + static S32 mNameCounter; + + S32 mMaxNumSliders; + BOOL mAllowOverlap; + BOOL mLoopOverlap; + F32 mOverlapThreshold; + BOOL mDrawTrack; + BOOL mUseTriangle; /// hacked in toggle to use a triangle + + S32 mMouseOffset; + LLRect mDragStartThumbRect; + S32 mThumbWidth; + + std::map + mThumbRects; + LLUIColor mTrackColor; + LLUIColor mThumbOutlineColor; + LLUIColor mThumbHighlightColor; + LLUIColor mThumbCenterColor; + LLUIColor mThumbCenterSelectedColor; + LLUIColor mDisabledThumbColor; + LLUIColor mTriangleColor; + LLUIImagePtr mThumbImagep; //blimps on the slider, for now no 'disabled' support + LLUIImagePtr mRoundedSquareImgp; //blimps on the slider, for now no 'disabled' support + + const EOrientation mOrientation; + + commit_signal_t* mMouseDownSignal; + commit_signal_t* mMouseUpSignal; }; #endif // LL_MULTI_SLIDER_H diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index b3df7c154b..5319b0d3b6 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmultisliderctrl.cpp * @brief LLMultiSliderCtrl base class * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,479 +47,479 @@ static LLDefaultChildRegistry::Register r("multi_slider"); const U32 MAX_STRING_LENGTH = 10; LLMultiSliderCtrl::Params::Params() -: text_width("text_width"), - label_width("label_width"), - show_text("show_text", true), - can_edit_text("can_edit_text", false), - max_sliders("max_sliders", 1), - allow_overlap("allow_overlap", false), - loop_overlap("loop_overlap", false), - orientation("orientation"), - thumb_image("thumb_image"), - thumb_width("thumb_width"), - thumb_highlight_color("thumb_highlight_color"), - overlap_threshold("overlap_threshold", 0), - draw_track("draw_track", true), - use_triangle("use_triangle", false), - decimal_digits("decimal_digits", 3), - text_color("text_color"), - text_disabled_color("text_disabled_color"), - mouse_down_callback("mouse_down_callback"), - mouse_up_callback("mouse_up_callback"), - sliders("slider") +: text_width("text_width"), + label_width("label_width"), + show_text("show_text", true), + can_edit_text("can_edit_text", false), + max_sliders("max_sliders", 1), + allow_overlap("allow_overlap", false), + loop_overlap("loop_overlap", false), + orientation("orientation"), + thumb_image("thumb_image"), + thumb_width("thumb_width"), + thumb_highlight_color("thumb_highlight_color"), + overlap_threshold("overlap_threshold", 0), + draw_track("draw_track", true), + use_triangle("use_triangle", false), + decimal_digits("decimal_digits", 3), + text_color("text_color"), + text_disabled_color("text_disabled_color"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + sliders("slider") { - mouse_opaque = true; + mouse_opaque = true; } - + LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) -: LLF32UICtrl(p), - mLabelBox( NULL ), - mEditor( NULL ), - mTextBox( NULL ), - mTextEnabledColor(p.text_color()), - mTextDisabledColor(p.text_disabled_color()) +: LLF32UICtrl(p), + mLabelBox( NULL ), + mEditor( NULL ), + mTextBox( NULL ), + mTextEnabledColor(p.text_color()), + mTextDisabledColor(p.text_disabled_color()) { - static LLUICachedControl multi_sliderctrl_spacing ("UIMultiSliderctrlSpacing", 0); - - S32 top = getRect().getHeight(); - S32 bottom = 0; - S32 left = 0; - - S32 label_width = p.label_width; - S32 text_width = p.text_width; - - // Label - if( !p.label().empty() ) - { - if (p.label_width == 0) - { - label_width = p.font()->getWidth(p.label); - } - LLRect label_rect( left, top, label_width, bottom ); - LLTextBox::Params params; - params.name("MultiSliderCtrl Label"); - params.rect(label_rect); - params.initial_value(p.label()); - params.font(p.font); - mLabelBox = LLUICtrlFactory::create (params); - addChild(mLabelBox); - } - - S32 slider_right = getRect().getWidth(); - - if (p.show_text) - { - if (!p.text_width.isProvided()) - { - text_width = 0; - // calculate the size of the text box (log max_value is number of digits - 1 so plus 1) - if ( p.max_value() ) - text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( p.max_value ) ) + p.decimal_digits + 1 ); - - if ( p.increment < 1.0f ) - text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value - - if ( p.min_value < 0.0f || p.max_value < 0.0f ) - text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign - - // padding to make things look nicer - text_width += 8; - } - S32 text_left = getRect().getWidth() - text_width; - - slider_right = text_left - multi_sliderctrl_spacing; - - LLRect text_rect( text_left, top, getRect().getWidth(), bottom ); - if( p.can_edit_text ) - { - LLLineEditor::Params params; - params.name("MultiSliderCtrl Editor"); - params.rect(text_rect); - params.font(p.font); - params.max_length.bytes(MAX_STRING_LENGTH); - params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit); - params.prevalidate_callback(&LLTextValidate::validateFloat); - params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); - mEditor = LLUICtrlFactory::create (params); - mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) ); - // don't do this, as selecting the entire text is single clicking in some cases - // and double clicking in others - //mEditor->setSelectAllonFocusReceived(TRUE); - addChild(mEditor); - } - else - { - LLTextBox::Params params; - params.name("MultiSliderCtrl Text"); - params.rect(text_rect); - params.font(p.font); - params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); - mTextBox = LLUICtrlFactory::create (params); - addChild(mTextBox); - } - } - - S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0; - LLRect slider_rect( slider_left, top, slider_right, bottom ); - LLMultiSlider::Params params; - params.sliders = p.sliders; - params.rect(slider_rect); - params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit ); - params.mouse_down_callback( p.mouse_down_callback ); - params.mouse_up_callback( p.mouse_up_callback ); - params.initial_value(p.initial_value()); - params.min_value(p.min_value); - params.max_value(p.max_value); - params.increment(p.increment); - params.max_sliders(p.max_sliders); - params.allow_overlap(p.allow_overlap); - params.loop_overlap(p.loop_overlap); - if (p.overlap_threshold.isProvided()) - { - params.overlap_threshold = p.overlap_threshold; - } - params.orientation(p.orientation); - params.thumb_image(p.thumb_image); - params.thumb_highlight_color(p.thumb_highlight_color); - if (p.thumb_width.isProvided()) - { - // otherwise should be provided by template - params.thumb_width(p.thumb_width); - } - params.draw_track(p.draw_track); - params.use_triangle(p.use_triangle); - params.control_name(p.control_name); - mMultiSlider = LLUICtrlFactory::create (params); - addChild( mMultiSlider ); - mCurValue = mMultiSlider->getCurSliderValue(); - - - updateText(); + static LLUICachedControl multi_sliderctrl_spacing ("UIMultiSliderctrlSpacing", 0); + + S32 top = getRect().getHeight(); + S32 bottom = 0; + S32 left = 0; + + S32 label_width = p.label_width; + S32 text_width = p.text_width; + + // Label + if( !p.label().empty() ) + { + if (p.label_width == 0) + { + label_width = p.font()->getWidth(p.label); + } + LLRect label_rect( left, top, label_width, bottom ); + LLTextBox::Params params; + params.name("MultiSliderCtrl Label"); + params.rect(label_rect); + params.initial_value(p.label()); + params.font(p.font); + mLabelBox = LLUICtrlFactory::create (params); + addChild(mLabelBox); + } + + S32 slider_right = getRect().getWidth(); + + if (p.show_text) + { + if (!p.text_width.isProvided()) + { + text_width = 0; + // calculate the size of the text box (log max_value is number of digits - 1 so plus 1) + if ( p.max_value() ) + text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( p.max_value ) ) + p.decimal_digits + 1 ); + + if ( p.increment < 1.0f ) + text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value + + if ( p.min_value < 0.0f || p.max_value < 0.0f ) + text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign + + // padding to make things look nicer + text_width += 8; + } + S32 text_left = getRect().getWidth() - text_width; + + slider_right = text_left - multi_sliderctrl_spacing; + + LLRect text_rect( text_left, top, getRect().getWidth(), bottom ); + if( p.can_edit_text ) + { + LLLineEditor::Params params; + params.name("MultiSliderCtrl Editor"); + params.rect(text_rect); + params.font(p.font); + params.max_length.bytes(MAX_STRING_LENGTH); + params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit); + params.prevalidate_callback(&LLTextValidate::validateFloat); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + mEditor = LLUICtrlFactory::create (params); + mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) ); + // don't do this, as selecting the entire text is single clicking in some cases + // and double clicking in others + //mEditor->setSelectAllonFocusReceived(TRUE); + addChild(mEditor); + } + else + { + LLTextBox::Params params; + params.name("MultiSliderCtrl Text"); + params.rect(text_rect); + params.font(p.font); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + mTextBox = LLUICtrlFactory::create (params); + addChild(mTextBox); + } + } + + S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0; + LLRect slider_rect( slider_left, top, slider_right, bottom ); + LLMultiSlider::Params params; + params.sliders = p.sliders; + params.rect(slider_rect); + params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit ); + params.mouse_down_callback( p.mouse_down_callback ); + params.mouse_up_callback( p.mouse_up_callback ); + params.initial_value(p.initial_value()); + params.min_value(p.min_value); + params.max_value(p.max_value); + params.increment(p.increment); + params.max_sliders(p.max_sliders); + params.allow_overlap(p.allow_overlap); + params.loop_overlap(p.loop_overlap); + if (p.overlap_threshold.isProvided()) + { + params.overlap_threshold = p.overlap_threshold; + } + params.orientation(p.orientation); + params.thumb_image(p.thumb_image); + params.thumb_highlight_color(p.thumb_highlight_color); + if (p.thumb_width.isProvided()) + { + // otherwise should be provided by template + params.thumb_width(p.thumb_width); + } + params.draw_track(p.draw_track); + params.use_triangle(p.use_triangle); + params.control_name(p.control_name); + mMultiSlider = LLUICtrlFactory::create (params); + addChild( mMultiSlider ); + mCurValue = mMultiSlider->getCurSliderValue(); + + + updateText(); } LLMultiSliderCtrl::~LLMultiSliderCtrl() { - // Children all cleaned up by default view destructor. + // Children all cleaned up by default view destructor. } // static void LLMultiSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata ) { - LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata; - llassert( caller == self->mEditor ); + LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata; + llassert( caller == self->mEditor ); - self->onFocusReceived(); + self->onFocusReceived(); } void LLMultiSliderCtrl::setValue(const LLSD& value) { - mMultiSlider->setValue(value); - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); + mMultiSlider->setValue(value); + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); } void LLMultiSliderCtrl::setSliderValue(const std::string& name, F32 v, BOOL from_event) { - mMultiSlider->setSliderValue(name, v, from_event ); - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); + mMultiSlider->setSliderValue(name, v, from_event ); + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); } void LLMultiSliderCtrl::setCurSlider(const std::string& name) { - mMultiSlider->setCurSlider(name); - mCurValue = mMultiSlider->getCurSliderValue(); + mMultiSlider->setCurSlider(name); + mCurValue = mMultiSlider->getCurSliderValue(); } void LLMultiSliderCtrl::resetCurSlider() { - mMultiSlider->resetCurSlider(); + mMultiSlider->resetCurSlider(); } BOOL LLMultiSliderCtrl::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - BOOL res = FALSE; - if (mLabelBox) - { - res = mLabelBox->setTextArg(key, text); - if (res && mLabelWidth == 0) - { - S32 label_width = mFont->getWidth(mLabelBox->getText()); - LLRect rect = mLabelBox->getRect(); - S32 prev_right = rect.mRight; - rect.mRight = rect.mLeft + label_width; - mLabelBox->setRect(rect); - - S32 delta = rect.mRight - prev_right; - rect = mMultiSlider->getRect(); - S32 left = rect.mLeft + delta; - static LLUICachedControl multi_slider_ctrl_spacing ("UIMultiSliderctrlSpacing", 0); - left = llclamp(left, 0, rect.mRight - multi_slider_ctrl_spacing); - rect.mLeft = left; - mMultiSlider->setRect(rect); - } - } - return res; + BOOL res = FALSE; + if (mLabelBox) + { + res = mLabelBox->setTextArg(key, text); + if (res && mLabelWidth == 0) + { + S32 label_width = mFont->getWidth(mLabelBox->getText()); + LLRect rect = mLabelBox->getRect(); + S32 prev_right = rect.mRight; + rect.mRight = rect.mLeft + label_width; + mLabelBox->setRect(rect); + + S32 delta = rect.mRight - prev_right; + rect = mMultiSlider->getRect(); + S32 left = rect.mLeft + delta; + static LLUICachedControl multi_slider_ctrl_spacing ("UIMultiSliderctrlSpacing", 0); + left = llclamp(left, 0, rect.mRight - multi_slider_ctrl_spacing); + rect.mLeft = left; + mMultiSlider->setRect(rect); + } + } + return res; } const std::string& LLMultiSliderCtrl::addSlider() { - const std::string& name = mMultiSlider->addSlider(); - - // if it returns null, pass it on - if(name == LLStringUtil::null) { - return LLStringUtil::null; - } - - // otherwise, update stuff - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); - return name; + const std::string& name = mMultiSlider->addSlider(); + + // if it returns null, pass it on + if(name == LLStringUtil::null) { + return LLStringUtil::null; + } + + // otherwise, update stuff + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); + return name; } const std::string& LLMultiSliderCtrl::addSlider(F32 val) { - const std::string& name = mMultiSlider->addSlider(val); + const std::string& name = mMultiSlider->addSlider(val); - // if it returns null, pass it on - if(name == LLStringUtil::null) { - return LLStringUtil::null; - } + // if it returns null, pass it on + if(name == LLStringUtil::null) { + return LLStringUtil::null; + } - // otherwise, update stuff - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); - return name; + // otherwise, update stuff + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); + return name; } bool LLMultiSliderCtrl::addSlider(F32 val, const std::string& name) { - bool res = mMultiSlider->addSlider(val, name); - if (res) - { - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); - } - return res; + bool res = mMultiSlider->addSlider(val, name); + if (res) + { + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); + } + return res; } void LLMultiSliderCtrl::deleteSlider(const std::string& name) { - mMultiSlider->deleteSlider(name); - mCurValue = mMultiSlider->getCurSliderValue(); - updateText(); + mMultiSlider->deleteSlider(name); + mCurValue = mMultiSlider->getCurSliderValue(); + updateText(); } void LLMultiSliderCtrl::clear() { - setCurSliderValue(0.0f); - if( mEditor ) - { - mEditor->setText(std::string("")); - } - if( mTextBox ) - { - mTextBox->setText(std::string("")); - } - - // get rid of sliders - mMultiSlider->clear(); + setCurSliderValue(0.0f); + if( mEditor ) + { + mEditor->setText(std::string("")); + } + if( mTextBox ) + { + mTextBox->setText(std::string("")); + } + + // get rid of sliders + mMultiSlider->clear(); } BOOL LLMultiSliderCtrl::isMouseHeldDown() { - return gFocusMgr.getMouseCapture() == mMultiSlider; + return gFocusMgr.getMouseCapture() == mMultiSlider; } void LLMultiSliderCtrl::updateText() { - if( mEditor || mTextBox ) - { - LLLocale locale(LLLocale::USER_LOCALE); - - // Don't display very small negative values as -0.000 - F32 displayed_value = (F32)(floor(getCurSliderValue() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision)); - - std::string format = llformat("%%.%df", mPrecision); - std::string text = llformat(format.c_str(), displayed_value); - if( mEditor ) - { - mEditor->setText( text ); - } - else - { - mTextBox->setText( text ); - } - } + if( mEditor || mTextBox ) + { + LLLocale locale(LLLocale::USER_LOCALE); + + // Don't display very small negative values as -0.000 + F32 displayed_value = (F32)(floor(getCurSliderValue() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision)); + + std::string format = llformat("%%.%df", mPrecision); + std::string text = llformat(format.c_str(), displayed_value); + if( mEditor ) + { + mEditor->setText( text ); + } + else + { + mTextBox->setText( text ); + } + } } // static void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata) { - llassert(ctrl); - if (!ctrl) - return; - - LLMultiSliderCtrl* self = dynamic_cast(ctrl->getParent()); - llassert(self); - if (!self) // cast failed - wrong type! :O - return; - - BOOL success = FALSE; - F32 val = self->mCurValue; - F32 saved_val = self->mCurValue; - - std::string text = self->mEditor->getText(); - if( LLLineEditor::postvalidateFloat( text ) ) - { - LLLocale locale(LLLocale::USER_LOCALE); - val = (F32) atof( text.c_str() ); - if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() ) - { - self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it. - if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) ) - { - success = TRUE; - } - } - } - - if( success ) - { - self->onCommit(); - } - else - { - if( self->getCurSliderValue() != saved_val ) - { - self->setCurSliderValue( saved_val ); - } - self->reportInvalidData(); - } - self->updateText(); + llassert(ctrl); + if (!ctrl) + return; + + LLMultiSliderCtrl* self = dynamic_cast(ctrl->getParent()); + llassert(self); + if (!self) // cast failed - wrong type! :O + return; + + BOOL success = FALSE; + F32 val = self->mCurValue; + F32 saved_val = self->mCurValue; + + std::string text = self->mEditor->getText(); + if( LLLineEditor::postvalidateFloat( text ) ) + { + LLLocale locale(LLLocale::USER_LOCALE); + val = (F32) atof( text.c_str() ); + if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() ) + { + self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it. + if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) ) + { + success = TRUE; + } + } + } + + if( success ) + { + self->onCommit(); + } + else + { + if( self->getCurSliderValue() != saved_val ) + { + self->setCurSliderValue( saved_val ); + } + self->reportInvalidData(); + } + self->updateText(); } // static void LLMultiSliderCtrl::onSliderCommit(LLUICtrl* ctrl, const LLSD& userdata) { - LLMultiSliderCtrl* self = dynamic_cast(ctrl->getParent()); - if (!self) - return; - - BOOL success = FALSE; - F32 saved_val = self->mCurValue; - F32 new_val = self->mMultiSlider->getCurSliderValue(); - - self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it. - if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) ) - { - success = TRUE; - } - - if( success ) - { - self->onCommit(); - } - else - { - if( self->mCurValue != saved_val ) - { - self->setCurSliderValue( saved_val ); - } - self->reportInvalidData(); - } - self->updateText(); + LLMultiSliderCtrl* self = dynamic_cast(ctrl->getParent()); + if (!self) + return; + + BOOL success = FALSE; + F32 saved_val = self->mCurValue; + F32 new_val = self->mMultiSlider->getCurSliderValue(); + + self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it. + if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) ) + { + success = TRUE; + } + + if( success ) + { + self->onCommit(); + } + else + { + if( self->mCurValue != saved_val ) + { + self->setCurSliderValue( saved_val ); + } + self->reportInvalidData(); + } + self->updateText(); } void LLMultiSliderCtrl::setEnabled(BOOL b) { - LLF32UICtrl::setEnabled( b ); + LLF32UICtrl::setEnabled( b ); - if( mLabelBox ) - { - mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() ); - } + if( mLabelBox ) + { + mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() ); + } - mMultiSlider->setEnabled( b ); + mMultiSlider->setEnabled( b ); - if( mEditor ) - { - mEditor->setEnabled( b ); - } + if( mEditor ) + { + mEditor->setEnabled( b ); + } - if( mTextBox ) - { - mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() ); - } + if( mTextBox ) + { + mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() ); + } } void LLMultiSliderCtrl::setTentative(BOOL b) { - if( mEditor ) - { - mEditor->setTentative(b); - } - LLF32UICtrl::setTentative(b); + if( mEditor ) + { + mEditor->setTentative(b); + } + LLF32UICtrl::setTentative(b); } void LLMultiSliderCtrl::onCommit() { - setTentative(FALSE); + setTentative(FALSE); - if( mEditor ) - { - mEditor->setTentative(FALSE); - } + if( mEditor ) + { + mEditor->setTentative(FALSE); + } - setControlValue(getValueF32()); - LLF32UICtrl::onCommit(); + setControlValue(getValueF32()); + LLF32UICtrl::onCommit(); } void LLMultiSliderCtrl::setPrecision(S32 precision) { - if (precision < 0 || precision > 10) - { - LL_ERRS() << "LLMultiSliderCtrl::setPrecision - precision out of range" << LL_ENDL; - return; - } - - mPrecision = precision; - updateText(); + if (precision < 0 || precision > 10) + { + LL_ERRS() << "LLMultiSliderCtrl::setPrecision - precision out of range" << LL_ENDL; + return; + } + + mPrecision = precision; + updateText(); } boost::signals2::connection LLMultiSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ) { - return mMultiSlider->setMouseDownCallback( cb ); + return mMultiSlider->setMouseDownCallback( cb ); } boost::signals2::connection LLMultiSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ) { - return mMultiSlider->setMouseUpCallback( cb ); + return mMultiSlider->setMouseUpCallback( cb ); } void LLMultiSliderCtrl::onTabInto() { - if( mEditor ) - { - mEditor->onTabInto(); - } + if( mEditor ) + { + mEditor->onTabInto(); + } LLF32UICtrl::onTabInto(); } void LLMultiSliderCtrl::reportInvalidData() { - make_ui_sound("UISndBadKeystroke"); + make_ui_sound("UISndBadKeystroke"); } // virtual void LLMultiSliderCtrl::setControlName(const std::string& control_name, LLView* context) { - mMultiSlider->setControlName(control_name, context); + mMultiSlider->setControlName(control_name, context); } diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index adb28676ec..e3b190a938 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -1,25 +1,25 @@ -/** +/** * @file llmultisliderctrl.h * @brief LLMultiSliderCtrl base class * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,130 +45,130 @@ class LLSlider; class LLMultiSliderCtrl : public LLF32UICtrl { public: - struct Params : public LLInitParam::Block - { - Optional label_width, - text_width; - Optional show_text, - can_edit_text; - Optional decimal_digits, - thumb_width; - Optional max_sliders; - Optional allow_overlap, - loop_overlap, - draw_track, - use_triangle; + struct Params : public LLInitParam::Block + { + Optional label_width, + text_width; + Optional show_text, + can_edit_text; + Optional decimal_digits, + thumb_width; + Optional max_sliders; + Optional allow_overlap, + loop_overlap, + draw_track, + use_triangle; - Optional orientation, - thumb_image; + Optional orientation, + thumb_image; - Optional overlap_threshold; + Optional overlap_threshold; - Optional text_color, - text_disabled_color, - thumb_highlight_color; + Optional text_color, + text_disabled_color, + thumb_highlight_color; - Optional mouse_down_callback, - mouse_up_callback; + Optional mouse_down_callback, + mouse_up_callback; - Multiple sliders; + Multiple sliders; - Params(); - }; + Params(); + }; protected: - LLMultiSliderCtrl(const Params&); - friend class LLUICtrlFactory; + LLMultiSliderCtrl(const Params&); + friend class LLUICtrlFactory; public: - virtual ~LLMultiSliderCtrl(); + virtual ~LLMultiSliderCtrl(); - F32 getSliderValue(const std::string& name) const { return mMultiSlider->getSliderValue(name); } - void setSliderValue(const std::string& name, F32 v, BOOL from_event = FALSE); + F32 getSliderValue(const std::string& name) const { return mMultiSlider->getSliderValue(name); } + void setSliderValue(const std::string& name, F32 v, BOOL from_event = FALSE); - virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const { return mMultiSlider->getValue(); } - virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + virtual void setValue(const LLSD& value ); + virtual LLSD getValue() const { return mMultiSlider->getValue(); } + virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - const std::string& getCurSlider() const { return mMultiSlider->getCurSlider(); } - F32 getCurSliderValue() const { return mCurValue; } - void setCurSlider(const std::string& name); - void resetCurSlider(); - void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); } + const std::string& getCurSlider() const { return mMultiSlider->getCurSlider(); } + F32 getCurSliderValue() const { return mCurValue; } + void setCurSlider(const std::string& name); + void resetCurSlider(); + void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); } - virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } - virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } - BOOL isMouseHeldDown(); + BOOL isMouseHeldDown(); - virtual void setEnabled( BOOL b ); - virtual void clear(); - virtual void setPrecision(S32 precision); - void setMinValue(F32 min_value) {mMultiSlider->setMinValue(min_value);} - void setMaxValue(F32 max_value) {mMultiSlider->setMaxValue(max_value);} - void setIncrement(F32 increment) {mMultiSlider->setIncrement(increment);} + virtual void setEnabled( BOOL b ); + virtual void clear(); + virtual void setPrecision(S32 precision); + void setMinValue(F32 min_value) {mMultiSlider->setMinValue(min_value);} + void setMaxValue(F32 max_value) {mMultiSlider->setMaxValue(max_value);} + void setIncrement(F32 increment) {mMultiSlider->setIncrement(increment);} - F32 getNearestIncrement(F32 value) const { return mMultiSlider->getNearestIncrement(value); } - F32 getSliderValueFromPos(S32 x, S32 y) const { return mMultiSlider->getSliderValueFromPos(x, y); } + F32 getNearestIncrement(F32 value) const { return mMultiSlider->getNearestIncrement(value); } + F32 getSliderValueFromPos(S32 x, S32 y) const { return mMultiSlider->getSliderValueFromPos(x, y); } LLRect getSliderThumbRect(const std::string &name) const { return mMultiSlider->getSliderThumbRect(name); } void setSliderThumbImage(const std::string &name) { mMultiSlider->setSliderThumbImage(name); } void clearSliderThumbImage() { mMultiSlider->clearSliderThumbImage(); } - /// for adding and deleting sliders - const std::string& addSlider(); - const std::string& addSlider(F32 val); - bool addSlider(F32 val, const std::string& name); - void deleteSlider(const std::string& name); - void deleteCurSlider() { deleteSlider(mMultiSlider->getCurSlider()); } + /// for adding and deleting sliders + const std::string& addSlider(); + const std::string& addSlider(F32 val); + bool addSlider(F32 val, const std::string& name); + void deleteSlider(const std::string& name); + void deleteCurSlider() { deleteSlider(mMultiSlider->getCurSlider()); } + + F32 getMinValue() const { return mMultiSlider->getMinValue(); } + F32 getMaxValue() const { return mMultiSlider->getMaxValue(); } + + S32 getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); } + S32 getCurNumSliders() { return mMultiSlider->getCurNumSliders(); } + F32 getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); } + bool canAddSliders() { return mMultiSlider->canAddSliders(); } - F32 getMinValue() const { return mMultiSlider->getMinValue(); } - F32 getMaxValue() const { return mMultiSlider->getMaxValue(); } + void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); } + void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } + void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; } - S32 getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); } - S32 getCurNumSliders() { return mMultiSlider->getCurNumSliders(); } - F32 getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); } - bool canAddSliders() { return mMultiSlider->canAddSliders(); } + boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ); - void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); } - void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } - void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; } + virtual void onTabInto(); - boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ); - boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ); + virtual void setTentative(BOOL b); // marks value as tentative + virtual void onCommit(); // mark not tentative, then commit - virtual void onTabInto(); + virtual void setControlName(const std::string& control_name, LLView* context); - virtual void setTentative(BOOL b); // marks value as tentative - virtual void onCommit(); // mark not tentative, then commit + static void onSliderCommit(LLUICtrl* caller, const LLSD& userdata); - virtual void setControlName(const std::string& control_name, LLView* context); - - static void onSliderCommit(LLUICtrl* caller, const LLSD& userdata); - - static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); - static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); + static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); + static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); + static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); private: - void updateText(); - void reportInvalidData(); + void updateText(); + void reportInvalidData(); private: - const LLFontGL* mFont; - BOOL mShowText; - BOOL mCanEditText; + const LLFontGL* mFont; + BOOL mShowText; + BOOL mCanEditText; - S32 mPrecision; - LLTextBox* mLabelBox; - S32 mLabelWidth; + S32 mPrecision; + LLTextBox* mLabelBox; + S32 mLabelWidth; - F32 mCurValue; - LLMultiSlider* mMultiSlider; - LLLineEditor* mEditor; - LLTextBox* mTextBox; + F32 mCurValue; + LLMultiSlider* mMultiSlider; + LLLineEditor* mEditor; + LLTextBox* mTextBox; - LLUIColor mTextEnabledColor; - LLUIColor mTextDisabledColor; + LLUIColor mTextEnabledColor; + LLUIColor mTextDisabledColor; }; #endif // LL_MULTI_SLIDERCTRL_H diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h index 580f353c7d..60ff7711a0 100644 --- a/indra/llui/llnotificationptr.h +++ b/indra/llui/llnotificationptr.h @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 907408f309..875be5bc6f 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -51,241 +51,241 @@ const std::string NOTIFICATION_PERSIST_VERSION = "0.93"; void NotificationPriorityValues::declareValues() { - declare("low", NOTIFICATION_PRIORITY_LOW); - declare("normal", NOTIFICATION_PRIORITY_NORMAL); - declare("high", NOTIFICATION_PRIORITY_HIGH); - declare("critical", NOTIFICATION_PRIORITY_CRITICAL); + declare("low", NOTIFICATION_PRIORITY_LOW); + declare("normal", NOTIFICATION_PRIORITY_NORMAL); + declare("high", NOTIFICATION_PRIORITY_HIGH); + declare("critical", NOTIFICATION_PRIORITY_CRITICAL); } LLNotificationForm::FormElementBase::FormElementBase() -: name("name"), - enabled("enabled", true) +: name("name"), + enabled("enabled", true) {} LLNotificationForm::FormIgnore::FormIgnore() -: text("text"), - control("control"), - invert_control("invert_control", false), - save_option("save_option", false), - session_only("session_only", false), - checkbox_only("checkbox_only", false) +: text("text"), + control("control"), + invert_control("invert_control", false), + save_option("save_option", false), + session_only("session_only", false), + checkbox_only("checkbox_only", false) {} LLNotificationForm::FormButton::FormButton() -: index("index"), - text("text"), - ignore("ignore"), - is_default("default"), - width("width", 0), - type("type") +: index("index"), + text("text"), + ignore("ignore"), + is_default("default"), + width("width", 0), + type("type") { - // set type here so it gets serialized - type = "button"; + // set type here so it gets serialized + type = "button"; } LLNotificationForm::FormInput::FormInput() -: type("type"), - text("text"), - max_length_chars("max_length_chars"), - width("width", 0), - value("value") +: type("type"), + text("text"), + max_length_chars("max_length_chars"), + width("width", 0), + value("value") {} LLNotificationForm::FormElement::FormElement() -: button("button"), - input("input") +: button("button"), + input("input") {} LLNotificationForm::FormElements::FormElements() -: elements("") +: elements("") {} LLNotificationForm::Params::Params() -: name("name"), - ignore("ignore"), - form_elements("") +: name("name"), + ignore("ignore"), + form_elements("") {} bool filterIgnoredNotifications(LLNotificationPtr notification) { - LLNotificationFormPtr form = notification->getForm(); - // Check to see if the user wants to ignore this alert - return !notification->getForm()->getIgnored(); + LLNotificationFormPtr form = notification->getForm(); + // Check to see if the user wants to ignore this alert + return !notification->getForm()->getIgnored(); } bool handleIgnoredNotification(const LLSD& payload) { - if (payload["sigtype"].asString() == "add") - { - LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); - if (!pNotif) return false; - - LLNotificationFormPtr form = pNotif->getForm(); - LLSD response; - switch(form->getIgnoreType()) - { - case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE: - case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY: - response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON); - break; - case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE: - response = LLUI::getInstance()->mSettingGroups["ignores"]->getLLSD("Default" + pNotif->getName()); - break; - case LLNotificationForm::IGNORE_SHOW_AGAIN: - break; - default: - return false; - } - pNotif->setIgnored(true); - pNotif->respond(response); - return true; // don't process this item any further - } - return false; + if (payload["sigtype"].asString() == "add") + { + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + if (!pNotif) return false; + + LLNotificationFormPtr form = pNotif->getForm(); + LLSD response; + switch(form->getIgnoreType()) + { + case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE: + case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY: + response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON); + break; + case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE: + response = LLUI::getInstance()->mSettingGroups["ignores"]->getLLSD("Default" + pNotif->getName()); + break; + case LLNotificationForm::IGNORE_SHOW_AGAIN: + break; + default: + return false; + } + pNotif->setIgnored(true); + pNotif->respond(response); + return true; // don't process this item any further + } + return false; } bool defaultResponse(const LLSD& payload) { - if (payload["sigtype"].asString() == "add") - { - LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); - if (pNotif) - { - // supply default response - pNotif->respond(pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON)); - } - } - return false; + if (payload["sigtype"].asString() == "add") + { + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + if (pNotif) + { + // supply default response + pNotif->respond(pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON)); + } + } + return false; } bool visibilityRuleMached(const LLSD& payload) { - // This is needed because LLNotifications::isVisibleByRules may have cancelled the notification. - // Returning true here makes LLNotificationChannelBase::updateItem do an early out, which prevents things from happening in the wrong order. - return true; + // This is needed because LLNotifications::isVisibleByRules may have cancelled the notification. + // Returning true here makes LLNotificationChannelBase::updateItem do an early out, which prevents things from happening in the wrong order. + return true; } namespace LLNotificationFilters { - // a sample filter - bool includeEverything(LLNotificationPtr p) - { - return true; - } + // a sample filter + bool includeEverything(LLNotificationPtr p) + { + return true; + } }; LLNotificationForm::LLNotificationForm() -: mIgnore(IGNORE_NO) +: mIgnore(IGNORE_NO) { } LLNotificationForm::LLNotificationForm( const LLNotificationForm& other ) { - mFormData = other.mFormData; - mIgnore = other.mIgnore; - mIgnoreMsg = other.mIgnoreMsg; - mIgnoreSetting = other.mIgnoreSetting; - mInvertSetting = other.mInvertSetting; -} - -LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p) -: mIgnore(IGNORE_NO), - mInvertSetting(false) // ignore settings by default mean true=show, false=ignore -{ - if (p.ignore.isProvided()) - { - // For all cases but IGNORE_CHECKBOX_ONLY this is name for use in preferences - mIgnoreMsg = p.ignore.text; - - LLUI *ui_inst = LLUI::getInstance(); - if (p.ignore.checkbox_only) - { - mIgnore = IGNORE_CHECKBOX_ONLY; - } - else if (!p.ignore.save_option) - { - mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE; - } - else - { - // remember last option chosen by user and automatically respond with that in the future - mIgnore = IGNORE_WITH_LAST_RESPONSE; - ui_inst->mSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name)); - } - - BOOL show_notification = TRUE; - if (p.ignore.control.isProvided()) - { - mIgnoreSetting = ui_inst->mSettingGroups["config"]->getControl(p.ignore.control); - mInvertSetting = p.ignore.invert_control; - } - else if (mIgnore > IGNORE_NO) - { - ui_inst->mSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT); - mIgnoreSetting = ui_inst->mSettingGroups["ignores"]->getControl(name); - } - } - - LLParamSDParser parser; - parser.writeSD(mFormData, p.form_elements); - - for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray(); - it != end_it; - ++it) - { - // lift contents of form element up a level, since element type is already encoded in "type" param - if (it->isMap() && it->beginMap() != it->endMap()) - { - *it = it->beginMap()->second; - } - } - - LL_DEBUGS("Notifications") << name << LL_ENDL; - LL_DEBUGS("Notifications") << ll_pretty_print_sd(mFormData) << LL_ENDL; + mFormData = other.mFormData; + mIgnore = other.mIgnore; + mIgnoreMsg = other.mIgnoreMsg; + mIgnoreSetting = other.mIgnoreSetting; + mInvertSetting = other.mInvertSetting; +} + +LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p) +: mIgnore(IGNORE_NO), + mInvertSetting(false) // ignore settings by default mean true=show, false=ignore +{ + if (p.ignore.isProvided()) + { + // For all cases but IGNORE_CHECKBOX_ONLY this is name for use in preferences + mIgnoreMsg = p.ignore.text; + + LLUI *ui_inst = LLUI::getInstance(); + if (p.ignore.checkbox_only) + { + mIgnore = IGNORE_CHECKBOX_ONLY; + } + else if (!p.ignore.save_option) + { + mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE; + } + else + { + // remember last option chosen by user and automatically respond with that in the future + mIgnore = IGNORE_WITH_LAST_RESPONSE; + ui_inst->mSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name)); + } + + BOOL show_notification = TRUE; + if (p.ignore.control.isProvided()) + { + mIgnoreSetting = ui_inst->mSettingGroups["config"]->getControl(p.ignore.control); + mInvertSetting = p.ignore.invert_control; + } + else if (mIgnore > IGNORE_NO) + { + ui_inst->mSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT); + mIgnoreSetting = ui_inst->mSettingGroups["ignores"]->getControl(name); + } + } + + LLParamSDParser parser; + parser.writeSD(mFormData, p.form_elements); + + for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray(); + it != end_it; + ++it) + { + // lift contents of form element up a level, since element type is already encoded in "type" param + if (it->isMap() && it->beginMap() != it->endMap()) + { + *it = it->beginMap()->second; + } + } + + LL_DEBUGS("Notifications") << name << LL_ENDL; + LL_DEBUGS("Notifications") << ll_pretty_print_sd(mFormData) << LL_ENDL; } LLNotificationForm::LLNotificationForm(const LLSD& sd) - : mIgnore(IGNORE_NO) + : mIgnore(IGNORE_NO) { - if (sd.isArray()) - { - mFormData = sd; - } - else - { - LL_WARNS("Notifications") << "Invalid form data " << sd << LL_ENDL; - mFormData = LLSD::emptyArray(); - } + if (sd.isArray()) + { + mFormData = sd; + } + else + { + LL_WARNS("Notifications") << "Invalid form data " << sd << LL_ENDL; + mFormData = LLSD::emptyArray(); + } } LLSD LLNotificationForm::asLLSD() const -{ - return mFormData; +{ + return mFormData; } LLSD LLNotificationForm::getElement(const std::string& element_name) { - for (LLSD::array_const_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - if ((*it)["name"].asString() == element_name) return (*it); - } - return LLSD(); + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) return (*it); + } + return LLSD(); } bool LLNotificationForm::hasElement(const std::string& element_name) const { - for (LLSD::array_const_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - if ((*it)["name"].asString() == element_name) return true; - } - return false; + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) return true; + } + return false; } void LLNotificationForm::getElements(LLSD& elements, S32 offset) @@ -302,241 +302,241 @@ void LLNotificationForm::getElements(LLSD& elements, S32 offset) bool LLNotificationForm::getElementEnabled(const std::string& element_name) const { - for (LLSD::array_const_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - if ((*it)["name"].asString() == element_name) - { - return (*it)["enabled"].asBoolean(); - } - } + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) + { + return (*it)["enabled"].asBoolean(); + } + } - return false; + return false; } void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled) { - for (LLSD::array_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - if ((*it)["name"].asString() == element_name) - { - (*it)["enabled"] = enabled; - } - } + for (LLSD::array_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) + { + (*it)["enabled"] = enabled; + } + } } void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled) { - LLSD element; - element["type"] = type; - element["name"] = name; - element["text"] = name; - element["value"] = value; - element["index"] = LLSD::Integer(mFormData.size()); - element["enabled"] = enabled; - mFormData.append(element); + LLSD element; + element["type"] = type; + element["name"] = name; + element["text"] = name; + element["value"] = value; + element["index"] = LLSD::Integer(mFormData.size()); + element["enabled"] = enabled; + mFormData.append(element); } void LLNotificationForm::append(const LLSD& sub_form) { - if (sub_form.isArray()) - { - for (LLSD::array_const_iterator it = sub_form.beginArray(); - it != sub_form.endArray(); - ++it) - { - mFormData.append(*it); - } - } + if (sub_form.isArray()) + { + for (LLSD::array_const_iterator it = sub_form.beginArray(); + it != sub_form.endArray(); + ++it) + { + mFormData.append(*it); + } + } } void LLNotificationForm::formatElements(const LLSD& substitutions) { - for (LLSD::array_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - // format "text" component of each form element - if ((*it).has("text")) - { - std::string text = (*it)["text"].asString(); - LLStringUtil::format(text, substitutions); - (*it)["text"] = text; - } - if ((*it)["type"].asString() == "text" && (*it).has("value")) - { - std::string value = (*it)["value"].asString(); - LLStringUtil::format(value, substitutions); - (*it)["value"] = value; - } - } + for (LLSD::array_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + // format "text" component of each form element + if ((*it).has("text")) + { + std::string text = (*it)["text"].asString(); + LLStringUtil::format(text, substitutions); + (*it)["text"] = text; + } + if ((*it)["type"].asString() == "text" && (*it).has("value")) + { + std::string value = (*it)["value"].asString(); + LLStringUtil::format(value, substitutions); + (*it)["value"] = value; + } + } } std::string LLNotificationForm::getDefaultOption() { - for (LLSD::array_const_iterator it = mFormData.beginArray(); - it != mFormData.endArray(); - ++it) - { - if ((*it)["default"]) return (*it)["name"].asString(); - } - return ""; + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["default"]) return (*it)["name"].asString(); + } + return ""; } -LLControlVariablePtr LLNotificationForm::getIgnoreSetting() -{ - return mIgnoreSetting; +LLControlVariablePtr LLNotificationForm::getIgnoreSetting() +{ + return mIgnoreSetting; } bool LLNotificationForm::getIgnored() { - bool show = true; - if (mIgnore > LLNotificationForm::IGNORE_NO - && mIgnoreSetting) - { - show = mIgnoreSetting->getValue().asBoolean(); - if (mInvertSetting) show = !show; - } - return !show; + bool show = true; + if (mIgnore > LLNotificationForm::IGNORE_NO + && mIgnoreSetting) + { + show = mIgnoreSetting->getValue().asBoolean(); + if (mInvertSetting) show = !show; + } + return !show; } void LLNotificationForm::setIgnored(bool ignored) { - if (mIgnoreSetting) - { - if (mInvertSetting) ignored = !ignored; - mIgnoreSetting->setValue(!ignored); - } + if (mIgnoreSetting) + { + if (mInvertSetting) ignored = !ignored; + mIgnoreSetting->setValue(!ignored); + } } LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Params& p) -: mName(p.name), - mType(p.type), - mMessage(p.value), - mFooter(p.footer.value), - mLabel(p.label), - mIcon(p.icon), - mURL(p.url.value), - mExpireSeconds(p.duration), - mExpireOption(p.expire_option), - mURLOption(p.url.option), - mURLTarget(p.url.target), - mForceUrlsExternal(p.force_urls_external), - mUnique(p.unique.isProvided()), - mCombineBehavior(p.unique.combine), - mPriority(p.priority), - mPersist(p.persist), - mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), - mLogToChat(p.log_to_chat), - mLogToIM(p.log_to_im), - mShowToast(p.show_toast), - mFadeToast(p.fade_toast), +: mName(p.name), + mType(p.type), + mMessage(p.value), + mFooter(p.footer.value), + mLabel(p.label), + mIcon(p.icon), + mURL(p.url.value), + mExpireSeconds(p.duration), + mExpireOption(p.expire_option), + mURLOption(p.url.option), + mURLTarget(p.url.target), + mForceUrlsExternal(p.force_urls_external), + mUnique(p.unique.isProvided()), + mCombineBehavior(p.unique.combine), + mPriority(p.priority), + mPersist(p.persist), + mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), + mLogToChat(p.log_to_chat), + mLogToIM(p.log_to_im), + mShowToast(p.show_toast), + mFadeToast(p.fade_toast), mSoundName("") { - if (p.sound.isProvided() - && LLUI::getInstance()->mSettingGroups["config"]->controlExists(p.sound)) - { - mSoundName = p.sound; - } + if (p.sound.isProvided() + && LLUI::getInstance()->mSettingGroups["config"]->controlExists(p.sound)) + { + mSoundName = p.sound; + } + + for (const LLNotificationTemplate::UniquenessContext& context : p.unique.contexts) + { + mUniqueContext.push_back(context.value); + } + + LL_DEBUGS("Notifications") << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL; - for (const LLNotificationTemplate::UniquenessContext& context : p.unique.contexts) - { - mUniqueContext.push_back(context.value); - } - - LL_DEBUGS("Notifications") << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL; - - for (const LLNotificationTemplate::Tag& tag : p.tags) - { - LL_DEBUGS("Notifications") << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL; - mTags.push_back(tag.value); - } + for (const LLNotificationTemplate::Tag& tag : p.tags) + { + LL_DEBUGS("Notifications") << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL; + mTags.push_back(tag.value); + } - mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form)); + mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form)); } LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationVisibilityRule::Rule &p) { - if (p.show.isChosen()) - { - mType = p.show.type; - mTag = p.show.tag; - mName = p.show.name; - mVisible = true; - } - else if (p.hide.isChosen()) - { - mType = p.hide.type; - mTag = p.hide.tag; - mName = p.hide.name; - mVisible = false; - } - else if (p.respond.isChosen()) - { - mType = p.respond.type; - mTag = p.respond.tag; - mName = p.respond.name; - mVisible = false; - mResponse = p.respond.response; - } -} - -LLNotification::LLNotification(const LLSDParamAdapter& p) : - mTimestamp(p.time_stamp), - mSubstitutions(p.substitutions), - mPayload(p.payload), - mExpiresAt(p.expiry), - mTemporaryResponder(false), - mRespondedTo(false), - mPriority(p.priority), - mCancelled(false), - mIgnored(false), - mResponderObj(NULL), - mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), - mOfferFromAgent(p.offer_from_agent), + if (p.show.isChosen()) + { + mType = p.show.type; + mTag = p.show.tag; + mName = p.show.name; + mVisible = true; + } + else if (p.hide.isChosen()) + { + mType = p.hide.type; + mTag = p.hide.tag; + mName = p.hide.name; + mVisible = false; + } + else if (p.respond.isChosen()) + { + mType = p.respond.type; + mTag = p.respond.tag; + mName = p.respond.name; + mVisible = false; + mResponse = p.respond.response; + } +} + +LLNotification::LLNotification(const LLSDParamAdapter& p) : + mTimestamp(p.time_stamp), + mSubstitutions(p.substitutions), + mPayload(p.payload), + mExpiresAt(p.expiry), + mTemporaryResponder(false), + mRespondedTo(false), + mPriority(p.priority), + mCancelled(false), + mIgnored(false), + mResponderObj(NULL), + mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), + mOfferFromAgent(p.offer_from_agent), mIsDND(p.is_dnd) { - if (p.functor.name.isChosen()) - { - mResponseFunctorName = p.functor.name; - } - else if (p.functor.function.isChosen()) - { - mResponseFunctorName = LLUUID::generateNewID().asString(); - LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, p.functor.function()); + if (p.functor.name.isChosen()) + { + mResponseFunctorName = p.functor.name; + } + else if (p.functor.function.isChosen()) + { + mResponseFunctorName = LLUUID::generateNewID().asString(); + LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, p.functor.function()); - mTemporaryResponder = true; - } - else if(p.functor.responder.isChosen()) - { - mResponder = p.functor.responder; - } + mTemporaryResponder = true; + } + else if(p.functor.responder.isChosen()) + { + mResponder = p.functor.responder; + } - if(p.responder.isProvided()) - { - mResponderObj = p.responder; - } + if(p.responder.isProvided()) + { + mResponderObj = p.responder; + } - init(p.name, p.form_elements); + init(p.name, p.form_elements); } LLSD LLNotification::asLLSD(bool excludeTemplateElements) -{ - LLParamSDParser parser; - - Params p; - p.id = mId; - p.name = mTemplatep->mName; - p.substitutions = mSubstitutions; - p.payload = mPayload; - p.time_stamp = mTimestamp; - p.expiry = mExpiresAt; - p.priority = mPriority; +{ + LLParamSDParser parser; + + Params p; + p.id = mId; + p.name = mTemplatep->mName; + p.substitutions = mSubstitutions; + p.payload = mPayload; + p.time_stamp = mTimestamp; + p.expiry = mExpiresAt; + p.priority = mPriority; LLNotificationFormPtr templateForm = mTemplatep->mForm; LLSD formElements = mForm->asLLSD(); @@ -560,202 +560,202 @@ LLSD LLNotification::asLLSD(bool excludeTemplateElements) p.functor.responder_sd = mResponder->asLLSD(); } - if(!mResponseFunctorName.empty()) - { - p.functor.name = mResponseFunctorName; - } + if(!mResponseFunctorName.empty()) + { + p.functor.name = mResponseFunctorName; + } - LLSD output; - parser.writeSD(output, p); - return output; + LLSD output; + parser.writeSD(output, p); + return output; } void LLNotification::update() { - LLNotifications::instance().update(shared_from_this()); + LLNotifications::instance().update(shared_from_this()); } void LLNotification::updateFrom(LLNotificationPtr other) { - // can only update from the same notification type - if (mTemplatep != other->mTemplatep) return; + // can only update from the same notification type + if (mTemplatep != other->mTemplatep) return; - // NOTE: do NOT change the ID, since it is the key to - // this given instance, just update all the metadata - //mId = other->mId; + // NOTE: do NOT change the ID, since it is the key to + // this given instance, just update all the metadata + //mId = other->mId; - mPayload = other->mPayload; - mSubstitutions = other->mSubstitutions; - mTimestamp = other->mTimestamp; - mExpiresAt = other->mExpiresAt; - mCancelled = other->mCancelled; - mIgnored = other->mIgnored; - mPriority = other->mPriority; - mForm = other->mForm; - mResponseFunctorName = other->mResponseFunctorName; - mRespondedTo = other->mRespondedTo; - mResponse = other->mResponse; - mTemporaryResponder = other->mTemporaryResponder; + mPayload = other->mPayload; + mSubstitutions = other->mSubstitutions; + mTimestamp = other->mTimestamp; + mExpiresAt = other->mExpiresAt; + mCancelled = other->mCancelled; + mIgnored = other->mIgnored; + mPriority = other->mPriority; + mForm = other->mForm; + mResponseFunctorName = other->mResponseFunctorName; + mRespondedTo = other->mRespondedTo; + mResponse = other->mResponse; + mTemporaryResponder = other->mTemporaryResponder; - update(); + update(); } const LLNotificationFormPtr LLNotification::getForm() { - return mForm; + return mForm; } void LLNotification::cancel() { - mCancelled = true; + mCancelled = true; } LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) { - LLSD response = LLSD::emptyMap(); - for (S32 element_idx = 0; - element_idx < mForm->getNumElements(); - ++element_idx) - { - LLSD element = mForm->getElement(element_idx); - if (element.has("name")) - { - response[element["name"].asString()] = element["value"]; - } - - if ((type == WITH_DEFAULT_BUTTON) - && element["default"].asBoolean()) - { - response[element["name"].asString()] = true; - } - } - return response; + LLSD response = LLSD::emptyMap(); + for (S32 element_idx = 0; + element_idx < mForm->getNumElements(); + ++element_idx) + { + LLSD element = mForm->getElement(element_idx); + if (element.has("name")) + { + response[element["name"].asString()] = element["value"]; + } + + if ((type == WITH_DEFAULT_BUTTON) + && element["default"].asBoolean()) + { + response[element["name"].asString()] = true; + } + } + return response; } //static S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) { - LLNotificationForm form(notification["form"]); + LLNotificationForm form(notification["form"]); - for (S32 element_idx = 0; - element_idx < form.getNumElements(); - ++element_idx) - { - LLSD element = form.getElement(element_idx); - - // only look at buttons - if (element["type"].asString() == "button" - && response[element["name"].asString()].asBoolean()) - { - return element["index"].asInteger(); - } - } + for (S32 element_idx = 0; + element_idx < form.getNumElements(); + ++element_idx) + { + LLSD element = form.getElement(element_idx); + + // only look at buttons + if (element["type"].asString() == "button" + && response[element["name"].asString()].asBoolean()) + { + return element["index"].asInteger(); + } + } - return -1; + return -1; } //static std::string LLNotification::getSelectedOptionName(const LLSD& response) { - for (LLSD::map_const_iterator response_it = response.beginMap(); - response_it != response.endMap(); - ++response_it) - { - if (response_it->second.isBoolean() && response_it->second.asBoolean()) - { - return response_it->first; - } - } - return ""; + for (LLSD::map_const_iterator response_it = response.beginMap(); + response_it != response.endMap(); + ++response_it) + { + if (response_it->second.isBoolean() && response_it->second.asBoolean()) + { + return response_it->first; + } + } + return ""; } void LLNotification::respond(const LLSD& response) { - // *TODO may remove mRespondedTo and use mResponce.isDefined() in isRespondedTo() - mRespondedTo = true; - mResponse = response; - - if(mResponder) - { - mResponder->handleRespond(asLLSD(), response); - } - else if (!mResponseFunctorName.empty()) - { - // look up the functor - LLNotificationFunctorRegistry::ResponseFunctor functor = - LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName); - // and then call it - functor(asLLSD(), response); - } - else if (mCombinedNotifications.empty()) - { - // no registered responder - return; - } - - if (mTemporaryResponder) - { - LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); - mResponseFunctorName = ""; - mTemporaryResponder = false; - } - - if (mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO) - { - mForm->setIgnored(mIgnored); - if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) - { - LLUI::getInstance()->mSettingGroups["ignores"]->setLLSD("Default" + getName(), response); - } - } - - for (std::vector::const_iterator it = mCombinedNotifications.begin(); it != mCombinedNotifications.end(); ++it) - { - if ((*it)) - { - (*it)->respond(response); - } - } - - update(); + // *TODO may remove mRespondedTo and use mResponce.isDefined() in isRespondedTo() + mRespondedTo = true; + mResponse = response; + + if(mResponder) + { + mResponder->handleRespond(asLLSD(), response); + } + else if (!mResponseFunctorName.empty()) + { + // look up the functor + LLNotificationFunctorRegistry::ResponseFunctor functor = + LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName); + // and then call it + functor(asLLSD(), response); + } + else if (mCombinedNotifications.empty()) + { + // no registered responder + return; + } + + if (mTemporaryResponder) + { + LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); + mResponseFunctorName = ""; + mTemporaryResponder = false; + } + + if (mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO) + { + mForm->setIgnored(mIgnored); + if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) + { + LLUI::getInstance()->mSettingGroups["ignores"]->setLLSD("Default" + getName(), response); + } + } + + for (std::vector::const_iterator it = mCombinedNotifications.begin(); it != mCombinedNotifications.end(); ++it) + { + if ((*it)) + { + (*it)->respond(response); + } + } + + update(); } void LLNotification::respondWithDefault() { - respond(getResponseTemplate(WITH_DEFAULT_BUTTON)); + respond(getResponseTemplate(WITH_DEFAULT_BUTTON)); } const std::string& LLNotification::getName() const { - return mTemplatep->mName; + return mTemplatep->mName; } const std::string& LLNotification::getIcon() const { - return mTemplatep->mIcon; + return mTemplatep->mIcon; } bool LLNotification::isPersistent() const { - return mTemplatep->mPersist; + return mTemplatep->mPersist; } std::string LLNotification::getType() const { - return (mTemplatep ? mTemplatep->mType : ""); + return (mTemplatep ? mTemplatep->mType : ""); } S32 LLNotification::getURLOption() const { - return (mTemplatep ? mTemplatep->mURLOption : -1); + return (mTemplatep ? mTemplatep->mURLOption : -1); } S32 LLNotification::getURLOpenExternally() const { - return(mTemplatep? mTemplatep->mURLTarget == "_external": -1); + return(mTemplatep? mTemplatep->mURLTarget == "_external": -1); } bool LLNotification::getForceUrlsExternal() const @@ -763,223 +763,223 @@ bool LLNotification::getForceUrlsExternal() const return (mTemplatep ? mTemplatep->mForceUrlsExternal : false); } -bool LLNotification::hasUniquenessConstraints() const -{ - return (mTemplatep ? mTemplatep->mUnique : false); +bool LLNotification::hasUniquenessConstraints() const +{ + return (mTemplatep ? mTemplatep->mUnique : false); } bool LLNotification::matchesTag(const std::string& tag) { - bool result = false; - - if(mTemplatep) - { - std::list::iterator it; - for(it = mTemplatep->mTags.begin(); it != mTemplatep->mTags.end(); it++) - { - if((*it) == tag) - { - result = true; - break; - } - } - } - - return result; + bool result = false; + + if(mTemplatep) + { + std::list::iterator it; + for(it = mTemplatep->mTags.begin(); it != mTemplatep->mTags.end(); it++) + { + if((*it) == tag) + { + result = true; + break; + } + } + } + + return result; } void LLNotification::setIgnored(bool ignore) { - mIgnored = ignore; + mIgnored = ignore; } void LLNotification::setResponseFunctor(std::string const &responseFunctorName) { - if (mTemporaryResponder) - // get rid of the old one - LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); - mResponseFunctorName = responseFunctorName; - mTemporaryResponder = false; + if (mTemporaryResponder) + // get rid of the old one + LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); + mResponseFunctorName = responseFunctorName; + mTemporaryResponder = false; } void LLNotification::setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb) { - if(mTemporaryResponder) - { - LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); - } + if(mTemporaryResponder) + { + LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); + } - LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, cb); + LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, cb); } void LLNotification::setResponseFunctor(const LLNotificationResponderPtr& responder) { - mResponder = responder; + mResponder = responder; } bool LLNotification::isEquivalentTo(LLNotificationPtr that) const { - if (this->mTemplatep->mName != that->mTemplatep->mName) - { - return false; // must have the same template name or forget it - } - if (this->mTemplatep->mUnique) - { - const LLSD& these_substitutions = this->getSubstitutions(); - const LLSD& those_substitutions = that->getSubstitutions(); - const LLSD& this_payload = this->getPayload(); - const LLSD& that_payload = that->getPayload(); - - // highlander bit sez there can only be one of these - for (std::vector::const_iterator it = mTemplatep->mUniqueContext.begin(), end_it = mTemplatep->mUniqueContext.end(); - it != end_it; - ++it) - { - // if templates differ in either substitution strings or payload with the given field name - // then they are considered inequivalent - // use of get() avoids converting the LLSD value to a map as the [] operator would - if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString() - || this_payload.get(*it).asString() != that_payload.get(*it).asString()) - { - return false; - } - } - return true; - } - - return false; + if (this->mTemplatep->mName != that->mTemplatep->mName) + { + return false; // must have the same template name or forget it + } + if (this->mTemplatep->mUnique) + { + const LLSD& these_substitutions = this->getSubstitutions(); + const LLSD& those_substitutions = that->getSubstitutions(); + const LLSD& this_payload = this->getPayload(); + const LLSD& that_payload = that->getPayload(); + + // highlander bit sez there can only be one of these + for (std::vector::const_iterator it = mTemplatep->mUniqueContext.begin(), end_it = mTemplatep->mUniqueContext.end(); + it != end_it; + ++it) + { + // if templates differ in either substitution strings or payload with the given field name + // then they are considered inequivalent + // use of get() avoids converting the LLSD value to a map as the [] operator would + if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString() + || this_payload.get(*it).asString() != that_payload.get(*it).asString()) + { + return false; + } + } + return true; + } + + return false; } void LLNotification::init(const std::string& template_name, const LLSD& form_elements) { - mTemplatep = LLNotifications::instance().getTemplate(template_name); - if (!mTemplatep) return; - - // add default substitutions - const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs(); - for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin(); - iter != default_args.end(); ++iter) - { - mSubstitutions[iter->first] = iter->second; - } - mSubstitutions["_URL"] = getURL(); - mSubstitutions["_NAME"] = template_name; - // TODO: something like this so that a missing alert is sensible: - //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); - - mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); + mTemplatep = LLNotifications::instance().getTemplate(template_name); + if (!mTemplatep) return; + + // add default substitutions + const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs(); + for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin(); + iter != default_args.end(); ++iter) + { + mSubstitutions[iter->first] = iter->second; + } + mSubstitutions["_URL"] = getURL(); + mSubstitutions["_NAME"] = template_name; + // TODO: something like this so that a missing alert is sensible: + //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); + + mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); mForm->append(form_elements); - // apply substitution to form labels - mForm->formatElements(mSubstitutions); + // apply substitution to form labels + mForm->formatElements(mSubstitutions); - mIgnored = mForm->getIgnored(); + mIgnored = mForm->getIgnored(); - LLDate rightnow = LLDate::now(); - if (mTemplatep->mExpireSeconds) - { - mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds); - } + LLDate rightnow = LLDate::now(); + if (mTemplatep->mExpireSeconds) + { + mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds); + } - if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED) - { - mPriority = mTemplatep->mPriority; - } + if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED) + { + mPriority = mTemplatep->mPriority; + } } std::string LLNotification::summarize() const { - std::string s = "Notification("; - s += getName(); - s += ") : "; - s += mTemplatep ? mTemplatep->mMessage : ""; - // should also include timestamp and expiration time (but probably not payload) - return s; + std::string s = "Notification("; + s += getName(); + s += ") : "; + s += mTemplatep ? mTemplatep->mMessage : ""; + // should also include timestamp and expiration time (but probably not payload) + return s; } std::string LLNotification::getMessage() const { - // all our callers cache this result, so it gives us more flexibility - // to do the substitution at call time rather than attempting to - // cache it in the notification - if (!mTemplatep) - return std::string(); + // all our callers cache this result, so it gives us more flexibility + // to do the substitution at call time rather than attempting to + // cache it in the notification + if (!mTemplatep) + return std::string(); - std::string message = mTemplatep->mMessage; - LLStringUtil::format(message, mSubstitutions); - return message; + std::string message = mTemplatep->mMessage; + LLStringUtil::format(message, mSubstitutions); + return message; } std::string LLNotification::getFooter() const { - if (!mTemplatep) - return std::string(); + if (!mTemplatep) + return std::string(); - std::string footer = mTemplatep->mFooter; - LLStringUtil::format(footer, mSubstitutions); - return footer; + std::string footer = mTemplatep->mFooter; + LLStringUtil::format(footer, mSubstitutions); + return footer; } std::string LLNotification::getLabel() const { - std::string label = mTemplatep->mLabel; - LLStringUtil::format(label, mSubstitutions); - return (mTemplatep ? label : ""); + std::string label = mTemplatep->mLabel; + LLStringUtil::format(label, mSubstitutions); + return (mTemplatep ? label : ""); } std::string LLNotification::getURL() const { - if (!mTemplatep) - return std::string(); - std::string url = mTemplatep->mURL; - LLStringUtil::format(url, mSubstitutions); - return (mTemplatep ? url : ""); + if (!mTemplatep) + return std::string(); + std::string url = mTemplatep->mURL; + LLStringUtil::format(url, mSubstitutions); + return (mTemplatep ? url : ""); } bool LLNotification::canLogToChat() const { - return mTemplatep->mLogToChat; + return mTemplatep->mLogToChat; } bool LLNotification::canLogToIM() const { - return mTemplatep->mLogToIM; + return mTemplatep->mLogToIM; } bool LLNotification::canShowToast() const { - return mTemplatep->mShowToast; + return mTemplatep->mShowToast; } bool LLNotification::canFadeToast() const { - return mTemplatep->mFadeToast; + return mTemplatep->mFadeToast; } bool LLNotification::hasFormElements() const { - return mTemplatep->mForm->getNumElements() != 0; + return mTemplatep->mForm->getNumElements() != 0; } void LLNotification::playSound() -{ +{ make_ui_sound(mTemplatep->mSoundName.c_str()); } LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const { - return mTemplatep->mCombineBehavior; + return mTemplatep->mCombineBehavior; } void LLNotification::updateForm( const LLNotificationFormPtr& form ) { - mForm = form; + mForm = form; } void LLNotification::repost() { - mRespondedTo = false; - LLNotifications::instance().update(shared_from_this()); + mRespondedTo = false; + LLNotifications::instance().update(shared_from_this()); } @@ -989,50 +989,50 @@ void LLNotification::repost() // --- LLBoundListener LLNotificationChannelBase::connectChangedImpl(const LLEventListener& slot) { - // when someone wants to connect to a channel, we first throw them - // all of the notifications that are already in the channel - // we use a special signal called "load" in case the channel wants to care - // only about new notifications + // when someone wants to connect to a channel, we first throw them + // all of the notifications that are already in the channel + // we use a special signal called "load" in case the channel wants to care + // only about new notifications LLMutexLock lock(&mItemsMutex); - for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) - { - slot(LLSD().with("sigtype", "load").with("id", (*it)->id())); - } - // and then connect the signal so that all future notifications will also be - // forwarded. - return mChanged.connect(slot); + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + slot(LLSD().with("sigtype", "load").with("id", (*it)->id())); + } + // and then connect the signal so that all future notifications will also be + // forwarded. + return mChanged.connect(slot); } LLBoundListener LLNotificationChannelBase::connectAtFrontChangedImpl(const LLEventListener& slot) { - for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) - { - slot(LLSD().with("sigtype", "load").with("id", (*it)->id())); - } - return mChanged.connect(slot, boost::signals2::at_front); + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + slot(LLSD().with("sigtype", "load").with("id", (*it)->id())); + } + return mChanged.connect(slot, boost::signals2::at_front); } LLBoundListener LLNotificationChannelBase::connectPassedFilterImpl(const LLEventListener& slot) { - // these two filters only fire for notifications added after the current one, because - // they don't participate in the hierarchy. - return mPassedFilter.connect(slot); + // these two filters only fire for notifications added after the current one, because + // they don't participate in the hierarchy. + return mPassedFilter.connect(slot); } LLBoundListener LLNotificationChannelBase::connectFailedFilterImpl(const LLEventListener& slot) { - return mFailedFilter.connect(slot); + return mFailedFilter.connect(slot); } // external call, conforms to our standard signature bool LLNotificationChannelBase::updateItem(const LLSD& payload) -{ - // first check to see if it's in the master list - LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]); - if (!pNotification) - return false; // not found - - return updateItem(payload, pNotification); +{ + // first check to see if it's in the master list + LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]); + if (!pNotification) + return false; // not found + + return updateItem(payload, pNotification); } @@ -1041,134 +1041,134 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload) // internal call, for use in avoiding lookup bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPtr pNotification) -{ - std::string cmd = payload["sigtype"]; - LLNotificationSet::iterator foundItem = mItems.find(pNotification); - bool wasFound = (foundItem != mItems.end()); - bool passesFilter = mFilter ? mFilter(pNotification) : true; - - // first, we offer the result of the filter test to the simple - // signals for pass/fail. One of these is guaranteed to be called. - // If either signal returns true, the change processing is NOT performed - // (so don't return true unless you know what you're doing!) - bool abortProcessing = false; - if (passesFilter) - { - onFilterPass(pNotification); - abortProcessing = mPassedFilter(payload); - } - else - { - onFilterFail(pNotification); - abortProcessing = mFailedFilter(payload); - } - - if (abortProcessing) - { - return true; - } - - if (cmd == "load") - { - // should be no reason we'd ever get a load if we already have it - // if passes filter send a load message, else do nothing - assert(!wasFound); - if (passesFilter) - { - // not in our list, add it and say so - mItems.insert(pNotification); - onLoad(pNotification); - abortProcessing = mChanged(payload); - } - } - else if (cmd == "change") - { - // if it passes filter now and was found, we just send a change message - // if it passes filter now and wasn't found, we have to add it - // if it doesn't pass filter and wasn't found, we do nothing - // if it doesn't pass filter and was found, we need to delete it - if (passesFilter) - { - if (wasFound) - { - // it already existed, so this is a change - // since it changed in place, all we have to do is resend the signal - onChange(pNotification); - abortProcessing = mChanged(payload); - } - else - { - // not in our list, add it and say so - mItems.insert(pNotification); - onChange(pNotification); - // our payload is const, so make a copy before changing it - LLSD newpayload = payload; - newpayload["sigtype"] = "add"; - abortProcessing = mChanged(newpayload); - } - } - else - { - if (wasFound) - { - // it already existed, so this is a delete - mItems.erase(pNotification); - onChange(pNotification); - // our payload is const, so make a copy before changing it - LLSD newpayload = payload; - newpayload["sigtype"] = "delete"; - abortProcessing = mChanged(newpayload); - } - // didn't pass, not on our list, do nothing - } - } - else if (cmd == "add") - { - // should be no reason we'd ever get an add if we already have it - // if passes filter send an add message, else do nothing - assert(!wasFound); - if (passesFilter) - { - // not in our list, add it and say so - mItems.insert(pNotification); - onAdd(pNotification); - abortProcessing = mChanged(payload); - } - } - else if (cmd == "delete") - { - // if we have it in our list, pass on the delete, then delete it, else do nothing - if (wasFound) - { - onDelete(pNotification); - abortProcessing = mChanged(payload); - mItems.erase(pNotification); - } - } - return abortProcessing; +{ + std::string cmd = payload["sigtype"]; + LLNotificationSet::iterator foundItem = mItems.find(pNotification); + bool wasFound = (foundItem != mItems.end()); + bool passesFilter = mFilter ? mFilter(pNotification) : true; + + // first, we offer the result of the filter test to the simple + // signals for pass/fail. One of these is guaranteed to be called. + // If either signal returns true, the change processing is NOT performed + // (so don't return true unless you know what you're doing!) + bool abortProcessing = false; + if (passesFilter) + { + onFilterPass(pNotification); + abortProcessing = mPassedFilter(payload); + } + else + { + onFilterFail(pNotification); + abortProcessing = mFailedFilter(payload); + } + + if (abortProcessing) + { + return true; + } + + if (cmd == "load") + { + // should be no reason we'd ever get a load if we already have it + // if passes filter send a load message, else do nothing + assert(!wasFound); + if (passesFilter) + { + // not in our list, add it and say so + mItems.insert(pNotification); + onLoad(pNotification); + abortProcessing = mChanged(payload); + } + } + else if (cmd == "change") + { + // if it passes filter now and was found, we just send a change message + // if it passes filter now and wasn't found, we have to add it + // if it doesn't pass filter and wasn't found, we do nothing + // if it doesn't pass filter and was found, we need to delete it + if (passesFilter) + { + if (wasFound) + { + // it already existed, so this is a change + // since it changed in place, all we have to do is resend the signal + onChange(pNotification); + abortProcessing = mChanged(payload); + } + else + { + // not in our list, add it and say so + mItems.insert(pNotification); + onChange(pNotification); + // our payload is const, so make a copy before changing it + LLSD newpayload = payload; + newpayload["sigtype"] = "add"; + abortProcessing = mChanged(newpayload); + } + } + else + { + if (wasFound) + { + // it already existed, so this is a delete + mItems.erase(pNotification); + onChange(pNotification); + // our payload is const, so make a copy before changing it + LLSD newpayload = payload; + newpayload["sigtype"] = "delete"; + abortProcessing = mChanged(newpayload); + } + // didn't pass, not on our list, do nothing + } + } + else if (cmd == "add") + { + // should be no reason we'd ever get an add if we already have it + // if passes filter send an add message, else do nothing + assert(!wasFound); + if (passesFilter) + { + // not in our list, add it and say so + mItems.insert(pNotification); + onAdd(pNotification); + abortProcessing = mChanged(payload); + } + } + else if (cmd == "delete") + { + // if we have it in our list, pass on the delete, then delete it, else do nothing + if (wasFound) + { + onDelete(pNotification); + abortProcessing = mChanged(payload); + mItems.erase(pNotification); + } + } + return abortProcessing; } LLNotificationChannel::LLNotificationChannel(const Params& p) -: LLNotificationChannelBase(p.filter()), - LLInstanceTracker(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), - mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) +: LLNotificationChannelBase(p.filter()), + LLInstanceTracker(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), + mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) { - for (const std::string& source : p.sources) + for (const std::string& source : p.sources) { - connectToChannel(source); - } + connectToChannel(source); + } } -LLNotificationChannel::LLNotificationChannel(const std::string& name, - const std::string& parent, - LLNotificationFilter filter) -: LLNotificationChannelBase(filter), - LLInstanceTracker(name), - mName(name) +LLNotificationChannel::LLNotificationChannel(const std::string& name, + const std::string& parent, + LLNotificationFilter filter) +: LLNotificationChannelBase(filter), + LLInstanceTracker(name), + mName(name) { - // bind to notification broadcast - connectToChannel(parent); + // bind to notification broadcast + connectToChannel(parent); } LLNotificationChannel::~LLNotificationChannel() @@ -1181,7 +1181,7 @@ LLNotificationChannel::~LLNotificationChannel() bool LLNotificationChannel::isEmpty() const { - return mItems.empty(); + return mItems.empty(); } S32 LLNotificationChannel::size() const @@ -1191,7 +1191,7 @@ S32 LLNotificationChannel::size() const size_t LLNotificationChannel::size() { - return mItems.size(); + return mItems.size(); } void LLNotificationChannel::forEachNotification(NotificationProcess process) @@ -1202,31 +1202,31 @@ void LLNotificationChannel::forEachNotification(NotificationProcess process) std::string LLNotificationChannel::summarize() { - std::string s("Channel '"); - s += mName; - s += "'\n "; + std::string s("Channel '"); + s += mName; + s += "'\n "; LLMutexLock lock(&mItemsMutex); - for (LLNotificationChannel::Iterator it = mItems.begin(); it != mItems.end(); ++it) - { - s += (*it)->summarize(); - s += "\n "; - } - return s; + for (LLNotificationChannel::Iterator it = mItems.begin(); it != mItems.end(); ++it) + { + s += (*it)->summarize(); + s += "\n "; + } + return s; } void LLNotificationChannel::connectToChannel( const std::string& channel_name ) { - if (channel_name.empty()) - { + if (channel_name.empty()) + { mListeners.push_back(LLNotifications::instance().connectChanged( - boost::bind(&LLNotificationChannelBase::updateItem, this, _1))); - } - else - { - mParents.push_back(channel_name); - LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); + boost::bind(&LLNotificationChannelBase::updateItem, this, _1))); + } + else + { + mParents.push_back(channel_name); + LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); mListeners.push_back(p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1))); - } + } } // --- @@ -1234,18 +1234,18 @@ void LLNotificationChannel::connectToChannel( const std::string& channel_name ) // ========================================================= -// ============================================== =========== +// ============================================== =========== // LLNotifications implementation // --- -LLNotifications::LLNotifications() -: LLNotificationChannelBase(LLNotificationFilters::includeEverything), - mIgnoreAllNotifications(false) +LLNotifications::LLNotifications() +: LLNotificationChannelBase(LLNotificationFilters::includeEverything), + mIgnoreAllNotifications(false) { mListener.reset(new LLNotificationsListener(*this)); - LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); - // touch the instance tracker for notification channels, so that it will still be around in our destructor - LLInstanceTracker::instanceCount(); + // touch the instance tracker for notification channels, so that it will still be around in our destructor + LLInstanceTracker::instanceCount(); } void LLNotifications::clear() @@ -1256,152 +1256,152 @@ void LLNotifications::clear() // The expiration channel gets all notifications that are cancelled bool LLNotifications::expirationFilter(LLNotificationPtr pNotification) { - return pNotification->isCancelled() || pNotification->isRespondedTo(); + return pNotification->isCancelled() || pNotification->isRespondedTo(); } bool LLNotifications::expirationHandler(const LLSD& payload) { - if (payload["sigtype"].asString() != "delete") - { - // anything added to this channel actually should be deleted from the master - cancel(find(payload["id"])); - return true; // don't process this item any further - } - return false; + if (payload["sigtype"].asString() != "delete") + { + // anything added to this channel actually should be deleted from the master + cancel(find(payload["id"])); + return true; // don't process this item any further + } + return false; } bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) { - if (!pNotif->hasUniquenessConstraints()) - { - return true; - } - - // checks against existing unique notifications - for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); - existing_it != mUniqueNotifications.end(); - ++existing_it) - { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) - { - if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) - { - cancel(existing_notification); - return true; - } - else - { - return false; - } - } - } - - return true; + if (!pNotif->hasUniquenessConstraints()) + { + return true; + } + + // checks against existing unique notifications + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) + { + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) + { + cancel(existing_notification); + return true; + } + else + { + return false; + } + } + } + + return true; } bool LLNotifications::uniqueHandler(const LLSD& payload) { - std::string cmd = payload["sigtype"]; + std::string cmd = payload["sigtype"]; - LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); - if (pNotif && pNotif->hasUniquenessConstraints()) - { - if (cmd == "add") - { - // not a duplicate according to uniqueness criteria, so we keep it - // and store it for future uniqueness checks - mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); - } - else if (cmd == "delete") - { - mUniqueNotifications.erase(pNotif->getName()); - } - } + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + if (pNotif && pNotif->hasUniquenessConstraints()) + { + if (cmd == "add") + { + // not a duplicate according to uniqueness criteria, so we keep it + // and store it for future uniqueness checks + mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); + } + else if (cmd == "delete") + { + mUniqueNotifications.erase(pNotif->getName()); + } + } - return false; + return false; } bool LLNotifications::failedUniquenessTest(const LLSD& payload) { - LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); - - std::string cmd = payload["sigtype"]; - - if (!pNotif || cmd != "add") - { - return false; - } - - switch(pNotif->getCombineBehavior()) - { - case LLNotification::REPLACE_WITH_NEW: - // Update the existing unique notification with the data from this particular instance... - // This guarantees that duplicate notifications will be collapsed to the one - // most recently triggered - for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); - existing_it != mUniqueNotifications.end(); - ++existing_it) - { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) - { - // copy notification instance data over to oldest instance - // of this unique notification and update it - existing_notification->updateFrom(pNotif); - // then delete the new one - cancel(pNotif); - } - } - break; - case LLNotification::COMBINE_WITH_NEW: - // Add to the existing unique notification with the data from this particular instance... - // This guarantees that duplicate notifications will be collapsed to the one - // most recently triggered - for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); - existing_it != mUniqueNotifications.end(); - ++existing_it) - { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) - { - // copy the notifications from the newest instance into the oldest - existing_notification->mCombinedNotifications.push_back(pNotif); - existing_notification->mCombinedNotifications.insert(existing_notification->mCombinedNotifications.end(), - pNotif->mCombinedNotifications.begin(), pNotif->mCombinedNotifications.end()); - - // pop up again - existing_notification->update(); - } - } - break; - case LLNotification::KEEP_OLD: - break; - case LLNotification::CANCEL_OLD: - // already handled by filter logic - break; - default: - break; - } - - return false; + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + + std::string cmd = payload["sigtype"]; + + if (!pNotif || cmd != "add") + { + return false; + } + + switch(pNotif->getCombineBehavior()) + { + case LLNotification::REPLACE_WITH_NEW: + // Update the existing unique notification with the data from this particular instance... + // This guarantees that duplicate notifications will be collapsed to the one + // most recently triggered + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) + { + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy notification instance data over to oldest instance + // of this unique notification and update it + existing_notification->updateFrom(pNotif); + // then delete the new one + cancel(pNotif); + } + } + break; + case LLNotification::COMBINE_WITH_NEW: + // Add to the existing unique notification with the data from this particular instance... + // This guarantees that duplicate notifications will be collapsed to the one + // most recently triggered + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) + { + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy the notifications from the newest instance into the oldest + existing_notification->mCombinedNotifications.push_back(pNotif); + existing_notification->mCombinedNotifications.insert(existing_notification->mCombinedNotifications.end(), + pNotif->mCombinedNotifications.begin(), pNotif->mCombinedNotifications.end()); + + // pop up again + existing_notification->update(); + } + } + break; + case LLNotification::KEEP_OLD: + break; + case LLNotification::CANCEL_OLD: + // already handled by filter logic + break; + default: + break; + } + + return false; } LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) { - return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName).get()); + return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName).get()); } // this function is called once at construction time, after the object is constructed. void LLNotifications::initSingleton() { - loadTemplates(); - loadVisibilityRules(); - createDefaultChannels(); + loadTemplates(); + loadVisibilityRules(); + createDefaultChannels(); } void LLNotifications::cleanupSingleton() @@ -1412,525 +1412,525 @@ void LLNotifications::cleanupSingleton() void LLNotifications::createDefaultChannels() { LL_INFOS("Notifications") << "Generating default notification channels" << LL_ENDL; - // now construct the various channels AFTER loading the notifications, - // because the history channel is going to rewrite the stored notifications file - mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", - !boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); - mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", - boost::bind(&LLNotifications::expirationFilter, this, _1))); - mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", - !boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind - mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", - boost::bind(&LLNotifications::uniqueFilter, this, _1))); - mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", - filterIgnoredNotifications)); - mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", - boost::bind(&LLNotifications::isVisibleByRules, this, _1))); - mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", - &LLNotificationFilters::includeEverything)); - mDefaultChannels.push_back(new LLPersistentNotificationChannel()); - - // connect action methods to these channels - getChannel("Enabled")->connectFailedFilter(&defaultResponse); - getChannel("Expiration")->connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); - // uniqueHandler slot should be added as first slot of the signal due to - // usage LLStopWhenHandled combiner in LLStandardSignal - getChannel("Unique")->connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); - getChannel("Unique")->connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); - getChannel("Ignore")->connectFailedFilter(&handleIgnoredNotification); - getChannel("VisibilityRules")->connectFailedFilter(&visibilityRuleMached); + // now construct the various channels AFTER loading the notifications, + // because the history channel is going to rewrite the stored notifications file + mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", + !boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); + mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", + boost::bind(&LLNotifications::expirationFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", + !boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind + mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", + boost::bind(&LLNotifications::uniqueFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", + filterIgnoredNotifications)); + mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", + boost::bind(&LLNotifications::isVisibleByRules, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", + &LLNotificationFilters::includeEverything)); + mDefaultChannels.push_back(new LLPersistentNotificationChannel()); + + // connect action methods to these channels + getChannel("Enabled")->connectFailedFilter(&defaultResponse); + getChannel("Expiration")->connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); + // uniqueHandler slot should be added as first slot of the signal due to + // usage LLStopWhenHandled combiner in LLStandardSignal + getChannel("Unique")->connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); + getChannel("Unique")->connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); + getChannel("Ignore")->connectFailedFilter(&handleIgnoredNotification); + getChannel("VisibilityRules")->connectFailedFilter(&visibilityRuleMached); } LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name) { - if (mTemplates.count(name)) - { - return mTemplates[name]; - } - else - { - return mTemplates["MissingAlert"]; - } + if (mTemplates.count(name)) + { + return mTemplates[name]; + } + else + { + return mTemplates["MissingAlert"]; + } } bool LLNotifications::templateExists(const std::string& name) { - return (mTemplates.count(name) != 0); + return (mTemplates.count(name) != 0); } void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) { - LLNotificationPtr temp_notify(new LLNotification(params)); - LLSD response = temp_notify->getResponseTemplate(); - LLSD selected_item = temp_notify->getForm()->getElement(option); - - if (selected_item.isUndefined()) - { - LL_WARNS("Notifications") << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL; - return; - } - response[selected_item["name"].asString()] = true; + LLNotificationPtr temp_notify(new LLNotification(params)); + LLSD response = temp_notify->getResponseTemplate(); + LLSD selected_item = temp_notify->getForm()->getElement(option); + + if (selected_item.isUndefined()) + { + LL_WARNS("Notifications") << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL; + return; + } + response[selected_item["name"].asString()] = true; - temp_notify->respond(response); + temp_notify->respond(response); } LLNotifications::TemplateNames LLNotifications::getTemplateNames() const { - TemplateNames names; - for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it) - { - names.push_back(it->first); - } - return names; + TemplateNames names; + for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it) + { + names.push_back(it->first); + } + return names; } typedef std::map StringMap; void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements) { - // walk the list of attributes looking for replacements - for (LLXMLAttribList::iterator it=node->mAttributes.begin(); - it != node->mAttributes.end(); ++it) - { - std::string value = it->second->getValue(); - if (value[0] == '$') - { - value.erase(0, 1); // trim off the $ - std::string replacement; - StringMap::const_iterator found = replacements.find(value); - if (found != replacements.end()) - { - replacement = found->second; - LL_DEBUGS("Notifications") << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL; - it->second->setValue(replacement); - } - else - { - LL_WARNS("Notifications") << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL; - } - } - } - - // now walk the list of children and call this recursively. - for (LLXMLNodePtr child = node->getFirstChild(); - child.notNull(); child = child->getNextSibling()) - { - replaceSubstitutionStrings(child, replacements); - } + // walk the list of attributes looking for replacements + for (LLXMLAttribList::iterator it=node->mAttributes.begin(); + it != node->mAttributes.end(); ++it) + { + std::string value = it->second->getValue(); + if (value[0] == '$') + { + value.erase(0, 1); // trim off the $ + std::string replacement; + StringMap::const_iterator found = replacements.find(value); + if (found != replacements.end()) + { + replacement = found->second; + LL_DEBUGS("Notifications") << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL; + it->second->setValue(replacement); + } + else + { + LL_WARNS("Notifications") << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL; + } + } + } + + // now walk the list of children and call this recursively. + for (LLXMLNodePtr child = node->getFirstChild(); + child.notNull(); child = child->getNextSibling()) + { + replaceSubstitutionStrings(child, replacements); + } } void replaceFormText(LLNotificationForm::Params& form, const std::string& pattern, const std::string& replace) { - if (form.ignore.isProvided() && form.ignore.text() == pattern) - { - form.ignore.text = replace; - } + if (form.ignore.isProvided() && form.ignore.text() == pattern) + { + form.ignore.text = replace; + } - for (LLNotificationForm::FormElement& element : form.form_elements.elements) - { - if (element.button.isChosen() && element.button.text() == pattern) - { - element.button.text = replace; - } - } + for (LLNotificationForm::FormElement& element : form.form_elements.elements) + { + if (element.button.isChosen() && element.button.text() == pattern) + { + element.button.text = replace; + } + } } void addPathIfExists(const std::string& new_path, std::vector& paths) { - if (gDirUtilp->fileExists(new_path)) - { - paths.push_back(new_path); - } + if (gDirUtilp->fileExists(new_path)) + { + paths.push_back(new_path); + } } bool LLNotifications::loadTemplates() { - LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL; - // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it - // output all relevant pathnames instead of just the ones from the most - // specific skin. - std::vector search_paths = - gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL; + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); - std::string base_filename = search_paths.front(); - LLXMLNodePtr root; - BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); + std::string base_filename = search_paths.front(); + LLXMLNodePtr root; + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); - if (!success || root.isNull() || !root->hasName( "notifications" )) - { + if (!success || root.isNull() || !root->hasName( "notifications" )) + { LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); - LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; - return false; - } + LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; + return false; + } - LLNotificationTemplate::Notifications params; - LLXUIParser parser; - parser.readXUI(root, params, base_filename); + LLNotificationTemplate::Notifications params; + LLXUIParser parser; + parser.readXUI(root, params, base_filename); - if(!params.validateBlock()) - { + if(!params.validateBlock()) + { LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); - LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL; - return false; - } - - mTemplates.clear(); - - for (const LLNotificationTemplate::GlobalString& string : params.strings) - { - mGlobalStrings[string.name] = string.value; - } - - std::map form_templates; - - for (const LLNotificationTemplate::Template& notification_template : params.templates) - { - form_templates[notification_template.name] = notification_template.form; - } - - for (LLNotificationTemplate::Params& notification : params.notifications) - { - if (notification.form_ref.form_template.isChosen()) - { - // replace form contents from template - notification.form_ref.form = form_templates[notification.form_ref.form_template.name]; - if(notification.form_ref.form_template.yes_text.isProvided()) - { - replaceFormText(notification.form_ref.form, "$yestext", notification.form_ref.form_template.yes_text); - } - if(notification.form_ref.form_template.no_text.isProvided()) - { - replaceFormText(notification.form_ref.form, "$notext", notification.form_ref.form_template.no_text); - } - if(notification.form_ref.form_template.cancel_text.isProvided()) - { - replaceFormText(notification.form_ref.form, "$canceltext", notification.form_ref.form_template.cancel_text); - } - if(notification.form_ref.form_template.help_text.isProvided()) - { - replaceFormText(notification.form_ref.form, "$helptext", notification.form_ref.form_template.help_text); - } - if(notification.form_ref.form_template.ignore_text.isProvided()) - { - replaceFormText(notification.form_ref.form, "$ignoretext", notification.form_ref.form_template.ignore_text); - } - } - mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification)); - } - - LL_INFOS("Notifications") << "...done" << LL_ENDL; - - return true; + LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL; + return false; + } + + mTemplates.clear(); + + for (const LLNotificationTemplate::GlobalString& string : params.strings) + { + mGlobalStrings[string.name] = string.value; + } + + std::map form_templates; + + for (const LLNotificationTemplate::Template& notification_template : params.templates) + { + form_templates[notification_template.name] = notification_template.form; + } + + for (LLNotificationTemplate::Params& notification : params.notifications) + { + if (notification.form_ref.form_template.isChosen()) + { + // replace form contents from template + notification.form_ref.form = form_templates[notification.form_ref.form_template.name]; + if(notification.form_ref.form_template.yes_text.isProvided()) + { + replaceFormText(notification.form_ref.form, "$yestext", notification.form_ref.form_template.yes_text); + } + if(notification.form_ref.form_template.no_text.isProvided()) + { + replaceFormText(notification.form_ref.form, "$notext", notification.form_ref.form_template.no_text); + } + if(notification.form_ref.form_template.cancel_text.isProvided()) + { + replaceFormText(notification.form_ref.form, "$canceltext", notification.form_ref.form_template.cancel_text); + } + if(notification.form_ref.form_template.help_text.isProvided()) + { + replaceFormText(notification.form_ref.form, "$helptext", notification.form_ref.form_template.help_text); + } + if(notification.form_ref.form_template.ignore_text.isProvided()) + { + replaceFormText(notification.form_ref.form, "$ignoretext", notification.form_ref.form_template.ignore_text); + } + } + mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification)); + } + + LL_INFOS("Notifications") << "...done" << LL_ENDL; + + return true; } bool LLNotifications::loadVisibilityRules() { - const std::string xml_filename = "notification_visibility.xml"; - // Note that here we're looking for the "en" version, the default - // language, rather than the most localized version of this file. - std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xml_filename); + const std::string xml_filename = "notification_visibility.xml"; + // Note that here we're looking for the "en" version, the default + // language, rather than the most localized version of this file. + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xml_filename); - LLNotificationVisibilityRule::Rules params; - LLSimpleXUIParser parser; - parser.readXUI(full_filename, params); + LLNotificationVisibilityRule::Rules params; + LLSimpleXUIParser parser; + parser.readXUI(full_filename, params); - if(!params.validateBlock()) - { + if(!params.validateBlock()) + { LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); - LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL; - return false; - } + LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL; + return false; + } - mVisibilityRules.clear(); + mVisibilityRules.clear(); - for (const LLNotificationVisibilityRule::Rule& rule : params.rules) - { - mVisibilityRules.push_back(LLNotificationVisibilityRulePtr(new LLNotificationVisibilityRule(rule))); - } + for (const LLNotificationVisibilityRule::Rule& rule : params.rules) + { + mVisibilityRules.push_back(LLNotificationVisibilityRulePtr(new LLNotificationVisibilityRule(rule))); + } - return true; + return true; } // Add a simple notification (from XUI) void LLNotifications::addFromCallback(const LLSD& name) { - add(name.asString(), LLSD(), LLSD()); + add(name.asString(), LLSD(), LLSD()); } LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload) { - LLNotification::Params::Functor functor_p; - functor_p.name = name; - return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name) { - LLNotification::Params::Functor functor_p; - functor_p.name = functor_name; - return add(LLNotification::Params().name(name) - .substitutions(substitutions) - .payload(payload) - .functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = functor_name; + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } - + //virtual LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor) { - LLNotification::Params::Functor functor_p; - functor_p.function = functor; - return add(LLNotification::Params().name(name) - .substitutions(substitutions) - .payload(payload) - .functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.function = functor; + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } // generalized add function that takes a parameter block object for more complex instantiations LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) { - LLNotificationPtr pNotif(new LLNotification(p)); - add(pNotif); - return pNotif; + LLNotificationPtr pNotif(new LLNotification(p)); + add(pNotif); + return pNotif; } void LLNotifications::add(const LLNotificationPtr pNotif) { - if (pNotif == NULL) return; + if (pNotif == NULL) return; - // first see if we already have it -- if so, that's a problem - LLNotificationSet::iterator it=mItems.find(pNotif); - if (it != mItems.end()) - { - LL_ERRS() << "Notification added a second time to the master notification channel." << LL_ENDL; - } + // first see if we already have it -- if so, that's a problem + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + LL_ERRS() << "Notification added a second time to the master notification channel." << LL_ENDL; + } - updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif); + updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif); } void LLNotifications::load(const LLNotificationPtr pNotif) { - if (pNotif == NULL) return; + if (pNotif == NULL) return; - // first see if we already have it -- if so, that's a problem - LLNotificationSet::iterator it=mItems.find(pNotif); - if (it != mItems.end()) - { - LL_ERRS() << "Notification loaded a second time to the master notification channel." << LL_ENDL; - } + // first see if we already have it -- if so, that's a problem + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + LL_ERRS() << "Notification loaded a second time to the master notification channel." << LL_ENDL; + } - updateItem(LLSD().with("sigtype", "load").with("id", pNotif->id()), pNotif); + updateItem(LLSD().with("sigtype", "load").with("id", pNotif->id()), pNotif); } void LLNotifications::cancel(LLNotificationPtr pNotif) { - if (pNotif == NULL || pNotif->isCancelled()) return; + if (pNotif == NULL || pNotif->isCancelled()) return; - LLNotificationSet::iterator it=mItems.find(pNotif); - if (it != mItems.end()) - { - pNotif->cancel(); - updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); - } + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + pNotif->cancel(); + updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); + } } void LLNotifications::cancelByName(const std::string& name) { LLMutexLock lock(&mItemsMutex); - std::vector notifs_to_cancel; - for (LLNotificationSet::iterator it=mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - LLNotificationPtr pNotif = *it; - if (pNotif->getName() == name) - { - notifs_to_cancel.push_back(pNotif); - } - } - - for (std::vector::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end(); - it != end_it; - ++it) - { - LLNotificationPtr pNotif = *it; - pNotif->cancel(); - updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); - } + std::vector notifs_to_cancel; + for (LLNotificationSet::iterator it=mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + LLNotificationPtr pNotif = *it; + if (pNotif->getName() == name) + { + notifs_to_cancel.push_back(pNotif); + } + } + + for (std::vector::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end(); + it != end_it; + ++it) + { + LLNotificationPtr pNotif = *it; + pNotif->cancel(); + updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); + } } void LLNotifications::cancelByOwner(const LLUUID ownerId) { LLMutexLock lock(&mItemsMutex); - std::vector notifs_to_cancel; - for (LLNotificationSet::iterator it = mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - LLNotificationPtr pNotif = *it; - if (pNotif && pNotif->getPayload().get("owner_id").asUUID() == ownerId) - { - notifs_to_cancel.push_back(pNotif); - } - } - - for (std::vector::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end(); - it != end_it; - ++it) - { - LLNotificationPtr pNotif = *it; - pNotif->cancel(); - updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); - } + std::vector notifs_to_cancel; + for (LLNotificationSet::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + LLNotificationPtr pNotif = *it; + if (pNotif && pNotif->getPayload().get("owner_id").asUUID() == ownerId) + { + notifs_to_cancel.push_back(pNotif); + } + } + + for (std::vector::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end(); + it != end_it; + ++it) + { + LLNotificationPtr pNotif = *it; + pNotif->cancel(); + updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); + } } void LLNotifications::update(const LLNotificationPtr pNotif) { - LLNotificationSet::iterator it=mItems.find(pNotif); - if (it != mItems.end()) - { - updateItem(LLSD().with("sigtype", "change").with("id", pNotif->id()), pNotif); - } + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + updateItem(LLSD().with("sigtype", "change").with("id", pNotif->id()), pNotif); + } } LLNotificationPtr LLNotifications::find(LLUUID uuid) { - LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid))); - LLNotificationSet::iterator it=mItems.find(target); - if (it == mItems.end()) - { - LL_DEBUGS("Notifications") << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << LL_ENDL; - return LLNotificationPtr((LLNotification*)NULL); - } - else - { - return *it; - } + LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid))); + LLNotificationSet::iterator it=mItems.find(target); + if (it == mItems.end()) + { + LL_DEBUGS("Notifications") << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << LL_ENDL; + return LLNotificationPtr((LLNotification*)NULL); + } + else + { + return *it; + } } std::string LLNotifications::getGlobalString(const std::string& key) const { - GlobalStringMap::const_iterator it = mGlobalStrings.find(key); - if (it != mGlobalStrings.end()) - { - return it->second; - } - else - { - // if we don't have the key as a global, return the key itself so that the error - // is self-diagnosing. - return key; - } + GlobalStringMap::const_iterator it = mGlobalStrings.find(key); + if (it != mGlobalStrings.end()) + { + return it->second; + } + else + { + // if we don't have the key as a global, return the key itself so that the error + // is self-diagnosing. + return key; + } } void LLNotifications::setIgnoreAllNotifications(bool setting) { - mIgnoreAllNotifications = setting; + mIgnoreAllNotifications = setting; } bool LLNotifications::getIgnoreAllNotifications() { - return mIgnoreAllNotifications; + return mIgnoreAllNotifications; } void LLNotifications::setIgnored(const std::string& name, bool ignored) { - LLNotificationTemplatePtr templatep = getTemplate(name); - templatep->mForm->setIgnored(ignored); + LLNotificationTemplatePtr templatep = getTemplate(name); + templatep->mForm->setIgnored(ignored); } bool LLNotifications::getIgnored(const std::string& name) { - LLNotificationTemplatePtr templatep = getTemplate(name); - return (mIgnoreAllNotifications) || ( (templatep->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) && (templatep->mForm->getIgnored()) ); + LLNotificationTemplatePtr templatep = getTemplate(name); + return (mIgnoreAllNotifications) || ( (templatep->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) && (templatep->mForm->getIgnored()) ); } - + bool LLNotifications::isVisibleByRules(LLNotificationPtr n) { - if(n->isRespondedTo()) - { - // This avoids infinite recursion in the case where the filter calls respond() - return true; - } - - VisibilityRuleList::iterator it; - - for(it = mVisibilityRules.begin(); it != mVisibilityRules.end(); it++) - { - // An empty type/tag/name string will match any notification, so only do the comparison when the string is non-empty in the rule. - LL_DEBUGS("Notifications") - << "notification \"" << n->getName() << "\" " - << "testing against " << ((*it)->mVisible?"show":"hide") << " rule, " - << "name = \"" << (*it)->mName << "\" " - << "tag = \"" << (*it)->mTag << "\" " - << "type = \"" << (*it)->mType << "\" " - << LL_ENDL; - - if(!(*it)->mType.empty()) - { - if((*it)->mType != n->getType()) - { - // Type doesn't match, so skip this rule. - continue; - } - } - - if(!(*it)->mTag.empty()) - { - // check this notification's tag(s) against it->mTag and continue if no match is found. - if(!n->matchesTag((*it)->mTag)) - { - // This rule's non-empty tag didn't match one of the notification's tags. Skip this rule. - continue; - } - } - - if(!(*it)->mName.empty()) - { - // check this notification's name against the notification's name and continue if no match is found. - if((*it)->mName != n->getName()) - { - // This rule's non-empty name didn't match the notification. Skip this rule. - continue; - } - } - - // If we got here, the rule matches. Don't evaluate subsequent rules. - if(!(*it)->mVisible) - { - // This notification is being hidden. - - if((*it)->mResponse.empty()) - { - // Response property is empty. Cancel this notification. - LL_DEBUGS("Notifications") << "cancelling notification " << n->getName() << LL_ENDL; - - cancel(n); - } - else - { - // Response property is not empty. Return the specified response. - LLSD response = n->getResponseTemplate(LLNotification::WITHOUT_DEFAULT_BUTTON); - // TODO: verify that the response template has an item with the correct name - response[(*it)->mResponse] = true; - - LL_DEBUGS("Notifications") << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL; - - n->respond(response); - } - - return false; - } - - // If we got here, exit the loop and return true. - break; - } - - LL_DEBUGS("Notifications") << "allowing notification " << n->getName() << LL_ENDL; - - return true; -} - + if(n->isRespondedTo()) + { + // This avoids infinite recursion in the case where the filter calls respond() + return true; + } + + VisibilityRuleList::iterator it; + + for(it = mVisibilityRules.begin(); it != mVisibilityRules.end(); it++) + { + // An empty type/tag/name string will match any notification, so only do the comparison when the string is non-empty in the rule. + LL_DEBUGS("Notifications") + << "notification \"" << n->getName() << "\" " + << "testing against " << ((*it)->mVisible?"show":"hide") << " rule, " + << "name = \"" << (*it)->mName << "\" " + << "tag = \"" << (*it)->mTag << "\" " + << "type = \"" << (*it)->mType << "\" " + << LL_ENDL; + + if(!(*it)->mType.empty()) + { + if((*it)->mType != n->getType()) + { + // Type doesn't match, so skip this rule. + continue; + } + } + + if(!(*it)->mTag.empty()) + { + // check this notification's tag(s) against it->mTag and continue if no match is found. + if(!n->matchesTag((*it)->mTag)) + { + // This rule's non-empty tag didn't match one of the notification's tags. Skip this rule. + continue; + } + } + + if(!(*it)->mName.empty()) + { + // check this notification's name against the notification's name and continue if no match is found. + if((*it)->mName != n->getName()) + { + // This rule's non-empty name didn't match the notification. Skip this rule. + continue; + } + } + + // If we got here, the rule matches. Don't evaluate subsequent rules. + if(!(*it)->mVisible) + { + // This notification is being hidden. + + if((*it)->mResponse.empty()) + { + // Response property is empty. Cancel this notification. + LL_DEBUGS("Notifications") << "cancelling notification " << n->getName() << LL_ENDL; + + cancel(n); + } + else + { + // Response property is not empty. Return the specified response. + LLSD response = n->getResponseTemplate(LLNotification::WITHOUT_DEFAULT_BUTTON); + // TODO: verify that the response template has an item with the correct name + response[(*it)->mResponse] = true; + + LL_DEBUGS("Notifications") << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL; + + n->respond(response); + } + + return false; + } + + // If we got here, exit the loop and return true. + break; + } + + LL_DEBUGS("Notifications") << "allowing notification " << n->getName() << LL_ENDL; + + return true; +} + // --- // END OF LLNotifications implementation @@ -1938,66 +1938,66 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) std::ostream& operator<<(std::ostream& s, const LLNotification& notification) { - s << notification.summarize(); - return s; + s << notification.summarize(); + return s; } void LLPostponedNotification::lookupName(const LLUUID& id, - bool is_group) + bool is_group) { - if (is_group) - { - gCacheName->getGroup(id, - boost::bind(&LLPostponedNotification::onGroupNameCache, - this, _1, _2, _3)); - } - else - { - fetchAvatarName(id); - } + if (is_group) + { + gCacheName->getGroup(id, + boost::bind(&LLPostponedNotification::onGroupNameCache, + this, _1, _2, _3)); + } + else + { + fetchAvatarName(id); + } } void LLPostponedNotification::onGroupNameCache(const LLUUID& id, - const std::string& full_name, - bool is_group) + const std::string& full_name, + bool is_group) { - finalizeName(full_name); + finalizeName(full_name); } void LLPostponedNotification::fetchAvatarName(const LLUUID& id) { - if (id.notNull()) - { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } + if (id.notNull()) + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } - mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); - } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); + } } void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) + const LLAvatarName& av_name) { - mAvatarNameCacheConnection.disconnect(); + mAvatarNameCacheConnection.disconnect(); - std::string name = av_name.getCompleteName(); + std::string name = av_name.getCompleteName(); + + // from PE merge - we should figure out if this is the right thing to do + if (name.empty()) + { + LL_WARNS("Notifications") << "Empty name received for Id: " << agent_id << LL_ENDL; + name = SYSTEM_FROM; + } - // from PE merge - we should figure out if this is the right thing to do - if (name.empty()) - { - LL_WARNS("Notifications") << "Empty name received for Id: " << agent_id << LL_ENDL; - name = SYSTEM_FROM; - } - - finalizeName(name); + finalizeName(name); } void LLPostponedNotification::finalizeName(const std::string& name) { - mName = name; - modifyNotificationParams(); - LLNotifications::instance().add(mParams); - cleanup(); + mName = name; + modifyNotificationParams(); + LLNotifications::instance().add(mParams); + cleanup(); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 8e61ff5259..99f67c06e5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,46 +31,46 @@ /** * This system is intended to provide a singleton mechanism for adding * notifications to one of an arbitrary set of event channels. - * + * * Controlling JIRA: DEV-9061 * * Every notification has (see code for full list): * - a textual name, which is used to look up its template in the XML files * - a payload, which is a block of LLSD * - a channel, which is normally extracted from the XML files but - * can be overridden. + * can be overridden. * - a timestamp, used to order the notifications * - expiration time -- if nonzero, specifies a time after which the * notification will no longer be valid. * - a callback name and a couple of status bits related to callbacks (see below) - * + * * There is a management class called LLNotifications, which is an LLSingleton. * The class maintains a collection of all of the notifications received * or processed during this session, and also manages the persistence * of those notifications that must be persisted. - * + * * We also have Channels. A channel is a view on a collection of notifications; * The collection is defined by a filter function that controls which - * notifications are in the channel, and its ordering is controlled by - * a comparator. + * notifications are in the channel, and its ordering is controlled by + * a comparator. * * There is a hierarchy of channels; notifications flow down from * the management class (LLNotifications, which itself inherits from * The channel base class) to the individual channels. - * Any change to notifications (add, delete, modify) is + * Any change to notifications (add, delete, modify) is * automatically propagated through the channel hierarchy. - * + * * We provide methods for adding a new notification, for removing * one, and for managing channels. Channels are relatively cheap to construct * and maintain, so in general, human interfaces should use channels to * select and manage their lists of notifications. - * - * We also maintain a collection of templates that are loaded from the + * + * We also maintain a collection of templates that are loaded from the * XML file of template translations. The system supports substitution * of named variables from the payload into the XML file. - * + * * By default, only the "unknown message" template is built into the system. - * It is not an error to add a notification that's not found in the + * It is not an error to add a notification that's not found in the * template system, but it is logged. * */ @@ -103,29 +103,29 @@ class LLAvatarName; typedef enum e_notification_priority { - NOTIFICATION_PRIORITY_UNSPECIFIED, - NOTIFICATION_PRIORITY_LOW, - NOTIFICATION_PRIORITY_NORMAL, - NOTIFICATION_PRIORITY_HIGH, - NOTIFICATION_PRIORITY_CRITICAL + NOTIFICATION_PRIORITY_UNSPECIFIED, + NOTIFICATION_PRIORITY_LOW, + NOTIFICATION_PRIORITY_NORMAL, + NOTIFICATION_PRIORITY_HIGH, + NOTIFICATION_PRIORITY_CRITICAL } ENotificationPriority; struct NotificationPriorityValues : public LLInitParam::TypeValuesHelper { - static void declareValues(); + static void declareValues(); }; class LLNotificationResponderInterface { public: - LLNotificationResponderInterface(){}; - virtual ~LLNotificationResponderInterface(){}; + LLNotificationResponderInterface(){}; + virtual ~LLNotificationResponderInterface(){}; - virtual void handleRespond(const LLSD& notification, const LLSD& response) = 0; + virtual void handleRespond(const LLSD& notification, const LLSD& response) = 0; - virtual LLSD asLLSD() = 0; + virtual LLSD asLLSD() = 0; - virtual void fromLLSD(const LLSD& params) = 0; + virtual void fromLLSD(const LLSD& params) = 0; }; typedef boost::function LLNotificationResponder; @@ -141,16 +141,16 @@ class LLNotificationContext : public LLInstanceTracker(LLUUID::generateNewID()) - { - } + LLNotificationContext() : LLInstanceTracker(LLUUID::generateNewID()) + { + } - virtual ~LLNotificationContext() {} + virtual ~LLNotificationContext() {} - LLSD asLLSD() const - { - return getKey(); - } + LLSD asLLSD() const + { + return getKey(); + } private: @@ -160,119 +160,119 @@ private: // manipulator functions class LLNotificationForm { - LOG_CLASS(LLNotificationForm); + LOG_CLASS(LLNotificationForm); public: - struct FormElementBase : public LLInitParam::Block - { - Optional name; - Optional enabled; - - FormElementBase(); - }; - - struct FormIgnore : public LLInitParam::Block - { - Optional text; - Optional save_option; - Optional control; - Optional invert_control; - Optional session_only; - Optional checkbox_only; - - FormIgnore(); - }; - - struct FormButton : public LLInitParam::Block - { - Mandatory index; - Mandatory text; - Optional ignore; - Optional is_default; - Optional width; - - Mandatory type; - - FormButton(); - }; - - struct FormInput : public LLInitParam::Block - { - Mandatory type; - Optional width; - Optional max_length_chars; - Optional text; - - Optional value; - FormInput(); - }; - - struct FormElement : public LLInitParam::ChoiceBlock - { - Alternative button; - Alternative input; - - FormElement(); - }; - - struct FormElements : public LLInitParam::Block - { - Multiple elements; - FormElements(); - }; - - struct Params : public LLInitParam::Block - { - Optional name; - Optional ignore; - Optional form_elements; - - Params(); - }; - - typedef enum e_ignore_type - { - IGNORE_CHECKBOX_ONLY = -1, // ignore won't be handled, will set value/checkbox only - IGNORE_NO = 0, - IGNORE_WITH_DEFAULT_RESPONSE, - IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY, - IGNORE_WITH_LAST_RESPONSE, - IGNORE_SHOW_AGAIN - } EIgnoreType; - - LLNotificationForm(); - LLNotificationForm(const LLNotificationForm&); - LLNotificationForm(const LLSD& sd); - LLNotificationForm(const std::string& name, const Params& p); - - void fromLLSD(const LLSD& sd); - LLSD asLLSD() const; - - S32 getNumElements() { return mFormData.size(); } - LLSD getElement(S32 index) { return mFormData.get(index); } - LLSD getElement(const std::string& element_name); + struct FormElementBase : public LLInitParam::Block + { + Optional name; + Optional enabled; + + FormElementBase(); + }; + + struct FormIgnore : public LLInitParam::Block + { + Optional text; + Optional save_option; + Optional control; + Optional invert_control; + Optional session_only; + Optional checkbox_only; + + FormIgnore(); + }; + + struct FormButton : public LLInitParam::Block + { + Mandatory index; + Mandatory text; + Optional ignore; + Optional is_default; + Optional width; + + Mandatory type; + + FormButton(); + }; + + struct FormInput : public LLInitParam::Block + { + Mandatory type; + Optional width; + Optional max_length_chars; + Optional text; + + Optional value; + FormInput(); + }; + + struct FormElement : public LLInitParam::ChoiceBlock + { + Alternative button; + Alternative input; + + FormElement(); + }; + + struct FormElements : public LLInitParam::Block + { + Multiple elements; + FormElements(); + }; + + struct Params : public LLInitParam::Block + { + Optional name; + Optional ignore; + Optional form_elements; + + Params(); + }; + + typedef enum e_ignore_type + { + IGNORE_CHECKBOX_ONLY = -1, // ignore won't be handled, will set value/checkbox only + IGNORE_NO = 0, + IGNORE_WITH_DEFAULT_RESPONSE, + IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY, + IGNORE_WITH_LAST_RESPONSE, + IGNORE_SHOW_AGAIN + } EIgnoreType; + + LLNotificationForm(); + LLNotificationForm(const LLNotificationForm&); + LLNotificationForm(const LLSD& sd); + LLNotificationForm(const std::string& name, const Params& p); + + void fromLLSD(const LLSD& sd); + LLSD asLLSD() const; + + S32 getNumElements() { return mFormData.size(); } + LLSD getElement(S32 index) { return mFormData.get(index); } + LLSD getElement(const std::string& element_name); void getElements(LLSD& elements, S32 offset = 0); - bool hasElement(const std::string& element_name) const; - bool getElementEnabled(const std::string& element_name) const; - void setElementEnabled(const std::string& element_name, bool enabled); - void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); - void formatElements(const LLSD& substitutions); - // appends form elements from another form serialized as LLSD - void append(const LLSD& sub_form); - std::string getDefaultOption(); - LLPointer getIgnoreSetting(); - bool getIgnored(); - void setIgnored(bool ignored); - - EIgnoreType getIgnoreType() { return mIgnore; } - std::string getIgnoreMessage() { return mIgnoreMsg; } + bool hasElement(const std::string& element_name) const; + bool getElementEnabled(const std::string& element_name) const; + void setElementEnabled(const std::string& element_name, bool enabled); + void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); + void formatElements(const LLSD& substitutions); + // appends form elements from another form serialized as LLSD + void append(const LLSD& sub_form); + std::string getDefaultOption(); + LLPointer getIgnoreSetting(); + bool getIgnored(); + void setIgnored(bool ignored); + + EIgnoreType getIgnoreType() { return mIgnore; } + std::string getIgnoreMessage() { return mIgnoreMsg; } private: - LLSD mFormData; - EIgnoreType mIgnore; - std::string mIgnoreMsg; - LLPointer mIgnoreSetting; - bool mInvertSetting; + LLSD mFormData; + EIgnoreType mIgnore; + std::string mIgnoreMsg; + LLPointer mIgnoreSetting; + bool mInvertSetting; }; typedef std::shared_ptr LLNotificationFormPtr; @@ -292,253 +292,253 @@ typedef std::shared_ptr LLNotificationVisibilityRu /** * @class LLNotification * @brief The object that expresses the details of a notification - * + * * We make this noncopyable because * we want to manage these through LLNotificationPtr, and only * ever create one instance of any given notification. - * + * * The enable_shared_from_this flag ensures that if we construct * a smart pointer from a notification, we'll always get the same * shared pointer. */ -class LLNotification : - boost::noncopyable, - public std::enable_shared_from_this +class LLNotification : + boost::noncopyable, + public std::enable_shared_from_this { LOG_CLASS(LLNotification); friend class LLNotifications; public: - // parameter object used to instantiate a new notification - struct Params : public LLInitParam::Block - { - friend class LLNotification; - - Mandatory name; - Optional id; - Optional substitutions, - form_elements, - payload; - Optional priority; - Optional time_stamp, - expiry; - Optional context; - Optional responder; - Optional offer_from_agent; - Optional is_dnd; - - struct Functor : public LLInitParam::ChoiceBlock - { - Alternative name; - Alternative function; - Alternative responder; - Alternative responder_sd; - - Functor() - : name("responseFunctor"), - function("functor"), - responder("responder"), + // parameter object used to instantiate a new notification + struct Params : public LLInitParam::Block + { + friend class LLNotification; + + Mandatory name; + Optional id; + Optional substitutions, + form_elements, + payload; + Optional priority; + Optional time_stamp, + expiry; + Optional context; + Optional responder; + Optional offer_from_agent; + Optional is_dnd; + + struct Functor : public LLInitParam::ChoiceBlock + { + Alternative name; + Alternative function; + Alternative responder; + Alternative responder_sd; + + Functor() + : name("responseFunctor"), + function("functor"), + responder("responder"), responder_sd("responder_sd") - {} - }; - Optional functor; - - Params() - : name("name"), - id("id"), - priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time"), - payload("payload"), - form_elements("form"), - substitutions("substitutions"), - expiry("expiry"), - offer_from_agent("offer_from_agent", false), + {} + }; + Optional functor; + + Params() + : name("name"), + id("id"), + priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), + time_stamp("time"), + payload("payload"), + form_elements("form"), + substitutions("substitutions"), + expiry("expiry"), + offer_from_agent("offer_from_agent", false), is_dnd("is_dnd", false) - { - time_stamp = LLDate::now(); - responder = NULL; - } - - Params(const std::string& _name) - : name("name"), - priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time"), - payload("payload"), - form_elements("form"), - substitutions("substitutions"), - expiry("expiry"), - offer_from_agent("offer_from_agent", false), + { + time_stamp = LLDate::now(); + responder = NULL; + } + + Params(const std::string& _name) + : name("name"), + priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), + time_stamp("time"), + payload("payload"), + form_elements("form"), + substitutions("substitutions"), + expiry("expiry"), + offer_from_agent("offer_from_agent", false), is_dnd("is_dnd", false) - { - functor.name = _name; - name = _name; - time_stamp = LLDate::now(); - responder = NULL; - } - }; + { + functor.name = _name; + name = _name; + time_stamp = LLDate::now(); + responder = NULL; + } + }; - LLNotificationResponderPtr getResponderPtr() { return mResponder; } + LLNotificationResponderPtr getResponderPtr() { return mResponder; } private: - - const LLUUID mId; - LLSD mPayload; - LLSD mSubstitutions; - LLDate mTimestamp; - LLDate mExpiresAt; - bool mCancelled; - bool mRespondedTo; // once the notification has been responded to, this becomes true - LLSD mResponse; - bool mIgnored; - ENotificationPriority mPriority; - LLNotificationFormPtr mForm; - void* mResponderObj; // TODO - refactor/remove this field - LLNotificationResponderPtr mResponder; - bool mOfferFromAgent; + + const LLUUID mId; + LLSD mPayload; + LLSD mSubstitutions; + LLDate mTimestamp; + LLDate mExpiresAt; + bool mCancelled; + bool mRespondedTo; // once the notification has been responded to, this becomes true + LLSD mResponse; + bool mIgnored; + ENotificationPriority mPriority; + LLNotificationFormPtr mForm; + void* mResponderObj; // TODO - refactor/remove this field + LLNotificationResponderPtr mResponder; + bool mOfferFromAgent; bool mIsDND; - // a reference to the template - LLNotificationTemplatePtr mTemplatep; - - /* - We want to be able to store and reload notifications so that they can survive - a shutdown/restart of the client. So we can't simply pass in callbacks; - we have to specify a callback mechanism that can be used by name rather than - by some arbitrary pointer -- and then people have to initialize callbacks - in some useful location. So we use LLNotificationFunctorRegistry to manage them. - */ - std::string mResponseFunctorName; - - /* - In cases where we want to specify an explict, non-persisted callback, - we store that in the callback registry under a dynamically generated - key, and store the key in the notification, so we can still look it up - using the same mechanism. - */ - bool mTemporaryResponder; - - // keep track of other notifications combined with COMBINE_WITH_NEW - std::vector mCombinedNotifications; - - void init(const std::string& template_name, const LLSD& form_elements); - - void cancel(); + // a reference to the template + LLNotificationTemplatePtr mTemplatep; -public: - LLNotification(const LLSDParamAdapter& p); + /* + We want to be able to store and reload notifications so that they can survive + a shutdown/restart of the client. So we can't simply pass in callbacks; + we have to specify a callback mechanism that can be used by name rather than + by some arbitrary pointer -- and then people have to initialize callbacks + in some useful location. So we use LLNotificationFunctorRegistry to manage them. + */ + std::string mResponseFunctorName; + + /* + In cases where we want to specify an explict, non-persisted callback, + we store that in the callback registry under a dynamically generated + key, and store the key in the notification, so we can still look it up + using the same mechanism. + */ + bool mTemporaryResponder; + + // keep track of other notifications combined with COMBINE_WITH_NEW + std::vector mCombinedNotifications; - void setResponseFunctor(std::string const &responseFunctorName); + void init(const std::string& template_name, const LLSD& form_elements); - void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); + void cancel(); - void setResponseFunctor(const LLNotificationResponderPtr& responder); +public: + LLNotification(const LLSDParamAdapter& p); - typedef enum e_response_template_type - { - WITHOUT_DEFAULT_BUTTON, - WITH_DEFAULT_BUTTON - } EResponseTemplateType; + void setResponseFunctor(std::string const &responseFunctorName); - // return response LLSD filled in with default form contents and (optionally) the default button selected - LLSD getResponseTemplate(EResponseTemplateType type = WITHOUT_DEFAULT_BUTTON); + void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); - // returns index of first button with value==TRUE - // usually this the button the user clicked on - // returns -1 if no button clicked (e.g. form has not been displayed) - static S32 getSelectedOption(const LLSD& notification, const LLSD& response); - // returns name of first button with value==TRUE - static std::string getSelectedOptionName(const LLSD& notification); + void setResponseFunctor(const LLNotificationResponderPtr& responder); - // after someone responds to a notification (usually by clicking a button, - // but sometimes by filling out a little form and THEN clicking a button), + typedef enum e_response_template_type + { + WITHOUT_DEFAULT_BUTTON, + WITH_DEFAULT_BUTTON + } EResponseTemplateType; + + // return response LLSD filled in with default form contents and (optionally) the default button selected + LLSD getResponseTemplate(EResponseTemplateType type = WITHOUT_DEFAULT_BUTTON); + + // returns index of first button with value==TRUE + // usually this the button the user clicked on + // returns -1 if no button clicked (e.g. form has not been displayed) + static S32 getSelectedOption(const LLSD& notification, const LLSD& response); + // returns name of first button with value==TRUE + static std::string getSelectedOptionName(const LLSD& notification); + + // after someone responds to a notification (usually by clicking a button, + // but sometimes by filling out a little form and THEN clicking a button), // the result of the response (the name and value of the button clicked, - // plus any other data) should be packaged up as LLSD, then passed as a - // parameter to the notification's respond() method here. This will look up - // and call the appropriate responder. - // - // response is notification serialized as LLSD: - // ["name"] = notification name - // ["form"] = LLSD tree that includes form description and any prefilled form data - // ["response"] = form data filled in by user - // (including, but not limited to which button they clicked on) - // ["payload"] = transaction specific data, such as ["source_id"] (originator of notification), - // ["item_id"] (attached inventory item), etc. - // ["substitutions"] = string substitutions used to generate notification message + // plus any other data) should be packaged up as LLSD, then passed as a + // parameter to the notification's respond() method here. This will look up + // and call the appropriate responder. + // + // response is notification serialized as LLSD: + // ["name"] = notification name + // ["form"] = LLSD tree that includes form description and any prefilled form data + // ["response"] = form data filled in by user + // (including, but not limited to which button they clicked on) + // ["payload"] = transaction specific data, such as ["source_id"] (originator of notification), + // ["item_id"] (attached inventory item), etc. + // ["substitutions"] = string substitutions used to generate notification message // from the template - // ["time"] = time at which notification was generated; - // ["expiry"] = time at which notification expires; - // ["responseFunctor"] = name of registered functor that handles responses to notification; - LLSD asLLSD(bool excludeTemplateElements = false); + // ["time"] = time at which notification was generated; + // ["expiry"] = time at which notification expires; + // ["responseFunctor"] = name of registered functor that handles responses to notification; + LLSD asLLSD(bool excludeTemplateElements = false); - const LLNotificationFormPtr getForm(); - void updateForm(const LLNotificationFormPtr& form); + const LLNotificationFormPtr getForm(); + void updateForm(const LLNotificationFormPtr& form); - void repost(); + void repost(); - void respond(const LLSD& sd); - void respondWithDefault(); + void respond(const LLSD& sd); + void respondWithDefault(); - void* getResponder() { return mResponderObj; } + void* getResponder() { return mResponderObj; } - void setResponder(void* responder) { mResponderObj = responder; } + void setResponder(void* responder) { mResponderObj = responder; } - void setIgnored(bool ignore); + void setIgnored(bool ignore); - bool isCancelled() const - { - return mCancelled; - } + bool isCancelled() const + { + return mCancelled; + } - bool isRespondedTo() const - { - return mRespondedTo; - } + bool isRespondedTo() const + { + return mRespondedTo; + } - bool isActive() const - { - return !isRespondedTo() - && !isCancelled() - && !isExpired(); - } + bool isActive() const + { + return !isRespondedTo() + && !isCancelled() + && !isExpired(); + } - const LLSD& getResponse() { return mResponse; } + const LLSD& getResponse() { return mResponse; } + + bool isIgnored() const + { + return mIgnored; + } - bool isIgnored() const - { - return mIgnored; - } + const std::string& getName() const; - const std::string& getName() const; + const std::string& getIcon() const; - const std::string& getIcon() const; + bool isPersistent() const; - bool isPersistent() const; + const LLUUID& id() const + { + return mId; + } - const LLUUID& id() const - { - return mId; - } - - const LLSD& getPayload() const - { - return mPayload; - } + const LLSD& getPayload() const + { + return mPayload; + } - const LLSD& getSubstitutions() const - { - return mSubstitutions; - } + const LLSD& getSubstitutions() const + { + return mSubstitutions; + } - const LLDate& getDate() const - { - return mTimestamp; - } + const LLDate& getDate() const + { + return mTimestamp; + } - bool getOfferFromAgent() const - { - return mOfferFromAgent; - } + bool getOfferFromAgent() const + { + return mOfferFromAgent; + } bool isDND() const { @@ -550,165 +550,165 @@ public: mIsDND = flag; } - std::string getType() const; - std::string getMessage() const; - std::string getFooter() const; - std::string getLabel() const; - std::string getURL() const; - S32 getURLOption() const; - S32 getURLOpenExternally() const; //for url responce option - bool getForceUrlsExternal() const; - bool canLogToChat() const; - bool canLogToIM() const; - bool canShowToast() const; - bool canFadeToast() const; - bool hasFormElements() const; + std::string getType() const; + std::string getMessage() const; + std::string getFooter() const; + std::string getLabel() const; + std::string getURL() const; + S32 getURLOption() const; + S32 getURLOpenExternally() const; //for url responce option + bool getForceUrlsExternal() const; + bool canLogToChat() const; + bool canLogToIM() const; + bool canShowToast() const; + bool canFadeToast() const; + bool hasFormElements() const; void playSound(); - typedef enum e_combine_behavior - { - REPLACE_WITH_NEW, - COMBINE_WITH_NEW, - KEEP_OLD, - CANCEL_OLD - - } ECombineBehavior; - - ECombineBehavior getCombineBehavior() const; - - const LLDate getExpiration() const - { - return mExpiresAt; - } - - ENotificationPriority getPriority() const - { - return mPriority; - } - - const LLUUID getID() const - { - return mId; - } - - // comparing two notifications normally means comparing them by UUID (so we can look them - // up quickly this way) - bool operator<(const LLNotification& rhs) const - { - return mId < rhs.mId; - } - - bool operator==(const LLNotification& rhs) const - { - return mId == rhs.mId; - } - - bool operator!=(const LLNotification& rhs) const - { - return !operator==(rhs); - } - - bool isSameObjectAs(const LLNotification* rhs) const - { - return this == rhs; - } - - // this object has been updated, so tell all our clients - void update(); - - void updateFrom(LLNotificationPtr other); - - // A fuzzy equals comparator. - // true only if both notifications have the same template and - // 1) flagged as unique (there can be only one of these) OR - // 2) all required payload fields of each also exist in the other. - bool isEquivalentTo(LLNotificationPtr that) const; - - // if the current time is greater than the expiration, the notification is expired - bool isExpired() const - { - if (mExpiresAt.secondsSinceEpoch() == 0) - { - return false; - } - - LLDate rightnow = LLDate::now(); - return rightnow > mExpiresAt; - } - - std::string summarize() const; - - bool hasUniquenessConstraints() const; - - bool matchesTag(const std::string& tag); - - virtual ~LLNotification() {} + typedef enum e_combine_behavior + { + REPLACE_WITH_NEW, + COMBINE_WITH_NEW, + KEEP_OLD, + CANCEL_OLD + + } ECombineBehavior; + + ECombineBehavior getCombineBehavior() const; + + const LLDate getExpiration() const + { + return mExpiresAt; + } + + ENotificationPriority getPriority() const + { + return mPriority; + } + + const LLUUID getID() const + { + return mId; + } + + // comparing two notifications normally means comparing them by UUID (so we can look them + // up quickly this way) + bool operator<(const LLNotification& rhs) const + { + return mId < rhs.mId; + } + + bool operator==(const LLNotification& rhs) const + { + return mId == rhs.mId; + } + + bool operator!=(const LLNotification& rhs) const + { + return !operator==(rhs); + } + + bool isSameObjectAs(const LLNotification* rhs) const + { + return this == rhs; + } + + // this object has been updated, so tell all our clients + void update(); + + void updateFrom(LLNotificationPtr other); + + // A fuzzy equals comparator. + // true only if both notifications have the same template and + // 1) flagged as unique (there can be only one of these) OR + // 2) all required payload fields of each also exist in the other. + bool isEquivalentTo(LLNotificationPtr that) const; + + // if the current time is greater than the expiration, the notification is expired + bool isExpired() const + { + if (mExpiresAt.secondsSinceEpoch() == 0) + { + return false; + } + + LLDate rightnow = LLDate::now(); + return rightnow > mExpiresAt; + } + + std::string summarize() const; + + bool hasUniquenessConstraints() const; + + bool matchesTag(const std::string& tag); + + virtual ~LLNotification() {} }; std::ostream& operator<<(std::ostream& s, const LLNotification& notification); namespace LLNotificationFilters { - // a sample filter - bool includeEverything(LLNotificationPtr p); - - typedef enum e_comparison - { - EQUAL, - LESS, - GREATER, - LESS_EQUAL, - GREATER_EQUAL - } EComparison; - - // generic filter functor that takes method or member variable reference - template - struct filterBy - { - typedef boost::function field_t; - typedef typename boost::remove_reference::type value_t; - - filterBy(field_t field, value_t value, EComparison comparison = EQUAL) - : mField(field), - mFilterValue(value), - mComparison(comparison) - { - } - - bool operator()(LLNotificationPtr p) - { - switch(mComparison) - { - case EQUAL: - return mField(p) == mFilterValue; - case LESS: - return mField(p) < mFilterValue; - case GREATER: - return mField(p) > mFilterValue; - case LESS_EQUAL: - return mField(p) <= mFilterValue; - case GREATER_EQUAL: - return mField(p) >= mFilterValue; - default: - return false; - } - } - - field_t mField; - value_t mFilterValue; - EComparison mComparison; - }; + // a sample filter + bool includeEverything(LLNotificationPtr p); + + typedef enum e_comparison + { + EQUAL, + LESS, + GREATER, + LESS_EQUAL, + GREATER_EQUAL + } EComparison; + + // generic filter functor that takes method or member variable reference + template + struct filterBy + { + typedef boost::function field_t; + typedef typename boost::remove_reference::type value_t; + + filterBy(field_t field, value_t value, EComparison comparison = EQUAL) + : mField(field), + mFilterValue(value), + mComparison(comparison) + { + } + + bool operator()(LLNotificationPtr p) + { + switch(mComparison) + { + case EQUAL: + return mField(p) == mFilterValue; + case LESS: + return mField(p) < mFilterValue; + case GREATER: + return mField(p) > mFilterValue; + case LESS_EQUAL: + return mField(p) <= mFilterValue; + case GREATER_EQUAL: + return mField(p) >= mFilterValue; + default: + return false; + } + } + + field_t mField; + value_t mFilterValue; + EComparison mComparison; + }; }; namespace LLNotificationComparators { - struct orderByUUID - { - bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) const - { - return lhs->id() < rhs->id(); - } - }; + struct orderByUUID + { + bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) const + { + return lhs->id() < rhs->id(); + } + }; }; typedef boost::function LLNotificationFilter; @@ -729,18 +729,18 @@ typedef std::multimap LLNotificationMap; // +-- Alerts // +-- Notifications // -// In general, new channels that want to only see notifications that pass through +// In general, new channels that want to only see notifications that pass through // all of the built-in tests should attach to the "Visible" channel // class LLNotificationChannelBase : - public LLEventTrackable, - public LLRefCount + public LLEventTrackable, + public LLRefCount { - LOG_CLASS(LLNotificationChannelBase); + LOG_CLASS(LLNotificationChannelBase); public: - LLNotificationChannelBase(LLNotificationFilter filter) + LLNotificationChannelBase(LLNotificationFilter filter) : mFilter(filter) - , mItems() + , mItems() , mItemsMutex() {} @@ -753,8 +753,8 @@ public: LLMutexLock lock(&mItemsMutex); mItems.clear(); } - // you can also connect to a Channel, so you can be notified of - // changes to this channel + // you can also connect to a Channel, so you can be notified of + // changes to this channel LLBoundListener connectChanged(const LLEventListener& slot) { // Call this->connectChangedImpl() to actually connect it. @@ -775,9 +775,9 @@ public: return connectFailedFilterImpl(slot); } - // use this when items change or to add a new one - bool updateItem(const LLSD& payload); - const LLNotificationFilter& getFilter() { return mFilter; } + // use this when items change or to add a new one + bool updateItem(const LLSD& payload); + const LLNotificationFilter& getFilter() { return mFilter; } protected: LLBoundListener connectChangedImpl(const LLEventListener& slot); @@ -785,29 +785,29 @@ protected: LLBoundListener connectPassedFilterImpl(const LLEventListener& slot); LLBoundListener connectFailedFilterImpl(const LLEventListener& slot); - LLNotificationSet mItems; - LLStandardSignal mChanged; - LLStandardSignal mPassedFilter; - LLStandardSignal mFailedFilter; + LLNotificationSet mItems; + LLStandardSignal mChanged; + LLStandardSignal mPassedFilter; + LLStandardSignal mFailedFilter; LLMutex mItemsMutex; - - // these are action methods that subclasses can override to take action - // on specific types of changes; the management of the mItems list is - // still handled by the generic handler. - virtual void onLoad(LLNotificationPtr p) {} - virtual void onAdd(LLNotificationPtr p) {} - virtual void onDelete(LLNotificationPtr p) {} - virtual void onChange(LLNotificationPtr p) {} - - virtual void onFilterPass(LLNotificationPtr p) {} - virtual void onFilterFail(LLNotificationPtr p) {} - - bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); - LLNotificationFilter mFilter; + + // these are action methods that subclasses can override to take action + // on specific types of changes; the management of the mItems list is + // still handled by the generic handler. + virtual void onLoad(LLNotificationPtr p) {} + virtual void onAdd(LLNotificationPtr p) {} + virtual void onDelete(LLNotificationPtr p) {} + virtual void onChange(LLNotificationPtr p) {} + + virtual void onFilterPass(LLNotificationPtr p) {} + virtual void onFilterFail(LLNotificationPtr p) {} + + bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); + LLNotificationFilter mFilter; }; // The type of the pointers that we're going to manage in the NotificationQueue system -// Because LLNotifications is a singleton, we don't actually expect to ever +// Because LLNotifications is a singleton, we don't actually expect to ever // destroy it, but if it becomes necessary to do so, the shared_ptr model // will ensure that we don't leak resources. class LLNotificationChannel; @@ -815,39 +815,39 @@ typedef boost::intrusive_ptr LLNotificationChannelPtr; // manages a list of notifications // Note that if this is ever copied around, we might find ourselves with multiple copies -// of a queue with notifications being added to different nonequivalent copies. So we +// of a queue with notifications being added to different nonequivalent copies. So we // make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it. // -class LLNotificationChannel : - boost::noncopyable, - public LLNotificationChannelBase, - public LLInstanceTracker +class LLNotificationChannel : + boost::noncopyable, + public LLNotificationChannelBase, + public LLInstanceTracker { - LOG_CLASS(LLNotificationChannel); - -public: - // Notification Channels have a filter, which determines which notifications - // will be added to this channel. - // Channel filters cannot change. - struct Params : public LLInitParam::Block - { - Mandatory name; - Optional filter; - Multiple sources; - }; - - LLNotificationChannel(const Params& p = Params()); - LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); - - virtual ~LLNotificationChannel(); - typedef LLNotificationSet::iterator Iterator; - - std::string getName() const { return mName; } - typedef std::vector::const_iterator parents_iter; - boost::iterator_range getParents() const - { - return boost::iterator_range(mParents); - } + LOG_CLASS(LLNotificationChannel); + +public: + // Notification Channels have a filter, which determines which notifications + // will be added to this channel. + // Channel filters cannot change. + struct Params : public LLInitParam::Block + { + Mandatory name; + Optional filter; + Multiple sources; + }; + + LLNotificationChannel(const Params& p = Params()); + LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); + + virtual ~LLNotificationChannel(); + typedef LLNotificationSet::iterator Iterator; + + std::string getName() const { return mName; } + typedef std::vector::const_iterator parents_iter; + boost::iterator_range getParents() const + { + return boost::iterator_range(mParents); + } bool isEmpty() const; S32 size() const; @@ -856,14 +856,14 @@ public: typedef boost::function NotificationProcess; void forEachNotification(NotificationProcess process); - std::string summarize(); + std::string summarize(); protected: void connectToChannel(const std::string& channel_name); private: - std::string mName; - std::vector mParents; + std::string mName; + std::vector mParents; std::vector mListeners; }; @@ -872,20 +872,20 @@ private: class LLNotificationsInterface { public: - virtual LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - LLNotificationFunctorRegistry::ResponseFunctor functor) = 0; + virtual LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) = 0; }; -class LLNotifications : - public LLNotificationsInterface, - public LLSingleton, - public LLNotificationChannelBase +class LLNotifications : + public LLNotificationsInterface, + public LLSingleton, + public LLNotificationChannelBase { - LLSINGLETON(LLNotifications); - LOG_CLASS(LLNotifications); - virtual ~LLNotifications() {} + LLSINGLETON(LLNotifications); + LOG_CLASS(LLNotifications); + virtual ~LLNotifications() {} public: @@ -895,106 +895,106 @@ public: // void clear(); - // load all notification descriptions from file - // calling more than once will overwrite existing templates - // but never delete a template - bool loadTemplates(); - - // load visibility rules from file; - // OK to call more than once because it will reload - bool loadVisibilityRules(); - - // Add a simple notification (from XUI) - void addFromCallback(const LLSD& name); - - // *NOTE: To add simple notifications, #include "llnotificationsutil.h" - // and use LLNotificationsUtil::add("MyNote") or add("MyNote", args) - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload); - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name); - /* virtual */ LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - LLNotificationFunctorRegistry::ResponseFunctor functor) override; - LLNotificationPtr add(const LLNotification::Params& p); - - void add(const LLNotificationPtr pNotif); - void load(const LLNotificationPtr pNotif); - void cancel(LLNotificationPtr pNotif); - void cancelByName(const std::string& name); - void cancelByOwner(const LLUUID ownerId); - void update(const LLNotificationPtr pNotif); - - LLNotificationPtr find(LLUUID uuid); - - // This is all stuff for managing the templates - // take your template out - LLNotificationTemplatePtr getTemplate(const std::string& name); - - // get the whole collection - typedef std::vector TemplateNames; - TemplateNames getTemplateNames() const; // returns a list of notification names - - typedef std::map TemplateMap; - - TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); } - TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); } - - // test for existence - bool templateExists(const std::string& name); - - typedef std::list VisibilityRuleList; - - void forceResponse(const LLNotification::Params& params, S32 option); - - void createDefaultChannels(); - - LLNotificationChannelPtr getChannel(const std::string& channelName); - - std::string getGlobalString(const std::string& key) const; - - void setIgnoreAllNotifications(bool ignore); - bool getIgnoreAllNotifications(); - - void setIgnored(const std::string& name, bool ignored); - bool getIgnored(const std::string& name); - - bool isVisibleByRules(LLNotificationPtr pNotification); - + // load all notification descriptions from file + // calling more than once will overwrite existing templates + // but never delete a template + bool loadTemplates(); + + // load visibility rules from file; + // OK to call more than once because it will reload + bool loadVisibilityRules(); + + // Add a simple notification (from XUI) + void addFromCallback(const LLSD& name); + + // *NOTE: To add simple notifications, #include "llnotificationsutil.h" + // and use LLNotificationsUtil::add("MyNote") or add("MyNote", args) + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload); + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name); + /* virtual */ LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) override; + LLNotificationPtr add(const LLNotification::Params& p); + + void add(const LLNotificationPtr pNotif); + void load(const LLNotificationPtr pNotif); + void cancel(LLNotificationPtr pNotif); + void cancelByName(const std::string& name); + void cancelByOwner(const LLUUID ownerId); + void update(const LLNotificationPtr pNotif); + + LLNotificationPtr find(LLUUID uuid); + + // This is all stuff for managing the templates + // take your template out + LLNotificationTemplatePtr getTemplate(const std::string& name); + + // get the whole collection + typedef std::vector TemplateNames; + TemplateNames getTemplateNames() const; // returns a list of notification names + + typedef std::map TemplateMap; + + TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); } + TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); } + + // test for existence + bool templateExists(const std::string& name); + + typedef std::list VisibilityRuleList; + + void forceResponse(const LLNotification::Params& params, S32 option); + + void createDefaultChannels(); + + LLNotificationChannelPtr getChannel(const std::string& channelName); + + std::string getGlobalString(const std::string& key) const; + + void setIgnoreAllNotifications(bool ignore); + bool getIgnoreAllNotifications(); + + void setIgnored(const std::string& name, bool ignored); + bool getIgnored(const std::string& name); + + bool isVisibleByRules(LLNotificationPtr pNotification); + private: - /*virtual*/ void initSingleton() override; - /*virtual*/ void cleanupSingleton() override; - - void loadPersistentNotifications(); - - bool expirationFilter(LLNotificationPtr pNotification); - bool expirationHandler(const LLSD& payload); - bool uniqueFilter(LLNotificationPtr pNotification); - bool uniqueHandler(const LLSD& payload); - bool failedUniquenessTest(const LLSD& payload); - LLNotificationChannelPtr pHistoryChannel; - LLNotificationChannelPtr pExpirationChannel; - - TemplateMap mTemplates; - - VisibilityRuleList mVisibilityRules; - - std::string mFileName; - - LLNotificationMap mUniqueNotifications; - - typedef std::map GlobalStringMap; - GlobalStringMap mGlobalStrings; - - bool mIgnoreAllNotifications; - - std::unique_ptr mListener; - - std::vector mDefaultChannels; + /*virtual*/ void initSingleton() override; + /*virtual*/ void cleanupSingleton() override; + + void loadPersistentNotifications(); + + bool expirationFilter(LLNotificationPtr pNotification); + bool expirationHandler(const LLSD& payload); + bool uniqueFilter(LLNotificationPtr pNotification); + bool uniqueHandler(const LLSD& payload); + bool failedUniquenessTest(const LLSD& payload); + LLNotificationChannelPtr pHistoryChannel; + LLNotificationChannelPtr pExpirationChannel; + + TemplateMap mTemplates; + + VisibilityRuleList mVisibilityRules; + + std::string mFileName; + + LLNotificationMap mUniqueNotifications; + + typedef std::map GlobalStringMap; + GlobalStringMap mGlobalStrings; + + bool mIgnoreAllNotifications; + + std::unique_ptr mListener; + + std::vector mDefaultChannels; }; /** @@ -1010,64 +1010,64 @@ private: class LLPostponedNotification : public LLMortician { public: - /** - * Performs hooking cache name callback which will add notification to notifications system. - * Type of added notification should be specified by template parameter T - * and non-private derived from LLPostponedNotification class, - * otherwise compilation error will occur. - */ - template - static void add(const LLNotification::Params& params, - const LLUUID& id, bool is_group) - { - // upcast T to the base type to restrict T derivation from LLPostponedNotification - LLPostponedNotification* thiz = new T(); - thiz->mParams = params; - - // Avoid header file dependency on llcachename.h - thiz->lookupName(id, is_group); - } + /** + * Performs hooking cache name callback which will add notification to notifications system. + * Type of added notification should be specified by template parameter T + * and non-private derived from LLPostponedNotification class, + * otherwise compilation error will occur. + */ + template + static void add(const LLNotification::Params& params, + const LLUUID& id, bool is_group) + { + // upcast T to the base type to restrict T derivation from LLPostponedNotification + LLPostponedNotification* thiz = new T(); + thiz->mParams = params; + + // Avoid header file dependency on llcachename.h + thiz->lookupName(id, is_group); + } private: - void lookupName(const LLUUID& id, bool is_group); - // only used for groups - void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - // only used for avatars - void fetchAvatarName(const LLUUID& id); - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - // used for both group and avatar names - void finalizeName(const std::string& name); - - void cleanup() - { - die(); - } + void lookupName(const LLUUID& id, bool is_group); + // only used for groups + void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group); + // only used for avatars + void fetchAvatarName(const LLUUID& id); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + // used for both group and avatar names + void finalizeName(const std::string& name); + + void cleanup() + { + die(); + } protected: - LLPostponedNotification() - : mParams(), - mName(), - mAvatarNameCacheConnection() - {} - - virtual ~LLPostponedNotification() - { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - } - - /** - * Abstract method provides possibility to modify notification parameters and - * will be called after cache name retrieve information about avatar or group - * and before notification will be added to the notification system. - */ - virtual void modifyNotificationParams() = 0; - - LLNotification::Params mParams; - std::string mName; - boost::signals2::connection mAvatarNameCacheConnection; + LLPostponedNotification() + : mParams(), + mName(), + mAvatarNameCacheConnection() + {} + + virtual ~LLPostponedNotification() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } + + /** + * Abstract method provides possibility to modify notification parameters and + * will be called after cache name retrieve information about avatar or group + * and before notification will be added to the notification system. + */ + virtual void modifyNotificationParams() = 0; + + LLNotification::Params mParams; + std::string mName; + boost::signals2::connection mAvatarNameCacheConnection; }; // Stores only persistent notifications. @@ -1075,57 +1075,57 @@ protected: // (see LLPersistentNotificationStorage for example). class LLPersistentNotificationChannel : public LLNotificationChannel { - LOG_CLASS(LLPersistentNotificationChannel); + LOG_CLASS(LLPersistentNotificationChannel); public: - LLPersistentNotificationChannel() - : LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) - {} + LLPersistentNotificationChannel() + : LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) + {} virtual ~LLPersistentNotificationChannel() { mHistory.clear(); } - typedef std::vector history_list_t; - history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } - history_list_t::iterator endHistory() { return mHistory.end(); } + typedef std::vector history_list_t; + history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } + history_list_t::iterator endHistory() { return mHistory.end(); } private: - struct sortByTime - { - S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) - { - return a->getDate() < b->getDate(); - } - }; - - void sortHistory() - { - std::sort(mHistory.begin(), mHistory.end(), sortByTime()); - } - - // The channel gets all persistent notifications except those that have been canceled - static bool notificationFilter(LLNotificationPtr pNotification) - { - bool handle_notification = false; - - handle_notification = pNotification->isPersistent() - && !pNotification->isCancelled(); - - return handle_notification; - } - - void onAdd(LLNotificationPtr p) - { - mHistory.push_back(p); - } - - void onLoad(LLNotificationPtr p) - { - mHistory.push_back(p); - } - - std::vector mHistory; + struct sortByTime + { + S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) + { + return a->getDate() < b->getDate(); + } + }; + + void sortHistory() + { + std::sort(mHistory.begin(), mHistory.end(), sortByTime()); + } + + // The channel gets all persistent notifications except those that have been canceled + static bool notificationFilter(LLNotificationPtr pNotification) + { + bool handle_notification = false; + + handle_notification = pNotification->isPersistent() + && !pNotification->isCancelled(); + + return handle_notification; + } + + void onAdd(LLNotificationPtr p) + { + mHistory.push_back(p); + } + + void onLoad(LLNotificationPtr p) + { + mHistory.push_back(p); + } + + std::vector mHistory; }; #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 859222f907..ace9e37e25 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -3,25 +3,25 @@ * @author Brad Kittenbrink * @date 2009-07-08 * @brief Implementation for llnotificationslistener. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -87,39 +87,39 @@ LLNotificationsListener::~LLNotificationsListener() void LLNotificationsListener::requestAdd(const LLSD& event_data) const { - if(event_data.has("reply")) - { - LLSD payload(event_data["payload"]); - // copy reqid, if provided, to link response with request - payload["reqid"] = event_data["reqid"]; - mNotifications.add(event_data["name"], - event_data["substitutions"], - payload, - boost::bind(&LLNotificationsListener::NotificationResponder, - this, - event_data["reply"].asString(), - _1, _2 - ) - ); - } - else - { - mNotifications.add(event_data["name"], - event_data["substitutions"], - event_data["payload"]); - } + if(event_data.has("reply")) + { + LLSD payload(event_data["payload"]); + // copy reqid, if provided, to link response with request + payload["reqid"] = event_data["reqid"]; + mNotifications.add(event_data["name"], + event_data["substitutions"], + payload, + boost::bind(&LLNotificationsListener::NotificationResponder, + this, + event_data["reply"].asString(), + _1, _2 + ) + ); + } + else + { + mNotifications.add(event_data["name"], + event_data["substitutions"], + event_data["payload"]); + } } -void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, - const LLSD& notification, - const LLSD& response) const +void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, + const LLSD& notification, + const LLSD& response) const { - LLSD response_event; - response_event["notification"] = notification; - response_event["response"] = response; - // surface reqid at top level of response for request/response protocol - response_event["reqid"] = notification["payload"]["reqid"]; - LLEventPumps::getInstance()->obtain(reply_pump).post(response_event); + LLSD response_event; + response_event["notification"] = notification; + response_event["response"] = response; + // surface reqid at top level of response for request/response protocol + response_event["reqid"] = notification["payload"]["reqid"]; + LLEventPumps::getInstance()->obtain(reply_pump).post(response_event); } void LLNotificationsListener::listChannels(const LLSD& params) const @@ -191,11 +191,11 @@ void LLNotificationsListener::ignore(const LLSD& params) const if (params["name"].isDefined()) { // ["name"] was passed: ignore just that notification - LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); - if (templatep) - { - templatep->mForm->setIgnored(ignore); - } + LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); + if (templatep) + { + templatep->mForm->setIgnored(ignore); + } } else { diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 4bab377626..65993c9ff8 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -3,25 +3,25 @@ * @author Brad Kittenbrink * @date 2009-07-08 * @brief Wrap subset of LLNotifications API in event API for test scripts. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,9 +46,9 @@ public: private: void requestAdd(LLSD const & event_data) const; - void NotificationResponder(const std::string& replypump, - const LLSD& notification, - const LLSD& response) const; + void NotificationResponder(const std::string& replypump, + const LLSD& notification, + const LLSD& response) const; void listChannels(const LLSD& params) const; void listChannelNotifications(const LLSD& params) const; @@ -62,7 +62,7 @@ private: class Forwarder; typedef std::map > ForwarderMap; ForwarderMap mForwarders; - LLNotifications & mNotifications; + LLNotifications & mNotifications; }; #endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp index cc791c26d1..c1cad431c5 100644 --- a/indra/llui/llnotificationsutil.cpp +++ b/indra/llui/llnotificationsutil.cpp @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,68 +28,68 @@ #include "llnotifications.h" #include "llsd.h" -#include "llxmlnode.h" // apparently needed to call LLNotifications::instance() +#include "llxmlnode.h" // apparently needed to call LLNotifications::instance() LLNotificationPtr LLNotificationsUtil::add(const std::string& name) { - LLNotification::Params::Functor functor_p; - functor_p.name = name; - return LLNotifications::instance().add( - LLNotification::Params().name(name).substitutions(LLSD()).payload(LLSD()).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(LLSD()).payload(LLSD()).functor(functor_p)); } -LLNotificationPtr LLNotificationsUtil::add(const std::string& name, - const LLSD& substitutions) +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions) { - LLNotification::Params::Functor functor_p; - functor_p.name = name; - return LLNotifications::instance().add( - LLNotification::Params().name(name).substitutions(substitutions).payload(LLSD()).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(LLSD()).functor(functor_p)); } -LLNotificationPtr LLNotificationsUtil::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload) +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload) { - LLNotification::Params::Functor functor_p; - functor_p.name = name; - return LLNotifications::instance().add( - LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } -LLNotificationPtr LLNotificationsUtil::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name) +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name) { - LLNotification::Params::Functor functor_p; - functor_p.name = functor_name; - return LLNotifications::instance().add( - LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.name = functor_name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } -LLNotificationPtr LLNotificationsUtil::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - boost::function functor) +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function functor) { - LLNotification::Params::Functor functor_p; - functor_p.function = functor; - return LLNotifications::instance().add( - LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + LLNotification::Params::Functor functor_p; + functor_p.function = functor; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } S32 LLNotificationsUtil::getSelectedOption(const LLSD& notification, const LLSD& response) { - return LLNotification::getSelectedOption(notification, response); + return LLNotification::getSelectedOption(notification, response); } void LLNotificationsUtil::cancel(LLNotificationPtr pNotif) { - LLNotifications::instance().cancel(pNotif); + LLNotifications::instance().cancel(pNotif); } LLNotificationPtr LLNotificationsUtil::find(LLUUID uuid) { - return LLNotifications::instance().find(uuid); + return LLNotifications::instance().find(uuid); } diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h index 9f29087b4a..f21d93a50e 100644 --- a/indra/llui/llnotificationsutil.h +++ b/indra/llui/llnotificationsutil.h @@ -4,28 +4,28 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLNOTIFICATIONSUTIL_H #define LLNOTIFICATIONSUTIL_H -// The vast majority of clients of the notifications system just want to add +// The vast majority of clients of the notifications system just want to add // a notification to the screen, so define this lightweight public interface // to avoid including the heavyweight llnotifications.h @@ -38,30 +38,30 @@ class LLSD; namespace LLNotificationsUtil { - LLNotificationPtr add(const std::string& name); - - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions); - - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload); - - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name); + LLNotificationPtr add(const std::string& name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function functor); - LLNotificationPtr add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - boost::function functor); - - S32 getSelectedOption(const LLSD& notification, const LLSD& response); + S32 getSelectedOption(const LLSD& notification, const LLSD& response); - void cancel(LLNotificationPtr pNotif); + void cancel(LLNotificationPtr pNotif); - LLNotificationPtr find(LLUUID uuid); + LLNotificationPtr find(LLUUID uuid); } #endif diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index a8902486e4..0f77251ffe 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. -* +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,212 +33,212 @@ typedef std::shared_ptr LLNotificationFormPtr; -// This is the class of object read from the XML file (notifications.xml, +// This is the class of object read from the XML file (notifications.xml, // from the appropriate local language directory). struct LLNotificationTemplate { - struct CombineBehaviorNames - : public LLInitParam::TypeValuesHelper - { - static void declareValues() - { - declare("replace_with_new", LLNotification::REPLACE_WITH_NEW); - declare("combine_with_new", LLNotification::COMBINE_WITH_NEW); - declare("keep_old", LLNotification::KEEP_OLD); - declare("cancel_old", LLNotification::CANCEL_OLD); - } - }; - - - struct GlobalString : public LLInitParam::Block - { - Mandatory name, - value; - - GlobalString() - : name("name"), - value("value") - {} - }; - - struct UniquenessContext : public LLInitParam::Block - { - Mandatory value; - - UniquenessContext() - : value("value") - { - addSynonym(value, "key"); - } - - }; - - struct UniquenessConstraint : public LLInitParam::Block - { - private: - // this idiom allows - // - // as well as - // ... - Optional dummy_val; - public: - Multiple contexts; - Optional combine; - - UniquenessConstraint() - : contexts("context"), - combine("combine", LLNotification::REPLACE_WITH_NEW), - dummy_val("") - {} - }; - - // Templates are used to define common form types, such as OK/Cancel dialogs, etc. - - struct Template : public LLInitParam::Block