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 c3da5bb12d1c7c173929433589a4068555791bea Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 15 May 2024 09:11:29 -0400 Subject: Manual whitespace fixes (fix_whitespace.py). --- indra/llui/llmenugl.h | 1248 ++++++------ indra/llui/lltexteditor.cpp | 4634 +++++++++++++++++++++---------------------- indra/llui/lltexteditor.h | 456 ++--- 3 files changed, 3169 insertions(+), 3169 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index fdbfb38474..e8d6043e54 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,199 +368,199 @@ 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); // Add the menu item to this menu. virtual BOOL append( LLMenuItemGL* item ); @@ -571,31 +571,31 @@ public: const LLFontGL *getFont() const { return mFont; } protected: - void createSpilloverBranch(); - void cleanupSpilloverBranch(); - - // 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(); + + // 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; @@ -603,27 +603,27 @@ protected: 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 @@ -638,61 +638,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 @@ -705,44 +705,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; }; //----------------------------------------------------------------------------- @@ -752,28 +752,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; }; @@ -786,43 +786,43 @@ 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; } // add a menu - this will create a drop down menu. virtual BOOL appendMenu(LLMenuGL *menu); private: - // rearrange the child rects so they fit the shape of the menu - // bar. - virtual void arrange( void ); + // 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; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -833,39 +833,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; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -877,26 +877,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; }; @@ -909,16 +909,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(); }; @@ -926,13 +926,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() {}; }; @@ -941,40 +941,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/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d6fc7d5377..348a4603de 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1,24 +1,24 @@ -/** +/** * @file lltexteditor.cpp * * $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,7 +32,7 @@ #include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR #include "llfontgl.h" -#include "llgl.h" // LLGLSUIDefault() +#include "llgl.h" // LLGLSUIDefault() #include "lllocalcliprect.h" #include "llrender.h" #include "llui.h" @@ -64,105 +64,105 @@ #include #include "llcombobox.h" -// +// // Globals // static LLDefaultChildRegistry::Register r("simple_text_editor"); // Compiler optimization, generate extern template template class LLTextEditor* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; // // Constants // -const S32 SPACES_PER_TAB = 4; -const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on +const S32 SPACES_PER_TAB = 4; +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on /////////////////////////////////////////////////////////////////// class LLTextEditor::TextCmdInsert : public LLTextBase::TextCmd { public: - TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment) - : TextCmd(pos, group_with_next, segment), mWString(ws) - { - } - virtual ~TextCmdInsert() {} - virtual BOOL execute( LLTextBase* editor, S32* delta ) - { - *delta = insert(editor, getPosition(), mWString ); - LLWStringUtil::truncate(mWString, *delta); - //mWString = wstring_truncate(mWString, *delta); - return (*delta != 0); - } - virtual S32 undo( LLTextBase* editor ) - { - remove(editor, getPosition(), mWString.length() ); - return getPosition(); - } - virtual S32 redo( LLTextBase* editor ) - { - insert(editor, getPosition(), mWString ); - return getPosition() + mWString.length(); - } + TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment) + : TextCmd(pos, group_with_next, segment), mWString(ws) + { + } + virtual ~TextCmdInsert() {} + virtual BOOL execute( LLTextBase* editor, S32* delta ) + { + *delta = insert(editor, getPosition(), mWString ); + LLWStringUtil::truncate(mWString, *delta); + //mWString = wstring_truncate(mWString, *delta); + return (*delta != 0); + } + virtual S32 undo( LLTextBase* editor ) + { + remove(editor, getPosition(), mWString.length() ); + return getPosition(); + } + virtual S32 redo( LLTextBase* editor ) + { + insert(editor, getPosition(), mWString ); + return getPosition() + mWString.length(); + } private: - LLWString mWString; + LLWString mWString; }; /////////////////////////////////////////////////////////////////// class LLTextEditor::TextCmdAddChar : public LLTextBase::TextCmd { public: - TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment) - : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE) - { - } - virtual void blockExtensions() - { - mBlockExtensions = TRUE; - } - virtual BOOL canExtend(S32 pos) const - { - // cannot extend text with custom segments - if (!mSegments.empty()) return FALSE; - - return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length()); - } - virtual BOOL execute( LLTextBase* editor, S32* delta ) - { - *delta = insert(editor, getPosition(), mWString); - LLWStringUtil::truncate(mWString, *delta); - //mWString = wstring_truncate(mWString, *delta); - return (*delta != 0); - } - virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta ) - { - LLWString ws; - ws += wc; - - *delta = insert(editor, pos, ws); - if( *delta > 0 ) - { - mWString += wc; - } - return (*delta != 0); - } - virtual S32 undo( LLTextBase* editor ) - { - remove(editor, getPosition(), mWString.length() ); - return getPosition(); - } - virtual S32 redo( LLTextBase* editor ) - { - insert(editor, getPosition(), mWString ); - return getPosition() + mWString.length(); - } + TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment) + : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE) + { + } + virtual void blockExtensions() + { + mBlockExtensions = TRUE; + } + virtual BOOL canExtend(S32 pos) const + { + // cannot extend text with custom segments + if (!mSegments.empty()) return FALSE; + + return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length()); + } + virtual BOOL execute( LLTextBase* editor, S32* delta ) + { + *delta = insert(editor, getPosition(), mWString); + LLWStringUtil::truncate(mWString, *delta); + //mWString = wstring_truncate(mWString, *delta); + return (*delta != 0); + } + virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta ) + { + LLWString ws; + ws += wc; + + *delta = insert(editor, pos, ws); + if( *delta > 0 ) + { + mWString += wc; + } + return (*delta != 0); + } + virtual S32 undo( LLTextBase* editor ) + { + remove(editor, getPosition(), mWString.length() ); + return getPosition(); + } + virtual S32 redo( LLTextBase* editor ) + { + insert(editor, getPosition(), mWString ); + return getPosition() + mWString.length(); + } private: - LLWString mWString; - BOOL mBlockExtensions; + LLWString mWString; + BOOL mBlockExtensions; }; @@ -171,30 +171,30 @@ private: class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd { public: - TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc) - : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {} - - virtual BOOL execute( LLTextBase* editor, S32* delta ) - { - mOldChar = editor->getWText()[getPosition()]; - overwrite(editor, getPosition(), mChar); - *delta = 0; - return TRUE; - } - virtual S32 undo( LLTextBase* editor ) - { - overwrite(editor, getPosition(), mOldChar); - return getPosition(); - } - virtual S32 redo( LLTextBase* editor ) - { - overwrite(editor, getPosition(), mChar); - return getPosition()+1; - } + TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc) + : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {} + + virtual BOOL execute( LLTextBase* editor, S32* delta ) + { + mOldChar = editor->getWText()[getPosition()]; + overwrite(editor, getPosition(), mChar); + *delta = 0; + return TRUE; + } + virtual S32 undo( LLTextBase* editor ) + { + overwrite(editor, getPosition(), mOldChar); + return getPosition(); + } + virtual S32 redo( LLTextBase* editor ) + { + overwrite(editor, getPosition(), mChar); + return getPosition()+1; + } private: - llwchar mChar; - llwchar mOldChar; + llwchar mChar; + llwchar mOldChar; }; /////////////////////////////////////////////////////////////////// @@ -202,114 +202,114 @@ private: class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd { public: - TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) : - TextCmd(pos, group_with_next), mLen(len) - { - std::swap(mSegments, segments); - } - virtual BOOL execute( LLTextBase* editor, S32* delta ) - { - mWString = editor->getWText().substr(getPosition(), mLen); - *delta = remove(editor, getPosition(), mLen ); - return (*delta != 0); - } - virtual S32 undo( LLTextBase* editor ) - { - insert(editor, getPosition(), mWString); - return getPosition() + mWString.length(); - } - virtual S32 redo( LLTextBase* editor ) - { - remove(editor, getPosition(), mLen ); - return getPosition(); - } + TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) : + TextCmd(pos, group_with_next), mLen(len) + { + std::swap(mSegments, segments); + } + virtual BOOL execute( LLTextBase* editor, S32* delta ) + { + mWString = editor->getWText().substr(getPosition(), mLen); + *delta = remove(editor, getPosition(), mLen ); + return (*delta != 0); + } + virtual S32 undo( LLTextBase* editor ) + { + insert(editor, getPosition(), mWString); + return getPosition() + mWString.length(); + } + virtual S32 redo( LLTextBase* editor ) + { + remove(editor, getPosition(), mLen ); + return getPosition(); + } private: - LLWString mWString; - S32 mLen; + LLWString mWString; + S32 mLen; }; /////////////////////////////////////////////////////////////////// LLTextEditor::Params::Params() -: default_text("default_text"), - prevalidate_callback("prevalidate_callback"), - embedded_items("embedded_items", false), - ignore_tab("ignore_tab", true), - auto_indent("auto_indent", true), - default_color("default_color"), +: default_text("default_text"), + prevalidate_callback("prevalidate_callback"), + 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), - show_context_menu("show_context_menu"), - show_emoji_helper("show_emoji_helper"), - enable_tooltip_paste("enable_tooltip_paste") + show_context_menu("show_context_menu"), + show_emoji_helper("show_emoji_helper"), + enable_tooltip_paste("enable_tooltip_paste") { - addSynonym(prevalidate_callback, "text_type"); + addSynonym(prevalidate_callback, "text_type"); } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : - LLTextBase(p), - mAutoreplaceCallback(), - mBaseDocIsPristine(TRUE), - mPristineCmd( NULL ), - mLastCmd( NULL ), - mDefaultColor( p.default_color() ), - mAutoIndent(p.auto_indent), - mCommitOnFocusLost( p.commit_on_focus_lost), - mAllowEmbeddedItems( p.embedded_items ), - mMouseDownX(0), - mMouseDownY(0), - mTabsToNextField(p.ignore_tab), - mPrevalidateFunc(p.prevalidate_callback()), - mShowContextMenu(p.show_context_menu), - mShowEmojiHelper(p.show_emoji_helper), - mEnableTooltipPaste(p.enable_tooltip_paste), - mPassDelete(FALSE), - mKeepSelectionOnReturn(false) -{ - mSourceID.generate(); - - //FIXME: use image? - LLViewBorder::Params params; - params.name = "text ed border"; - params.rect = getLocalRect(); - params.bevel_style = LLViewBorder::BEVEL_IN; - params.border_thickness = 1; - params.visible = p.border_visible; - mBorder = LLUICtrlFactory::create (params); - addChild( mBorder ); - setText(p.default_text()); - - mParseOnTheFly = TRUE; + LLTextBase(p), + mAutoreplaceCallback(), + mBaseDocIsPristine(TRUE), + mPristineCmd( NULL ), + mLastCmd( NULL ), + mDefaultColor( p.default_color() ), + mAutoIndent(p.auto_indent), + mCommitOnFocusLost( p.commit_on_focus_lost), + mAllowEmbeddedItems( p.embedded_items ), + mMouseDownX(0), + mMouseDownY(0), + mTabsToNextField(p.ignore_tab), + mPrevalidateFunc(p.prevalidate_callback()), + mShowContextMenu(p.show_context_menu), + mShowEmojiHelper(p.show_emoji_helper), + mEnableTooltipPaste(p.enable_tooltip_paste), + mPassDelete(FALSE), + mKeepSelectionOnReturn(false) +{ + mSourceID.generate(); + + //FIXME: use image? + LLViewBorder::Params params; + params.name = "text ed border"; + params.rect = getLocalRect(); + params.bevel_style = LLViewBorder::BEVEL_IN; + params.border_thickness = 1; + params.visible = p.border_visible; + mBorder = LLUICtrlFactory::create (params); + addChild( mBorder ); + setText(p.default_text()); + + mParseOnTheFly = TRUE; } void LLTextEditor::initFromParams( const LLTextEditor::Params& p) { - LLTextBase::initFromParams(p); + LLTextBase::initFromParams(p); - // HACK: text editors always need to be enabled so that we can scroll - LLView::setEnabled(true); + // HACK: text editors always need to be enabled so that we can scroll + LLView::setEnabled(true); + + if (p.commit_on_focus_lost.isProvided()) + { + mCommitOnFocusLost = p.commit_on_focus_lost; + } - if (p.commit_on_focus_lost.isProvided()) - { - mCommitOnFocusLost = p.commit_on_focus_lost; - } - - updateAllowingLanguageInput(); + updateAllowingLanguageInput(); } LLTextEditor::~LLTextEditor() { - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid - // Scrollbar is deleted by LLView - std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); - mUndoStack.clear(); - // Mark the menu as dead or its retained in memory till shutdown. - LLContextMenu* menu = static_cast(mContextMenuHandle.get()); - if(menu) - { - menu->die(); - mContextMenuHandle.markDead(); - } + // Scrollbar is deleted by LLView + std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); + mUndoStack.clear(); + // Mark the menu as dead or its retained in memory till shutdown. + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if(menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } } //////////////////////////////////////////////////////////// @@ -318,649 +318,649 @@ LLTextEditor::~LLTextEditor() void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params) { - // validate incoming text if necessary - if (mPrevalidateFunc) - { - LLWString test_text = utf8str_to_wstring(utf8str); - if (!mPrevalidateFunc(test_text)) - { - // not valid text, nothing to do - return; - } - } + // validate incoming text if necessary + if (mPrevalidateFunc) + { + LLWString test_text = utf8str_to_wstring(utf8str); + if (!mPrevalidateFunc(test_text)) + { + // not valid text, nothing to do + return; + } + } - blockUndo(); - deselect(); - - mParseOnTheFly = FALSE; - LLTextBase::setText(utf8str, input_params); - mParseOnTheFly = TRUE; + blockUndo(); + deselect(); - resetDirty(); + mParseOnTheFly = FALSE; + LLTextBase::setText(utf8str, input_params); + mParseOnTheFly = TRUE; + + resetDirty(); } void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap) { - if (search_text_in.empty()) - { - return; - } - - LLWString text = getWText(); - LLWString search_text = utf8str_to_wstring(search_text_in); - if (case_insensitive) - { - LLWStringUtil::toLower(text); - LLWStringUtil::toLower(search_text); - } - - if (mIsSelecting) - { - LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd); - - if (selected_text == search_text) - { - // We already have this word selected, we are searching for the next. - setCursorPos(mCursorPos + search_text.size()); - } - } - - S32 loc = text.find(search_text,mCursorPos); - - // If Maybe we wrapped, search again - if (wrap && (-1 == loc)) - { - loc = text.find(search_text); - } - - // If still -1, then search_text just isn't found. + if (search_text_in.empty()) + { + return; + } + + LLWString text = getWText(); + LLWString search_text = utf8str_to_wstring(search_text_in); + if (case_insensitive) + { + LLWStringUtil::toLower(text); + LLWStringUtil::toLower(search_text); + } + + if (mIsSelecting) + { + LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd); + + if (selected_text == search_text) + { + // We already have this word selected, we are searching for the next. + setCursorPos(mCursorPos + search_text.size()); + } + } + + S32 loc = text.find(search_text,mCursorPos); + + // If Maybe we wrapped, search again + if (wrap && (-1 == loc)) + { + loc = text.find(search_text); + } + + // If still -1, then search_text just isn't found. if (-1 == loc) - { - mIsSelecting = FALSE; - mSelectionEnd = 0; - mSelectionStart = 0; - return; - } + { + mIsSelecting = FALSE; + mSelectionEnd = 0; + mSelectionStart = 0; + return; + } + + setCursorPos(loc); - setCursorPos(loc); - - mIsSelecting = TRUE; - mSelectionEnd = mCursorPos; - mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); + mIsSelecting = TRUE; + mSelectionEnd = mCursorPos; + mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); } BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::string& replace_text, - BOOL case_insensitive, BOOL wrap) + BOOL case_insensitive, BOOL wrap) { - BOOL replaced = FALSE; + BOOL replaced = FALSE; - if (search_text_in.empty()) - { - return replaced; - } + if (search_text_in.empty()) + { + return replaced; + } - LLWString search_text = utf8str_to_wstring(search_text_in); - if (mIsSelecting) - { - LLWString text = getWText(); - LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd); + LLWString search_text = utf8str_to_wstring(search_text_in); + if (mIsSelecting) + { + LLWString text = getWText(); + LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd); - if (case_insensitive) - { - LLWStringUtil::toLower(selected_text); - LLWStringUtil::toLower(search_text); - } + if (case_insensitive) + { + LLWStringUtil::toLower(selected_text); + LLWStringUtil::toLower(search_text); + } - if (selected_text == search_text) - { - insertText(replace_text); - replaced = TRUE; - } - } + if (selected_text == search_text) + { + insertText(replace_text); + replaced = TRUE; + } + } - selectNext(search_text_in, case_insensitive, wrap); - return replaced; + selectNext(search_text_in, case_insensitive, wrap); + return replaced; } void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive) { - startOfDoc(); - selectNext(search_text, case_insensitive, FALSE); + startOfDoc(); + selectNext(search_text, case_insensitive, FALSE); - BOOL replaced = TRUE; - while ( replaced ) - { - replaced = replaceText(search_text,replace_text, case_insensitive, FALSE); - } + BOOL replaced = TRUE; + while ( replaced ) + { + replaced = replaceText(search_text,replace_text, case_insensitive, FALSE); + } } S32 LLTextEditor::prevWordPos(S32 cursorPos) const { - LLWString wtext(getWText()); - while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') ) - { - cursorPos--; - } - while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) - { - cursorPos--; - } - return cursorPos; + LLWString wtext(getWText()); + while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') ) + { + cursorPos--; + } + while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) + { + cursorPos--; + } + return cursorPos; } S32 LLTextEditor::nextWordPos(S32 cursorPos) const { - LLWString wtext(getWText()); - while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) - { - cursorPos++; - } - while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) - { - cursorPos++; - } - return cursorPos; + LLWString wtext(getWText()); + while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) + { + cursorPos++; + } + while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) + { + cursorPos++; + } + return cursorPos; } -const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const +const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const { - static LLPointer index_segment = new LLIndexSegment; + static LLPointer index_segment = new LLIndexSegment; - index_segment->setStart(mCursorPos); - index_segment->setEnd(mCursorPos); + index_segment->setStart(mCursorPos); + index_segment->setEnd(mCursorPos); - // find segment index at character to left of cursor (or rightmost edge of selection) - segment_set_t::const_iterator it = mSegments.lower_bound(index_segment); + // find segment index at character to left of cursor (or rightmost edge of selection) + segment_set_t::const_iterator it = mSegments.lower_bound(index_segment); - if (it != mSegments.end()) - { - return *it; - } - else - { - return LLTextSegmentPtr(); - } + if (it != mSegments.end()) + { + return *it; + } + else + { + return LLTextSegmentPtr(); + } } void LLTextEditor::getSelectedSegments(LLTextEditor::segment_vec_t& segments) const { - S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; - S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; + S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; + S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; - return getSegmentsInRange(segments, left, right, true); + return getSegmentsInRange(segments, left, right, true); } void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, S32 start, S32 end, bool include_partial) const { - segment_set_t::const_iterator first_it = getSegIterContaining(start); - segment_set_t::const_iterator end_it = getSegIterContaining(end - 1); - if (end_it != mSegments.end()) ++end_it; + segment_set_t::const_iterator first_it = getSegIterContaining(start); + segment_set_t::const_iterator end_it = getSegIterContaining(end - 1); + if (end_it != mSegments.end()) ++end_it; - for (segment_set_t::const_iterator it = first_it; it != end_it; ++it) - { - LLTextSegmentPtr segment = *it; - if (include_partial - || (segment->getStart() >= start - && segment->getEnd() <= end)) - { - segments_out.push_back(segment); - } - } + for (segment_set_t::const_iterator it = first_it; it != end_it; ++it) + { + LLTextSegmentPtr segment = *it; + if (include_partial + || (segment->getStart() >= start + && segment->getEnd() <= end)) + { + segments_out.push_back(segment); + } + } } void LLTextEditor::setShowEmojiHelper(bool show) { - if (!mShowEmojiHelper) - { - LLEmojiHelper::instance().hideHelper(this); - } + if (!mShowEmojiHelper) + { + LLEmojiHelper::instance().hideHelper(this); + } - mShowEmojiHelper = show; + mShowEmojiHelper = show; } BOOL LLTextEditor::selectionContainsLineBreaks() { - if (hasSelection()) - { - S32 left = llmin(mSelectionStart, mSelectionEnd); - S32 right = left + llabs(mSelectionStart - mSelectionEnd); + if (hasSelection()) + { + S32 left = llmin(mSelectionStart, mSelectionEnd); + S32 right = left + llabs(mSelectionStart - mSelectionEnd); - LLWString wtext = getWText(); - for( S32 i = left; i < right; i++ ) - { - if (wtext[i] == '\n') - { - return TRUE; - } - } - } - return FALSE; + LLWString wtext = getWText(); + for( S32 i = left; i < right; i++ ) + { + if (wtext[i] == '\n') + { + return TRUE; + } + } + } + return FALSE; } S32 LLTextEditor::indentLine( S32 pos, S32 spaces ) { - // Assumes that pos is at the start of the line - // spaces may be positive (indent) or negative (unindent). - // Returns the actual number of characters added or removed. - - llassert(pos >= 0); - llassert(pos <= getLength() ); - - S32 delta_spaces = 0; - - if (spaces >= 0) - { - // Indent - for(S32 i=0; i < spaces; i++) - { - delta_spaces += addChar(pos, ' '); - } - } - else - { - // Unindent - for(S32 i=0; i < -spaces; i++) - { - LLWString wtext = getWText(); - if (wtext[pos] == ' ') - { - delta_spaces += remove( pos, 1, FALSE ); - } - } - } - - return delta_spaces; + // Assumes that pos is at the start of the line + // spaces may be positive (indent) or negative (unindent). + // Returns the actual number of characters added or removed. + + llassert(pos >= 0); + llassert(pos <= getLength() ); + + S32 delta_spaces = 0; + + if (spaces >= 0) + { + // Indent + for(S32 i=0; i < spaces; i++) + { + delta_spaces += addChar(pos, ' '); + } + } + else + { + // Unindent + for(S32 i=0; i < -spaces; i++) + { + LLWString wtext = getWText(); + if (wtext[pos] == ' ') + { + delta_spaces += remove( pos, 1, FALSE ); + } + } + } + + return delta_spaces; } void LLTextEditor::indentSelectedLines( S32 spaces ) { - if( hasSelection() ) - { - LLWString text = getWText(); - S32 left = llmin( mSelectionStart, mSelectionEnd ); - S32 right = left + llabs( mSelectionStart - mSelectionEnd ); - BOOL cursor_on_right = (mSelectionEnd > mSelectionStart); - S32 cur = left; - - // Expand left to start of line - while( (cur > 0) && (text[cur] != '\n') ) - { - cur--; - } - left = cur; - if( cur > 0 ) - { - left++; - } - - // Expand right to end of line - if( text[right - 1] == '\n' ) - { - right--; - } - else - { - while( (text[right] != '\n') && (right <= getLength() ) ) - { - right++; - } - } - - // Disabling parsing on the fly to avoid updating text segments - // until all indentation commands are executed. - mParseOnTheFly = FALSE; - - // Find each start-of-line and indent it - do - { - if( text[cur] == '\n' ) - { - cur++; - } - - S32 delta_spaces = indentLine( cur, spaces ); - if( delta_spaces > 0 ) - { - cur += delta_spaces; - } - right += delta_spaces; - - text = getWText(); - - // Find the next new line - while( (cur < right) && (text[cur] != '\n') ) - { - cur++; - } - } - while( cur < right ); - - mParseOnTheFly = TRUE; - - if( (right < getLength()) && (text[right] == '\n') ) - { - right++; - } - - // Set the selection and cursor - if( cursor_on_right ) - { - mSelectionStart = left; - mSelectionEnd = right; - } - else - { - mSelectionStart = right; - mSelectionEnd = left; - } - setCursorPos(mSelectionEnd); - } + if( hasSelection() ) + { + LLWString text = getWText(); + S32 left = llmin( mSelectionStart, mSelectionEnd ); + S32 right = left + llabs( mSelectionStart - mSelectionEnd ); + BOOL cursor_on_right = (mSelectionEnd > mSelectionStart); + S32 cur = left; + + // Expand left to start of line + while( (cur > 0) && (text[cur] != '\n') ) + { + cur--; + } + left = cur; + if( cur > 0 ) + { + left++; + } + + // Expand right to end of line + if( text[right - 1] == '\n' ) + { + right--; + } + else + { + while( (text[right] != '\n') && (right <= getLength() ) ) + { + right++; + } + } + + // Disabling parsing on the fly to avoid updating text segments + // until all indentation commands are executed. + mParseOnTheFly = FALSE; + + // Find each start-of-line and indent it + do + { + if( text[cur] == '\n' ) + { + cur++; + } + + S32 delta_spaces = indentLine( cur, spaces ); + if( delta_spaces > 0 ) + { + cur += delta_spaces; + } + right += delta_spaces; + + text = getWText(); + + // Find the next new line + while( (cur < right) && (text[cur] != '\n') ) + { + cur++; + } + } + while( cur < right ); + + mParseOnTheFly = TRUE; + + if( (right < getLength()) && (text[right] == '\n') ) + { + right++; + } + + // Set the selection and cursor + if( cursor_on_right ) + { + mSelectionStart = left; + mSelectionEnd = right; + } + else + { + mSelectionStart = right; + mSelectionEnd = left; + } + setCursorPos(mSelectionEnd); + } } //virtual BOOL LLTextEditor::canSelectAll() const { - return TRUE; + return TRUE; } // virtual void LLTextEditor::selectAll() { - mSelectionStart = getLength(); - mSelectionEnd = 0; - setCursorPos(mSelectionEnd); - updatePrimary(); + mSelectionStart = getLength(); + mSelectionEnd = 0; + setCursorPos(mSelectionEnd); + updatePrimary(); } void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos) { - setCursorPos(prev_cursor_pos); - startSelection(); - setCursorPos(next_cursor_pos); - endSelection(); + setCursorPos(prev_cursor_pos); + startSelection(); + setCursorPos(next_cursor_pos); + endSelection(); } void LLTextEditor::insertEmoji(llwchar emoji) { - LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; - auto styleParams = LLStyle::Params(); - styleParams.font = LLFontGL::getFontEmoji(); - auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); - insert(mCursorPos, LLWString(1, emoji), false, segment); - setCursorPos(mCursorPos + 1); + LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; + auto styleParams = LLStyle::Params(); + styleParams.font = LLFontGL::getFontEmoji(); + auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); + insert(mCursorPos, LLWString(1, emoji), false, segment); + setCursorPos(mCursorPos + 1); } void LLTextEditor::handleEmojiCommit(llwchar emoji) { - S32 shortCodePos; - if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos)) - { - remove(shortCodePos, mCursorPos - shortCodePos, true); - setCursorPos(shortCodePos); + S32 shortCodePos; + if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos)) + { + remove(shortCodePos, mCursorPos - shortCodePos, true); + setCursorPos(shortCodePos); - insertEmoji(emoji); - } + insertEmoji(emoji); + } } BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // set focus first, in case click callbacks want to change it - // RN: do we really need to have a tab stop? - if (hasTabStop()) - { - setFocus( TRUE ); - } - - // Let scrollbar have first dibs - handled = LLTextBase::handleMouseDown(x, y, mask); - - if( !handled ) - { - if (!(mask & MASK_SHIFT)) - { - deselect(); - } - - BOOL start_select = TRUE; - if( start_select ) - { - // If we're not scrolling (handled by child), then we're selecting - if (mask & MASK_SHIFT) - { - S32 old_cursor_pos = mCursorPos; - setCursorAtLocalPos( x, y, true ); - - if (hasSelection()) - { - mSelectionEnd = mCursorPos; - } - else - { - mSelectionStart = old_cursor_pos; - mSelectionEnd = mCursorPos; - } - // assume we're starting a drag select - mIsSelecting = TRUE; - } - else - { - setCursorAtLocalPos( x, y, true ); - startSelection(); - } - } - - handled = TRUE; - } - - // Delay cursor flashing - resetCursorBlink(); - - if (handled && !gFocusMgr.getMouseCapture()) - { - gFocusMgr.setMouseCapture( this ); - } - return handled; + BOOL handled = FALSE; + + // set focus first, in case click callbacks want to change it + // RN: do we really need to have a tab stop? + if (hasTabStop()) + { + setFocus( TRUE ); + } + + // Let scrollbar have first dibs + handled = LLTextBase::handleMouseDown(x, y, mask); + + if( !handled ) + { + if (!(mask & MASK_SHIFT)) + { + deselect(); + } + + BOOL start_select = TRUE; + if( start_select ) + { + // If we're not scrolling (handled by child), then we're selecting + if (mask & MASK_SHIFT) + { + S32 old_cursor_pos = mCursorPos; + setCursorAtLocalPos( x, y, true ); + + if (hasSelection()) + { + mSelectionEnd = mCursorPos; + } + else + { + mSelectionStart = old_cursor_pos; + mSelectionEnd = mCursorPos; + } + // assume we're starting a drag select + mIsSelecting = TRUE; + } + else + { + setCursorAtLocalPos( x, y, true ); + startSelection(); + } + } + + handled = TRUE; + } + + // Delay cursor flashing + resetCursorBlink(); + + if (handled && !gFocusMgr.getMouseCapture()) + { + gFocusMgr.setMouseCapture( this ); + } + return handled; } BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (hasTabStop()) - { - setFocus(TRUE); - } + if (hasTabStop()) + { + setFocus(TRUE); + } - bool show_menu = false; + bool show_menu = false; - // Prefer editor menu if it has selection. See EXT-6806. - if (hasSelection()) - { - S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE); - if (click_pos > mSelectionStart && click_pos < mSelectionEnd) - { - show_menu = true; - } - } + // Prefer editor menu if it has selection. See EXT-6806. + if (hasSelection()) + { + S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE); + if (click_pos > mSelectionStart && click_pos < mSelectionEnd) + { + show_menu = true; + } + } - // Let segments handle the click, if nothing does, show editor menu - if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask)) - { - show_menu = true; - } + // Let segments handle the click, if nothing does, show editor menu + if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask)) + { + show_menu = true; + } - if (show_menu && getShowContextMenu()) - { - showContextMenu(x, y); - } + if (show_menu && getShowContextMenu()) + { + showContextMenu(x, y); + } - return TRUE; + return TRUE; } BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - if (hasTabStop()) - { - setFocus(TRUE); - } + if (hasTabStop()) + { + setFocus(TRUE); + } - if (!LLTextBase::handleMouseDown(x, y, mask)) - { - if( canPastePrimary() ) - { - setCursorAtLocalPos( x, y, true ); - // does not rely on focus being set - pastePrimary(); - } - } - return TRUE; + if (!LLTextBase::handleMouseDown(x, y, mask)) + { + if( canPastePrimary() ) + { + setCursorAtLocalPos( x, y, true ); + // does not rely on focus being set + pastePrimary(); + } + } + return TRUE; } BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - if(hasMouseCapture() ) - { - if( mIsSelecting ) - { - if(mScroller) - { - mScroller->autoScroll(x, y); - } - S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); - S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); - setCursorAtLocalPos( clamped_x, clamped_y, true ); - mSelectionEnd = mCursorPos; - } - LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; - getWindow()->setCursor(UI_CURSOR_IBEAM); - handled = TRUE; - } - - if( !handled ) - { - // Pass to children - handled = LLTextBase::handleHover(x, y, mask); - } - - if( handled ) - { - // Delay cursor flashing - resetCursorBlink(); - } - - if( !handled ) - { - getWindow()->setCursor(UI_CURSOR_IBEAM); - handled = TRUE; - } - - return handled; + BOOL handled = FALSE; + + if(hasMouseCapture() ) + { + if( mIsSelecting ) + { + if(mScroller) + { + mScroller->autoScroll(x, y); + } + S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); + S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); + setCursorAtLocalPos( clamped_x, clamped_y, true ); + mSelectionEnd = mCursorPos; + } + LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; + getWindow()->setCursor(UI_CURSOR_IBEAM); + handled = TRUE; + } + + if( !handled ) + { + // Pass to children + handled = LLTextBase::handleHover(x, y, mask); + } + + if( handled ) + { + // Delay cursor flashing + resetCursorBlink(); + } + + if( !handled ) + { + getWindow()->setCursor(UI_CURSOR_IBEAM); + handled = TRUE; + } + + return handled; } BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // if I'm not currently selecting text - if (!(mIsSelecting && hasMouseCapture())) - { - // let text segments handle mouse event - handled = LLTextBase::handleMouseUp(x, y, mask); - } - - if( !handled ) - { - if( mIsSelecting ) - { - if(mScroller) - { - mScroller->autoScroll(x, y); - } - S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); - S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); - setCursorAtLocalPos( clamped_x, clamped_y, true ); - endSelection(); - } - - // take selection to 'primary' clipboard - updatePrimary(); - - handled = TRUE; - } - - // Delay cursor flashing - resetCursorBlink(); - - if( hasMouseCapture() ) - { - gFocusMgr.setMouseCapture( NULL ); - - handled = TRUE; - } - - return handled; + BOOL handled = FALSE; + + // if I'm not currently selecting text + if (!(mIsSelecting && hasMouseCapture())) + { + // let text segments handle mouse event + handled = LLTextBase::handleMouseUp(x, y, mask); + } + + if( !handled ) + { + if( mIsSelecting ) + { + if(mScroller) + { + mScroller->autoScroll(x, y); + } + S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); + S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); + setCursorAtLocalPos( clamped_x, clamped_y, true ); + endSelection(); + } + + // take selection to 'primary' clipboard + updatePrimary(); + + handled = TRUE; + } + + // Delay cursor flashing + resetCursorBlink(); + + if( hasMouseCapture() ) + { + gFocusMgr.setMouseCapture( NULL ); + + handled = TRUE; + } + + return handled; } BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; + BOOL handled = FALSE; - // let scrollbar and text segments have first dibs - handled = LLTextBase::handleDoubleClick(x, y, mask); + // let scrollbar and text segments have first dibs + handled = LLTextBase::handleDoubleClick(x, y, mask); - if( !handled ) - { - setCursorAtLocalPos( x, y, false ); - deselect(); + if( !handled ) + { + setCursorAtLocalPos( x, y, false ); + deselect(); - LLWString text = getWText(); - - if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) - { - // Select word the cursor is over - while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1])) - { - if (!setCursorPos(mCursorPos - 1)) break; - } - startSelection(); + LLWString text = getWText(); - while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) - { - if (!setCursorPos(mCursorPos + 1)) break; - } - - mSelectionEnd = mCursorPos; - } - else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) ) - { - // Select the character the cursor is over - startSelection(); - setCursorPos(mCursorPos + 1); - mSelectionEnd = mCursorPos; - } + if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) + { + // Select word the cursor is over + while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1])) + { + if (!setCursorPos(mCursorPos - 1)) break; + } + startSelection(); + + while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) + { + if (!setCursorPos(mCursorPos + 1)) break; + } + + mSelectionEnd = mCursorPos; + } + else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) ) + { + // Select the character the cursor is over + startSelection(); + setCursorPos(mCursorPos + 1); + mSelectionEnd = mCursorPos; + } - // 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; + // 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 - resetCursorBlink(); + // delay cursor flashing + resetCursorBlink(); - // take selection to 'primary' clipboard - updatePrimary(); + // take selection to 'primary' clipboard + updatePrimary(); - handled = TRUE; - } + handled = TRUE; + } - return handled; + return handled; } @@ -969,228 +969,228 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) S32 LLTextEditor::execute( TextCmd* cmd ) { - if (!mReadOnly && mShowEmojiHelper) - { - // Any change to our contents should always hide the helper - LLEmojiHelper::instance().hideHelper(this); - } - - S32 delta = 0; - if( cmd->execute(this, &delta) ) - { - // Delete top of undo stack - undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); - std::for_each(mUndoStack.begin(), enditer, DeletePointer()); - mUndoStack.erase(mUndoStack.begin(), enditer); - // Push the new command is now on the top (front) of the undo stack. - mUndoStack.push_front(cmd); - mLastCmd = cmd; - - bool need_to_rollback = mPrevalidateFunc - && !mPrevalidateFunc(getViewModel()->getDisplay()); - if (need_to_rollback) - { - // get rid of this last command and clean up undo stack - undo(); - - // remove any evidence of this command from redo history - mUndoStack.pop_front(); - delete cmd; - - // failure, nothing changed - delta = 0; - } - } - else - { - // Operation failed, so don't put it on the undo stack. - delete cmd; - } - - return delta; + if (!mReadOnly && mShowEmojiHelper) + { + // Any change to our contents should always hide the helper + LLEmojiHelper::instance().hideHelper(this); + } + + S32 delta = 0; + if( cmd->execute(this, &delta) ) + { + // Delete top of undo stack + undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); + std::for_each(mUndoStack.begin(), enditer, DeletePointer()); + mUndoStack.erase(mUndoStack.begin(), enditer); + // Push the new command is now on the top (front) of the undo stack. + mUndoStack.push_front(cmd); + mLastCmd = cmd; + + bool need_to_rollback = mPrevalidateFunc + && !mPrevalidateFunc(getViewModel()->getDisplay()); + if (need_to_rollback) + { + // get rid of this last command and clean up undo stack + undo(); + + // remove any evidence of this command from redo history + mUndoStack.pop_front(); + delete cmd; + + // failure, nothing changed + delta = 0; + } + } + else + { + // Operation failed, so don't put it on the undo stack. + delete cmd; + } + + return delta; } S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment) { - return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) ); + return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) ); } S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op) { - S32 end_pos = getEditableIndex(pos + length, true); - BOOL removedChar = FALSE; + S32 end_pos = getEditableIndex(pos + length, true); + BOOL removedChar = FALSE; + + segment_vec_t segments_to_remove; + // store text segments + getSegmentsInRange(segments_to_remove, pos, pos + length, false); - segment_vec_t segments_to_remove; - // store text segments - getSegmentsInRange(segments_to_remove, pos, pos + length, false); - - if (pos <= end_pos) - { - removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) ); - } + if (pos <= end_pos) + { + removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) ); + } - return removedChar; + return removedChar; } S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc) { - if ((S32)getLength() == pos) - { - return addChar(pos, wc); - } - else - { - return execute(new TextCmdOverwriteChar(pos, FALSE, wc)); - } + if ((S32)getLength() == pos) + { + return addChar(pos, wc); + } + else + { + return execute(new TextCmdOverwriteChar(pos, FALSE, wc)); + } } // Remove a single character from the text. Tries to remove // a pseudo-tab (up to for spaces in a row) void LLTextEditor::removeCharOrTab() { - if (!getEnabled()) - { - return; - } - - if (mCursorPos > 0) - { - S32 chars_to_remove = 1; - - LLWString text = getWText(); - if (text[mCursorPos - 1] == ' ') - { - // Try to remove a "tab" - S32 offset = getLineOffsetFromDocIndex(mCursorPos); - if (offset > 0) - { - chars_to_remove = offset % SPACES_PER_TAB; - if (chars_to_remove == 0) - { - chars_to_remove = SPACES_PER_TAB; - } - - for (S32 i = 0; i < chars_to_remove; i++) - { - if (text[mCursorPos - i - 1] != ' ') - { - // Fewer than a full tab's worth of spaces, so - // just delete a single character. - chars_to_remove = 1; - break; - } - } - } - } - - for (S32 i = 0; i < chars_to_remove; i++) - { - setCursorPos(mCursorPos - 1); - remove(mCursorPos, 1, false); - } - - tryToShowEmojiHelper(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } -} + if (!getEnabled()) + { + return; + } -// Remove a single character from the text -S32 LLTextEditor::removeChar(S32 pos) -{ - return remove(pos, 1, false); + if (mCursorPos > 0) + { + S32 chars_to_remove = 1; + + LLWString text = getWText(); + if (text[mCursorPos - 1] == ' ') + { + // Try to remove a "tab" + S32 offset = getLineOffsetFromDocIndex(mCursorPos); + if (offset > 0) + { + chars_to_remove = offset % SPACES_PER_TAB; + if (chars_to_remove == 0) + { + chars_to_remove = SPACES_PER_TAB; + } + + for (S32 i = 0; i < chars_to_remove; i++) + { + if (text[mCursorPos - i - 1] != ' ') + { + // Fewer than a full tab's worth of spaces, so + // just delete a single character. + chars_to_remove = 1; + break; + } + } + } + } + + for (S32 i = 0; i < chars_to_remove; i++) + { + setCursorPos(mCursorPos - 1); + remove(mCursorPos, 1, false); + } + + tryToShowEmojiHelper(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } +} + +// Remove a single character from the text +S32 LLTextEditor::removeChar(S32 pos) +{ + return remove(pos, 1, false); } void LLTextEditor::removeChar() { - if (!getEnabled()) - { - return; - } + if (!getEnabled()) + { + return; + } - if (mCursorPos > 0) - { - setCursorPos(mCursorPos - 1); - removeChar(mCursorPos); - tryToShowEmojiHelper(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } + if (mCursorPos > 0) + { + setCursorPos(mCursorPos - 1); + removeChar(mCursorPos); + tryToShowEmojiHelper(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } } // Add a single character to the text S32 LLTextEditor::addChar(S32 pos, llwchar wc) { - if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength) - { - make_ui_sound("UISndBadKeystroke"); - return 0; - } - - if (mLastCmd && mLastCmd->canExtend(pos)) - { - S32 delta = 0; - if (mPrevalidateFunc) - { - // get a copy of current text contents - LLWString test_string(getViewModel()->getDisplay()); - - // modify text contents as if this addChar succeeded - llassert(pos <= (S32)test_string.size()); - test_string.insert(pos, 1, wc); - if (!mPrevalidateFunc( test_string)) - { - return 0; - } - } - mLastCmd->extendAndExecute(this, pos, wc, &delta); - - return delta; - } - else - { - return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); - } + if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength) + { + make_ui_sound("UISndBadKeystroke"); + return 0; + } + + if (mLastCmd && mLastCmd->canExtend(pos)) + { + S32 delta = 0; + if (mPrevalidateFunc) + { + // get a copy of current text contents + LLWString test_string(getViewModel()->getDisplay()); + + // modify text contents as if this addChar succeeded + llassert(pos <= (S32)test_string.size()); + test_string.insert(pos, 1, wc); + if (!mPrevalidateFunc( test_string)) + { + return 0; + } + } + mLastCmd->extendAndExecute(this, pos, wc, &delta); + + return delta; + } + else + { + return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); + } } void LLTextEditor::addChar(llwchar wc) { - if( !getEnabled() ) - { - return; - } - if( hasSelection() ) - { - deleteSelection(TRUE); - } - else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - removeChar(mCursorPos); - } - - setCursorPos(mCursorPos + addChar( mCursorPos, wc )); - tryToShowEmojiHelper(); - - if (!mReadOnly && mAutoreplaceCallback != NULL) - { - // autoreplace the text, if necessary - S32 replacement_start; - S32 replacement_length; - LLWString replacement_string; - S32 new_cursor_pos = mCursorPos; - mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText()); - - if (replacement_length > 0 || !replacement_string.empty()) - { - remove(replacement_start, replacement_length, true); - insert(replacement_start, replacement_string, false, LLTextSegmentPtr()); - setCursorPos(new_cursor_pos); - } - } + if( !getEnabled() ) + { + return; + } + if( hasSelection() ) + { + deleteSelection(TRUE); + } + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + removeChar(mCursorPos); + } + + setCursorPos(mCursorPos + addChar( mCursorPos, wc )); + tryToShowEmojiHelper(); + + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // autoreplace the text, if necessary + S32 replacement_start; + S32 replacement_length; + LLWString replacement_string; + S32 new_cursor_pos = mCursorPos; + mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText()); + + if (replacement_length > 0 || !replacement_string.empty()) + { + remove(replacement_start, replacement_length, true); + insert(replacement_start, replacement_string, false, LLTextSegmentPtr()); + setCursorPos(new_cursor_pos); + } + } } void LLTextEditor::showEmojiHelper() @@ -1226,792 +1226,792 @@ void LLTextEditor::tryToShowEmojiHelper() void LLTextEditor::addLineBreakChar(BOOL group_together) { - if( !getEnabled() ) - { - return; - } - if( hasSelection() ) - { - deleteSelection(TRUE); - } - else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - removeChar(mCursorPos); - } + if( !getEnabled() ) + { + return; + } + if( hasSelection() ) + { + deleteSelection(TRUE); + } + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + { + removeChar(mCursorPos); + } + + LLStyleConstSP sp(new LLStyle(LLStyle::Params())); + LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos); - LLStyleConstSP sp(new LLStyle(LLStyle::Params())); - LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos); + S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment)); - S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment)); - - setCursorPos(mCursorPos + pos); + setCursorPos(mCursorPos + pos); } BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) { - BOOL handled = FALSE; - - if( mask & MASK_SHIFT ) - { - handled = TRUE; - - switch( key ) - { - case KEY_LEFT: - if( 0 < mCursorPos ) - { - startSelection(); - setCursorPos(mCursorPos - 1); - if( mask & MASK_CONTROL ) - { - setCursorPos(prevWordPos(mCursorPos)); - } - mSelectionEnd = mCursorPos; - } - break; - - case KEY_RIGHT: - if( mCursorPos < getLength() ) - { - startSelection(); - setCursorPos(mCursorPos + 1); - if( mask & MASK_CONTROL ) - { - setCursorPos(nextWordPos(mCursorPos)); - } - mSelectionEnd = mCursorPos; - } - break; - - case KEY_UP: - startSelection(); - changeLine( -1 ); - mSelectionEnd = mCursorPos; - break; - - case KEY_PAGE_UP: - startSelection(); - changePage( -1 ); - mSelectionEnd = mCursorPos; - break; - - case KEY_HOME: - startSelection(); - if( mask & MASK_CONTROL ) - { - setCursorPos(0); - } - else - { - startOfLine(); - } - mSelectionEnd = mCursorPos; - break; - - case KEY_DOWN: - startSelection(); - changeLine( 1 ); - mSelectionEnd = mCursorPos; - break; - - case KEY_PAGE_DOWN: - startSelection(); - changePage( 1 ); - mSelectionEnd = mCursorPos; - break; - - case KEY_END: - startSelection(); - if( mask & MASK_CONTROL ) - { - setCursorPos(getLength()); - } - else - { - endOfLine(); - } - mSelectionEnd = mCursorPos; - 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 < mCursorPos ) + { + startSelection(); + setCursorPos(mCursorPos - 1); + if( mask & MASK_CONTROL ) + { + setCursorPos(prevWordPos(mCursorPos)); + } + mSelectionEnd = mCursorPos; + } + break; + + case KEY_RIGHT: + if( mCursorPos < getLength() ) + { + startSelection(); + setCursorPos(mCursorPos + 1); + if( mask & MASK_CONTROL ) + { + setCursorPos(nextWordPos(mCursorPos)); + } + mSelectionEnd = mCursorPos; + } + break; + + case KEY_UP: + startSelection(); + changeLine( -1 ); + mSelectionEnd = mCursorPos; + break; + + case KEY_PAGE_UP: + startSelection(); + changePage( -1 ); + mSelectionEnd = mCursorPos; + break; + + case KEY_HOME: + startSelection(); + if( mask & MASK_CONTROL ) + { + setCursorPos(0); + } + else + { + startOfLine(); + } + mSelectionEnd = mCursorPos; + break; + + case KEY_DOWN: + startSelection(); + changeLine( 1 ); + mSelectionEnd = mCursorPos; + break; + + case KEY_PAGE_DOWN: + startSelection(); + changePage( 1 ); + mSelectionEnd = mCursorPos; + break; + + case KEY_END: + startSelection(); + if( mask & MASK_CONTROL ) + { + setCursorPos(getLength()); + } + else + { + endOfLine(); + } + mSelectionEnd = mCursorPos; + break; + + default: + handled = FALSE; + break; + } + } + + if( handled ) + { + // take selection to 'primary' clipboard + updatePrimary(); + } + + return handled; } BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) { - BOOL handled = FALSE; - - // Ignore capslock key - if( MASK_NONE == mask ) - { - handled = TRUE; - switch( key ) - { - case KEY_UP: - changeLine( -1 ); - break; - - case KEY_PAGE_UP: - changePage( -1 ); - break; - - case KEY_HOME: - startOfLine(); - break; - - case KEY_DOWN: - changeLine( 1 ); - deselect(); - break; - - case KEY_PAGE_DOWN: - changePage( 1 ); - break; - - case KEY_END: - endOfLine(); - break; - - case KEY_LEFT: - if( hasSelection() ) - { - setCursorPos(llmin( mSelectionStart, mSelectionEnd )); - } - else - { - if( 0 < mCursorPos ) - { - setCursorPos(mCursorPos - 1); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - } - break; - - case KEY_RIGHT: - if( hasSelection() ) - { - setCursorPos(llmax( mSelectionStart, mSelectionEnd )); - } - else - { - if( mCursorPos < getLength() ) - { - setCursorPos(mCursorPos + 1); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - } - break; - - default: - handled = FALSE; - break; - } - } - - if (handled) - { - deselect(); - } - - return handled; + BOOL handled = FALSE; + + // Ignore capslock key + if( MASK_NONE == mask ) + { + handled = TRUE; + switch( key ) + { + case KEY_UP: + changeLine( -1 ); + break; + + case KEY_PAGE_UP: + changePage( -1 ); + break; + + case KEY_HOME: + startOfLine(); + break; + + case KEY_DOWN: + changeLine( 1 ); + deselect(); + break; + + case KEY_PAGE_DOWN: + changePage( 1 ); + break; + + case KEY_END: + endOfLine(); + break; + + case KEY_LEFT: + if( hasSelection() ) + { + setCursorPos(llmin( mSelectionStart, mSelectionEnd )); + } + else + { + if( 0 < mCursorPos ) + { + setCursorPos(mCursorPos - 1); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + } + break; + + case KEY_RIGHT: + if( hasSelection() ) + { + setCursorPos(llmax( mSelectionStart, mSelectionEnd )); + } + else + { + if( mCursorPos < getLength() ) + { + setCursorPos(mCursorPos + 1); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + } + break; + + default: + handled = FALSE; + break; + } + } + + if (handled) + { + deselect(); + } + + return handled; } void LLTextEditor::deleteSelection(BOOL group_with_next_op ) { - if( getEnabled() && hasSelection() ) - { - S32 pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - - remove( pos, length, group_with_next_op ); + if( getEnabled() && hasSelection() ) + { + S32 pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); - deselect(); - setCursorPos(pos); - } + remove( pos, length, group_with_next_op ); + + deselect(); + setCursorPos(pos); + } } // virtual BOOL LLTextEditor::canCut() const { - return !mReadOnly && hasSelection(); + return !mReadOnly && hasSelection(); } // cut selection to clipboard void LLTextEditor::cut() { - if( !canCut() ) - { - return; - } - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - LLClipboard::instance().copyToClipboard( getWText(), left_pos, length); - deleteSelection( FALSE ); + if( !canCut() ) + { + return; + } + S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); + LLClipboard::instance().copyToClipboard( getWText(), left_pos, length); + deleteSelection( FALSE ); - onKeyStroke(); + onKeyStroke(); } BOOL LLTextEditor::canCopy() const { - return hasSelection(); + return hasSelection(); } // copy selection to clipboard void LLTextEditor::copy() { - if( !canCopy() ) - { - return; - } - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - LLClipboard::instance().copyToClipboard(getWText(), left_pos, length); + if( !canCopy() ) + { + return; + } + S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length); } BOOL LLTextEditor::canPaste() const { - return !mReadOnly && LLClipboard::instance().isTextAvailable(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } // paste from clipboard void LLTextEditor::paste() { - bool is_primary = false; - pasteHelper(is_primary); + bool is_primary = false; + pasteHelper(is_primary); } // paste from primary void LLTextEditor::pastePrimary() { - bool is_primary = true; - pasteHelper(is_primary); + bool is_primary = true; + pasteHelper(is_primary); } // paste from primary (itsprimary==true) or clipboard (itsprimary==false) void LLTextEditor::pasteHelper(bool is_primary) { - mParseOnTheFly = FALSE; - bool can_paste_it; - if (is_primary) - { - can_paste_it = canPastePrimary(); - } - else - { - can_paste_it = canPaste(); - } + mParseOnTheFly = FALSE; + bool can_paste_it; + if (is_primary) + { + can_paste_it = canPastePrimary(); + } + else + { + can_paste_it = canPaste(); + } - if (!can_paste_it) - { - return; - } + if (!can_paste_it) + { + return; + } - LLWString paste; - LLClipboard::instance().pasteFromClipboard(paste, is_primary); + LLWString paste; + LLClipboard::instance().pasteFromClipboard(paste, is_primary); - if (paste.empty()) - { - return; - } + if (paste.empty()) + { + return; + } - // Delete any selected characters (the paste replaces them) - if( (!is_primary) && hasSelection() ) - { - deleteSelection(TRUE); - } + // Delete any selected characters (the paste replaces them) + if( (!is_primary) && hasSelection() ) + { + deleteSelection(TRUE); + } - // Clean up string (replace tabs and remove characters that our fonts don't support). - LLWString clean_string(paste); - cleanStringForPaste(clean_string); + // Clean up string (replace tabs and remove characters that our fonts don't support). + LLWString clean_string(paste); + cleanStringForPaste(clean_string); - // Insert the new text into the existing text. + // Insert the new text into the existing text. - //paste text with linebreaks. - pasteTextWithLinebreaks(clean_string); + //paste text with linebreaks. + pasteTextWithLinebreaks(clean_string); - deselect(); + deselect(); - onKeyStroke(); - mParseOnTheFly = TRUE; + onKeyStroke(); + mParseOnTheFly = TRUE; } // Clean up string (replace tabs and remove characters that our fonts don't support). void LLTextEditor::cleanStringForPaste(LLWString & clean_string) { - std::string clean_string_utf = wstring_to_utf8str(clean_string); - std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n'); - clean_string = utf8str_to_wstring(clean_string_utf); - - LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB); - if( mAllowEmbeddedItems ) - { - const llwchar LF = 10; - S32 len = clean_string.length(); - for( S32 i = 0; i < len; i++ ) - { - llwchar wc = clean_string[i]; - if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) ) - { - clean_string[i] = LL_UNKNOWN_CHAR; - } - else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR) - { - clean_string[i] = pasteEmbeddedItem(wc); - } - } - } + std::string clean_string_utf = wstring_to_utf8str(clean_string); + std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n'); + clean_string = utf8str_to_wstring(clean_string_utf); + + LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB); + if( mAllowEmbeddedItems ) + { + const llwchar LF = 10; + S32 len = clean_string.length(); + for( S32 i = 0; i < len; i++ ) + { + llwchar wc = clean_string[i]; + if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) ) + { + clean_string[i] = LL_UNKNOWN_CHAR; + } + else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR) + { + clean_string[i] = pasteEmbeddedItem(wc); + } + } + } } template <> void LLTextEditor::pasteTextWithLinebreaks(const LLWString & clean_string) { - std::basic_string::size_type start = 0; - std::basic_string::size_type pos = clean_string.find('\n',start); - - while((pos != -1) && (pos != clean_string.length() -1)) - { - if(pos!=start) - { - std::basic_string str = std::basic_string(clean_string,start,pos-start); - setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr())); - } - addLineBreakChar(TRUE); // Add a line break and group with the next addition. - - start = pos+1; - pos = clean_string.find('\n',start); - } - - if (pos != start) - { - std::basic_string str = std::basic_string(clean_string,start,clean_string.length()-start); - setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); - } - else - { - addLineBreakChar(FALSE); // Add a line break and end the grouping. - } + std::basic_string::size_type start = 0; + std::basic_string::size_type pos = clean_string.find('\n',start); + + while((pos != -1) && (pos != clean_string.length() -1)) + { + if(pos!=start) + { + std::basic_string str = std::basic_string(clean_string,start,pos-start); + setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr())); + } + addLineBreakChar(TRUE); // Add a line break and group with the next addition. + + start = pos+1; + pos = clean_string.find('\n',start); + } + + if (pos != start) + { + std::basic_string str = std::basic_string(clean_string,start,clean_string.length()-start); + setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + } + else + { + addLineBreakChar(FALSE); // Add a line break and end the grouping. + } } // copy selection to primary void LLTextEditor::copyPrimary() { - if( !canCopy() ) - { - return; - } - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - S32 length = llabs( mSelectionStart - mSelectionEnd ); - LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true); + if( !canCopy() ) + { + return; + } + S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); + S32 length = llabs( mSelectionStart - mSelectionEnd ); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true); } BOOL LLTextEditor::canPastePrimary() const { - return !mReadOnly && LLClipboard::instance().isTextAvailable(true); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLTextEditor::updatePrimary() { - if (canCopy()) - { - copyPrimary(); - } -} - -BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) -{ - BOOL handled = FALSE; - - if( mask & MASK_CONTROL ) - { - handled = TRUE; - - switch( key ) - { - case KEY_HOME: - if( mask & MASK_SHIFT ) - { - startSelection(); - setCursorPos(0); - mSelectionEnd = mCursorPos; - } - else - { - // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down - // all move the cursor as if clicking, so should deselect. - deselect(); - startOfDoc(); - } - break; - - case KEY_END: - { - if( mask & MASK_SHIFT ) - { - startSelection(); - } - else - { - // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down - // all move the cursor as if clicking, so should deselect. - deselect(); - } - endOfDoc(); - if( mask & MASK_SHIFT ) - { - mSelectionEnd = mCursorPos; - } - break; - } - - case KEY_RIGHT: - if( mCursorPos < getLength() ) - { - // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down - // all move the cursor as if clicking, so should deselect. - deselect(); - - setCursorPos(nextWordPos(mCursorPos + 1)); - } - break; - - - case KEY_LEFT: - if( mCursorPos > 0 ) - { - // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down - // all move the cursor as if clicking, so should deselect. - deselect(); - - setCursorPos(prevWordPos(mCursorPos - 1)); - } - break; - - default: - handled = FALSE; - break; - } - } - - if (handled && !gFocusMgr.getMouseCapture()) - { - updatePrimary(); - } - - return handled; -} - - -BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask) - { - BOOL handled = TRUE; - - if (mReadOnly) return FALSE; - - switch( key ) - { - case KEY_INSERT: - if (mask == MASK_NONE) - { - gKeyboard->toggleInsertMode(); - } - break; - - case KEY_BACKSPACE: - if( hasSelection() ) - { - deleteSelection(FALSE); - } - else - if( 0 < mCursorPos ) - { - removeCharOrTab(); - } - else - { - LLUI::getInstance()->reportBadKeystroke(); - } - break; - - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( hasSelection() && !mKeepSelectionOnReturn ) - { - deleteSelection(FALSE); - } - if (mAutoIndent) - { - autoIndent(); - } - } - else - { - handled = FALSE; - break; - } - break; - - case KEY_TAB: - if (mask & MASK_CONTROL) - { - handled = FALSE; - break; - } - if( hasSelection() && selectionContainsLineBreaks() ) - { - indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB ); - } - else - { - if( hasSelection() ) - { - deleteSelection(FALSE); - } - - S32 offset = getLineOffsetFromDocIndex(mCursorPos); - - S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB); - for( S32 i=0; i < spaces_needed; i++ ) - { - addChar( ' ' ); - } - } - break; - - default: - handled = FALSE; - break; - } - - if (handled) - { - onKeyStroke(); - } - return handled; + if (canCopy()) + { + copyPrimary(); + } } - -void LLTextEditor::unindentLineBeforeCloseBrace() +BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) { - if( mCursorPos >= 1 ) - { - LLWString text = getWText(); - if( ' ' == text[ mCursorPos - 1 ] ) - { - S32 line = getLineNumFromDocIndex(mCursorPos, false); - S32 line_start = getLineStart(line); + BOOL handled = FALSE; + + if( mask & MASK_CONTROL ) + { + handled = TRUE; + + switch( key ) + { + case KEY_HOME: + if( mask & MASK_SHIFT ) + { + startSelection(); + setCursorPos(0); + mSelectionEnd = mCursorPos; + } + else + { + // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down + // all move the cursor as if clicking, so should deselect. + deselect(); + startOfDoc(); + } + break; + + case KEY_END: + { + if( mask & MASK_SHIFT ) + { + startSelection(); + } + else + { + // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down + // all move the cursor as if clicking, so should deselect. + deselect(); + } + endOfDoc(); + if( mask & MASK_SHIFT ) + { + mSelectionEnd = mCursorPos; + } + break; + } + + case KEY_RIGHT: + if( mCursorPos < getLength() ) + { + // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down + // all move the cursor as if clicking, so should deselect. + deselect(); + + setCursorPos(nextWordPos(mCursorPos + 1)); + } + break; + + + case KEY_LEFT: + if( mCursorPos > 0 ) + { + // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down + // all move the cursor as if clicking, so should deselect. + deselect(); + + setCursorPos(prevWordPos(mCursorPos - 1)); + } + break; + + default: + handled = FALSE; + break; + } + } + + if (handled && !gFocusMgr.getMouseCapture()) + { + updatePrimary(); + } + + return handled; +} + + +BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask) + { + BOOL handled = TRUE; + + if (mReadOnly) return FALSE; + + switch( key ) + { + case KEY_INSERT: + if (mask == MASK_NONE) + { + gKeyboard->toggleInsertMode(); + } + break; + + case KEY_BACKSPACE: + if( hasSelection() ) + { + deleteSelection(FALSE); + } + else + if( 0 < mCursorPos ) + { + removeCharOrTab(); + } + else + { + LLUI::getInstance()->reportBadKeystroke(); + } + break; + + + case KEY_RETURN: + if (mask == MASK_NONE) + { + if( hasSelection() && !mKeepSelectionOnReturn ) + { + deleteSelection(FALSE); + } + if (mAutoIndent) + { + autoIndent(); + } + } + else + { + handled = FALSE; + break; + } + break; + + case KEY_TAB: + if (mask & MASK_CONTROL) + { + handled = FALSE; + break; + } + if( hasSelection() && selectionContainsLineBreaks() ) + { + indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB ); + } + else + { + if( hasSelection() ) + { + deleteSelection(FALSE); + } + + S32 offset = getLineOffsetFromDocIndex(mCursorPos); + + S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB); + for( S32 i=0; i < spaces_needed; i++ ) + { + addChar( ' ' ); + } + } + break; - // Jump over spaces in the current line - while ((' ' == text[line_start]) && (line_start < mCursorPos)) - { - line_start++; - } + default: + handled = FALSE; + break; + } - // Make sure there is nothing but ' ' before the Brace we are unindenting - if (line_start == mCursorPos) - { - removeCharOrTab(); - } - } - } + if (handled) + { + onKeyStroke(); + } + return handled; +} + + +void LLTextEditor::unindentLineBeforeCloseBrace() +{ + if( mCursorPos >= 1 ) + { + LLWString text = getWText(); + if( ' ' == text[ mCursorPos - 1 ] ) + { + S32 line = getLineNumFromDocIndex(mCursorPos, false); + S32 line_start = getLineStart(line); + + // Jump over spaces in the current line + while ((' ' == text[line_start]) && (line_start < mCursorPos)) + { + line_start++; + } + + // Make sure there is nothing but ' ' before the Brace we are unindenting + if (line_start == mCursorPos) + { + removeCharOrTab(); + } + } + } } BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) { - BOOL handled = FALSE; - - // Special case for TAB. If want to move to next field, report - // not handled and let the parent take care of field movement. - if (KEY_TAB == key && mTabsToNextField) - { - return FALSE; - } - - if (mReadOnly && mScroller) - { - handled = (mScroller && mScroller->handleKeyHere( key, mask )) - || handleSelectionKey(key, mask) - || handleControlKey(key, mask); - } - else - { - if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) - { - return TRUE; - } - - if (mEnableTooltipPaste && - LLToolTipMgr::instance().toolTipVisible() && + BOOL handled = FALSE; + + // Special case for TAB. If want to move to next field, report + // not handled and let the parent take care of field movement. + if (KEY_TAB == key && mTabsToNextField) + { + return FALSE; + } + + if (mReadOnly && mScroller) + { + handled = (mScroller && mScroller->handleKeyHere( key, mask )) + || handleSelectionKey(key, mask) + || handleControlKey(key, mask); + } + else + { + if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) + { + return TRUE; + } + + if (mEnableTooltipPaste && + LLToolTipMgr::instance().toolTipVisible() && LLToolTipMgr::instance().isTooltipPastable() && - KEY_TAB == key) - { // Paste the first line of a tooltip into the editor - std::string message; - LLToolTipMgr::instance().getToolTipMessage(message); - LLWString tool_tip_text(utf8str_to_wstring(message)); - - if (tool_tip_text.size() > 0) - { - // Delete any selected characters (the tooltip text replaces them) - if(hasSelection()) - { - deleteSelection(TRUE); - } - - std::basic_string::size_type pos = tool_tip_text.find('\n',0); - if (pos != -1) - { // Extract the first line of the tooltip - tool_tip_text = std::basic_string(tool_tip_text, 0, pos); - } - - // Add the text - cleanStringForPaste(tool_tip_text); - pasteTextWithLinebreaks(tool_tip_text); - handled = TRUE; - } - } - else - { // Normal key handling - handled = handleNavigationKey( key, mask ) - || handleSelectionKey(key, mask) - || handleControlKey(key, mask) - || handleSpecialKey(key, mask); - } - } - - if( handled ) - { - resetCursorBlink(); - needsScroll(); - - if (mShowEmojiHelper) - { - // Dismiss the helper whenever we handled a key that it didn't - LLEmojiHelper::instance().hideHelper(this); - } - } - - return handled; + KEY_TAB == key) + { // Paste the first line of a tooltip into the editor + std::string message; + LLToolTipMgr::instance().getToolTipMessage(message); + LLWString tool_tip_text(utf8str_to_wstring(message)); + + if (tool_tip_text.size() > 0) + { + // Delete any selected characters (the tooltip text replaces them) + if(hasSelection()) + { + deleteSelection(TRUE); + } + + std::basic_string::size_type pos = tool_tip_text.find('\n',0); + if (pos != -1) + { // Extract the first line of the tooltip + tool_tip_text = std::basic_string(tool_tip_text, 0, pos); + } + + // Add the text + cleanStringForPaste(tool_tip_text); + pasteTextWithLinebreaks(tool_tip_text); + handled = TRUE; + } + } + else + { // Normal key handling + handled = handleNavigationKey( key, mask ) + || handleSelectionKey(key, mask) + || handleControlKey(key, mask) + || handleSpecialKey(key, mask); + } + } + + if( handled ) + { + resetCursorBlink(); + needsScroll(); + + if (mShowEmojiHelper) + { + // Dismiss the helper whenever we handled a key that it didn't + LLEmojiHelper::instance().hideHelper(this); + } + } + + return handled; } BOOL LLTextEditor::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; - // Handle most keys only if the text editor is writeable. - if( !mReadOnly ) - { + // Handle most keys only if the text editor is writeable. + if( !mReadOnly ) + { if (mShowEmojiHelper && uni_char < 0x80 && LLEmojiHelper::instance().handleKey(this, (KEY)uni_char, MASK_NONE)) { return TRUE; } if( mAutoIndent && '}' == uni_char ) - { - unindentLineBeforeCloseBrace(); - } + { + unindentLineBeforeCloseBrace(); + } - // TODO: KLW Add auto show of tool tip on ( - addChar( uni_char ); + // TODO: KLW Add auto show of tool tip on ( + addChar( uni_char ); - // Keys that add characters temporarily hide the cursor - getWindow()->hideCursorUntilMouseMove(); + // Keys that add characters temporarily hide the cursor + getWindow()->hideCursorUntilMouseMove(); - handled = TRUE; - } + handled = TRUE; + } - if( handled ) - { - resetCursorBlink(); + if( handled ) + { + resetCursorBlink(); - // Most keystrokes will make the selection box go away, but not all will. - deselect(); + // Most keystrokes will make the selection box go away, but not all will. + deselect(); - onKeyStroke(); - } + onKeyStroke(); + } - return handled; + return handled; } // virtual BOOL LLTextEditor::canDoDelete() const { - return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) ); + return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) ); } void LLTextEditor::doDelete() { - if( !canDoDelete() ) - { - return; - } - if( hasSelection() ) - { - deleteSelection(FALSE); - } - else - if( mCursorPos < getLength() ) - { - S32 i; - S32 chars_to_remove = 1; - LLWString text = getWText(); - if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) ) - { - // Try to remove a full tab's worth of spaces - S32 offset = getLineOffsetFromDocIndex(mCursorPos); - chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB); - if( chars_to_remove == 0 ) - { - chars_to_remove = SPACES_PER_TAB; - } - - for( i = 0; i < chars_to_remove; i++ ) - { - if( text[mCursorPos + i] != ' ' ) - { - chars_to_remove = 1; - break; - } - } - } - - for( i = 0; i < chars_to_remove; i++ ) - { - setCursorPos(mCursorPos + 1); - removeChar(); - } - - } - - onKeyStroke(); + if( !canDoDelete() ) + { + return; + } + if( hasSelection() ) + { + deleteSelection(FALSE); + } + else + if( mCursorPos < getLength() ) + { + S32 i; + S32 chars_to_remove = 1; + LLWString text = getWText(); + if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) ) + { + // Try to remove a full tab's worth of spaces + S32 offset = getLineOffsetFromDocIndex(mCursorPos); + chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB); + if( chars_to_remove == 0 ) + { + chars_to_remove = SPACES_PER_TAB; + } + + for( i = 0; i < chars_to_remove; i++ ) + { + if( text[mCursorPos + i] != ' ' ) + { + chars_to_remove = 1; + break; + } + } + } + + for( i = 0; i < chars_to_remove; i++ ) + { + setCursorPos(mCursorPos + 1); + removeChar(); + } + + } + + onKeyStroke(); } //---------------------------------------------------------------------------- @@ -2019,624 +2019,624 @@ void LLTextEditor::doDelete() void LLTextEditor::blockUndo() { - mBaseDocIsPristine = FALSE; - mLastCmd = NULL; - std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); - mUndoStack.clear(); + mBaseDocIsPristine = FALSE; + mLastCmd = NULL; + std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); + mUndoStack.clear(); } // virtual BOOL LLTextEditor::canUndo() const { - return !mReadOnly && mLastCmd != NULL; + return !mReadOnly && mLastCmd != NULL; } void LLTextEditor::undo() { - if( !canUndo() ) - { - return; - } - deselect(); - S32 pos = 0; - do - { - pos = mLastCmd->undo(this); - undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); - if (iter != mUndoStack.end()) - ++iter; - if (iter != mUndoStack.end()) - mLastCmd = *iter; - else - mLastCmd = NULL; + if( !canUndo() ) + { + return; + } + deselect(); + S32 pos = 0; + do + { + pos = mLastCmd->undo(this); + undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); + if (iter != mUndoStack.end()) + ++iter; + if (iter != mUndoStack.end()) + mLastCmd = *iter; + else + mLastCmd = NULL; - } while( mLastCmd && mLastCmd->groupWithNext() ); + } while( mLastCmd && mLastCmd->groupWithNext() ); - setCursorPos(pos); + setCursorPos(pos); - onKeyStroke(); + onKeyStroke(); } BOOL LLTextEditor::canRedo() const { - return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front()); + return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front()); } void LLTextEditor::redo() { - if( !canRedo() ) - { - return; - } - deselect(); - S32 pos = 0; - do - { - if( !mLastCmd ) - { - mLastCmd = mUndoStack.back(); - } - else - { - undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); - if (iter != mUndoStack.begin()) - mLastCmd = *(--iter); - else - mLastCmd = NULL; - } - - if( mLastCmd ) - { - pos = mLastCmd->redo(this); - } - } while( - mLastCmd && - mLastCmd->groupWithNext() && - (mLastCmd != mUndoStack.front()) ); - - setCursorPos(pos); - - onKeyStroke(); + if( !canRedo() ) + { + return; + } + deselect(); + S32 pos = 0; + do + { + if( !mLastCmd ) + { + mLastCmd = mUndoStack.back(); + } + else + { + undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd); + if (iter != mUndoStack.begin()) + mLastCmd = *(--iter); + else + mLastCmd = NULL; + } + + if( mLastCmd ) + { + pos = mLastCmd->redo(this); + } + } while( + mLastCmd && + mLastCmd->groupWithNext() && + (mLastCmd != mUndoStack.front()) ); + + setCursorPos(pos); + + onKeyStroke(); } void LLTextEditor::onFocusReceived() { - LLTextBase::onFocusReceived(); - updateAllowingLanguageInput(); + LLTextBase::onFocusReceived(); + updateAllowingLanguageInput(); } void LLTextEditor::focusLostHelper() { - updateAllowingLanguageInput(); + updateAllowingLanguageInput(); - // Route menu back to the default - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } + // Route menu back to the default + if( gEditMenuHandler == this ) + { + gEditMenuHandler = NULL; + } - if (mCommitOnFocusLost) - { - onCommit(); - } + if (mCommitOnFocusLost) + { + onCommit(); + } - // Make sure cursor is shown again - getWindow()->showCursorFromMouseMove(); + // Make sure cursor is shown again + getWindow()->showCursorFromMouseMove(); } void LLTextEditor::onFocusLost() { - focusLostHelper(); - LLTextBase::onFocusLost(); + focusLostHelper(); + LLTextBase::onFocusLost(); } void LLTextEditor::onCommit() { - setControlValue(getValue()); - LLTextBase::onCommit(); + setControlValue(getValue()); + LLTextBase::onCommit(); } void LLTextEditor::setEnabled(BOOL enabled) { - // just treat enabled as read-only flag - bool read_only = !enabled; - if (read_only != mReadOnly) - { - //mReadOnly = read_only; - LLTextBase::setReadOnly(read_only); - updateSegments(); - updateAllowingLanguageInput(); - } + // just treat enabled as read-only flag + bool read_only = !enabled; + if (read_only != mReadOnly) + { + //mReadOnly = read_only; + LLTextBase::setReadOnly(read_only); + updateSegments(); + updateAllowingLanguageInput(); + } } void LLTextEditor::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()); + 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()); if(!menu) { LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL; return; } - mContextMenuHandle = menu->getHandle(); - } - - // Route menu to this class - // previously this was done in ::handleRightMoseDown: - //if(hasTabStop()) - // setFocus(TRUE) - why? weird... - // and then inside setFocus - // .... - // gEditMenuHandler = this; - // .... - // but this didn't work in all cases and just weird... - //why not here? - // (all this was done for EXT-4443) - - gEditMenuHandler = this; - - S32 screen_x, screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - - setCursorAtLocalPos(x, y, false); - if (hasSelection()) - { - if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) - { - deselect(); - } - else - { - setCursorPos(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); + mContextMenuHandle = menu->getHandle(); + } + + // Route menu to this class + // previously this was done in ::handleRightMoseDown: + //if(hasTabStop()) + // setFocus(TRUE) - why? weird... + // and then inside setFocus + // .... + // gEditMenuHandler = this; + // .... + // but this didn't work in all cases and just weird... + //why not here? + // (all this was done for EXT-4443) + + gEditMenuHandler = this; + + S32 screen_x, screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + setCursorAtLocalPos(x, y, false); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursorPos(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 LLTextEditor::drawPreeditMarker() { - 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); + 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); - if (!hasPreeditString()) - { - return; - } + if (!hasPreeditString()) + { + return; + } const LLWString textString(getWText()); - const llwchar *text = textString.c_str(); - const S32 text_len = getLength(); - const S32 num_lines = getLineCount(); - - S32 cur_line = getFirstVisibleLine(); - if (cur_line >= num_lines) - { - return; - } - - const S32 line_height = mFont->getLineHeight(); - - S32 line_start = getLineStart(cur_line); - S32 line_y = mVisibleTextRect.mTop - line_height; - while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line)) - { - S32 next_start = -1; - S32 line_end = text_len; - - if ((cur_line + 1) < num_lines) - { - next_start = getLineStart(cur_line + 1); - line_end = next_start; - } - if ( text[line_end-1] == '\n' ) - { - --line_end; - } - - // Does this line contain preedits? - if (line_start >= mPreeditPositions.back()) - { - // We have passed the preedits. - break; - } - if (line_end > mPreeditPositions.front()) - { - for (U32 i = 0; i < mPreeditStandouts.size(); i++) - { - S32 left = mPreeditPositions[i]; - S32 right = mPreeditPositions[i + 1]; - if (right <= line_start || left >= line_end) - { - continue; - } - - line_info& line = mLineInfoList[cur_line]; - LLRect text_rect(line.mRect); - text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents - text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position - - S32 preedit_left = text_rect.mLeft; - if (left > line_start) - { - preedit_left += mFont->getWidth(text, line_start, left - line_start); - } - S32 preedit_right = text_rect.mLeft; - if (right < line_end) - { - preedit_right += mFont->getWidth(text, line_start, right - line_start); - } - else - { - preedit_right += mFont->getWidth(text, line_start, line_end - line_start); - } - - if (mPreeditStandouts[i]) - { - gl_rect_2d(preedit_left + preedit_standout_gap, - text_rect.mBottom + mFont->getDescenderHeight() - 1, - preedit_right - preedit_standout_gap - 1, - text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness, - (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f)); - } - else - { - gl_rect_2d(preedit_left + preedit_marker_gap, - text_rect.mBottom + mFont->getDescenderHeight() - 1, - preedit_right - preedit_marker_gap - 1, - text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness, - (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f)); - } - } - } - - // move down one line - line_y -= line_height; - line_start = next_start; - cur_line++; - } + const llwchar *text = textString.c_str(); + const S32 text_len = getLength(); + const S32 num_lines = getLineCount(); + + S32 cur_line = getFirstVisibleLine(); + if (cur_line >= num_lines) + { + return; + } + + const S32 line_height = mFont->getLineHeight(); + + S32 line_start = getLineStart(cur_line); + S32 line_y = mVisibleTextRect.mTop - line_height; + while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line)) + { + S32 next_start = -1; + S32 line_end = text_len; + + if ((cur_line + 1) < num_lines) + { + next_start = getLineStart(cur_line + 1); + line_end = next_start; + } + if ( text[line_end-1] == '\n' ) + { + --line_end; + } + + // Does this line contain preedits? + if (line_start >= mPreeditPositions.back()) + { + // We have passed the preedits. + break; + } + if (line_end > mPreeditPositions.front()) + { + for (U32 i = 0; i < mPreeditStandouts.size(); i++) + { + S32 left = mPreeditPositions[i]; + S32 right = mPreeditPositions[i + 1]; + if (right <= line_start || left >= line_end) + { + continue; + } + + line_info& line = mLineInfoList[cur_line]; + LLRect text_rect(line.mRect); + text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents + text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position + + S32 preedit_left = text_rect.mLeft; + if (left > line_start) + { + preedit_left += mFont->getWidth(text, line_start, left - line_start); + } + S32 preedit_right = text_rect.mLeft; + if (right < line_end) + { + preedit_right += mFont->getWidth(text, line_start, right - line_start); + } + else + { + preedit_right += mFont->getWidth(text, line_start, line_end - line_start); + } + + if (mPreeditStandouts[i]) + { + gl_rect_2d(preedit_left + preedit_standout_gap, + text_rect.mBottom + mFont->getDescenderHeight() - 1, + preedit_right - preedit_standout_gap - 1, + text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness, + (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f)); + } + else + { + gl_rect_2d(preedit_left + preedit_marker_gap, + text_rect.mBottom + mFont->getDescenderHeight() - 1, + preedit_right - preedit_marker_gap - 1, + text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness, + (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f)); + } + } + } + + // move down one line + line_y -= line_height; + line_start = next_start; + cur_line++; + } } void LLTextEditor::draw() { - { - // pad clipping rectangle so that cursor can draw at full width - // when at left edge of mVisibleTextRect - LLRect clip_rect(mVisibleTextRect); - clip_rect.stretch(1); - LLLocalClipRect clip(clip_rect); - } + { + // pad clipping rectangle so that cursor can draw at full width + // when at left edge of mVisibleTextRect + LLRect clip_rect(mVisibleTextRect); + clip_rect.stretch(1); + LLLocalClipRect clip(clip_rect); + } - LLTextBase::draw(); + LLTextBase::draw(); drawPreeditMarker(); - //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret - // when in readonly mode - mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly); + //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret + // when in readonly mode + mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly); } // Start or stop the editor from accepting text-editing keystrokes // see also LLLineEditor void LLTextEditor::setFocus( BOOL new_state ) { - BOOL old_state = hasFocus(); + BOOL old_state = hasFocus(); - // Don't change anything if the focus state didn't change - if (new_state == old_state) return; + // Don't change anything if the focus state didn't change + if (new_state == old_state) return; - // Notify early if we are losing focus. - if (!new_state) - { - getWindow()->allowLanguageTextInput(this, FALSE); - } + // Notify early if we are losing focus. + if (!new_state) + { + getWindow()->allowLanguageTextInput(this, FALSE); + } - LLTextBase::setFocus( new_state ); + LLTextBase::setFocus( new_state ); - if( new_state ) - { - // Route menu to this class - gEditMenuHandler = this; + if( new_state ) + { + // Route menu to this class + gEditMenuHandler = this; - // Don't start the cursor flashing right away - resetCursorBlink(); - } - else - { - // Route menu back to the default - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } + // Don't start the cursor flashing right away + resetCursorBlink(); + } + else + { + // Route menu back to the default + if( gEditMenuHandler == this ) + { + gEditMenuHandler = NULL; + } - endSelection(); - } + endSelection(); + } } // public void LLTextEditor::setCursorAndScrollToEnd() { - deselect(); - endOfDoc(); + deselect(); + endOfDoc(); } -void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ) -{ - *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap); - *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap); +void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ) +{ + *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap); + *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap); } void LLTextEditor::autoIndent() { - // Count the number of spaces in the current line - S32 line = getLineNumFromDocIndex(mCursorPos, false); - S32 line_start = getLineStart(line); - S32 space_count = 0; - S32 i; + // Count the number of spaces in the current line + S32 line = getLineNumFromDocIndex(mCursorPos, false); + S32 line_start = getLineStart(line); + S32 space_count = 0; + S32 i; - LLWString text = getWText(); - S32 offset = getLineOffsetFromDocIndex(mCursorPos); - while(( ' ' == text[line_start] ) && (space_count < offset)) - { - space_count++; - line_start++; - } + LLWString text = getWText(); + S32 offset = getLineOffsetFromDocIndex(mCursorPos); + while(( ' ' == text[line_start] ) && (space_count < offset)) + { + space_count++; + line_start++; + } - // If we're starting a braced section, indent one level. - if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') ) - { - space_count += SPACES_PER_TAB; - } + // If we're starting a braced section, indent one level. + if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') ) + { + space_count += SPACES_PER_TAB; + } - // Insert that number of spaces on the new line + // Insert that number of spaces on the new line - //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' ); - addLineBreakChar(); + //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' ); + addLineBreakChar(); - for( i = 0; i < space_count; i++ ) - { - addChar( ' ' ); - } + for( i = 0; i < space_count; i++ ) + { + addChar( ' ' ); + } } // Inserts new text at the cursor position void LLTextEditor::insertText(const std::string &new_text) { - BOOL enabled = getEnabled(); - setEnabled( TRUE ); + BOOL enabled = getEnabled(); + setEnabled( TRUE ); + + // Delete any selected characters (the insertion replaces them) + if( hasSelection() ) + { + deleteSelection(TRUE); + } - // Delete any selected characters (the insertion replaces them) - if( hasSelection() ) - { - deleteSelection(TRUE); - } + setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() )); - setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() )); - - setEnabled( enabled ); + setEnabled( enabled ); } void LLTextEditor::insertText(LLWString &new_text) { - BOOL enabled = getEnabled(); - setEnabled( TRUE ); + BOOL enabled = getEnabled(); + setEnabled( TRUE ); - // Delete any selected characters (the insertion replaces them) - if( hasSelection() ) - { - deleteSelection(TRUE); - } + // Delete any selected characters (the insertion replaces them) + if( hasSelection() ) + { + deleteSelection(TRUE); + } - setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() )); + setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() )); - setEnabled( enabled ); + setEnabled( enabled ); } void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo) { - // Save old state - S32 selection_start = mSelectionStart; - S32 selection_end = mSelectionEnd; - BOOL was_selecting = mIsSelecting; - S32 cursor_pos = mCursorPos; - S32 old_length = getLength(); - BOOL cursor_was_at_end = (mCursorPos == old_length); + // Save old state + S32 selection_start = mSelectionStart; + S32 selection_end = mSelectionEnd; + BOOL was_selecting = mIsSelecting; + S32 cursor_pos = mCursorPos; + S32 old_length = getLength(); + BOOL cursor_was_at_end = (mCursorPos == old_length); - deselect(); + deselect(); - setCursorPos(old_length); + setCursorPos(old_length); - LLWString widget_wide_text = utf8str_to_wstring(text); + LLWString widget_wide_text = utf8str_to_wstring(text); - LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size()); - insert(getLength(), widget_wide_text, FALSE, segment); + LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size()); + insert(getLength(), widget_wide_text, FALSE, segment); - // Set the cursor and scroll position - if( selection_start != selection_end ) - { - mSelectionStart = selection_start; - mSelectionEnd = selection_end; + // Set the cursor and scroll position + if( selection_start != selection_end ) + { + mSelectionStart = selection_start; + mSelectionEnd = selection_end; - mIsSelecting = was_selecting; - setCursorPos(cursor_pos); - } - else if( cursor_was_at_end ) - { - setCursorPos(getLength()); - } - else - { - setCursorPos(cursor_pos); - } + mIsSelecting = was_selecting; + setCursorPos(cursor_pos); + } + else if( cursor_was_at_end ) + { + setCursorPos(getLength()); + } + else + { + setCursorPos(cursor_pos); + } - if (!allow_undo) - { - blockUndo(); - } + if (!allow_undo) + { + blockUndo(); + } } void LLTextEditor::removeTextFromEnd(S32 num_chars) { - if (num_chars <= 0) return; + if (num_chars <= 0) return; - remove(getLength() - num_chars, num_chars, FALSE); + remove(getLength() - num_chars, num_chars, FALSE); - S32 len = getLength(); - setCursorPos (llclamp(mCursorPos, 0, len)); - mSelectionStart = llclamp(mSelectionStart, 0, len); - mSelectionEnd = llclamp(mSelectionEnd, 0, len); + S32 len = getLength(); + setCursorPos (llclamp(mCursorPos, 0, len)); + mSelectionStart = llclamp(mSelectionStart, 0, len); + mSelectionEnd = llclamp(mSelectionEnd, 0, len); - needsScroll(); + needsScroll(); } //---------------------------------------------------------------------------- void LLTextEditor::onSpellCheckPerformed() { - if (isPristine()) - { - mBaseDocIsPristine = FALSE; - } + if (isPristine()) + { + mBaseDocIsPristine = FALSE; + } } void LLTextEditor::makePristine() { - mPristineCmd = mLastCmd; - mBaseDocIsPristine = !mLastCmd; + mPristineCmd = mLastCmd; + mBaseDocIsPristine = !mLastCmd; - // Create a clean partition in the undo stack. We don't want a single command to extend from - // the "pre-pristine" state to the "post-pristine" state. - if( mLastCmd ) - { - mLastCmd->blockExtensions(); - } + // Create a clean partition in the undo stack. We don't want a single command to extend from + // the "pre-pristine" state to the "post-pristine" state. + if( mLastCmd ) + { + mLastCmd->blockExtensions(); + } } BOOL LLTextEditor::isPristine() const { - if( mPristineCmd ) - { - return (mPristineCmd == mLastCmd); - } - else - { - // No undo stack, so check if the version before and commands were done was the original version - return !mLastCmd && mBaseDocIsPristine; - } + if( mPristineCmd ) + { + return (mPristineCmd == mLastCmd); + } + else + { + // No undo stack, so check if the version before and commands were done was the original version + return !mLastCmd && mBaseDocIsPristine; + } } BOOL LLTextEditor::tryToRevertToPristineState() { - if( !isPristine() ) - { - deselect(); - S32 i = 0; - while( !isPristine() && canUndo() ) - { - undo(); - i--; - } - - while( !isPristine() && canRedo() ) - { - redo(); - i++; - } - - if( !isPristine() ) - { - // failed, so go back to where we started - while( i > 0 ) - { - undo(); - i--; - } - } - } - - return isPristine(); // TRUE => success + if( !isPristine() ) + { + deselect(); + S32 i = 0; + while( !isPristine() && canUndo() ) + { + undo(); + i--; + } + + while( !isPristine() && canRedo() ) + { + redo(); + i++; + } + + if( !isPristine() ) + { + // failed, so go back to where we started + while( i > 0 ) + { + undo(); + i--; + } + } + } + + return isPristine(); // TRUE => success } void LLTextEditor::updateLinkSegments() { - LLWString wtext = getWText(); - - // update any segments that contain a link - for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it) - { - LLTextSegment *segment = *it; - if (segment && segment->getStyle() && segment->getStyle()->isLink()) - { - LLStyleConstSP style = segment->getStyle(); - LLStyleSP new_style(new LLStyle(*style)); - LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart()); - - segment_set_t::const_iterator next_it = mSegments.upper_bound(segment); - LLTextSegment *next_segment = *next_it; - if (next_segment) - { - LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart()); - std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label); - LLUrlMatch match; - - if ( LLUrlRegistry::instance().findUrl(link_check, match)) - { - if(match.getQuery() == wstring_to_utf8str(next_url_label)) - { - continue; - } - } - } - - // if the link's label (what the user can edit) is a valid Url, - // then update the link's HREF to be the same as the label text. - // This lets users edit Urls in-place. - if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label)) - { - std::string new_url = wstring_to_utf8str(url_label); - LLStringUtil::trim(new_url); - new_style->setLinkHREF(new_url); - LLStyleConstSP sp(new_style); - segment->setStyle(sp); - } - } - } + LLWString wtext = getWText(); + + // update any segments that contain a link + for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it) + { + LLTextSegment *segment = *it; + if (segment && segment->getStyle() && segment->getStyle()->isLink()) + { + LLStyleConstSP style = segment->getStyle(); + LLStyleSP new_style(new LLStyle(*style)); + LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart()); + + segment_set_t::const_iterator next_it = mSegments.upper_bound(segment); + LLTextSegment *next_segment = *next_it; + if (next_segment) + { + LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart()); + std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label); + LLUrlMatch match; + + if ( LLUrlRegistry::instance().findUrl(link_check, match)) + { + if(match.getQuery() == wstring_to_utf8str(next_url_label)) + { + continue; + } + } + } + + // if the link's label (what the user can edit) is a valid Url, + // then update the link's HREF to be the same as the label text. + // This lets users edit Urls in-place. + if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label)) + { + std::string new_url = wstring_to_utf8str(url_label); + LLStringUtil::trim(new_url); + new_style->setLinkHREF(new_url); + LLStyleConstSP sp(new_style); + segment->setStyle(sp); + } + } + } } void LLTextEditor::onMouseCaptureLost() { - endSelection(); + endSelection(); } /////////////////////////////////////////////////////////////////// @@ -2644,135 +2644,135 @@ void LLTextEditor::onMouseCaptureLost() BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) { - std::istringstream instream(buffer); - - // Version 1 format: - // Linden text version 1\n - // {\n - // - // Text length \n - // (text may contain ext_char_values) - // }\n - - char tbuf[MAX_STRING]; /* Flawfinder: ignore */ - - S32 version = 0; - instream.getline(tbuf, MAX_STRING); - if( 1 != sscanf(tbuf, "Linden text version %d", &version) ) - { - LL_WARNS() << "Invalid Linden text file header " << LL_ENDL; - return FALSE; - } - - if( 1 != version ) - { - LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL; - return FALSE; - } - - instream.getline(tbuf, MAX_STRING); - if( 0 != sscanf(tbuf, "{") ) - { - LL_WARNS() << "Invalid Linden text file format" << LL_ENDL; - return FALSE; - } - - S32 text_len = 0; - instream.getline(tbuf, MAX_STRING); - if( 1 != sscanf(tbuf, "Text length %d", &text_len) ) - { - LL_WARNS() << "Invalid Linden text length field" << LL_ENDL; - return FALSE; - } - - if( text_len > mMaxTextByteLength ) - { - LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL; - return FALSE; - } - - BOOL success = TRUE; - - char* text = new char[ text_len + 1]; - if (text == NULL) - { + std::istringstream instream(buffer); + + // Version 1 format: + // Linden text version 1\n + // {\n + // + // Text length \n + // (text may contain ext_char_values) + // }\n + + char tbuf[MAX_STRING]; /* Flawfinder: ignore */ + + S32 version = 0; + instream.getline(tbuf, MAX_STRING); + if( 1 != sscanf(tbuf, "Linden text version %d", &version) ) + { + LL_WARNS() << "Invalid Linden text file header " << LL_ENDL; + return FALSE; + } + + if( 1 != version ) + { + LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL; + return FALSE; + } + + instream.getline(tbuf, MAX_STRING); + if( 0 != sscanf(tbuf, "{") ) + { + LL_WARNS() << "Invalid Linden text file format" << LL_ENDL; + return FALSE; + } + + S32 text_len = 0; + instream.getline(tbuf, MAX_STRING); + if( 1 != sscanf(tbuf, "Text length %d", &text_len) ) + { + LL_WARNS() << "Invalid Linden text length field" << LL_ENDL; + return FALSE; + } + + if( text_len > mMaxTextByteLength ) + { + LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL; + return FALSE; + } + + BOOL success = TRUE; + + char* text = new char[ text_len + 1]; + if (text == NULL) + { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS() << "Memory allocation failure." << LL_ENDL; - return FALSE; - } - instream.get(text, text_len + 1, '\0'); - text[text_len] = '\0'; - if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */ - { - LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */ - success = FALSE; - } - - instream.getline(tbuf, MAX_STRING); - if( success && (0 != sscanf(tbuf, "}")) ) - { - LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL; - success = FALSE; - } - - if( success ) - { - // Actually set the text - setText( LLStringExplicit(text) ); - } - - delete[] text; - - startOfDoc(); - deselect(); - - return success; + LL_ERRS() << "Memory allocation failure." << LL_ENDL; + return FALSE; + } + instream.get(text, text_len + 1, '\0'); + text[text_len] = '\0'; + if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */ + { + LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */ + success = FALSE; + } + + instream.getline(tbuf, MAX_STRING); + if( success && (0 != sscanf(tbuf, "}")) ) + { + LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL; + success = FALSE; + } + + if( success ) + { + // Actually set the text + setText( LLStringExplicit(text) ); + } + + delete[] text; + + startOfDoc(); + deselect(); + + return success; } BOOL LLTextEditor::exportBuffer(std::string &buffer ) { - std::ostringstream outstream(buffer); - - outstream << "Linden text version 1\n"; - outstream << "{\n"; + std::ostringstream outstream(buffer); - outstream << llformat("Text length %d\n", getLength() ); - outstream << getText(); - outstream << "}\n"; + outstream << "Linden text version 1\n"; + outstream << "{\n"; - return TRUE; + outstream << llformat("Text length %d\n", getLength() ); + outstream << getText(); + outstream << "}\n"; + + return TRUE; } void LLTextEditor::updateAllowingLanguageInput() { - LLWindow* window = getWindow(); - if (!window) - { - // test app, no window available - return; - } - if (hasFocus() && !mReadOnly) - { - window->allowLanguageTextInput(this, TRUE); - } - else - { - window->allowLanguageTextInput(this, FALSE); - } + LLWindow* window = getWindow(); + if (!window) + { + // test app, no window available + return; + } + if (hasFocus() && !mReadOnly) + { + window->allowLanguageTextInput(this, TRUE); + } + else + { + window->allowLanguageTextInput(this, FALSE); + } } // Preedit is managed off the undo/redo command stack. BOOL LLTextEditor::hasPreeditString() const { - return (mPreeditPositions.size() > 1); + return (mPreeditPositions.size() > 1); } void LLTextEditor::resetPreedit() { if (hasSelection()) { - if (hasPreeditString()) + if (hasPreeditString()) { LL_WARNS() << "Preedit and selection!" << LL_ENDL; deselect(); @@ -2782,277 +2782,277 @@ void LLTextEditor::resetPreedit() deleteSelection(TRUE); } } - if (hasPreeditString()) - { - if (hasSelection()) - { - LL_WARNS() << "Preedit and selection!" << LL_ENDL; - deselect(); - } + if (hasPreeditString()) + { + if (hasSelection()) + { + LL_WARNS() << "Preedit and selection!" << LL_ENDL; + deselect(); + } - setCursorPos(mPreeditPositions.front()); - removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos); - insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString); + setCursorPos(mPreeditPositions.front()); + removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos); + insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString); - mPreeditWString.clear(); - mPreeditOverwrittenWString.clear(); - mPreeditPositions.clear(); + mPreeditWString.clear(); + mPreeditOverwrittenWString.clear(); + mPreeditPositions.clear(); - // A call to updatePreedit should soon follow under a - // normal course of operation, so we don't need to - // maintain internal variables such as line start - // positions now. - } + // A call to updatePreedit should soon follow under a + // normal course of operation, so we don't need to + // maintain internal variables such as line start + // positions now. + } } void LLTextEditor::updatePreedit(const LLWString &preedit_string, - const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) + const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) { - // Just in case. - if (mReadOnly) - { - return; - } + // Just in case. + if (mReadOnly) + { + return; + } + + getWindow()->hideCursorUntilMouseMove(); - getWindow()->hideCursorUntilMouseMove(); + S32 insert_preedit_at = mCursorPos; - S32 insert_preedit_at = mCursorPos; + 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; - 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 = getWText().substr(insert_preedit_at, mPreeditWString.length()); + removeStringNoUndo(insert_preedit_at, mPreeditWString.length()); + } + else + { + mPreeditOverwrittenWString.clear(); + } - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) - { - mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length()); - removeStringNoUndo(insert_preedit_at, mPreeditWString.length()); - } - else - { - mPreeditOverwrittenWString.clear(); - } - - segment_vec_t segments; - //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed. - insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments); + segment_vec_t segments; + //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed. + insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments); - mPreeditStandouts = preedit_standouts; + mPreeditStandouts = preedit_standouts; - setCursorPos(insert_preedit_at + caret_position); + setCursorPos(insert_preedit_at + caret_position); - // Update of the preedit should be caused by some key strokes. - resetCursorBlink(); + // Update of the preedit should be caused by some key strokes. + resetCursorBlink(); - onKeyStroke(); + onKeyStroke(); } BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const { - if (control) - { - LLRect control_rect_screen; - localRectToScreen(mVisibleTextRect, &control_rect_screen); - LLUI::getInstance()->screenRectToGL(control_rect_screen, control); - } - - S32 preedit_left_position, preedit_right_position; - if (hasPreeditString()) - { - preedit_left_position = mPreeditPositions.front(); - preedit_right_position = mPreeditPositions.back(); - } - else - { - preedit_left_position = preedit_right_position = mCursorPos; - } - - const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos); - if (query < preedit_left_position || query > preedit_right_position) - { - return FALSE; - } - - const S32 first_visible_line = getFirstVisibleLine(); - if (query < getLineStart(first_visible_line)) - { - return FALSE; - } - - S32 current_line = first_visible_line; - S32 current_line_start, current_line_end; - for (;;) - { - current_line_start = getLineStart(current_line); - current_line_end = getLineStart(current_line + 1); - if (query >= current_line_start && query < current_line_end) - { - break; - } - if (current_line_start == current_line_end) - { - // We have reached on the last line. The query position must be here. - break; - } - current_line++; - } + if (control) + { + LLRect control_rect_screen; + localRectToScreen(mVisibleTextRect, &control_rect_screen); + LLUI::getInstance()->screenRectToGL(control_rect_screen, control); + } + + S32 preedit_left_position, preedit_right_position; + if (hasPreeditString()) + { + preedit_left_position = mPreeditPositions.front(); + preedit_right_position = mPreeditPositions.back(); + } + else + { + preedit_left_position = preedit_right_position = mCursorPos; + } + + const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos); + if (query < preedit_left_position || query > preedit_right_position) + { + return FALSE; + } + + const S32 first_visible_line = getFirstVisibleLine(); + if (query < getLineStart(first_visible_line)) + { + return FALSE; + } + + S32 current_line = first_visible_line; + S32 current_line_start, current_line_end; + for (;;) + { + current_line_start = getLineStart(current_line); + current_line_end = getLineStart(current_line + 1); + if (query >= current_line_start && query < current_line_end) + { + break; + } + if (current_line_start == current_line_end) + { + // We have reached on the last line. The query position must be here. + break; + } + current_line++; + } const LLWString textString(getWText()); - const llwchar * const text = textString.c_str(); - const S32 line_height = mFont->getLineHeight(); - - if (coord) - { - const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start); - const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; - S32 query_screen_x, query_screen_y; - localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); - LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY); - } - - if (bounds) - { - S32 preedit_left = mVisibleTextRect.mLeft; - if (preedit_left_position > current_line_start) - { - preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); - } - - S32 preedit_right = mVisibleTextRect.mLeft; - if (preedit_right_position < current_line_end) - { - preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); - } - else - { - preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start); - } - - const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height; - const S32 preedit_bottom = preedit_top - line_height; - - const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom); - LLRect preedit_rect_screen; - localRectToScreen(preedit_rect_local, &preedit_rect_screen); - LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds); - } - - return TRUE; + const llwchar * const text = textString.c_str(); + const S32 line_height = mFont->getLineHeight(); + + if (coord) + { + const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start); + const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; + S32 query_screen_x, query_screen_y; + localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); + LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY); + } + + if (bounds) + { + S32 preedit_left = mVisibleTextRect.mLeft; + if (preedit_left_position > current_line_start) + { + preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); + } + + S32 preedit_right = mVisibleTextRect.mLeft; + if (preedit_right_position < current_line_end) + { + preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); + } + else + { + preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start); + } + + const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height; + const S32 preedit_bottom = preedit_top - line_height; + + const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom); + LLRect preedit_rect_screen; + localRectToScreen(preedit_rect_local, &preedit_rect_screen); + LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds); + } + + return TRUE; } void LLTextEditor::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 LLTextEditor::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 LLTextEditor::markAsPreedit(S32 position, S32 length) { - deselect(); - setCursorPos(position); - if (hasPreeditString()) - { - LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL; - } - mPreeditWString = LLWString( getWText(), 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(); + setCursorPos(position); + if (hasPreeditString()) + { + LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL; + } + mPreeditWString = LLWString( getWText(), 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 LLTextEditor::getPreeditFontSize() const { - return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); + return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } BOOL LLTextEditor::isDirty() const { - if(mReadOnly) - { - return FALSE; - } + if(mReadOnly) + { + return FALSE; + } - if( mPristineCmd ) - { - return ( mPristineCmd == mLastCmd ); - } - else - { - return ( NULL != mLastCmd ); - } + if( mPristineCmd ) + { + return ( mPristineCmd == mLastCmd ); + } + else + { + return ( NULL != mLastCmd ); + } } void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback) { - mKeystrokeSignal.connect(callback); + mKeystrokeSignal.connect(callback); } void LLTextEditor::onKeyStroke() { - mKeystrokeSignal(this); + mKeystrokeSignal(this); - mSpellCheckStart = mSpellCheckEnd = -1; - mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + mSpellCheckStart = mSpellCheckEnd = -1; + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } //virtual void LLTextEditor::clear() { - getViewModel()->setDisplay(LLWStringUtil::null); - clearSegments(); + getViewModel()->setDisplay(LLWStringUtil::null); + clearSegments(); } bool LLTextEditor::canLoadOrSaveToFile() { - return !mReadOnly; + return !mReadOnly; } S32 LLTextEditor::spacesPerTab() { - return SPACES_PER_TAB; + return SPACES_PER_TAB; } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 658bfb9295..2bc4184ca8 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -48,316 +48,316 @@ class LLUICtrlFactory; class LLScrollContainer; class LLTextEditor : - public LLTextBase, - protected LLPreeditor + public LLTextBase, + protected LLPreeditor { public: - struct Params : public LLInitParam::Block - { - Optional default_text; - Optional prevalidate_callback; - - Optional embedded_items, - ignore_tab, - commit_on_focus_lost, - show_context_menu, - show_emoji_helper, - enable_tooltip_paste, - auto_indent; - - //colors - Optional default_color; - - Params(); - }; - - void initFromParams(const Params&); + struct Params : public LLInitParam::Block + { + Optional default_text; + Optional prevalidate_callback; + + Optional embedded_items, + ignore_tab, + commit_on_focus_lost, + show_context_menu, + show_emoji_helper, + enable_tooltip_paste, + auto_indent; + + //colors + Optional default_color; + + Params(); + }; + + void initFromParams(const Params&); protected: - LLTextEditor(const Params&); - friend class LLUICtrlFactory; + LLTextEditor(const Params&); + friend class LLUICtrlFactory; public: - // - // Constants - // - static const llwchar FIRST_EMBEDDED_CHAR = 0x100000; - static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff; - static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1; + // + // Constants + // + static const llwchar FIRST_EMBEDDED_CHAR = 0x100000; + static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff; + static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1; - virtual ~LLTextEditor(); + virtual ~LLTextEditor(); - typedef boost::signals2::signal keystroke_signal_t; + typedef boost::signals2::signal keystroke_signal_t; - void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback); + void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback); - void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} + void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} - static S32 spacesPerTab(); + static S32 spacesPerTab(); - void insertEmoji(llwchar emoji); - void handleEmojiCommit(llwchar emoji); + void insertEmoji(llwchar emoji); + void handleEmojiCommit(llwchar emoji); - // mousehandler overrides - 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 handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); - virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask); + // mousehandler overrides + 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 handleHover(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 handleKeyHere(KEY key, MASK mask ); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); + virtual BOOL handleKeyHere(KEY key, MASK mask ); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual void onMouseCaptureLost(); + virtual void onMouseCaptureLost(); - // view overrides - virtual void draw(); - virtual void onFocusReceived(); - virtual void onFocusLost(); - virtual void onCommit(); - virtual void setEnabled(BOOL enabled); + // view overrides + virtual void draw(); + virtual void onFocusReceived(); + virtual void onFocusLost(); + virtual void onCommit(); + virtual void setEnabled(BOOL enabled); - // uictrl overrides - virtual void clear(); - virtual void setFocus( BOOL b ); - virtual BOOL isDirty() const; + // uictrl overrides + virtual void clear(); + virtual void setFocus( BOOL b ); + virtual BOOL isDirty() const; - // LLEditMenuHandler interface - virtual void undo(); - virtual BOOL canUndo() const; - virtual void redo(); - virtual BOOL canRedo() const; + // LLEditMenuHandler interface + virtual void undo(); + virtual BOOL canUndo() const; + virtual void redo(); + virtual BOOL canRedo() const; - virtual void cut(); - virtual BOOL canCut() const; - virtual void copy(); - virtual BOOL canCopy() const; - virtual void paste(); - virtual BOOL canPaste() const; + virtual void cut(); + virtual BOOL canCut() const; + virtual void copy(); + virtual BOOL canCopy() const; + virtual void paste(); + virtual BOOL canPaste() const; - virtual void updatePrimary(); - virtual void copyPrimary(); - virtual void pastePrimary(); - virtual BOOL canPastePrimary() const; + virtual void updatePrimary(); + virtual void copyPrimary(); + virtual void pastePrimary(); + virtual BOOL canPastePrimary() const; - virtual void doDelete(); - virtual BOOL canDoDelete() const; - virtual void selectAll(); - virtual BOOL canSelectAll() const; + virtual void doDelete(); + virtual BOOL canDoDelete() const; + virtual void selectAll(); + virtual BOOL canSelectAll() const; - void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); + void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); - virtual bool canLoadOrSaveToFile(); + virtual bool canLoadOrSaveToFile(); - void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); - BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE); - void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive); + void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); + BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE); + void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive); - // Undo/redo stack - void blockUndo(); + // Undo/redo stack + void blockUndo(); - // Text editing - virtual void makePristine(); - BOOL isPristine() const; - BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } + // Text editing + virtual void makePristine(); + BOOL isPristine() const; + BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } - // Autoreplace (formerly part of LLLineEditor) - typedef boost::function autoreplace_callback_t; - autoreplace_callback_t mAutoreplaceCallback; - void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // Autoreplace (formerly part of LLLineEditor) + typedef boost::function autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } - /*virtual*/ void onSpellCheckPerformed(); + /*virtual*/ void onSpellCheckPerformed(); - // - // Text manipulation - // + // + // Text manipulation + // - // inserts text at cursor - void insertText(const std::string &text); - void insertText(LLWString &text); + // inserts text at cursor + void insertText(const std::string &text); + void insertText(LLWString &text); - void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); - // Non-undoable - void setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params = LLStyle::Params()); + void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); + // Non-undoable + void setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params = LLStyle::Params()); - // Removes text from the end of document - // Does not change highlight or cursor position. - void removeTextFromEnd(S32 num_chars); + // Removes text from the end of document + // Does not change highlight or cursor position. + void removeTextFromEnd(S32 num_chars); - BOOL tryToRevertToPristineState(); + BOOL tryToRevertToPristineState(); - void setCursorAndScrollToEnd(); + void setCursorAndScrollToEnd(); - void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ); + void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ); - // Hacky methods to make it into a word-wrapping, potentially scrolling, - // read-only text box. - void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; } + // Hacky methods to make it into a word-wrapping, potentially scrolling, + // read-only text box. + void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; } - // Hack to handle Notecards - virtual BOOL importBuffer(const char* buffer, S32 length ); - virtual BOOL exportBuffer(std::string& buffer ); + // Hack to handle Notecards + virtual BOOL importBuffer(const char* buffer, S32 length ); + virtual BOOL exportBuffer(std::string& buffer ); - const LLUUID& getSourceID() const { return mSourceID; } + const LLUUID& getSourceID() const { return mSourceID; } - const LLTextSegmentPtr getPreviousSegment() const; - const LLTextSegmentPtr getLastSegment() const; - void getSelectedSegments(segment_vec_t& segments) const; + const LLTextSegmentPtr getPreviousSegment() const; + const LLTextSegmentPtr getLastSegment() const; + void getSelectedSegments(segment_vec_t& segments) const; - void setShowContextMenu(bool show) { mShowContextMenu = show; } - bool getShowContextMenu() const { return mShowContextMenu; } + void setShowContextMenu(bool show) { mShowContextMenu = show; } + bool getShowContextMenu() const { return mShowContextMenu; } - void showEmojiHelper(); - void setShowEmojiHelper(bool show); - bool getShowEmojiHelper() const { return mShowEmojiHelper; } + void showEmojiHelper(); + void setShowEmojiHelper(bool show); + bool getShowEmojiHelper() const { return mShowEmojiHelper; } - void setPassDelete(BOOL b) { mPassDelete = b; } + void setPassDelete(BOOL b) { mPassDelete = b; } protected: - void showContextMenu(S32 x, S32 y); - void drawPreeditMarker(); + void showContextMenu(S32 x, S32 y); + void drawPreeditMarker(); - void assignEmbedded(const std::string &s); + void assignEmbedded(const std::string &s); - void removeCharOrTab(); + void removeCharOrTab(); - void indentSelectedLines( S32 spaces ); - S32 indentLine( S32 pos, S32 spaces ); - void unindentLineBeforeCloseBrace(); + void indentSelectedLines( S32 spaces ); + S32 indentLine( S32 pos, S32 spaces ); + void unindentLineBeforeCloseBrace(); - virtual BOOL handleSpecialKey(const KEY key, const MASK mask); - BOOL handleNavigationKey(const KEY key, const MASK mask); - BOOL handleSelectionKey(const KEY key, const MASK mask); - BOOL handleControlKey(const KEY key, const MASK mask); + virtual BOOL handleSpecialKey(const KEY key, const MASK mask); + BOOL handleNavigationKey(const KEY key, const MASK mask); + BOOL handleSelectionKey(const KEY key, const MASK mask); + BOOL handleControlKey(const KEY key, const MASK mask); - BOOL selectionContainsLineBreaks(); - void deleteSelection(BOOL transient_operation); + BOOL selectionContainsLineBreaks(); + void deleteSelection(BOOL transient_operation); - S32 prevWordPos(S32 cursorPos) const; - S32 nextWordPos(S32 cursorPos) const; + S32 prevWordPos(S32 cursorPos) const; + S32 nextWordPos(S32 cursorPos) const; - void autoIndent(); + void autoIndent(); - void findEmbeddedItemSegments(S32 start, S32 end); - void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const; + void findEmbeddedItemSegments(S32 start, S32 end); + void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const; - virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } + virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } - // Here's the method that takes and applies text commands. - S32 execute(TextCmd* cmd); + // Here's the method that takes and applies text commands. + S32 execute(TextCmd* cmd); - // Undoable operations - void addChar(llwchar c); // at mCursorPos - S32 addChar(S32 pos, llwchar wc); + // Undoable operations + void addChar(llwchar c); // at mCursorPos + S32 addChar(S32 pos, llwchar wc); public: - void addLineBreakChar(BOOL group_together = FALSE); + void addLineBreakChar(BOOL group_together = FALSE); protected: - S32 overwriteChar(S32 pos, llwchar wc); - void removeChar(); - S32 removeChar(S32 pos); - S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment); - S32 remove(S32 pos, S32 length, bool group_with_next_op); - - void tryToShowEmojiHelper(); - void focusLostHelper(); - void updateAllowingLanguageInput(); - BOOL hasPreeditString() const; - - // Overrides LLPreeditor - virtual void resetPreedit(); - virtual void updatePreedit(const LLWString &preedit_string, - const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position); - virtual void markAsPreedit(S32 position, S32 length); - virtual void getPreeditRange(S32 *position, S32 *length) const; - virtual void getSelectionRange(S32 *position, S32 *length) const; - virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const; - virtual S32 getPreeditFontSize() const; - virtual LLWString getPreeditString() const { return getWText(); } - // - // Protected data - // - // Probably deserves serious thought to hiding as many of these - // as possible behind protected accessor methods. - // - - // Use these to determine if a click on an embedded item is a drag or not. - S32 mMouseDownX; - S32 mMouseDownY; - - LLWString mPreeditWString; - LLWString mPreeditOverwrittenWString; - std::vector mPreeditPositions; - std::vector mPreeditStandouts; + S32 overwriteChar(S32 pos, llwchar wc); + void removeChar(); + S32 removeChar(S32 pos); + S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment); + S32 remove(S32 pos, S32 length, bool group_with_next_op); + + void tryToShowEmojiHelper(); + void focusLostHelper(); + void updateAllowingLanguageInput(); + BOOL hasPreeditString() const; + + // Overrides LLPreeditor + virtual void resetPreedit(); + virtual void updatePreedit(const LLWString &preedit_string, + const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position); + virtual void markAsPreedit(S32 position, S32 length); + virtual void getPreeditRange(S32 *position, S32 *length) const; + virtual void getSelectionRange(S32 *position, S32 *length) const; + virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const; + virtual S32 getPreeditFontSize() const; + virtual LLWString getPreeditString() const { return getWText(); } + // + // Protected data + // + // Probably deserves serious thought to hiding as many of these + // as possible behind protected accessor methods. + // + + // Use these to determine if a click on an embedded item is a drag or not. + S32 mMouseDownX; + S32 mMouseDownY; + + LLWString mPreeditWString; + LLWString mPreeditOverwrittenWString; + std::vector mPreeditPositions; + std::vector mPreeditStandouts; protected: - LLUIColor mDefaultColor; + LLUIColor mDefaultColor; - bool mAutoIndent; - bool mParseOnTheFly; + bool mAutoIndent; + bool mParseOnTheFly; - void updateLinkSegments(); - void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; } - class LLViewBorder* mBorder; + void updateLinkSegments(); + void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; } + class LLViewBorder* mBorder; private: - // - // Methods - // - void pasteHelper(bool is_primary); - void cleanStringForPaste(LLWString & clean_string); + // + // Methods + // + void pasteHelper(bool is_primary); + void cleanStringForPaste(LLWString & clean_string); public: - template - void pasteTextWithLinebreaks(const STRINGTYPE& clean_string) - { - pasteTextWithLinebreaks(ll_convert(clean_string)); - } - template <> - void pasteTextWithLinebreaks(const LLWString & clean_string); + template + void pasteTextWithLinebreaks(const STRINGTYPE& clean_string) + { + pasteTextWithLinebreaks(ll_convert(clean_string)); + } + template <> + void pasteTextWithLinebreaks(const LLWString & clean_string); private: - void onKeyStroke(); + void onKeyStroke(); - // Concrete TextCmd sub-classes used by the LLTextEditor base class - class TextCmdInsert; - class TextCmdAddChar; - class TextCmdOverwriteChar; - class TextCmdRemove; + // Concrete TextCmd sub-classes used by the LLTextEditor base class + class TextCmdInsert; + class TextCmdAddChar; + class TextCmdOverwriteChar; + class TextCmdRemove; - BOOL mBaseDocIsPristine; - TextCmd* mPristineCmd; + BOOL mBaseDocIsPristine; + TextCmd* mPristineCmd; - TextCmd* mLastCmd; + TextCmd* mLastCmd; - typedef std::deque undo_stack_t; - undo_stack_t mUndoStack; + typedef std::deque undo_stack_t; + undo_stack_t mUndoStack; - BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces - BOOL mCommitOnFocusLost; - BOOL mTakesFocus; + BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces + BOOL mCommitOnFocusLost; + BOOL mTakesFocus; - BOOL mAllowEmbeddedItems; - bool mShowContextMenu; - bool mShowEmojiHelper; - bool mEnableTooltipPaste; - bool mPassDelete; - bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter + BOOL mAllowEmbeddedItems; + bool mShowContextMenu; + bool mShowEmojiHelper; + bool mEnableTooltipPaste; + bool mPassDelete; + bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter - LLUUID mSourceID; + LLUUID mSourceID; - LLCoordGL mLastIMEPosition; // Last position of the IME editor + LLCoordGL mLastIMEPosition; // Last position of the IME editor - keystroke_signal_t mKeystrokeSignal; - LLTextValidate::validate_func_t mPrevalidateFunc; + keystroke_signal_t mKeystrokeSignal; + LLTextValidate::validate_func_t mPrevalidateFunc; - LLHandle mContextMenuHandle; + LLHandle mContextMenuHandle; }; // end class LLTextEditor // Build time optimization, generate once in .cpp file #ifndef LLTEXTEDITOR_CPP extern template class LLTextEditor* LLView::getChild( - const std::string& name, BOOL recurse) const; + const std::string& name, BOOL recurse) const; #endif #endif // LL_TEXTEDITOR_H -- cgit v1.2.3