diff options
Diffstat (limited to 'indra/llui')
36 files changed, 403 insertions, 409 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 2ed1082f56..cdcf780d2e 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -372,11 +372,33 @@ void LLAccordionCtrl::arrangeSinge() } else { - panel_height = expanded_height; + if(mFitParent) + { + panel_height = expanded_height; + } + else + { + if(accordion_tab->getAccordionView()) + { + panel_height = accordion_tab->getAccordionView()->getRect().getHeight() + + accordion_tab->getHeaderHeight() + 2*BORDER_MARGIN; + } + else + { + panel_height = accordion_tab->getRect().getHeight(); + } + } } + + // make sure at least header is shown + panel_height = llmax(panel_height, accordion_tab->getHeaderHeight()); + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); panel_top-=mAccordionTabs[i]->getRect().getHeight(); } + + show_hide_scrollbar(getRect().getWidth(), getRect().getHeight()); + updateLayout(getRect().getWidth(), getRect().getHeight()); } void LLAccordionCtrl::arrangeMultiple() diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index e12776f83a..0959722aa6 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -465,10 +465,11 @@ void LLAccordionCtrlTab::setHeaderVisible(bool value) reshape(getRect().getWidth(), getRect().getHeight(), FALSE); }; -//vurtual +//virtual BOOL LLAccordionCtrlTab::postBuild() { - mHeader->setVisible(mHeaderVisible); + if(mHeader) + mHeader->setVisible(mHeaderVisible); static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); @@ -504,7 +505,8 @@ BOOL LLAccordionCtrlTab::postBuild() mScrollbar->setVisible(false); } - mContainerPanel->setVisible(mDisplayChildren); + if(mContainerPanel) + mContainerPanel->setVisible(mDisplayChildren); return LLUICtrl::postBuild(); } diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 462ccc6d53..4b8b22405e 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -35,8 +35,9 @@ #include <string> #include "llrect.h" +#include "lluictrl.h" +#include "lluicolor.h" -class LLUICtrl; class LLUICtrlFactory; class LLUIImage; class LLButton; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 1d4dc35cee..33c6a8b6ac 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -824,7 +824,7 @@ void LLButton::draw() x = text_right; break; case LLFontGL::HCENTER: - x = getRect().getWidth() / 2; + x = text_left + (text_width / 2); break; case LLFontGL::LEFT: default: diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 3a8efadaa4..cc107c972d 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -495,7 +495,6 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p) params.max_length_bytes(mMaxChars); params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); - params.handle_edit_keys_directly(true); params.commit_on_focus_lost(false); params.follows.flags(FOLLOWS_ALL); params.label(mLabel); diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 832f148902..9d4e2fa495 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -248,15 +248,14 @@ void LLDragHandleTop::reshapeTitleBox() return; } const LLFontGL* font = LLFontGL::getFontSansSerif(); - S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_HPAD; - if (getMaxTitleWidth() > 0) - title_width = llmin(title_width, getMaxTitleWidth()); + S32 title_width = getRect().getWidth(); + title_width -= 2 * LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); S32 title_height = llround(font->getLineHeight()); LLRect title_rect; title_rect.setLeftTopAndSize( LEFT_PAD, getRect().getHeight() - title_vpad, - getRect().getWidth() - LEFT_PAD - RIGHT_PAD, + title_width, title_height); // calls reshape on mTitleBox diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index dc5410787b..825bc9303e 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -71,6 +71,8 @@ public: BOOL getForeground() const { return mForeground; } void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } S32 getMaxTitleWidth() const { return mMaxTitleWidth; } + void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } + LLRect getButtonsRect() { return mButtonsRect; } void setTitleVisible(BOOL visible); virtual void setTitle( const std::string& title ) = 0; @@ -88,6 +90,7 @@ protected: LLTextBox* mTitleBox; private: + LLRect mButtonsRect; S32 mDragLastScreenX; S32 mDragLastScreenY; S32 mLastMouseScreenX; diff --git a/indra/llui/lleditmenuhandler.cpp b/indra/llui/lleditmenuhandler.cpp index 821afae8fd..245bce76f5 100644 --- a/indra/llui/lleditmenuhandler.cpp +++ b/indra/llui/lleditmenuhandler.cpp @@ -37,3 +37,10 @@ /* static */ LLEditMenuHandler* LLEditMenuHandler::gEditMenuHandler = NULL; +LLEditMenuHandler::~LLEditMenuHandler() +{ + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } +} diff --git a/indra/llui/lleditmenuhandler.h b/indra/llui/lleditmenuhandler.h index 1de9c56afb..d72283cd99 100644 --- a/indra/llui/lleditmenuhandler.h +++ b/indra/llui/lleditmenuhandler.h @@ -38,7 +38,7 @@ class LLEditMenuHandler { public: // this is needed even though this is just an interface class. - virtual ~LLEditMenuHandler() {}; + virtual ~LLEditMenuHandler(); virtual void undo() {}; virtual BOOL canUndo() const { return FALSE; } diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 2e5aeec41d..35f5a6bbb9 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -243,7 +243,7 @@ LLUUID LLFlatListView::getSelectedUUID() const } } -void LLFlatListView::getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const +void LLFlatListView::getSelectedUUIDs(uuid_vec_t& selected_uuids) const { if (mSelectedItemPairs.empty()) return; @@ -558,15 +558,6 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) } break; } - case 'A': - { - if(MASK_CONTROL & mask) - { - selectAll(); - handled = TRUE; - } - break; - } default: break; } @@ -791,10 +782,15 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti return false; } -bool LLFlatListView::selectAll() +BOOL LLFlatListView::canSelectAll() const { - if (!mAllowSelection) - return false; + return !mItemPairs.empty() && mAllowSelection && mMultipleSelection; +} + +void LLFlatListView::selectAll() +{ + if (!mAllowSelection || !mMultipleSelection) + return; mSelectedItemPairs.clear(); @@ -814,8 +810,6 @@ bool LLFlatListView::selectAll() // Stretch selected item rect to ensure it won't be clipped mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); - - return true; } bool LLFlatListView::isSelected(item_pair_t* item_pair) const @@ -953,11 +947,17 @@ void LLFlatListView::getValues(std::vector<LLSD>& values) const void LLFlatListView::onFocusReceived() { mSelectedItemsBorder->setVisible(TRUE); + gEditMenuHandler = this; } // virtual void LLFlatListView::onFocusLost() { mSelectedItemsBorder->setVisible(FALSE); + // Route menu back to the default + if( gEditMenuHandler == this ) + { + gEditMenuHandler = NULL; + } } //virtual diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 92cb40332e..e3c07e811f 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -58,7 +58,7 @@ * - Order of returned selected items are not guaranteed * - The control assumes that all items being added are unique. */ -class LLFlatListView : public LLScrollContainer +class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler { public: @@ -114,8 +114,6 @@ public: Params(); }; - virtual ~LLFlatListView() { clear(); }; - /** * Connects callback to signal called when Return key is pressed. */ @@ -224,7 +222,7 @@ public: * Get LLUUIDs associated with selected items * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items */ - virtual void getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const; + virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const; /** Get the top selected item */ virtual LLPanel* getSelectedItem() const; @@ -344,7 +342,8 @@ protected: virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); - virtual bool selectAll(); + virtual BOOL canSelectAll() const; + virtual void selectAll(); virtual bool isSelected(item_pair_t* item_pair) const; @@ -379,11 +378,14 @@ private: void setNoItemsCommentVisible(bool visible) const; -private: +protected: /** Comparator to use when sorting the list. */ const ItemComparator* mItemComparator; + +private: + LLPanel* mItemsPanel; S32 mItemsNoScrollWidth; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index ab14c08948..e672252a50 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -346,7 +346,7 @@ void LLFloater::layoutDragHandle() rect = getLocalRect(); } mDragHandle->setRect(rect); - updateButtons(); + updateTitleButtons(); applyTitle(); } @@ -1061,11 +1061,10 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); } - - applyTitle (); make_ui_sound("UISndWindowClose"); - updateButtons(); + updateTitleButtons(); + applyTitle (); } void LLFloater::setFocus( BOOL b ) @@ -1121,6 +1120,7 @@ void LLFloater::setIsChrome(BOOL is_chrome) setFocus(FALSE); // can't Ctrl-Tab to "chrome" floaters setFocusRoot(FALSE); + mButtons[BUTTON_CLOSE]->setToolTip(LLStringExplicit(getButtonTooltip(Params(), BUTTON_CLOSE, is_chrome))); } // no titles displayed on "chrome" floaters @@ -1190,7 +1190,7 @@ void LLFloater::setHost(LLMultiFloater* host) mButtonScale = 1.f; //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; } - updateButtons(); + updateTitleButtons(); if (host) { mHostHandle = host->getHandle(); @@ -1389,7 +1389,7 @@ void LLFloater::setCanDock(bool b) mButtonsEnabled[BUTTON_DOCK] = FALSE; } } - updateButtons(); + updateTitleButtons(); } void LLFloater::setDocked(bool docked, bool pop_on_undock) @@ -1398,7 +1398,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) { mDocked = docked; mButtonsEnabled[BUTTON_DOCK] = !mDocked; - updateButtons(); + updateTitleButtons(); storeDockStateControl(); } @@ -1451,7 +1451,7 @@ void LLFloater::onClickTearOff(LLFloater* self) } self->setTornOff(false); } - self->updateButtons(); + self->updateTitleButtons(); } // static @@ -1691,7 +1691,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanClose(BOOL can_close) @@ -1699,7 +1699,7 @@ void LLFloater::setCanClose(BOOL can_close) mCanClose = can_close; mButtonsEnabled[BUTTON_CLOSE] = can_close; - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanTearOff(BOOL can_tear_off) @@ -1707,7 +1707,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) mCanTearOff = can_tear_off; mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead(); - updateButtons(); + updateTitleButtons(); } @@ -1731,10 +1731,11 @@ void LLFloater::setCanDrag(BOOL can_drag) } } -void LLFloater::updateButtons() +void LLFloater::updateTitleButtons() { static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0); + LLRect buttons_rect; S32 button_count = 0; for (S32 i = 0; i < BUTTON_COUNT; i++) { @@ -1785,6 +1786,15 @@ void LLFloater::updateButtons() llround((F32)floater_close_box_size * mButtonScale)); } + if(!buttons_rect.isValid()) + { + buttons_rect = btn_rect; + } + else + { + mDragOnLeft ? buttons_rect.mRight + btn_rect.mRight : + buttons_rect.mLeft = btn_rect.mLeft; + } mButtons[i]->setRect(btn_rect); mButtons[i]->setVisible(TRUE); // the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater @@ -1796,7 +1806,10 @@ void LLFloater::updateButtons() } } if (mDragHandle) - mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); + { + localRectToOtherView(buttons_rect, &buttons_rect, mDragHandle); + mDragHandle->setButtonsRect(buttons_rect); + } } void LLFloater::buildButtons(const Params& floater_params) @@ -1844,7 +1857,7 @@ void LLFloater::buildButtons(const Params& floater_params) p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); p.tab_stop(false); p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); - p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i); + p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i, getIsChrome()); p.scale_image(true); p.chrome(true); @@ -1853,7 +1866,7 @@ void LLFloater::buildButtons(const Params& floater_params) mButtons[i] = buttonp; } - updateButtons(); + updateTitleButtons(); } // static @@ -1899,8 +1912,15 @@ LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e) } // static -std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e) +std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome) { + // EXT-4081 (Lag Meter: Ctrl+W does not close floater) + // If floater is chrome set 'Close' text for close button's tooltip + if(is_chrome && BUTTON_CLOSE == e) + { + static std::string close_tooltip_chrome = LLTrans::getString("BUTTON_CLOSE_CHROME"); + return close_tooltip_chrome; + } // TODO: per-floater localizable tooltips set in XML return sButtonToolTips[e]; } @@ -2810,3 +2830,15 @@ bool LLFloater::isShown(const LLFloater* floater) { return floater && floater->isShown(); } + +/* static */ +bool LLFloater::isMinimized(const LLFloater* floater) +{ + return floater && floater->isMinimized(); +} + +/* static */ +bool LLFloater::isVisible(const LLFloater* floater) +{ + return floater && floater->getVisible(); +} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index c1e8813f87..403723d9d8 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -194,6 +194,8 @@ public: /// The static isShown() can accept a NULL pointer (which of course /// returns false). When non-NULL, it calls the non-static isShown(). static bool isShown(const LLFloater* floater); + static bool isVisible(const LLFloater* floater); + static bool isMinimized(const LLFloater* floater); BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } @@ -309,19 +311,26 @@ protected: virtual void onClickCloseBtn(); + virtual void updateTitleButtons(); + private: void setForeground(BOOL b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); - void updateButtons(); void buildButtons(const Params& p); // Images and tooltips are named in the XML, but we want to look them // up by index. static LLUIImage* getButtonImage(const Params& p, EFloaterButton e); static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e); - static std::string getButtonTooltip(const Params& p, EFloaterButton e); + /** + * @params is_chrome - if floater is Chrome it means that floater will never get focus. + * Therefore it can't be closed with 'Ctrl+W'. So the tooltip text of close button( X ) + * should be 'Close' not 'Close(Ctrl+W)' as for usual floaters. + */ + static std::string getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome); + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); void addResizeCtrls(); void layoutResizeCtrls(); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 5de3934c8a..7588d8ab7a 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -272,11 +272,11 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) } //static -// returns true if the instance exists and is visible +// returns true if the instance exists and is visible (doesnt matter minimized or not) bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key) { LLFloater* instance = findInstance(name, key); - return LLFloater::isShown(instance); + return LLFloater::isVisible(instance); } //static @@ -463,3 +463,12 @@ bool LLFloaterReg::floaterInstanceVisible(const LLSD& sdname) return instanceVisible(name, key); } +//static +bool LLFloaterReg::floaterInstanceMinimized(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + LLFloater* instance = findInstance(name, key); + return LLFloater::isShown(instance); +} diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 8a11d5c3f2..5cacf76771 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -134,6 +134,7 @@ public: static void hideFloaterInstance(const LLSD& sdname); static void toggleFloaterInstance(const LLSD& sdname); static bool floaterInstanceVisible(const LLSD& sdname); + static bool floaterInstanceMinimized(const LLSD& sdname); // Typed find / get / show template <class T> diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 483a394bbd..843f72d8e4 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -91,7 +91,6 @@ LLLineEditor::Params::Params() background_image_disabled("background_image_disabled"), background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), - handle_edit_keys_directly("handle_edit_keys_directly", false), revert_on_esc("revert_on_esc", true), commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), @@ -136,7 +135,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( FALSE ), - mHandleEditKeysDirectly(p.handle_edit_keys_directly), mSelectAllonFocusReceived( p.select_on_focus ), mPassDelete(FALSE), mReadOnly(FALSE), @@ -192,12 +190,8 @@ LLLineEditor::~LLLineEditor() { mCommitOnFocusLost = FALSE; + // calls onCommit() while LLLineEditor still valid gFocusMgr.releaseFocusIfNeeded( this ); - - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } } @@ -497,6 +491,7 @@ void LLLineEditor::selectAll() setCursor(mSelectionEnd); //mScrollHPos = 0; mIsSelecting = TRUE; + updatePrimary(); } @@ -788,7 +783,7 @@ void LLLineEditor::removeChar() } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } @@ -827,7 +822,7 @@ void LLLineEditor::addChar(const llwchar uni_char) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } getWindow()->hideCursorUntilMouseMove(); @@ -916,7 +911,7 @@ BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } break; @@ -932,7 +927,7 @@ BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } break; @@ -958,22 +953,6 @@ BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) } } - if (!handled && mHandleEditKeysDirectly) - { - if( (MASK_CONTROL & mask) && ('A' == key) ) - { - if( canSelectAll() ) - { - selectAll(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - } - if(handled) { // take selection to 'primary' clipboard @@ -1020,7 +999,7 @@ void LLLineEditor::cut() if( need_to_rollback ) { rollback.doRollback( this ); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } else if( mKeystrokeCallback ) @@ -1129,7 +1108,7 @@ void LLLineEditor::pasteHelper(bool is_primary) } // Truncate the clean string at the limit of what will fit clean_string = clean_string.substr(0, wchars_that_fit); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } mText.insert(getCursor(), clean_string); @@ -1141,7 +1120,7 @@ void LLLineEditor::pasteHelper(bool is_primary) if( need_to_rollback ) { rollback.doRollback( this ); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } else if( mKeystrokeCallback ) @@ -1206,7 +1185,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } handled = TRUE; @@ -1255,7 +1234,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } handled = TRUE; } @@ -1282,7 +1261,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } handled = TRUE; } @@ -1299,7 +1278,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } handled = TRUE; } @@ -1316,7 +1295,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } handled = TRUE; } @@ -1339,64 +1318,6 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) break; } - if( !handled && mHandleEditKeysDirectly ) - { - // Standard edit keys (Ctrl-X, Delete, etc,) are handled here instead of routed by the menu system. - if( KEY_DELETE == key ) - { - if( canDoDelete() ) - { - doDelete(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( MASK_CONTROL & mask ) - { - if( 'C' == key ) - { - if( canCopy() ) - { - copy(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( 'V' == key ) - { - if( canPaste() ) - { - paste(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( 'X' == key ) - { - if( canCut() ) - { - cut(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - } - } return handled; } @@ -1451,7 +1372,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) { rollback.doRollback(this); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } // Notify owner if requested @@ -1499,7 +1420,7 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) { rollback.doRollback( this ); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } // Notify owner if requested @@ -1544,7 +1465,7 @@ void LLLineEditor::doDelete() if( need_to_rollback ) { rollback.doRollback( this ); - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } else { @@ -1879,11 +1800,6 @@ S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const return result; } -void LLLineEditor::reportBadKeystroke() -{ - make_ui_sound("UISndBadKeystroke"); -} - //virtual void LLLineEditor::clear() { diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index b62138426b..9489e723e3 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -81,7 +81,6 @@ public: background_image_focused; Optional<bool> select_on_focus, - handle_edit_keys_directly, revert_on_esc, commit_on_focus_lost, ignore_tab; @@ -215,7 +214,6 @@ public: void extendSelection(S32 new_cursor_pos); void deleteSelection(); - void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; } void setSelectAllonFocusReceived(BOOL b); typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t; @@ -247,7 +245,6 @@ private: void addChar(const llwchar c); void setCursorAtLocalPos(S32 local_mouse_x); S32 findPixelNearestPos(S32 cursor_offset = 0) const; - void reportBadKeystroke(); BOOL handleSpecialKey(KEY key, MASK mask); BOOL handleSelectionKey(KEY key, MASK mask); BOOL handleControlKey(KEY key, MASK mask); @@ -325,7 +322,6 @@ protected: BOOL mIgnoreTab; BOOL mDrawAsterixes; - BOOL mHandleEditKeysDirectly; // If true, the standard edit keys (Ctrl-X, Delete, etc,) are handled here instead of routed by the menu system BOOL mSelectAllonFocusReceived; BOOL mPassDelete; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index fb4a9d032d..e0e86ae228 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3345,7 +3345,7 @@ void LLMenuHolderGL::draw() LLView::draw(); // now draw last selected item as overlay LLMenuItemGL* selecteditem = (LLMenuItemGL*)sItemLastSelectedHandle.get(); - if (selecteditem && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) + if (selecteditem && selecteditem->getVisible() && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) { // make sure toggle items, for example, show the proper state when fading out selecteditem->buildDrawLabel(); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 39d1986461..6f0f83d4b9 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -295,7 +295,7 @@ private: // class, by allowing another method to be specified which determines // if the menu item should consider itself checked as true or not. Be // careful that the provided callback is fast - it needs to be VERY -// FUCKING EFFICIENT, because it may need to be checked a lot. +// EFFICIENT because it may need to be checked a lot. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLMenuItemCheckGL diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 4af9108329..3aea648562 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -345,7 +345,7 @@ void LLMultiFloater::setVisible(BOOL visible) BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask) { - if (key == 'W' && mask == MASK_CONTROL) + if (key == 'W' && mask == (MASK_CONTROL|MASK_SHIFT)) { LLFloater* floater = getActiveFloater(); // is user closeable and is system closeable diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d7424cf05a..65ef53443b 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1552,3 +1552,11 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification) return s; } +void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first, + const std::string& last, bool is_group) +{ + gCacheName->getFullName(id, mName); + modifyNotificationParams(); + LLNotifications::instance().add(mParams); + cleanup(); +} diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 400491a154..1799ca65b7 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -104,6 +104,7 @@ #include "llinitparam.h" #include "llnotificationslistener.h" #include "llnotificationptr.h" +#include "llcachename.h" typedef enum e_notification_priority @@ -949,6 +950,62 @@ private: boost::scoped_ptr<LLNotificationsListener> mListener; }; +/** + * Abstract class for postponed notifications. + * Provides possibility to add notification after specified by id avatar or group will be + * received from cache name. The object of this type automatically well be deleted + * by cleanup method after respond will be received from cache name. + * + * To add custom postponed notification to the notification system client should: + * 1 create class derived from LLPostponedNotification; + * 2 call LLPostponedNotification::add method; + */ +class LLPostponedNotification +{ +public: + /** + * Performs hooking cache name callback which will add notification to notifications system. + * Type of added notification should be specified by template parameter T + * and non-private derived from LLPostponedNotification class, + * otherwise compilation error will occur. + */ + template<class T> + static void add(const LLNotification::Params& params, + const LLUUID& id, bool is_group) + { + // upcast T to the base type to restrict T derivation from LLPostponedNotification + LLPostponedNotification* thiz = new T(); + + thiz->mParams = params; + + gCacheName->get(id, is_group, boost::bind( + &LLPostponedNotification::onCachedNameReceived, thiz, _1, _2, + _3, _4)); + } + +private: + void onCachedNameReceived(const LLUUID& id, const std::string& first, + const std::string& last, bool is_group); + + void cleanup() + { + delete this; + } + +protected: + LLPostponedNotification() {} + virtual ~LLPostponedNotification() {} + + /** + * Abstract method provides possibility to modify notification parameters and + * will be called after cache name retrieve information about avatar or group + * and before notification will be added to the notification system. + */ + virtual void modifyNotificationParams() = 0; + + LLNotification::Params mParams; + std::string mName; +}; #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp index 4f55c0507c..b7840d1b59 100644 --- a/indra/llui/llscrollingpanellist.cpp +++ b/indra/llui/llscrollingpanellist.cpp @@ -47,7 +47,12 @@ void LLScrollingPanelList::clearPanels() { deleteAllChildren(); mPanelList.clear(); - reshape( 1, 1, FALSE ); + + LLRect rc = getRect(); + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, 1, 1); + setRect(rc); + + notifySizeChanged(rc.getHeight()); } S32 LLScrollingPanelList::addPanel( LLScrollingPanel* panel ) @@ -67,7 +72,11 @@ S32 LLScrollingPanelList::addPanel( LLScrollingPanel* panel ) max_width = llmax( max_width, childp->getRect().getWidth() ); cur_gap = GAP_BETWEEN_PANELS; } - reshape( max_width, total_height, FALSE ); + LLRect rc = getRect(); + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, max_width, total_height); + setRect(rc); + + notifySizeChanged(rc.getHeight()); // Reposition each of the child views S32 cur_y = total_height; @@ -131,7 +140,11 @@ void LLScrollingPanelList::removePanel( U32 panel_index ) max_width = llmax( max_width, childp->getRect().getWidth() ); cur_gap = GAP_BETWEEN_PANELS; } - reshape( max_width, total_height, FALSE ); + LLRect rc = getRect(); + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, max_width, total_height); + setRect(rc); + + notifySizeChanged(rc.getHeight()); // Reposition each of the child views S32 cur_y = total_height; @@ -200,3 +213,12 @@ void LLScrollingPanelList::draw() LLUICtrl::draw(); } +void LLScrollingPanelList::notifySizeChanged(S32 height) +{ + LLSD info; + info["action"] = "size_changes"; + info["height"] = height; + notifyParent(info); +} + +// EOF diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h index 3abfbcbbe7..5f1996159b 100644 --- a/indra/llui/llscrollingpanellist.h +++ b/indra/llui/llscrollingpanellist.h @@ -61,7 +61,6 @@ public: Params() { name = "scrolling_panel_list"; - follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; } }; LLScrollingPanelList(const Params& p) @@ -86,6 +85,11 @@ public: private: void updatePanelVisiblilty(); + /** + * Notify parent about size change, makes sense when used inside accordion + */ + void notifySizeChanged(S32 height); + panel_list_t mPanelList; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 77caaaa425..db0f2bd6e2 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -324,11 +324,6 @@ LLScrollListCtrl::~LLScrollListCtrl() delete mSortCallback; std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); - - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } } @@ -957,14 +952,14 @@ void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index) } } -S32 LLScrollListCtrl::selectMultiple( std::vector<LLUUID> ids ) +S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) { item_list::iterator iter; S32 count = 0; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - std::vector<LLUUID>::iterator iditr; + uuid_vec_t::iterator iditr; for(iditr = ids.begin(); iditr != ids.end(); ++iditr) { if (item->getEnabled() && (item->getUUID() == (*iditr))) diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index ebdc82115f..1f0ef585db 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -379,7 +379,7 @@ public: BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } BOOL hasSortOrder() const; - S32 selectMultiple( std::vector<LLUUID> ids ); + S32 selectMultiple( uuid_vec_t ids ); // conceptually const, but mutates mItemList void updateSort() const; // sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 5f4b16ec9e..e08026eaf4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -962,7 +962,18 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) { + //EXT-4288 + //to keep consistance scrolling behaviour + //when scrolling from top and from bottom... + bool is_scrolled_to_end = (mScroller!=NULL) && scrolledToEnd(); + LLUICtrl::reshape( width, height, called_from_parent ); + + if (is_scrolled_to_end) + { + deselect(); + endOfDoc(); + } // do this first after reshape, because other things depend on // up-to-date mVisibleTextRect @@ -1048,6 +1059,13 @@ void LLTextBase::setValue(const LLSD& value ) } //virtual +BOOL LLTextBase::canDeselect() const +{ + return hasSelection(); +} + + +//virtual void LLTextBase::deselect() { mSelectionStart = 0; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 5b24c63557..8ed0680df9 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -132,6 +132,7 @@ public: /*virtual*/ LLTextViewModel* getViewModel() const; // LLEditMenuHandler interface + /*virtual*/ BOOL canDeselect() const; /*virtual*/ void deselect(); // used by LLTextSegment layout code diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 7d230f7d42..a1cae4bb98 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -240,7 +240,6 @@ LLTextEditor::Params::Params() prevalidate_callback("prevalidate_callback"), embedded_items("embedded_items", false), ignore_tab("ignore_tab", true), - handle_edit_keys_directly("handle_edit_keys_directly", false), show_line_numbers("show_line_numbers", false), default_color("default_color"), commit_on_focus_lost("commit_on_focus_lost", false), @@ -258,7 +257,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mShowLineNumbers ( p.show_line_numbers ), mCommitOnFocusLost( p.commit_on_focus_lost), mAllowEmbeddedItems( p.embedded_items ), - mHandleEditKeysDirectly( p.handle_edit_keys_directly ), mMouseDownX(0), mMouseDownY(0), mTabsToNextField(p.ignore_tab), @@ -305,12 +303,6 @@ LLTextEditor::~LLTextEditor() { gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid - // Route menu back to the default - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } - // Scrollbar is deleted by LLView std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); @@ -507,21 +499,6 @@ void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, } } -// virtual -BOOL LLTextEditor::canDeselect() const -{ - return hasSelection(); -} - - -void LLTextEditor::deselect() -{ - mSelectionStart = 0; - mSelectionEnd = 0; - mIsSelecting = FALSE; -} - - BOOL LLTextEditor::selectionContainsLineBreaks() { if (hasSelection()) @@ -668,6 +645,7 @@ void LLTextEditor::selectAll() mSelectionStart = getLength(); mSelectionEnd = 0; setCursorPos(mSelectionEnd); + updatePrimary(); } BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) @@ -1025,7 +1003,7 @@ void LLTextEditor::removeCharOrTab() } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } @@ -1048,7 +1026,7 @@ void LLTextEditor::removeChar() } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } @@ -1198,22 +1176,6 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) } } - if( !handled && mHandleEditKeysDirectly ) - { - if( (MASK_CONTROL & mask) && ('A' == key) ) - { - if( canSelectAll() ) - { - selectAll(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - } - if( handled ) { // take selection to 'primary' clipboard @@ -1247,6 +1209,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) case KEY_DOWN: changeLine( 1 ); + deselect(); break; case KEY_PAGE_DOWN: @@ -1260,7 +1223,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) case KEY_LEFT: if( hasSelection() ) { - setCursorPos(llmin( mCursorPos - 1, mSelectionStart, mSelectionEnd )); + setCursorPos(llmin( mSelectionStart, mSelectionEnd )); } else { @@ -1270,7 +1233,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } break; @@ -1278,7 +1241,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) case KEY_RIGHT: if( hasSelection() ) { - setCursorPos(llmax( mCursorPos + 1, mSelectionStart, mSelectionEnd )); + setCursorPos(llmax( mSelectionStart, mSelectionEnd )); } else { @@ -1288,7 +1251,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } } break; @@ -1299,6 +1262,11 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) } } + if (handled) + { + deselect(); + } + return handled; } @@ -1551,75 +1519,13 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) return handled; } -BOOL LLTextEditor::handleEditKey(const KEY key, const MASK mask) -{ - BOOL handled = FALSE; - // Standard edit keys (Ctrl-X, Delete, etc,) are handled here instead of routed by the menu system. - if( KEY_DELETE == key ) - { - if( canDoDelete() ) - { - doDelete(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( MASK_CONTROL & mask ) +BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask) { - if( 'C' == key ) - { - if( canCopy() ) - { - copy(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( 'V' == key ) - { - if( canPaste() ) - { - paste(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - else - if( 'X' == key ) - { - if( canCut() ) - { - cut(); - } - else - { - reportBadKeystroke(); - } - handled = TRUE; - } - } - - return handled; -} - - -BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return_key_hit) -{ - *return_key_hit = FALSE; BOOL handled = TRUE; + if (mReadOnly) return FALSE; + switch( key ) { case KEY_INSERT: @@ -1641,7 +1547,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return } else { - reportBadKeystroke(); + LLUI::reportBadKeystroke(); } break; @@ -1694,6 +1600,10 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return break; } + if (handled) + { + onKeyStroke(); + } return handled; } @@ -1714,9 +1624,6 @@ void LLTextEditor::unindentLineBeforeCloseBrace() BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) { BOOL handled = FALSE; - BOOL selection_modified = FALSE; - BOOL return_key_hit = FALSE; - BOOL text_may_have_changed = TRUE; // Special case for TAB. If want to move to next field, report // not handled and let the parent take care of field movement. @@ -1724,116 +1631,24 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) { return FALSE; } - /* - if (KEY_F10 == key) - { - LLComboBox::Params cp; - cp.name = "combo box"; - cp.label = "my combo"; - cp.rect.width = 100; - cp.rect.height = 20; - cp.items.add().label = "item 1"; - cp.items.add().label = "item 2"; - cp.items.add().label = "item 3"; - appendWidget(LLUICtrlFactory::create<LLComboBox>(cp), "combo", true, false); - } - if (KEY_F11 == key) - { - LLButton::Params bp; - bp.name = "text button"; - bp.label = "Click me"; - bp.rect.width = 100; - bp.rect.height = 20; - - appendWidget(LLUICtrlFactory::create<LLButton>(bp), "button", true, false); - } - */ - if (mReadOnly) + if (mReadOnly && mScroller) { - if(mScroller) - { - handled = mScroller->handleKeyHere( key, mask ); + handled = (mScroller && mScroller->handleKeyHere( key, mask )) + || handleSelectionKey(key, mask) + || handleControlKey(key, mask); } else { - handled = handleNavigationKey( key, mask ); - } - - } - else - { - // handle navigation keys ourself - handled = handleNavigationKey( key, mask ); - } - - - if( handled ) - { - text_may_have_changed = FALSE; - } - - if( !handled ) - { - handled = handleSelectionKey( key, mask ); - if( handled ) - { - selection_modified = TRUE; - } - } - - if( !handled ) - { - handled = handleControlKey( key, mask ); - if( handled ) - { - selection_modified = TRUE; - } - } - - if( !handled && mHandleEditKeysDirectly ) - { - handled = handleEditKey( key, mask ); - if( handled ) - { - selection_modified = TRUE; - text_may_have_changed = TRUE; - } - } - - // Handle most keys only if the text editor is writeable. - if( !mReadOnly ) - { - if( !handled ) - { - handled = handleSpecialKey( key, mask, &return_key_hit ); - if( handled ) - { - selection_modified = TRUE; - text_may_have_changed = TRUE; - } - } - + handled = handleNavigationKey( key, mask ) + || handleSelectionKey(key, mask) + || handleControlKey(key, mask) + || handleSpecialKey(key, mask); } if( handled ) { resetCursorBlink(); - - // Most keystrokes will make the selection box go away, but not all will. - if( !selection_modified && - KEY_SHIFT != key && - KEY_CONTROL != key && - KEY_ALT != key && - KEY_CAPSLOCK ) - { - deselect(); - } - - if(text_may_have_changed) - { - onKeyStroke(); - } needsScroll(); } @@ -2334,7 +2149,7 @@ void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wo void LLTextEditor::autoIndent() { // Count the number of spaces in the current line - S32 line = getLineNumFromDocIndex(mCursorPos); + S32 line = getLineNumFromDocIndex(mCursorPos, false); S32 line_start = getLineStart(line); S32 space_count = 0; S32 i; diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 71d937b2c4..9b3ab9414c 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -68,7 +68,6 @@ public: Optional<bool> embedded_items, ignore_tab, - handle_edit_keys_directly, show_line_numbers, commit_on_focus_lost, show_context_menu; @@ -146,8 +145,6 @@ public: virtual BOOL canDoDelete() const; virtual void selectAll(); virtual BOOL canSelectAll() const; - virtual void deselect(); - virtual BOOL canDeselect() const; 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); @@ -218,13 +215,10 @@ protected: S32 indentLine( S32 pos, S32 spaces ); void unindentLineBeforeCloseBrace(); - void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); } - BOOL handleNavigationKey(const KEY key, const MASK mask); - BOOL handleSpecialKey(const KEY key, const MASK mask, BOOL* return_key_hit); + BOOL handleSpecialKey(const KEY key, const MASK mask); BOOL handleSelectionKey(const KEY key, const MASK mask); BOOL handleControlKey(const KEY key, const MASK mask); - BOOL handleEditKey(const KEY key, const MASK mask); BOOL selectionContainsLineBreaks(); void deleteSelection(BOOL transient_operation); @@ -329,10 +323,6 @@ private: LLUUID mSourceID; - // If true, the standard edit keys (Ctrl-X, Delete, etc,) are handled here - //instead of routed by the menu system - BOOL mHandleEditKeysDirectly; - LLCoordGL mLastIMEPosition; // Last position of the IME editor keystroke_signal_t mKeystrokeSignal; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b049895526..f9a4ed7285 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1914,7 +1914,12 @@ void LLUI::clearPopups() } } - +//static +void LLUI::reportBadKeystroke() +{ + make_ui_sound("UISndBadKeystroke"); +} + //static // spawn_x and spawn_y are top left corner of view in screen GL coordinates void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y) diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 30f3623ded..c18262ef76 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -217,6 +217,8 @@ public: static void removePopup(LLView*); static void clearPopups(); + static void reportBadKeystroke(); + // Ensures view does not overlap mouse cursor, but is inside // the view's parent rectangle. Used for tooltips, inspectors. // Optionally override the view's default X/Y, which are relative to the diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e8e3459673..d7666ca4c3 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -41,6 +41,9 @@ #include "lltrans.h" #include "lluicolortable.h" +#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" + + LLUrlEntryBase::LLUrlEntryBase() : mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")), mDisabledLink(false) @@ -303,10 +306,11 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const // // LLUrlEntryAgent Describes a Second Life agent Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about +// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about // LLUrlEntryAgent::LLUrlEntryAgent() { - mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+", + mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_agent.xml"; mIcon = "Generic_Person"; @@ -418,10 +422,11 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa // LLUrlEntryGroup Describes a Second Life group Url, e.g., // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect +// x-grid-location-info://lincoln.lindenlab.com/app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect // LLUrlEntryGroup::LLUrlEntryGroup() { - mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/\\w+", + mPattern = boost::regex(APP_HEADER_REGEX "/group/[\\da-f-]+/\\w+", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_group.xml"; mIcon = "Generic_Group"; @@ -482,7 +487,8 @@ LLUrlEntryInventory::LLUrlEntryInventory() //*TODO: add supporting of inventory item names with whitespaces //this pattern cann't parse for example //secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces¶m2=value - mPattern = boost::regex("secondlife:///app/inventory/[\\da-f-]+/\\w+\\S*", + //x-grid-location-info://lincoln.lindenlab.com/app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces¶m2=value + mPattern = boost::regex(APP_HEADER_REGEX "/inventory/[\\da-f-]+/\\w+\\S*", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_inventory.xml"; } @@ -493,13 +499,43 @@ std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLab return LLURI::unescape(label.empty() ? url : label); } +// +// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g., +// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1 +// +LLUrlEntryObjectIM::LLUrlEntryObjectIM() +{ + mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\?.*", + boost::regex::perl|boost::regex::icase); + mMenuName = "menu_url_objectim.xml"; +} + +std::string LLUrlEntryObjectIM::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + LLURI uri(url); + LLSD query_map = uri.queryMap(); + if (query_map.has("name")) + return query_map["name"]; + return unescapeUrl(url); +} + +std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const +{ + LLURI uri(url); + LLSD query_map = uri.queryMap(); + if (query_map.has("slurl")) + return query_map["slurl"]; + return LLUrlEntryBase::getLocation(url); +} + /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about +/// x-grid-location-info://lincoln.lindenlab.com/app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about /// LLUrlEntryParcel::LLUrlEntryParcel() { - mPattern = boost::regex("secondlife:///app/parcel/[\\da-f-]+/about", + mPattern = boost::regex(APP_HEADER_REGEX "/parcel/[\\da-f-]+/about", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_parcel.xml"; mTooltip = LLTrans::getString("TooltipParcelUrl"); @@ -515,7 +551,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC // LLUrlEntryPlace::LLUrlEntryPlace() { - mPattern = boost::regex("secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", + mPattern = boost::regex("((x-grid-location-info://[-\\w\\.]+/region/)|(secondlife://))\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); @@ -560,10 +596,11 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const // // LLUrlEntryTeleport Describes a Second Life teleport Url, e.g., // secondlife:///app/teleport/Ahern/50/50/50/ +// x-grid-location-info://lincoln.lindenlab.com/app/teleport/Ahern/50/50/50/ // LLUrlEntryTeleport::LLUrlEntryTeleport() { - mPattern = boost::regex("secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*", + mPattern = boost::regex(APP_HEADER_REGEX "/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_teleport.xml"; mTooltip = LLTrans::getString("TooltipTeleportUrl"); @@ -581,7 +618,12 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe LLURI uri(url); LLSD path_array = uri.pathArray(); S32 path_parts = path_array.size(); - const std::string label = LLTrans::getString("SLurlLabelTeleport"); + std::string host = uri.hostName(); + std::string label = LLTrans::getString("SLurlLabelTeleport"); + if (!host.empty()) + { + label += " " + host; + } if (path_parts == 6) { // handle teleport url with (X,Y,Z) coordinates @@ -680,7 +722,7 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const // LLUrlEntryWorldMap::LLUrlEntryWorldMap() { - mPattern = boost::regex("secondlife:///app/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*", + mPattern = boost::regex(APP_HEADER_REGEX "/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_map.xml"; mTooltip = LLTrans::getString("TooltipMapUrl"); diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 84d0968779..29575d752c 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -201,6 +201,18 @@ public: private: }; +/// +/// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g., +/// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1 +/// +class LLUrlEntryObjectIM : public LLUrlEntryBase +{ +public: + LLUrlEntryObjectIM(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLocation(const std::string &url) const; +private: +}; /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index faa02e1904..7e09a5a919 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -55,6 +55,7 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryWorldMap()); registerUrl(new LLUrlEntryPlace()); registerUrl(new LLUrlEntryInventory()); + registerUrl(new LLUrlEntryObjectIM()); //LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern, //so it should be registered in the end of list registerUrl(new LLUrlEntrySL()); diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index cbb303a059..4463b6cc6f 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -286,6 +286,13 @@ namespace tut "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar", "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar"); + testRegex("Standalone Agent Url ", url, + "x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about", + "x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about"); + + testRegex("Standalone Agent Url Multicase with Text", url, + "M x-grid-location-info://lincoln.lindenlab.com/app/AGENT/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about M", + "x-grid-location-info://lincoln.lindenlab.com/app/AGENT/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about"); } template<> template<> @@ -315,6 +322,15 @@ namespace tut testRegex("Group Url multicase", url, "XXX secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About XXX", "secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About"); + + testRegex("Standalone Group Url ", url, + "x-grid-location-info://lincoln.lindenlab.com/app/group/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about", + "x-grid-location-info://lincoln.lindenlab.com/app/group/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about"); + + testRegex("Standalone Group Url Multicase ith Text", url, + "M x-grid-location-info://lincoln.lindenlab.com/app/GROUP/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about M", + "x-grid-location-info://lincoln.lindenlab.com/app/GROUP/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about"); + } template<> template<> @@ -361,7 +377,11 @@ namespace tut // DEV-35459: SLURLs and teleport Links not parsed properly testRegex("SLURL with quote", url, "XXX secondlife://A'ksha%20Oasis/41/166/701 XXX", - "secondlife://A%27ksha%20Oasis/41/166/701"); + "secondlife://A%27ksha%20Oasis/41/166/701"); + + testRegex("Standalone All Hands (50,50) [2] with text", url, + "XXX x-grid-location-info://lincoln.lindenlab.com/region/All%20Hands/50/50/50 XXX", + "x-grid-location-info://lincoln.lindenlab.com/region/All%20Hands/50/50/50"); } template<> template<> @@ -461,6 +481,10 @@ namespace tut testRegex("Teleport url with quote", url, "XXX secondlife:///app/teleport/A'ksha%20Oasis/41/166/701 XXX", "secondlife:///app/teleport/A%27ksha%20Oasis/41/166/701"); + + testRegex("Standalone All Hands", url, + "XXX x-grid-location-info://lincoln.lindenlab.com/app/teleport/All%20Hands/50/50/50 XXX", + "x-grid-location-info://lincoln.lindenlab.com/app/teleport/All%20Hands/50/50/50"); } template<> template<> |