summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2010-02-22 14:15:58 -0500
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2010-02-22 14:15:58 -0500
commitbd84d36c9d08878c895c896e097e8e3310b61cf3 (patch)
treee2e333ba15c131dfb25c4baf54bcb98fd2a3bd46 /indra/llui
parent00fdc0acd5e27d353c070706e838a35bf889a536 (diff)
parent04712617c55c53dbec1f73a4e8834ebe3167e5ed (diff)
merge
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp97
-rw-r--r--indra/llui/llaccordionctrl.h3
-rw-r--r--indra/llui/llbutton.h2
-rw-r--r--indra/llui/llconsole.cpp3
-rw-r--r--indra/llui/llfloater.cpp18
-rw-r--r--indra/llui/llkeywords.cpp82
-rw-r--r--indra/llui/llkeywords.h29
-rw-r--r--indra/llui/llmenugl.cpp40
-rw-r--r--indra/llui/llmenugl.h10
-rw-r--r--indra/llui/llpanel.cpp10
-rw-r--r--indra/llui/llpanel.h8
-rw-r--r--indra/llui/llresizehandle.cpp86
-rw-r--r--indra/llui/llsearcheditor.cpp2
-rw-r--r--indra/llui/lltabcontainer.cpp3
-rw-r--r--indra/llui/lltextbase.cpp40
-rw-r--r--indra/llui/lltextbase.h8
16 files changed, 339 insertions, 102 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index d0c73fbfbc..aa69dfe0cc 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -103,6 +103,13 @@ 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);
+ */
}
@@ -338,36 +345,55 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
}
-
-void LLAccordionCtrl::arrange()
+void LLAccordionCtrl::arrangeSinge()
{
- if( mAccordionTabs.size() == 0)
- {
- //We do not arrange if we do not have what should be arranged
- return;
- }
-
- //Calculate params
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
+ S32 panel_height;
-
- if(mAccordionTabs.size() == 1)
+ S32 collapsed_height = 0;
+
+ for(size_t i=0;i<mAccordionTabs.size();++i)
{
- LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
-
- LLRect panel_rect = accordion_tab->getRect();
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
- S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
+ if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
+ continue;
+ if(!accordion_tab->isExpanded() )
+ {
+ collapsed_height+=mAccordionTabs[i]->getRect().getHeight();
+ }
+ }
- ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
+ S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height;
+
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
- show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
- return;
-
+ if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
+ continue;
+ if(!accordion_tab->isExpanded() )
+ {
+ panel_height = accordion_tab->getRect().getHeight();
+ }
+ else
+ {
+ panel_height = expanded_height;
+ }
+ ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
+ panel_top-=mAccordionTabs[i]->getRect().getHeight();
}
+}
+
+void LLAccordionCtrl::arrangeMultiple()
+{
+ S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
+ S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
+ S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
+ //Calculate params
for(size_t i = 0; i < mAccordionTabs.size(); i++ )
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
@@ -415,7 +441,40 @@ void LLAccordionCtrl::arrange()
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(),getRect().getHeight());
+}
+
+
+void LLAccordionCtrl::arrange()
+{
+ if( mAccordionTabs.size() == 0)
+ {
+ //We do not arrange if we do not have what should be arranged
+ return;
+ }
+
+ if(mAccordionTabs.size() == 1)
+ {
+ S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
+ S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
+
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
+
+ LLRect panel_rect = accordion_tab->getRect();
+
+ S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
+
+ ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
+
+ show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+ return;
+
+ }
+
+ if(mSingleExpansion)
+ arrangeSinge ();
+ else
+ arrangeMultiple ();
}
//---------------------------------------------------------------------------------
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index d57a42df32..7c29e545b7 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -105,6 +105,9 @@ public:
void reset ();
private:
+ void arrangeSinge();
+ void arrangeMultiple();
+
// Calc Splitter's height that is necessary to display all child content
S32 calcRecuiredHeight();
S32 getRecuiredHeight() const { return mInnerRect.getHeight(); }
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 8f35db1007..6a0d8ef3d6 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -257,6 +257,8 @@ public:
void setForcePressedState(bool b) { mForcePressedState = b; }
+ void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; }
+
protected:
LLPointer<LLUIImage> getImageUnselected() const { return mImageUnselected; }
LLPointer<LLUIImage> getImageSelected() const { return mImageSelected; }
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index a4f69e7ac1..badbddc3cc 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -300,7 +300,8 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, b
S32 paragraph_offset = 0; //Offset into the paragraph text.
// Wrap lines that are longer than the view is wide.
- while( paragraph_offset < (S32)mParagraphText.length() )
+ while( paragraph_offset < (S32)mParagraphText.length() &&
+ mParagraphText[paragraph_offset] != 0)
{
S32 skip_chars; // skip '\n'
// Figure out if a word-wrapped line fits here.
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 0199fe3f57..b6d73cda3c 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1574,22 +1574,25 @@ void LLFloater::draw()
LLUIImage* image = NULL;
LLColor4 color;
+ LLColor4 overlay_color;
if (isBackgroundOpaque())
{
// NOTE: image may not be set
image = getBackgroundImage();
color = getBackgroundColor();
+ overlay_color = getBackgroundImageOverlay();
}
else
{
image = getTransparentImage();
color = getTransparentColor();
+ overlay_color = getTransparentImageOverlay();
}
if (image)
{
// We're using images for this floater's backgrounds
- image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha);
+ image->draw(getLocalRect(), overlay_color % alpha);
}
else
{
@@ -2387,10 +2390,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
LLRect new_rect;
new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height);
- floater->reshape( new_width, new_height, TRUE );
- floater->setRect(new_rect);
+ floater->setShape(new_rect);
- floater->translateIntoRect( getLocalRect(), false );
+ if (floater->followsRight())
+ {
+ floater->translate(old_width - new_width, 0);
+ }
+
+ if (floater->followsTop())
+ {
+ floater->translate(0, old_height - new_height);
+ }
}
}
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index ede32084d0..75342afbe2 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
llassert(0);
}
}
+LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
+{
+ if(other.mOwner)
+ {
+ copyData(other.mData, other.mLength);
+ }
+ else
+ {
+ mOwner = false;
+ mLength = other.mLength;
+ mData = other.mData;
+ }
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
+{
+ copyData(str.data(), str.size());
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
+mData(start), mLength(length), mOwner(false)
+{
+}
+
+LLKeywords::WStringMapIndex::~WStringMapIndex()
+{
+ if(mOwner)
+ delete[] mData;
+}
+
+void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
+{
+ llwchar *data = new llwchar[length];
+ memcpy((void*)data, (const void*)start, length * sizeof(llwchar));
+
+ mOwner = true;
+ mLength = length;
+ mData = data;
+}
+
+bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const
+{
+ // NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
+ // The comparison only needs to strictly order all possible strings, and be stable.
+
+ bool result = false;
+ const llwchar* self_iter = mData;
+ const llwchar* self_end = mData + mLength;
+ const llwchar* other_iter = other.mData;
+ const llwchar* other_end = other.mData + other.mLength;
+
+ while(true)
+ {
+ if(other_iter >= other_end)
+ {
+ // We've hit the end of other.
+ // This covers two cases: other being shorter than self, or the strings being equal.
+ // In either case, we want to return false.
+ result = false;
+ break;
+ }
+ else if(self_iter >= self_end)
+ {
+ // self is shorter than other.
+ result = true;
+ break;
+ }
+ else if(*self_iter != *other_iter)
+ {
+ // The current character differs. The strings are not equal.
+ result = *self_iter < *other_iter;
+ break;
+ }
+
+ self_iter++;
+ other_iter++;
+ }
+
+ return result;
+}
LLColor3 LLKeywords::readColor( const std::string& s )
{
@@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_len = p - cur;
if( seg_len > 0 )
{
- LLWString word( cur, 0, seg_len );
+ WStringMapIndex word( cur, seg_len );
word_token_map_t::iterator map_iter = mWordTokenMap.find(word);
if( map_iter != mWordTokenMap.end() )
{
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 53377869ca..e5b66dfa56 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -92,8 +92,33 @@ public:
const std::string& key,
const LLColor3& color,
const std::string& tool_tip = LLStringUtil::null);
-
- typedef std::map<LLWString, LLKeywordToken*> word_token_map_t;
+
+ // This class is here as a performance optimization.
+ // The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
+ // This worked, but caused a performance bottleneck due to memory allocation and string copies
+ // because it's not possible to search such a map without creating an LLWString.
+ // Using this class as the map index instead allows us to search using segments of an existing
+ // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
+ class WStringMapIndex
+ {
+ public:
+ // copy constructor
+ WStringMapIndex(const WStringMapIndex& other);
+ // constructor from a string (copies the string's data into the new object)
+ WStringMapIndex(const LLWString& str);
+ // constructor from pointer and length
+ // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
+ WStringMapIndex(const llwchar *start, size_t length);
+ ~WStringMapIndex();
+ bool operator<(const WStringMapIndex &other) const;
+ private:
+ void copyData(const llwchar *start, size_t length);
+ const llwchar *mData;
+ size_t mLength;
+ bool mOwner;
+ };
+
+ typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
typedef word_token_map_t::const_iterator keyword_iterator_t;
keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
keyword_iterator_t end() const { return mWordTokenMap.end(); }
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index d18abbfb2f..0d56c5ed31 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -657,11 +657,38 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void )
// Class LLMenuItemTearOffGL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p)
-: LLMenuItemGL(p),
- mParentHandle(p.parent_floater_handle)
+: LLMenuItemGL(p)
{
}
+// Returns the first floater ancestor if there is one
+LLFloater* LLMenuItemTearOffGL::getParentFloater()
+{
+ LLView* parent_view = getMenu();
+
+ while (parent_view)
+ {
+ if (dynamic_cast<LLFloater*>(parent_view))
+ {
+ return dynamic_cast<LLFloater*>(parent_view);
+ }
+
+ bool parent_is_menu = dynamic_cast<LLMenuGL*>(parent_view) && !dynamic_cast<LLMenuBarGL*>(parent_view);
+
+ if (parent_is_menu)
+ {
+ // use menu parent
+ parent_view = dynamic_cast<LLMenuGL*>(parent_view)->getParentMenuItem();
+ }
+ else
+ {
+ // just use regular view parent
+ parent_view = parent_view->getParent();
+ }
+ }
+
+ return NULL;
+}
void LLMenuItemTearOffGL::onCommit()
{
@@ -680,7 +707,7 @@ void LLMenuItemTearOffGL::onCommit()
getMenu()->needsArrange();
- LLFloater* parent_floater = mParentHandle.get();
+ LLFloater* parent_floater = getParentFloater();
LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu());
if (tear_off_menu)
@@ -1671,7 +1698,6 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mSpilloverMenu(NULL),
mJumpKey(p.jump_key),
mCreateJumpKeys(p.create_jump_keys),
- mParentFloaterHandle(p.parent_floater),
mNeedsArrange(FALSE),
mShortcutPad(p.shortcut_pad)
{
@@ -1699,7 +1725,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
void LLMenuGL::initFromParams(const LLMenuGL::Params& p)
{
LLUICtrl::initFromParams(p);
- setCanTearOff(p.can_tear_off, p.parent_floater);
+ setCanTearOff(p.can_tear_off);
}
// Destroys the object
@@ -1711,12 +1737,11 @@ LLMenuGL::~LLMenuGL( void )
mJumpKeys.clear();
}
-void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle )
+void LLMenuGL::setCanTearOff(BOOL tear_off)
{
if (tear_off && mTearOffItem == NULL)
{
LLMenuItemTearOffGL::Params p;
- p.parent_floater_handle = parent_floater_handle;
mTearOffItem = LLUICtrlFactory::create<LLMenuItemTearOffGL>(p);
addChildInBack(mTearOffItem);
}
@@ -2233,7 +2258,6 @@ void LLMenuGL::createSpilloverBranch()
LLMenuGL::Params p;
p.name("More");
p.label("More"); // *TODO: Translate
- p.parent_floater(mParentFloaterHandle);
p.bg_color(mBackgroundColor);
p.bg_visible(true);
p.can_tear_off(false);
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 8441aaadd4..39d1986461 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -355,7 +355,6 @@ class LLMenuGL
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
- Optional<LLHandle<LLFloater> > parent_floater;
Optional<KEY> jump_key;
Optional<bool> horizontal_layout,
can_tear_off,
@@ -430,7 +429,7 @@ public:
void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
- void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
+ void setCanTearOff(BOOL tear_off);
// add a separator to this menu
virtual BOOL addSeparator();
@@ -553,7 +552,6 @@ private:
class LLMenuItemTearOffGL* mTearOffItem;
class LLMenuItemBranchGL* mSpilloverBranch;
LLMenuGL* mSpilloverMenu;
- LLHandle<LLFloater> mParentFloaterHandle;
KEY mJumpKey;
BOOL mCreateJumpKeys;
S32 mShortcutPad;
@@ -814,7 +812,6 @@ class LLMenuItemTearOffGL : public LLMenuItemGL
public:
struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
{
- Optional<LLHandle<LLFloater> > parent_floater_handle;
Params()
{
name = "tear off";
@@ -823,13 +820,12 @@ public:
};
LLMenuItemTearOffGL( const Params& );
-
+
virtual void onCommit(void);
virtual void draw(void);
virtual U32 getNominalHeight() const;
-private:
- LLHandle<LLFloater> mParentHandle;
+ LLFloater* getParentFloater();
};
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index d963cf4c98..0cd052eefa 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -80,6 +80,8 @@ LLPanel::Params::Params()
background_opaque("background_opaque", false),
bg_opaque_color("bg_opaque_color"),
bg_alpha_color("bg_alpha_color"),
+ bg_opaque_image_overlay("bg_opaque_image_overlay"),
+ bg_alpha_image_overlay("bg_alpha_image_overlay"),
bg_opaque_image("bg_opaque_image"),
bg_alpha_image("bg_alpha_image"),
min_width("min_width", 100),
@@ -103,6 +105,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mBgOpaque(p.background_opaque),
mBgOpaqueColor(p.bg_opaque_color()),
mBgAlphaColor(p.bg_alpha_color()),
+ mBgOpaqueImageOverlay(p.bg_opaque_image_overlay),
+ mBgAlphaImageOverlay(p.bg_alpha_image_overlay),
mBgOpaqueImage(p.bg_opaque_image()),
mBgAlphaImage(p.bg_alpha_image()),
mDefaultBtn(NULL),
@@ -199,7 +203,7 @@ void LLPanel::draw()
// opaque, in-front look
if (mBgOpaqueImage.notNull())
{
- mBgOpaqueImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+ mBgOpaqueImage->draw( local_rect, mBgOpaqueImageOverlay % alpha );
}
else
{
@@ -212,7 +216,7 @@ void LLPanel::draw()
// transparent, in-back look
if (mBgAlphaImage.notNull())
{
- mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+ mBgAlphaImage->draw( local_rect, mBgAlphaImageOverlay % alpha );
}
else
{
@@ -481,6 +485,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
setTransparentColor(p.bg_alpha_color().get());
mBgOpaqueImage = p.bg_opaque_image();
mBgAlphaImage = p.bg_alpha_image();
+ mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
+ mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
}
static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 4e53fd7ea3..03e3dc0c0e 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -77,7 +77,9 @@ public:
background_opaque;
Optional<LLUIColor> bg_opaque_color,
- bg_alpha_color;
+ bg_alpha_color,
+ bg_opaque_image_overlay,
+ bg_alpha_image_overlay;
// opaque image is for "panel in foreground" look
Optional<LLUIImage*> bg_opaque_image,
bg_alpha_image;
@@ -137,6 +139,8 @@ public:
const LLColor4& getTransparentColor() const { return mBgAlphaColor; }
LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; }
LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; }
+ LLColor4 getBackgroundImageOverlay() { return mBgOpaqueImageOverlay; }
+ LLColor4 getTransparentImageOverlay() { return mBgAlphaImageOverlay; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
BOOL isBackgroundVisible() const { return mBgVisible; }
void setBackgroundOpaque(BOOL b) { mBgOpaque = b; }
@@ -262,6 +266,8 @@ private:
BOOL mBgOpaque; // use opaque color or image
LLUIColor mBgOpaqueColor;
LLUIColor mBgAlphaColor;
+ LLUIColor mBgOpaqueImageOverlay;
+ LLUIColor mBgAlphaImageOverlay;
LLPointer<LLUIImage> mBgOpaqueImage; // "panel in front" look
LLPointer<LLUIImage> mBgAlphaImage; // "panel in back" look
LLViewBorder* mBorder;
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index 3df09d124a..00214d451c 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -124,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
{
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
-
+
S32 screen_x;
S32 screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
@@ -136,9 +136,10 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
if( resizing_view )
{
// undock floater when user resize it
- if (((LLFloater*)getParent())->isDocked())
+ LLFloater* floater_parent = dynamic_cast<LLFloater*>(getParent());
+ if (floater_parent && floater_parent->isDocked())
{
- ((LLFloater*)getParent())->setDocked(false, false);
+ floater_parent->setDocked(false, false);
}
// Resize the parent
@@ -146,61 +147,68 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
LLRect scaled_rect = orig_rect;
S32 delta_x = screen_x - mDragLastScreenX;
S32 delta_y = screen_y - mDragLastScreenY;
-
- if(delta_x == 0 && delta_y == 0)
- return FALSE;
-
LLCoordGL mouse_dir;
// use hysteresis on mouse motion to preserve user intent when mouse stops moving
mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
-
mLastMouseScreenX = screen_x;
mLastMouseScreenY = screen_y;
mLastMouseDir = mouse_dir;
- S32 new_width = orig_rect.getWidth();
- S32 new_height = orig_rect.getHeight();
+ S32 x_multiple = 1;
+ S32 y_multiple = 1;
+ switch( mCorner )
+ {
+ case LEFT_TOP:
+ x_multiple = -1;
+ y_multiple = 1;
+ break;
+ case LEFT_BOTTOM:
+ x_multiple = -1;
+ y_multiple = -1;
+ break;
+ case RIGHT_TOP:
+ x_multiple = 1;
+ y_multiple = 1;
+ break;
+ case RIGHT_BOTTOM:
+ x_multiple = 1;
+ y_multiple = -1;
+ break;
+ }
- S32 new_pos_x = orig_rect.mLeft;
- S32 new_pos_y = orig_rect.mTop;
+ S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
+ if( new_width < mMinWidth )
+ {
+ new_width = mMinWidth;
+ delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
+ }
+
+ S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
+ if( new_height < mMinHeight )
+ {
+ new_height = mMinHeight;
+ delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
+ }
switch( mCorner )
{
- case LEFT_TOP:
- new_width-=delta_x;
- new_height+=delta_y;
- new_pos_x+=delta_x;
- new_pos_y+=delta_y;
+ case LEFT_TOP:
+ scaled_rect.translate(delta_x, 0);
break;
case LEFT_BOTTOM:
- new_width-=delta_x;
- new_height-=delta_y;
- new_pos_x+=delta_x;
+ scaled_rect.translate(delta_x, delta_y);
break;
case RIGHT_TOP:
- new_width+=delta_x;
- new_height+=delta_y;
- new_pos_y+=delta_y;
break;
case RIGHT_BOTTOM:
- new_width+=delta_x;
- new_height-=delta_y;
+ scaled_rect.translate(0, delta_y);
break;
}
- new_width = llmax(new_width,mMinWidth);
- new_height = llmax(new_height,mMinHeight);
-
- LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth();
- LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight();
-
- new_width = llmin(new_width, screen_width);
- new_height = llmin(new_height, screen_height);
-
// temporarily set new parent rect
- scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height);
-
+ scaled_rect.mRight = scaled_rect.mLeft + new_width;
+ scaled_rect.mTop = scaled_rect.mBottom + new_height;
resizing_view->setRect(scaled_rect);
LLView* snap_view = NULL;
@@ -251,11 +259,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
resizing_view->setRect(orig_rect);
// translate and scale to new shape
- resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight());
- resizing_view->setRect(scaled_rect);
- //set shape to handle dependent floaters...
- resizing_view->handleReshape(scaled_rect, false);
-
+ resizing_view->setShape(scaled_rect, true);
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = resizing_view->getRect();
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index 491eeeab54..8075575bab 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -156,7 +156,7 @@ void LLSearchEditor::setFocus( BOOL b )
void LLSearchEditor::onClearButtonClick(const LLSD& data)
{
setText(LLStringUtil::null);
- mSearchEditor->doDelete(); // force keystroke callback
+ mSearchEditor->onCommit(); // force keystroke callback
}
void LLSearchEditor::handleKeystroke()
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index e810b6fe8f..07e4cc22e0 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -214,7 +214,8 @@ LLTabContainer::Params::Params()
last_tab("last_tab"),
use_custom_icon_ctrl("use_custom_icon_ctrl", false),
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
- use_ellipses("use_ellipses")
+ use_ellipses("use_ellipses"),
+ font_halign("halign")
{
name(std::string("tab_container"));
mouse_opaque = false;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index b84e6f45fb..851fb966ec 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1445,10 +1445,10 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
}
// Finds the text segment (if any) at the give local screen position
-LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line)
{
// Find the cursor position at the requested local screen position
- S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
+ S32 offset = getDocIndexFromLocalCoord( x, y, FALSE, hit_past_end_of_line);
segment_set_t::iterator seg_iter = getSegIterContaining(offset);
if (seg_iter != mSegments.end())
{
@@ -1788,7 +1788,7 @@ const LLWString& LLTextBase::getWText() const
// will be put to its right. If round is false, the cursor will always be put to the
// character's left.
-S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{
// Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
@@ -1817,7 +1817,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
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
- || segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line
+ || (hit_past_end_of_line && (segmentp->getEnd() >= line_iter->mDocIndexEnd - 1))) // or this segment wraps to next line
{
// Figure out which character we're nearest to.
S32 offset;
@@ -2402,8 +2402,12 @@ BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
- LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
- return TRUE;
+ // Only process the click if it's actually in this segment, not to the right of the end-of-line.
+ if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+ {
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
}
return FALSE;
}
@@ -2412,8 +2416,12 @@ BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
- mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
- return TRUE;
+ // Only process the click if it's actually in this segment, not to the right of the end-of-line.
+ if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+ {
+ mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
+ return TRUE;
+ }
}
return FALSE;
}
@@ -2422,8 +2430,12 @@ BOOL LLNormalTextSegment::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
- // eat mouse down event on hyperlinks, so we get the mouse up
- return TRUE;
+ // Only process the click if it's actually in this segment, not to the right of the end-of-line.
+ if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+ {
+ // eat mouse down event on hyperlinks, so we get the mouse up
+ return TRUE;
+ }
}
return FALSE;
@@ -2433,8 +2445,12 @@ BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
- LLUrlAction::clickAction(getStyle()->getLinkHREF());
- return TRUE;
+ // Only process the click if it's actually in this segment, not to the right of the end-of-line.
+ if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+ {
+ LLUrlAction::clickAction(getStyle()->getLinkHREF());
+ return TRUE;
+ }
}
return FALSE;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 3dda6f4cc8..5b24c63557 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -48,6 +48,7 @@
class LLContextMenu;
class LLTextSegment;
+class LLNormalTextSegment;
typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
@@ -61,6 +62,9 @@ class LLTextBase
protected LLEditMenuHandler
{
public:
+ friend class LLTextSegment;
+ friend class LLNormalTextSegment;
+
struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
{
Alternative<F32> multiple;
@@ -165,7 +169,7 @@ public:
S32 getVPad() { return mVPad; }
S32 getHPad() { return mHPad; }
- S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line = true) const;
LLRect getLocalRectFromDocIndex(S32 pos) const;
LLRect getDocRectFromDocIndex(S32 pos) const;
@@ -275,7 +279,7 @@ protected:
// manage segments
void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
- LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
+ LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true);
segment_set_t::iterator getSegIterContaining(S32 index);
segment_set_t::const_iterator getSegIterContaining(S32 index) const;
void clearSegments();