diff options
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/lltextbase.cpp | 125 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 14 | ||||
-rw-r--r-- | indra/llui/lltexteditor.cpp | 14 | ||||
-rw-r--r-- | indra/llui/lltexteditor.h | 2 | ||||
-rw-r--r-- | indra/llui/lltooltip.cpp | 10 | ||||
-rw-r--r-- | indra/llui/llurlentry.cpp | 85 |
6 files changed, 149 insertions, 101 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 4cf8d76827..1d36a16ea7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -340,11 +340,14 @@ void LLTextBase::drawSelectionBackground() S32 segment_line_start = segmentp->getStart() + segment_offset; S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); + S32 segment_width, segment_height; + // if selection after beginning of segment if(selection_left >= segment_line_start) { S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; - selection_rect.mLeft += segmentp->getWidth(segment_offset, num_chars); + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mLeft += segment_width; } // if selection spans end of current segment... @@ -352,13 +355,16 @@ void LLTextBase::drawSelectionBackground() { // extend selection slightly beyond end of line // to indicate selection of newline character (use "n" character to determine width) - selection_rect.mRight += segmentp->getWidth(segment_offset, segment_line_end - segment_line_start); + S32 num_chars = segment_line_end - segment_line_start; + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mRight += segment_width; } // else if selection ends on current segment... else { S32 num_chars = selection_right - segment_line_start; - selection_rect.mRight += segmentp->getWidth(segment_offset, num_chars); + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mRight += segment_width; break; } @@ -424,7 +430,9 @@ void LLTextBase::drawCursor() if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) { - S32 width = llmax(CURSOR_THICKNESS, segmentp->getWidth(mCursorPos - segmentp->getStart(), 1)); + S32 segment_width, segment_height; + segmentp->getDimensions(mCursorPos - segmentp->getStart(), 1, segment_width, segment_height); + S32 width = llmax(CURSOR_THICKNESS, segment_width); cursor_rect.mRight = cursor_rect.mLeft + width; } else @@ -1087,24 +1095,18 @@ void LLTextBase::reflow(S32 start_index) 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); - + S32_MAX); - S32 segment_width = segment->getWidth(seg_offset, character_count); + S32 segment_width, segment_height; + segment->getDimensions(seg_offset, character_count, segment_width, segment_height); + // grow line height as necessary based on reported height of this segment + line_height = llmax(line_height, segment_height); remaining_pixels -= segment_width; seg_offset += character_count; @@ -1120,16 +1122,6 @@ void LLTextBase::reflow(S32 start_index) // 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++; - } - // add line info and keep going mLineInfoList.push_back(line_info( line_start_index, @@ -1141,7 +1133,6 @@ void LLTextBase::reflow(S32 start_index) 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()) @@ -1801,7 +1792,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round S32 segment_line_start = segmentp->getStart() + line_seg_offset; S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start; - S32 text_width = segmentp->getWidth(line_seg_offset, segment_line_length); + 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 { @@ -1809,7 +1801,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round S32 offset; if (!segmentp->canEdit()) { - S32 segment_width = segmentp->getWidth(0, segmentp->getEnd() - segmentp->getStart()); + S32 segment_width, segment_height; + segmentp->getDimensions(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height); if (round && local_x - start_x > segment_width / 2) { offset = segment_line_length; @@ -1868,14 +1861,18 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const if (line_seg_iter == cursor_seg_iter) { // cursor advanced to right based on difference in offset of cursor to start of line - local_rect.mLeft += segmentp->getWidth(line_seg_offset, cursor_seg_offset - line_seg_offset); + S32 segment_width, segment_height; + segmentp->getDimensions(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height); + local_rect.mLeft += segment_width; break; } else { // add remainder of current text segment to cursor position - local_rect.mLeft += segmentp->getWidth(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset); + S32 segment_width, segment_height; + segmentp->getDimensions(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height); + local_rect.mLeft += segment_width; // offset will be 0 for all segments after the first line_seg_offset = 0; // go to next text segment on this line @@ -2115,12 +2112,11 @@ LLRect LLTextBase::getVisibleDocumentRect() const LLTextSegment::~LLTextSegment() {} -S32 LLTextSegment::getWidth(S32 first_char, S32 num_chars) const { return 0; } +void LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; } S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; } S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; } void LLTextSegment::updateLayout(const LLTextBase& editor) {} F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { return draw_rect.mLeft; } -S32 LLTextSegment::getMaxHeight() const { return 0; } bool LLTextSegment::canEdit() const { return false; } void LLTextSegment::unlinkFromDocument(LLTextBase*) {} void LLTextSegment::linkToDocument(LLTextBase*) {} @@ -2158,7 +2154,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 mToken(NULL), mEditor(editor) { - mMaxHeight = llceil(mStyle->getFont()->getLineHeight()); + mFontHeight = llceil(mStyle->getFont()->getLineHeight()); } LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible) @@ -2168,7 +2164,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 { mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color)); - mMaxHeight = llceil(mStyle->getFont()->getLineHeight()); + mFontHeight = llceil(mStyle->getFont()->getLineHeight()); } F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) @@ -2266,11 +2262,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele return right_x; } -S32 LLNormalTextSegment::getMaxHeight() const -{ - return mMaxHeight; -} - BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask) { if (getStyle() && getStyle()->isLink()) @@ -2344,10 +2335,21 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip) mTooltip = tooltip; } -S32 LLNormalTextSegment::getWidth(S32 first_char, S32 num_chars) const +void LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { LLWString text = mEditor.getWText(); - return mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); + + // look for any printable character, then return the font height + height = 0; + for (S32 index = mStart + first_char; index < mStart + first_char + num_chars; ++index) + { + if (text[index] != '\n') + { + height = mFontHeight; + break; + } + } + width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); } S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const @@ -2363,6 +2365,17 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { LLWString text = mEditor.getWText(); + + // search for newline and if found, truncate there + S32 last_char = mStart + segment_offset; + for (; last_char != mEnd; ++last_char) + { + if (text[last_char] == '\n') break; + } + + // set max characters to length of segment, or to first newline + max_chars = llmin(max_chars, last_char - (mStart + segment_offset)); + S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart, (F32)num_pixels, max_chars, @@ -2380,6 +2393,10 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin // include terminating NULL num_chars++; } + else if (text[mStart + segment_offset + num_chars] == '\n') + { + num_chars++; + } return num_chars; } @@ -2399,9 +2416,10 @@ void LLNormalTextSegment::dump() const // LLInlineViewSegment // -LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end) +LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line) : LLTextSegment(start, end), - mView(view) + mView(view), + mForceNewLine(force_new_line) { } @@ -2410,21 +2428,29 @@ LLInlineViewSegment::~LLInlineViewSegment() mView->die(); } -S32 LLInlineViewSegment::getWidth(S32 first_char, S32 num_chars) const +void LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { if (first_char == 0 && num_chars == 0) { - return 0; + // we didn't fit on a line, the widget will fall on the next line + // so dimensions here are 0 + width = 0; + height = 0; } else { - return mView->getRect().getWidth(); + width = mView->getRect().getWidth(); + height = mView->getRect().getHeight(); } } S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { - if (line_offset != 0 && num_pixels < mView->getRect().getWidth()) + // if putting a widget anywhere but at the beginning of a line + // and the widget doesn't fit or mForceNewLine is true + // then return 0 chars for that line, and all characters for the next + if (line_offset != 0 + && (mForceNewLine || num_pixels < mView->getRect().getWidth())) { return 0; } @@ -2446,11 +2472,6 @@ F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec return (F32)(draw_rect.mLeft + mView->getRect().getWidth()); } -S32 LLInlineViewSegment::getMaxHeight() const -{ - return mView->getRect().getHeight(); -} - void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor) { editor->removeDocumentChild(mView); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index ca9b1cc123..c05a31baec 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -366,12 +366,11 @@ public: LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){}; virtual ~LLTextSegment(); - virtual S32 getWidth(S32 first_char, S32 num_chars) const; + virtual void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; virtual void updateLayout(const class LLTextBase& editor); virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); - virtual S32 getMaxHeight() const; virtual bool canEdit() const; virtual void unlinkFromDocument(class LLTextBase* editor); virtual void linkToDocument(class LLTextBase* editor); @@ -418,11 +417,10 @@ public: LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor ); LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); - /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const; + /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); - /*virtual*/ S32 getMaxHeight() const; /*virtual*/ bool canEdit() const { return true; } /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); } /*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); } @@ -446,7 +444,7 @@ protected: protected: class LLTextBase& mEditor; LLStyleSP mStyle; - S32 mMaxHeight; + S32 mFontHeight; LLKeywordToken* mToken; std::string mTooltip; }; @@ -460,19 +458,19 @@ public: class LLInlineViewSegment : public LLTextSegment { public: - LLInlineViewSegment(LLView* widget, S32 start, S32 end); + LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line); ~LLInlineViewSegment(); - /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const; + /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); - /*virtuaL*/ S32 getMaxHeight() const; /*virtual*/ bool canEdit() const { return false; } /*virtual*/ void unlinkFromDocument(class LLTextBase* editor); /*virtual*/ void linkToDocument(class LLTextBase* editor); private: LLView* mView; + bool mForceNewLine; }; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 7c925b8899..953c5b292f 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2276,7 +2276,7 @@ void LLTextEditor::insertText(const std::string &new_text) setEnabled( enabled ); } -void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline) +void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line) { // Save old state S32 selection_start = mSelectionStart; @@ -2293,17 +2293,9 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, LLWString widget_wide_text; // Add carriage return if not first line - if (getLength() != 0 - && prepend_newline) - { - widget_wide_text = utf8str_to_wstring(std::string("\n") + widget_text); - } - else - { - widget_wide_text = utf8str_to_wstring(widget_text); - } + widget_wide_text = utf8str_to_wstring(widget_text); - LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size()); + LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line); insert(getLength(), widget_wide_text, FALSE, segment); needsReflow(); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index e232efbfb3..82f3956855 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -165,7 +165,7 @@ public: // inserts text at cursor void insertText(const std::string &text); - void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline); + void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline); // Non-undoable void setText(const LLStringExplicit &utf8str); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index f30e56b907..c8094f9c7c 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -183,6 +183,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) params.font = p.font; params.use_ellipses = true; params.wrap = p.wrap; + params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips mTextBox = LLUICtrlFactory::create<LLTextBox> (params); addChild(mTextBox); @@ -319,9 +320,16 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) LLToolTip::Params tooltip_params(params); // block mouse events if there is a click handler registered (specifically, hover) - tooltip_params.mouse_opaque = params.click_callback.isProvided(); + if (params.click_callback.isProvided()) + { + // set mouse_opaque to true if it wasn't already set to something else + // this prevents mouse down from going "through" the tooltip and ultimately + // causing the tooltip to disappear + tooltip_params.mouse_opaque.setIfNotProvided(true); + } tooltip_params.rect = LLRect (0, 1, 1, 0); + mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); mToolTip->setValue(params.message()); gToolTipView->addChild(mToolTip); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e04ccfbc2f..52e4229fb4 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -280,23 +280,37 @@ void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id, std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { - std::string id = getIDStringFromUrl(url); - if (gCacheName && ! id.empty()) + if (!gCacheName) { - LLUUID uuid(id); - std::string full_name; - if (gCacheName->getFullName(uuid, full_name)) - { - return full_name; - } - else - { - gCacheName->get(uuid, FALSE, boost::bind(&LLUrlEntryAgent::onAgentNameReceived, this, _1, _2, _3, _4)); - addObserver(id, url, cb); - } + // probably at the login screen, use short string for layout + return LLTrans::getString("LoadingData"); + } + + std::string agent_id_string = getIDStringFromUrl(url); + if (agent_id_string.empty()) + { + // something went wrong, just give raw url + return unescapeUrl(url); } - return LLTrans::getString("LoadingData");//unescapeUrl(url); + LLUUID agent_id(agent_id_string); + std::string full_name; + if (agent_id.isNull()) + { + return LLTrans::getString("AvatarNameNobody"); + } + else if (gCacheName->getFullName(agent_id, full_name)) + { + return full_name; + } + else + { + gCacheName->get(agent_id, FALSE, + boost::bind(&LLUrlEntryAgent::onAgentNameReceived, + this, _1, _2, _3, _4)); + addObserver(agent_id_string, url, cb); + return LLTrans::getString("LoadingData"); + } } // @@ -311,6 +325,7 @@ LLUrlEntryGroup::LLUrlEntryGroup() mMenuName = "menu_url_group.xml"; mIcon = "Generic_Group"; mTooltip = LLTrans::getString("TooltipGroupUrl"); + mColor = LLUIColorTable::instance().getColor("GroupLinkColor"); } void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id, @@ -324,23 +339,37 @@ void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id, std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { - std::string id = getIDStringFromUrl(url); - if (gCacheName && ! id.empty()) + if (!gCacheName) { - LLUUID uuid(id); - std::string group_name; - if (gCacheName->getGroupName(uuid, group_name)) - { - return group_name; - } - else - { - gCacheName->get(uuid, TRUE, boost::bind(&LLUrlEntryGroup::onGroupNameReceived, this, _1, _2, _3, _4)); - addObserver(id, url, cb); - } + // probably at login screen, give something short for layout + return LLTrans::getString("LoadingData"); } - return unescapeUrl(url); + std::string group_id_string = getIDStringFromUrl(url); + if (group_id_string.empty()) + { + // something went wrong, give raw url + return unescapeUrl(url); + } + + LLUUID group_id(group_id_string); + std::string group_name; + if (group_id.isNull()) + { + return LLTrans::getString("GroupNameNone"); + } + else if (gCacheName->getGroupName(group_id, group_name)) + { + return group_name; + } + else + { + gCacheName->get(group_id, TRUE, + boost::bind(&LLUrlEntryGroup::onGroupNameReceived, + this, _1, _2, _3, _4)); + addObserver(group_id_string, url, cb); + return LLTrans::getString("LoadingData"); + } } /// |