From a53d111cfab7b030a4bd603ba163b7cb66f4a35d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 21 Sep 2023 23:51:03 +0300 Subject: SL-15039 Prune unused preferences #2 List of removed preferences (usused per statistics): BottomPanelNew BrowserHomePage BlockSomeAvatarAppearanceVisualParams ButtonHPad ButtonHeight ButtonHeightSmall CacheNumberOfRegionsForObjects ChatBarStealsFocus ChatLoadGroupTimeout ChatPersistTime ChatShowTimestamps ContextConeInAlpha ContextConeOutAlpha ContextConeFadeTime ConversationHistoryPageSize ContactsTornOff CurlMaximumNumberOfHandles CurlUseMultipleThreads CustomServer DebugShowPrivateMem --- indra/llui/llbutton.cpp | 12 ++++++------ indra/llui/llfloater.h | 4 ++++ indra/llui/llmenugl.cpp | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 3354cb2db3..fe9908a475 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -58,10 +58,10 @@ static LLDefaultChildRegistry::Register r("button"); template class LLButton* LLView::getChild( const std::string& name, BOOL recurse) const; -// globals loaded from settings.xml -S32 LLBUTTON_H_PAD = 0; -S32 BTN_HEIGHT_SMALL= 0; -S32 BTN_HEIGHT = 0; +// globals +S32 LLBUTTON_H_PAD = 4; +S32 BTN_HEIGHT_SMALL= 23; +S32 BTN_HEIGHT = 23; LLButton::Params::Params() : label_selected("label_selected"), // requires is_toggle true @@ -91,8 +91,8 @@ LLButton::Params::Params() 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_right("pad_right", LLBUTTON_H_PAD), + pad_left("pad_left", LLBUTTON_H_PAD), pad_bottom("pad_bottom"), click_callback("click_callback"), mouse_down_callback("mouse_down_callback"), diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 668cd208a9..7840611ce1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -61,6 +61,10 @@ const BOOL CLOSE_NO = FALSE; const BOOL ADJUST_VERTICAL_YES = TRUE; const BOOL ADJUST_VERTICAL_NO = FALSE; +const F32 CONTEXT_CONE_IN_ALPHA = 0.f; +const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +const F32 CONTEXT_CONE_FADE_TIME = .08f; + namespace LLFloaterEnums { enum EOpenPositioning diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 16c27da56a..32c5ceb20e 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -66,8 +66,8 @@ LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL; view_listener_t::listener_map_t view_listener_t::sListeners; -S32 MENU_BAR_HEIGHT = 0; -S32 MENU_BAR_WIDTH = 0; +S32 MENU_BAR_HEIGHT = 18; +S32 MENU_BAR_WIDTH = 410; ///============================================================================ /// Local function declarations, constants, enums, and typedefs -- cgit v1.2.3 From 145a5ffe7f57ec87b0604c2e06104a4eb3cb8644 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 22 Sep 2023 01:01:42 +0300 Subject: SL-15039 Prune unused preferences #3 DebugInventoryFilters DebugShowXUINames DebugSlshareLogTag DebugStat**** DefaultBlankNormalTexture DefaultObjectNormalTexture DefaultObjectSpecularTexture DefaultUploadCost DisplayAvatarAgentTarget DisplayChat DisplayDebug DisplayDebugConsole DisplayIM DisplayLinden DisplayRegion DragAndDropToolTipDelay DragAndDropDistanceThreshold DropShadowButton DropShadowFloater DropShadowSlider DropShadowTooltip UIImgWhiteUUID UseEnvironmentFromRegion UseDayCycle WaterPresetName SkyPresetName DayCycleName DestinationGuideHintTimeout SidePanelHintTimeout DisablePrecacheDelayAfterTeleporting --- indra/llui/llbutton.cpp | 1 + indra/llui/llbutton.h | 2 +- indra/llui/llcombobox.cpp | 15 +++++---------- indra/llui/llfloater.cpp | 3 +-- indra/llui/llfolderviewitem.cpp | 4 +--- indra/llui/llmenugl.cpp | 3 +-- indra/llui/llmodaldialog.cpp | 3 +-- indra/llui/lltoolbar.cpp | 3 +-- indra/llui/llui.h | 2 +- indra/llui/lluictrl.h | 1 + 10 files changed, 14 insertions(+), 23 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index fe9908a475..061c24db50 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -62,6 +62,7 @@ template class LLButton* LLView::getChild( S32 LLBUTTON_H_PAD = 4; S32 BTN_HEIGHT_SMALL= 23; S32 BTN_HEIGHT = 23; +S32 BTN_DROP_SHADOW = 2; LLButton::Params::Params() : label_selected("label_selected"), // requires is_toggle true diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index ccd31e90c0..ab64440c19 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -43,10 +43,10 @@ // // 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 BTN_DROP_SHADOW; // // Helpful functions diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 9ca05a16f3..7a925c0659 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -482,8 +482,6 @@ void LLComboBox::onFocusLost() void LLComboBox::setButtonVisible(BOOL visible) { - static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); - mButton->setVisible(visible); if (mTextEntry) { @@ -491,7 +489,7 @@ void LLComboBox::setButtonVisible(BOOL visible) if (visible) { S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -530,19 +528,18 @@ 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; + S32 shadow_size = BTN_DROP_SHADOW; 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; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; // clear label on button std::string cur_label = mButton->getLabelSelected(); LLLineEditor::Params params = p.combo_editor; @@ -1081,13 +1078,11 @@ void LLComboBox::onSetHighlight() const void LLComboBox::imageLoaded() { - static LLUICachedControl drop_shadow_button("DropShadowButton", 0); - if (mAllowTextEntry) { LLRect rect = getLocalRect(); S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = drop_shadow_button; + S32 shadow_size = BTN_DROP_SHADOW; mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); if (mButton->getVisible()) @@ -1096,7 +1091,7 @@ void LLComboBox::imageLoaded() if (mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW; mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); } } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 2303cd24b7..d08084cdf5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1961,10 +1961,9 @@ void LLFloater::drawShadow(LLPanel* panel) 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; + F32 shadow_offset = (F32)DROP_SHADOW_FLOATER; if (!panel->isBackgroundOpaque()) { diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5319af1b60..ed0e705fd5 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -596,15 +596,13 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) 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() + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD && root->getAllowDrag() && root->getCurSelectedItem() && root->startDrag()) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 32c5ceb20e..fe25ac1647 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3220,10 +3220,9 @@ void LLMenuGL::draw( void ) } 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 ); + color_drop_shadow, DROP_SHADOW_FLOATER); } if( mBgVisible ) diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 3e5978eb59..22d98469ec 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -284,10 +284,9 @@ BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask ) void LLModalDialog::draw() { 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); + shadow_color, DROP_SHADOW_FLOATER); LLFloater::draw(); diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 2707f7a15c..58ecf3e603 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -1134,8 +1134,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask) BOOL handled = FALSE; S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY); - static LLCachedControl drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3); - if (mouse_distance_squared > drag_threshold * drag_threshold + if (mouse_distance_squared > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD && hasMouseCapture() && mStartDragItemCallback && mHandleDragItemCallback) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 30dbd7248f..868e1d21a6 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -53,7 +53,7 @@ class LLWindow; class LLView; class LLHelp; - +const S32 DRAG_N_DROP_DISTANCE_THRESHOLD = 3; // this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim) enum EDragAndDropType { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 67dd24341c..424b4879ce 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -41,6 +41,7 @@ const BOOL TAKE_FOCUS_YES = TRUE; const BOOL TAKE_FOCUS_NO = FALSE; +const S32 DROP_SHADOW_FLOATER = 5; class LLUICtrl : public LLView, public boost::signals2::trackable -- cgit v1.2.3 From d0d05ddddfe6736b50e589a20d4d6ea457ad9b32 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 22 Sep 2023 23:38:20 +0300 Subject: SL-15039 Prune unused preferences #4 --- indra/llui/llfolderview.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 62c311f522..ed49c0dcfd 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -333,9 +333,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) void LLFolderView::filter( LLFolderViewFilter& filter ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - static LLCachedControl time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); - static LLCachedControl time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); - filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100)); + const S32 TIME_VISIBLE = 10; // in milliseconds + const S32 TIME_INVISIBLE = 1; + filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100)); // Note: we filter the model, not the view getViewModelItem()->filter(filter); -- cgit v1.2.3 From ad6dceb1c3e9024c93be6c7212b4d3687ca13e0d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 27 Sep 2023 23:50:46 +0300 Subject: SL-15039 Fixed missed filter time variable --- indra/llui/llfolderviewmodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 93122503d1..394581d6d7 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,8 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - static LLCachedControl max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); - getFilter().resetTime(llclamp(max_time(), 1, 100)); + const S32 MAX_FILTER_TIME = 10; + getFilter().resetTime(MAX_FILTER_TIME); mFolderView->getViewModelItem()->filter(getFilter()); } -- cgit v1.2.3 From 683e96ed61692d26b3eba2b08fe9978de998cb41 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 9 Oct 2023 12:35:53 +0300 Subject: SL-20380 Add group notices button as hover button on Groups floater --- indra/llui/llaccordionctrl.cpp | 17 +++++++++++++++++ indra/llui/llaccordionctrl.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 809d72208f..d0146910b6 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -936,3 +936,20 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl expanded_tab_height /= num_expanded; return expanded_tab_height; } + +void LLAccordionCtrl::collapseAllTabs() +{ + if (mAccordionTabs.size() > 0) + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab *tab = mAccordionTabs[i]; + + if (tab->getDisplayChildren()) + { + tab->setDisplayChildren(false); + } + } + arrange(); + } +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 2828254472..cc49ac8086 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -122,6 +122,8 @@ public: void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } void sort(); + void collapseAllTabs(); + /** * Sets filter substring as a search_term for help text when there are no any visible tabs. */ -- cgit v1.2.3 From af17d4ca3874bc88816ed53f7c8888e0e0609ab5 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 10 Oct 2023 23:18:41 +0200 Subject: SL-20288 Lags in Appearance floater (code format in LLAccordionCtrl) --- indra/llui/llaccordionctrl.cpp | 330 ++++++++++++++++----------------- indra/llui/llaccordionctrl.h | 2 +- indra/llui/llaccordionctrltab.cpp | 371 ++++++++++++++++++++------------------ indra/llui/llaccordionctrltab.h | 2 +- indra/llui/llflatlistview.cpp | 52 +++--- 5 files changed, 387 insertions(+), 370 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index d0146910b6..e18c40e7c3 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -60,7 +60,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) initNoTabsWidget(params.no_matched_tabs_text); mSingleExpansion = params.single_expansion; - if(mFitParent && !mSingleExpansion) + if (mFitParent && !mSingleExpansion) { LL_INFOS() << "fit_parent works best when combined with single_expansion" << LL_ENDL; } @@ -102,14 +102,13 @@ void LLAccordionCtrl::draw() LLPanel::draw(); } - //--------------------------------------------------------------------------------- BOOL LLAccordionCtrl::postBuild() { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); LLRect scroll_rect; - scroll_rect.setOriginAndSize( + scroll_rect.setOriginAndSize( getRect().getWidth() - scrollbar_size, 1, scrollbar_size, @@ -126,39 +125,42 @@ BOOL LLAccordionCtrl::postBuild() 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 = 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(); + for (child_list_const_iter_t it = getChildList()->begin(); getChildList()->end() != it; ++it) { LLAccordionCtrlTab* accordion_tab = dynamic_cast(*it); - if(accordion_tab == NULL) + if (accordion_tab == NULL) continue; - if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end()) + 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) + for (std::vector::reverse_iterator it = accordion_tabs.rbegin(); + it < accordion_tabs.rend(); ++it) + { addCollapsibleCtrl(*it); + } - arrange (); + arrange(); - if(mSingleExpansion) + if (mSingleExpansion) { - if(!mAccordionTabs[0]->getDisplayChildren()) + if (!mAccordionTabs[0]->getDisplayChildren()) mAccordionTabs[0]->setDisplayChildren(true); - for(size_t i=1;igetDisplayChildren()) + if (mAccordionTabs[i]->getDisplayChildren()) mAccordionTabs[i]->setDisplayChildren(false); } } @@ -205,23 +207,22 @@ BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) //--------------------------------------------------------------------------------- void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta) { - for(size_t i = panel_num; i < mAccordionTabs.size(); i++ ) + for (size_t i = panel_num; i < mAccordionTabs.size(); ++i) { ctrlShiftVertical(mAccordionTabs[i],delta); } } - //--------------------------------------------------------------------------------- void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) { - if(mSingleExpansion) + if (mSingleExpansion) { - for(size_t i=0;igetDisplayChildren()) + if (mAccordionTabs[i]->getDisplayChildren()) mAccordionTabs[i]->setDisplayChildren(false); } @@ -232,64 +233,63 @@ void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height) { calcRecuiredHeight(); - if(getRecuiredHeight() > height ) - showScrollbar(width,height); + if (getRecuiredHeight() > height) + showScrollbar(width, height); else - hideScrollbar(width,height); + hideScrollbar(width, height); } -void LLAccordionCtrl::showScrollbar(S32 width, S32 height) +void LLAccordionCtrl::showScrollbar(S32 width, S32 height) { bool was_visible = mScrollbar->getVisible(); - mScrollbar->setVisible(true); + 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-2*PARENT_BORDER_MARGIN); + , 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->setDocParams(mInnerRect.getHeight(), mScrollbar->getDocPos()); - if(was_visible) + if (was_visible) { S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); mScrollbar->setDocPos(scroll_pos); } } -void LLAccordionCtrl::hideScrollbar( S32 width, S32 height ) +void LLAccordionCtrl::hideScrollbar(S32 width, S32 height) { - if(mScrollbar->getVisible() == false) + if (mScrollbar->getVisible() == FALSE) return; - mScrollbar->setVisible(false); + mScrollbar->setVisible(FALSE); static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); S32 panel_width = width - 2*BORDER_MARGIN; - //reshape all accordeons and shift all draggers - for(size_t i=0;igetRect(); - ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight()); + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_rect.mTop, panel_width, panel_rect.getHeight()); } mScrollbar->setDocPos(0); - if(mAccordionTabs.size()>0) + if (!mAccordionTabs.empty()) { - S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; - shiftAccordionTabs(0,diff); + shiftAccordionTabs(0, diff); } } - //--------------------------------------------------------------------------------- S32 LLAccordionCtrl::calcRecuiredHeight() { @@ -305,7 +305,7 @@ S32 LLAccordionCtrl::calcRecuiredHeight() } } - mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); + mInnerRect.setLeftTopAndSize(0, rec_height + BORDER_MARGIN * 2, getRect().getWidth(), rec_height + BORDER_MARGIN); return mInnerRect.getHeight(); } @@ -313,7 +313,7 @@ S32 LLAccordionCtrl::calcRecuiredHeight() //--------------------------------------------------------------------------------- void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) { - if(!panel) + if (!panel) return; LLRect panel_rect = panel->getRect(); panel_rect.setLeftTopAndSize( left, top, width, height); @@ -321,9 +321,9 @@ void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S3 panel->setRect(panel_rect); } -void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta) +void LLAccordionCtrl::ctrlShiftVertical(LLView* panel, S32 delta) { - if(!panel) + if (!panel) return; panel->translate(0,delta); } @@ -333,9 +333,9 @@ void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta) void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) { LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); - if(!accordion_tab) + if (!accordion_tab) return; - if(std::find(beginChild(), endChild(), accordion_tab) == endChild()) + if (std::find(beginChild(), endChild(), accordion_tab) == endChild()) addChild(accordion_tab); mAccordionTabs.push_back(accordion_tab); @@ -369,7 +369,7 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) } } -void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) +void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) { LLTextBox::Params tp = tb_params; tp.rect(getLocalRect()); @@ -377,39 +377,39 @@ void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) mNoVisibleTabsHelpText = LLUICtrlFactory::create(tp, this); } -void LLAccordionCtrl::updateNoTabsHelpTextVisibility() +void LLAccordionCtrl::updateNoTabsHelpTextVisibility() { bool visible_exists = false; std::vector::const_iterator it = mAccordionTabs.begin(); const std::vector::const_iterator it_end = mAccordionTabs.end(); - for (; it != it_end; ++it) + while (it < it_end) { - if ((*it)->getVisible()) + if ((*(it++))->getVisible()) { visible_exists = true; break; } } - mNoVisibleTabsHelpText->setVisible(!visible_exists); + mNoVisibleTabsHelpText->setVisible(visible_exists ? FALSE : TRUE); } -void LLAccordionCtrl::arrangeSinge() +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; // Top coordinate of the first panel + 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[i]); - if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs continue; - if(!accordion_tab->isExpanded() ) + if (!accordion_tab->isExpanded() ) { collapsed_height+=mAccordionTabs[i]->getRect().getHeight(); } @@ -417,28 +417,28 @@ void LLAccordionCtrl::arrangeSinge() S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height; - for(size_t i=0;i(mAccordionTabs[i]); - if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs continue; - if(!accordion_tab->isExpanded() ) + if (!accordion_tab->isExpanded() ) { panel_height = accordion_tab->getRect().getHeight(); } else { - if(mFitParent) + if (mFitParent) { panel_height = expanded_height; } else { - if(accordion_tab->getAccordionView()) + if (accordion_tab->getAccordionView()) { panel_height = accordion_tab->getAccordionView()->getRect().getHeight() + - accordion_tab->getHeaderHeight() + 2*BORDER_MARGIN; + accordion_tab->getHeaderHeight() + BORDER_MARGIN * 2; } else { @@ -451,67 +451,67 @@ void LLAccordionCtrl::arrangeSinge() 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(); + panel_top -= mAccordionTabs[i]->getRect().getHeight(); } show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); updateLayout(getRect().getWidth(), getRect().getHeight()); } -void LLAccordionCtrl::arrangeMultiple() +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; // Top coordinate of the first panel + 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++ ) + 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 + if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs continue; - if(!accordion_tab->isExpanded() ) + if (!accordion_tab->isExpanded() ) { ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); - panel_top-=mAccordionTabs[i]->getRect().getHeight(); + panel_top -= mAccordionTabs[i]->getRect().getHeight(); } else { S32 panel_height = accordion_tab->getRect().getHeight(); - if(mFitParent) + if (mFitParent) { - // all expanded tabs will have equal height + // 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. + // 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) + if (optimal_height < panel_height) { panel_height = optimal_height; } // minimum tab height is equal to header height - if(mAccordionTabs[i]->getHeaderHeight() > panel_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; + panel_top -= panel_height; } } - show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); - updateLayout(getRect().getWidth(),getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); } @@ -519,70 +519,67 @@ void LLAccordionCtrl::arrange() { updateNoTabsHelpTextVisibility(); - if( mAccordionTabs.size() == 0) + if (mAccordionTabs.empty()) { - //We do not arrange if we do not have what should be arranged + // Nothing to arrange return; } - - if(mAccordionTabs.size() == 1) + if (mAccordionTabs.size() == 1) { - S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel - S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + 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() - 2*BORDER_MARGIN; - + 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); + + ctrlSetLeftTopAndSize(accordion_tab, panel_rect.mLeft, panel_top, panel_width, panel_height); - show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); return; - } - if(mSingleExpansion) - arrangeSinge (); + if (mSingleExpansion) + arrangeSingle(); else - arrangeMultiple (); + arrangeMultiple(); } //--------------------------------------------------------------------------------- -BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +BOOL LLAccordionCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if(LLPanel::handleScrollWheel(x,y,clicks)) + if (LLPanel::handleScrollWheel(x, y, clicks)) return TRUE; - if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + if (mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) return TRUE; - return false; - + return FALSE; } -BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask) +BOOL LLAccordionCtrl::handleKeyHere(KEY key, MASK mask) { - if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) + if (mScrollbar->getVisible() && mScrollbar->handleKeyHere(key, mask)) return TRUE; - return LLPanel::handleKeyHere(key,mask); + 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 LLAccordionCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, + 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); - if( !handled ) + if (!handled) { handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL; @@ -590,14 +587,14 @@ BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask, return TRUE; } -BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y) +BOOL LLAccordionCtrl::autoScroll(S32 x, S32 y) { static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); bool scrolling = false; - if( mScrollbar->getVisible() ) + if (mScrollbar->getVisible()) { - LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 ); + LLRect rect_local(0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0); LLRect screen_local_extents; // clip rect against root view @@ -610,51 +607,52 @@ BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y) 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()) ) + if (bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax())) { - mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed ); + 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) ) + if (top_scroll_rect.pointInRect(x, y) && (mScrollbar->getDocPos() > 0)) { - mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed ); + mScrollbar->setDocPos(mScrollbar->getDocPos() - auto_scroll_speed); mAutoScrolling = true; scrolling = true; } } - return scrolling; + + return scrolling ? TRUE : FALSE; } -void LLAccordionCtrl::updateLayout (S32 width, S32 height) +void LLAccordionCtrl::updateLayout(S32 width, S32 height) { S32 panel_top = height - BORDER_MARGIN ; - if(mScrollbar->getVisible()) - panel_top+=mScrollbar->getDocPos(); + if (mScrollbar->getVisible()) + panel_top += mScrollbar->getDocPos(); - S32 panel_width = width - 2*BORDER_MARGIN; + S32 panel_width = width - BORDER_MARGIN * 2; static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - if(mScrollbar->getVisible()) - panel_width-=scrollbar_size; + if (mScrollbar->getVisible()) + panel_width -= scrollbar_size; - //set sizes for first panels and dragbars - for(size_t i=0;igetVisible()) + 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(); + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_top, panel_width, panel_rect.getHeight()); + panel_top -= panel_rect.getHeight(); } } -void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) +void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) { - updateLayout(getRect().getWidth(),getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); } // virtual @@ -687,42 +685,43 @@ void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl) LLUICtrl::onUpdateScrollToChild(cntrl); } -void LLAccordionCtrl::onOpen (const LLSD& key) +void LLAccordionCtrl::onOpen(const LLSD& key) { - for(size_t i=0;i(mAccordionTabs[i]); LLPanel* panel = dynamic_cast(accordion_tab->getAccordionView()); - if(panel!=NULL) + if (panel != NULL) { panel->onOpen(key); } } } + S32 LLAccordionCtrl::notifyParent(const LLSD& info) { - if(info.has("action")) + if (info.has("action")) { std::string str_action = info["action"]; - if(str_action == "size_changes") + if (str_action == "size_changes") { // arrange(); return 1; } - else if(str_action == "select_next") + if (str_action == "select_next") { - for(size_t i=0;i(mAccordionTabs[i]); - if(accordion_tab->hasFocus()) + if (accordion_tab->hasFocus()) { - while(++igetVisible()) + if (mAccordionTabs[i]->getVisible()) break; } - if(i(mAccordionTabs[i]); accordion_tab->notify(LLSD().with("action","select_first")); @@ -733,17 +732,17 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return 0; } - else if(str_action == "select_prev") + if (str_action == "select_prev") { - for(size_t i=0;i(mAccordionTabs[i]); - if(accordion_tab->hasFocus() && i>0) + if (accordion_tab->hasFocus() && i > 0) { bool prev_visible_tab_found = false; - while(i>0) + while (i > 0) { - if(mAccordionTabs[--i]->getVisible()) + if (mAccordionTabs[--i]->getVisible()) { prev_visible_tab_found = true; break; @@ -761,12 +760,12 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return 0; } - else if(str_action == "select_current") + if (str_action == "select_current") { - for(size_t i=0;ihasFocus()) + if (mAccordionTabs[i]->hasFocus()) { if (mAccordionTabs[i] != mSelectedTab) { @@ -783,7 +782,7 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return 0; } - else if(str_action == "deselect_current") + if (str_action == "deselect_current") { // Reset selection to the currently selected tab. if (mSelectedTab) @@ -802,9 +801,9 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) screenRectToLocal(screen_rc, &local_rc); // Translate to parent coordinatess to check if we are in visible rectangle - local_rc.translate( getRect().mLeft, getRect().mBottom ); + local_rc.translate(getRect().mLeft, getRect().mBottom); - if ( !getRect().contains (local_rc) ) + if (!getRect().contains (local_rc)) { // Back to local coords and calculate position for scroller S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; @@ -814,7 +813,7 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) bottom, // min vertical scroll top); // max vertical scroll - mScrollbar->setDocPos( scroll_pos ); + mScrollbar->setDocPos(scroll_pos); } return 1; } @@ -834,15 +833,16 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return LLPanel::notifyParent(info); } -void LLAccordionCtrl::reset () + +void LLAccordionCtrl::reset() { - if(mScrollbar) + if (mScrollbar) mScrollbar->setDocPos(0); } void LLAccordionCtrl::expandDefaultTab() { - if (mAccordionTabs.size() > 0) + if (!mAccordionTabs.empty()) { LLAccordionCtrlTab* tab = mAccordionTabs.front(); @@ -877,7 +877,7 @@ void LLAccordionCtrl::sort() arrange(); } -void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) +void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) { LLStringUtil::format_map_t args; args["[SEARCH_TERM]"] = LLURI::escape(filter_string); @@ -907,7 +907,7 @@ const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) { - if(tab_index < 0) + if (tab_index < 0) { return available_height; } @@ -915,9 +915,9 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl S32 collapsed_tabs_height = 0; S32 num_expanded = 0; - for(size_t n = tab_index; n < mAccordionTabs.size(); ++n) + for (size_t n = tab_index; n < mAccordionTabs.size(); ++n) { - if(!mAccordionTabs[n]->isExpanded()) + if (!mAccordionTabs[n]->isExpanded()) { collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); } @@ -927,7 +927,7 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl } } - if(0 == num_expanded) + if (0 == num_expanded) { return available_height; } diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index cc49ac8086..f226d38bed 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -146,7 +146,7 @@ private: void initNoTabsWidget(const LLTextBox::Params& tb_params); void updateNoTabsHelpTextVisibility(); - void arrangeSinge(); + void arrangeSingle(); void arrangeMultiple(); // Calc Splitter's height that is necessary to display all child content diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 04485c6262..20da568746 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -69,13 +69,13 @@ public: virtual BOOL postBuild(); std::string getTitle(); - void setTitle(const std::string& title, const std::string& hl); + 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); @@ -85,8 +85,8 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); -private: +private: LLTextBox* mHeaderTextbox; // Overlay images (arrows) @@ -102,7 +102,7 @@ private: LLPointer mImageHeaderFocused; // style saved when applying it in setTitleFontStyle - LLStyle::Params mStyleParams; + LLStyle::Params mStyleParams; LLUIColor mHeaderBGColor; @@ -157,19 +157,17 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle() { - if(mHeaderTextbox) + if (mHeaderTextbox) { return mHeaderTextbox->getText(); } - else - { - return LLStringUtil::null; - } + + return LLStringUtil::null; } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl) { - if(mHeaderTextbox) + if (mHeaderTextbox) { LLTextUtil::textboxSetHighlightedVal( mHeaderTextbox, @@ -192,7 +190,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleColor(LLUIColor color) { - if(mHeaderTextbox) + if (mHeaderTextbox) { mHeaderTextbox->setColor(color); } @@ -204,11 +202,11 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() S32 height = getRect().getHeight(); F32 alpha = getCurrentTransparency(); - gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get() % alpha,true); + 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()); + 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, @@ -218,23 +216,22 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() /*&& !(collapsible && !expanded)*/ // WHY?? ) { - mImageHeaderFocused->draw(0,0,width,height); + mImageHeaderFocused->draw(0, 0, width, height); } else { - mImageHeader->draw(0,0,width,height); + mImageHeader->draw(0, 0, width, height); } - if(mNeedsHighlight) + if (mNeedsHighlight) { - mImageHeaderOver->draw(0,0,width,height); + mImageHeaderOver->draw(0, 0, width, height); } - - if(collapsible) + if (collapsible) { LLPointer overlay_image; - if(expanded) + if (expanded) { overlay_image = mImageExpanded; } @@ -242,8 +239,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() { overlay_image = mImageCollapsed; } - overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, - (height - overlay_image->getHeight()) / 2); + overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, (height - overlay_image->getHeight()) / 2); } LLUICtrl::draw(); @@ -253,7 +249,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height { S32 header_height = mHeaderTextbox->getTextPixelHeight(); - LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2); + LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET, (height + header_height) / 2, width, (height - header_height) / 2); mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); mHeaderTextbox->setRect(textboxRect); @@ -272,20 +268,24 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MA 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(); } + BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) + 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); } + BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -295,7 +295,7 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 { LLAccordionCtrlTab* parent = dynamic_cast(getParent()); - if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() ) + if (parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose()) { if (mAutoOpenTimer.getStarted()) { @@ -307,12 +307,15 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 } } 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) @@ -384,41 +387,39 @@ LLAccordionCtrlTab::~LLAccordionCtrlTab() { } - void LLAccordionCtrlTab::setDisplayChildren(bool display) { mDisplayChildren = display; LLRect rect = getRect(); - rect.mBottom = rect.mTop - (getDisplayChildren() ? - mExpandedHeight : HEADER_HEIGHT); + rect.mBottom = rect.mTop - (getDisplayChildren() ? mExpandedHeight : HEADER_HEIGHT); setRect(rect); - if(mContainerPanel) + if (mContainerPanel) + { mContainerPanel->setVisible(getDisplayChildren()); + } - if(mDisplayChildren) + if (mDisplayChildren) { adjustContainerPanel(); } else { - if(mScrollbar) - mScrollbar->setVisible(false); + if (mScrollbar) + mScrollbar->setVisible(FALSE); } - } void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { LLRect headerRect; - headerRect.setLeftTopAndSize( - 0,height,width,HEADER_HEIGHT); + headerRect.setLeftTopAndSize(0, height, width, HEADER_HEIGHT); mHeader->setRect(headerRect); mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); - if(!mDisplayChildren) + if (!mDisplayChildren) return; LLRect childRect; @@ -426,7 +427,7 @@ void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent childRect.setLeftTopAndSize( getPaddingLeft(), height - getHeaderHeight() - getPaddingTop(), - width - getPaddingLeft() - getPaddingRight(), + width - getPaddingLeft() - getPaddingRight(), height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() ); adjustContainerPanel(childRect); @@ -434,7 +435,7 @@ void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent void LLAccordionCtrlTab::changeOpenClose(bool is_open) { - if(is_open) + if (is_open) mExpandedHeight = getRect().getHeight(); setDisplayChildren(!is_open); @@ -483,14 +484,14 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) { - if(mCollapsible && mHeaderVisible && mCanOpenClose) + if (mCollapsible && mHeaderVisible && mCanOpenClose) { - if(y >= (getRect().getHeight() - HEADER_HEIGHT) ) + if (y >= (getRect().getHeight() - HEADER_HEIGHT)) { mHeader->setFocus(true); changeOpenClose(getDisplayChildren()); - //reset stored state + // Reset stored state mWasStateStored = false; return TRUE; } @@ -510,7 +511,7 @@ boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback( bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) { - if(DD_HEADER_NAME != child->getName()) + if (DD_HEADER_NAME != child->getName()) { reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); mExpandedHeight = getRect().getHeight(); @@ -518,12 +519,12 @@ bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) bool res = LLUICtrl::addChild(child, tab_group); - if(DD_HEADER_NAME != child->getName()) + if (DD_HEADER_NAME != child->getName()) { - if(!mCollapsible) + if (!mCollapsible) setDisplayChildren(true); else - setDisplayChildren(getDisplayChildren()); + setDisplayChildren(getDisplayChildren()); } if (!mContainerPanel) @@ -534,7 +535,7 @@ bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) void LLAccordionCtrlTab::setAccordionView(LLView* panel) { - addChild(panel,0); + addChild(panel, 0); } std::string LLAccordionCtrlTab::getTitle() const @@ -543,10 +544,8 @@ std::string LLAccordionCtrlTab::getTitle() const { return mHeader->getTitle(); } - else - { - return LLStringUtil::null; - } + + return LLStringUtil::null; } void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) @@ -579,6 +578,7 @@ boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const f { return mHeader->setFocusReceivedCallback(cb); } + return boost::signals2::connection(); } @@ -588,6 +588,7 @@ boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus { return mHeader->setFocusLostCallback(cb); } + return boost::signals2::connection(); } @@ -601,59 +602,65 @@ void LLAccordionCtrlTab::setSelected(bool is_selected) LLView* LLAccordionCtrlTab::findContainerView() { - for(child_list_const_iter_t it = getChildList()->begin(); - getChildList()->end() != it; ++it) + 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()) - continue; - if(!child->getVisible()) - continue; - return child; + 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")); + } } void LLAccordionCtrlTab::deselectOnFocusLost() { - if(getParent()) // A parent may not be set if tabs are added dynamically. + 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) +void LLAccordionCtrlTab::setHeaderVisible(bool value) { - if(mHeaderVisible == value) + if (mHeaderVisible == value) return; + mHeaderVisible = value; - if(mHeader) - mHeader->setVisible(value); + + if (mHeader) + { + mHeader->setVisible(value ? TRUE : FALSE); + } + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); }; //virtual BOOL LLAccordionCtrlTab::postBuild() { - if(mHeader) + if (mHeader) + { mHeader->setVisible(mHeaderVisible); - - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + } + + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); LLRect scroll_rect; - scroll_rect.setOriginAndSize( + scroll_rect.setOriginAndSize( getRect().getWidth() - scrollbar_size, 1, scrollbar_size, @@ -661,7 +668,7 @@ BOOL LLAccordionCtrlTab::postBuild() mContainerPanel = findContainerView(); - if(!mFitPanel) + if (!mFitPanel) { LLScrollbar::Params sbparams; sbparams.name("scrollable vertical"); @@ -674,9 +681,8 @@ BOOL LLAccordionCtrlTab::postBuild() 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 = LLUICtrlFactory::create(sbparams); + LLView::addChild(mScrollbar); mScrollbar->setFollowsRight(); mScrollbar->setFollowsTop(); mScrollbar->setFollowsBottom(); @@ -684,44 +690,48 @@ BOOL LLAccordionCtrlTab::postBuild() mScrollbar->setVisible(false); } - if(mContainerPanel) + if (mContainerPanel) + { mContainerPanel->setVisible(mDisplayChildren); + } return LLUICtrl::postBuild(); } -bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) + +bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) { - if(info.has("action")) + if (info.has("action")) { std::string str_action = info["action"]; - if(str_action == "store_state") + if (str_action == "store_state") { storeOpenCloseState(); return true; } - if(str_action == "restore_state") + + if (str_action == "restore_state") { restoreOpenCloseState(); return true; } } + return LLUICtrl::notifyChildren(info); } S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) { - if(info.has("action")) + if (info.has("action")) { std::string str_action = info["action"]; - if(str_action == "size_changes") + if (str_action == "size_changes") { - // S32 height = info["height"]; - height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); + height = llmax(height, 10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); mExpandedHeight = height; - if(isExpanded() && !mSkipChangesOnNotifyParent) + if (isExpanded() && !mSkipChangesOnNotifyParent) { LLRect panel_rect = getRect(); panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); @@ -729,12 +739,13 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) setRect(panel_rect); } - //LLAccordionCtrl should rearrange accordion tab if one of accordion change its size + // 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; } - else if(str_action == "select_prev") + + if (str_action == "select_prev") { showAndFocusHeader(); return 1; @@ -772,78 +783,85 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) S32 LLAccordionCtrlTab::notify(const LLSD& info) { - if(info.has("action")) + if (info.has("action")) { std::string str_action = info["action"]; - if(str_action == "select_first") + if (str_action == "select_first") { showAndFocusHeader(); return 1; } - else if( str_action == "select_last" ) + + if (str_action == "select_last") { - if(getDisplayChildren() == false) + if (!getDisplayChildren()) { showAndFocusHeader(); } else { LLView* view = getAccordionView(); - if(view) - view->notify(LLSD().with("action","select_last")); + 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() ) + if (!mHeader->hasFocus()) return LLUICtrl::handleKey(key, mask, called_from_parent); - if ( (key == KEY_RETURN )&& mask == MASK_NONE) + if ((key == KEY_RETURN) && mask == MASK_NONE) { changeOpenClose(getDisplayChildren()); return TRUE; } - if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE) + if ((key == KEY_ADD || key == KEY_RIGHT) && mask == MASK_NONE) { - if(getDisplayChildren() == false) + if (!getDisplayChildren()) { changeOpenClose(getDisplayChildren()); return TRUE; } } - if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE) + + if ((key == KEY_SUBTRACT || key == KEY_LEFT) && mask == MASK_NONE) { - if(getDisplayChildren() == true) + if (getDisplayChildren()) { changeOpenClose(getDisplayChildren()); return TRUE; } } - if ( key == KEY_DOWN && mask == MASK_NONE) + if (key == KEY_DOWN && mask == MASK_NONE) { - //if collapsed go to the next accordion - if(getDisplayChildren() == false) - //we processing notifyParent so let call parent directly - getParent()->notifyParent(LLSD().with("action","select_next")); + // 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")); + getAccordionView()->notify(LLSD().with("action", "select_first")); } return TRUE; } - if ( key == KEY_UP && mask == MASK_NONE) + if (key == KEY_UP && mask == MASK_NONE) { - //go to the previous accordion + // go to the previous accordion - //we processing notifyParent so let call parent directly - getParent()->notifyParent(LLSD().with("action","select_prev")); + // we're processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action", "select_prev")); return TRUE; } @@ -869,28 +887,29 @@ void LLAccordionCtrlTab::showAndFocusHeader() // 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())); + getParent()->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); } -void LLAccordionCtrlTab::storeOpenCloseState() + +void LLAccordionCtrlTab::storeOpenCloseState() { - if(mWasStateStored) + if (mWasStateStored) return; mStoredOpenCloseState = getDisplayChildren(); mWasStateStored = true; } -void LLAccordionCtrlTab::restoreOpenCloseState() +void LLAccordionCtrlTab::restoreOpenCloseState() { - if(!mWasStateStored) + if (!mWasStateStored) return; - if(getDisplayChildren() != mStoredOpenCloseState) + if (getDisplayChildren() != mStoredOpenCloseState) { changeOpenClose(getDisplayChildren()); } mWasStateStored = false; } -void LLAccordionCtrlTab::adjustContainerPanel () +void LLAccordionCtrlTab::adjustContainerPanel() { S32 width = getRect().getWidth(); S32 height = getRect().getHeight(); @@ -907,83 +926,83 @@ void LLAccordionCtrlTab::adjustContainerPanel () void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect) { - if(!mContainerPanel) + if (!mContainerPanel) return; - if(!mFitPanel) + if (!mFitPanel) { show_hide_scrollbar(child_rect); updateLayout(child_rect); } else { - mContainerPanel->reshape(child_rect.getWidth(),child_rect.getHeight()); + mContainerPanel->reshape(child_rect.getWidth(), child_rect.getHeight()); mContainerPanel->setRect(child_rect); } } S32 LLAccordionCtrlTab::getChildViewHeight() { - if(!mContainerPanel) + if (!mContainerPanel) return 0; return mContainerPanel->getRect().getHeight(); } void LLAccordionCtrlTab::show_hide_scrollbar(const LLRect& child_rect) { - if(getChildViewHeight() > child_rect.getHeight() ) + if (getChildViewHeight() > child_rect.getHeight()) showScrollbar(child_rect); else hideScrollbar(child_rect); } + void LLAccordionCtrlTab::showScrollbar(const LLRect& child_rect) { - if(!mContainerPanel || !mScrollbar) + 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()-2*PARENT_BORDER_MARGIN); - } + 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()); + mScrollbar->setDocParams(orig_rect.getHeight(), mScrollbar->getDocPos()); - if(was_visible) + if (was_visible) { S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1); mScrollbar->setDocPos(scroll_pos); } - else//shrink child panel + else // Shrink child panel { updateLayout(child_rect); } - } -void LLAccordionCtrlTab::hideScrollbar( const LLRect& child_rect ) +void LLAccordionCtrlTab::hideScrollbar(const LLRect& child_rect) { - if(!mContainerPanel || !mScrollbar) + if (!mContainerPanel || !mScrollbar) return; - if(mScrollbar->getVisible() == false) + if (mScrollbar->getVisible() == FALSE) return; - mScrollbar->setVisible(false); + + mScrollbar->setVisible(FALSE); mScrollbar->setDocPos(0); //shrink child panel updateLayout(child_rect); } -void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*) +void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*) { LLRect child_rect; @@ -999,21 +1018,20 @@ void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*) updateLayout(child_rect); } -void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child) +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)) + 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(); } @@ -1022,64 +1040,67 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child) void LLAccordionCtrlTab::draw() { - if(mFitPanel) + if (mFitPanel) + { LLUICtrl::draw(); + } else { - LLRect root_rect = getRootView()->getRect(); - drawChild(root_rect,mHeader); - drawChild(root_rect,mScrollbar ); - { - LLRect child_rect; + LLRect root_rect(getRootView()->getRect()); + drawChild(root_rect, mHeader); + drawChild(root_rect, mScrollbar); - 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() ); + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); - LLLocalClipRect clip(child_rect); - drawChild(root_rect,mContainerPanel); - } + 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 ) +void LLAccordionCtrlTab::updateLayout(const LLRect& child_rect) { LLView* child = getAccordionView(); - if(!mContainerPanel) + 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() != false) + static LLUICachedControl scrollbar_size("UIScrollbarSize", 0); + if (mScrollbar && mScrollbar->getVisible()) { - panel_top+=mScrollbar->getDocPos(); - panel_width-=scrollbar_size; + panel_top += mScrollbar->getDocPos(); + panel_width -= scrollbar_size; } - //set sizes for first panels and dragbars + // Set sizes for first panels and dragbars LLRect panel_rect = child->getRect(); - ctrlSetLeftTopAndSize(mContainerPanel,child_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); + 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) + if (!panel) return; LLRect panel_rect = panel->getRect(); - panel_rect.setLeftTopAndSize( left, top, width, height); + 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) ) + if (y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT / 2)) { //inside tab header //fix for EXT-6619 @@ -1088,16 +1109,18 @@ BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask) } return LLUICtrl::handleToolTip(x, y, mask); } -BOOL LLAccordionCtrlTab::handleScrollWheel ( S32 x, S32 y, S32 clicks ) + +BOOL LLAccordionCtrlTab::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if( LLUICtrl::handleScrollWheel(x,y,clicks)) + if (LLUICtrl::handleScrollWheel(x, y, clicks)) { return TRUE; } - if( mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + + if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks)) { return TRUE; } + return FALSE; } - diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 2c72e8c036..896a34cac4 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -104,7 +104,7 @@ public: virtual void setDisplayChildren(bool display); // Returns expand/collapse state - virtual bool getDisplayChildren() const {return mDisplayChildren;}; + virtual bool getDisplayChildren() const { return mDisplayChildren; }; //set LLAccordionCtrlTab panel void setAccordionView(LLView* panel); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index b13e7389cc..460bd0945b 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1198,7 +1198,7 @@ void LLFlatListView::onFocusReceived() { if (size()) { - mSelectedItemsBorder->setVisible(TRUE); + mSelectedItemsBorder->setVisible(TRUE); } gEditMenuHandler = this; } @@ -1207,7 +1207,7 @@ void LLFlatListView::onFocusLost() { mSelectedItemsBorder->setVisible(FALSE); // Route menu back to the default - if( gEditMenuHandler == this ) + if (gEditMenuHandler == this) { gEditMenuHandler = NULL; } @@ -1216,16 +1216,16 @@ void LLFlatListView::onFocusLost() //virtual S32 LLFlatListView::notify(const LLSD& info) { - if(info.has("action")) + if (info.has("action")) { std::string str_action = info["action"]; - if(str_action == "select_first") + if (str_action == "select_first") { setFocus(true); selectFirstItem(); return 1; } - else if(str_action == "select_last") + else if (str_action == "select_last") { setFocus(true); selectLastItem(); @@ -1238,6 +1238,7 @@ S32 LLFlatListView::notify(const LLSD& info) notifyParentItemsRectChanged(); return 1; } + return 0; } @@ -1249,10 +1250,8 @@ void LLFlatListView::detachItems(std::vector& detached_items) detached_items.clear(); // Go through items and detach valid items, remove them from items panel // and add to detached_items. - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) { LLPanel* pItem = (*iter)->first; if (1 == pItem->notify(action)) @@ -1261,6 +1260,7 @@ void LLFlatListView::detachItems(std::vector& detached_items) mItemsPanel->removeChild(pItem); detached_items.push_back(pItem); } + iter++; } if (!detached_items.empty()) { @@ -1268,13 +1268,12 @@ void LLFlatListView::detachItems(std::vector& detached_items) if (detached_items.size() == mItemPairs.size()) { // This way will be faster if all items were disconnected - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) + 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. @@ -1287,16 +1286,14 @@ void LLFlatListView::detachItems(std::vector& detached_items) } else { - for (std::vector::const_iterator - detached_iter = detached_items.begin(), - detached_iter_end = detached_items.end(); - detached_iter != detached_iter_end; ++detached_iter) + 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; - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++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) @@ -1306,7 +1303,9 @@ void LLFlatListView::detachItems(std::vector& detached_items) delete item_pair; break; } + iter++; } + detached_iter++; } rearrangeItems(); } @@ -1322,7 +1321,6 @@ LLFlatListViewEx::Params::Params() : no_items_msg("no_items_msg") , no_filtered_items_msg("no_filtered_items_msg") { - } LLFlatListViewEx::LLFlatListViewEx(const Params& p) @@ -1332,7 +1330,6 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p) , mForceShowingUnmatchedItems(false) , mHasMatchedItems(false) { - } void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) @@ -1352,7 +1349,6 @@ void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) // list does not contain any items at all setNoItemsCommentText(mNoItemsMsg); } - } bool LLFlatListViewEx::getForceShowingUnmatchedItems() @@ -1411,12 +1407,10 @@ void LLFlatListViewEx::filterItems() getItems(items); mHasMatchedItems = false; - for (item_panel_list_t::iterator - iter = items.begin(), - iter_end = items.end(); - iter != iter_end; ++iter) + item_panel_list_t::iterator iter = items.begin(), iter_end = items.end(); + while (iter < iter_end) { - LLPanel* pItem = (*iter); + LLPanel* pItem = *(iter++); updateItemVisibility(pItem, action); } -- cgit v1.2.3 From 42e062888f6276c1e2dc043514a270a8dcf580db Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 10 Oct 2023 23:21:08 +0200 Subject: SL-20432 Filtering My Outfits with big number of items freezes UI --- indra/llui/llaccordionctrltab.h | 10 ++++----- indra/llui/llflatlistview.cpp | 47 +++++++++++++++++++++++++++-------------- indra/llui/llflatlistview.h | 11 ++++++---- 3 files changed, 43 insertions(+), 25 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 896a34cac4..496c34c38b 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -126,12 +126,12 @@ public: void setSelected(bool is_selected); - bool getCollapsible() {return mCollapsible;}; + bool getCollapsible() { return mCollapsible; }; - void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; + void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; void changeOpenClose(bool is_open); - void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; }; bool canOpenClose() const { return mCanOpenClose; }; virtual BOOL postBuild(); @@ -142,8 +142,8 @@ public: void draw(); - void storeOpenCloseState (); - void restoreOpenCloseState (); + void storeOpenCloseState(); + void restoreOpenCloseState(); protected: LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 460bd0945b..e4f2dd11a4 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1361,26 +1361,28 @@ void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) mForceShowingUnmatchedItems = show; } -void LLFlatListViewEx::setFilterSubString(const std::string& filter_str) +void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) { if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) { mFilterSubString = filter_str; updateNoItemsMessage(mFilterSubString); - filterItems(); + filterItems(false, notify_parent); } } -void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) +bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) { - if (!item) return; + 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; - item->setVisible(true); } else { @@ -1388,12 +1390,20 @@ void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) if (!mForceShowingUnmatchedItems) { selectItem(item, false); + visible = FALSE; } - item->setVisible(mForceShowingUnmatchedItems); } + + if (item->getVisible() != visible) + { + item->setVisible(visible); + return true; + } + + return false; } -void LLFlatListViewEx::filterItems() +void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { typedef std::vector item_panel_list_t; @@ -1403,19 +1413,24 @@ void LLFlatListViewEx::filterItems() LLSD action; action.with("match_filter", cur_filter); - item_panel_list_t items; - getItems(items); - mHasMatchedItems = false; - item_panel_list_t::iterator iter = items.begin(), iter_end = items.end(); - while (iter < iter_end) + bool visibility_changed = false; + pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); + while (iter != iter_end) { - LLPanel* pItem = *(iter++); - updateItemVisibility(pItem, action); + LLPanel* pItem = (*(iter++))->first; + visibility_changed |= updateItemVisibility(pItem, action); } - sort(); - notifyParentItemsRectChanged(); + if (re_sort) + { + sort(); + } + + if (visibility_changed && notify_parent) + { + notifyParentItemsRectChanged(); + } } bool LLFlatListViewEx::hasMatchedItems() diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index d47c1cf333..adb0e3e553 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -300,6 +300,7 @@ public: virtual S32 notify(const LLSD& info) ; virtual ~LLFlatListView(); + protected: /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ @@ -375,7 +376,9 @@ protected: LLRect getLastSelectedItemRect(); - void ensureSelectedVisible(); + void ensureSelectedVisible(); + + const pairs_list_t& getItemPairs() { return mItemPairs; } private: @@ -482,14 +485,14 @@ public: /** * Sets up new filter string and filters the list. */ - void setFilterSubString(const std::string& filter_str); + 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(); + void filterItems(bool re_sort, bool notify_parent); /** * Returns true if last call of filterItems() found at least one matching item @@ -513,7 +516,7 @@ protected: * @param item - item we are changing * @param item - action - parameters to determin visibility from */ - void updateItemVisibility(LLPanel* item, const LLSD &action); + bool updateItemVisibility(LLPanel* item, const LLSD &action); private: std::string mNoFilteredItemsMsg; -- cgit v1.2.3 From 52c7aeb480095063b6b407d7fbc51fd781e1d1a7 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 11 Oct 2023 14:31:21 +0200 Subject: SL-20432 Buildfix --- indra/llui/llflatlistview.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index e4f2dd11a4..fd4c33df30 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1405,8 +1405,6 @@ bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { - typedef std::vector item_panel_list_t; - std::string cur_filter = mFilterSubString; LLStringUtil::toUpper(cur_filter); -- cgit v1.2.3 From 1f00b2e04857bf118e7217e1310c38d08738f657 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 11 Oct 2023 21:51:30 +0300 Subject: SL-20403 FIXED People floater showing arrows on default size --- indra/llui/lltabcontainer.cpp | 15 ++++++++------- indra/llui/lltabcontainer.h | 4 ++++ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 76b9e448a1..b423de77c9 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -225,7 +225,8 @@ LLTabContainer::Params::Params() tabs_flashing_color("tabs_flashing_color"), tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), use_ellipses("use_ellipses"), - font_halign("halign") + font_halign("halign"), + use_tab_offset("use_tab_offset", false) {} LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) @@ -264,7 +265,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) mTabIconCtrlPad(p.tab_icon_ctrl_pad), mEnableTabsFlashing(p.enable_tabs_flashing), mTabsFlashingColor(p.tabs_flashing_color), - mUseTabEllipses(p.use_ellipses) + mUseTabEllipses(p.use_ellipses), + mUseTabOffset(p.use_tab_offset) { static LLUICachedControl tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); @@ -1023,11 +1025,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3, - tab_panel_top, - getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2, - tab_panel_bottom ); - } + S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH; + S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH; + tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, tab_panel_bottom); + } child->setFollowsAll(); child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom); child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE ); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index aa4a08c4ff..7d6fd15927 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -121,6 +121,8 @@ public: */ Optional tab_icon_ctrl_pad; + Optional use_tab_offset; + Params(); }; @@ -321,6 +323,8 @@ private: S32 mTabIconCtrlPad; bool mUseTabEllipses; LLFrameTimer mMouseDownTimer; + + bool mUseTabOffset; }; #endif // LL_TABCONTAINER_H -- cgit v1.2.3 From 136a993ef2fad587cb61d5aa2b142ac9119d2e42 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 11 Oct 2023 20:56:25 +0200 Subject: SL-20419 Receiving new objects or items, etc causes inventory to switch from recent to my inventory tab --- indra/llui/lltabcontainer.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index b423de77c9..024444e1c9 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1517,25 +1517,23 @@ BOOL LLTabContainer::selectTab(S32 which) LLTabTuple* selected_tuple = getTab(which); if (!selected_tuple) - { return FALSE; - } - + LLSD cbdata; if (selected_tuple->mTabPanel) cbdata = selected_tuple->mTabPanel->getName(); - BOOL res = FALSE; - if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) ) + BOOL result = FALSE; + if (!mValidateSignal || (*mValidateSignal)(this, cbdata)) { - res = setTab(which); - if (res && mCommitSignal) + result = setTab(which); + if (result && mCommitSignal) { (*mCommitSignal)(this, cbdata); } } - - return res; + + return result; } // private -- cgit v1.2.3 From a62f5bfac1e55455c67e1c36eb388af99795dab6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 14 Oct 2023 02:40:59 +0300 Subject: SL-20232 Allow deletion of worn items #1 --- indra/llui/llfolderview.cpp | 2 +- indra/llui/llfolderviewmodel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index bbbb4afb54..d7ba47c9f5 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -765,7 +765,7 @@ void LLFolderView::removeSelectedItems() } else { - LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL; + LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL; return; } } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 551a60e097..0f11560790 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -170,7 +170,7 @@ public: 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 isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector& batch) = 0; -- cgit v1.2.3 From ddb2c93818fe1132116c6efaebc9bd3afd012187 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 18 Oct 2023 11:02:51 +0200 Subject: SL-20463 Rename outfit dialog box accepts emoji characters --- indra/llui/lllineeditor.cpp | 28 +++++++++++++++++++++++++--- indra/llui/lllineeditor.h | 3 +++ indra/llui/llnotifications.cpp | 1 + indra/llui/llnotifications.h | 1 + 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 940cf398c0..96fa57b5a6 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -95,6 +95,7 @@ LLLineEditor::Params::Params() commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), + allow_emoji("allow_emoji"), cursor_color("cursor_color"), use_bg_color("use_bg_color", false), bg_color("bg_color"), @@ -141,6 +142,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( p.is_password ), + mAllowEmoji( p.allow_emoji ), mSpellCheck( p.spellcheck ), mSpellCheckStart(-1), mSpellCheckEnd(-1), @@ -413,8 +415,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived); std::string truncated_utf8 = new_text; + if (!mAllowEmoji) + { + // Cut emoji symbols if exist + utf8str_remove_emojis(truncated_utf8); + } if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) - { + { truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes); } mText.assign(truncated_utf8); @@ -586,13 +593,21 @@ void LLLineEditor::replaceWithSuggestion(U32 index) { if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) { + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + if (!mAllowEmoji) + { + // Cut emoji symbols if exist + wstring_remove_emojis(suggestion); + } + if (suggestion.empty()) + return; + deselect(); // 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()); @@ -955,9 +970,11 @@ void LLLineEditor::removeChar() } } - void LLLineEditor::addChar(const llwchar uni_char) { + if (!mAllowEmoji && LLStringOps::isEmoji(uni_char)) + return; + llwchar new_c = uni_char; if (hasSelection()) { @@ -1257,6 +1274,11 @@ void LLLineEditor::pasteHelper(bool is_primary) if (!paste.empty()) { + if (!mAllowEmoji) + { + wstring_remove_emojis(paste); + } + if (!prevalidateInput(paste)) return; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index ae4e05c065..8e5735acb4 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -92,6 +92,7 @@ public: ignore_tab, bg_image_always_focused, is_password, + allow_emoji, use_bg_color; // colors @@ -238,6 +239,7 @@ public: void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } void setIgnoreTab(BOOL b) { mIgnoreTab = b; } void setPassDelete(BOOL b) { mPassDelete = b; } + void setAllowEmoji(BOOL b) { mAllowEmoji = b; } void setDrawAsterixes(BOOL b); // get the cursor position of the beginning/end of the prev/next word in the text @@ -396,6 +398,7 @@ protected: BOOL mShowImageFocused; + bool mAllowEmoji; bool mUseBgColor; LLWString mPreeditWString; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d736aa6634..464ef576a7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -88,6 +88,7 @@ LLNotificationForm::FormInput::FormInput() : type("type"), text("text"), max_length_chars("max_length_chars"), + allow_emoji("allow_emoji"), width("width", 0), value("value") {} diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 921398a693..0729c00946 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -201,6 +201,7 @@ public: Mandatory type; Optional width; Optional max_length_chars; + Optional allow_emoji; Optional text; Optional value; -- cgit v1.2.3 From 9b27b6e5098aee7a050d4c3f3f14050c509f74ec Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 14 Dec 2022 19:41:07 +0200 Subject: SL-13610 [MAC] WIP List HID available devices in joystick selection Doesn't filter the list yet, just shows full list of usb devices Selecting visible devices doesn't work yet --- indra/llui/lltransutil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp index 5da722a72b..ecd065a4ef 100644 --- a/indra/llui/lltransutil.cpp +++ b/indra/llui/lltransutil.cpp @@ -44,8 +44,8 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::setdumpCurrentDirectories(LLError::LEVEL_WARN); - LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; + //gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); + LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; return false; } -- cgit v1.2.3 From 51088cde7f5a0bdaf9249bfdd5d31b9b212403ab Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 3 Jan 2024 22:57:28 +0200 Subject: SL-17896 Don't crash silently if files are missing or out of memory Under debug LL_ERRS will show a message as well, but release won't show anything and will quit silently so show a notification when applicable. --- indra/llui/llnotifications.cpp | 3 +++ indra/llui/lltexteditor.cpp | 1 + indra/llui/lltransutil.cpp | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 464ef576a7..25062f2cad 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1554,6 +1554,7 @@ bool LLNotifications::loadTemplates() 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; } @@ -1564,6 +1565,7 @@ bool LLNotifications::loadTemplates() if(!params.validateBlock()) { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1630,6 +1632,7 @@ bool LLNotifications::loadVisibilityRules() if(!params.validateBlock()) { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL; return false; } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3d2a426913..513cc56a02 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2600,6 +2600,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) char* text = new char[ text_len + 1]; if (text == NULL) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Memory allocation failure." << LL_ENDL; return FALSE; } diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp index ecd065a4ef..06760c4196 100644 --- a/indra/llui/lltransutil.cpp +++ b/indra/llui/lltransutil.cpp @@ -45,7 +45,12 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::setdumpCurrentDirectories(LLError::LEVEL_WARN); - LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; + const std::string error_string = + "Second Life viewer couldn't access some of the files it needs and will be closed." + "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " + "contact https://support.secondlife.com if issue persists after reinstall."; + LLError::LLUserWarningMsg::show(error_string); + LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL; return false; } @@ -60,6 +65,7 @@ bool LLTransUtil::parseLanguageStrings(const std::string& xml_filename) if (!success) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Couldn't load localization table " << xml_filename << LL_ENDL; return false; } -- cgit v1.2.3 From d3448fa204a648d61d07f12ecc982841160380d2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 30 Jan 2024 01:50:15 +0200 Subject: BugSplat Crash #1409959 onTopLost onTopLost crashed 1. It contradicts callstack, but clearPopups() definetely has an issue due to not checking the pointer prior to calling onTopLost 2. According to callstack, crash happened around ~LLFolderViewFolder and while it does call removePopup for itself, it isn't a popup, the only one in the list would be the renamer, which calls back to parent, so made sure to secure it. 3. mFlashTimer was never deleted 4. Some explicit cleanup for TopLost --- indra/llui/llcombobox.cpp | 2 ++ indra/llui/llfolderview.cpp | 19 ++++++++++++++++--- indra/llui/llfolderview.h | 2 ++ indra/llui/llmodaldialog.cpp | 2 ++ 4 files changed, 22 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 7a925c0659..8bf1bb9c9f 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -188,6 +188,8 @@ LLComboBox::~LLComboBox() // explicitly disconect this signal, since base class destructor might fire top lost mTopLostSignalConnection.disconnect(); mImageLoadedConnection.disconnect(); + + LLUI::getInstance()->removePopup(this); } diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index d7ba47c9f5..cbe8cf2dac 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -256,7 +256,13 @@ LLFolderView::LLFolderView(const Params& p) // Destroys the object LLFolderView::~LLFolderView( void ) { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + // instead of using closeRenamer remove it directly, + // since it might already be hidden + LLUI::getInstance()->removePopup(mRenamer); + } // The release focus call can potentially call the // scrollcontainer, which can potentially be called with a partly @@ -1072,7 +1078,10 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + if (!mRenamerTopLostSignalConnection.connected()) + { + mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + } LLUI::getInstance()->addPopup(mRenamer); } } @@ -1598,7 +1607,11 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + LLUI::getInstance()->removePopup(mRenamer); + } if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mPopupMenuHandle.markDead(); mScrollContainer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 5f8a173889..f3c23ffc17 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -345,6 +345,8 @@ protected: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; + boost::signals2::connection mRenamerTopLostSignalConnection; + bool mForceArrange; public: diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 22d98469ec..c4dacd777e 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -67,6 +67,8 @@ LLModalDialog::~LLModalDialog() { LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL; } + + LLUI::getInstance()->removePopup(this); } // virtual -- cgit v1.2.3 From 27dd9ee482f7f69651d44f8c7114a22ff761c013 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 28 Feb 2024 23:19:46 +0100 Subject: triage#86 Use Emoji font in LineEditor by default --- indra/llui/lllineeditor.cpp | 2 +- indra/llui/lltextbase.cpp | 2 +- indra/llui/lltexteditor.cpp | 2 +- indra/llui/lluictrl.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 1928c0157e..0643680277 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -96,7 +96,7 @@ LLLineEditor::Params::Params() commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), - allow_emoji("allow_emoji"), + allow_emoji("allow_emoji", true), cursor_color("cursor_color"), use_bg_color("use_bg_color", false), bg_color("bg_color"), diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7ccf025a19..7b57c7e5b8 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -915,7 +915,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s if (!emoji_style) { emoji_style = new LLStyle(getStyleParams()); - emoji_style->setFont(LLFontGL::getFontEmoji()); + emoji_style->setFont(LLFontGL::getFontEmojiLarge()); } S32 new_seg_start = pos + text_kitty; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index a247e8700a..e9ddc6cf0b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -685,7 +685,7 @@ void LLTextEditor::insertEmoji(llwchar emoji) { LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; auto styleParams = LLStyle::Params(); - styleParams.font = LLFontGL::getFontEmoji(); + styleParams.font = LLFontGL::getFontEmojiLarge(); auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); insert(mCursorPos, LLWString(1, emoji), false, segment); setCursorPos(mCursorPos + 1); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 7eb9ae69fb..c7fcbaec1c 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -80,7 +80,7 @@ LLUICtrl::Params::Params() mouseenter_callback("mouseenter_callback"), mouseleave_callback("mouseleave_callback"), control_name("control_name"), - font("font", LLFontGL::getFontSansSerif()), + font("font", LLFontGL::getFontEmojiMedium()), font_halign("halign"), font_valign("valign"), length("length"), // ignore LLXMLNode cruft -- cgit v1.2.3 From a6e1f22a993fde79d0ecb76d60535fdc454a2acd Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 5 Mar 2024 14:14:01 +0100 Subject: jira#71179 Use Emoji font in ScrollList by default --- indra/llui/llscrolllistcell.h | 2 +- indra/llui/llscrolllistctrl.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 2588da2331..117489fead 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -81,7 +81,7 @@ public: alt_value("alt_value", ""), label("label"), tool_tip("tool_tip", ""), - font("font", LLFontGL::getFontSansSerifSmall()), + font("font", LLFontGL::getFontEmojiSmall()), font_color("font_color", LLColor4::black), color("color", LLColor4::white), font_halign("halign", LLFontGL::LEFT) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index f982dc99e8..2a6e33fff6 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1810,7 +1810,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask) // display tooltip exactly over original cell, in same font LLToolTipMgr::instance().show(LLToolTip::Params() .message(hit_cell->getToolTip()) - .font(LLFontGL::getFontSansSerifSmall()) + .font(LLFontGL::getFontEmojiSmall()) .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6)) .delay_time(0.2f) .sticky_rect(sticky_rect)); @@ -3294,7 +3294,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E item_params.value(entry_id); item_params.columns.add() .value(value) - .font(LLFontGL::getFontSansSerifSmall()); + .font(LLFontGL::getFontEmojiSmall()); return addRow(item_params, pos); } -- cgit v1.2.3 From 1781e2d17b777e32e9b51e5a901c1295db80a4d8 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 8 Mar 2024 13:25:43 +0100 Subject: viewer#944 Make 'Debug Unicode' feature available for all LLViews --- indra/llui/llbutton.h | 2 +- indra/llui/llcheckboxctrl.h | 2 +- indra/llui/lllineeditor.cpp | 13 ------------- indra/llui/lllineeditor.h | 5 ++--- indra/llui/lltextbase.cpp | 19 +++---------------- indra/llui/lltextbase.h | 5 ++--- indra/llui/llview.cpp | 28 ++++++++++++++++++++++++++++ indra/llui/llview.h | 6 ++++-- indra/llui/llviewmodel.cpp | 35 +++++++++++++++++++++++------------ indra/llui/llviewmodel.h | 6 ++++++ 10 files changed, 70 insertions(+), 51 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 5ab7f07ab8..ecb08d1f23 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -251,7 +251,7 @@ public: void setFont(const LLFontGL *font) { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } const LLFontGL* getFont() const { return mGLFont; } - + const std::string& getText() const { return getCurrentLabel().getString(); } S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; } bool labelIsTruncated() const; diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index eb5bd5b6da..ba3c723fcb 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -117,7 +117,7 @@ public: std::string getLabel() const; void setFont( const LLFontGL* font ) { mFont = font; } - const LLFontGL* getFont() { return mFont; } + const LLFontGL* getFont() const { return mFont; } virtual void setControlName(const std::string& control_name, LLView* context); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 0643680277..3bf77cdb1c 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1761,19 +1761,6 @@ void LLLineEditor::drawBackground() } } -//virtual -const std::string LLLineEditor::getToolTip() const -{ - if (sDebugUnicode) - { - std::string text = getText(); - std::string tooltip = utf8str_showBytesUTF8(text); - return tooltip; - } - - return LLUICtrl::getToolTip(); -} - //virtual void LLLineEditor::draw() { diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 40de9e155e..87afa9a1d5 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -176,7 +176,6 @@ public: 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; @@ -204,7 +203,7 @@ public: void setText(const LLStringExplicit &new_text); - const std::string& getText() const { return mText.getString(); } + const std::string& getText() const override { return mText.getString(); } LLWString getWText() const { return mText.getWString(); } LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines @@ -236,7 +235,7 @@ public: const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); } const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } - const LLFontGL* getFont() const { return mGLFont; } + const LLFontGL* getFont() const override { return mGLFont; } void setFont(const LLFontGL* font); void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7b57c7e5b8..feac3400c7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1286,19 +1286,6 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask) return LLUICtrl::handleToolTip(x, y, mask); } -//virtual -const std::string LLTextBase::getToolTip() const -{ - if (sDebugUnicode) - { - std::string text = getText(); - std::string tooltip = utf8str_showBytesUTF8(text); - return tooltip; - } - - return LLUICtrl::getToolTip(); -} - //virtual void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { @@ -2182,10 +2169,10 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& onValueChange(0, getLength()); } -//virtual -std::string LLTextBase::getText() const +// virtual +const std::string& LLTextBase::getText() const { - return getViewModel()->getValue().asString(); + return getViewModel()->getStringValue(); } // IDEVO - icons can be UI image names or UUID sent from diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 9d3c54fbee..d65e3bfd7c 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -366,7 +366,6 @@ public: /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask) override; // LLView interface - /*virtual*/ const std::string getToolTip() const override; /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; /*virtual*/ void draw() override; @@ -422,7 +421,7 @@ public: // Text accessors // TODO: add optional style parameter virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style - virtual std::string getText() const; + /*virtual*/ const std::string& getText() const override; void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } S32 getMaxTextLength() { return mMaxTextByteLength; } @@ -495,7 +494,7 @@ public: bool scrolledToStart(); bool scrolledToEnd(); - const LLFontGL* getFont() const { return mFont; } + const LLFontGL* getFont() const override { return mFont; } virtual void appendLineBreakSegment(const LLStyle::Params& style_params); virtual void appendImageSegment(const LLStyle::Params& style_params); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 139eb17efa..1a80a69293 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -898,6 +898,34 @@ F32 LLView::getTooltipTimeout() : tooltip_delay); } +// virtual +const std::string LLView::getToolTip() const +{ + if (sDebugUnicode) + { + std::string text = getText(); + if (!text.empty()) + { + const std::string& name = getName(); + std::string tooltip = llformat("Name: \"%s\"", name.c_str()); + + if (const LLFontGL* font = getFont()) + { + tooltip += llformat("\nFont: %s (%s)", + font->getFontDesc().getName().c_str(), + font->getFontDesc().getSize().c_str() + ); + } + + tooltip += "\n\n" + utf8str_showBytesUTF8(text); + + return tooltip; + } + } + + return mToolTipMsg.getString(); +} + BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 6e16d41cba..c023cc95b7 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -243,8 +243,10 @@ public: ECursorType getHoverCursor() { return mHoverCursor; } - static F32 getTooltipTimeout(); - virtual const std::string getToolTip() const { return mToolTipMsg.getString(); } + static F32 getTooltipTimeout(); + virtual const std::string getToolTip() const; + virtual const std::string& getText() const { return LLStringUtil::null; } + virtual const LLFontGL* getFont() const { return nullptr; } void sendChildToFront(LLView* child); void sendChildToBack(LLView* child); diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp index a400eb70c0..41082a2848 100644 --- a/indra/llui/llviewmodel.cpp +++ b/indra/llui/llviewmodel.cpp @@ -81,7 +81,7 @@ void LLTextViewModel::setValue(const LLSD& value) { // approximate LLSD storage usage LLViewModel::setValue(value); - mDisplay = utf8str_to_wstring(value.asString()); + mDisplay = utf8str_to_wstring(mStringValue = value.asString()); // mDisplay and mValue agree mUpdateFromDisplay = false; @@ -101,23 +101,34 @@ void LLTextViewModel::setDisplay(const LLWString& value) mUpdateFromDisplay = true; } -LLSD LLTextViewModel::getValue() const +inline void updateFromDisplayIfNeeded(const LLTextViewModel* model) { - // Has anyone called setDisplay() since the last setValue()? If so, have - // to convert mDisplay back to UTF8. - if (mUpdateFromDisplay) + // Has anyone called setDisplay() since the last setValue()? + // If so, have to convert mDisplay back to UTF8. + if (model->mUpdateFromDisplay) { - // The fact that we're lazily updating fields in this object should be - // transparent to clients, which is why this method is left - // conventionally const. Nor do we particularly want to make these - // members mutable. Just cast away constness in this one place. - LLTextViewModel* nthis = const_cast(this); + // The fact that we're lazily updating fields + // in this object should be transparent to clients, + // which is why this method is left conventionally const. + // Nor do we particularly want to make these members mutable. + // Just cast away constness in this one place. + LLTextViewModel* nthis = const_cast(model); nthis->mUpdateFromDisplay = false; - nthis->mValue = wstring_to_utf8str(mDisplay); + nthis->mValue = nthis->mStringValue = wstring_to_utf8str(model->mDisplay); } - return LLViewModel::getValue(); } +LLSD LLTextViewModel::getValue() const +{ + updateFromDisplayIfNeeded(this); + return mValue; +} + +const std::string& LLTextViewModel::getStringValue() const +{ + updateFromDisplayIfNeeded(this); + return mStringValue; +} //////////////////////////////////////////////////////////////////////////// diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index e7dceb6c31..ffd67f455d 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -100,6 +100,7 @@ public: // LLViewModel functions virtual void setValue(const LLSD& value); virtual LLSD getValue() const; + const std::string& getStringValue() const; // New functions /// Get the stored value in string form @@ -114,12 +115,17 @@ public: void setDisplay(const LLWString& value); private: + std::string mStringValue; + /// To avoid converting every widget's stored value from LLSD to LLWString /// every frame, cache the converted value LLWString mDisplay; + /// As the user edits individual characters (setDisplay()), defer /// LLWString-to-UTF8 conversions until s/he's done. bool mUpdateFromDisplay; + + friend void updateFromDisplayIfNeeded(const LLTextViewModel* model); }; /** -- cgit v1.2.3 From 15734c19783fc5fc38e5c1cba485d756285161e0 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 12 Mar 2024 18:30:33 +0100 Subject: viewer#961 Add a notification appearing when user tries to insert a disallowed character --- indra/llui/llfolderview.cpp | 2 +- indra/llui/lllineeditor.cpp | 75 ++-- indra/llui/lllineeditor.h | 12 +- indra/llui/llmultisliderctrl.cpp | 2 +- indra/llui/llresmgr.cpp | 14 +- indra/llui/llsliderctrl.cpp | 2 +- indra/llui/lltexteditor.cpp | 69 ++-- indra/llui/lltexteditor.h | 4 +- indra/llui/lltextvalidate.cpp | 764 +++++++++++++++++++++++---------------- indra/llui/lltextvalidate.h | 83 +++-- indra/llui/lltimectrl.cpp | 41 ++- indra/llui/lltimectrl.h | 26 +- 12 files changed, 648 insertions(+), 446 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index cbe8cf2dac..23891cad7f 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -220,7 +220,7 @@ LLFolderView::LLFolderView(const Params& p) 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.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe); params.commit_on_focus_lost(true); params.visible(false); mRenamer = LLUICtrlFactory::create (params); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 3bf77cdb1c..406cc36119 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -82,9 +82,9 @@ template class LLLineEditor* LLView::getChild( LLLineEditor::Params::Params() : max_length(""), - keystroke_callback("keystroke_callback"), - prevalidate_callback("prevalidate_callback"), - prevalidate_input_callback("prevalidate_input_callback"), + keystroke_callback("keystroke_callback"), + prevalidator("prevalidator"), + input_prevalidator("input_prevalidator"), background_image("background_image"), background_image_disabled("background_image_disabled"), background_image_focused("background_image_focused"), @@ -112,6 +112,8 @@ LLLineEditor::Params::Params() default_text("default_text") { changeDefault(mouse_opaque, true); + addSynonym(prevalidator, "prevalidate_callback"); + addSynonym(input_prevalidator, "prevalidate_input_callback"); addSynonym(select_on_focus, "select_all_on_focus_received"); addSynonym(border, "border"); addSynonym(label, "watermark_text"); @@ -159,6 +161,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mUseBgColor(p.use_bg_color), mHaveHistory(FALSE), mReplaceNewlinesWithSpaces( TRUE ), + mPrevalidator(p.prevalidator()), + mInputPrevalidator(p.input_prevalidator()), mLabel(p.label), mCursorColor(p.cursor_color()), mBgColor(p.bg_color()), @@ -212,8 +216,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) } mSpellCheckTimer.reset(); - setPrevalidateInput(p.prevalidate_input_callback()); - setPrevalidate(p.prevalidate_callback()); + updateAllowingLanguageInput(); } LLLineEditor::~LLLineEditor() @@ -1210,11 +1213,12 @@ void LLLineEditor::cut() deleteSelection(); // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -1343,11 +1347,12 @@ void LLLineEditor::pasteHelper(bool is_primary) deselect(); // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -1590,19 +1595,27 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) deselect(); } - BOOL need_to_rollback = FALSE; + bool prevalidator_failed = false; // If read-only, don't allow changes - need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText())); + bool 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 && mPrevalidator) + { + prevalidator_failed = !mPrevalidator.validate(mText.getWString()); + need_to_rollback |= prevalidator_failed; + } if (need_to_rollback) { rollback.doRollback(this); LLUI::getInstance()->reportBadKeystroke(); + if (prevalidator_failed) + { + mPrevalidator.showLastErrorUsingTimeout(); + } } // Notify owner if requested @@ -1649,20 +1662,18 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) deselect(); - BOOL need_to_rollback = FALSE; - // Validate new string and rollback the keystroke if needed. - need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - - if( need_to_rollback ) + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } // Notify owner if requested - if( !need_to_rollback && handled ) + 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 @@ -1692,7 +1703,7 @@ void LLLineEditor::doDelete() deleteSelection(); } else if ( getCursor() < mText.length()) - { + { const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1); if (!prevalidateInput(text_to_delete)) @@ -1705,11 +1716,12 @@ void LLLineEditor::doDelete() } // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { - rollback.doRollback( this ); + rollback.doRollback(this); LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -2241,7 +2253,7 @@ void LLLineEditor::setFocus( BOOL new_state ) // 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); + getWindow()->allowLanguageTextInput(this, !mPrevalidator); } } @@ -2260,26 +2272,21 @@ void LLLineEditor::setRect(const LLRect& rect) } } -void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func) +void LLLineEditor::setPrevalidate(LLTextValidate::Validator validator) { - mPrevalidateFunc = func; + mPrevalidator = validator; updateAllowingLanguageInput(); } -void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func) +void LLLineEditor::setPrevalidateInput(LLTextValidate::Validator validator) { - mPrevalidateInputFunc = func; + mInputPrevalidator = validator; updateAllowingLanguageInput(); } bool LLLineEditor::prevalidateInput(const LLWString& wstr) { - if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr)) - { - return false; - } - - return true; + return mInputPrevalidator.validate(wstr); } // static @@ -2421,7 +2428,7 @@ void LLLineEditor::updateAllowingLanguageInput() // test app, no window available return; } - if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL) + if (hasFocus() && !mReadOnly && !mDrawAsterixes && !mPrevalidator) { window->allowLanguageTextInput(this, TRUE); } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 87afa9a1d5..15eb789897 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -76,8 +76,8 @@ public: Optional max_length; Optional keystroke_callback; - Optional prevalidate_callback; - Optional prevalidate_input_callback; + Optional prevalidator; + Optional input_prevalidator; Optional border; @@ -268,12 +268,12 @@ public: void setTextPadding(S32 left, S32 right); // Prevalidation controls which keystrokes can affect the editor - void setPrevalidate( LLTextValidate::validate_func_t func ); + void setPrevalidate(LLTextValidate::Validator validator); // 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); + void setPrevalidateInput(LLTextValidate::Validator validator); static BOOL postvalidateFloat(const std::string &str); bool prevalidateInput(const LLWString& wstr); @@ -375,8 +375,8 @@ protected: std::list > mMisspellRanges; std::vector mSuggestionList; - LLTextValidate::validate_func_t mPrevalidateFunc; - LLTextValidate::validate_func_t mPrevalidateInputFunc; + LLTextValidate::Validator mPrevalidator; + LLTextValidate::Validator mInputPrevalidator; LLFrameTimer mKeystrokeTimer; LLTimer mTripleClickTimer; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index b3df7c154b..b651d85970 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) params.font(p.font); params.max_length.bytes(MAX_STRING_LENGTH); params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit); - params.prevalidate_callback(&LLTextValidate::validateFloat); + params.prevalidator(&LLTextValidate::validateFloat); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create (params); mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) ); diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp index d65c220974..f18569d47f 100644 --- a/indra/llui/llresmgr.cpp +++ b/indra/llui/llresmgr.cpp @@ -47,9 +47,9 @@ void LLResMgr::setLocale( LLLOCALE_ID locale_id ) mLocale = locale_id; } -char LLResMgr::getDecimalPoint() const +char LLResMgr::getDecimalPoint() const { - char decimal = localeconv()->decimal_point[0]; + char decimal = localeconv()->decimal_point[0]; #if LL_DARWIN // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped. @@ -62,9 +62,9 @@ char LLResMgr::getDecimalPoint() const return decimal; } -char LLResMgr::getThousandsSeparator() const +char LLResMgr::getThousandsSeparator() const { - char separator = localeconv()->thousands_sep[0]; + char separator = localeconv()->thousands_sep[0]; #if LL_DARWIN // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped. @@ -79,7 +79,7 @@ char LLResMgr::getThousandsSeparator() const char LLResMgr::getMonetaryDecimalPoint() const { - char decimal = localeconv()->mon_decimal_point[0]; + char decimal = localeconv()->mon_decimal_point[0]; #if LL_DARWIN // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped. @@ -92,9 +92,9 @@ char LLResMgr::getMonetaryDecimalPoint() const return decimal; } -char LLResMgr::getMonetaryThousandsSeparator() const +char LLResMgr::getMonetaryThousandsSeparator() const { - char separator = localeconv()->mon_thousands_sep[0]; + char separator = localeconv()->mon_thousands_sep[0]; #if LL_DARWIN // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped. diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index d80a434f22..e6cb739702 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -167,7 +167,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) } line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit); - line_p.prevalidate_callback(&LLTextValidate::validateFloat); + line_p.prevalidator(&LLTextValidate::validateFloat); mEditor = LLUICtrlFactory::create(line_p); mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this )); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index e9ddc6cf0b..875a5faa2b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -232,17 +232,18 @@ private: /////////////////////////////////////////////////////////////////// LLTextEditor::Params::Params() : default_text("default_text"), - prevalidate_callback("prevalidate_callback"), + prevalidator("prevalidator"), embedded_items("embedded_items", false), ignore_tab("ignore_tab", true), auto_indent("auto_indent", true), default_color("default_color"), - commit_on_focus_lost("commit_on_focus_lost", false), + commit_on_focus_lost("commit_on_focus_lost", false), show_context_menu("show_context_menu"), show_emoji_helper("show_emoji_helper"), enable_tooltip_paste("enable_tooltip_paste") { - addSynonym(prevalidate_callback, "text_type"); + addSynonym(prevalidator, "prevalidate_callback"); + addSynonym(prevalidator, "text_type"); } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : @@ -253,16 +254,17 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mLastCmd( NULL ), mDefaultColor( p.default_color() ), mAutoIndent(p.auto_indent), + mParseOnTheFly(false), mCommitOnFocusLost( p.commit_on_focus_lost), mAllowEmbeddedItems( p.embedded_items ), mMouseDownX(0), mMouseDownY(0), mTabsToNextField(p.ignore_tab), - mPrevalidateFunc(p.prevalidate_callback()), + mPrevalidator(p.prevalidator()), mShowContextMenu(p.show_context_menu), mShowEmojiHelper(p.show_emoji_helper), mEnableTooltipPaste(p.enable_tooltip_paste), - mPassDelete(FALSE), + mPassDelete(false), mKeepSelectionOnReturn(false) { mSourceID.generate(); @@ -278,7 +280,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : addChild( mBorder ); setText(p.default_text()); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; } void LLTextEditor::initFromParams( const LLTextEditor::Params& p) @@ -319,11 +321,13 @@ LLTextEditor::~LLTextEditor() void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params) { // validate incoming text if necessary - if (mPrevalidateFunc) + if (mPrevalidator) { - LLWString test_text = utf8str_to_wstring(utf8str); - if (!mPrevalidateFunc(test_text)) + if (!mPrevalidator.validate(utf8str)) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); + // not valid text, nothing to do return; } @@ -332,9 +336,9 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Param blockUndo(); deselect(); - mParseOnTheFly = FALSE; + mParseOnTheFly = false; LLTextBase::setText(utf8str, input_params); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; resetDirty(); } @@ -609,7 +613,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) // Disabling parsing on the fly to avoid updating text segments // until all indentation commands are executed. - mParseOnTheFly = FALSE; + mParseOnTheFly = false; // Find each start-of-line and indent it do @@ -636,7 +640,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) } while( cur < right ); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; if( (right < getLength()) && (text[right] == '\n') ) { @@ -986,10 +990,12 @@ S32 LLTextEditor::execute( TextCmd* cmd ) mUndoStack.push_front(cmd); mLastCmd = cmd; - bool need_to_rollback = mPrevalidateFunc - && !mPrevalidateFunc(getViewModel()->getDisplay()); + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(getViewModel()->getDisplay()); if (need_to_rollback) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); + // get rid of this last command and clean up undo stack undo(); @@ -1125,16 +1131,15 @@ void LLTextEditor::removeChar() // Add a single character to the text S32 LLTextEditor::addChar(S32 pos, llwchar wc) { - if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength) + if ((wstring_utf8_length(getWText()) + wchar_utf8_length(wc)) > mMaxTextByteLength) { - make_ui_sound("UISndBadKeystroke"); + LLUI::getInstance()->reportBadKeystroke(); return 0; } if (mLastCmd && mLastCmd->canExtend(pos)) { - S32 delta = 0; - if (mPrevalidateFunc) + if (mPrevalidator) { // get a copy of current text contents LLWString test_string(getViewModel()->getDisplay()); @@ -1142,28 +1147,31 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc) // modify text contents as if this addChar succeeded llassert(pos <= (S32)test_string.size()); test_string.insert(pos, 1, wc); - if (!mPrevalidateFunc( test_string)) + if (!mPrevalidator.validate(test_string)) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); return 0; } } + + S32 delta = 0; mLastCmd->extendAndExecute(this, pos, wc, &delta); return delta; } - else - { - return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); - } + + return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); } void LLTextEditor::addChar(llwchar wc) { - if( !getEnabled() ) + if (!getEnabled()) { return; } - if( hasSelection() ) + + if (hasSelection()) { deleteSelection(TRUE); } @@ -1508,7 +1516,13 @@ void LLTextEditor::pastePrimary() // paste from primary (itsprimary==true) or clipboard (itsprimary==false) void LLTextEditor::pasteHelper(bool is_primary) { - mParseOnTheFly = FALSE; + struct BoolReset + { + BoolReset(bool& value) : mValuePtr(&value) { *mValuePtr = false; } + ~BoolReset() { *mValuePtr = true; } + bool* mValuePtr; + } reset(mParseOnTheFly); + bool can_paste_it; if (is_primary) { @@ -1550,7 +1564,6 @@ void LLTextEditor::pasteHelper(bool is_primary) deselect(); onKeyStroke(); - mParseOnTheFly = TRUE; } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 521405ec25..ded1444008 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -54,7 +54,7 @@ public: struct Params : public LLInitParam::Block { Optional default_text; - Optional prevalidate_callback; + Optional prevalidator; Optional embedded_items, ignore_tab, @@ -337,7 +337,7 @@ private: LLCoordGL mLastIMEPosition; // Last position of the IME editor keystroke_signal_t mKeystrokeSignal; - LLTextValidate::validate_func_t mPrevalidateFunc; + LLTextValidate::Validator mPrevalidator; LLHandle mContextMenuHandle; }; // end class LLTextEditor diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp index bfe0a5bb5d..9e27ed6232 100644 --- a/indra/llui/lltextvalidate.cpp +++ b/indra/llui/lltextvalidate.cpp @@ -27,330 +27,452 @@ // Text editor widget to let users enter a single line. #include "linden_common.h" - + #include "lltextvalidate.h" + +#include "llnotificationsutil.h" +#include "lltrans.h" + #include "llresmgr.h" // for LLLocale namespace LLTextValidate { - void ValidateTextNamedFuncs::declareValues() - { - declare("ascii", validateASCII); - declare("float", validateFloat); - declare("int", validateInt); - declare("positive_s32", validatePositiveS32); - declare("non_negative_s32", validateNonNegativeS32); - declare("alpha_num", validateAlphaNum); - declare("alpha_num_space", validateAlphaNumSpace); - declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe); - declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); - declare("ascii_with_newline", validateASCIIWithNewLine); - } - - // Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. - // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for - // the simple reasons that intermediate states may be invalid even if the final result is valid. - // - bool validateFloat(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - bool success = TRUE; - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - if( 0 < len ) - { - // May be a comma or period, depending on the locale - llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint(); - - S32 i = 0; - - // First character can be a negative sign - if( '-' == trimmed[0] ) - { - i++; - } - - for( ; i < len; i++ ) - { - if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) ) - { - success = FALSE; - break; - } - } - } - - return success; - } - - // Limits what characters can be used to [1234567890-] with [-] only valid in the first position. - // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for - // the simple reasons that intermediate states may be invalid even if the final result is valid. - // - bool validateInt(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - bool success = TRUE; - LLWString trimmed = 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++; - } - - for( ; i < len; i++ ) - { - if( !LLStringOps::isDigit( trimmed[i] ) ) - { - success = FALSE; - break; - } - } - } - - return success; - } - - bool validatePositiveS32(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - bool success = TRUE; - if(0 < len) - { - if(('-' == trimmed[0]) || ('0' == trimmed[0])) - { - success = FALSE; - } - S32 i = 0; - while(success && (i < len)) - { - if(!LLStringOps::isDigit(trimmed[i++])) - { - success = FALSE; - } - } - } - if (success) - { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val <= 0) - { - success = FALSE; - } - } - return success; - } - - bool validateNonNegativeS32(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - bool success = TRUE; - if(0 < len) - { - if('-' == trimmed[0]) - { - success = FALSE; - } - S32 i = 0; - while(success && (i < len)) - { - if(!LLStringOps::isDigit(trimmed[i++])) - { - success = FALSE; - } - } - } - if (success) - { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val < 0) - { - success = FALSE; - } - } - return success; - } - - bool validateNonNegativeS32NoSpace(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - LLWString test_str = str; - S32 len = test_str.length(); - bool success = TRUE; - if(0 < len) - { - if('-' == test_str[0]) - { - success = FALSE; - } - S32 i = 0; - while(success && (i < len)) - { - if(!LLStringOps::isDigit(test_str[i]) || LLStringOps::isSpace(test_str[i++])) - { - success = FALSE; - } - } - } - if (success) - { - S32 val = strtol(wstring_to_utf8str(test_str).c_str(), NULL, 10); - if (val < 0) - { - success = FALSE; - } - } - return success; - } - - bool validateAlphaNum(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - bool rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - if( !LLStringOps::isAlnum((char)str[len]) ) - { - rv = FALSE; - break; - } - } - return rv; - } - - bool validateAlphaNumSpace(const LLWString &str) - { - LLLocale locale(LLLocale::USER_LOCALE); - - bool rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len]))) - { - rv = FALSE; - break; - } - } - return rv; - } - - // Used for most names of things stored on the server, due to old file-formats - // that used the pipe (|) for multiline text storage. Examples include - // inventory item names, parcel names, object names, etc. - bool validateASCIIPrintableNoPipe(const LLWString &str) - { - bool rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || wc == '|') - { - rv = FALSE; - break; - } - if(!(wc == ' ' - || LLStringOps::isAlnum((char)wc) - || LLStringOps::isPunct((char)wc) ) ) - { - rv = FALSE; - break; - } - } - return rv; - } - - - // Used for avatar names - bool validateASCIIPrintableNoSpace(const LLWString &str) - { - bool rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || LLStringOps::isSpace(wc)) - { - rv = FALSE; - break; - } - if( !(LLStringOps::isAlnum((char)str[len]) || - LLStringOps::isPunct((char)str[len]) ) ) - { - rv = FALSE; - break; - } - } - return rv; - } - - bool validateASCII(const LLWString &str) - { - bool rv = TRUE; - S32 len = str.length(); - while(len--) - { - if (str[len] < 0x20 || str[len] > 0x7f) - { - rv = FALSE; - break; - } - } - return rv; - } - - bool validateASCIINoLeadingSpace(const LLWString &str) - { - if (LLStringOps::isSpace(str[0])) - { - return FALSE; - } - return validateASCII(str); - } - - // Used for multiline text stored on the server. - // Example is landmark description in Places SP. - bool validateASCIIWithNewLine(const LLWString &str) - { - bool rv = TRUE; - S32 len = str.length(); - while(len--) - { - if ((str[len] < 0x20 && str[len] != 0xA) || str[len] > 0x7f) - { - rv = FALSE; - break; - } - } - return rv; - } + +static S32 strtol(const std::string& str) { return ::strtol(str.c_str(), NULL, 10); } +static S32 strtol(const LLWString& str) { return ::strtol(wstring_to_utf8str(str).c_str(), NULL, 10); } + +static LLSD llsd(const std::string& str) { return LLSD(str); } +static LLSD llsd(const LLWString& str) { return LLSD(wstring_to_utf8str(str)); } +template +LLSD llsd(CHAR ch) { return llsd(std::basic_string(1, ch)); } + +void ValidatorImpl::setLastErrorShowTime() +{ + mLastErrorShowTime = (U32Seconds)LLTimer::getTotalTime(); +} + +void Validator::showLastErrorUsingTimeout(U32 timeout) +{ + if (mImpl && (U32Seconds)LLTimer::getTotalTime() >= mImpl->getLastErrorShowTime() + timeout) + { + mImpl->setLastErrorShowTime(); + std::string reason = LLTrans::getString(mImpl->getLastErrorName(), mImpl->getLastErrorValues()); + LLNotificationsUtil::add("InvalidKeystroke", LLSD().with("REASON", reason)); + } } + +// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. +// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for +// the simple reasons that intermediate states may be invalid even if the final result is valid. +class ValidatorFloat : public ValidatorImpl +{ + template + bool validate(const std::basic_string &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + std::basic_string trimmed = str; + LLStringUtilBase::trim(trimmed); + S32 len = trimmed.length(); + if (0 < len) + { + // May be a comma or period, depending on the locale + CHAR decimal_point = LLResMgr::getInstance()->getDecimalPoint(); + + S32 i = 0; + + // First character can be a negative sign + if ('-' == trimmed.front()) + { + i++; + } + + for (; i < len; i++) + { + CHAR ch = trimmed[i]; + if ((decimal_point != ch) && !LLStringOps::isDigit(ch)) + { + return setError("Validator_ShouldBeDigitOrDot", LLSD().with("NR", i + 1).with("CH", llsd(ch))); + } + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorFloatImpl; +Validator validateFloat(validatorFloatImpl); + +// Limits what characters can be used to [1234567890-] with [-] only valid in the first position. +// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for +// the simple reasons that intermediate states may be invalid even if the final result is valid. +class ValidatorInt : public ValidatorImpl +{ + template + bool validate(const std::basic_string &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + std::basic_string trimmed = str; + LLStringUtilBase::trim(trimmed); + S32 len = trimmed.length(); + if (0 < len) + { + S32 i = 0; + + // First character can be a negative sign + if ('-' == trimmed.front()) + { + i++; + } + + for (; i < len; i++) + { + CHAR ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) + { + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); + } + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorIntImpl; +Validator validateInt(validatorIntImpl); + +class ValidatorPositiveS32 : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + std::basic_string trimmed = str; + LLStringUtilBase::trim(trimmed); + S32 len = trimmed.length(); + if (0 < len) + { + CHAR ch = trimmed.front(); + + if (('-' == ch) || ('0' == ch)) + { + return setError("Validator_ShouldNotBeMinusOrZero", LLSD().with("CH", llsd(ch))); + } + + for (S32 i = 0; i < len; ++i) + { + ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) + { + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); + } + } + } + + S32 val = strtol(trimmed); + if (val <= 0) + { + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed))); + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorPositiveS32Impl; +Validator validatePositiveS32(validatorPositiveS32Impl); + +class ValidatorNonNegativeS32 : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + std::basic_string trimmed = str; + LLStringUtilBase::trim(trimmed); + S32 len = trimmed.length(); + if (0 < len) + { + CHAR ch = trimmed.front(); + + if ('-' == ch) + { + return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch))); + } + + for (S32 i = 0; i < len; ++i) + { + ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) + { + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); + } + } + } + + S32 val = strtol(trimmed); + if (val < 0) + { + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed))); + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorNonNegativeS32Impl; +Validator validateNonNegativeS32(validatorNonNegativeS32Impl); + +class ValidatorNonNegativeS32NoSpace : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + std::basic_string test_str = str; + S32 len = test_str.length(); + if (0 < len) + { + CHAR ch = test_str.front(); + + if ('-' == ch) + { + return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch))); + } + + for (S32 i = 0; i < len; ++i) + { + ch = test_str[i]; + if (!LLStringOps::isDigit(ch) || LLStringOps::isSpace(ch)) + { + return setError("Validator_ShouldBeDigitNotSpace", LLSD().with("NR", i + 1).with("CH", llsd(ch))); + } + } + } + + S32 val = strtol(test_str); + if (val < 0) + { + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(test_str))); + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorNonNegativeS32NoSpaceImpl; +Validator validateNonNegativeS32NoSpace(validatorNonNegativeS32NoSpaceImpl); + +class ValidatorAlphaNum : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if (!LLStringOps::isAlnum(ch)) + { + return setError("Validator_ShouldBeDigitOrAlpha", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorAlphaNumImpl; +Validator validateAlphaNum(validatorAlphaNumImpl); + +class ValidatorAlphaNumSpace : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if (!LLStringOps::isAlnum(ch) && (' ' != ch)) + { + return setError("Validator_ShouldBeDigitOrAlphaOrSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorAlphaNumSpaceImpl; +Validator validateAlphaNumSpace(validatorAlphaNumSpaceImpl); + +// Used for most names of things stored on the server, due to old file-formats +// that used the pipe (|) for multiline text storage. Examples include +// inventory item names, parcel names, object names, etc. +class ValidatorASCIIPrintableNoPipe : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if (ch < 0x20 || ch > 0x7f || ch == '|' || + (ch != ' ' && !LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch))) + { + return setError("Validator_ShouldBeDigitOrAlphaOrPunct", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorASCIIPrintableNoPipeImpl; +Validator validateASCIIPrintableNoPipe(validatorASCIIPrintableNoPipeImpl); + +// Used for avatar names +class ValidatorASCIIPrintableNoSpace : public ValidatorImpl +{ + template + bool validate(const std::basic_string& str) + { + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if (ch <= 0x20 || ch > 0x7f || LLStringOps::isSpace(ch) || + (!LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch))) + { + return setError("Validator_ShouldBeDigitOrAlphaOrPunctNotSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorASCIIPrintableNoSpaceImpl; +Validator validateASCIIPrintableNoSpace(validatorASCIIPrintableNoSpaceImpl); + +class ValidatorASCII : public ValidatorImpl +{ +protected: + template + bool validate(const std::basic_string& str) + { + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if (ch < 0x20 || ch > 0x7f) + { + return setError("Validator_ShouldBeASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorASCIIImpl; +Validator validateASCII(validatorASCIIImpl); + +class ValidatorASCIINoLeadingSpace : public ValidatorASCII +{ + template + bool validate(const std::basic_string& str) + { + if (LLStringOps::isSpace(str.front())) + { + return false; + } + + return ValidatorASCII::validate(str); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorASCIINoLeadingSpaceImpl; +Validator validateASCIINoLeadingSpace(validatorASCIINoLeadingSpaceImpl); + +class ValidatorASCIIWithNewLine : public ValidatorImpl +{ + // Used for multiline text stored on the server. + // Example is landmark description in Places SP. + template + bool validate(const std::basic_string& str) + { + S32 len = str.length(); + while (len--) + { + CHAR ch = str[len]; + + if ((ch < 0x20 && ch != 0xA) || ch > 0x7f) + { + return setError("Validator_ShouldBeNewLineOrASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch))); + } + } + + return resetError(); + } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate(str); } +} validatorASCIIWithNewLineImpl; +Validator validateASCIIWithNewLine(validatorASCIIWithNewLineImpl); + +void Validators::declareValues() +{ + declare("ascii", validateASCII); + declare("float", validateFloat); + declare("int", validateInt); + declare("positive_s32", validatePositiveS32); + declare("non_negative_s32", validateNonNegativeS32); + declare("alpha_num", validateAlphaNum); + declare("alpha_num_space", validateAlphaNumSpace); + declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe); + declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); + declare("ascii_with_newline", validateASCIIWithNewLine); +} + +} // namespace LLTextValidate diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h index e2b6c313d6..2c2941de7f 100644 --- a/indra/llui/lltextvalidate.h +++ b/indra/llui/lltextvalidate.h @@ -34,27 +34,68 @@ namespace LLTextValidate { - typedef boost::function validate_func_t; - - struct ValidateTextNamedFuncs - : public LLInitParam::TypeValuesHelper - { - static void declareValues(); - }; - - bool validateFloat(const LLWString &str ); - bool validateInt(const LLWString &str ); - bool validatePositiveS32(const LLWString &str); - bool validateNonNegativeS32(const LLWString &str); - bool validateNonNegativeS32NoSpace(const LLWString &str); - bool validateAlphaNum(const LLWString &str ); - bool validateAlphaNumSpace(const LLWString &str ); - bool validateASCIIPrintableNoPipe(const LLWString &str); - bool validateASCIIPrintableNoSpace(const LLWString &str); - bool validateASCII(const LLWString &str); - bool validateASCIINoLeadingSpace(const LLWString &str); - bool validateASCIIWithNewLine(const LLWString &str); -} + class ValidatorImpl + { + public: + ValidatorImpl() {} + virtual ~ValidatorImpl() {} + virtual bool validate(const std::string& str) = 0; + virtual bool validate(const LLWString& str) = 0; + + bool setError(std::string name, LLSD values = LLSD()) { return mLastErrorName = name, mLastErrorValues = values, false; } + bool resetError() { return mLastErrorName.clear(), mLastErrorValues.clear(), true; } + const std::string& getLastErrorName() const { return mLastErrorName; } + const LLSD& getLastErrorValues() const { return mLastErrorValues; } + + void setLastErrorShowTime(); + U32 getLastErrorShowTime() const { return mLastErrorShowTime; } + + protected: + std::string mLastErrorName; + LLSD mLastErrorValues; + U32 mLastErrorShowTime { 0 }; + }; + + class Validator + { + public: + Validator() : mImpl(nullptr) {} + Validator(ValidatorImpl& impl) : mImpl(&impl) {} + Validator(const Validator& validator) : mImpl(validator.mImpl) {} + Validator(const Validator* validator) : mImpl(validator->mImpl) {} + + bool validate(const std::string& str) const { return !mImpl || mImpl->validate(str); } + bool validate(const LLWString& str) const { return !mImpl || mImpl->validate(str); } + + operator bool() const { return mImpl; } + + static const U32 SHOW_LAST_ERROR_TIMEOUT_SEC = 30; + void showLastErrorUsingTimeout(U32 timeout = SHOW_LAST_ERROR_TIMEOUT_SEC); + + private: + ValidatorImpl* mImpl; + }; + + // Available validators + extern Validator validateFloat; + extern Validator validateInt; + extern Validator validatePositiveS32; + extern Validator validateNonNegativeS32; + extern Validator validateNonNegativeS32NoSpace; + extern Validator validateAlphaNum; + extern Validator validateAlphaNumSpace; + extern Validator validateASCIIPrintableNoPipe; + extern Validator validateASCIIPrintableNoSpace; + extern Validator validateASCII; + extern Validator validateASCIINoLeadingSpace; + extern Validator validateASCIIWithNewLine; + + // Add available validators to the internal map + struct Validators : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; +}; #endif diff --git a/indra/llui/lltimectrl.cpp b/indra/llui/lltimectrl.cpp index 516057f8fd..564d0b6264 100644 --- a/indra/llui/lltimectrl.cpp +++ b/indra/llui/lltimectrl.cpp @@ -49,6 +49,36 @@ const U32 HOURS_MAX = 12; const U32 MINUTES_PER_HOUR = 60; const U32 MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR; +class LLTimeValidatorImpl : public LLTextValidate::ValidatorImpl +{ +public: + // virtual + bool validate(const std::string& str) override + { + std::string hours = LLTimeCtrl::getHoursString(str); + if (!LLTimeCtrl::isHoursStringValid(hours)) + return setError("ValidatorInvalidHours", LLSD().with("STR", hours)); + + std::string minutes = LLTimeCtrl::getMinutesString(str); + if (!LLTimeCtrl::isMinutesStringValid(minutes)) + return setError("ValidatorInvalidMinutes", LLSD().with("STR", minutes)); + + std::string ampm = LLTimeCtrl::getAMPMString(str); + if (!LLTimeCtrl::isPMAMStringValid(ampm)) + return setError("ValidatorInvalidAMPM", LLSD().with("STR", ampm)); + + return resetError(); + } + + // virtual + bool validate(const LLWString& wstr) override + { + std::string str = wstring_to_utf8str(wstr); + + return validate(str); + } +} validateTimeImpl; +LLTextValidate::Validator validateTime(validateTimeImpl); LLTimeCtrl::Params::Params() : label_width("label_width"), @@ -111,7 +141,7 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p) params.keystroke_callback(boost::bind(&LLTimeCtrl::onTextEntry, this, _1)); mEditor = LLUICtrlFactory::create (params); mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace); - mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1)); + mEditor->setPrevalidate(validateTime); mEditor->setText(LLStringExplicit("12:00 AM")); addChild(mEditor); @@ -247,15 +277,6 @@ void LLTimeCtrl::onTextEntry(LLLineEditor* line_editor) mTime = h24 * MINUTES_PER_HOUR + m; } -bool LLTimeCtrl::isTimeStringValid(const LLWString &wstr) -{ - std::string str = wstring_to_utf8str(wstr); - - return isHoursStringValid(getHoursString(str)) && - isMinutesStringValid(getMinutesString(str)) && - isPMAMStringValid(getAMPMString(str)); -} - void LLTimeCtrl::increaseMinutes() { mTime = (mTime + mSnapToMin) % MINUTES_PER_DAY - (mTime % mSnapToMin); diff --git a/indra/llui/lltimectrl.h b/indra/llui/lltimectrl.h index b5f268c76a..1c8ac78289 100644 --- a/indra/llui/lltimectrl.h +++ b/indra/llui/lltimectrl.h @@ -60,6 +60,18 @@ public: void setTime24(F32 time); // 0.0 - 23.98(3) + static std::string getHoursString(const std::string& str); + static std::string getMinutesString(const std::string& str); + static std::string getAMPMString(const std::string& str); + + static bool isHoursStringValid(const std::string& str); + static bool isMinutesStringValid(const std::string& str); + static bool isPMAMStringValid(const std::string& str); + + static U32 parseHours(const std::string& str); + static U32 parseMinutes(const std::string& str); + static bool parseAMPM(const std::string& str); + protected: LLTimeCtrl(const Params&); friend class LLUICtrlFactory; @@ -87,8 +99,6 @@ private: void onDownBtn(); void onTextEntry(LLLineEditor* line_editor); - bool isTimeStringValid(const LLWString& wstr); - void increaseMinutes(); void increaseHours(); @@ -102,18 +112,6 @@ private: EEditingPart getEditingPart(); - static std::string getHoursString(const std::string& str); - static std::string getMinutesString(const std::string& str); - static std::string getAMPMString(const std::string& str); - - static bool isHoursStringValid(const std::string& str); - static bool isMinutesStringValid(const std::string& str); - static bool isPMAMStringValid(const std::string& str); - - static U32 parseHours(const std::string& str); - static U32 parseMinutes(const std::string& str); - static bool parseAMPM(const std::string& str); - class LLTextBox* mLabelBox; class LLLineEditor* mEditor; -- cgit v1.2.3 From 977168eda4a3ae22cdd8e50e682dd31c466f306a Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 27 Mar 2024 18:49:18 +0100 Subject: secondlife/viewer#944 Display should be consistent between llDialog text and llDialog buttons --- indra/llui/lltextbase.cpp | 3 +++ indra/llui/lltextbase.h | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index feac3400c7..a24f5e830c 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -168,6 +168,7 @@ LLTextBase::Params::Params() trusted_content("trusted_content", true), always_show_icons("always_show_icons", false), use_ellipses("use_ellipses", false), + use_emoji("use_emoji", true), use_color("use_color", true), parse_urls("parse_urls", false), force_urls_external("force_urls_external", false), @@ -227,6 +228,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mPlainText ( p.plain_text ), mWordWrap(p.wrap), mUseEllipses( p.use_ellipses ), + mUseEmoji(p.use_emoji), mUseColor(p.use_color), mParseHTML(p.parse_urls), mForceUrlsExternal(p.force_urls_external), @@ -903,6 +905,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } // Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us) + if (mUseEmoji) { LLStyleSP emoji_style; LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index d65e3bfd7c..dc2e3e7a83 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -328,6 +328,7 @@ public: plain_text, wrap, use_ellipses, + use_emoji, use_color, parse_urls, force_urls_external, @@ -407,12 +408,15 @@ public: virtual void onSpellCheckPerformed(){} // used by LLTextSegment layout code - bool getWordWrap() { return mWordWrap; } - bool getUseEllipses() { return mUseEllipses; } - bool getUseColor() { return mUseColor; } + bool getWordWrap() const { return mWordWrap; } + bool getUseEllipses() const { return mUseEllipses; } + bool getUseEmoji() const { return mUseEmoji; } + void setUseEmoji(bool value) { mUseEmoji = value; } + bool getUseColor() const { return mUseColor; } + void setUseColor(bool value) { mUseColor = value; } bool truncate(); // returns true of truncation occurred - bool isContentTrusted() {return mTrustedContent;} + bool isContentTrusted() const { return mTrustedContent; } void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; } // TODO: move into LLTextSegment? @@ -715,6 +719,7 @@ protected: bool mParseHighlights; // highlight user-defined keywords bool mWordWrap; bool mUseEllipses; + bool mUseEmoji; bool mUseColor; bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; -- cgit v1.2.3 From f382180eb584d8e8690935a63bda3039fe8bccc9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 27 Mar 2024 22:49:56 +0200 Subject: viewer#1069 Crash after getting list of notification files --- indra/llui/llnotifications.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 25062f2cad..1ccd664022 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1547,6 +1547,11 @@ bool LLNotifications::loadTemplates() // specific skin. std::vector search_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + if (search_paths.empty()) + { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LL_ERRS() << "Problem finding notifications.xml" << LL_ENDL; + } std::string base_filename = search_paths.front(); LLXMLNodePtr root; -- cgit v1.2.3 From 7719d54f4e649f2731a9d4248f2ca5f61da1320e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 25 Apr 2024 23:28:48 +0300 Subject: viewer#1308 LLFloaterView::restoreAll Crash --- indra/llui/llfloater.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 53a087eaf2..b3ccc47786 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2476,7 +2476,8 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) void LLFloaterView::restoreAll() { // make sure all subwindows aren't minimized - for (auto child : *getChildList()) + child_list_t child_list = *(getChildList()); + for (LLView* child : child_list) { LLFloater* floaterp = dynamic_cast(child); if (floaterp) -- cgit v1.2.3 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