summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorbrad kittenbrink <brad@lindenlab.com>2009-10-07 16:12:56 -0700
committerbrad kittenbrink <brad@lindenlab.com>2009-10-07 16:12:56 -0700
commit146e084af3344ada737340115c5fa063c0aab6b3 (patch)
tree19e0115569a06f9ec27bd7c482a1066c99afb501 /indra/llui
parentd2464757c6fa86caa30a13071cb43047de2dd2ff (diff)
parent584d0ac64e973da3a9096fb85b796716255988be (diff)
Merged in latest svn-imports-viewer-20 changes.
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/lldockablefloater.cpp10
-rw-r--r--indra/llui/lldockablefloater.h3
-rw-r--r--indra/llui/lldockcontrol.cpp22
-rw-r--r--indra/llui/llfloater.cpp3
-rw-r--r--indra/llui/llfloater.h13
-rw-r--r--indra/llui/llmenubutton.cpp6
-rw-r--r--indra/llui/llmenubutton.h1
-rw-r--r--indra/llui/llpanel.cpp2
-rw-r--r--indra/llui/llscrolllistctrl.cpp2
-rw-r--r--indra/llui/lltextbase.cpp320
-rw-r--r--indra/llui/lltextbase.h4
-rw-r--r--indra/llui/lltextbox.cpp75
-rw-r--r--indra/llui/lltextbox.h1
-rw-r--r--indra/llui/lltooltip.cpp12
-rw-r--r--indra/llui/lluictrlfactory.h2
15 files changed, 279 insertions, 197 deletions
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 4525f0a45b..c512ef25be 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -91,6 +91,16 @@ void LLDockableFloater::setVisible(BOOL visible)
LLFloater::setVisible(visible);
}
+void LLDockableFloater::onDockHidden()
+{
+ setCanDock(FALSE);
+}
+
+void LLDockableFloater::onDockShown()
+{
+ setCanDock(TRUE);
+}
+
void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
{
if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible())
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index ed90567ad3..7d91d007ee 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -68,6 +68,9 @@ public:
*/
/*virtual*/ void setVisible(BOOL visible);
+ virtual void onDockHidden();
+ virtual void onDockShown();
+
private:
/**
* Provides unique of dockable floater.
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 146c7a969a..cdcd823b1c 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -33,6 +33,7 @@
#include "linden_common.h"
#include "lldockcontrol.h"
+#include "lldockablefloater.h"
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
@@ -91,8 +92,8 @@ void LLDockControl::repositionDockable()
// recalculate dockable position if dock position changed, dock visibility changed,
// root view rect changed or recalculation is forced
- if (mEnabled && (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible()
- || mRootRect != rootRect || mRecalculateDocablePosition))
+ if (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible()
+ || mRootRect != rootRect || mRecalculateDocablePosition)
{
// undock dockable and off() if dock not visible
if (!isDockVisible())
@@ -100,10 +101,25 @@ void LLDockControl::repositionDockable()
mDockableFloater->setDocked(false);
// force off() since dockable may not have dockControll at this time
off();
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockHidden();
+ }
}
else
{
- moveDockable();
+ if(mEnabled)
+ {
+ moveDockable();
+ }
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockShown();
+ }
}
mPrevDockRect = dockRect;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 564e4d748f..b7a15a2b33 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -664,7 +664,8 @@ void LLFloater::closeFloater(bool app_quitting)
dirtyRect();
- // Close callback
+ // Close callbacks
+ onClose(app_quitting);
mCloseSignal(this, LLSD(app_quitting));
// Hide or Destroy
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 1dc5177f81..17ffc94014 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -208,8 +208,8 @@ public:
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
virtual void draw();
- // *TODO: Eliminate this in favor of mOpenSignal
virtual void onOpen(const LLSD& key) {}
+ virtual void onClose(bool app_quitting) {}
// This cannot be "const" until all derived floater canClose()
// methods are const as well. JC
@@ -293,11 +293,18 @@ private:
void addResizeCtrls();
void addDragHandle();
+public:
+ // Called when floater is opened, passes mKey
+ // Public so external views or floaters can watch for this floater opening
+ commit_signal_t mOpenSignal;
+
+ // Called when floater is closed, passes app_qitting as LLSD()
+ // Public so external views or floaters can watch for this floater closing
+ commit_signal_t mCloseSignal;
+
protected:
std::string mRectControl;
std::string mVisibilityControl;
- commit_signal_t mOpenSignal; // Called when floater is opened, passes mKey
- commit_signal_t mCloseSignal; // Called when floater is closed, passes app_qitting as LLSD()
LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg
LLDragHandle* mDragHandle;
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 2bb6749c83..8dbcd6e229 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -83,6 +83,12 @@ void LLMenuButton::toggleMenu()
}
+void LLMenuButton::hideMenu()
+{
+ mMenu->setVisible(FALSE);
+}
+
+
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index 94b0e4355d..02eb9d3806 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -54,6 +54,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
+ void hideMenu();
protected:
friend class LLUICtrlFactory;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 1695aee2b8..69ff3dddc3 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -522,7 +522,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
// be built/added. JC
if (parent)
{
- S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1;
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup();
parent->addChild(this, tab_group);
}
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index af05686c70..7b74b1f93b 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1566,7 +1566,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(hit_cell->getValue().asString())
.font(LLFontGL::getFontSansSerifSmall())
- .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 4))
+ .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6))
.delay_time(0.2f)
.sticky_rect(sticky_rect));
}
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 6c048aa908..3dacf979c7 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -209,7 +209,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
mParseHTML(p.allow_html),
- mParseHighlights(p.parse_highlights)
+ mParseHighlights(p.parse_highlights),
+ mHideScrollbar(p.hide_scrollbar)
{
LLScrollContainer::Params scroll_params;
scroll_params.name = "text scroller";
@@ -278,7 +279,9 @@ bool LLTextBase::truncate()
// Truncate safely in UTF-8
std::string temp_utf8_text = wstring_to_utf8str(text);
temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
- getViewModel()->setDisplay(utf8str_to_wstring( temp_utf8_text ));
+ LLWString text = utf8str_to_wstring( temp_utf8_text );
+ // remove extra bit of current string, to preserve formatting, etc.
+ removeStringNoUndo(text.size(), getWText().size() - text.size());
did_truncate = TRUE;
}
}
@@ -755,47 +758,63 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
// split old at start point for new segment
cur_segmentp->setEnd(segment_to_insert->getStart());
// advance to next segment
- ++cur_seg_iter;
// insert remainder of old segment
LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
- cur_seg_iter = mSegments.insert(cur_seg_iter, remainder_segment);
+ mSegments.insert(cur_seg_iter, remainder_segment);
remainder_segment->linkToDocument(this);
// insert new segment before remainder of old segment
- cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
+ mSegments.insert(cur_seg_iter, segment_to_insert);
segment_to_insert->linkToDocument(this);
- // move to "remanider" segment and start truncation there
- ++cur_seg_iter;
+ // at this point, there will be two overlapping segments owning the text
+ // associated with the incoming segment
}
else
{
- cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert);
- ++cur_seg_iter;
+ mSegments.insert(cur_seg_iter, segment_to_insert);
segment_to_insert->linkToDocument(this);
}
// now delete/truncate remaining segments as necessary
+ // cur_seg_iter points to segment before incoming segment
while(cur_seg_iter != mSegments.end())
{
cur_segmentp = *cur_seg_iter;
- if (cur_segmentp->getEnd() <= segment_to_insert->getEnd())
+ if (cur_segmentp == segment_to_insert)
{
- cur_segmentp->unlinkFromDocument(this);
- segment_set_t::iterator seg_to_erase(cur_seg_iter++);
- mSegments.erase(seg_to_erase);
+ ++cur_seg_iter;
+ continue;
}
- else
+
+ if (cur_segmentp->getStart() >= segment_to_insert->getStart())
{
- cur_segmentp->setStart(segment_to_insert->getEnd());
- break;
+ if(cur_segmentp->getEnd() <= segment_to_insert->getEnd())
+ {
+ cur_segmentp->unlinkFromDocument(this);
+ // grab copy of iterator to erase, and bump it
+ segment_set_t::iterator seg_to_erase(cur_seg_iter++);
+ mSegments.erase(seg_to_erase);
+ continue;
+ }
+ else
+ {
+ // last overlapping segment, clip to end of incoming segment
+ // and stop traversal
+ cur_segmentp->setStart(segment_to_insert->getEnd());
+ break;
+ }
}
+ ++cur_seg_iter;
}
}
+
+ // layout potentially changed
+ needsReflow();
}
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleMouseDown(x, y, mask))
{
return TRUE;
@@ -806,7 +825,7 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleMouseUp(x, y, mask))
{
// Did we just click on a link?
@@ -824,7 +843,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleMiddleMouseDown(x, y, mask))
{
return TRUE;
@@ -835,7 +854,7 @@ BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleMiddleMouseUp(x, y, mask))
{
return TRUE;
@@ -846,7 +865,7 @@ BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleRightMouseDown(x, y, mask))
{
return TRUE;
@@ -857,7 +876,7 @@ BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleRightMouseUp(x, y, mask))
{
return TRUE;
@@ -868,7 +887,7 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
{
return TRUE;
@@ -879,7 +898,7 @@ BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleHover(x, y, mask))
{
return TRUE;
@@ -890,7 +909,7 @@ BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleScrollWheel(x, y, clicks))
{
return TRUE;
@@ -901,7 +920,7 @@ BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks)
BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
{
- LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y);
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleToolTip(x, y, mask))
{
return TRUE;
@@ -1040,109 +1059,106 @@ void LLTextBase::reflow(S32 start_index)
S32 cur_top = 0;
- if (getLength())
+ segment_set_t::iterator seg_iter = mSegments.begin();
+ S32 seg_offset = 0;
+ S32 line_start_index = 0;
+ const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
+ S32 remaining_pixels = text_width;
+ LLWString text(getWText());
+ S32 line_count = 0;
+
+ // find and erase line info structs starting at start_index and going to end of document
+ if (!mLineInfoList.empty())
{
- segment_set_t::iterator seg_iter = mSegments.begin();
- S32 seg_offset = 0;
- S32 line_start_index = 0;
- const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
- S32 remaining_pixels = text_width;
- LLWString text(getWText());
- S32 line_count = 0;
-
- // find and erase line info structs starting at start_index and going to end of document
- if (!mLineInfoList.empty())
- {
- // find first element whose end comes after start_index
- line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
- line_start_index = iter->mDocIndexStart;
- line_count = iter->mLineNum;
- getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
- mLineInfoList.erase(iter, mLineInfoList.end());
- }
+ // find first element whose end comes after start_index
+ line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
+ line_start_index = iter->mDocIndexStart;
+ line_count = iter->mLineNum;
+ getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
+ mLineInfoList.erase(iter, mLineInfoList.end());
+ }
- S32 line_height = 0;
+ S32 line_height = 0;
- while(seg_iter != mSegments.end())
+ while(seg_iter != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *seg_iter;
+
+ // track maximum height of any segment on this line
+ line_height = llmax(line_height, segment->getMaxHeight());
+ S32 cur_index = segment->getStart() + seg_offset;
+ // find run of text from this segment that we can display on one line
+ S32 end_index = cur_index;
+ while(end_index < segment->getEnd() && text[end_index] != '\n')
{
- LLTextSegmentPtr segment = *seg_iter;
-
- // track maximum height of any segment on this line
- line_height = llmax(line_height, segment->getMaxHeight());
- S32 cur_index = segment->getStart() + seg_offset;
- // find run of text from this segment that we can display on one line
- S32 end_index = cur_index;
- while(end_index < segment->getEnd() && text[end_index] != '\n')
- {
- ++end_index;
- }
-
- // ask segment how many character fit in remaining space
- S32 max_characters = end_index - cur_index;
- S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
- seg_offset,
- cur_index - line_start_index,
- max_characters);
-
+ ++end_index;
+ }
- S32 segment_width = segment->getWidth(seg_offset, character_count);
- remaining_pixels -= segment_width;
- S32 text_left = getLeftOffset(text_width - remaining_pixels);
+ // ask segment how many character fit in remaining space
+ S32 max_characters = end_index - cur_index;
+ S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
+ seg_offset,
+ cur_index - line_start_index,
+ max_characters);
+
- seg_offset += character_count;
+ S32 segment_width = segment->getWidth(seg_offset, character_count);
+ remaining_pixels -= segment_width;
+ S32 text_left = getLeftOffset(text_width - remaining_pixels);
- S32 last_segment_char_on_line = segment->getStart() + seg_offset;
+ seg_offset += character_count;
- // if we didn't finish the current segment...
- if (last_segment_char_on_line < segment->getEnd())
- {
- // set up index for next line
- // ...skip newline, we don't want to draw
- S32 next_line_count = line_count;
- if (text[last_segment_char_on_line] == '\n')
- {
- seg_offset++;
- last_segment_char_on_line++;
- next_line_count++;
- }
+ S32 last_segment_char_on_line = segment->getStart() + seg_offset;
- // add line info and keep going
- mLineInfoList.push_back(line_info(
- line_start_index,
- last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
- line_count));
-
- line_start_index = segment->getStart() + seg_offset;
- cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
- remaining_pixels = text_width;
- line_height = 0;
- line_count = next_line_count;
- }
- // ...just consumed last segment..
- else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
- {
- mLineInfoList.push_back(line_info(
- line_start_index,
- last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
- line_count));
- cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
- break;
- }
- // finished a segment and there are segments remaining on this line
- else
+ // if we didn't finish the current segment...
+ if (last_segment_char_on_line < segment->getEnd())
+ {
+ // set up index for next line
+ // ...skip newline, we don't want to draw
+ S32 next_line_count = line_count;
+ if (text[last_segment_char_on_line] == '\n')
{
- // subtract pixels used and increment segment
- ++seg_iter;
- seg_offset = 0;
+ seg_offset++;
+ last_segment_char_on_line++;
+ next_line_count++;
}
+
+ // add line info and keep going
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ LLRect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height),
+ line_count));
+
+ line_start_index = segment->getStart() + seg_offset;
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ remaining_pixels = text_width;
+ line_height = 0;
+ line_count = next_line_count;
+ }
+ // ...just consumed last segment..
+ else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
+ {
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ LLRect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height),
+ line_count));
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ break;
+ }
+ // finished a segment and there are segments remaining on this line
+ else
+ {
+ // subtract pixels used and increment segment
+ ++seg_iter;
+ seg_offset = 0;
}
}
@@ -1256,6 +1272,19 @@ S32 LLTextBase::getLineStart( S32 line ) const
return mLineInfoList[line].mDocIndexStart;
}
+S32 LLTextBase::getLineEnd( S32 line ) const
+{
+ S32 num_lines = getLineCount();
+ if (num_lines == 0)
+ {
+ return 0;
+ }
+
+ line = llclamp(line, 0, num_lines-1);
+ return mLineInfoList[line].mDocIndexEnd;
+}
+
+
S32 LLTextBase::getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap) const
{
@@ -1308,14 +1337,27 @@ S32 LLTextBase::getFirstVisibleLine() const
return iter - mLineInfoList.begin();
}
-std::pair<S32, S32> LLTextBase::getVisibleLines() const
+std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible)
{
LLRect visible_region = mScroller->getVisibleContentRect();
+ line_list_t::const_iterator first_iter;
+ line_list_t::const_iterator last_iter;
- // binary search for line that starts before top of visible buffer and starts before end of visible buffer
- line_list_t::const_iterator first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
- line_list_t::const_iterator last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top());
+ // make sure we have an up-to-date mLineInfoList
+ reflow();
+ if (fully_visible)
+ {
+ // binary search for line that starts before top of visible buffer and starts before end of visible buffer
+ first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_top());
+ last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom());
+ }
+ else
+ {
+ // binary search for line that starts before top of visible buffer and starts before end of visible buffer
+ first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
+ last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top());
+ }
return std::pair<S32, S32>(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin());
}
@@ -2147,7 +2189,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 start = seg_start;
S32 end = llmin( selection_start, seg_end );
S32 length = end - start;
- font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.getWidth(), &right_x, mEditor.getUseEllipses());
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ color,
+ LLFontGL::LEFT, LLFontGL::TOP,
+ 0,
+ mStyle->getShadowType(),
+ length, rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
@@ -2158,9 +2208,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = llmin( selection_end, seg_end );
S32 length = end - start;
- font->render(text, start, rect.mLeft, rect.mTop,
- LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
- LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, rect.mRight, &right_x, mEditor.getUseEllipses());
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
+ LLFontGL::LEFT, LLFontGL::TOP,
+ 0,
+ LLFontGL::NO_SHADOW,
+ length, rect.mRight,
+ &right_x,
+ mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
if( selection_end < seg_end )
@@ -2169,7 +2225,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 start = llmax( selection_end, seg_start );
S32 end = seg_end;
S32 length = end - start;
- font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.mRight, &right_x, mEditor.getUseEllipses());
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ color,
+ LLFontGL::LEFT, LLFontGL::TOP,
+ 0,
+ mStyle->getShadowType(),
+ length, rect.mRight,
+ &right_x,
+ mEditor.getUseEllipses());
}
return right_x;
}
@@ -2263,7 +2327,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
(F32)num_pixels,
max_chars,
- mEditor.getWordWrap());
+ TRUE);
if (num_chars == 0
&& line_offset == 0
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d0287a99ca..f20134fd6d 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -277,10 +277,11 @@ protected:
// manage lines
S32 getLineStart( S32 line ) const;
+ S32 getLineEnd( S32 line ) const;
S32 getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
S32 getLineOffsetFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
S32 getFirstVisibleLine() const;
- std::pair<S32, S32> getVisibleLines() const;
+ std::pair<S32, S32> getVisibleLines(bool fully_visible = false);
S32 getLeftOffset(S32 width);
void reflow(S32 start_index = 0);
@@ -344,6 +345,7 @@ protected:
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
bool mReadOnly;
bool mClip;
+ bool mHideScrollbar;
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 3feca136be..20bceb4675 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -47,26 +47,19 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
+ BOOL handled = LLTextBase::handleMouseDown(x, y, mask);
- // HACK: Only do this if there actually is something to click, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (isClickable())
+ if (getSoundFlags() & MOUSE_DOWN)
{
- handled = TRUE;
+ make_ui_sound("UISndClick");
+ }
+ if (!handled && mClickedCallback)
+ {
// Route future Mouse messages here preemptively. (Release on mouse up.)
gFocusMgr.setMouseCapture( this );
-
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
- }
- if (!handled)
- {
- handled = LLTextBase::handleMouseDown(x, y, mask);
+ handled = TRUE;
}
return handled;
@@ -76,33 +69,30 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // We only handle the click if the click both started and ended within us
-
- // HACK: Only do this if there actually is something to click, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (isClickable() && hasMouseCapture())
+ if (getSoundFlags() & MOUSE_UP)
{
- handled = TRUE;
+ make_ui_sound("UISndClickRelease");
+ }
+ // We only handle the click if the click both started and ended within us
+ if (hasMouseCapture())
+ {
// Release the mouse
gFocusMgr.setMouseCapture( NULL );
- if (getSoundFlags() & MOUSE_UP)
- {
- make_ui_sound("UISndClickRelease");
- }
-
- // handle clicks on Urls in the textbox first
- handled = LLTextBase::handleMouseUp(x, y, mask);
-
- // DO THIS AT THE VERY END to allow the button to be destroyed
+ // DO THIS AT THE VERY END to allow the button to be destroyed
// as a result of being clicked. If mouseup in the widget,
// it's been clicked
if (mClickedCallback && !handled)
{
mClickedCallback();
+ handled = TRUE;
}
}
+ else
+ {
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
return handled;
}
@@ -149,30 +139,3 @@ void LLTextBox::onUrlLabelUpdated(const std::string &url, const std::string &lab
needsReflow();
}
-bool LLTextBox::isClickable() const
-{
- // return true if we have been given a click callback
- if (mClickedCallback)
- {
- return true;
- }
-
- // also return true if we have a clickable Url in the text
- segment_set_t::const_iterator it;
- for (it = mSegments.begin(); it != mSegments.end(); ++it)
- {
- LLTextSegmentPtr segmentp = *it;
- if (segmentp)
- {
- const LLStyleSP style = segmentp->getStyle();
- if (style && style->isLink())
- {
- return true;
- }
- }
- }
-
- // otherwise there is nothing clickable here
- return false;
-}
-
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index f8c4447b62..da0bcbe972 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -79,7 +79,6 @@ public:
protected:
void onUrlLabelUpdated(const std::string &url, const std::string &label);
- bool isClickable() const;
LLUIString mText;
callback_t mClickedCallback;
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index d742281f30..c55273cacf 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -38,6 +38,7 @@
// Library includes
#include "lltextbox.h"
#include "lliconctrl.h"
+#include "llmenugl.h" // hideMenus()
#include "llui.h" // positionViewNearMouse()
#include "llwindow.h"
@@ -94,7 +95,16 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLToolTipMgr::instance().blockToolTips();
- return LLView::handleMouseDown(x, y, mask);
+
+ if (LLView::handleMouseDown(x, y, mask))
+ {
+ // If we are handling the mouse event menu holder
+ // won't get a chance to close menus so do this here
+ LLMenuGL::sMenuContainer->hideMenus();
+ return TRUE;
+ }
+
+ return FALSE;
}
BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index e47010c316..3c77c655b8 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -321,7 +321,7 @@ fail:
static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
private:
- //static void setCtrlValue(LLView* view, LLXMLNodePtr node);
+ // this exists to get around dependency on llview
static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group);
// Avoid directly using LLUI and LLDir in the template code