summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt10
-rw-r--r--indra/llui/llaccordionctrl.cpp32
-rw-r--r--indra/llui/llaccordionctrltab.cpp302
-rw-r--r--indra/llui/llaccordionctrltab.h34
-rw-r--r--indra/llui/llbutton.cpp2
-rw-r--r--indra/llui/llbutton.h3
-rw-r--r--indra/llui/llcombobox.cpp69
-rw-r--r--indra/llui/llcombobox.h36
-rw-r--r--indra/llui/lldockablefloater.cpp8
-rw-r--r--indra/llui/lldockablefloater.h2
-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.cpp36
-rw-r--r--indra/llui/llflatlistview.h14
-rw-r--r--indra/llui/llfloater.cpp87
-rw-r--r--indra/llui/llfloater.h17
-rw-r--r--indra/llui/llfloaterreg.cpp13
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/llfocusmgr.cpp51
-rw-r--r--indra/llui/llfocusmgr.h10
-rw-r--r--indra/llui/llhandle.h7
-rw-r--r--indra/llui/lllayoutstack.cpp38
-rw-r--r--indra/llui/lllayoutstack.h10
-rw-r--r--indra/llui/lllineeditor.cpp118
-rw-r--r--indra/llui/lllineeditor.h4
-rw-r--r--indra/llui/llmenugl.cpp7
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llmodaldialog.cpp6
-rw-r--r--indra/llui/llmultifloater.cpp9
-rw-r--r--indra/llui/llnotifications.cpp46
-rw-r--r--indra/llui/llnotifications.h75
-rw-r--r--indra/llui/llradiogroup.cpp8
-rw-r--r--indra/llui/llscrollingpanellist.cpp28
-rw-r--r--indra/llui/llscrollingpanellist.h6
-rw-r--r--indra/llui/llscrolllistcell.cpp4
-rw-r--r--indra/llui/llscrolllistcell.h5
-rw-r--r--indra/llui/llscrolllistctrl.cpp35
-rw-r--r--indra/llui/llscrolllistctrl.h40
-rw-r--r--indra/llui/llsearcheditor.cpp15
-rw-r--r--indra/llui/llsearcheditor.h2
-rw-r--r--indra/llui/lltabcontainer.cpp35
-rw-r--r--indra/llui/lltextbase.cpp51
-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.cpp158
-rw-r--r--indra/llui/llui.h14
-rw-r--r--indra/llui/llurlentry.cpp106
-rw-r--r--indra/llui/llurlentry.h16
-rw-r--r--indra/llui/llurlregistry.cpp4
-rw-r--r--indra/llui/llview.cpp16
-rw-r--r--indra/llui/llview.h4
-rw-r--r--indra/llui/llviewborder.cpp58
-rw-r--r--indra/llui/llviewborder.h3
56 files changed, 1221 insertions, 713 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 853f6f173d..532b6b6524 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -209,6 +209,16 @@ set(llui_HEADER_FILES
set_source_files_properties(${llui_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
+SET(llurlentry_TEST_DEPENDENCIES
+ llurlmatch.cpp
+ llurlregistry.cpp
+ )
+
+set_source_files_properties(llurlentry.cpp
+ PROPERTIES LL_TEST_ADDITIONAL_SOURCE_FILES
+ "${llurlentry_TEST_DEPENDENCIES}"
+ )
+
list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES})
add_library (llui ${llui_SOURCE_FILES})
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index aa69dfe0cc..cdcf780d2e 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -103,13 +103,6 @@ void LLAccordionCtrl::draw()
LLLocalClipRect clip(local_rect);
LLPanel::draw();
- /*
- S32 width = getRect().getWidth();
- S32 height = getRect().getHeight();
-
- gl_rect_2d(0, 0 , width - 1 ,height - 1,LLColor4::green,true);
- gl_line_2d(0, 0 , width - 1 ,height - 1,LLColor4::black);
- */
}
@@ -125,7 +118,6 @@ BOOL LLAccordionCtrl::postBuild()
scrollbar_size,
getRect().getHeight() - 1);
-
LLScrollbar::Params sbparams;
sbparams.name("scrollable vertical");
sbparams.rect(scroll_rect);
@@ -380,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 daa9e08f14..0959722aa6 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -33,8 +33,9 @@
#include "linden_common.h"
#include "lluictrl.h"
-
+#include "llscrollbar.h"
#include "llaccordionctrltab.h"
+#include "lllocalcliprect.h"
#include "lltextbox.h"
@@ -46,6 +47,8 @@ static const S32 HEADER_HEIGHT = 20;
static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
static const F32 AUTO_OPEN_TIME = 1.f;
+static const S32 VERTICAL_MULTIPLE = 16;
+static const S32 PARENT_BORDER_MARGIN = 5;
static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab");
@@ -277,6 +280,7 @@ LLAccordionCtrlTab::Params::Params()
,header_image_pressed("header_image_pressed")
,header_image_focused("header_image_focused")
,header_text_color("header_text_color")
+ ,fit_panel("fit_panel",true)
{
mouse_opaque(false);
}
@@ -293,6 +297,9 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
,mPaddingTop(p.padding_top)
,mPaddingBottom(p.padding_bottom)
,mCanOpenClose(true)
+ ,mFitPanel(p.fit_panel)
+ ,mContainerPanel(NULL)
+ ,mScrollbar(NULL)
{
mStoredOpenCloseState = false;
mWasStateStored = false;
@@ -321,54 +328,42 @@ void LLAccordionCtrlTab::setDisplayChildren(bool display)
mExpandedHeight : HEADER_HEIGHT);
setRect(rect);
- for(child_list_const_iter_t it = getChildList()->begin();
- getChildList()->end() != it; ++it)
- {
- LLView* child = *it;
- if(DD_HEADER_NAME == child->getName())
- continue;
+ if(mContainerPanel)
+ mContainerPanel->setVisible(getDisplayChildren());
- child->setVisible(getDisplayChildren());
+ if(mDisplayChildren)
+ {
+ adjustContainerPanel();
}
+ else
+ {
+ if(mScrollbar)
+ mScrollbar->setVisible(false);
+ }
+
}
void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
{
LLRect headerRect;
- LLUICtrl::reshape(width, height, TRUE);
-
headerRect.setLeftTopAndSize(
0,height,width,HEADER_HEIGHT);
mHeader->setRect(headerRect);
mHeader->reshape(headerRect.getWidth(), headerRect.getHeight());
- for(child_list_const_iter_t it = getChildList()->begin();
- getChildList()->end() != it; ++it)
- {
- LLView* child = *it;
- if(DD_HEADER_NAME == child->getName())
- continue;
- if(!child->getVisible())
- continue;
-
- LLRect childRect = child->getRect();
- S32 childWidth = width - getPaddingLeft() - getPaddingRight();
- S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom();
+ if(!mDisplayChildren)
+ return;
- child->reshape(childWidth,childHeight);
-
- childRect.setLeftTopAndSize(
- getPaddingLeft(),
- childHeight + getPaddingBottom(),
- childWidth,
- childHeight);
+ LLRect childRect;
- child->setRect(childRect);
-
- break;//suppose that there is only one panel
- }
+ childRect.setLeftTopAndSize(
+ getPaddingLeft(),
+ height - getHeaderHeight() - getPaddingTop(),
+ width - getPaddingLeft() - getPaddingRight(),
+ height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
+ adjustContainerPanel(childRect);
}
void LLAccordionCtrlTab::changeOpenClose(bool is_open)
@@ -439,7 +434,7 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)
}
-LLView* LLAccordionCtrlTab::getAccordionView()
+LLView* LLAccordionCtrlTab::findContainerView()
{
for(child_list_const_iter_t it = getChildList()->begin();
getChildList()->end() != it; ++it)
@@ -470,10 +465,49 @@ 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);
+
+ LLRect scroll_rect;
+ scroll_rect.setOriginAndSize(
+ getRect().getWidth() - scrollbar_size,
+ 1,
+ scrollbar_size,
+ getRect().getHeight() - 1);
+
+ mContainerPanel = findContainerView();
+
+ if(!mFitPanel)
+ {
+ LLScrollbar::Params sbparams;
+ sbparams.name("scrollable vertical");
+ sbparams.rect(scroll_rect);
+ sbparams.orientation(LLScrollbar::VERTICAL);
+ sbparams.doc_size(getRect().getHeight());
+ sbparams.doc_pos(0);
+ sbparams.page_size(getRect().getHeight());
+ sbparams.step_size(VERTICAL_MULTIPLE);
+ sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+ sbparams.change_callback(boost::bind(&LLAccordionCtrlTab::onScrollPosChangeCallback, this, _1, _2));
+
+
+ mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+ LLView::addChild( mScrollbar );
+ mScrollbar->setFollowsRight();
+ mScrollbar->setFollowsTop();
+ mScrollbar->setFollowsBottom();
+
+ mScrollbar->setVisible(false);
+ }
+
+ if(mContainerPanel)
+ mContainerPanel->setVisible(mDisplayChildren);
+
return LLUICtrl::postBuild();
}
bool LLAccordionCtrlTab::notifyChildren (const LLSD& info)
@@ -562,6 +596,12 @@ BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
if( !header->hasFocus() )
return LLUICtrl::handleKey(key, mask, called_from_parent);
+ if ( (key == KEY_RETURN )&& mask == MASK_NONE)
+ {
+ changeOpenClose(getDisplayChildren());
+ return TRUE;
+ }
+
if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE)
{
if(getDisplayChildren() == false)
@@ -622,6 +662,7 @@ void LLAccordionCtrlTab::storeOpenCloseState()
mStoredOpenCloseState = getDisplayChildren();
mWasStateStored = true;
}
+
void LLAccordionCtrlTab::restoreOpenCloseState()
{
if(!mWasStateStored)
@@ -632,3 +673,192 @@ void LLAccordionCtrlTab::restoreOpenCloseState()
}
mWasStateStored = false;
}
+
+void LLAccordionCtrlTab::adjustContainerPanel ()
+{
+ S32 width = getRect().getWidth();
+ S32 height = getRect().getHeight();
+
+ LLRect child_rect;
+ child_rect.setLeftTopAndSize(
+ getPaddingLeft(),
+ height - getHeaderHeight() - getPaddingTop(),
+ width - getPaddingLeft() - getPaddingRight(),
+ height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
+
+ adjustContainerPanel(child_rect);
+}
+
+void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect)
+{
+ if(!mContainerPanel)
+ return;
+
+ if(!mFitPanel)
+ {
+ show_hide_scrollbar(child_rect);
+ updateLayout(child_rect);
+ }
+ else
+ {
+ mContainerPanel->reshape(child_rect.getWidth(),child_rect.getHeight());
+ mContainerPanel->setRect(child_rect);
+ }
+}
+
+S32 LLAccordionCtrlTab::getChildViewHeight()
+{
+ if(!mContainerPanel)
+ return 0;
+ return mContainerPanel->getRect().getHeight();
+}
+
+void LLAccordionCtrlTab::show_hide_scrollbar(const LLRect& child_rect)
+{
+ if(getChildViewHeight() > child_rect.getHeight() )
+ showScrollbar(child_rect);
+ else
+ hideScrollbar(child_rect);
+}
+void LLAccordionCtrlTab::showScrollbar(const LLRect& child_rect)
+{
+ if(!mContainerPanel || !mScrollbar)
+ return;
+ bool was_visible = mScrollbar->getVisible();
+ mScrollbar->setVisible(true);
+
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ {
+ ctrlSetLeftTopAndSize(mScrollbar,child_rect.getWidth()-scrollbar_size,
+ child_rect.getHeight()-PARENT_BORDER_MARGIN,
+ scrollbar_size,
+ child_rect.getHeight()-2*PARENT_BORDER_MARGIN);
+ }
+
+ LLRect orig_rect = mContainerPanel->getRect();
+
+ mScrollbar->setPageSize(child_rect.getHeight());
+ mScrollbar->setDocParams(orig_rect.getHeight(),mScrollbar->getDocPos());
+
+ if(was_visible)
+ {
+ S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1);
+ mScrollbar->setDocPos(scroll_pos);
+ }
+ else//shrink child panel
+ {
+ updateLayout(child_rect);
+ }
+
+}
+
+void LLAccordionCtrlTab::hideScrollbar( const LLRect& child_rect )
+{
+ if(!mContainerPanel || !mScrollbar)
+ return;
+
+ if(mScrollbar->getVisible() == false)
+ return;
+ mScrollbar->setVisible(false);
+ mScrollbar->setDocPos(0);
+
+ //shrink child panel
+ updateLayout(child_rect);
+}
+
+void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*)
+{
+ LLRect child_rect;
+
+ S32 width = getRect().getWidth();
+ S32 height = getRect().getHeight();
+
+ child_rect.setLeftTopAndSize(
+ getPaddingLeft(),
+ height - getHeaderHeight() - getPaddingTop(),
+ width - getPaddingLeft() - getPaddingRight(),
+ height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
+
+ updateLayout(child_rect);
+}
+
+void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
+{
+ if (child && child->getVisible() && child->getRect().isValid())
+ {
+ LLRect screen_rect;
+ localRectToScreen(child->getRect(),&screen_rect);
+
+ if ( root_rect.overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
+ {
+ glMatrixMode(GL_MODELVIEW);
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom, 0.f);
+ child->draw();
+
+ }
+ LLUI::popMatrix();
+ }
+ }
+}
+
+void LLAccordionCtrlTab::draw()
+{
+ if(mFitPanel)
+ LLUICtrl::draw();
+ else
+ {
+ LLRect root_rect = getRootView()->getRect();
+ drawChild(root_rect,mHeader);
+ drawChild(root_rect,mScrollbar );
+ {
+ LLRect child_rect;
+
+ S32 width = getRect().getWidth();
+ S32 height = getRect().getHeight();
+
+ child_rect.setLeftTopAndSize(
+ getPaddingLeft(),
+ height - getHeaderHeight() - getPaddingTop(),
+ width - getPaddingLeft() - getPaddingRight(),
+ height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
+
+ LLLocalClipRect clip(child_rect);
+ drawChild(root_rect,mContainerPanel);
+ }
+ }
+}
+
+void LLAccordionCtrlTab::updateLayout ( const LLRect& child_rect )
+{
+ LLView* child = getAccordionView();
+ if(!mContainerPanel)
+ return;
+
+ S32 panel_top = child_rect.getHeight();
+ S32 panel_width = child_rect.getWidth();
+
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+ if(mScrollbar->getVisible() != false)
+ {
+ panel_top+=mScrollbar->getDocPos();
+ panel_width-=scrollbar_size;
+ }
+
+ //set sizes for first panels and dragbars
+ LLRect panel_rect = child->getRect();
+ ctrlSetLeftTopAndSize(mContainerPanel,child_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
+}
+void LLAccordionCtrlTab::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
+{
+ if(!panel)
+ return;
+ LLRect panel_rect = panel->getRect();
+ panel_rect.setLeftTopAndSize( left, top, width, height);
+ panel->reshape( width, height, 1);
+ panel->setRect(panel_rect);
+}
+
+
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index 2e0260ab16..4b8b22405e 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -35,12 +35,14 @@
#include <string>
#include "llrect.h"
+#include "lluictrl.h"
+#include "lluicolor.h"
-class LLUICtrl;
class LLUICtrlFactory;
class LLUIImage;
class LLButton;
class LLTextBox;
+class LLScrollbar;
@@ -84,6 +86,8 @@ public:
Optional<bool> header_visible;
+ Optional<bool> fit_panel;
+
Optional<S32> padding_left;
Optional<S32> padding_right;
Optional<S32> padding_top;
@@ -107,7 +111,7 @@ public:
//set LLAccordionCtrlTab panel
void setAccordionView(LLView* panel);
- LLView* getAccordionView();
+ LLView* getAccordionView() { return mContainerPanel; };
bool getCollapsible() {return mCollapsible;};
@@ -123,6 +127,8 @@ public:
S32 notify(const LLSD& info);
bool notifyChildren(const LLSD& info);
+ void draw();
+
void storeOpenCloseState ();
void restoreOpenCloseState ();
@@ -164,9 +170,26 @@ public:
void showAndFocusHeader();
-private:
+ void setFitPanel( bool fit ) { mFitPanel = true; }
-
+protected:
+ void adjustContainerPanel (const LLRect& child_rect);
+ void adjustContainerPanel ();
+ S32 getChildViewHeight ();
+
+ void onScrollPosChangeCallback(S32, LLScrollbar*);
+
+ void show_hide_scrollbar (const LLRect& child_rect);
+ void showScrollbar (const LLRect& child_rect);
+ void hideScrollbar (const LLRect& child_rect);
+
+ void updateLayout ( const LLRect& child_rect );
+ void ctrlSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height);
+
+ void drawChild(const LLRect& root_rect,LLView* child);
+
+ LLView* findContainerView ();
+private:
class LLAccordionCtrlTabHeader;
LLAccordionCtrlTabHeader* mHeader; //Header
@@ -176,6 +199,7 @@ private:
bool mHeaderVisible;
bool mCanOpenClose;
+ bool mFitPanel;
S32 mPaddingLeft;
S32 mPaddingRight;
@@ -185,6 +209,8 @@ private:
bool mStoredOpenCloseState;
bool mWasStateStored;
+ LLScrollbar* mScrollbar;
+ LLView* mContainerPanel;
LLUIColor mDropdownBGColor;
};
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/llbutton.h b/indra/llui/llbutton.h
index 6a0d8ef3d6..6a1e3a9425 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -216,7 +216,8 @@ public:
void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
-
+ LLFontGL::HAlign getImageOverlayHAlign() const { return mImageOverlayAlignment; }
+
void autoResize(); // resize with label of current btn state
void resize(LLUIString label); // resize with label input
void setLabel( const LLStringExplicit& label);
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 9d23daf56d..cc107c972d 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -160,7 +160,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)
createLineEditor(p);
- setTopLostCallback(boost::bind(&LLComboBox::hideList, this));
+ mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this));
}
void LLComboBox::initFromParams(const LLComboBox::Params& p)
@@ -187,6 +187,9 @@ BOOL LLComboBox::postBuild()
LLComboBox::~LLComboBox()
{
// children automatically deleted, including mMenu, mButton
+
+ // explicitly disconect this signal, since base class destructor might fire top lost
+ mTopLostSignalConnection.disconnect();
}
@@ -320,15 +323,19 @@ void LLComboBox::setValue(const LLSD& value)
LLScrollListItem* item = mList->getFirstSelected();
if (item)
{
- setLabel( mList->getSelectedItemLabel() );
+ setLabel(getSelectedItemLabel());
}
mLastSelectedIndex = mList->getFirstSelectedIndex();
}
+ else
+ {
+ mLastSelectedIndex = -1;
+ }
}
const std::string LLComboBox::getSimple() const
{
- const std::string res = mList->getSelectedItemLabel();
+ const std::string res = getSelectedItemLabel();
if (res.empty() && mAllowTextEntry)
{
return mTextEntry->getText();
@@ -407,7 +414,7 @@ BOOL LLComboBox::remove(S32 index)
if (index < mList->getItemCount())
{
mList->deleteSingleItem(index);
- setLabel(mList->getSelectedItemLabel());
+ setLabel(getSelectedItemLabel());
return TRUE;
}
return FALSE;
@@ -448,7 +455,7 @@ BOOL LLComboBox::setCurrentByIndex( S32 index )
BOOL found = mList->selectNthItem( index );
if (found)
{
- setLabel(mList->getSelectedItemLabel());
+ setLabel(getSelectedItemLabel());
mLastSelectedIndex = index;
}
return found;
@@ -488,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);
@@ -612,16 +618,14 @@ void LLComboBox::showList()
mList->setFocus(TRUE);
- // register ourselves as a "top" control
- // effectively putting us into a special draw layer
- // and not affecting the bounding rectangle calculation
- gFocusMgr.setTopCtrl(this);
-
// Show the list and push the button down
mButton->setToggleState(TRUE);
mList->setVisible(TRUE);
+ LLUI::addPopup(this);
+
setUseBoundingRect(TRUE);
+// updateBoundingRect();
}
void LLComboBox::hideList()
@@ -644,10 +648,8 @@ void LLComboBox::hideList()
mList->mouseOverHighlightNthItem(-1);
setUseBoundingRect(FALSE);
- if( gFocusMgr.getTopCtrl() == this )
- {
- gFocusMgr.setTopCtrl(NULL);
- }
+ LLUI::removePopup(this);
+// updateBoundingRect();
}
}
@@ -703,13 +705,10 @@ void LLComboBox::onListMouseUp()
void LLComboBox::onItemSelected(const LLSD& data)
{
- const std::string name = mList->getSelectedItemLabel();
-
- S32 cur_id = getCurrentIndex();
- mLastSelectedIndex = cur_id;
- if (cur_id != -1)
+ mLastSelectedIndex = getCurrentIndex();
+ if (mLastSelectedIndex != -1)
{
- setLabel(name);
+ setLabel(getSelectedItemLabel());
if (mAllowTextEntry)
{
@@ -717,7 +716,6 @@ void LLComboBox::onItemSelected(const LLSD& data)
mTextEntry->selectAll();
}
}
-
// hiding the list reasserts the old value stored in the text editor/dropdown button
hideList();
@@ -912,7 +910,7 @@ void LLComboBox::updateSelection()
}
else if (mList->selectItemByPrefix(left_wstring, FALSE))
{
- LLWString selected_item = utf8str_to_wstring(mList->getSelectedItemLabel());
+ LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel());
LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size());
mTextEntry->setText(wstring_to_utf8str(wtext));
mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size());
@@ -1014,7 +1012,7 @@ BOOL LLComboBox::setCurrentByID(const LLUUID& id)
if (found)
{
- setLabel(mList->getSelectedItemLabel());
+ setLabel(getSelectedItemLabel());
mLastSelectedIndex = mList->getFirstSelectedIndex();
}
@@ -1030,7 +1028,7 @@ BOOL LLComboBox::setSelectedByValue(const LLSD& value, BOOL selected)
BOOL found = mList->setSelectedByValue(value, selected);
if (found)
{
- setLabel(mList->getSelectedItemLabel());
+ setLabel(getSelectedItemLabel());
}
return found;
}
@@ -1069,3 +1067,24 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last )
{
return mList->selectItemRange(first, last);
}
+
+
+static LLDefaultChildRegistry::Register<LLIconsComboBox> register_icons_combo_box("icons_combo_box");
+
+LLIconsComboBox::Params::Params()
+: icon_column("icon_column", ICON_COLUMN),
+ label_column("label_column", LABEL_COLUMN)
+{}
+
+LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p)
+: LLComboBox(p),
+ mIconColumnIndex(p.icon_column),
+ mLabelColumnIndex(p.label_column)
+{}
+
+const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const
+{
+ mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign());
+
+ return LLComboBox::getSelectedItemLabel(mLabelColumnIndex);
+}
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 4f27588467..f0bd432f3a 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -150,7 +150,7 @@ public:
// Get name of current item. Returns an empty string if not found.
const std::string getSimple() const;
// Get contents of column x of selected row
- const std::string getSelectedItemLabel(S32 column = 0) const;
+ virtual const std::string getSelectedItemLabel(S32 column = 0) const;
// Sets the label, which doesn't have to exist in the label.
// This is probably a UI abuse.
@@ -230,6 +230,38 @@ private:
commit_callback_t mPrearrangeCallback;
commit_callback_t mTextEntryCallback;
commit_callback_t mSelectionCallback;
- S32 mLastSelectedIndex;
+ boost::signals2::connection mTopLostSignalConnection;
+ S32 mLastSelectedIndex;
};
+
+// A combo box with icons for the list of items.
+class LLIconsComboBox
+: public LLComboBox
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLComboBox::Params>
+ {
+ Optional<S32> icon_column,
+ label_column;
+ Params();
+ };
+
+ /*virtual*/ const std::string getSelectedItemLabel(S32 column = 0) const;
+
+private:
+ enum EColumnIndex
+ {
+ ICON_COLUMN = 0,
+ LABEL_COLUMN
+ };
+
+ friend class LLUICtrlFactory;
+ LLIconsComboBox(const Params&);
+ virtual ~LLIconsComboBox() {};
+
+ S32 mIconColumnIndex;
+ S32 mLabelColumnIndex;
+};
+
#endif
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 0492ab0f25..3d8670fef2 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -202,10 +202,6 @@ void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
translate(0, UNDOCK_LEAP_HEIGHT);
}
}
- else
- {
- docked = false;
- }
LLFloater::setDocked(docked, pop_on_undock);
}
@@ -223,10 +219,10 @@ void LLDockableFloater::draw()
LLFloater::draw();
}
-void LLDockableFloater::setDockControl(LLDockControl* dockControl, bool docked /* = true */)
+void LLDockableFloater::setDockControl(LLDockControl* dockControl)
{
mDockControl.reset(dockControl);
- setDocked(docked && mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
+ setDocked(isDocked());
}
const LLUIImagePtr& LLDockableFloater::getDockTongue()
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 4d747390af..2b1ce99ae2 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -127,7 +127,7 @@ private:
void resetInstance();
protected:
- void setDockControl(LLDockControl* dockControl, bool docked = true);
+ void setDockControl(LLDockControl* dockControl);
const LLUIImagePtr& getDockTongue();
private:
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 2481249f91..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;
@@ -492,6 +492,12 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
{
if (!item_pair) return;
+ if (!item_pair->first)
+ {
+ llwarning("Attempt to selet an item pair containing null panel item", 0);
+ return;
+ }
+
setFocus(TRUE);
bool select_item = !isSelected(item_pair);
@@ -552,15 +558,6 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
}
break;
}
- case 'A':
- {
- if(MASK_CONTROL & mask)
- {
- selectAll();
- handled = TRUE;
- }
- break;
- }
default:
break;
}
@@ -785,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();
@@ -808,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
@@ -947,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 b6d73cda3c..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();
}
@@ -527,10 +527,7 @@ void LLFloater::setVisible( BOOL visible )
if( !visible )
{
- if( gFocusMgr.childIsTopCtrl( this ) )
- {
- gFocusMgr.setTopCtrl(NULL);
- }
+ LLUI::removePopup(this);
if( gFocusMgr.childHasMouseCapture( this ) )
{
@@ -704,10 +701,7 @@ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLFloater::releaseFocus()
{
- if( gFocusMgr.childIsTopCtrl( this ) )
- {
- gFocusMgr.setTopCtrl(NULL);
- }
+ LLUI::removePopup(this);
setFocus(FALSE);
@@ -1067,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 )
@@ -1127,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
@@ -1196,7 +1190,7 @@ void LLFloater::setHost(LLMultiFloater* host)
mButtonScale = 1.f;
//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;
}
- updateButtons();
+ updateTitleButtons();
if (host)
{
mHostHandle = host->getHandle();
@@ -1360,7 +1354,6 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
{
- gFocusMgr.setTopCtrl(NULL);
setVisible(TRUE);
setFrontmost(take_focus);
}
@@ -1396,7 +1389,7 @@ void LLFloater::setCanDock(bool b)
mButtonsEnabled[BUTTON_DOCK] = FALSE;
}
}
- updateButtons();
+ updateTitleButtons();
}
void LLFloater::setDocked(bool docked, bool pop_on_undock)
@@ -1405,7 +1398,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock)
{
mDocked = docked;
mButtonsEnabled[BUTTON_DOCK] = !mDocked;
- updateButtons();
+ updateTitleButtons();
storeDockStateControl();
}
@@ -1458,7 +1451,7 @@ void LLFloater::onClickTearOff(LLFloater* self)
}
self->setTornOff(false);
}
- self->updateButtons();
+ self->updateTitleButtons();
}
// static
@@ -1554,7 +1547,12 @@ void LLFloater::onClickClose( LLFloater* self )
{
if (!self)
return;
- self->closeFloater(false);
+ self->onClickCloseBtn();
+}
+
+void LLFloater::onClickCloseBtn()
+{
+ closeFloater(false);
}
@@ -1693,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)
@@ -1701,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)
@@ -1709,7 +1707,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off)
mCanTearOff = can_tear_off;
mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead();
- updateButtons();
+ updateTitleButtons();
}
@@ -1733,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++)
{
@@ -1787,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
@@ -1798,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)
@@ -1846,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);
@@ -1855,7 +1866,7 @@ void LLFloater::buildButtons(const Params& floater_params)
mButtons[i] = buttonp;
}
- updateButtons();
+ updateTitleButtons();
}
// static
@@ -1901,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];
}
@@ -2503,10 +2521,7 @@ void LLFloaterView::syncFloaterTabOrder()
if (modal_dialog)
{
// If we have a visible modal dialog, make sure that it has focus
- if( gFocusMgr.getTopCtrl() != modal_dialog )
- {
- gFocusMgr.setTopCtrl( modal_dialog );
- }
+ LLUI::addPopup(modal_dialog);
if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) )
{
@@ -2815,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 19e8288807..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(); }
@@ -307,19 +309,28 @@ protected:
void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
+ 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();
@@ -346,6 +357,7 @@ protected:
LLResizeBar* mResizeBar[4];
LLResizeHandle* mResizeHandle[4];
+ LLButton* mButtons[BUTTON_COUNT];
private:
LLRect mExpandedRect;
@@ -379,7 +391,6 @@ private:
handle_set_t mDependents;
bool mButtonsEnabled[BUTTON_COUNT];
- LLButton* mButtons[BUTTON_COUNT];
F32 mButtonScale;
BOOL mAutoFocus;
LLHandle<LLFloater> mSnappedTo;
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/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 35fbc7b0a8..b3af258456 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -38,8 +38,6 @@
const F32 FOCUS_FADE_TIME = 0.3f;
-// NOTE: the LLFocusableElement implementation has been moved here from lluictrl.cpp.
-
LLFocusableElement::LLFocusableElement()
: mFocusLostCallback(NULL),
mFocusReceivedCallback(NULL),
@@ -124,8 +122,7 @@ boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_s
LLFocusMgr gFocusMgr;
LLFocusMgr::LLFocusMgr()
- :
- mLockedView( NULL ),
+: mLockedView( NULL ),
mMouseCaptor( NULL ),
mKeyboardFocus( NULL ),
mLastKeyboardFocus( NULL ),
@@ -133,16 +130,11 @@ LLFocusMgr::LLFocusMgr()
mKeystrokesOnly(FALSE),
mTopCtrl( NULL ),
mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true
- #ifdef _DEBUG
- , mMouseCaptorName("none")
- , mKeyboardFocusName("none")
- , mTopCtrlName("none")
- #endif
{
}
-void LLFocusMgr::releaseFocusIfNeeded( const LLView* view )
+void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
{
if( childHasMouseCapture( view ) )
{
@@ -162,10 +154,7 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view )
}
}
- if( childIsTopCtrl( view ) )
- {
- setTopCtrl( NULL );
- }
+ LLUI::removePopup(view);
}
@@ -248,11 +237,6 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL
return;
}
- #ifdef _DEBUG
- LLUICtrl* focus_ctrl = dynamic_cast<LLUICtrl*>(new_focus);
- mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none");
- #endif
-
// If we've got a default keyboard focus, and the caller is
// releasing keyboard focus, move to the default.
if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL)
@@ -334,20 +318,12 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* f
if( mKeyboardFocus == focus )
{
mKeyboardFocus = NULL;
- #ifdef _DEBUG
- mKeyboardFocusName = std::string("none");
- #endif
}
}
void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
{
- //if (mFocusLocked)
- //{
- // return;
- //}
-
if( new_captor != mMouseCaptor )
{
LLMouseHandler* old_captor = mMouseCaptor;
@@ -370,24 +346,14 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
old_captor->onMouseCaptureLost();
}
- #ifdef _DEBUG
- mMouseCaptorName = new_captor ? new_captor->getName() : std::string("none");
- #endif
}
}
void LLFocusMgr::removeMouseCaptureWithoutCallback( const LLMouseHandler* captor )
{
- //if (mFocusLocked)
- //{
- // return;
- //}
if( mMouseCaptor == captor )
{
mMouseCaptor = NULL;
- #ifdef _DEBUG
- mMouseCaptorName = std::string("none");
- #endif
}
}
@@ -416,10 +382,6 @@ void LLFocusMgr::setTopCtrl( LLUICtrl* new_top )
{
mTopCtrl = new_top;
- #ifdef _DEBUG
- mTopCtrlName = new_top ? new_top->getName() : std::string("none");
- #endif
-
if (old_top)
{
old_top->onTopLost();
@@ -432,9 +394,6 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view )
if( mTopCtrl == top_view )
{
mTopCtrl = NULL;
- #ifdef _DEBUG
- mTopCtrlName = std::string("none");
- #endif
}
}
@@ -478,9 +437,9 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)
}
// release focus from "top ctrl"s, which generally hides them
- if (!focus && mTopCtrl)
+ if (!focus)
{
- setTopCtrl(NULL);
+ LLUI::clearPopups();
}
mAppHasFocus = focus;
}
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 83ecd1d301..86d3ccf111 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -65,10 +65,10 @@ public:
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere
protected:
virtual void onFocusReceived();
virtual void onFocusLost();
- virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere
focus_signal_t* mFocusLostCallback;
focus_signal_t* mFocusReceivedCallback;
focus_signal_t* mFocusChangedCallback;
@@ -119,7 +119,7 @@ public:
BOOL childIsTopCtrl( const LLView* parent ) const;
// All Three
- void releaseFocusIfNeeded( const LLView* top_view );
+ void releaseFocusIfNeeded( LLView* top_view );
void lockFocus();
void unlockFocus();
BOOL focusLocked() const { return mLockedView != NULL; }
@@ -149,12 +149,6 @@ private:
typedef std::map<LLHandle<LLView>, LLHandle<LLView> > focus_history_map_t;
focus_history_map_t mFocusHistory;
-
- #ifdef _DEBUG
- std::string mMouseCaptorName;
- std::string mKeyboardFocusName;
- std::string mTopCtrlName;
- #endif
};
extern LLFocusMgr gFocusMgr;
diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h
index 899f6b9326..8ade327044 100644
--- a/indra/llui/llhandle.h
+++ b/indra/llui/llhandle.h
@@ -67,6 +67,13 @@ public:
return *this;
}
+ template<typename Subclass>
+ LLHandle<T>& operator =(const LLHandle<Subclass>& other)
+ {
+ mTombStone = other.mTombStone;
+ return *this;
+ }
+
bool isDead() const
{
return mTombStone->getTarget() == NULL;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index dc79550eb4..4512091371 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -49,9 +49,11 @@ static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("la
//
struct LLLayoutStack::LayoutPanel
{
- LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp),
+ LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp),
mMinWidth(min_width),
mMinHeight(min_height),
+ mMaxWidth(max_width),
+ mMaxHeight(max_height),
mAutoResize(auto_resize),
mUserResize(user_resize),
mOrientation(orientation),
@@ -112,6 +114,11 @@ struct LLLayoutStack::LayoutPanel
LLPanel* mPanel;
S32 mMinWidth;
S32 mMinHeight;
+
+ // mMaxWidth & mMaxHeight are added to make configurable max width of the nearby chat bar. EXT-5589
+ // they are not processed by LLLayoutStack but they can be if necessary
+ S32 mMaxWidth;
+ S32 mMaxHeight;
BOOL mAutoResize;
BOOL mUserResize;
BOOL mCollapsed;
@@ -261,10 +268,14 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
{
const S32 DEFAULT_MIN_WIDTH = 0;
const S32 DEFAULT_MIN_HEIGHT = 0;
+ const S32 DEFAULT_MAX_WIDTH = S32_MAX;
+ const S32 DEFAULT_MAX_HEIGHT = S32_MAX;
const BOOL DEFAULT_AUTO_RESIZE = TRUE;
S32 min_width = DEFAULT_MIN_WIDTH;
S32 min_height = DEFAULT_MIN_HEIGHT;
+ S32 max_width = DEFAULT_MAX_WIDTH;
+ S32 max_height = DEFAULT_MAX_HEIGHT;
BOOL auto_resize = DEFAULT_AUTO_RESIZE;
LLXMLNodePtr output_child;
@@ -281,6 +292,10 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
DEFAULT_MIN_WIDTH, output_child);
get_attribute_s32_and_write(child_node, "min_height", &min_height,
DEFAULT_MIN_HEIGHT, output_child);
+ get_attribute_s32_and_write(child_node, "max_width", &max_width,
+ DEFAULT_MAX_WIDTH, output_child);
+ get_attribute_s32_and_write(child_node, "max_height", &max_height,
+ DEFAULT_MAX_HEIGHT, output_child);
get_attribute_bool_and_write(child_node, "auto_resize", &auto_resize,
DEFAULT_AUTO_RESIZE, output_child);
@@ -293,7 +308,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
if (panelp)
{
panelp->setFollowsNone();
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize);
}
}
else
@@ -309,7 +324,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
if (new_child)
{
// put child in new embedded panel
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize);
// resize panel to contain widget and move widget to be contained in panel
panelp->setRect(new_child->getRect());
new_child->setOrigin(0, 0);
@@ -359,14 +374,14 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
return cur_width;
}
-void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
{
// panel starts off invisible (collapsed)
if (animate == ANIMATE)
{
panel->setVisible(FALSE);
}
- LayoutPanel* embedded_panel = new LayoutPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
+ LayoutPanel* embedded_panel = new LayoutPanel(panel, mOrientation, min_width, min_height, max_width, max_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
@@ -437,6 +452,19 @@ bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widt
return NULL != panel;
}
+bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_widthp, S32* max_heightp)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ if (max_widthp) *max_widthp = panel->mMaxWidth;
+ if (max_heightp) *max_heightp = panel->mMaxHeight;
+ }
+
+ return NULL != panel;
+}
+
static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
void LLLayoutStack::updateLayout(BOOL force_resize)
{
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index c4f10038f8..e454454fe2 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -74,7 +74,7 @@ public:
ANIMATE
} EAnimate;
- void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
@@ -89,6 +89,14 @@ public:
* @returns true if specified by panel_name internal panel exists, false otherwise.
*/
bool getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp);
+
+ /**
+ * Gets maximal width and/or height of the specified by name panel.
+ *
+ * If it is necessary to get only the one dimension pass NULL for another one.
+ * @returns true if specified by panel_name internal panel exists, false otherwise.
+ */
+ bool getPanelMaxSize(const std::string& panel_name, S32* max_width, S32* max_height);
void updateLayout(BOOL force_resize = FALSE);
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 0d56c5ed31..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();
@@ -3455,7 +3455,7 @@ LLView* const LLMenuHolderGL::getVisibleMenu() const
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
- if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL)
+ if (viewp->getVisible() && dynamic_cast<LLMenuGL*>(viewp) != NULL)
{
return viewp;
}
@@ -3478,8 +3478,7 @@ BOOL LLMenuHolderGL::hideMenus()
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
- // clicks off of menu do not hide menu bar
- if (dynamic_cast<LLMenuBarGL*>(viewp) == NULL && viewp->getVisible())
+ if (dynamic_cast<LLMenuGL*>(viewp) != NULL && viewp->getVisible())
{
viewp->setVisible(FALSE);
}
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/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index 387af05935..6cff68c20b 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -111,7 +111,7 @@ void LLModalDialog::onOpen(const LLSD& key)
// This is a modal dialog. It sucks up all mouse and keyboard operations.
gFocusMgr.setMouseCapture( this );
- gFocusMgr.setTopCtrl( this );
+ LLUI::addPopup(this);
setFocus(TRUE);
sModalStack.push_front( this );
@@ -153,7 +153,7 @@ void LLModalDialog::setVisible( BOOL visible )
gFocusMgr.setMouseCapture( this );
// The dialog view is a root view
- gFocusMgr.setTopCtrl( this );
+ LLUI::addPopup(this);
setFocus( TRUE );
}
else
@@ -291,7 +291,7 @@ void LLModalDialog::onAppFocusGained()
// This is a modal dialog. It sucks up all mouse and keyboard operations.
gFocusMgr.setMouseCapture( instance );
instance->setFocus(TRUE);
- gFocusMgr.setTopCtrl( instance );
+ LLUI::addPopup(instance);
instance->centerOnScreen();
}
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index 33d47a3f0e..3aea648562 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -345,13 +345,20 @@ 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
if (floater && floater->canClose() && floater->isCloseable())
{
floater->closeFloater();
+
+ // EXT-5695 (Tabbed IM window loses focus if close any tabs by Ctrl+W)
+ // bring back focus on tab container if there are any tab left
+ if(mTabContainer->getTabCount() > 0)
+ {
+ mTabContainer->setFocus(TRUE);
+ }
}
return TRUE;
}
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 5816cef6af..65ef53443b 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -402,7 +402,9 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
mRespondedTo(false),
mPriority(p.priority),
mCancelled(false),
- mIgnored(false)
+ mIgnored(false),
+ mResponderObj(NULL),
+ mIsReusable(false)
{
if (p.functor.name.isChosen())
{
@@ -416,6 +418,11 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
mTemporaryResponder = true;
}
+ if(p.responder.isProvided())
+ {
+ mResponderObj = p.responder;
+ }
+
mId.generate();
init(p.name, p.form_elements);
}
@@ -425,7 +432,9 @@ LLNotification::LLNotification(const LLSD& sd) :
mTemporaryResponder(false),
mRespondedTo(false),
mCancelled(false),
- mIgnored(false)
+ mIgnored(false),
+ mResponderObj(NULL),
+ mIsReusable(false)
{
mId.generate();
mSubstitutions = sd["substitutions"];
@@ -452,6 +461,7 @@ LLSD LLNotification::asLLSD()
output["expiry"] = mExpiresAt;
output["priority"] = (S32)mPriority;
output["responseFunctor"] = mResponseFunctorName;
+ output["reusable"] = mIsReusable;
return output;
}
@@ -479,7 +489,9 @@ void LLNotification::updateFrom(LLNotificationPtr other)
mForm = other->mForm;
mResponseFunctorName = other->mResponseFunctorName;
mRespondedTo = other->mRespondedTo;
+ mResponse = other->mResponse;
mTemporaryResponder = other->mTemporaryResponder;
+ mIsReusable = other->isReusable();
update();
}
@@ -556,14 +568,16 @@ std::string LLNotification::getSelectedOptionName(const LLSD& response)
void LLNotification::respond(const LLSD& response)
{
+ // *TODO may remove mRespondedTo and use mResponce.isDefined() in isRespondedTo()
mRespondedTo = true;
+ mResponse = response;
// look up the functor
LLNotificationFunctorRegistry::ResponseFunctor functor =
LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName);
// and then call it
functor(asLLSD(), response);
- if (mTemporaryResponder)
+ if (mTemporaryResponder && !isReusable())
{
LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
mResponseFunctorName = "";
@@ -597,6 +611,16 @@ void LLNotification::setResponseFunctor(std::string const &responseFunctorName)
mTemporaryResponder = false;
}
+void LLNotification::setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb)
+{
+ if(mTemporaryResponder)
+ {
+ LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
+ }
+
+ LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, cb);
+}
+
bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const
{
for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin();
@@ -856,8 +880,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
if (wasFound)
{
abortProcessing = mChanged(payload);
- mItems.erase(pNotification);
- onDelete(pNotification);
+ // do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window
+ if( ! pNotification->isReusable() )
+ {
+ mItems.erase(pNotification);
+ onDelete(pNotification);
+ }
}
}
return abortProcessing;
@@ -1524,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 8d993b71d7..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
@@ -296,6 +297,7 @@ public:
Optional<LLSD> form_elements;
Optional<LLDate> time_stamp;
Optional<LLNotificationContext*> context;
+ Optional<void*> responder;
struct Functor : public LLInitParam::Choice<Functor>
{
@@ -317,6 +319,7 @@ public:
form_elements("form_elements")
{
time_stamp = LLDate::now();
+ responder = NULL;
}
Params(const std::string& _name)
@@ -329,6 +332,7 @@ public:
functor.name = _name;
name = _name;
time_stamp = LLDate::now();
+ responder = NULL;
}
};
@@ -341,9 +345,12 @@ private:
LLDate mExpiresAt;
bool mCancelled;
bool mRespondedTo; // once the notification has been responded to, this becomes true
+ LLSD mResponse;
bool mIgnored;
ENotificationPriority mPriority;
LLNotificationFormPtr mForm;
+ void* mResponderObj;
+ bool mIsReusable;
// a reference to the template
LLNotificationTemplatePtr mTemplatep;
@@ -384,6 +391,8 @@ public:
void setResponseFunctor(std::string const &responseFunctorName);
+ void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb);
+
typedef enum e_response_template_type
{
WITHOUT_DEFAULT_BUTTON,
@@ -423,6 +432,10 @@ public:
void respond(const LLSD& sd);
+ void* getResponder() { return mResponderObj; }
+
+ void setResponder(void* responder) { mResponderObj = responder; }
+
void setIgnored(bool ignore);
bool isCancelled() const
@@ -435,6 +448,8 @@ public:
return mRespondedTo;
}
+ const LLSD& getResponse() { return mResponse; }
+
bool isIgnored() const
{
return mIgnored;
@@ -504,6 +519,10 @@ public:
{
return mId;
}
+
+ bool isReusable() { return mIsReusable; }
+
+ void setReusable(bool reusable) { mIsReusable = reusable; }
// comparing two notifications normally means comparing them by UUID (so we can look them
// up quickly this way)
@@ -931,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/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 4087b484aa..e27792dc1d 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -106,7 +106,6 @@ LLRadioGroup::LLRadioGroup(const LLRadioGroup::Params& p)
void LLRadioGroup::initFromParams(const Params& p)
{
- LLUICtrl::initFromParams(p);
for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
it != p.items().end();
++it)
@@ -124,6 +123,9 @@ void LLRadioGroup::initFromParams(const Params& p)
LLRadioCtrl* item = LLUICtrlFactory::create<LLRadioCtrl>(item_params, this);
mRadioButtons.push_back(item);
}
+
+ // call this *after* setting up mRadioButtons so we can handle setValue() calls
+ LLUICtrl::initFromParams(p);
}
@@ -138,10 +140,6 @@ BOOL LLRadioGroup::postBuild()
{
mRadioButtons[0]->setTabStop(true);
}
- if (mControlVariable)
- {
- setSelectedIndex(mControlVariable->getValue().asInteger());
- }
return TRUE;
}
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/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 3cc92baa8d..d17be8b94a 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -185,6 +185,8 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
{
sCount++;
+ mTextWidth = getWidth();
+
// initialize rounded rect image
if (!mRoundedRectImage)
{
@@ -340,7 +342,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
0,
LLFontGL::NO_SHADOW,
string_chars,
- getWidth(),
+ getTextWidth(),
&right_x,
TRUE);
}
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index 5fecf5aade..b1c8901fc4 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -151,11 +151,16 @@ public:
/*virtual*/ const std::string & getToolTip() const;
/*virtual*/ BOOL needsToolTip() const;
+ S32 getTextWidth() const { return mTextWidth;}
+ void setTextWidth(S32 value) { mTextWidth = value;}
+ virtual void setWidth(S32 width) { LLScrollListCell::setWidth(width); mTextWidth = width; }
+
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
private:
LLUIString mText;
+ S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
U8 mUseColor;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index ac4811210b..db0f2bd6e2 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -71,8 +71,9 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
// local structures & classes.
struct SortScrollListItem
{
- SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders)
+ SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal)
: mSortOrders(sort_orders)
+ , mSortSignal(sort_signal)
{}
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
@@ -85,12 +86,20 @@ struct SortScrollListItem
S32 col_idx = it->first;
BOOL sort_ascending = it->second;
+ S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column?
+
const LLScrollListCell *cell1 = i1->getColumn(col_idx);
const LLScrollListCell *cell2 = i2->getColumn(col_idx);
- S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column?
if (cell1 && cell2)
{
- sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
+ if(mSortSignal)
+ {
+ sort_result = order * (*mSortSignal)(col_idx,i1, i2);
+ }
+ else
+ {
+ sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
+ }
if (sort_result != 0)
{
break; // we have a sort order!
@@ -100,8 +109,10 @@ struct SortScrollListItem
return sort_result < 0;
}
+
typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
+ const LLScrollListCtrl::sort_signal_t* mSortSignal;
const sort_order_t& mSortOrders;
};
@@ -169,6 +180,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mOnSortChangedCallback( NULL ),
mHighlightedItem(-1),
mBorder(NULL),
+ mSortCallback(NULL),
mPopupMenu(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
@@ -309,12 +321,9 @@ bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child)
LLScrollListCtrl::~LLScrollListCtrl()
{
- std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
+ delete mSortCallback;
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
+ std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
}
@@ -540,7 +549,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
std::stable_sort(
mItemList.begin(),
mItemList.end(),
- SortScrollListItem(single_sort_column));
+ SortScrollListItem(single_sort_column,mSortCallback));
// ADD_SORTED just sorts by first column...
// this might not match user sort criteria, so flag list as being in unsorted state
@@ -943,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)))
@@ -2395,7 +2404,7 @@ void LLScrollListCtrl::updateSort() const
std::stable_sort(
mItemList.begin(),
mItemList.end(),
- SortScrollListItem(mSortColumns));
+ SortScrollListItem(mSortColumns,mSortCallback));
mSorted = true;
}
@@ -2411,7 +2420,7 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending)
std::stable_sort(
mItemList.begin(),
mItemList.end(),
- SortScrollListItem(sort_column));
+ SortScrollListItem(sort_column,mSortCallback));
}
void LLScrollListCtrl::dirtyColumns()
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index d2d2379328..1f0ef585db 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -73,6 +73,30 @@ public:
// *TODO: Add callbacks to Params
typedef boost::function<void (void)> callback_t;
+
+ template<typename T> struct maximum
+ {
+ typedef T result_type;
+
+ template<typename InputIterator>
+ T operator()(InputIterator first, InputIterator last) const
+ {
+ // If there are no slots to call, just return the
+ // default-constructed value
+ if(first == last ) return T();
+ T max_value = *first++;
+ while (first != last) {
+ if (max_value < *first)
+ max_value = *first;
+ ++first;
+ }
+
+ return max_value;
+ }
+ };
+
+
+ typedef boost::signals2::signal<S32 (S32,const LLScrollListItem*,const LLScrollListItem*),maximum<S32> > sort_signal_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@@ -195,7 +219,10 @@ public:
void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change
void clearHighlightedItems();
- void mouseOverHighlightNthItem( S32 index );
+
+ virtual void mouseOverHighlightNthItem( S32 index );
+
+ S32 getHighlightedItemInx() const { return mHighlightedItem; }
void setDoubleClickCallback( callback_t cb ) { mOnDoubleClickCallback = cb; }
void setMaximumSelectCallback( callback_t cb) { mOnMaximumSelectCallback = cb; }
@@ -352,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)
@@ -362,6 +389,13 @@ public:
void setNeedsSort(bool val = true) { mSorted = !val; }
void dirtyColumns(); // some operation has potentially affected column layout or ordering
+ boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb )
+ {
+ if (!mSortCallback) mSortCallback = new sort_signal_t();
+ return mSortCallback->connect(cb);
+ }
+
+
protected:
// "Full" interface: use this when you're creating a list that has one or more of the following:
// * contains icons
@@ -474,6 +508,8 @@ private:
typedef std::pair<S32, BOOL> sort_column_t;
std::vector<sort_column_t> mSortColumns;
+
+ sort_signal_t* mSortCallback;
}; // end class LLScrollListCtrl
#endif // LL_SCROLLLISTCTRL_H
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index 8075575bab..ec2ad5e5fa 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -44,17 +44,28 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
LLRect srch_btn_rect(p.search_button.left_pad, srch_btn_top, srch_btn_right, p.search_button.top_pad);
+
+ S32 clr_btn_top = p.clear_button.rect.bottom + p.clear_button.rect.height;
+ S32 clr_btn_right = getRect().getWidth() - p.clear_button.pad_right;
+ S32 clr_btn_left = clr_btn_right - p.clear_button.rect.width;
+ LLRect clear_btn_rect(clr_btn_left, clr_btn_top, clr_btn_right, p.clear_button.rect.bottom);
+
S32 text_pad_left = p.text_pad_left;
+ S32 text_pad_right = p.text_pad_right;
if (p.search_button_visible)
text_pad_left += srch_btn_rect.getWidth();
+ if (p.clear_button_visible)
+ text_pad_right = getRect().getWidth() - clr_btn_left + p.clear_button.pad_left;
+
// Set up line editor.
LLLineEditor::Params line_editor_params(p);
line_editor_params.name("filter edit box");
line_editor_params.rect(getLocalRect());
line_editor_params.follows.flags(FOLLOWS_ALL);
line_editor_params.text_pad_left(text_pad_left);
+ line_editor_params.text_pad_right(text_pad_right);
line_editor_params.revert_on_esc(false);
line_editor_params.commit_callback.function(boost::bind(&LLUICtrl::onCommit, this));
line_editor_params.keystroke_callback(boost::bind(&LLSearchEditor::handleKeystroke, this));
@@ -82,10 +93,6 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
// Set up clear button.
LLButton::Params clr_btn_params(p.clear_button);
clr_btn_params.name(std::string("clear button"));
- S32 clr_btn_top = clr_btn_params.rect.bottom + clr_btn_params.rect.height;
- S32 clr_btn_right = getRect().getWidth() - clr_btn_params.pad_right;
- S32 clr_btn_left = clr_btn_right - clr_btn_params.rect.width;
- LLRect clear_btn_rect(clr_btn_left, clr_btn_top, clr_btn_right, p.clear_button.rect.bottom);
clr_btn_params.rect(clear_btn_rect) ;
clr_btn_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
clr_btn_params.tab_stop(false);
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index 714aca9337..785d0633dc 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -66,6 +66,8 @@ public:
}
};
+ void setCommitOnFocusLost(BOOL b) { if (mSearchEditor) mSearchEditor->setCommitOnFocusLost(b); }
+
protected:
LLSearchEditor(const Params&);
friend class LLUICtrlFactory;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 07e4cc22e0..30fc7babae 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -172,6 +172,10 @@ public:
}
}
+ LLIconCtrl* getIconCtrl() const
+ {
+ return mIcon;
+ }
private:
LLIconCtrl* mIcon;
@@ -493,15 +497,15 @@ void LLTabContainer::draw()
if( mIsVertical && has_scroll_arrows )
{
// Redraw the arrows so that they appears on top.
- gGL.pushMatrix();
- gGL.translatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
mPrevArrowBtn->draw();
- gGL.popMatrix();
+ gGL.popUIMatrix();
- gGL.pushMatrix();
- gGL.translatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
mNextArrowBtn->draw();
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
}
@@ -951,7 +955,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLRect tab_panel_rect;
if (!getTabsHidden() && mIsVertical)
{
- tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
+ tab_panel_rect = LLRect(mMinTabWidth + mRightTabBtnOffset + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
LLPANEL_BORDER_WIDTH);
@@ -1629,6 +1633,7 @@ void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
if(button)
{
button->setIcon(icon);
+ reshapeTuple(tuple);
}
}
}
@@ -1639,12 +1644,22 @@ void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
if (!mIsVertical)
{
+ S32 image_overlay_width = 0;
+
+ if(mCustomIconCtrlUsed)
+ {
+ LLCustomButtonIconCtrl* button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
+ LLIconCtrl* icon_ctrl = button ? button->getIconCtrl() : NULL;
+ image_overlay_width = icon_ctrl ? icon_ctrl->getRect().getWidth() : 0;
+ }
+ else
+ {
+ image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
+ }
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
- S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
-
tuple->mPadding = image_overlay_width;
tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 851fb966ec..e08026eaf4 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -246,7 +246,7 @@ LLTextBase::~LLTextBase()
{
// Menu, like any other LLUICtrl, is deleted by its parent - gMenuHolder
- clearSegments();
+ mSegments.clear();
}
void LLTextBase::initFromParams(const LLTextBase::Params& p)
@@ -350,6 +350,8 @@ void LLTextBase::drawSelectionBackground()
S32 segment_line_start = segmentp->getStart() + segment_offset;
S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+ if (segment_line_start > segment_line_end) break;
+
S32 segment_width = 0;
S32 segment_height = 0;
@@ -361,8 +363,11 @@ void LLTextBase::drawSelectionBackground()
selection_rect.mLeft += segment_width;
}
- // if selection spans end of current segment...
- if (selection_right > segment_line_end)
+ // if selection_right == segment_line_end then that means we are the first character of the next segment
+ // or first character of the next line, in either case we want to add the length of the current segment
+ // to the selection rectangle and continue.
+ // if selection right > segment_line_end then selection spans end of current segment...
+ if (selection_right >= segment_line_end)
{
// extend selection slightly beyond end of line
// to indicate selection of newline character (use "n" character to determine width)
@@ -957,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
@@ -1043,6 +1059,13 @@ void LLTextBase::setValue(const LLSD& value )
}
//virtual
+BOOL LLTextBase::canDeselect() const
+{
+ return hasSelection();
+}
+
+
+//virtual
void LLTextBase::deselect()
{
mSelectionStart = 0;
@@ -1813,11 +1836,18 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
const LLTextSegmentPtr segmentp = *line_seg_iter;
S32 segment_line_start = segmentp->getStart() + line_seg_offset;
- S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start;
+ S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd) - segment_line_start;
S32 text_width, text_height;
- segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
- if (local_x < start_x + text_width // cursor to left of right edge of text
- || (hit_past_end_of_line && (segmentp->getEnd() >= line_iter->mDocIndexEnd - 1))) // or this segment wraps to next line
+ bool newline = segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
+
+ // if we've reached a line of text *below* the mouse cursor, doc index is first character on that line
+ if (hit_past_end_of_line && local_y - mVisibleTextRect.mBottom + visible_region.mBottom > line_iter->mRect.mTop)
+ {
+ pos = segment_line_start;
+ break;
+ }
+ if (local_x < start_x + text_width // cursor to left of right edge of text
+ || newline) // or this line ends with a newline, set doc pos to newline char
{
// Figure out which character we're nearest to.
S32 offset;
@@ -1841,6 +1871,13 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
pos = segment_line_start + offset;
break;
}
+ else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd - 1)
+ {
+ // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
+ pos = llmin(getLength(), line_iter->mDocIndexEnd);
+ break;
+ }
+
start_x += text_width;
}
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 caf04339c2..f9a4ed7285 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -39,6 +39,7 @@
// Linden library includes
#include "v2math.h"
+#include "m3math.h"
#include "v4color.h"
#include "llrender.h"
#include "llrect.h"
@@ -85,6 +86,9 @@ std::list<std::string> gUntranslated;
/*static*/ LLHelp* LLUI::sHelpImpl = NULL;
/*static*/ std::vector<std::string> LLUI::sXUIPaths;
/*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
+/*static*/ LLUI::add_popup_t LLUI::sAddPopupFunc;
+/*static*/ LLUI::remove_popup_t LLUI::sRemovePopupFunc;
+/*static*/ LLUI::clear_popups_t LLUI::sClearPopupsFunc;
// register filtereditor here
static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
@@ -180,19 +184,19 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LL
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
{
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
left += LLFontGL::sCurOrigin.mX;
right += LLFontGL::sCurOrigin.mX;
bottom += LLFontGL::sCurOrigin.mY;
top += LLFontGL::sCurOrigin.mY;
- glLoadIdentity();
+ gGL.loadUIIdentity();
gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset,
llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset,
llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset,
llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset,
filled);
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
@@ -203,7 +207,7 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
// Counterclockwise quad will face the viewer
if( filled )
- {
+ {
gGL.begin( LLRender::QUADS );
gGL.vertex2i(left, top);
gGL.vertex2i(left, bottom);
@@ -508,9 +512,9 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
}
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
{
- gGL.translatef((F32)x, (F32)y, 0.f);
+ gGL.translateUI((F32)x, (F32)y, 0.f);
gGL.getTexUnit(0)->bind(image);
@@ -637,7 +641,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
}
gGL.end();
}
- gGL.popMatrix();
+ gGL.popUIMatrix();
if (solid_color)
{
@@ -660,39 +664,72 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
LLGLSUIDefault gls_ui;
- gGL.pushMatrix();
+
+ gGL.getTexUnit(0)->bind(image);
+
+ gGL.color4fv(color.mV);
+
+ if (degrees == 0.f)
{
- gGL.translatef((F32)x, (F32)y, 0.f);
- if( degrees )
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)x, (F32)y, 0.f);
+
+ gGL.begin(LLRender::QUADS);
{
- F32 offset_x = F32(width/2);
- F32 offset_y = F32(height/2);
- gGL.translatef( offset_x, offset_y, 0.f);
- glRotatef( degrees, 0.f, 0.f, 1.f );
- gGL.translatef( -offset_x, -offset_y, 0.f );
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+ gGL.vertex2i(width, height );
+
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+ gGL.vertex2i(0, height );
+
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+ gGL.vertex2i(0, 0);
+
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+ gGL.vertex2i(width, 0);
}
+ gGL.end();
+ gGL.popUIMatrix();
+ }
+ else
+ {
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)x, (F32)y, 0.f);
+
+ F32 offset_x = F32(width/2);
+ F32 offset_y = F32(height/2);
+ gGL.translateUI(offset_x, offset_y, 0.f);
+
+ LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+
gGL.getTexUnit(0)->bind(image);
gGL.color4fv(color.mV);
gGL.begin(LLRender::QUADS);
{
+ LLVector3 v;
+
+ v = LLVector3(offset_x, offset_y, 0.f) * quat;
gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, height );
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ v = LLVector3(-offset_x, offset_y, 0.f) * quat;
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, height );
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, 0);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ v = LLVector3(offset_x, -offset_y, 0.f) * quat;
gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, 0);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
}
gGL.end();
+ gGL.popUIMatrix();
}
- gGL.popMatrix();
}
@@ -747,9 +784,9 @@ void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F
end_angle += F_TWO_PI;
}
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
{
- gGL.translatef(center_x, center_y, 0.f);
+ gGL.translateUI(center_x, center_y, 0.f);
// Inexact, but reasonably fast.
F32 delta = (end_angle - start_angle) / steps;
@@ -780,15 +817,15 @@ void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F
}
gGL.end();
}
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
{
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.translatef(center_x, center_y, 0.f);
+ gGL.translateUI(center_x, center_y, 0.f);
// Inexact, but reasonably fast.
F32 delta = F_TWO_PI / steps;
@@ -819,7 +856,7 @@ void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled
}
gGL.end();
}
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
// Renders a ring with sides (tube shape)
@@ -846,9 +883,9 @@ void gl_deep_circle( F32 radius, F32 depth, S32 steps )
void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
{
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
{
- gGL.translatef(0.f, 0.f, -width / 2);
+ gGL.translateUI(0.f, 0.f, -width / 2);
if( render_center )
{
gGL.color4fv(center_color.mV);
@@ -857,11 +894,11 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
else
{
gl_washer_2d(radius, radius - width, steps, side_color, side_color);
- gGL.translatef(0.f, 0.f, width);
+ gGL.translateUI(0.f, 0.f, width);
gl_washer_2d(radius - width, radius, steps, side_color, side_color);
}
}
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
// Draw gray and white checkerboard with black border
@@ -1050,9 +1087,9 @@ void gl_segmented_rect_2d_tex(const S32 left,
S32 width = llabs(right - left);
S32 height = llabs(top - bottom);
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
- gGL.translatef((F32)left, (F32)bottom, 0.f);
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
if (border_uv_scale.mV[VX] > 0.5f)
@@ -1193,7 +1230,7 @@ void gl_segmented_rect_2d_tex(const S32 left,
}
gGL.end();
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
void gl_segmented_rect_2d_fragment_tex(const S32 left,
@@ -1210,9 +1247,9 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
S32 width = llabs(right - left);
S32 height = llabs(top - bottom);
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
- gGL.translatef((F32)left, (F32)bottom, 0.f);
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
if (border_uv_scale.mV[VX] > 0.5f)
@@ -1383,7 +1420,7 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
}
gGL.end();
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width,
@@ -1573,6 +1610,13 @@ void LLUI::cleanupClass()
sImageProvider->cleanUp();
}
+void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups)
+{
+ sAddPopupFunc = add_popup;
+ sRemovePopupFunc = remove_popup;
+ sClearPopupsFunc = clear_popups;
+}
+
//static
void LLUI::dirtyRect(LLRect rect)
{
@@ -1591,7 +1635,7 @@ void LLUI::dirtyRect(LLRect rect)
//static
void LLUI::translate(F32 x, F32 y, F32 z)
{
- gGL.translatef(x,y,z);
+ gGL.translateUI(x,y,z);
LLFontGL::sCurOrigin.mX += (S32) x;
LLFontGL::sCurOrigin.mY += (S32) y;
LLFontGL::sCurOrigin.mZ += z;
@@ -1600,14 +1644,14 @@ void LLUI::translate(F32 x, F32 y, F32 z)
//static
void LLUI::pushMatrix()
{
- gGL.pushMatrix();
+ gGL.pushUIMatrix();
LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin);
}
//static
void LLUI::popMatrix()
{
- gGL.popMatrix();
+ gGL.popUIMatrix();
LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin();
LLFontGL::sOriginStack.pop_back();
}
@@ -1615,7 +1659,7 @@ void LLUI::popMatrix()
//static
void LLUI::loadIdentity()
{
- glLoadIdentity();
+ gGL.loadUIIdentity();
LLFontGL::sCurOrigin.mX = 0;
LLFontGL::sCurOrigin.mY = 0;
LLFontGL::sCurOrigin.mZ = 0;
@@ -1843,6 +1887,39 @@ LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
return *sSettingGroups["config"]; // default group
}
+//static
+void LLUI::addPopup(LLView* viewp)
+{
+ if (sAddPopupFunc)
+ {
+ sAddPopupFunc(viewp);
+ }
+}
+
+//static
+void LLUI::removePopup(LLView* viewp)
+{
+ if (sRemovePopupFunc)
+ {
+ sRemovePopupFunc(viewp);
+ }
+}
+
+//static
+void LLUI::clearPopups()
+{
+ if (sClearPopupsFunc)
+ {
+ sClearPopupsFunc();
+ }
+}
+
+//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)
@@ -1943,6 +2020,7 @@ namespace LLInitParam
{
setBlockFromValue();
addSynonym(name, "");
+ setBlockFromValue();
}
void TypedParam<const LLFontGL*>::setValueFromBlock() const
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index af8d4ea03b..c18262ef76 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -160,12 +160,17 @@ public:
// Methods
//
typedef std::map<std::string, LLControlGroup*> settings_map_t;
+ typedef boost::function<void(LLView*)> add_popup_t;
+ typedef boost::function<void(LLView*)> remove_popup_t;
+ typedef boost::function<void(void)> clear_popups_t;
+
static void initClass(const settings_map_t& settings,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback = NULL,
const LLVector2 *scale_factor = NULL,
const std::string& language = LLStringUtil::null);
static void cleanupClass();
+ static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& );
static void pushMatrix();
static void popMatrix();
@@ -208,6 +213,12 @@ public:
static void resetMouseIdleTimer() { sMouseIdleTimer.reset(); }
static LLWindow* getWindow() { return sWindow; }
+ static void addPopup(LLView*);
+ 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
@@ -227,6 +238,9 @@ private:
static LLImageProviderInterface* sImageProvider;
static std::vector<std::string> sXUIPaths;
static LLFrameTimer sMouseIdleTimer;
+ static add_popup_t sAddPopupFunc;
+ static remove_popup_t sRemovePopupFunc;
+ static clear_popups_t sClearPopupsFunc;
};
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 3c73ae9b0c..736de651da 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -34,6 +34,8 @@
#include "linden_common.h"
#include "llurlentry.h"
#include "lluri.h"
+#include "llurlmatch.h"
+#include "llurlregistry.h"
#include "llcachename.h"
#include "lltrans.h"
@@ -232,7 +234,7 @@ std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const
LLUrlEntrySLURL::LLUrlEntrySLURL()
{
// see http://slurl.com/about.php for details on the SLURL format
- mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_slurl.xml";
mTooltip = LLTrans::getString("TooltipSLURL");
@@ -320,6 +322,38 @@ void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
callObservers(id.asString(), first + " " + last);
}
+std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
+{
+ // return a tooltip corresponding to the URL type instead of the generic one
+ std::string url = getUrl(string);
+
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("TooltipAgentMute");
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("TooltipAgentUnmute");
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("TooltipAgentIM");
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("TooltipAgentPay");
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("TooltipAgentOfferTeleport");
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("TooltipAgentRequestFriend");
+ }
+ return LLTrans::getString("TooltipAgentUrl");
+}
+
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (!gCacheName)
@@ -343,6 +377,31 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
else if (gCacheName->getFullName(agent_id, full_name))
{
+ // customize label string based on agent SLapp suffix
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("SLappAgentMute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("SLappAgentIM") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("SLappAgentPay") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
+ }
return full_name;
}
else
@@ -434,6 +493,35 @@ 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
@@ -602,6 +690,20 @@ std::string LLUrlEntrySLLabel::getUrl(const std::string &string) const
return getUrlFromWikiLink(string);
}
+std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
+{
+ // return a tooltip corresponding to the URL type instead of the generic one (EXT-4574)
+ std::string url = getUrl(string);
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return match.getTooltip();
+ }
+
+ // unrecognized URL? should not happen
+ return LLUrlEntryBase::getTooltip(string);
+}
+
//
// LLUrlEntryWorldMap Describes secondlife:///<location> URLs
//
@@ -630,7 +732,7 @@ std::string LLUrlEntryWorldMap::getLabel(const std::string &url, const LLUrlLabe
}
const std::string label = LLTrans::getString("SLurlLabelShowOnMap");
- std::string location = path_array[2];
+ std::string location = unescapeUrl(path_array[2]);
std::string x = (path_parts > 3) ? path_array[3] : "128";
std::string y = (path_parts > 4) ? path_array[4] : "128";
std::string z = (path_parts > 5) ? path_array[5] : "0";
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 3abada0f24..29575d752c 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -83,7 +83,7 @@ public:
LLUIColor getColor() const { return mColor; }
/// Given a matched Url, return a tooltip string for the hyperlink
- std::string getTooltip() const { return mTooltip; }
+ virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
@@ -169,6 +169,7 @@ class LLUrlEntryAgent : public LLUrlEntryBase
public:
LLUrlEntryAgent();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getTooltip(const std::string &string) const;
private:
void onAgentNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group);
@@ -200,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.,
@@ -257,6 +270,7 @@ public:
LLUrlEntrySLLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
+ /*virtual*/ std::string getTooltip(const std::string &string) const;
};
///
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 722dbe41b3..0a70aa586a 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -53,8 +53,10 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryParcel());
registerUrl(new LLUrlEntryTeleport());
registerUrl(new LLUrlEntryWorldMap());
+ registerUrl(new LLUrlEntryObjectIM());
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());
@@ -174,7 +176,7 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match.setValues(match_start, match_end,
match_entry->getUrl(url),
match_entry->getLabel(url, cb),
- match_entry->getTooltip(),
+ match_entry->getTooltip(url),
match_entry->getIcon(),
match_entry->getColor(),
match_entry->getMenuName(),
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 63e627ceb5..781c111474 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -73,9 +73,9 @@ S32 LLView::sLastBottomXML = S32_MIN;
std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
-#if LL_DEBUG
+//#if LL_DEBUG
BOOL LLView::sIsDrawing = FALSE;
-#endif
+//#endif
// Compiler optimization, generate extern template
template class LLView* LLView::getChild<class LLView>(
@@ -150,6 +150,10 @@ LLView::~LLView()
{
dirtyRect();
//llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
+ if (LLView::sIsDrawing)
+ {
+ lldebugs << "Deleting view " << mName << " during UI draw() phase" << llendl;
+ }
// llassert(LLView::sIsDrawing == FALSE);
// llassert_always(sDepth == 0); // avoid deleting views while drawing! It can subtly break list iterators
@@ -592,11 +596,6 @@ void LLView::setVisible(BOOL visible)
{
if ( mVisible != visible )
{
- if( !visible && (gFocusMgr.getTopCtrl() == this) )
- {
- gFocusMgr.setTopCtrl( NULL );
- }
-
mVisible = visible;
// notify children of visibility change if root, or part of visible hierarchy
@@ -1326,7 +1325,6 @@ void LLView::drawChildren()
localRectToScreen(viewp->getRect(),&screenRect);
if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
{
- glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
{
LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
@@ -1350,8 +1348,6 @@ void LLView::drawChildren()
}
--sDepth;
}
-
- gGL.getTexUnit(0)->disable();
}
void LLView::dirtyRect()
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index c4d7313743..efae00f0e5 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -171,9 +171,9 @@ private:
// widgets in general are not copyable
LLView(const LLView& other) {};
public:
-#if LL_DEBUG
+//#if LL_DEBUG
static BOOL sIsDrawing;
-#endif
+//#endif
enum ESoundFlags
{
SILENT = 0,
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index 30717f87de..bd9c43c97f 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -125,14 +125,6 @@ void LLViewBorder::draw()
llassert( FALSE ); // not implemented
}
}
- else
- if( STYLE_TEXTURE == mStyle )
- {
- if( mTexture )
- {
- drawTextures();
- }
- }
LLView::draw();
}
@@ -255,56 +247,6 @@ void LLViewBorder::drawTwoPixelLines()
gl_line_2d(left+1, bottom+1, right-1, bottom+1);
}
-void LLViewBorder::drawTextures()
-{
- //LLGLSUIDefault gls_ui;
-
- //llassert( FALSE ); // TODO: finish implementing
-
- //gGL.color4fv(UI_VERTEX_COLOR.mV);
-
- //gGL.getTexUnit(0)->bind(mTexture);
- //gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
-
- //drawTextureTrapezoid( 0.f, mBorderWidth, getRect().getWidth(), 0, 0 );
- //drawTextureTrapezoid( 90.f, mBorderWidth, getRect().getHeight(), (F32)getRect().getWidth(),0 );
- //drawTextureTrapezoid( 180.f, mBorderWidth, getRect().getWidth(), (F32)getRect().getWidth(),(F32)getRect().getHeight() );
- //drawTextureTrapezoid( 270.f, mBorderWidth, getRect().getHeight(), 0, (F32)getRect().getHeight() );
-}
-
-
-void LLViewBorder::drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y )
-{
- gGL.pushMatrix();
- {
- gGL.translatef(start_x, start_y, 0.f);
- glRotatef( degrees, 0, 0, 1 );
-
- gGL.begin(LLRender::QUADS);
- {
- // width, width /---------\ length-width, width //
- // / \ //
- // / \ //
- // /---------------\ //
- // 0,0 length, 0 //
-
- gGL.texCoord2f( 0, 0 );
- gGL.vertex2i( 0, 0 );
-
- gGL.texCoord2f( (GLfloat)length, 0 );
- gGL.vertex2i( length, 0 );
-
- gGL.texCoord2f( (GLfloat)(length - width), (GLfloat)width );
- gGL.vertex2i( length - width, width );
-
- gGL.texCoord2f( (GLfloat)width, (GLfloat)width );
- gGL.vertex2i( width, width );
- }
- gGL.end();
- }
- gGL.popMatrix();
-}
-
BOOL LLViewBorder::getBevelFromAttribute(LLXMLNodePtr node, LLViewBorder::EBevel& bevel_style)
{
if (node->hasAttribute("bevel_style"))
diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h
index 92fd569325..342e84fd93 100644
--- a/indra/llui/llviewborder.h
+++ b/indra/llui/llviewborder.h
@@ -99,8 +99,7 @@ private:
void drawOnePixelLines();
void drawTwoPixelLines();
void drawTextures();
- void drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y );
-
+
EBevel mBevel;
EStyle mStyle;
LLUIColor mHighlightLight;