diff options
Diffstat (limited to 'indra/llui/lltextbase.cpp')
-rw-r--r-- | indra/llui/lltextbase.cpp | 192 |
1 files changed, 110 insertions, 82 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3dacf979c7..123e59ae6a 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -124,17 +124,6 @@ struct LLTextBase::line_end_compare ////////////////////////////////////////////////////////////////////////// // -// LLTextBase::DocumentPanel -// - - -LLTextBase::DocumentPanel::DocumentPanel(const Params& p) -: LLPanel(p) -{} - - -////////////////////////////////////////////////////////////////////////// -// // LLTextBase // @@ -157,8 +146,7 @@ LLTextBase::Params::Params() bg_readonly_color("bg_readonly_color"), bg_writeable_color("bg_writeable_color"), bg_focus_color("bg_focus_color"), - hide_scrollbar("hide_scrollbar"), - clip_to_rect("clip_to_rect", true), + allow_scroll("allow_scroll", true), track_end("track_end", false), read_only("read_only", false), v_pad("v_pad", 0), @@ -205,35 +193,44 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mSelectionStart( 0 ), mSelectionEnd( 0 ), mIsSelecting( FALSE ), - mClip(p.clip_to_rect), mWordWrap(p.wrap), mUseEllipses( p.use_ellipses ), mParseHTML(p.allow_html), mParseHighlights(p.parse_highlights), - mHideScrollbar(p.hide_scrollbar) -{ - LLScrollContainer::Params scroll_params; - scroll_params.name = "text scroller"; - scroll_params.rect = getLocalRect(); - scroll_params.follows.flags = FOLLOWS_ALL; - scroll_params.is_opaque = false; - scroll_params.mouse_opaque = false; - scroll_params.min_auto_scroll_rate = 200; - scroll_params.max_auto_scroll_rate = 800; - scroll_params.hide_scrollbar = p.hide_scrollbar; - scroll_params.border_visible = p.border_visible; - mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params); - addChild(mScroller); - - LLPanel::Params panel_params; - panel_params.name = "text_contents"; - panel_params.rect = LLRect(0, 500, 500, 0); - panel_params.background_visible = p.bg_visible; - panel_params.background_opaque = true; - panel_params.mouse_opaque = false; - - mDocumentPanel = LLUICtrlFactory::create<DocumentPanel>(panel_params); - mScroller->addChild(mDocumentPanel); + mBGVisible(p.bg_visible), + mScroller(NULL) +{ + if(p.allow_scroll) + { + LLScrollContainer::Params scroll_params; + scroll_params.name = "text scroller"; + scroll_params.rect = getLocalRect(); + scroll_params.follows.flags = FOLLOWS_ALL; + scroll_params.is_opaque = false; + scroll_params.mouse_opaque = false; + scroll_params.min_auto_scroll_rate = 200; + scroll_params.max_auto_scroll_rate = 800; + // all text widgets only show scrollbar on demand + scroll_params.hide_scrollbar = true; + scroll_params.border_visible = p.border_visible; + mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params); + addChild(mScroller); + } + + LLView::Params view_params; + view_params.name = "text_contents"; + view_params.rect = LLRect(0, 500, 500, 0); + view_params.mouse_opaque = false; + + mDocumentView = LLUICtrlFactory::create<LLView>(view_params); + if (mScroller) + { + mScroller->addChild(mDocumentView); + } + else + { + addChild(mDocumentView); + } createDefaultSegment(); @@ -314,7 +311,7 @@ void LLTextBase::drawSelectionBackground() LLRect selection_rect = mTextRect; // Skip through the lines we aren't drawing. - LLRect content_display_rect = mScroller->getVisibleContentRect(); + LLRect content_display_rect = getVisibleDocumentRect(); // binary search for line that starts before top of visible buffer line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); @@ -496,8 +493,7 @@ void LLTextBase::drawText() selection_right = llmax( mSelectionStart, mSelectionEnd ); } - LLRect scrolled_view_rect = mScroller->getVisibleContentRect(); - LLRect content_rect = mScroller->getContentWindowRect(); + LLRect scrolled_view_rect = getVisibleDocumentRect(); std::pair<S32, S32> line_range = getVisibleLines(); S32 first_line = line_range.first; S32 last_line = line_range.second; @@ -540,7 +536,7 @@ void LLTextBase::drawText() LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft, line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom, - mDocumentPanel->getRect().getWidth() - scrolled_view_rect.mLeft, + mDocumentView->getRect().getWidth() - scrolled_view_rect.mLeft, line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom); // draw a single line of text @@ -645,6 +641,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } onValueChange(pos, pos + insert_len); + needsReflow(); return insert_len; } @@ -704,6 +701,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) createDefaultSegment(); onValueChange(pos, pos); + needsReflow(); return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length } @@ -719,6 +717,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc) getViewModel()->setDisplay(text); onValueChange(pos, pos + 1); + needsReflow(); return 1; } @@ -949,29 +948,31 @@ void LLTextBase::draw() // then update scroll position, as cursor may have moved updateScrollFromCursor(); - LLColor4 bg_color = mReadOnly - ? mReadOnlyBgColor.get() - : hasFocus() - ? mFocusBgColor.get() - : mWriteableBgColor.get(); + if (mBGVisible) + { + // clip background rect against extents, if we support scrolling + LLLocalClipRect clip(getLocalRect(), mScroller != NULL); - mDocumentPanel->setBackgroundColor(bg_color); + LLColor4 bg_color = mReadOnly + ? mReadOnlyBgColor.get() + : hasFocus() + ? mFocusBgColor.get() + : mWriteableBgColor.get(); + gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE); + } + // draw document view LLUICtrl::draw(); + { - LLLocalClipRect clip(mTextRect, mClip); + // only clip if we support scrolling (mScroller != NULL) + LLLocalClipRect clip(mTextRect, mScroller != NULL); drawSelectionBackground(); drawText(); drawCursor(); } } -//virtual -void LLTextBase::clear() -{ - getViewModel()->setDisplay(LLWStringUtil::null); - clearSegments(); -} //virtual void LLTextBase::setColor( const LLColor4& c ) @@ -1000,14 +1001,14 @@ void LLTextBase::updateScrollFromCursor() // Update scroll position even in read-only mode (when there's no cursor displayed) // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736. - if (!mScrollNeeded) + if (!mScrollNeeded || !mScroller) { return; } mScrollNeeded = FALSE; // scroll so that the cursor is at the top of the page - LLRect scroller_doc_window = mScroller->getVisibleContentRect(); + LLRect scroller_doc_window = getVisibleDocumentRect(); LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos); cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom); mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5)); @@ -1042,7 +1043,7 @@ void LLTextBase::reflow(S32 start_index) { mReflowNeeded = FALSE; - bool scrolled_to_bottom = mScroller->isAtBottom(); + bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false; LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos); bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible @@ -1183,17 +1184,29 @@ void LLTextBase::reflow(S32 start_index) mContentsRect.stretch(1); } - // change mDocumentPanel document size to accomodate reflowed text + // change mDocumentView size to accomodate reflowed text LLRect document_rect; - document_rect.setOriginAndSize(1, 1, - mScroller->getContentWindowRect().getWidth(), - llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight())); - mDocumentPanel->setShape(document_rect); + if (mScroller) + { + // document is size of scroller or size of text contents, whichever is larger + document_rect.setOriginAndSize(0, 0, + mScroller->getContentWindowRect().getWidth(), + llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight())); + } + else + { + // document size is just extents of reflowed text, reset to origin 0,0 + document_rect.set(0, + getLocalRect().getHeight(), + getLocalRect().getWidth(), + llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight())); + } + mDocumentView->setShape(document_rect); // after making document big enough to hold all the text, move the text to fit in the document if (!mLineInfoList.empty()) { - S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad; + S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad; // move line segments to fit new document rect for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it) { @@ -1215,9 +1228,9 @@ void LLTextBase::reflow(S32 start_index) } // apply scroll constraints after reflowing text - if (!hasMouseCapture()) + if (!hasMouseCapture() && mScroller) { - LLRect visible_content_rect = mScroller->getVisibleContentRect(); + LLRect visible_content_rect = getVisibleDocumentRect(); if (scrolled_to_bottom && mTrackEnd) { // keep bottom of text buffer visible @@ -1329,7 +1342,7 @@ S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap) S32 LLTextBase::getFirstVisibleLine() const { - LLRect visible_region = mScroller->getVisibleContentRect(); + LLRect visible_region = getVisibleDocumentRect(); // binary search for line that starts before top of visible buffer line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); @@ -1339,7 +1352,7 @@ S32 LLTextBase::getFirstVisibleLine() const std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible) { - LLRect visible_region = mScroller->getVisibleContentRect(); + LLRect visible_region = getVisibleDocumentRect(); line_list_t::const_iterator first_iter; line_list_t::const_iterator last_iter; @@ -1370,12 +1383,12 @@ LLTextViewModel* LLTextBase::getViewModel() const void LLTextBase::addDocumentChild(LLView* view) { - mDocumentPanel->addChild(view); + mDocumentView->addChild(view); } void LLTextBase::removeDocumentChild(LLView* view) { - mDocumentPanel->removeChild(view); + mDocumentView->removeChild(view); } @@ -1481,11 +1494,10 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) void LLTextBase::setText(const LLStringExplicit &utf8str) { // clear out the existing text and segments - clear(); - - truncate(); + getViewModel()->setDisplay(LLWStringUtil::null); - createDefaultSegment(); + clearSegments(); +// createDefaultSegment(); startOfDoc(); deselect(); @@ -1496,10 +1508,9 @@ void LLTextBase::setText(const LLStringExplicit &utf8str) appendText(text, false); - needsReflow(); - //resetDirty(); onValueChange(0, getLength()); + needsReflow(); } //virtual @@ -1767,7 +1778,7 @@ LLWString LLTextBase::getWText() const S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const { // Figure out which line we're nearest to. - LLRect visible_region = mScroller->getVisibleContentRect(); + LLRect visible_region = getVisibleDocumentRect(); // binary search for line that starts before local_y line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom()); @@ -1838,7 +1849,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const // find line that contains cursor line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare()); - LLRect scrolled_view_rect = mScroller->getVisibleContentRect(); + LLRect scrolled_view_rect = getVisibleDocumentRect(); local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft; local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom); local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom); @@ -1917,7 +1928,7 @@ void LLTextBase::endOfDoc() void LLTextBase::changePage( S32 delta ) { const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10; - if (delta == 0) return; + if (delta == 0 || !mScroller) return; LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos); @@ -1970,7 +1981,7 @@ void LLTextBase::changeLine( S32 delta ) new_line = line + 1; } - LLRect visible_region = mScroller->getVisibleContentRect(); + LLRect visible_region = getVisibleDocumentRect(); S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE); setCursorPos(new_cursor_pos, true); @@ -2047,7 +2058,7 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction) void LLTextBase::updateTextRect() { LLRect old_text_rect = mTextRect; - mTextRect = mScroller->getContentWindowRect(); + mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); //FIXME: replace border with image? if (mBorderVisible) { @@ -2081,6 +2092,22 @@ void LLTextBase::endSelection() } } +// get portion of document that is visible in text editor +LLRect LLTextBase::getVisibleDocumentRect() const +{ + if (mScroller) + { + return mScroller->getVisibleContentRect(); + } + else + { + // entire document rect when not scrolling + LLRect doc_rect = mDocumentView->getLocalRect(); + doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom); + return doc_rect; + } +} + // // LLTextSegment // @@ -2150,6 +2177,7 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec { if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart)) { + LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha; LLUIImagePtr image = mStyle->getImage(); S32 style_image_height = image->getHeight(); S32 style_image_width = image->getWidth(); @@ -2398,7 +2426,7 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin void LLInlineViewSegment::updateLayout(const LLTextBase& editor) { LLRect start_rect = editor.getLocalRectFromDocIndex(mStart); - LLRect doc_rect = editor.getDocumentPanel()->getRect(); + LLRect doc_rect = editor.getDocumentView()->getRect(); mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom); } |