diff options
-rw-r--r-- | indra/llui/llfloater.cpp | 2 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llmultislider.cpp | 48 | ||||
-rw-r--r-- | indra/llui/llmultislider.h | 32 | ||||
-rw-r--r-- | indra/llui/llmultisliderctrl.cpp | 4 | ||||
-rw-r--r-- | indra/llui/llmultisliderctrl.h | 2 | ||||
-rw-r--r-- | indra/llui/llpanel.cpp | 4 | ||||
-rw-r--r-- | indra/llui/llradiogroup.cpp | 4 | ||||
-rw-r--r-- | indra/llui/llscrolllistcell.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llspinctrl.cpp | 20 | ||||
-rw-r--r-- | indra/llui/lltabcontainer.cpp | 8 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 23 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 2 | ||||
-rw-r--r-- | indra/llui/lluictrlfactory.h | 3 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 24 | ||||
-rw-r--r-- | indra/llui/llview.h | 8 | ||||
-rw-r--r-- | indra/newview/llchathistory.cpp | 141 | ||||
-rw-r--r-- | indra/newview/llchathistory.h | 22 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_aaa.xml | 10 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 6 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/widgets/chat_history.xml | 8 |
21 files changed, 279 insertions, 96 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index f7fd2dbdfe..d7a692ec9b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2717,7 +2717,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o } params.from_xui = true; - setupParams(params, parent); + applyXUILayout(params, parent); initFromParams(params); initFloater(params); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 5e15fa3919..7d8c102750 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -247,7 +247,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o } p.from_xui = true; - setupParams(p, parent); + applyXUILayout(p, parent); LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p); if (parent && layout_stackp) diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 1891bca36c..aea7c5f87c 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -50,6 +50,12 @@ const F32 FLOAT_THRESHOLD = 0.00001f; S32 LLMultiSlider::mNameCounter = 0; +LLMultiSlider::SliderParams::SliderParams() +: name("name"), + value("value", 0.f) +{ +} + LLMultiSlider::Params::Params() : max_sliders("max_sliders", 1), allow_overlap("allow_overlap", false), @@ -63,7 +69,8 @@ LLMultiSlider::Params::Params() triangle_color("triangle_color"), mouse_down_callback("mouse_down_callback"), mouse_up_callback("mouse_up_callback"), - thumb_width("thumb_width") + thumb_width("thumb_width"), + sliders("slider") { name = "multi_slider_bar"; mouse_opaque(true); @@ -99,6 +106,20 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) { setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); } + + for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders().begin(); + it != p.sliders().end(); + ++it) + { + if (it->name.isProvided()) + { + addSlider(it->value, it->name); + } + else + { + addSlider(it->value); + } + } } LLMultiSlider::~LLMultiSlider() @@ -230,6 +251,30 @@ const std::string& LLMultiSlider::addSlider(F32 val) return mCurSlider; } +void LLMultiSlider::addSlider(F32 val, const std::string& name) +{ + F32 initVal = val; + + if(mValue.size() >= mMaxNumSliders) { + return; + } + + bool foundOne = findUnusedValue(initVal); + if(!foundOne) { + return; + } + + // add a new thumb rect + mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 ); + + // add the value and set the current slider to this one + mValue.insert(name, initVal); + mCurSlider = name; + + // move the slider + setSliderValue(mCurSlider, initVal, TRUE); +} + bool LLMultiSlider::findUnusedValue(F32& initVal) { bool firstTry = true; @@ -572,7 +617,6 @@ void LLMultiSlider::draw() LLF32UICtrl::draw(); } - boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) { if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index f8e43a0470..88576da85b 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -41,6 +41,13 @@ class LLUICtrlFactory; class LLMultiSlider : public LLF32UICtrl { public: + struct SliderParams : public LLInitParam::Block<SliderParams> + { + Optional<std::string> name; + Mandatory<F32> value; + SliderParams(); + }; + struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params> { Optional<S32> max_sliders; @@ -60,6 +67,7 @@ public: mouse_up_callback; Optional<S32> thumb_width; + Multiple<SliderParams> sliders; Params(); }; @@ -68,13 +76,13 @@ protected: friend class LLUICtrlFactory; public: virtual ~LLMultiSlider(); - void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); - F32 getSliderValue(const std::string& name) const; + void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); + F32 getSliderValue(const std::string& name) const; - const std::string& getCurSlider() const { return mCurSlider; } - F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } - void setCurSlider(const std::string& name); - void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } + const std::string& getCurSlider() const { return mCurSlider; } + F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } + void setCurSlider(const std::string& name); + void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } /*virtual*/ void setValue(const LLSD& value); /*virtual*/ LLSD getValue() const { return mValue; } @@ -82,12 +90,13 @@ public: boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); - bool findUnusedValue(F32& initVal); + bool findUnusedValue(F32& initVal); const std::string& addSlider(); const std::string& addSlider(F32 val); - void deleteSlider(const std::string& name); - void deleteCurSlider() { deleteSlider(mCurSlider); } - void clear(); + void addSlider(F32 val, const std::string& name); + void deleteSlider(const std::string& name); + void deleteCurSlider() { deleteSlider(mCurSlider); } + void clear(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -109,7 +118,8 @@ protected: LLRect mDragStartThumbRect; S32 mThumbWidth; - std::map<std::string, LLRect> mThumbRects; + std::map<std::string, LLRect> + mThumbRects; LLUIColor mTrackColor; LLUIColor mThumbOutlineColor; LLUIColor mThumbCenterColor; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 7323323d8c..f4434a0f78 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -65,7 +65,8 @@ LLMultiSliderCtrl::Params::Params() text_color("text_color"), text_disabled_color("text_disabled_color"), mouse_down_callback("mouse_down_callback"), - mouse_up_callback("mouse_up_callback") + mouse_up_callback("mouse_up_callback"), + sliders("slider") { mouse_opaque = true; } @@ -161,6 +162,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0; LLRect slider_rect( slider_left, top, slider_right, bottom ); LLMultiSlider::Params params; + params.sliders = p.sliders; params.rect(slider_rect); params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit ); params.mouse_down_callback( p.mouse_down_callback ); diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index 16d07541f2..e8366d09c2 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -69,6 +69,8 @@ public: Optional<CommitCallbackParam> mouse_down_callback, mouse_up_callback; + Multiple<LLMultiSlider::SliderParams> sliders; + Params(); }; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 738a96f730..db32882438 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -452,7 +452,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p) parseFollowsFlags(p); setToolTip(p.tool_tip()); - setSaveToXML(p.from_xui); + setFromXUI(p.from_xui); mHoverCursor = getCursorFromString(p.hover_cursor); @@ -542,7 +542,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu } params.from_xui = true; - setupParams(params, parent); + applyXUILayout(params, parent); { LLFastTimer timer(FTM_PANEL_CONSTRUCTION); initFromParams(params); diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 997b9c13f8..4087b484aa 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -116,6 +116,10 @@ void LLRadioGroup::initFromParams(const Params& p) item_params.font.setIfNotProvided(mFont); // apply radio group font by default item_params.commit_callback.function = boost::bind(&LLRadioGroup::onClickButton, this, _1); item_params.from_xui = p.from_xui; + if (p.from_xui) + { + applyXUILayout(item_params, this); + } LLRadioCtrl* item = LLUICtrlFactory::create<LLRadioCtrl>(item_params, this); mRadioButtons.push_back(item); diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 544352176a..7238d903a3 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -353,7 +353,7 @@ LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p) { LLCheckBoxCtrl::Params checkbox_p; checkbox_p.name("checkbox"); - checkbox_p.rect.left(0).bottom(0).width(p.width).height(p.width); + checkbox_p.rect = LLRect(0, p.width, p.width, 0); checkbox_p.enabled(p.enabled); checkbox_p.initial_value(p.value()); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index d6d46654d5..20a1ab7af3 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -75,10 +75,8 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0); static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0); static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0); - S32 top = getRect().getHeight(); - S32 bottom = top - 2 * spinctrl_btn_height; - S32 centered_top = top; - S32 centered_bottom = bottom; + S32 centered_top = getRect().getHeight(); + S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height; S32 btn_left = 0; // reserve space for spinner S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40)); @@ -105,25 +103,15 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) // Spin buttons LLButton::Params up_button_params(p.up_button); - up_button_params.rect - .left(btn_left) - .top(top) - .right(btn_right) - .height(spinctrl_btn_height); + up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height); up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params); addChild(mUpBtn); - LLRect down_rect( btn_left, top - spinctrl_btn_height, btn_right, bottom ); - LLButton::Params down_button_params(p.down_button); - down_button_params.rect - .left(btn_left) - .right(btn_right) - .bottom(bottom) - .height(spinctrl_btn_height); + down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height); down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 83e2e3db50..327dd01612 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -266,8 +266,6 @@ bool LLTabContainer::addChild(LLView* view, S32 tab_group) if (panelp) { - panelp->setSaveToXML(TRUE); - addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL)); return true; } @@ -1019,12 +1017,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) { if (textbox) { - textbox->setSaveToXML(false); addChild( textbox, 0 ); } if (btn) { - btn->setSaveToXML(false); addChild( btn, 0 ); } } @@ -1747,24 +1743,20 @@ void LLTabContainer::initButtons() } } - mPrevArrowBtn->setSaveToXML(false); mPrevArrowBtn->setTabStop(FALSE); addChild(mPrevArrowBtn); - mNextArrowBtn->setSaveToXML(false); mNextArrowBtn->setTabStop(FALSE); addChild(mNextArrowBtn); if (mJumpPrevArrowBtn) { - mJumpPrevArrowBtn->setSaveToXML(false); mJumpPrevArrowBtn->setTabStop(FALSE); addChild(mJumpPrevArrowBtn); } if (mJumpNextArrowBtn) { - mJumpNextArrowBtn->setSaveToXML(false); mJumpNextArrowBtn->setTabStop(FALSE); addChild(mJumpNextArrowBtn); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cb0907a771..e54032ac5e 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -962,7 +962,10 @@ void LLTextBase::draw() reflow(); // then update scroll position, as cursor may have moved - updateScrollFromCursor(); + if (!mReadOnly) + { + updateScrollFromCursor(); + } LLRect doc_rect; if (mScroller) @@ -1932,11 +1935,19 @@ void LLTextBase::endOfLine() void LLTextBase::startOfDoc() { setCursorPos(0); + if (mScroller) + { + mScroller->goToTop(); + } } void LLTextBase::endOfDoc() { setCursorPos(getLength()); + if (mScroller) + { + mScroller->goToBottom(); + } } void LLTextBase::changePage( S32 delta ) @@ -2001,6 +2012,16 @@ void LLTextBase::changeLine( S32 delta ) setCursorPos(new_cursor_pos, true); } +bool LLTextBase::scrolledToStart() +{ + return mScroller->isAtTop(); +} + +bool LLTextBase::scrolledToEnd() +{ + return mScroller->isAtBottom(); +} + bool LLTextBase::setCursor(S32 row, S32 column) { diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a1f8ba39ae..c91578b637 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -180,6 +180,8 @@ public: void changePage( S32 delta ); void changeLine( S32 delta ); + bool scrolledToStart(); + bool scrolledToEnd(); const LLFontGL* getDefaultFont() const { return mDefaultFont; } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 6788f29ba9..b1fa6add67 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -184,8 +184,6 @@ public: { T* widget = NULL; - T::setupParams(params, parent); - if (!params.validateBlock()) { llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; @@ -310,6 +308,7 @@ fail: // Apply layout transformations, usually munging rect params.from_xui = true; + T::applyXUILayout(params, parent); T* widget = createWidget<T>(params, parent); typedef typename T::child_registry_t registry_t; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index a8d8626e49..f1b08c380b 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -126,7 +126,7 @@ LLView::LLView(const LLView::Params& p) : mName(p.name), mParentView(NULL), mReshapeFlags(FOLLOWS_NONE), - mSaveToXML(p.from_xui), + mFromXUI(p.from_xui), mIsFocusRoot(FALSE), mLastVisible(FALSE), mNextInsertionOrdinal(0), @@ -2479,7 +2479,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) for (;itor != parent->getChildList()->end(); ++itor) { LLView *last_view = (*itor); - if (last_view->getSaveToXML()) + if (last_view->getFromXUI()) { *rect = last_view->getRect(); return true; @@ -2489,7 +2489,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) } //static -void LLView::setupParams(LLView::Params& p, LLView* parent) +void LLView::applyXUILayout(LLView::Params& p, LLView* parent) { const S32 VPAD = 4; const S32 MIN_WIDGET_HEIGHT = 10; @@ -2509,7 +2509,7 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) LLRect last_rect = parent->getLocalRect(); bool layout_topleft = (p.layout() == "topleft"); - if (layout_topleft && p.from_xui) + if (layout_topleft) { //invert top to bottom if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; @@ -2535,10 +2535,10 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) p.rect.right.setProvided(false); // recalculate the right } } - else if (p.from_xui) // only do negative coordinate magic for XUI + else { - if (p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); - if (p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); + if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); + if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); } if (p.center_vert) { @@ -2556,15 +2556,15 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) p.rect.top.setProvided(false); // recalculate the top } } - else if (p.from_xui) + else { - if (p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); - if (p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); + if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); + if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); } // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels - if (!p.rect.height.isProvided() && !p.rect.top.isProvided()) + if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) { p.rect.height = MIN_WIDGET_HEIGHT; } @@ -2663,7 +2663,7 @@ static void convert_to_relative_layout(LLView::Params& p, LLView* parent) // Use setupParams to get the final widget rectangle // according to our wacky layout rules. LLView::Params final = p; - LLView::setupParams(final, parent); + LLView::applyXUILayout(final, parent); // Must actually extract the rectangle to get consistent // right = left+width, top = bottom+height LLRect final_rect = final.rect; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f8460f5361..c4d7313743 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -395,8 +395,8 @@ public: void parseFollowsFlags(const LLView::Params& params); // Some widgets, like close box buttons, don't need to be saved - BOOL getSaveToXML() const { return mSaveToXML; } - void setSaveToXML(BOOL b) { mSaveToXML = b; } + BOOL getFromXUI() const { return mFromXUI; } + void setFromXUI(BOOL b) { mFromXUI = b; } typedef enum e_hit_test_type { @@ -498,7 +498,7 @@ public: // Set up params after XML load before calling new(), // usually to adjust layout. - static void setupParams(Params& p, LLView* parent); + static void applyXUILayout(Params& p, LLView* parent); // For re-export of floaters and panels, convert the coordinate system // to be top-left based. @@ -573,7 +573,7 @@ private: LLUIString mToolTipMsg; // isNull() is true if none. U8 mSoundFlags; - BOOL mSaveToXML; + BOOL mFromXUI; BOOL mIsFocusRoot; BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index ee60df1b4b..37e27cf165 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -44,6 +44,8 @@ #include "llfloaterreg.h" #include "llmutelist.h" #include "llstylemap.h" +#include "lllayoutstack.h" +#include "llagent.h" #include "llsidetray.h"//for blocked objects panel @@ -311,18 +313,23 @@ protected: LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) -: LLTextEditor(p), -mMessageHeaderFilename(p.message_header), -mMessageSeparatorFilename(p.message_separator), -mLeftTextPad(p.left_text_pad), -mRightTextPad(p.right_text_pad), -mLeftWidgetPad(p.left_widget_pad), -mRightWidgetPad(p.right_widget_pad), -mTopSeparatorPad(p.top_separator_pad), -mBottomSeparatorPad(p.bottom_separator_pad), -mTopHeaderPad(p.top_header_pad), -mBottomHeaderPad(p.bottom_header_pad) +: LLUICtrl(p), + mMessageHeaderFilename(p.message_header), + mMessageSeparatorFilename(p.message_separator), + mLeftTextPad(p.left_text_pad), + mRightTextPad(p.right_text_pad), + mLeftWidgetPad(p.left_widget_pad), + mRightWidgetPad(p.right_widget_pad), + mTopSeparatorPad(p.top_separator_pad), + mBottomSeparatorPad(p.bottom_separator_pad), + mTopHeaderPad(p.top_header_pad), + mBottomHeaderPad(p.bottom_header_pad) { + LLTextEditor::Params editor_params(p); + editor_params.rect = getLocalRect(); + editor_params.follows.flags = FOLLOWS_ALL; + editor_params.enabled = false; // read only + mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } LLChatHistory::~LLChatHistory() @@ -330,6 +337,49 @@ LLChatHistory::~LLChatHistory() this->clear(); } +void LLChatHistory::initFromParams(const LLChatHistory::Params& p) +{ + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + + LLRect stack_rect = getLocalRect(); + stack_rect.mRight -= scrollbar_size; + LLLayoutStack::Params layout_p; + layout_p.rect = stack_rect; + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.orientation = "vertical"; + layout_p.mouse_opaque = false; + + LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this); + + const S32 NEW_TEXT_NOTICE_HEIGHT = 20; + + LLPanel::Params panel_p; + panel_p.name = "spacer"; + panel_p.background_visible = false; + panel_p.has_border = false; + panel_p.mouse_opaque = false; + stackp->addPanel(LLUICtrlFactory::create<LLPanel>(panel_p), 0, 30, true, false, LLLayoutStack::ANIMATE); + + panel_p.name = "new_text_notice_holder"; + LLRect new_text_notice_rect = getLocalRect(); + new_text_notice_rect.mTop = new_text_notice_rect.mBottom + NEW_TEXT_NOTICE_HEIGHT; + panel_p.rect = new_text_notice_rect; + panel_p.background_opaque = true; + panel_p.background_visible = true; + panel_p.visible = false; + mMoreChatPanel = LLUICtrlFactory::create<LLPanel>(panel_p); + + LLTextBox::Params text_p(p.more_chat_text); + text_p.rect = mMoreChatPanel->getLocalRect(); + text_p.follows.flags = FOLLOWS_ALL; + text_p.name = "more_chat_text"; + mMoreChatText = LLUICtrlFactory::create<LLTextBox>(text_p, mMoreChatPanel); + mMoreChatText->setClickedCallback(boost::bind(&LLChatHistory::onClickMoreText, this)); + + stackp->addPanel(mMoreChatPanel, 0, 0, false, false, LLLayoutStack::ANIMATE); +} + + /*void LLChatHistory::updateTextRect() { static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0); @@ -358,15 +408,49 @@ LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style return header; } +void LLChatHistory::onClickMoreText() +{ + mEditor->endOfDoc(); +} + void LLChatHistory::clear() { mLastFromName.clear(); - LLTextEditor::clear(); + mEditor->clear(); mLastFromID = LLUUID::null; } void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_chat_history, const LLStyle::Params& input_append_params) { + if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) + { + mUnreadChatSources.insert(chat.mFromName); + mMoreChatPanel->setVisible(TRUE); + std::string chatters; + for (unread_chat_source_t::iterator it = mUnreadChatSources.begin(); + it != mUnreadChatSources.end();) + { + chatters += *it; + if (++it != mUnreadChatSources.end()) + { + chatters += ","; + } + } + LLStringUtil::format_map_t args; + args["SOURCES"] = chatters; + + if (mUnreadChatSources.size() == 1) + { + mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args)); + } + else + { + mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args)); + } + S32 height = mMoreChatText->getTextPixelHeight() + 5; + mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height); + } + LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); @@ -381,7 +465,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (use_plain_text_chat_history) { - appendText("[" + chat.mTimeStr + "] ", getText().size() != 0, style_params); + mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params); if (utf8str_trim(chat.mFromName).size() != 0) { @@ -391,11 +475,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ LLStyle::Params link_params(style_params); link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); // Convert the name to a hotlink and add to message. - appendText(chat.mFromName + ": ", false, link_params); + mEditor->appendText(chat.mFromName + ": ", false, link_params); } else { - appendText(chat.mFromName + ": ", false, style_params); + mEditor->appendText(chat.mFromName + ": ", false, style_params); } } } @@ -422,7 +506,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ else { view = getHeader(chat, style_params); - if (getText().size() == 0) + if (mEditor->getText().size() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; @@ -432,9 +516,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ p.view = view; //Prepare the rect for the view - LLRect target_rect = getDocumentView()->getRect(); + LLRect target_rect = mEditor->getDocumentView()->getRect(); // squeeze down the widget by subtracting padding off left and right - target_rect.mLeft += mLeftWidgetPad + mHPad; + target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); target_rect.mRight -= mRightWidgetPad; view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); @@ -443,7 +527,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM) header_text += chat.mFromName + ": "; - appendWidget(p, header_text, false); + mEditor->appendWidget(p, header_text, false); mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; @@ -455,10 +539,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ style_params.font.style = "ITALIC"; if (chat.mFromName.size() > 0) - appendText(chat.mFromName + " ", TRUE, style_params); + mEditor->appendText(chat.mFromName + " ", TRUE, style_params); // Ensure that message ends with NewLine, to avoid losing of new lines // while copy/paste from text chat. See EXT-3263. - appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); + mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); } else { @@ -469,8 +553,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ // while copy/paste from text chat. See EXT-3263. message += NEW_LINE; } - appendText(message, FALSE, style_params); + mEditor->appendText(message, FALSE, style_params); } - blockUndo(); + mEditor->blockUndo(); +} + +void LLChatHistory::draw() +{ + if (mEditor->scrolledToEnd()) + { + mUnreadChatSources.clear(); + mMoreChatPanel->setVisible(FALSE); + } + + LLUICtrl::draw(); } diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 8ca7dd1d58..260015e2dc 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -34,10 +34,11 @@ #define LLCHATHISTORY_H_ #include "lltexteditor.h" +#include "lltextbox.h" #include "llviewerchat.h" //Chat log widget allowing addition of a message as a widget -class LLChatHistory : public LLTextEditor +class LLChatHistory : public LLUICtrl { public: struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> @@ -63,6 +64,8 @@ class LLChatHistory : public LLTextEditor //Header bottom padding Optional<S32> bottom_header_pad; + Optional<LLTextBox::Params> more_chat_text; + Params() : message_header("message_header"), message_separator("message_separator"), @@ -73,15 +76,16 @@ class LLChatHistory : public LLTextEditor top_separator_pad("top_separator_pad"), bottom_separator_pad("bottom_separator_pad"), top_header_pad("top_header_pad"), - bottom_header_pad("bottom_header_pad") - { - } + bottom_header_pad("bottom_header_pad"), + more_chat_text("more_chat_text") + {} }; protected: LLChatHistory(const Params&); friend class LLUICtrlFactory; + /*virtual*/ void draw(); /** * Redefinition of LLTextEditor::updateTextRect() to considerate text * left/right padding params. @@ -98,9 +102,13 @@ class LLChatHistory : public LLTextEditor */ LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params); + void onClickMoreText(); + public: ~LLChatHistory(); + void initFromParams(const Params&); + /** * Appends a widget message. * If last user appended message, concurs with current user, @@ -129,5 +137,11 @@ class LLChatHistory : public LLTextEditor S32 mBottomSeparatorPad; S32 mTopHeaderPad; S32 mBottomHeaderPad; + + LLPanel* mMoreChatPanel; + LLTextBox* mMoreChatText; + LLTextEditor* mEditor; + typedef std::set<std::string> unread_chat_source_t; + unread_chat_source_t mUnreadChatSources; }; #endif /* LLCHATHISTORY_H_ */ diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 6956b73371..cb4cbd229a 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -15,21 +15,21 @@ title="TEST FLOATER" save_dock_state="true" save_visibility="true" - single_instance="true" + single_instance="true" width="320"> <string name="nudge_parabuild">Nudge 1</string> <string name="test_the_vlt">This string is extracted.</string> <chat_history allow_html="true" bg_readonly_color="ChatHistoryBgColor" - bg_writeable_color="ChatHistoryBgColor" - border_visible="false" + bg_writeable_color="ChatHistoryBgColor" + border_visible="false" follows="all" font="SansSerif" - left="1" + left="1" top="20" layout="topleft" - height="260" + height="260" name="chat_history" parse_highlights="true" text_color="ChatHistoryTextColor" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ec4723bd55..1ab2507232 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2929,4 +2929,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="close_on_no_ability"> You no longer have the ability to be in the chat session. </string> + <string name="unread_chat_single"> + [SOURCES] has said something new + </string>" + <string name="unread_chat_multiple"> + [SOURCES] have said something new + </string>" </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index 2be37d222a..8785dff2ae 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -11,9 +11,13 @@ top_header_pad="17" bottom_header_pad="10" max_length="2147483647" - enabled="false" track_bottom="true" name="chat_history" type="string" word_wrap="true" - font="SansSerif"/> + font="SansSerif"> + <more_chat_text + mouse_opaque="true" + word_wrap="true" + /> +</chat_history> |