From 92aaa3778872a660bed78b1ab7e77dc441200d3b Mon Sep 17 00:00:00 2001 From: James Cook Date: Mon, 5 Oct 2009 16:17:51 +0000 Subject: Tweak inspector tooltip icon spacing. --- indra/llui/lltooltip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 8f5c029816..d742281f30 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -189,7 +189,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) addChild(LLUICtrlFactory::create(icon_params)); // move text over to fit image in - mTextBox->translate(TOOLTIP_ICON_SIZE,0); + mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0); } if (p.click_callback.isProvided()) -- cgit v1.3 From 606311b508c5b13cd995a98d16660e61a58fa3f7 Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Mon, 5 Oct 2009 20:53:51 +0000 Subject: text boxes are now *not* mouse_opaque by default fixed some textbox and text editor layout problems (getWidth called with wrong index) EXT-1302 - rewrite LLExpandableTextBox to use new LLTextBase functionality (using custom LLExpanderSegment) reviewed by James --- indra/llrender/llfontgl.cpp | 6 +- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/lltextbase.cpp | 317 ++++++++++++-------- indra/llui/lltextbase.h | 4 +- indra/llui/lltextbox.cpp | 75 ++--- indra/llui/lltextbox.h | 1 - indra/newview/llexpandabletextbox.cpp | 322 ++++++--------------- indra/newview/llexpandabletextbox.h | 36 +-- .../skins/default/xui/en/floater_test_widgets.xml | 5 +- .../newview/skins/default/xui/en/panel_profile.xml | 8 +- .../default/xui/en/widgets/expandable_text.xml | 10 - .../newview/skins/default/xui/en/widgets/text.xml | 1 + 12 files changed, 323 insertions(+), 464 deletions(-) (limited to 'indra/llui') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 8f943182b8..f7bab3de67 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -208,10 +208,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons case LEFT: break; case RIGHT: - cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)); + cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)); break; case HCENTER: - cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)) / 2; + cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2; break; default: break; @@ -234,7 +234,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (use_ellipses) { // check for too long of a string - if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels) + if (getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); 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..62f03f47e6 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,60 @@ 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; } } } 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 +822,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 +840,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 +851,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 +862,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 +873,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 +884,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 +895,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 +906,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 +917,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 +1056,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 +1269,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 +1334,27 @@ S32 LLTextBase::getFirstVisibleLine() const return iter - mLineInfoList.begin(); } -std::pair LLTextBase::getVisibleLines() const +std::pair 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(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin()); } @@ -2147,7 +2186,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 +2205,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 +2222,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 +2324,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 getVisibleLines() const; + std::pair 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/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index f8f5db9d7e..28c124d1c6 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -34,253 +34,121 @@ #include "llexpandabletextbox.h" #include "llscrollcontainer.h" +#include "llwindow.h" static LLDefaultChildRegistry::Register t1("expandable_text"); -LLExpandableTextBox::LLTextBoxEx::Params::Params() -: expand_textbox("expand_textbox") +class LLExpanderSegment : public LLTextSegment { -} +public: + LLExpanderSegment(const LLStyleSP& style, S32 start, S32 end, const std::string& more_text, LLTextBase& editor ) + : LLTextSegment(start, end), + mEditor(editor), + mStyle(style), + mMoreText(more_text) + {} + + /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const + { + // more label always spans width of text box + return mEditor.getTextRect().getWidth(); + } + /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const + { + return start_offset; + } + /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return getEnd() - getStart(); } + /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) + { + F32 right_x; + mStyle->getFont()->renderUTF8(mMoreText, start, draw_rect.mRight, draw_rect.mTop, mStyle->getColor(), LLFontGL::RIGHT, LLFontGL::TOP, 0, mStyle->getShadowType(), end - start, draw_rect.getWidth(), &right_x, mEditor.getUseEllipses()); + return right_x; + } + /*virtual*/ S32 getMaxHeight() const { return llceil(mStyle->getFont()->getLineHeight()); } + /*virtual*/ bool canEdit() const { return false; } + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) { mEditor.onCommit(); return TRUE; } + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) + { + LLUI::getWindow()->setCursor(UI_CURSOR_HAND); + return TRUE; + } +private: + LLTextBase& mEditor; + LLStyleSP mStyle; + std::string mMoreText; +}; + + LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) -: LLTextBox(p) +: LLTextBox(p), + mExpanded(false) { setIsChrome(TRUE); - LLTextBox::Params params = p.expand_textbox; - mExpandTextBox = LLUICtrlFactory::create(params); - addChild(mExpandTextBox); - - LLRect rc = getLocalRect(); - rc.mRight -= getHPad(); - rc.mLeft = rc.mRight - mExpandTextBox->getTextPixelWidth(); - rc.mTop = mExpandTextBox->getTextPixelHeight(); - mExpandTextBox->setRect(rc); } -BOOL LLExpandableTextBox::LLTextBoxEx::handleMouseUp(S32 x, S32 y, MASK mask) +void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL called_from_parent) { - BOOL ret = LLTextBox::handleMouseUp(x, y, mask); + LLTextBox::reshape(width, height, called_from_parent); - if(mExpandTextBox->getRect().pointInRect(x, y)) + if (getTextPixelHeight() > getRect().getHeight()) { - onCommit(); + showExpandText(); + } + else + { + hideExpandText(); } - - return ret; } -void LLExpandableTextBox::LLTextBoxEx::draw() +void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value) { - // draw text box - LLTextBox::draw(); - // force text box to draw children - LLUICtrl::draw(); -} - -/* LLTextBox has been rewritten, the variables referenced in this code -no longer exist. + LLTextBox::setValue(value); -void LLExpandableTextBox::LLTextBoxEx::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color ) -{ - // *NOTE:dzaporozhan: - // Copy/paste from LLTextBox::drawText in order to modify last - // line width if needed and who "More" link - F32 alpha = getDrawContext().mAlpha; - if (mSegments.size() > 1) + if (getTextPixelHeight() > getRect().getHeight()) { - // we have Urls (or other multi-styled segments) - drawTextSegments(x, y, text); - } - else if( mLineLengthList.empty() ) - { - // simple case of 1 line of text in one style - mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha, - mHAlign, mVAlign, - 0, - mShadowType, - S32_MAX, getRect().getWidth(), NULL, mUseEllipses); - - mExpandTextBox->setVisible(FALSE); + showExpandText(); } else { - // simple case of multiple lines of text, all in the same style - S32 cur_pos = 0; - for (std::vector::iterator iter = mLineLengthList.begin(); - iter != mLineLengthList.end(); ++iter) - { - S32 line_length = *iter; - S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing; - S32 max_pixels = getRect().getWidth(); - - if(iter + 1 != mLineLengthList.end() - && y - line_height < line_height) - { - max_pixels = getCropTextWidth(); - } - - mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha, - mHAlign, mVAlign, - 0, - mShadowType, - line_length, max_pixels, NULL, mUseEllipses ); - - cur_pos += line_length + 1; - - y -= line_height; - if(y < line_height) - { - if( mLineLengthList.end() != iter + 1 ) - { - showExpandText(y); - } - else - { - hideExpandText(); - } - break; - } - } + hideExpandText(); } } -*/ -void LLExpandableTextBox::LLTextBoxEx::showExpandText(S32 y) -{ - LLRect rc = mExpandTextBox->getRect(); - rc.mTop = y + mExpandTextBox->getTextPixelHeight(); - rc.mBottom = y; - mExpandTextBox->setRect(rc); - mExpandTextBox->setVisible(TRUE); -} -void LLExpandableTextBox::LLTextBoxEx::hideExpandText() -{ - mExpandTextBox->setVisible(FALSE); -} - -S32 LLExpandableTextBox::LLTextBoxEx::getCropTextWidth() -{ - return mExpandTextBox->getRect().mLeft - getHPad() * 2; -} - -/* -// *NOTE:James: -// LLTextBox::drawText() has been completely rewritten, as it now handles -// arbitrarily styled segments of text. This needs to be rebuilt. - -void LLExpandableTextBox::LLTextBoxEx::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text) +void LLExpandableTextBox::LLTextBoxEx::showExpandText() { - - // *NOTE:dzaporozhan: - // Copy/paste from LLTextBox::drawTextSegments in order to modify last - // line width if needed and who "More" link - F32 alpha = getDrawContext().mAlpha; - - const S32 text_len = text.length(); - if (text_len <= 0) + if (!mExpanded) { - return; + // get fully visible lines + std::pair visible_lines = getVisibleLines(true); + S32 last_line = visible_lines.second - 1; + + LLStyle::Params expander_style = getDefaultStyle(); + expander_style.font.name.setIfNotProvided(LLFontGL::nameFromFont(expander_style.font)); + expander_style.font.style = "UNDERLINE"; + expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, "More", *this); + insertSegment(expanderp); + mExpanded = true; } - S32 cur_line = 0; - S32 num_lines = getLineCount(); - S32 line_start = getLineStart(cur_line); - S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing; - F32 text_y = (F32) init_y; - segment_set_t::iterator cur_seg = mSegments.begin(); +} - // render a line of text at a time - const LLRect textRect = getLocalRect(); - while((textRect.mBottom <= text_y) && (cur_line < num_lines)) +//NOTE: obliterates existing styles (including hyperlinks) +void LLExpandableTextBox::LLTextBoxEx::hideExpandText() +{ + if (mExpanded) { - S32 next_start = -1; - S32 line_end = text_len; - - if ((cur_line + 1) < num_lines) - { - next_start = getLineStart(cur_line + 1); - line_end = next_start; - } - if ( text[line_end-1] == '\n' ) - { - --line_end; - } - - // render all segments on this line - F32 text_x = init_x; - S32 seg_start = line_start; - while (seg_start < line_end && cur_seg != mSegments.end()) - { - // move to the next segment (or continue the previous one) - LLTextSegment *cur_segment = *cur_seg; - while (cur_segment->getEnd() <= seg_start) - { - if (++cur_seg == mSegments.end()) - { - return; - } - cur_segment = *cur_seg; - } - - // Draw a segment within the line - S32 clipped_end = llmin( line_end, cur_segment->getEnd() ); - S32 clipped_len = clipped_end - seg_start; - if( clipped_len > 0 ) - { - LLStyleSP style = cur_segment->getStyle(); - if (style && style->isVisible()) - { - // work out the color for the segment - LLColor4 color ; - if (getEnabled()) - { - color = style->isLink() ? mLinkColor.get() : mTextColor.get(); - } - else - { - color = mDisabledColor.get(); - } - color = color % alpha; - - S32 max_pixels = textRect.getWidth(); - - if(cur_line + 1 < num_lines - && text_y - line_height < line_height) - { - max_pixels = getCropTextWidth(); - } - - // render a single line worth for this segment - mDefaultFont->render(text, seg_start, text_x, text_y, color, - mHAlign, mVAlign, 0, mShadowType, clipped_len, - max_pixels, &text_x, mUseEllipses); - } - - seg_start += clipped_len; - } - } - - // move down one line - text_y -= (F32)line_height; - line_start = next_start; - cur_line++; - if(text_y < line_height) - { - if( cur_line < num_lines ) - { - showExpandText((S32)text_y); - } - else - { - hideExpandText(); - } - break; - } + // this will overwrite the expander segment and all text styling with a single style + LLNormalTextSegment* segmentp = new LLNormalTextSegment( + new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this); + insertSegment(segmentp); + + mExpanded = false; } } -*/ S32 LLExpandableTextBox::LLTextBoxEx::getVerticalTextDelta() { @@ -295,24 +163,24 @@ S32 LLExpandableTextBox::LLTextBoxEx::getVerticalTextDelta() ////////////////////////////////////////////////////////////////////////// LLExpandableTextBox::Params::Params() -: textbox("textbox") -, scroll("scroll") -, max_height("max_height", 0) -, bg_visible("bg_visible", false) -, expanded_bg_visible("expanded_bg_visible", true) -, bg_color("bg_color", LLColor4::black) -, expanded_bg_color("expanded_bg_color", LLColor4::black) +: textbox("textbox"), + scroll("scroll"), + max_height("max_height", 0), + bg_visible("bg_visible", false), + expanded_bg_visible("expanded_bg_visible", true), + bg_color("bg_color", LLColor4::black), + expanded_bg_color("expanded_bg_color", LLColor4::black) { } LLExpandableTextBox::LLExpandableTextBox(const Params& p) -: LLUICtrl(p) -, mMaxHeight(p.max_height) -, mBGVisible(p.bg_visible) -, mExpandedBGVisible(p.expanded_bg_visible) -, mBGColor(p.bg_color) -, mExpandedBGColor(p.expanded_bg_color) -, mExpanded(false) +: LLUICtrl(p), + mMaxHeight(p.max_height), + mBGVisible(p.bg_visible), + mExpandedBGVisible(p.expanded_bg_visible), + mBGColor(p.bg_color), + mExpandedBGColor(p.expanded_bg_color), + mExpanded(false) { LLRect rc = getLocalRect(); @@ -474,8 +342,6 @@ void LLExpandableTextBox::collapseTextBox() updateTextBoxRect(); - // Should be handled automatically in reshape above. JC - //mTextBox->setWrappedText(mText); if(gFocusMgr.getTopCtrl() == this) { gFocusMgr.setTopCtrl(NULL); diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index 0b9c3f7258..b78a4dc674 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -54,27 +54,11 @@ protected: public: struct Params : public LLInitParam::Block { - Optional expand_textbox; - - Params(); }; - /** - * Draw text box and "More" link - */ - /*virtual*/ void draw(); - -// /** -// * Draws simple text(no urls) line by line, will show or hide "More" link -// * if needed. -// */ -// /*virtual*/ void drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color ); -// -// /** -// * Draws segmented text(with urls) line by line. Will show or hide "More" link -// * if needed -// */ -// void drawTextSegments(S32 x, S32 y, const LLWString &text); + // adds or removes "More" link as needed + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void setValue(const LLSD& value); /** * Returns difference between text box height and text height. @@ -92,11 +76,6 @@ protected: */ virtual S32 getHPad() { return mHPad; } - /** - * Broadcasts "commit" signal if user clicked "More" link - */ - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - protected: LLTextBoxEx(const Params& p); @@ -105,21 +84,16 @@ protected: /** * Shows "More" link */ - void showExpandText(S32 y); + void showExpandText(); /** * Hides "More" link */ void hideExpandText(); - /** - * Returns cropped line width - */ - S32 getCropTextWidth(); - private: - LLTextBox* mExpandTextBox; + bool mExpanded; }; public: diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index 5a29c6a319..8ed2047a27 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -316,13 +316,16 @@ height="40" follows="top|left|bottom" layout="topleft" - name="test_text_editor" + name="test_text_box" tool_tip="text box" top_pad="5" width="200"> Text box with multiple lines +and too +many +line to actually fit diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index b4212aaa34..9cf699ad46 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -43,7 +43,7 @@ layout="topleft" top="0" left="0" - width="284" + width="300" height="700"> + width="285"> + width="285"> Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml index bcfc2f6472..e470f42d36 100644 --- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml +++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml @@ -9,16 +9,6 @@ tab_stop="true" v_pad="2" h_pad="3" > - Date: Tue, 6 Oct 2009 01:25:47 +0000 Subject: made "more" link in LLExpandableTextBox localizable fixed logic for showing/hiding "more" link in LLExpandableTextBox fixed invisible background on combobox popup list reviewed by Leyla --- indra/llui/lltextbase.cpp | 3 ++ indra/newview/llexpandabletextbox.cpp | 37 ++++++++++++++++------ indra/newview/llexpandabletextbox.h | 15 +++++---- .../skins/default/xui/en/widgets/combo_box.xml | 4 ++- .../default/xui/en/widgets/expandable_text.xml | 1 + 5 files changed, 43 insertions(+), 17 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 62f03f47e6..3dacf979c7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -807,6 +807,9 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert) ++cur_seg_iter; } } + + // layout potentially changed + needsReflow(); } BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 28c124d1c6..2467356018 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -45,7 +45,7 @@ public: : LLTextSegment(start, end), mEditor(editor), mStyle(style), - mMoreText(more_text) + mExpanderLabel(more_text) {} /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const @@ -61,7 +61,15 @@ public: /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { F32 right_x; - mStyle->getFont()->renderUTF8(mMoreText, start, draw_rect.mRight, draw_rect.mTop, mStyle->getColor(), LLFontGL::RIGHT, LLFontGL::TOP, 0, mStyle->getShadowType(), end - start, draw_rect.getWidth(), &right_x, mEditor.getUseEllipses()); + mStyle->getFont()->renderUTF8(mExpanderLabel, start, + draw_rect.mRight, draw_rect.mTop, + mStyle->getColor(), + LLFontGL::RIGHT, LLFontGL::TOP, + 0, + mStyle->getShadowType(), + end - start, draw_rect.getWidth(), + &right_x, + mEditor.getUseEllipses()); return right_x; } /*virtual*/ S32 getMaxHeight() const { return llceil(mStyle->getFont()->getLineHeight()); } @@ -75,14 +83,17 @@ public: private: LLTextBase& mEditor; LLStyleSP mStyle; - std::string mMoreText; + std::string mExpanderLabel; }; - +LLExpandableTextBox::LLTextBoxEx::Params::Params() +: more_label("more_label") +{} LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) : LLTextBox(p), - mExpanded(false) + mExpanderLabel(p.more_label), + mExpanderVisible(false) { setIsChrome(TRUE); @@ -106,6 +117,9 @@ void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value) { LLTextBox::setValue(value); + // text contents have changed, segments are cleared out + // so hide the expander and determine if we need it + //mExpanderVisible = false; if (getTextPixelHeight() > getRect().getHeight()) { showExpandText(); @@ -119,7 +133,7 @@ void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value) void LLExpandableTextBox::LLTextBoxEx::showExpandText() { - if (!mExpanded) + if (!mExpanderVisible) { // get fully visible lines std::pair visible_lines = getVisibleLines(true); @@ -129,9 +143,9 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText() expander_style.font.name.setIfNotProvided(LLFontGL::nameFromFont(expander_style.font)); expander_style.font.style = "UNDERLINE"; expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, "More", *this); + LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this); insertSegment(expanderp); - mExpanded = true; + mExpanderVisible = true; } } @@ -139,14 +153,14 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText() //NOTE: obliterates existing styles (including hyperlinks) void LLExpandableTextBox::LLTextBoxEx::hideExpandText() { - if (mExpanded) + if (mExpanderVisible) { // this will overwrite the expander segment and all text styling with a single style LLNormalTextSegment* segmentp = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this); insertSegment(segmentp); - mExpanded = false; + mExpanderVisible = false; } } @@ -275,6 +289,9 @@ S32 LLExpandableTextBox::recalculateTextDelta(S32 text_delta) void LLExpandableTextBox::expandTextBox() { + // hide "more" link, and show full text contents + mTextBox->hideExpandText(); + S32 text_delta = mTextBox->getVerticalTextDelta(); text_delta += mTextBox->getVPad() * 2 + mScroll->getBorderWidth() * 2; // no need to expand diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index b78a4dc674..d6401e224f 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -54,6 +54,8 @@ protected: public: struct Params : public LLInitParam::Block { + Mandatory more_label; + Params(); }; // adds or removes "More" link as needed @@ -76,11 +78,6 @@ protected: */ virtual S32 getHPad() { return mHPad; } - protected: - - LLTextBoxEx(const Params& p); - friend class LLUICtrlFactory; - /** * Shows "More" link */ @@ -91,9 +88,15 @@ protected: */ void hideExpandText(); + protected: + + LLTextBoxEx(const Params& p); + friend class LLUICtrlFactory; + private: + std::string mExpanderLabel; - bool mExpanded; + bool mExpanderVisible; }; public: diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml index d7369d0726..0dbca318b6 100644 --- a/indra/newview/skins/default/xui/en/widgets/combo_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml @@ -20,7 +20,9 @@ image_unselected="DropDown_Off" image_selected="DropDown_Selected" image_disabled="DropDown_Disabled" /> - + diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml index e470f42d36..6381dce1d6 100644 --- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml +++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml @@ -2,6 +2,7 @@ Date: Tue, 6 Oct 2009 20:03:04 +0000 Subject: EXT-1013 - tab ordering is inconsistent in the preferences window reviewed by James --- indra/llui/llpanel.cpp | 2 +- indra/llui/lluictrlfactory.cpp | 8 -------- indra/llui/lluictrlfactory.h | 7 ++----- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'indra/llui') 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/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 4ce6677294..d8633453a8 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -379,14 +379,6 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na return res; } -//static -void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group) -{ - if (tab_group < 0) tab_group = parent->getLastTabGroup(); - parent->addChild(view, tab_group); -} - - // Avoid directly using LLUI and LLDir in the template code //static std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename) diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index e47010c316..5a028702e7 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -295,8 +295,8 @@ fail: if (parent) { - S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; - setCtrlParent(widget, parent, tab_group); + S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup(); + parent->addChild(widget, tab_group); } typedef typename T::child_registry_t registry_t; @@ -321,9 +321,6 @@ fail: static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); private: - //static void setCtrlValue(LLView* view, LLXMLNodePtr node); - static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); - // Avoid directly using LLUI and LLDir in the template code static std::string findSkinnedFilename(const std::string& filename); -- cgit v1.3 From 29ca0f064d56d957839aa05d94786b0c2d5ad5e5 Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Tue, 6 Oct 2009 21:09:54 +0000 Subject: fix for gcc --- indra/llui/lluictrlfactory.cpp | 8 ++++++++ indra/llui/lluictrlfactory.h | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index d8633453a8..4ce6677294 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -379,6 +379,14 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na return res; } +//static +void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group) +{ + if (tab_group < 0) tab_group = parent->getLastTabGroup(); + parent->addChild(view, tab_group); +} + + // Avoid directly using LLUI and LLDir in the template code //static std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename) diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 5a028702e7..3c77c655b8 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -295,8 +295,8 @@ fail: if (parent) { - S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup(); - parent->addChild(widget, tab_group); + S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; + setCtrlParent(widget, parent, tab_group); } typedef typename T::child_registry_t registry_t; @@ -321,6 +321,9 @@ fail: static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); private: + // 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 static std::string findSkinnedFilename(const std::string& filename); -- cgit v1.3 From 8086923d663cbca32a9b147973f912adcbd4a08a Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Tue, 6 Oct 2009 22:55:01 +0000 Subject: EXT-1283 [Inspectors] Avatar gear menu does not dismiss when selecting another AV reviewed by James --- indra/llui/llmenubutton.cpp | 6 ++++++ indra/llui/llmenubutton.h | 1 + indra/llui/lltooltip.cpp | 12 +++++++++++- indra/newview/llinspectavatar.cpp | 11 +++++++++++ indra/newview/llinspectobject.cpp | 3 +++ 5 files changed, 32 insertions(+), 1 deletion(-) (limited to 'indra/llui') 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/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/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 9b75c15597..fd301505cd 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -51,6 +51,7 @@ #include "llcontrol.h" // LLCachedControl #include "llfloater.h" #include "llfloaterreg.h" +#include "llmenubutton.h" #include "lltooltip.h" // positionViewNearMouse() #include "lluictrl.h" @@ -80,6 +81,9 @@ public: // Because floater is single instance, need to re-parse data on each spawn // (for example, inspector about same avatar but in different position) /*virtual*/ void onOpen(const LLSD& avatar_id); + + // When closing they should close their gear menu + /*virtual*/ void onClose(); // Inspectors close themselves when they lose focus /*virtual*/ void onFocusLost(); @@ -224,6 +228,8 @@ BOOL LLInspectAvatar::postBuild(void) getChild("volume_slider")->setCommitCallback( boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); + mCloseSignal.connect(boost::bind(&LLInspectAvatar::onClose, this)); + return TRUE; } @@ -288,6 +294,11 @@ void LLInspectAvatar::onOpen(const LLSD& data) updateVolumeSlider(); } +void LLInspectAvatar::onClose() +{ + getChild("gear_btn")->hideMenu(); +} + //virtual void LLInspectAvatar::onFocusLost() { diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index b0e6273c41..1a88bcb8f0 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -46,6 +46,7 @@ #include "llcontrol.h" // LLCachedControl #include "llfloater.h" #include "llfloaterreg.h" +#include "llmenubutton.h" #include "llresmgr.h" // getMonetaryString #include "llsafehandle.h" #include "lltextbox.h" // for description truncation @@ -254,6 +255,8 @@ void LLInspectObject::onClose() { // Release selection to deselect mObjectSelection = NULL; + + getChild("gear_btn")->hideMenu(); } //virtual -- cgit v1.3 From ae0827d387dc1e4d0f8a749cab36138f8ac174a0 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Wed, 7 Oct 2009 07:09:34 +0000 Subject: merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0@1908 https://svn.aws.productengine.com/secondlife/pe/stable-2@1917 -> viewer-2.0.0-3 * Bugs: EXT-1257 EXT-1299 EXT-1149 EXT-1117 EXT-1134 * New Dev: EXT-721 --- indra/llui/lldockablefloater.cpp | 10 + indra/llui/lldockablefloater.h | 3 + indra/llui/lldockcontrol.cpp | 22 +- indra/newview/llpanelplaceinfo.cpp | 199 +++++++--- indra/newview/llpanelplaceinfo.h | 15 +- indra/newview/llpanelplaces.cpp | 437 ++++++++++----------- indra/newview/llpanelplaces.h | 25 +- indra/newview/lltoastalertpanel.cpp | 1 - indra/newview/llviewermessage.cpp | 17 +- .../default/xui/en/floater_whitelist_entry.xml | 48 +-- .../newview/skins/default/xui/en/panel_places.xml | 52 ++- .../skins/default/xui/en/widgets/scroll_list.xml | 2 +- 12 files changed, 469 insertions(+), 362 deletions(-) (limited to 'indra/llui') 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 (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockHidden(); + } } else { - moveDockable(); + if(mEnabled) + { + moveDockable(); + } + LLDockableFloater* dockable_floater = + dynamic_cast (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockShown(); + } } mPrevDockRect = dockRect; diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index eb269fabe3..d6be0a9419 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -44,14 +44,16 @@ #include "llqueryflags.h" #include "llbutton.h" +#include "llcombobox.h" #include "lliconctrl.h" -#include "lllineeditor.h" #include "llscrollcontainer.h" #include "lltextbox.h" +#include "lltrans.h" #include "llaccordionctrl.h" #include "llaccordionctrltab.h" #include "llagent.h" +#include "llagentui.h" #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" #include "llinventorymodel.h" @@ -64,6 +66,16 @@ #include "llviewertexteditor.h" #include "llworldmap.h" +//---------------------------------------------------------------------------- +// Aux types and methods +//---------------------------------------------------------------------------- + +typedef std::pair folder_pair_t; + +static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); +static std::string getFullFolderName(const LLViewerInventoryCategory* cat); +static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); + static LLRegisterPanelClassWrapper t_place_info("panel_place_info"); LLPanelPlaceInfo::LLPanelPlaceInfo() @@ -141,11 +153,8 @@ BOOL LLPanelPlaceInfo::postBuild() mCreated = getChild("created"); mTitleEditor = getChild("title_editor"); - mTitleEditor->setCommitCallback(boost::bind(&LLPanelPlaceInfo::onCommitTitleOrNote, this, TITLE)); - mNotesEditor = getChild("notes_editor"); - mNotesEditor->setCommitCallback(boost::bind(&LLPanelPlaceInfo::onCommitTitleOrNote, this, NOTE)); - mNotesEditor->setCommitOnFocusLost(true); + mFolderCombo = getChild("folder_combo"); LLScrollContainer* scroll_container = getChild("scroll_container"); scroll_container->setBorderVisible(FALSE); @@ -316,6 +325,7 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) LLPanel* landmark_edit_panel = getChild("landmark_edit_panel"); bool is_info_type_agent = type == AGENT; + bool is_info_type_create_landmark = type == CREATE_LANDMARK; bool is_info_type_landmark = type == LANDMARK; bool is_info_type_teleport_history = type == TELEPORT_HISTORY; @@ -329,7 +339,10 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) mLastVisited->setVisible(is_info_type_teleport_history); landmark_info_panel->setVisible(is_info_type_landmark); - landmark_edit_panel->setVisible(is_info_type_landmark || type == CREATE_LANDMARK); + landmark_edit_panel->setVisible(is_info_type_landmark || is_info_type_create_landmark); + + getChild("folder_lable")->setVisible(is_info_type_create_landmark); + mFolderCombo->setVisible(is_info_type_create_landmark); getChild("advanced_info_accordion")->setVisible(is_info_type_agent); @@ -337,6 +350,11 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) { case CREATE_LANDMARK: mCurrentTitle = getString("title_create_landmark"); + + mTitleEditor->setEnabled(TRUE); + mNotesEditor->setEnabled(TRUE); + + populateFoldersList(); break; case AGENT: @@ -351,6 +369,11 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) case LANDMARK: mCurrentTitle = getString("title_landmark"); + + mTitleEditor->setEnabled(FALSE); + mNotesEditor->setEnabled(FALSE); + + populateFoldersList(); break; case TELEPORT_HISTORY: @@ -485,10 +508,9 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) parcel_data.sim_name.c_str(), region_x, region_y, region_z); mRegionName->setText(name); } - + if (mInfoType == CREATE_LANDMARK) { - if (parcel_data.name.empty()) { mTitleEditor->setText(name); @@ -498,7 +520,15 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mTitleEditor->setText(parcel_data.name); } - mNotesEditor->setText(LLStringUtil::null); + // FIXME: Creating landmark works only for current agent location. + std::string desc; + LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, gAgent.getPositionAgent()); + mNotesEditor->setText(desc); + + if (!LLLandmarkActions::landmarkAlreadyExists()) + { + createLandmark(mFolderCombo->getValue().asUUID()); + } } } @@ -694,7 +724,6 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel, &rent_price, &for_sale, &dwell); - if (for_sale) { // Adding "For Sale" flag in remote parcel response format. @@ -803,52 +832,42 @@ void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date) } } -void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type) +void LLPanelPlaceInfo::toggleLandmarkEditMode(BOOL enabled) { - LLInventoryItem* item = gInventory.getItem(mLandmarkID); - if (!item) - return; - - std::string current_value; - std::string item_value; - if (type == TITLE) + // If switching to edit mode while creating landmark + // the "Create Landmark" title remains. + if (enabled && mInfoType != CREATE_LANDMARK) { - if (mTitleEditor) - { - current_value = mTitleEditor->getText(); - item_value = item->getName(); - } + mTitle->setText(getString("title_edit_landmark")); } else { - if (mNotesEditor) - { - current_value = mNotesEditor->getText(); - item_value = item->getDescription(); - } + mTitle->setText(mCurrentTitle); } - LLStringUtil::trim(current_value); + mTitleEditor->setEnabled(enabled); + mNotesEditor->setReadOnly(!enabled); + mFolderCombo->setVisible(enabled); + getChild("folder_lable")->setVisible(enabled); - if (!current_value.empty() && - item_value != current_value && - gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) - { - LLPointer new_item = new LLViewerInventoryItem(item); + // HACK: To change the text color in a text editor + // when it was enabled/disabled we set the text once again. + mNotesEditor->setText(mNotesEditor->getText()); +} - if (type == TITLE) - { - new_item->rename(current_value); - } - else - { - new_item->setDescription(current_value); - } +const std::string& LLPanelPlaceInfo::getLandmarkTitle() const +{ + return mTitleEditor->getText(); +} - new_item->updateServer(FALSE); - gInventory.updateItem(new_item); - gInventory.notifyObservers(); - } +const std::string LLPanelPlaceInfo::getLandmarkNotes() const +{ + return mNotesEditor->getText(); +} + +const LLUUID LLPanelPlaceInfo::getLandmarkFolder() const +{ + return mFolderCombo->getValue().asUUID(); } void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id) @@ -921,3 +940,91 @@ void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility) } } } + +void LLPanelPlaceInfo::populateFoldersList() +{ + // Collect all folders that can contain landmarks. + LLInventoryModel::cat_array_t cats; + collectLandmarkFolders(cats); + + mFolderCombo->removeall(); + + // Put the "Landmarks" folder first in list. + LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + const LLViewerInventoryCategory* cat = gInventory.getCategory(landmarks_id); + if (!cat) + { + llwarns << "Cannot find the landmarks folder" << llendl; + } + std::string cat_full_name = getFullFolderName(cat); + mFolderCombo->add(cat_full_name, cat->getUUID()); + + typedef std::vector folder_vec_t; + folder_vec_t folders; + // Sort the folders by their full name. + for (S32 i = 0; i < cats.count(); i++) + { + cat = cats.get(i); + cat_full_name = getFullFolderName(cat); + folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name)); + } + sort(folders.begin(), folders.end(), cmp_folders); + + // Finally, populate the combobox. + for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++) + mFolderCombo->add(it->second, LLSD(it->first)); +} + +static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) +{ + return left.second < right.second; +} + +static std::string getFullFolderName(const LLViewerInventoryCategory* cat) +{ + std::string name = cat->getName(); + LLUUID parent_id; + + // translate category name, if it's right below the root + // FIXME: it can throw notification about non existent string in strings.xml + if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID()) + { + LLTrans::findString(name, "InvFolder " + name); + } + + // we don't want "My Inventory" to appear in the name + while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID()) + { + cat = gInventory.getCategory(parent_id); + name = cat->getName() + "/" + name; + } + + return name; +} + +static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) +{ + LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + + // Add descendent folders of the "Landmarks" category. + LLInventoryModel::item_array_t items; // unused + LLIsType is_category(LLAssetType::AT_CATEGORY); + gInventory.collectDescendentsIf( + landmarks_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_category); + + // Add the "My Favorites" category. + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); + if (!favorites_cat) + { + llwarns << "Cannot find the favorites folder" << llendl; + } + else + { + cats.put(favorites_cat); + } +} diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 23a845bc20..49aa195490 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -42,6 +42,7 @@ #include "llremoteparcelrequest.h" class LLButton; +class LLComboBox; class LLInventoryItem; class LLLineEditor; class LLPanelPick; @@ -117,18 +118,19 @@ public: const std::string& first, const std::string& last); + void toggleLandmarkEditMode(BOOL enabled); + + const std::string& getLandmarkTitle() const; + const std::string getLandmarkNotes() const; + const LLUUID getLandmarkFolder() const; + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); /*virtual*/ void handleVisibilityChange (BOOL new_visibility); private: - enum LANDMARK_INFO_TYPE - { - TITLE, - NOTE - }; - void onCommitTitleOrNote(LANDMARK_INFO_TYPE type); + void populateFoldersList(); LLUUID mParcelID; LLUUID mRequestedID; @@ -182,6 +184,7 @@ private: LLTextBox* mCreated; LLLineEditor* mTitleEditor; LLTextEditor* mNotesEditor; + LLComboBox* mFolderCombo; LLPanel* mScrollingPanel; LLPanel* mInfoPanel; LLMediaPanel* mMediaPanel; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 80ecc95afb..35206f54c7 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -40,16 +40,19 @@ #include "lllandmark.h" #include "llparcel.h" +#include "llcombobox.h" +#include "llfiltereditor.h" #include "llfloaterreg.h" #include "llnotifications.h" -#include "llfiltereditor.h" #include "lltabcontainer.h" +#include "lltexteditor.h" #include "lltrans.h" #include "lluictrlfactory.h" #include "llagent.h" #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" +#include "llinventorybridge.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" #include "lllandmarklist.h" @@ -74,9 +77,6 @@ static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history"; // Helper functions static bool is_agent_in_selected_parcel(LLParcel* parcel); -static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); -static std::string getFullFolderName(const LLViewerInventoryCategory* cat); -static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); static void onSLURLBuilt(std::string& slurl); static void setAllChildrenVisible(LLView* view, BOOL visible); @@ -125,8 +125,8 @@ LLPanelPlaces::LLPanelPlaces() mItem(NULL), mPlaceMenu(NULL), mLandmarkMenu(NULL), - mLandmarkFoldersMenuHandle(), - mPosGlobal() + mPosGlobal(), + isLandmarkEditModeOn(false) { mParcelObserver = new LLPlacesParcelObserver(this); mInventoryObserver = new LLPlacesInventoryObserver(this); @@ -146,20 +146,12 @@ LLPanelPlaces::~LLPanelPlaces() LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver); - LLView::deleteViewByHandle(mLandmarkFoldersMenuHandle); - delete mInventoryObserver; delete mParcelObserver; } BOOL LLPanelPlaces::postBuild() { - mCreateLandmarkBtn = getChild("create_landmark_btn"); - mCreateLandmarkBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, LLUUID())); - - mFolderMenuBtn = getChild("folder_menu_btn"); - mFolderMenuBtn->setClickedCallback(boost::bind(&LLPanelPlaces::showLandmarkFoldersMenu, this)); - mTeleportBtn = getChild("teleport_btn"); mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this)); @@ -169,6 +161,18 @@ BOOL LLPanelPlaces::postBuild() mShareBtn = getChild("share_btn"); //mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this)); + mEditBtn = getChild("edit_btn"); + mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); + + mSaveBtn = getChild("save_btn"); + mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this)); + + mCancelBtn = getChild("cancel_btn"); + mCancelBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCancelButtonClicked, this)); + + mCloseBtn = getChild("close_btn"); + mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); + mOverflowBtn = getChild("overflow_btn"); mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this)); @@ -200,10 +204,18 @@ BOOL LLPanelPlaces::postBuild() } mPlaceInfo = getChild("panel_place_info"); - + LLButton* back_btn = mPlaceInfo->getChild("back_btn"); back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); + LLLineEditor* title_editor = mPlaceInfo->getChild("title_editor"); + title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL); + + LLTextEditor* notes_editor = mPlaceInfo->getChild("notes_editor"); + notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); + + LLComboBox* folder_combo = mPlaceInfo->getChild("folder_combo"); + folder_combo->setSelectionCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); return TRUE; } @@ -217,6 +229,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) mPlaceInfoType = key["type"].asString(); mPosGlobal.setZero(); + mItem = NULL; togglePlaceInfoPanel(TRUE); updateVerbs(); @@ -227,11 +240,25 @@ void LLPanelPlaces::onOpen(const LLSD& key) else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE) { mPlaceInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK); + + if (key.has("x") && key.has("y") && key.has("z")) + { + mPosGlobal = LLVector3d(key["x"].asReal(), + key["y"].asReal(), + key["z"].asReal()); + } + else + { + mPosGlobal = gAgent.getPositionGlobal(); + } + + mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal); } else if (mPlaceInfoType == LANDMARK_INFO_TYPE) { - LLUUID item_uuid = key["id"].asUUID(); - LLInventoryItem* item = gInventory.getItem(item_uuid); + mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK); + + LLInventoryItem* item = gInventory.getItem(key["id"].asUUID()); if (!item) return; @@ -272,8 +299,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) // Start using LLViewerParcelMgr for land selection if // information about nearby land is requested. // Otherwise stop using land selection and deselect land. - if (mPlaceInfoType == AGENT_INFO_TYPE || - mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE) + if (mPlaceInfoType == AGENT_INFO_TYPE) { parcel_mgr->addObserver(mParcelObserver); parcel_mgr->selectParcelAt(gAgent.getPositionGlobal()); @@ -291,7 +317,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) void LLPanelPlaces::setItem(LLInventoryItem* item) { - if (!mPlaceInfo) + if (!item) return; mItem = item; @@ -304,7 +330,9 @@ void LLPanelPlaces::setItem(LLInventoryItem* item) return; } - mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK); + if (!mPlaceInfo) + return; + mPlaceInfo->displayItemInfo(mItem); LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(), @@ -324,6 +352,12 @@ void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark) landmark->getRegionID(region_id); landmark->getGlobalPos(mPosGlobal); mPlaceInfo->displayParcelInfo(region_id, mPosGlobal); + + // Check if item is in agent's inventory and he has the permission to modify it. + BOOL is_landmark_editable = mItem.notNull() && + gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) && + mItem->getPermissions().allowModifyBy(gAgent.getID()); + mEditBtn->setEnabled(is_landmark_editable); } void LLPanelPlaces::onFilterEdit(const std::string& search_string) @@ -436,6 +470,136 @@ void LLPanelPlaces::onShowOnMapButtonClicked() } } +void LLPanelPlaces::onEditButtonClicked() +{ + if (!mPlaceInfo || isLandmarkEditModeOn) + return; + + isLandmarkEditModeOn = true; + + mPlaceInfo->toggleLandmarkEditMode(TRUE); + + updateVerbs(); +} + +void LLPanelPlaces::onSaveButtonClicked() +{ + if (!mPlaceInfo || mItem.isNull()) + return; + + LLAssetType::EType item_type = mItem->getType(); + if (item_type == LLAssetType::AT_LANDMARK || item_type != LLAssetType::AT_LINK) + { + // If the item is a link get a linked item + if (item_type == LLAssetType::AT_LINK) + { + mItem = gInventory.getItem(mItem->getAssetUUID()); + if (mItem.isNull()) + return; + } + } + else + { + return; + } + + std::string current_title_value = mPlaceInfo->getLandmarkTitle(); + std::string item_title_value = mItem->getName(); + std::string current_notes_value = mPlaceInfo->getLandmarkNotes(); + std::string item_notes_value = mItem->getDescription(); + + LLStringUtil::trim(current_title_value); + LLStringUtil::trim(current_notes_value); + + bool is_item_update_needed = false; + + if (!current_title_value.empty() && + (item_title_value != current_title_value || item_notes_value != current_notes_value)) + { + is_item_update_needed = true; + } + + LLUUID item_id = mItem->getUUID(); + LLUUID folder_id = mPlaceInfo->getLandmarkFolder(); + + // Check if item is in agent's inventory and he has the permission to modify it. + if (!gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) || + !mItem->getPermissions().allowModifyBy(gAgent.getID())) + return; + + if(folder_id != mItem->getParentUUID() || is_item_update_needed) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)mItem.get(); + LLPointer new_item = new LLViewerInventoryItem(item); + + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + + // If target is the favorites folder we create link to it. + if (favorites_id == folder_id) + { + if (is_item_update_needed) + { + new_item->rename(current_title_value); + new_item->setDescription(current_notes_value); + new_item->updateServer(FALSE); + + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } + + link_inventory_item(gAgent.getID(), + item->getUUID(), + folder_id, + item->getName(), + LLAssetType::AT_LINK, + LLPointer(NULL)); + } + else + { + if (is_item_update_needed) + { + new_item->rename(current_title_value); + new_item->setDescription(current_notes_value); + new_item->updateServer(FALSE); + } + + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + new_item->setParent(folder_id); + new_item->updateParentOnServer(FALSE); + + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } + } + + onCancelButtonClicked(); +} + +void LLPanelPlaces::onCancelButtonClicked() +{ + if (!mPlaceInfo) + return; + + if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE) + { + onBackButtonClicked(); + } + else + { + mPlaceInfo->toggleLandmarkEditMode(FALSE); + updateVerbs(); + + // Reload the landmark properties. + mPlaceInfo->displayItemInfo(mItem); + } +} + void LLPanelPlaces::onOverflowButtonClicked() { LLToggleableMenu* menu; @@ -487,7 +651,12 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) std::string item = param.asString(); if (item == "landmark") { - onOpen(LLSD().insert("type", CREATE_LANDMARK_INFO_TYPE)); + LLSD key; + key["type"] = CREATE_LANDMARK_INFO_TYPE; + key["x"] = mPosGlobal.mdV[VX]; + key["y"] = mPosGlobal.mdV[VY]; + key["z"] = mPosGlobal.mdV[VZ]; + onOpen(key); } else if (item == "copy") { @@ -523,20 +692,6 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) } } -void LLPanelPlaces::onCreateLandmarkButtonClicked(const LLUUID& folder_id) -{ - if (!mPlaceInfo) - return; - - // To prevent creating duplicate landmarks - // disable landmark creating buttons until - // the information on existing landmarks is reloaded. - mCreateLandmarkBtn->setEnabled(FALSE); - mFolderMenuBtn->setEnabled(FALSE); - - mPlaceInfo->createLandmark(folder_id); -} - void LLPanelPlaces::onBackButtonClicked() { if (!mPlaceInfo) @@ -697,10 +852,14 @@ void LLPanelPlaces::updateVerbs() bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; bool is_media_panel_visible = mPlaceInfo->isMediaPanelVisible(); - mTeleportBtn->setVisible(!is_create_landmark_visible); - mShareBtn->setVisible(!is_create_landmark_visible); - mCreateLandmarkBtn->setVisible(is_create_landmark_visible); - mFolderMenuBtn->setVisible(is_create_landmark_visible); + mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mShareBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mOverflowBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn); + mSaveBtn->setVisible(isLandmarkEditModeOn); + mCancelBtn->setVisible(isLandmarkEditModeOn); + mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); mOverflowBtn->setEnabled(is_place_info_visible && !is_media_panel_visible && !is_create_landmark_visible); @@ -714,15 +873,6 @@ void LLPanelPlaces::updateVerbs() !mPosGlobal.isExactlyZero() && !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal)); } - else if (is_create_landmark_visible) - { - // Enable "Create Landmark" only if there is no landmark - // for the current parcel and agent is inside it. - bool enable = !LLLandmarkActions::landmarkAlreadyExists() && - is_agent_in_selected_parcel(mParcel->getParcel()); - mCreateLandmarkBtn->setEnabled(enable); - mFolderMenuBtn->setEnabled(enable); - } else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE) { mTeleportBtn->setEnabled(TRUE); @@ -735,131 +885,8 @@ void LLPanelPlaces::updateVerbs() if (mActivePanel) mActivePanel->updateVerbs(); } -} - -void LLPanelPlaces::showLandmarkFoldersMenu() -{ - if (mLandmarkFoldersMenuHandle.isDead()) - { - LLToggleableMenu::Params menu_p; - menu_p.name("landmarks_folders_menu"); - menu_p.can_tear_off(false); - menu_p.visible(false); - menu_p.scrollable(true); - menu_p.max_scrollable_items = 10; - - LLToggleableMenu* menu = LLUICtrlFactory::create(menu_p); - - mLandmarkFoldersMenuHandle = menu->getHandle(); - } - - LLToggleableMenu* menu = (LLToggleableMenu*)mLandmarkFoldersMenuHandle.get(); - if(!menu) - return; - - if (!menu->toggleVisibility()) - return; - - // Collect all folders that can contain landmarks. - LLInventoryModel::cat_array_t cats; - collectLandmarkFolders(cats); - - // Sort the folders by their full name. - folder_vec_t folders; - S32 count = cats.count(); - for (S32 i = 0; i < count; i++) - { - const LLViewerInventoryCategory* cat = cats.get(i); - std::string cat_full_name = getFullFolderName(cat); - folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name)); - } - sort(folders.begin(), folders.end(), cmp_folders); - - LLRect btn_rect = mFolderMenuBtn->getRect(); - - LLRect root_rect = getRootView()->getRect(); - - // Check it there are changed items or viewer dimensions - // have changed since last call - if (mLandmarkFoldersCache.size() == count && - mRootViewWidth == root_rect.getWidth() && - mRootViewHeight == root_rect.getHeight()) - { - S32 i; - for (i = 0; i < count; i++) - { - if (mLandmarkFoldersCache[i].second != folders[i].second) - { - break; - } - } - - // Check passed, just show the menu - if (i == count) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - - menu->setButtonRect(btn_rect, this); - LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop); - return; - } - } - - // If there are changes, store the new viewer dimensions - // and a list of folders - mRootViewWidth = root_rect.getWidth(); - mRootViewHeight = root_rect.getHeight(); - mLandmarkFoldersCache = folders; - - menu->empty(); - - // Menu width must not exceed the root view limits, - // so we assume the space between the left edge of - // the root view and - LLRect screen_btn_rect; - localRectToScreen(btn_rect, &screen_btn_rect); - S32 free_space = screen_btn_rect.mRight; - U32 max_width = llmin(LANDMARK_FOLDERS_MENU_WIDTH, free_space); - for(folder_vec_t::const_iterator it = mLandmarkFoldersCache.begin(); it != mLandmarkFoldersCache.end(); it++) - { - const std::string& item_name = it->second; - - LLMenuItemCallGL::Params item_params; - item_params.name(item_name); - item_params.label(item_name); - - item_params.on_click.function(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, it->first)); - - LLMenuItemCallGL *menu_item = LLUICtrlFactory::create(item_params); - - // *TODO: Use a separate method for menu width calculation. - // Check whether item name wider than menu - if (menu_item->getNominalWidth() > max_width) - { - S32 chars_total = item_name.length(); - S32 chars_fitted = 1; - menu_item->setLabel(LLStringExplicit("")); - S32 label_space = max_width - menu_item->getFont()->getWidth("...") - - menu_item->getNominalWidth(); // This returns width of menu item with empty label (pad pixels) - - while (chars_fitted < chars_total && menu_item->getFont()->getWidth(item_name, 0, chars_fitted) < label_space) - { - chars_fitted++; - } - chars_fitted--; // Rolling back one char, that doesn't fit - - menu_item->setLabel(item_name.substr(0, chars_fitted) + "..."); - } - - menu->addChild(menu_item); - } - - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - menu->setButtonRect(btn_rect, this); - LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop); + isLandmarkEditModeOn = false; } static bool is_agent_in_selected_parcel(LLParcel* parcel) @@ -874,70 +901,6 @@ static bool is_agent_in_selected_parcel(LLParcel* parcel) parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID(); } -static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) -{ - return left.second < right.second; -} - -static std::string getFullFolderName(const LLViewerInventoryCategory* cat) -{ - std::string name = cat->getName(); - LLUUID parent_id; - - // translate category name, if it's right below the root - // FIXME: it can throw notification about non existent string in strings.xml - if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID()) - { - LLTrans::findString(name, "InvFolder " + name); - } - - // we don't want "My Inventory" to appear in the name - while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID()) - { - cat = gInventory.getCategory(parent_id); - name = cat->getName() + "/" + name; - } - - return name; -} - -static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) -{ - // Add the "Landmarks" category itself. - LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); - LLViewerInventoryCategory* landmarks_cat = gInventory.getCategory(landmarks_id); - if (!landmarks_cat) - { - llwarns << "Cannot find the landmarks folder" << llendl; - } - else - { - cats.put(landmarks_cat); - } - - // Add descendent folders of the "Landmarks" category. - LLInventoryModel::item_array_t items; // unused - LLIsType is_category(LLAssetType::AT_CATEGORY); - gInventory.collectDescendentsIf( - landmarks_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_category); - - // Add the "My Favorites" category. - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); - LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); - if (!favorites_cat) - { - llwarns << "Cannot find the favorites folder" << llendl; - } - else - { - cats.put(favorites_cat); - } -} - static void onSLURLBuilt(std::string& slurl) { LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index f208e91237..0b3b3b5fc3 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -72,6 +72,9 @@ private: //void onShareButtonClicked(); void onTeleportButtonClicked(); void onShowOnMapButtonClicked(); + void onEditButtonClicked(); + void onSaveButtonClicked(); + void onCancelButtonClicked(); void onOverflowButtonClicked(); void onOverflowMenuItemClicked(const LLSD& param); void onCreateLandmarkButtonClicked(const LLUUID& folder_id); @@ -84,8 +87,6 @@ private: void onAgentParcelChange(); void updateVerbs(); - void showLandmarkFoldersMenu(); - LLFilterEditor* mFilterEditor; LLPanelPlacesTab* mActivePanel; LLTabContainer* mTabContainer; @@ -94,11 +95,13 @@ private: LLToggleableMenu* mPlaceMenu; LLToggleableMenu* mLandmarkMenu; - LLButton* mCreateLandmarkBtn; - LLButton* mFolderMenuBtn; LLButton* mTeleportBtn; LLButton* mShowOnMapBtn; LLButton* mShareBtn; + LLButton* mEditBtn; + LLButton* mSaveBtn; + LLButton* mCancelBtn; + LLButton* mCloseBtn; LLButton* mOverflowBtn; LLPlacesInventoryObserver* mInventoryObserver; @@ -118,19 +121,7 @@ private: // Information type currently shown in Place Information panel std::string mPlaceInfoType; - // Menu handle for pop-up menu to chose a landmark saving - // folder when creating a new landmark - LLHandle mLandmarkFoldersMenuHandle; - - typedef std::vector folder_vec_t; - - // List of folders to choose from when creating a landmark - folder_vec_t mLandmarkFoldersCache; - - // If root view width or height is changed - // the pop-up menu must be updated - S32 mRootViewWidth; - S32 mRootViewHeight; + bool isLandmarkEditModeOn; LLSafeHandle mParcel; }; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index d9be6b172c..e4a3f8603b 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -308,7 +308,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal //gFloaterView->adjustToFitScreen(this, FALSE); if (mLineEditor) { - mLineEditor->setFocus(TRUE); mLineEditor->selectAll(); } if(mDefaultOption >= 0) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 2e8580907e..aa662b713e 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -98,6 +98,7 @@ #include "llnotifications.h" #include "llnotify.h" #include "llpanelgrouplandmoney.h" +#include "llpanelplaces.h" #include "llrecentpeople.h" #include "llselectmgr.h" #include "llsidetray.h" @@ -138,7 +139,6 @@ #include "llkeythrottle.h" #include "llgroupactions.h" #include "llagentui.h" -#include "llsidetray.h" #include "llpanelblockedlist.h" #include "llpanelplaceinfo.h" @@ -907,14 +907,15 @@ void open_offer(const std::vector& items, const std::string& from_name) LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID()); LLSD args; args["LANDMARK_NAME"] = item->getName(); - args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unnkown"); + args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown"); LLNotifications::instance().add("LandmarkCreated", args); - - // Open new landmark for editing in Places panel. - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - LLSideTray::getInstance()->showPanel("panel_places", key); + + // Created landmark is passed to Places panel to allow its editing. + LLPanelPlaces *panel = dynamic_cast(LLSideTray::getInstance()->showPanel("panel_places", LLSD())); + if (panel) + { + panel->setItem(item); + } } break; case LLAssetType::AT_TEXTURE: diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml index 0eb2c5e1be..4f501b65f3 100644 --- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml +++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml @@ -1,24 +1,24 @@ - - - - - Enter a URL or URL pattern to add to the list of allowed domains - - - - -