summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp24
-rw-r--r--indra/llui/llaccordionctrltab.cpp8
-rw-r--r--indra/llui/llaccordionctrltab.h3
-rw-r--r--indra/llui/llbutton.cpp2
-rw-r--r--indra/llui/llcombobox.cpp1
-rw-r--r--indra/llui/lldraghandle.cpp7
-rw-r--r--indra/llui/lldraghandle.h3
-rw-r--r--indra/llui/lleditmenuhandler.cpp7
-rw-r--r--indra/llui/lleditmenuhandler.h2
-rw-r--r--indra/llui/llflatlistview.cpp30
-rw-r--r--indra/llui/llflatlistview.h14
-rw-r--r--indra/llui/llfloater.cpp64
-rw-r--r--indra/llui/llfloater.h13
-rw-r--r--indra/llui/llfloaterreg.cpp13
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/lllineeditor.cpp118
-rw-r--r--indra/llui/lllineeditor.h4
-rw-r--r--indra/llui/llmenugl.cpp2
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llmultifloater.cpp2
-rw-r--r--indra/llui/llnotifications.cpp8
-rw-r--r--indra/llui/llnotifications.h57
-rw-r--r--indra/llui/llscrollingpanellist.cpp28
-rw-r--r--indra/llui/llscrollingpanellist.h6
-rw-r--r--indra/llui/llscrolllistctrl.cpp9
-rw-r--r--indra/llui/llscrolllistctrl.h2
-rw-r--r--indra/llui/lltextbase.cpp18
-rw-r--r--indra/llui/lltextbase.h1
-rw-r--r--indra/llui/lltexteditor.cpp245
-rw-r--r--indra/llui/lltexteditor.h12
-rw-r--r--indra/llui/llui.cpp7
-rw-r--r--indra/llui/llui.h2
-rw-r--r--indra/llui/llurlentry.cpp58
-rw-r--r--indra/llui/llurlentry.h12
-rw-r--r--indra/llui/llurlregistry.cpp1
-rw-r--r--indra/llui/tests/llurlentry_test.cpp26
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&param2=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&param2=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<>