diff options
77 files changed, 2690 insertions, 469 deletions
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index f5c90291b8..645bbb88ff 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -39,40 +39,24 @@ #define TIME_FAST_TIMERS 0 #if LL_WINDOWS +#include <intrin.h> +#define LL_INLINE __forceinline // shift off lower 8 bits for lower resolution but longer term timing // on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing inline U32 get_cpu_clock_count_32() { - U32 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - shr eax,8 - shl edx,24 - or eax, edx - mov dword ptr [ret_val], eax - } - return ret_val; + U64 time_stamp = __rdtsc(); + return (U32)(time_stamp >> 8); } // return full timer value, *not* shifted by 8 bits inline U64 get_cpu_clock_count_64() { - U64 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - mov eax,eax - mov edx,edx - mov dword ptr [ret_val+4], edx - mov dword ptr [ret_val], eax - } - return ret_val; + return __rdtsc(); } - +#else +#define LL_INLINE #endif // LL_WINDOWS #if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) @@ -113,10 +97,25 @@ class LLMutex; #include <queue> #include "llsd.h" - class LL_COMMON_API LLFastTimer { public: + + class NamedTimer; + + struct LL_COMMON_API FrameState + { + FrameState(NamedTimer* timerp); + + U32 mSelfTimeCounter; + U32 mCalls; + FrameState* mParent; // info for caller timer + FrameState* mLastCaller; // used to bootstrap tree construction + NamedTimer* mTimer; + U16 mActiveCount; // number of timers with this ID active on stack + bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame + }; + // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances class LL_COMMON_API NamedTimer : public LLInstanceTracker<NamedTimer> @@ -149,24 +148,10 @@ public: static NamedTimer& getRootNamedTimer(); - struct FrameState - { - FrameState(NamedTimer* timerp); - - U32 mSelfTimeCounter; - U32 mCalls; - FrameState* mParent; // info for caller timer - FrameState* mLastCaller; // used to bootstrap tree construction - NamedTimer* mTimer; - U16 mActiveCount; // number of timers with this ID active on stack - bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame - }; - S32 getFrameStateIndex() const { return mFrameStateIndex; } FrameState& getFrameState() const; - private: friend class LLFastTimer; friend class NamedTimerFactory; @@ -185,7 +170,6 @@ public: static void buildHierarchy(); static void resetFrame(); static void reset(); - // // members @@ -207,58 +191,47 @@ public: std::vector<NamedTimer*> mChildren; bool mCollapsed; // don't show children bool mNeedsSorting; // sort children whenever child added - }; // used to statically declare a new named timer class LL_COMMON_API DeclareTimer : public LLInstanceTracker<DeclareTimer> { + friend class LLFastTimer; public: DeclareTimer(const std::string& name, bool open); DeclareTimer(const std::string& name); static void updateCachedPointers(); - // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) - operator NamedTimer::FrameState&() { return *mFrameState; } private: - NamedTimer& mTimer; - NamedTimer::FrameState* mFrameState; + NamedTimer& mTimer; + FrameState* mFrameState; }; - public: - static LLMutex* sLogLock; - static std::queue<LLSD> sLogQueue; - static BOOL sLog; - static BOOL sMetricLog; - - typedef std::vector<NamedTimer::FrameState> info_list_t; - static info_list_t& getFrameStateList(); - - enum RootTimerMarker { ROOT }; - LLFastTimer(RootTimerMarker); + LLFastTimer(LLFastTimer::FrameState* state); - LLFastTimer(NamedTimer::FrameState& timer) - : mFrameState(&timer) + LL_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer) + : mFrameState(timer.mFrameState) { #if TIME_FAST_TIMERS U64 timer_start = get_cpu_clock_count_64(); #endif #if FAST_TIMER_ON - NamedTimer::FrameState* frame_state = &timer; - U32 cur_time = get_cpu_clock_count_32(); - mStartSelfTime = cur_time; - mStartTotalTime = cur_time; + LLFastTimer::FrameState* frame_state = mFrameState; + mStartTime = get_cpu_clock_count_32(); frame_state->mActiveCount++; frame_state->mCalls++; // keep current parent as long as it is active when we are frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); - mLastTimer = sCurTimer; - sCurTimer = this; + LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData; + mLastTimerData = *cur_timer_data; + cur_timer_data->mCurTimer = this; + cur_timer_data->mFrameState = frame_state; + cur_timer_data->mChildTime = 0; #endif #if TIME_FAST_TIMERS U64 timer_end = get_cpu_clock_count_64(); @@ -266,26 +239,26 @@ public: #endif } - ~LLFastTimer() + LL_INLINE ~LLFastTimer() { #if TIME_FAST_TIMERS U64 timer_start = get_cpu_clock_count_64(); #endif #if FAST_TIMER_ON - NamedTimer::FrameState* frame_state = mFrameState; - U32 cur_time = get_cpu_clock_count_32(); - frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; + LLFastTimer::FrameState* frame_state = mFrameState; + U32 total_time = get_cpu_clock_count_32() - mStartTime; + frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; frame_state->mActiveCount--; - LLFastTimer* last_timer = mLastTimer; - sCurTimer = last_timer; // store last caller to bootstrap tree creation - frame_state->mLastCaller = last_timer->mFrameState; + // do this in the destructor in case of recursion to get topmost caller + frame_state->mLastCaller = mLastTimerData.mFrameState; // we are only tracking self time, so subtract our total time delta from parents - U32 total_time = cur_time - mStartTotalTime; - last_timer->mStartSelfTime += total_time; + mLastTimerData.mChildTime += total_time; + + LLFastTimer::sCurTimerData = mLastTimerData; #endif #if TIME_FAST_TIMERS U64 timer_end = get_cpu_clock_count_64(); @@ -294,7 +267,20 @@ public: #endif } +public: + static LLMutex* sLogLock; + static std::queue<LLSD> sLogQueue; + static BOOL sLog; + static BOOL sMetricLog; + static bool sPauseHistory; + static bool sResetHistory; + static U64 sTimerCycles; + static U32 sTimerCalls; + + typedef std::vector<FrameState> info_list_t; + static info_list_t& getFrameStateList(); + // call this once a frame to reset timers static void nextFrame(); @@ -312,23 +298,26 @@ public: static void writeLog(std::ostream& os); static const NamedTimer* getTimerByName(const std::string& name); -public: - static bool sPauseHistory; - static bool sResetHistory; - static U64 sTimerCycles; - static U32 sTimerCalls; - + struct CurTimerData + { + LLFastTimer* mCurTimer; + FrameState* mFrameState; + U32 mChildTime; + }; + static CurTimerData sCurTimerData; + private: - static LLFastTimer* sCurTimer; static S32 sCurFrameIndex; static S32 sLastFrameIndex; static U64 sLastFrameTime; static info_list_t* sTimerInfos; - U32 mStartSelfTime; // start time + time of all child timers - U32 mStartTotalTime; // start time + time of all child timers - NamedTimer::FrameState* mFrameState; - LLFastTimer* mLastTimer; + U32 mStartTime; + LLFastTimer::FrameState* mFrameState; + LLFastTimer::CurTimerData mLastTimerData; + }; +typedef class LLFastTimer LLFastTimer; + #endif // LL_LLFASTTIMER_H diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 3400a72385..187a9a984e 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1919,6 +1919,16 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) { stop_glerror(); + + checkState(); + + if (!depth_enabled) + { // always disable depth writes if depth testing is disabled + // GL spec defines this as a requirement, but some implementations allow depth writes with testing disabled + // The proper way to write to depth buffer with testing disabled is to enable testing and use a depth_func of GL_ALWAYS + write_enabled = FALSE; + } + if (depth_enabled != sDepthEnabled) { gGL.flush(); @@ -1942,6 +1952,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G LLGLDepthTest::~LLGLDepthTest() { + checkState(); if (sDepthEnabled != mPrevDepthEnabled ) { gGL.flush(); @@ -1963,6 +1974,32 @@ LLGLDepthTest::~LLGLDepthTest() } } +void LLGLDepthTest::checkState() +{ + if (gDebugGL) + { + GLint func = 0; + GLboolean mask = FALSE; + + glGetIntegerv(GL_DEPTH_FUNC, &func); + glGetBooleanv(GL_DEPTH_WRITEMASK, &mask); + + if (glIsEnabled(GL_DEPTH_TEST) != sDepthEnabled || + sWriteEnabled != mask || + sDepthFunc != func) + { + if (gDebugSession) + { + gFailLog << "Unexpected depth testing state." << std::endl; + } + else + { + LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL; + } + } + } +} + LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P) { for (U32 i = 0; i < 4; i++) diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 4a51cac438..968a37cab0 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -46,6 +46,8 @@ public: ~LLGLDepthTest(); + void checkState(); + GLboolean mPrevDepthEnabled; GLenum mPrevDepthFunc; GLboolean mPrevWriteEnabled; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index fc45df8153..f97d81126e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -162,6 +162,8 @@ void LLTexUnit::enable(eTextureType type) disable(); // Force a disable of a previous texture type if it's enabled. } mCurrTexType = type; + + gGL.flush(); glEnable(sGLTextureType[type]); } } diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 82ec02d2eb..ce068618e2 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -26,6 +26,8 @@ include_directories( ) set(llui_SOURCE_FILES + llaccordionctrl.cpp + llaccordionctrltab.cpp llbutton.cpp llcheckboxctrl.cpp llclipboard.cpp @@ -111,6 +113,8 @@ set(llui_SOURCE_FILES set(llui_HEADER_FILES CMakeLists.txt + llaccordionctrl.h + llaccordionctrltab.h llbutton.h llcallbackmap.h llcheckboxctrl.h diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp new file mode 100644 index 0000000000..b5e870228a --- /dev/null +++ b/indra/llui/llaccordionctrl.cpp @@ -0,0 +1,578 @@ +/** + * @file llaccordionctrl.cpp + * @brief Accordion panel implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" + +#include "lluictrlfactory.h" // builds floaters from XML + +#include "llwindow.h" +#include "llfocusmgr.h" +#include "lllocalcliprect.h" + +#include "boost/bind.hpp" + +static const S32 DRAGGER_BAR_MARGIN = 4; +static const S32 DRAGGER_BAR_HEIGHT = 5; +static const S32 BORDER_MARGIN = 2; +static const S32 PARENT_BORDER_MARGIN = 5; + +static const S32 panel_delta = DRAGGER_BAR_MARGIN; // Distanse between two panels + +static const S32 HORIZONTAL_MULTIPLE = 8; +static const S32 VERTICAL_MULTIPLE = 16; +static const F32 MIN_AUTO_SCROLL_RATE = 120.f; +static const F32 MAX_AUTO_SCROLL_RATE = 500.f; +static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; + + +// LLAccordionCtrl =================================================================| + +static LLDefaultChildRegistry::Register<LLAccordionCtrl> t2("accordion"); + + +LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) + , mFitParent(params.fit_parent) +{ + mSingleExpansion = params.single_expansion; + if(mFitParent && !mSingleExpansion) + { + llinfos << "fit_parent works best when combined with single_expansion" << llendl; + } +} + +LLAccordionCtrl::LLAccordionCtrl() : LLPanel() +{ + mSingleExpansion = false; + mFitParent = false; + LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml"); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::draw() +{ + LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + + LLLocalClipRect clip(local_rect); + + LLPanel::draw(); +} + + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::postBuild() +{ + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + + LLScrollbar::Params sbparams; + sbparams.name("scrollable vertical"); + sbparams.rect(scroll_rect); + sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(mInnerRect.getHeight()); + sbparams.doc_pos(0); + sbparams.page_size(mInnerRect.getHeight()); + sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2)); + + mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams); + LLView::addChild( mScrollbar ); + mScrollbar->setVisible( false ); + mScrollbar->setFollowsRight(); + mScrollbar->setFollowsTop(); + mScrollbar->setFollowsBottom(); + + //if it was created from xml... + std::vector<LLUICtrl*> accordion_tabs; + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it); + if(accordion_tab == NULL) + continue; + if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end()) + { + accordion_tabs.push_back(accordion_tab); + } + } + + for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it) + addCollapsibleCtrl(*it); + + arrange (); + + if(mSingleExpansion) + { + if(!mAccordionTabs[0]->getDisplayChildren()) + mAccordionTabs[0]->setDisplayChildren(true); + for(size_t i=1;i<mAccordionTabs.size();++i) + { + if(mAccordionTabs[i]->getDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + } + + return TRUE; +} + + +//--------------------------------------------------------------------------------- +LLAccordionCtrl::~LLAccordionCtrl() +{ + mAccordionTabs.clear(); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + // adjust our rectangle + LLRect rcLocal = getRect(); + rcLocal.mRight = rcLocal.mLeft + width; + rcLocal.mTop = rcLocal.mBottom + height; + + setRect(rcLocal); + + arrange(); +} + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return LLPanel::handleRightMouseDown(x, y, mask); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta) +{ + for(size_t i = panel_num; i < mAccordionTabs.size(); i++ ) + { + ctrlShiftVertical(mAccordionTabs[i],delta); + } +} + + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) +{ + if(mSingleExpansion) + { + for(size_t i=0;i<mAccordionTabs.size();++i) + { + if(i==panel_num) + continue; + if(mAccordionTabs[i]->getDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + + } + arrange(); +} + +void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height) +{ + calcRecuiredHeight(); + if(getRecuiredHeight() > height ) + showScrollbar(width,height); + else + hideScrollbar(width,height); +} + +void LLAccordionCtrl::showScrollbar(S32 width, S32 height) +{ + bool was_visible = mScrollbar->getVisible(); + + mScrollbar->setVisible(true); + + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + + ctrlSetLeftTopAndSize(mScrollbar + ,width-scrollbar_size - PARENT_BORDER_MARGIN/2 + ,height-PARENT_BORDER_MARGIN + ,scrollbar_size + ,height-2*PARENT_BORDER_MARGIN); + + mScrollbar->setPageSize(height); + mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos()); + + if(was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); + mScrollbar->setDocPos(scroll_pos); + } +} + +void LLAccordionCtrl::hideScrollbar( S32 width, S32 height ) +{ + if(mScrollbar->getVisible() == false) + return; + mScrollbar->setVisible(false); + + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + + S32 panel_width = width - 2*BORDER_MARGIN; + + //reshape all accordeons and shift all draggers + for(size_t i=0;i<mAccordionTabs.size();++i) + { + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight()); + } + + mScrollbar->setDocPos(0); + + if(mAccordionTabs.size()>0) + { + S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel + S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; + shiftAccordionTabs(0,diff); + } +} + + +//--------------------------------------------------------------------------------- +S32 LLAccordionCtrl::calcRecuiredHeight() +{ + S32 rec_height = 0; + + std::vector<LLAccordionCtrlTab*>::iterator panel; + for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*panel); + if(accordion_tab && accordion_tab->getVisible()) + { + rec_height += accordion_tab->getRect().getHeight(); + } + } + + mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); + + return mInnerRect.getHeight(); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) +{ + if(!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize( left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); +} + +void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta) +{ + if(!panel) + return; + panel->translate(0,delta); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) +{ + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view); + if(!accordion_tab) + return; + if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end()) + addChild(accordion_tab); + mAccordionTabs.push_back(accordion_tab); + + accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) ); + +} + + +void LLAccordionCtrl::arrange() +{ + if( mAccordionTabs.size() == 0) + { + //We do not arrange if we do not have what should be arranged + return; + } + + //Calculate params + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + + + if(mAccordionTabs.size() == 1) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]); + + LLRect panel_rect = accordion_tab->getRect(); + + S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN; + + ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height); + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + return; + + } + + for(size_t i = 0; i < mAccordionTabs.size(); i++ ) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + + if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + continue; + + if(!accordion_tab->isExpanded() ) + { + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); + panel_top-=mAccordionTabs[i]->getRect().getHeight(); + } + else + { + S32 panel_height = accordion_tab->getRect().getHeight(); + + if(mFitParent) + { + // all expanded tabs will have equal height + panel_height = calcExpandedTabHeight(i, panel_top); + ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height); + + // try to make accordion tab fit accordion view height. + // Accordion View should implement getRequiredRect() and provide valid height + S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight(); + optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN; + if(optimal_height < panel_height) + { + panel_height = optimal_height; + } + + // minimum tab height is equal to header height + if(mAccordionTabs[i]->getHeaderHeight() > panel_height) + { + panel_height = mAccordionTabs[i]->getHeaderHeight(); + } + } + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top-=panel_height; + + } + } + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + + updateLayout(getRect().getWidth(),getRect().getHeight()); + +} + +//--------------------------------------------------------------------------------- + +BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +{ + if(LLPanel::handleScrollWheel(x,y,clicks)) + return TRUE; + if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + return TRUE; + return false; + +} + +BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask) +{ + if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) + return TRUE; + return LLPanel::handleKeyHere(key,mask); +} + +void LLAccordionCtrl::updateLayout (S32 width, S32 height) +{ + S32 panel_top = height - BORDER_MARGIN ; + if(mScrollbar->getVisible()) + panel_top+=mScrollbar->getDocPos(); + + S32 panel_width = width - 2*BORDER_MARGIN; + + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + if(mScrollbar->getVisible()) + panel_width-=scrollbar_size; + + //set sizes for first panels and dragbars + for(size_t i=0;i<mAccordionTabs.size();++i) + { + if(!mAccordionTabs[i]->getVisible()) + continue; + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); + panel_top-=panel_rect.getHeight(); + } +} + +void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) +{ + updateLayout(getRect().getWidth(),getRect().getHeight()); +} +void LLAccordionCtrl::onOpen (const LLSD& key) +{ + for(size_t i=0;i<mAccordionTabs.size();++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView()); + if(panel!=NULL) + { + panel->onOpen(key); + } + } +} +S32 LLAccordionCtrl::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + arrange(); + return 1; + } + else if(str_action == "select_next") + { + for(size_t i=0;i<mAccordionTabs.size();++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + if(accordion_tab->hasFocus()) + { + while(++i<mAccordionTabs.size()) + { + if(mAccordionTabs[i]->getVisible()) + break; + } + if(i<mAccordionTabs.size()) + { + accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_first")); + return 1; + } + break; + } + } + return 0; + } + else if(str_action == "select_prev") + { + for(size_t i=0;i<mAccordionTabs.size();++i) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + if(accordion_tab->hasFocus() && i>0) + { + while(i>0) + { + if(mAccordionTabs[--i]->getVisible()) + break; + } + + accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_last")); + return 1; + } + } + return 0; + } + } + else if (info.has("scrollToShowRect")) + { + LLRect screen_rc, local_rc; + screen_rc.setValue(info["scrollToShowRect"]); + screenRectToLocal(screen_rc, &local_rc); + + // Translate to parent coordinatess to check if we are in visible rectangle + local_rc.translate( getRect().mLeft, getRect().mBottom ); + + if ( !getRect().contains (local_rc) ) + { + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos( scroll_pos ); + } + return 1; + } + return LLPanel::notifyParent(info); +} +void LLAccordionCtrl::reset () +{ + if(mScrollbar) + mScrollbar->setDocPos(0); +} + +S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) +{ + if(tab_index < 0) + { + return available_height; + } + + S32 collapsed_tabs_height = 0; + S32 num_expanded = 0; + + for(size_t n = tab_index; n < mAccordionTabs.size(); ++n) + { + if(!mAccordionTabs[n]->isExpanded()) + { + collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); + } + else + { + ++num_expanded; + } + } + + if(0 == num_expanded) + { + return available_height; + } + + S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN + expanded_tab_height /= num_expanded; + return expanded_tab_height; +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h new file mode 100644 index 0000000000..4cb0f38281 --- /dev/null +++ b/indra/llui/llaccordionctrl.h @@ -0,0 +1,123 @@ +/** + * @file LLAccordionCtrl.h + * @brief Accordion Panel implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_ACCORDIONCTRL_H +#define LL_ACCORDIONCTRL_H + +#include "llpanel.h" +#include "llscrollbar.h" + +#include <vector> +#include <algorithm> +#include <string> + +class LLAccordionCtrlTab; + +class LLAccordionCtrl: public LLPanel +{ +private: + + std::vector<LLAccordionCtrlTab*> mAccordionTabs; + + void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height); + void ctrlShiftVertical(LLView* panel,S32 delta); + + void onCollapseCtrlCloseOpen(S16 panel_num); + void shiftAccordionTabs(S16 panel_num, S32 delta); + + +public: + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<bool> single_expansion, + fit_parent; /* Accordion will fit its parent size, controls that are placed into + accordion tabs are responsible for scrolling their content. + *NOTE fit_parent works best when combined with single_expansion. + Accordion view should implement getRequiredRect() and provide valid height*/ + + Params() + : single_expansion("single_expansion",false) + , fit_parent("fit_parent", false) + {}; + }; + + LLAccordionCtrl(const Params& params); + + LLAccordionCtrl(); + virtual ~LLAccordionCtrl(); + + virtual BOOL postBuild(); + + virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks ); + virtual BOOL handleKeyHere (KEY key, MASK mask); + // + + // Call reshape after changing splitter's size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + void addCollapsibleCtrl(LLView* view); + void arrange(); + + + void draw(); + + void onScrollPosChangeCallback(S32, LLScrollbar*); + + void onOpen (const LLSD& key); + S32 notifyParent(const LLSD& info); + + void reset (); + +private: + // Calc Splitter's height that is necessary to display all child content + S32 calcRecuiredHeight(); + S32 getRecuiredHeight() const { return mInnerRect.getHeight(); } + S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0); + + void updateLayout (S32 width, S32 height); + + void show_hide_scrollbar (S32 width, S32 height); + + void showScrollbar (S32 width, S32 height); + void hideScrollbar (S32 width, S32 height); + +private: + LLRect mInnerRect; + LLScrollbar* mScrollbar; + bool mSingleExpansion; + bool mFitParent; +}; + + +#endif // LL_LLSPLITTER_H diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp new file mode 100644 index 0000000000..9d6ba57c29 --- /dev/null +++ b/indra/llui/llaccordionctrltab.cpp @@ -0,0 +1,599 @@ +/** + * @file LLAccordionCtrlTab.cpp + * @brief Collapsible control implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lluictrl.h" + +#include "llaccordionctrltab.h" + +#include "lltextbox.h" + +static const std::string DD_BUTTON_NAME = "dd_button"; +static const std::string DD_TEXTBOX_NAME = "dd_textbox"; +static const std::string DD_HEADER_NAME = "dd_header"; + +static const S32 HEADER_HEIGHT = 20; +static const S32 HEADER_IMAGE_LEFT_OFFSET = 5; +static const S32 HEADER_TEXT_LEFT_OFFSET = 30; + +static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab"); + +class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl +{ +public: + friend class LLUICtrlFactory; + + struct Params : public LLInitParam::Block<Params, LLAccordionCtrlTab::Params> + { + Params(); + }; + + LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p); + + virtual ~LLAccordionCtrlTabHeader(); + + virtual void draw(); + + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + virtual BOOL postBuild(); + + void setTitle(const std::string& title); + + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); +private: + + LLTextBox* mHeaderTextbox; + + // Overlay images (arrows) + LLPointer<LLUIImage> mImageCollapsed; + LLPointer<LLUIImage> mImageExpanded; + LLPointer<LLUIImage> mImageCollapsedPressed; + LLPointer<LLUIImage> mImageExpandedPressed; + + // Background images + LLPointer<LLUIImage> mImageHeader; + LLPointer<LLUIImage> mImageHeaderOver; + LLPointer<LLUIImage> mImageHeaderPressed; + LLPointer<LLUIImage> mImageHeaderFocused; + + LLUIColor mHeaderBGColor; + + bool mNeedsHighlight; +}; + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() +{ +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader( + const LLAccordionCtrlTabHeader::Params& p) +: LLUICtrl(p) +, mHeaderBGColor(p.header_bg_color()) +,mNeedsHighlight(false), + mImageCollapsed(p.header_collapse_img), + mImageCollapsedPressed(p.header_collapse_img_pressed), + mImageExpanded(p.header_expand_img), + mImageExpandedPressed(p.header_expand_img_pressed), + mImageHeader(p.header_image), + mImageHeaderOver(p.header_image_over), + mImageHeaderPressed(p.header_image_pressed), + mImageHeaderFocused(p.header_image_focused) +{ + LLTextBox::Params textboxParams; + textboxParams.name(DD_TEXTBOX_NAME); + textboxParams.initial_value(p.title()); + textboxParams.text_color(p.header_text_color()); + textboxParams.follows.flags(FOLLOWS_NONE); + textboxParams.font( p.font() ); + textboxParams.font_shadow(LLFontGL::NO_SHADOW); + textboxParams.use_ellipses = true; + textboxParams.bg_visible = false; + textboxParams.mouse_opaque = false; + mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams); + addChild(mHeaderTextbox); +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader() +{ +} + +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() +{ + return TRUE; +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title) +{ + if(mHeaderTextbox) + mHeaderTextbox->setText(title); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() +{ + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true); + + LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent()); + bool collapsible = (parent && parent->getCollapsible()); + bool expanded = (parent && parent->getDisplayChildren()); + + // Handle overlay images, if needed + // Only show green "focus" background image if the accordion is open, + // because the user's mental model of focus is that it goes away after + // the accordion is closed. + if (getParent()->hasFocus() + && !(collapsible && !expanded)) + { + mImageHeaderFocused->draw(0,0,width,height); + } + else + { + mImageHeader->draw(0,0,width,height); + } + + if(mNeedsHighlight) + { + mImageHeaderOver->draw(0,0,width,height); + } + + + if(collapsible) + { + LLPointer<LLUIImage> overlay_image; + if(expanded) + { + overlay_image = mImageExpanded; + } + else + { + overlay_image = mImageCollapsed; + } + overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, + (height - overlay_image->getHeight()) / 2); + } + + LLUICtrl::draw(); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + S32 header_height = mHeaderTextbox->getTextPixelHeight(); + + LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2); + mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); + mHeaderTextbox->setRect(textboxRect); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseEnter(x, y, mask); + mNeedsHighlight = true; +} +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseLeave(x, y, mask); + mNeedsHighlight = false; +} +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) + { + return getParent()->handleKey(key, mask, called_from_parent); + } + return LLUICtrl::handleKey(key, mask, called_from_parent); +} + + +LLAccordionCtrlTab::Params::Params() + : title("title") + ,display_children("expanded", true) + ,header_height("header_height", HEADER_HEIGHT), + min_width("min_width", 0), + min_height("min_height", 0) + ,collapsible("collapsible", true) + ,header_bg_color("header_bg_color") + ,dropdown_bg_color("dropdown_bg_color") + ,header_visible("header_visible",true) + ,padding_left("padding_left",2) + ,padding_right("padding_right",2) + ,padding_top("padding_top",2) + ,padding_bottom("padding_bottom",2) + ,header_expand_img("header_expand_img") + ,header_expand_img_pressed("header_expand_img_pressed") + ,header_collapse_img("header_collapse_img") + ,header_collapse_img_pressed("header_collapse_img_pressed") + ,header_image("header_image") + ,header_image_over("header_image_over") + ,header_image_pressed("header_image_pressed") + ,header_image_focused("header_image_focused") + ,header_text_color("header_text_color") +{ + mouse_opaque(false); +} + +LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) + : LLUICtrl(p) + ,mDisplayChildren(p.display_children) + ,mCollapsible(p.collapsible) + ,mExpandedHeight(0) + ,mDropdownBGColor(p.dropdown_bg_color()) + ,mHeaderVisible(p.header_visible) + ,mPaddingLeft(p.padding_left) + ,mPaddingRight(p.padding_right) + ,mPaddingTop(p.padding_top) + ,mPaddingBottom(p.padding_bottom) + ,mCanOpenClose(true) +{ + mStoredOpenCloseState = false; + mWasStateStored = false; + + mDropdownBGColor = LLColor4::white; + LLAccordionCtrlTabHeader::Params headerParams; + headerParams.name(DD_HEADER_NAME); + headerParams.title(p.title); + mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams); + addChild(mHeader, 1); + + reshape(100, 200,FALSE); +} + +LLAccordionCtrlTab::~LLAccordionCtrlTab() +{ +} + + +void LLAccordionCtrlTab::setDisplayChildren(bool display) +{ + mDisplayChildren = display; + LLRect rect = getRect(); + + rect.mBottom = rect.mTop - (getDisplayChildren() ? + mExpandedHeight : HEADER_HEIGHT); + setRect(rect); + + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + + child->setVisible(getDisplayChildren()); + } +} + +void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + LLRect headerRect; + + LLUICtrl::reshape(width, height, TRUE); + + headerRect.setLeftTopAndSize( + 0,height,width,HEADER_HEIGHT); + mHeader->setRect(headerRect); + mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + if(!child->getVisible()) + continue; + + LLRect childRect = child->getRect(); + S32 childWidth = width - getPaddingLeft() - getPaddingRight(); + S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom(); + + child->reshape(childWidth,childHeight); + + childRect.setLeftTopAndSize( + getPaddingLeft(), + childHeight + getPaddingBottom(), + childWidth, + childHeight); + + child->setRect(childRect); + + break;//suppose that there is only one panel + } + +} + +void LLAccordionCtrlTab::changeOpenClose(bool is_open) +{ + if(is_open) + mExpandedHeight = getRect().getHeight(); + + setDisplayChildren(!is_open); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + if (mCommitSignal) + { + (*mCommitSignal)(this, getDisplayChildren()); + } +} + +BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if(mCollapsible && mHeaderVisible && mCanOpenClose) + { + if(y >= (getRect().getHeight() - HEADER_HEIGHT) ) + { + LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); + header->setFocus(true); + changeOpenClose(getDisplayChildren()); + + //reset stored state + mWasStateStored = false; + return TRUE; + } + } + return LLUICtrl::handleMouseDown(x,y,mask); +} + +BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask) +{ + return LLUICtrl::handleMouseUp(x,y,mask); +} + +boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb) +{ + return setCommitCallback(cb); +} + +bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) +{ + if(DD_HEADER_NAME != child->getName()) + { + reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); + mExpandedHeight = getRect().getHeight(); + } + + bool res = LLUICtrl::addChild(child, tab_group); + + if(DD_HEADER_NAME != child->getName()) + { + if(!mCollapsible) + setDisplayChildren(true); + else + setDisplayChildren(getDisplayChildren()); + } + + return res; +} + +void LLAccordionCtrlTab::setAccordionView(LLView* panel) +{ + addChild(panel,0); +} + + +LLView* LLAccordionCtrlTab::getAccordionView() +{ + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + if(!child->getVisible()) + continue; + return child; + } + return NULL; +} + + +S32 LLAccordionCtrlTab::getHeaderHeight() +{ + return mHeaderVisible?HEADER_HEIGHT:0; +} + +void LLAccordionCtrlTab::setHeaderVisible(bool value) +{ + if(mHeaderVisible == value) + return; + mHeaderVisible = value; + if(mHeader) + mHeader->setVisible(value); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); +}; + +//vurtual +BOOL LLAccordionCtrlTab::postBuild() +{ + mHeader->setVisible(mHeaderVisible); + return LLUICtrl::postBuild(); +} +bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "store_state") + { + storeOpenCloseState(); + return true; + } + if(str_action == "restore_state") + { + restoreOpenCloseState(); + return true; + } + } + return LLUICtrl::notifyChildren(info); +} + +S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + S32 height = info["height"]; + height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); + + mExpandedHeight = height; + + if(isExpanded()) + { + LLRect panel_rect = getRect(); + panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); + reshape(getRect().getWidth(),height); + setRect(panel_rect); + } + + //LLAccordionCtrl should rearrange accodion tab if one of accordion change its size + getParent()->notifyParent(info); + return 1; + } + else if(str_action == "select_prev") + { + showAndFocusHeader(); + return 1; + } + } + return LLUICtrl::notifyParent(info); +} + +S32 LLAccordionCtrlTab::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + showAndFocusHeader(); + return 1; + } + else if( str_action == "select_last" ) + { + if(getDisplayChildren() == false) + { + showAndFocusHeader(); + } + else + { + LLView* view = getAccordionView(); + if(view) + view->notify(LLSD().with("action","select_last")); + } + } + } + return 0; +} + +BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); + if( !header->hasFocus() ) + return LLUICtrl::handleKey(key, mask, called_from_parent); + + if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == false) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == true) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + + if ( key == KEY_DOWN && mask == MASK_NONE) + { + //if collapsed go to the next accordion + if(getDisplayChildren() == false) + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_next")); + else + { + getAccordionView()->notify(LLSD().with("action","select_first")); + } + return TRUE; + } + + if ( key == KEY_UP && mask == MASK_NONE) + { + //go to the previous accordion + + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_prev")); + return TRUE; + } + + return LLUICtrl::handleKey(key, mask, called_from_parent); +} + +void LLAccordionCtrlTab::showAndFocusHeader() +{ + LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); + header->setFocus(true); + + LLRect screen_rc; + LLRect selected_rc = header->getRect(); + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); + +} +void LLAccordionCtrlTab::storeOpenCloseState() +{ + if(mWasStateStored) + return; + mStoredOpenCloseState = getDisplayChildren(); + mWasStateStored = true; +} +void LLAccordionCtrlTab::restoreOpenCloseState() +{ + if(!mWasStateStored) + return; + if(getDisplayChildren() != mStoredOpenCloseState) + { + changeOpenClose(getDisplayChildren()); + } + mWasStateStored = false; +} diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h new file mode 100644 index 0000000000..b200d43438 --- /dev/null +++ b/indra/llui/llaccordionctrltab.h @@ -0,0 +1,191 @@ +/** + * @file LLAccordionCtrlTab.h + * @brief Collapsible box control implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_ACCORDIONCTRLTAB_H_ +#define LL_ACCORDIONCTRLTAB_H_ + +#include <string> +#include "llrect.h" + +class LLUICtrl; +class LLUICtrlFactory; +class LLUIImage; +class LLButton; +class LLTextBox; + + + +// LLAccordionCtrlTab is a container for other controls. +// It has a Header, by clicking on which hosted controls are shown or hidden. +// When hosted controls are show - LLAccordionCtrlTab is expanded. +// When hosted controls are hidden - LLAccordionCtrlTab is collapsed. + +class LLAccordionCtrlTab : public LLUICtrl +{ +// Interface +public: + + struct Params + : public LLInitParam::Block<Params, LLUICtrl::Params> + { + Optional<bool> display_children, //expanded or collapsed after initialization + collapsible; + + Optional<std::string> title; + + Optional<S32> header_height, + min_width, + min_height; + + // Overlay images (arrows on the left) + Mandatory<LLUIImage*> header_expand_img, + header_expand_img_pressed, + header_collapse_img, + header_collapse_img_pressed; + + // Background images for the accordion tabs + Mandatory<LLUIImage*> header_image, + header_image_over, + header_image_pressed, + header_image_focused; + + Optional<LLUIColor> header_bg_color, + header_text_color, + dropdown_bg_color; + + Optional<bool> header_visible; + + Optional<S32> padding_left; + Optional<S32> padding_right; + Optional<S32> padding_top; + Optional<S32> padding_bottom; + + Params(); + }; + + typedef LLDefaultChildRegistry child_registry_t; + + virtual ~LLAccordionCtrlTab(); + + // Registers callback for expand/collapse events. + boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb); + + // Changes expand/collapse state + virtual void setDisplayChildren(bool display); + + // Returns expand/collapse state + virtual bool getDisplayChildren() const {return mDisplayChildren;}; + + //set LLAccordionCtrlTab panel + void setAccordionView(LLView* panel); + LLView* getAccordionView(); + + bool getCollapsible() {return mCollapsible;}; + + void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; + void changeOpenClose(bool is_open); + + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; + + virtual BOOL postBuild(); + + S32 notifyParent(const LLSD& info); + S32 notify(const LLSD& info); + bool notifyChildren(const LLSD& info); + + void storeOpenCloseState (); + void restoreOpenCloseState (); + +protected: + LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); + friend class LLUICtrlFactory; + +// Overrides +public: + + // Call reshape after changing size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + // Changes expand/collapse state and triggers expand/collapse callbacks + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + virtual bool addChild(LLView* child, S32 tab_group); + + bool isExpanded() { return mDisplayChildren; } + + S32 getHeaderHeight(); + + // Min size functions + + void setHeaderVisible(bool value); + + bool getHeaderVisible() { return mHeaderVisible;} + + S32 mExpandedHeight; // Height of expanded ctrl. + // Used to restore height after expand. + + S32 getPaddingLeft() const { return mPaddingLeft;} + S32 getPaddingRight() const { return mPaddingRight;} + S32 getPaddingTop() const { return mPaddingTop;} + S32 getPaddingBottom() const { return mPaddingBottom;} + + void showAndFocusHeader(); + +private: + + + + class LLAccordionCtrlTabHeader; + LLAccordionCtrlTabHeader* mHeader; //Header + + bool mDisplayChildren; //Expanded/collapsed + bool mCollapsible; + bool mHeaderVisible; + + bool mCanOpenClose; + + S32 mPaddingLeft; + S32 mPaddingRight; + S32 mPaddingTop; + S32 mPaddingBottom; + + bool mStoredOpenCloseState; + bool mWasStateStored; + + + LLUIColor mDropdownBGColor; +}; + +#endif diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 845203b420..a35d279500 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -878,9 +878,11 @@ void LLFloater::setSnappedTo(const LLView* snap_view) else { //RN: assume it's a floater as it must be a sibling to our parent floater - LLFloater* floaterp = (LLFloater*)snap_view; - - setSnapTarget(floaterp->getHandle()); + const LLFloater* floaterp = dynamic_cast<const LLFloater*>(snap_view); + if (floaterp) + { + setSnapTarget(floaterp->getHandle()); + } } } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 527c0a1b87..bd67949c2a 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -46,6 +46,7 @@ #include "llmenugl.h" +#include "llgl.h" #include "llmath.h" #include "llrender.h" #include "llfocusmgr.h" @@ -477,6 +478,7 @@ void LLMenuItemGL::draw( void ) if (dynamic_cast<LLMenuItemCallGL*>(this)) debug_count++; gGL.color4fv( mHighlightBackground.get().mV ); + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index db32882438..143f19eea6 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -43,6 +43,7 @@ #include "llerror.h" #include "lltimer.h" +#include "llaccordionctrltab.h" #include "llbutton.h" #include "llmenugl.h" //#include "llstatusbar.h" @@ -851,14 +852,26 @@ static LLPanel *childGetVisibleTabWithHelp(LLView *parent) // look through immediate children first for an active tab with help for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) { + LLPanel *curTabPanel = NULL; + + // do we have a tab container? LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child); if (tab && tab->getVisible()) { - LLPanel *curTabPanel = tab->getCurrentPanel(); - if (curTabPanel && !curTabPanel->getHelpTopic().empty()) - { - return curTabPanel; - } + curTabPanel = tab->getCurrentPanel(); + } + + // do we have an accordion tab? + LLAccordionCtrlTab* accordion = dynamic_cast<LLAccordionCtrlTab *>(child); + if (accordion && accordion->getDisplayChildren()) + { + curTabPanel = dynamic_cast<LLPanel *>(accordion->getAccordionView()); + } + + // if we found a valid tab, does it have a help topic? + if (curTabPanel && !curTabPanel->getHelpTopic().empty()) + { + return curTabPanel; } } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index e8fc9475a5..f2c3879a6c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -308,7 +308,8 @@ LLTextEditor::~LLTextEditor() // Scrollbar is deleted by LLView std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); - delete mContextMenu; + // context menu is owned by menu holder, not us + //delete mContextMenu; } //////////////////////////////////////////////////////////// diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index f7528bc62a..1b6dd1b264 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -101,7 +101,7 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url) { start++; } - return url.substr(start, url.size()-start-1); + return unescapeUrl(url.substr(start, url.size()-start-1)); } std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string) diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 128cd134c1..38cf7124ce 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -545,4 +545,50 @@ namespace tut "XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY", "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]"); } + + template<> template<> + void object::test<11>() + { + // + // test LLUrlEntryHTTPNoProtocol - general URLs without a protocol + // + LLUrlEntryHTTPNoProtocol url; + boost::regex r = url.getPattern(); + + testRegex("naked .com URL", r, + "see google.com", + "google.com"); + + testRegex("naked .org URL", r, + "see en.wikipedia.org for details", + "en.wikipedia.org"); + + testRegex("naked .net URL", r, + "example.net", + "example.net"); + + testRegex("naked .edu URL (2 instances)", r, + "MIT web site is at web.mit.edu and also www.mit.edu", + "web.mit.edu"); + + testRegex("invalid .com URL [1]", r, + "..com", + ""); + + testRegex("invalid .com URL [2]", r, + "you.come", + ""); + + testRegex("invalid .com URL [3]", r, + "recommended", + ""); + + testRegex("invalid .edu URL", r, + "hi there scheduled maitenance has begun", + ""); + + testRegex("invalid .net URL", r, + "foo.netty", + ""); + } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8918fc3018..39594bcf3e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -63,8 +63,6 @@ include_directories( ) set(viewer_SOURCE_FILES - llaccordionctrl.cpp - llaccordionctrltab.cpp llagent.cpp llagentaccess.cpp llagentdata.cpp @@ -214,7 +212,6 @@ set(viewer_SOURCE_FILES llfloaterurldisplay.cpp llfloaterurlentry.cpp llfloatervoicedevicesettings.cpp - llfloatervolumepulldown.cpp llfloaterwater.cpp llfloaterwhitelistentry.cpp llfloaterwindlight.cpp @@ -349,6 +346,7 @@ set(viewer_SOURCE_FILES llpanelshower.cpp llpanelteleporthistory.cpp llpanelvolume.cpp + llpanelvolumepulldown.cpp llparcelselection.cpp llparticipantlist.cpp llpatchvertexarray.cpp @@ -569,8 +567,6 @@ endif (LINUX) set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake - llaccordionctrl.h - llaccordionctrltab.h llagent.h llagentaccess.h llagentdata.h @@ -852,6 +848,7 @@ set(viewer_HEADER_FILES llpanelshower.h llpanelteleporthistory.h llpanelvolume.h + llpanelvolumepulldown.h llparcelselection.h llparticipantlist.h llpatchvertexarray.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 382793a497..e57b77e2df 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1141,7 +1141,18 @@ <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>S32</string> + <key>Value</key> + <integer>5</integer> + </map> + <key>CallFloaterMaxItems</key> + <map> + <key>Comment</key> + <string>Max number of visible participants in voice controls window</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> <key>Value</key> <integer>1</integer> </map> diff --git a/indra/newview/installers/darwin/dmg-cleanup.applescript b/indra/newview/installers/darwin/dmg-cleanup.applescript index f3d39aec21..f3d39aec21 100644..100755 --- a/indra/newview/installers/darwin/dmg-cleanup.applescript +++ b/indra/newview/installers/darwin/dmg-cleanup.applescript diff --git a/indra/newview/installers/darwin/fix_application_icon_position.sh b/indra/newview/installers/darwin/fix_application_icon_position.sh new file mode 100755 index 0000000000..a0b72a89f2 --- /dev/null +++ b/indra/newview/installers/darwin/fix_application_icon_position.sh @@ -0,0 +1,14 @@ +# just run this script each time after you change the installer's name to fix the icon misalignment +#!/bin/bash +cp -r ./../../../build-darwin-i386/newview/*.dmg ~/Desktop/TempBuild.dmg +hdid ~/Desktop/TempBuild.dmg +open -a finder /Volumes/Second\ Life\ Installer +osascript dmg-cleanup.applescript +cp /Volumes/Second\ Life\ Installer/.DS_Store ~/Desktop/_DS_Store +chflags nohidden ~/Desktop/_DS_Store +cp ~/Desktop/_DS_Store ./firstlook-dmg/_DS_Store +cp ~/Desktop/_DS_Store ./publicnightly-dmg/_DS_Store +cp ~/Desktop/_DS_Store ./release-dmg/_DS_Store +cp ~/Desktop/_DS_Store ./releasecandidate-dmg/_DS_Store +umount /Volumes/Second\ Life\ Installer/ +rm ~/Desktop/_DS_Store ~/Desktop/TempBuild.dmg diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index f49f862045..10a2dd132a 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -95,19 +95,38 @@ public: enum ELibraryOutfitFetchStep { LOFS_FOLDER = 0, LOFS_OUTFITS, + LOFS_LIBRARY, + LOFS_IMPORTED, LOFS_CONTENTS }; - LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} + LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) + { + mMyOutfitsID = LLUUID::null; + mClothingID = LLUUID::null; + mLibraryClothingID = LLUUID::null; + mImportedClothingID = LLUUID::null; + mImportedClothingName = "Imported Library Clothing"; + } ~LLLibraryOutfitsFetch() {} - virtual void done(); + virtual void done(); void doneIdle(); + LLUUID mMyOutfitsID; + void importedFolderFetch(); protected: void folderDone(void); void outfitsDone(void); + void libraryDone(void); + void importedFolderDone(void); void contentsDone(void); enum ELibraryOutfitFetchStep mCurrFetchStep; - std::vector< std::pair< LLUUID, std::string > > mOutfits; + typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t; + cloth_folder_vec_t mLibraryClothingFolders; + cloth_folder_vec_t mImportedClothingFolders; bool mOutfitsPopulated; + LLUUID mClothingID; + LLUUID mLibraryClothingID; + LLUUID mImportedClothingID; + std::string mImportedClothingName; }; LLAgentWearables gAgentWearables; @@ -2126,11 +2145,15 @@ void LLAgentWearables::populateMyOutfitsFolder(void) // Get the complete information on the items in the inventory and // setup an observer that will wait for that to happen. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + outfits->mMyOutfitsID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - folders.push_back(my_outfits_id); + folders.push_back(outfits->mMyOutfitsID); gInventory.addObserver(outfits); outfits->fetchDescendents(folders); + if (outfits->isEverythingComplete()) + { + outfits->done(); + } } void LLLibraryOutfitsFetch::done() @@ -2144,13 +2167,24 @@ void LLLibraryOutfitsFetch::done() void LLLibraryOutfitsFetch::doneIdle() { gInventory.addObserver(this); // Add this back in since it was taken out during ::done() + switch (mCurrFetchStep) { case LOFS_FOLDER: folderDone(); + mCurrFetchStep = LOFS_OUTFITS; break; case LOFS_OUTFITS: outfitsDone(); + mCurrFetchStep = LOFS_LIBRARY; + break; + case LOFS_LIBRARY: + libraryDone(); + mCurrFetchStep = LOFS_IMPORTED; + break; + case LOFS_IMPORTED: + importedFolderDone(); + mCurrFetchStep = LOFS_CONTENTS; break; case LOFS_CONTENTS: contentsDone(); @@ -2172,67 +2206,217 @@ void LLLibraryOutfitsFetch::doneIdle() void LLLibraryOutfitsFetch::folderDone(void) { - // Early out if we already have items in My Outfits. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); + + // Early out if we already have items in My Outfits. if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; return; } - // Get the UUID of the library's clothing folder - const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); + mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); mCompleteFolders.clear(); // Get the complete information on the items in the inventory. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - folders.push_back(library_clothing_id); - mCurrFetchStep = LOFS_OUTFITS; + folders.push_back(mClothingID); + folders.push_back(mLibraryClothingID); fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } void LLLibraryOutfitsFetch::outfitsDone(void) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; + // Collect the contents of the Library's Clothing folder + gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + llassert(cat_array.count() > 0); for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); iter != cat_array.end(); ++iter) { const LLViewerInventoryCategory *cat = iter->get(); + + // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits. if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") { + // Get the name of every outfit in the library folders.push_back(cat->getUUID()); - mOutfits.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + } + } + + // Collect the contents of your Inventory Clothing folder + cat_array.clear(); + wearable_array.clear(); + gInventory.collectDescendents(mClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + // Check if you already have an "Imported Library Clothing" folder + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + if (cat->getName() == mImportedClothingName) + { + mImportedClothingID = cat->getUUID(); } } + mCompleteFolders.clear(); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +class LLLibraryOutfitsCopyDone: public LLInventoryCallback +{ +public: + LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): + mFireCount(0), mLibraryOutfitsFetcher(fetcher) + { + } + + virtual ~LLLibraryOutfitsCopyDone() + { + if (mLibraryOutfitsFetcher) + { + gInventory.addObserver(mLibraryOutfitsFetcher); + mLibraryOutfitsFetcher->done(); + } + } + + /* virtual */ void fire(const LLUUID& inv_item) + { + mFireCount++; + } +private: + U32 mFireCount; + LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; +}; - mCurrFetchStep = LOFS_CONTENTS; +void LLLibraryOutfitsFetch::libraryDone(void) +{ + // Copy the clothing folders from the library into the imported clothing folder if necessary. + if (mImportedClothingID == LLUUID::null) + { + gInventory.removeObserver(this); + LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); + mImportedClothingID = gInventory.createNewCategory(mClothingID, + LLFolderType::FT_NONE, + mImportedClothingName); + + for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); + iter != mLibraryClothingFolders.end(); + ++iter) + { + LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID, + LLFolderType::FT_NONE, + iter->second); + LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter); + } + } + else + { + // Skip straight to fetching the contents of the imported folder + importedFolderFetch(); + } +} + +void LLLibraryOutfitsFetch::importedFolderFetch(void) +{ + // Fetch the contents of the Imported Clothing Folder + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(mImportedClothingID); + + mCompleteFolders.clear(); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } -void LLLibraryOutfitsFetch::contentsDone(void) +void LLLibraryOutfitsFetch::importedFolderDone(void) { - for(S32 i = 0; i < (S32)mOutfits.size(); ++i) + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + + // Collect the contents of the Imported Clothing folder + gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + + // Get the name of every imported outfit + folders.push_back(cat->getUUID()); + mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + } + + mCompleteFolders.clear(); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +void LLLibraryOutfitsFetch::contentsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + + for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + folder_iter != mImportedClothingFolders.end(); + ++folder_iter) { // First, make a folder in the My Outfits directory. - const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLUUID folder_id = gInventory.createNewCategory(parent_id, - LLFolderType::FT_OUTFIT, - mOutfits[i].second); - LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second); + + cat_array.clear(); + wearable_array.clear(); + // Collect the contents of each imported clothing folder, so we can create new outfit links for it + gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); + wearable_iter != wearable_array.end(); + ++wearable_iter) + { + const LLViewerInventoryItem *item = wearable_iter->get(); + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + new_outfit_folder_id, + item->getName(), + LLAssetType::AT_LINK, + NULL); + } } + mOutfitsPopulated = true; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e0356bc091..fb1bded795 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -313,6 +313,7 @@ void init_default_trans_args() { default_trans_args.insert("SECOND_LIFE"); // World default_trans_args.insert("APP_NAME"); + default_trans_args.insert("CAPITALIZED_APP_NAME"); default_trans_args.insert("SECOND_LIFE_GRID"); default_trans_args.insert("SUPPORT_SITE"); } diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 1468f6d584..c0efb85b51 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -51,6 +51,7 @@ #include "lltransientfloatermgr.h" #include "llviewerwindow.h" #include "llvoicechannel.h" +#include "lllayoutstack.h" static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids); @@ -314,7 +315,7 @@ void LLCallFloater::updateSession() //hide "Leave Call" button for nearby chat bool is_local_chat = mVoiceType == VC_LOCAL_CHAT; - childSetVisible("leave_call_btn", !is_local_chat); + childSetVisible("leave_call_btn_panel", !is_local_chat); refreshParticipantList(); updateAgentModeratorState(); @@ -818,8 +819,8 @@ void reshape_floater(LLCallFloater* floater, S32 delta_height) } } - floater->reshape(floater_rect.getWidth(), floater_rect.getHeight()); - floater->setRect(floater_rect); + floater->setShape(floater_rect); + floater->getChild<LLLayoutStack>("my_call_stack")->updateLayout(FALSE); } void LLCallFloater::reshapeToFitContent() @@ -864,9 +865,8 @@ S32 LLCallFloater::getParticipantItemHeight() S32 LLCallFloater::getMaxVisibleItems() { - S32 value = 5; // default value, in case convertToS32() fails. - LLStringUtil::convertToS32(getString("max_visible_items"), value); - return value; + static LLCachedControl<S32> max_visible_items(*LLUI::sSettingGroups["config"],"CallFloaterMaxItems"); + return max_visible_items; } //EOF diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index dac3280575..cda3e3a419 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -576,10 +576,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ style_params.font.style = "ITALIC"; if (chat.mFromName.size() > 0) - mEditor->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. - mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); + mEditor->appendText(chat.mText.substr(3) + NEW_LINE, FALSE, style_params); } else { diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 60a37ac4af..9ce3f29853 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -170,10 +170,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification) std::string str_sender; - if(gAgentID != mFromID) - str_sender = fromName; - else - str_sender = LLTrans::getString("You"); + str_sender = fromName; str_sender+=" "; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 598a13de15..42c961a956 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -276,6 +276,7 @@ void LLFloaterLand::refresh() mPanelAudio->refresh(); mPanelMedia->refresh(); mPanelAccess->refresh(); + mPanelCovenant->refresh(); } @@ -2795,12 +2796,6 @@ LLPanelLandCovenant::~LLPanelLandCovenant() { } -BOOL LLPanelLandCovenant::postBuild() -{ - refresh(); - return TRUE; -} - // virtual void LLPanelLandCovenant::refresh() { diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index d7d02ba1a3..a4785e8f5b 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -391,7 +391,6 @@ class LLPanelLandCovenant public: LLPanelLandCovenant(LLSafeHandle<LLParcelSelection>& parcelp); virtual ~LLPanelLandCovenant(); - virtual BOOL postBuild(); void refresh(); static void updateCovenantText(const std::string& string); static void updateEstateName(const std::string& name); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index d0716f67b8..9af37e8174 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -602,8 +602,8 @@ void LLFloaterPreference::onBtnOK() apply(); closeFloater(false); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); LLUIColorTable::instance().saveUserSettings(); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults gCrashSettings.saveToFile(crash_settings_filename, FALSE); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index c4b87c1b2d..0402ba20e2 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -406,6 +406,11 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region) { + if (!region) + { + return; + } + // call refresh from region on all panels std::for_each( mInfoPanels.begin(), diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 3042fbc6ec..0964ad7f91 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -64,6 +64,8 @@ // summary which only shows available & correct information #define USE_SIMPLE_SUMMARY +const S32 SIZE_OF_ONE_KB = 1024; + LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed) : LLFloater(seed) { @@ -130,7 +132,6 @@ void LLFloaterScriptLimits::refresh() } } - ///---------------------------------------------------------------------------- // Base class for panels ///---------------------------------------------------------------------------- @@ -331,6 +332,57 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; } +// callback from the name cache with an owner name to add to the list +void LLPanelScriptLimitsRegionMemory::onNameCache( + const LLUUID& id, + const std::string& first_name, + const std::string& last_name) +{ + std::string name = first_name + " " + last_name; + + LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + std::vector<LLSD>::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + + // fill in the url's tab if needed, all urls must have memory so we can do it all here + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + + LLScrollListCtrl *list = panel->getChild<LLScrollListCtrl>("scripts_list"); + std::vector<LLSD>::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + } +} + void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) { LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); @@ -345,22 +397,40 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; + std::vector<LLUUID> names_requested; + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); - + LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); for(S32 j = 0; j < number_objects; j++) { - S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024; + S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; total_size += size; std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + + BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf); + if(!name_is_cached) + { + if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end()) + { + names_requested.push_back(owner_id); + gCacheName->get(owner_id, TRUE, + boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache, + this, _1, _2, _3)); + } + } LLSD element; element["id"] = task_id; + element["owner_id"] = owner_id; element["columns"][0]["column"] = "size"; element["columns"][0]["value"] = llformat("%d", size); element["columns"][0]["font"] = "SANSSERIF"; @@ -368,18 +438,18 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; - list->addElement(element); - mObjectListIDs.push_back(task_id); + list->addElement(element, ADD_SORTED); + mObjectListItems.push_back(element); total_objects++; } } - + mParcelMemoryUsed =total_size; mGotParcelMemoryUsed = TRUE; populateParcelMemoryText(); @@ -556,7 +626,7 @@ void LLPanelScriptLimitsRegionMemory::clearList() childSetValue("memory_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -728,7 +798,7 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; - + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); @@ -744,6 +814,10 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field LLSD element; @@ -755,14 +829,14 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; list->addElement(element); - mObjectListIDs.push_back(task_id); + mObjectListItems.push_back(element); total_objects++; } } @@ -868,7 +942,7 @@ void LLPanelScriptLimitsRegionURLs::clearList() childSetValue("urls_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -982,7 +1056,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) S32 size = 0; if(content["attachments"][i]["objects"][j]["resources"].has("memory")) { - size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger(); + size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; } S32 urls = 0; if(content["attachments"][i]["objects"][j]["resources"].has("urls")) @@ -1059,3 +1133,4 @@ void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata) return; } } + diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index 88239136e3..7e2b536eb6 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -54,12 +54,12 @@ public: // from LLPanel virtual void refresh(); - + private: - + LLFloaterScriptLimits(const LLSD& seed); ~LLFloaterScriptLimits(); - + protected: LLTabContainer* mTab; @@ -167,13 +167,17 @@ public: private: + void onNameCache( const LLUUID& id, + const std::string& first_name, + const std::string& last_name); + LLUUID mParcelId; BOOL mGotParcelMemoryUsed; BOOL mGotParcelMemoryMax; S32 mParcelMemoryMax; S32 mParcelMemoryUsed; - std::vector<LLUUID> mObjectListIDs; + std::vector<LLSD> mObjectListItems; protected: @@ -218,7 +222,7 @@ private: S32 mParcelURLsMax; S32 mParcelURLsUsed; - std::vector<LLUUID> mObjectListIDs; + std::vector<LLSD> mObjectListItems; protected: diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index c6d9fee630..a7401fdb6f 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -32,6 +32,9 @@ */ #include "llviewerprecompiledheaders.h" + +#include "llcommandhandler.h" +#include "llfloaterreg.h" #include "llfloatersearch.h" #include "llmediactrl.h" #include "lllogininstance.h" @@ -41,6 +44,42 @@ #include "llviewercontrol.h" #include "llweb.h" +// support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps +class LLSearchHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + const size_t parts = tokens.size(); + + // get the (optional) category for the search + std::string category; + if (parts > 0) + { + category = tokens[0].asString(); + } + + // get the (optional) search string + std::string search_text; + if (parts > 1) + { + search_text = tokens[1].asString(); + } + + // create the LLSD arguments for the search floater + LLSD args; + args["category"] = category; + args["id"] = LLURI::unescape(search_text); + + // open the search floater and perform the requested search + LLFloaterReg::showInstance("search", args); + return true; + } +}; +LLSearchHandler gSearchHandler; + LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), LLViewerMediaObserver(), diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1ab111a41d..9aed403991 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -822,10 +822,11 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) +BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) const { - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) { selection.insert((*item_it)->getListener()->getUUID()); } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 2598af4df4..89e1865e35 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -162,7 +162,7 @@ public: virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); - virtual BOOL getSelectionList(std::set<LLUUID> &selection); + virtual BOOL getSelectionList(std::set<LLUUID> &selection) const; // make sure if ancestor is selected, descendents are not void sanitizeSelection(); diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 14fac5bdf9..be8e73a5a9 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -235,7 +235,7 @@ public: virtual void recursiveDeselect(BOOL deselect_self); // gets multiple-element selection - virtual BOOL getSelectionList(std::set<LLUUID> &selection){return TRUE;} + virtual BOOL getSelectionList(std::set<LLUUID> &selection) const {return TRUE;} // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); @@ -302,7 +302,7 @@ public: // Show children (unfortunate that this is called "open") virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() { return FALSE; } + virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); @@ -497,7 +497,7 @@ public: virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); // Get the current state of the folder. - virtual BOOL isOpen() { return mIsOpen; } + virtual BOOL isOpen() const { return mIsOpen; } // special case if an object is dropped on the child. BOOL handleDragAndDropFromChild(MASK mask, diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index fdc5d14d97..b05568f353 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -595,7 +595,7 @@ void LLIMFloater::updateMessages() std::string time = msg["time"].asString(); LLUUID from_id = msg["from_id"].asUUID(); - std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You"); + std::string from = msg["from"].asString(); std::string message = msg["message"].asString(); LLChat chat; diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 5f9d479b3e..8f4fba244d 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -278,7 +278,7 @@ void LLInspectAvatar::onOpen(const LLSD& data) getChild<LLUICtrl>("gear_self_btn")->setVisible(self); getChild<LLUICtrl>("gear_btn")->setVisible(!self); - + // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned // See LLToolTipMgr::createToolTip @@ -544,6 +544,7 @@ void LLInspectAvatar::updateVolumeSlider() LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); volume_slider->setEnabled( !is_muted ); + const F32 DEFAULT_VOLUME = 0.5f; F32 volume; if (is_muted) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2a395d79dc..20d7f5214b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2074,7 +2074,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model { if ("open" == action) { - openItem(); + LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(folder->getItemByID(mUUID)); + if (f) + { + f->setOpen(TRUE); + } + return; } else if ("paste" == action) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 498a29728c..9141d50829 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -98,10 +98,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor")); - setBackgroundVisible(TRUE); - setBackgroundOpaque(TRUE); - if (mStartFolderString != "") { mBuildDefaultHierarchy = false; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index fc9654e9ad..92f19c9232 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -59,9 +59,6 @@ const static std::string NEW_LINE_SPACE_PREFIX("\n "); const static std::string TWO_SPACES(" "); const static std::string MULTI_LINE_PREFIX(" "); -//viewer 1.23 may have used "You" for Agent's entries -const static std::string YOU("You"); - /** * Chat log lines - timestamp and name are optional but message text is mandatory. * diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e7043b2d00..fc0e51b76d 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -178,7 +178,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive) if (!chat.mMuted) { - tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You"); + tmp_chat.mFromName = chat.mFromName; if (chat.mChatStyle == CHAT_STYLE_IRC) { diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index f3d6dbbb46..fb898f7cdf 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -594,8 +594,8 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g if (it != mGroups.begin()) groups += ", "; - - std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + it->first + "]"; + std::string group_name = LLURI::escape(it->first); + std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]"; groups += group_url; } diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index a1c12412b5..550fee71bf 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -181,6 +181,10 @@ void LLPanelOutfitsInventory::onNew() { const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); + if (mAppearanceTabs) + { + mAppearanceTabs->selectTabByName("outfitslist_tab"); + } } void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) @@ -412,8 +416,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return (getCorrectListenerForAction() != NULL) && hasItemsSelected(); } - if (command_name == "wear" || - command_name == "make_outfit") + if (command_name == "wear") { const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab"); if (!is_my_outfits) @@ -421,6 +424,10 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return FALSE; } } + if (command_name == "make_outfit") + { + return TRUE; + } if (command_name == "edit" || command_name == "add" diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp new file mode 100644 index 0000000000..74e37efe4e --- /dev/null +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -0,0 +1,154 @@ +/** + * @file llpanelvolumepulldown.cpp + * @author Tofu Linden + * @brief A floater showing the master volume pull-down + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelvolumepulldown.h" + +// Viewer libs +#include "llviewercontrol.h" +#include "llstatusbar.h" + +// Linden libs +#include "llbutton.h" +#include "lltabcontainer.h" +#include "llfloaterreg.h" +#include "llfloaterpreference.h" +#include "llslider.h" + +/* static */ const F32 LLPanelVolumePulldown::sAutoCloseFadeStartTimeSec = 4.0f; +/* static */ const F32 LLPanelVolumePulldown::sAutoCloseTotalTimeSec = 5.0f; + +///---------------------------------------------------------------------------- +/// Class LLPanelVolumePulldown +///---------------------------------------------------------------------------- + +// Default constructor +LLPanelVolumePulldown::LLPanelVolumePulldown() +{ + mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); + mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2)); + LLUICtrlFactory::instance().buildPanel(this, "panel_volume_pulldown.xml"); +} + +BOOL LLPanelVolumePulldown::postBuild() +{ + // set the initial volume-slider's position to reflect reality + LLSlider* volslider = getChild<LLSlider>( "mastervolume" ); + volslider->setValue(gSavedSettings.getF32("AudioLevelMaster")); + + return LLPanel::postBuild(); +} + +/*virtual*/ +void LLPanelVolumePulldown::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mHoverTimer.stop(); + LLPanel::onMouseEnter(x,y,mask); +} + + +/*virtual*/ +void LLPanelVolumePulldown::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mHoverTimer.start(); + LLPanel::onMouseLeave(x,y,mask); +} + +/*virtual*/ +void LLPanelVolumePulldown::handleVisibilityChange ( BOOL new_visibility ) +{ + if (new_visibility) + { + mHoverTimer.start(); // timer will be stopped when mouse hovers over panel + gFocusMgr.setTopCtrl(this); + } + else + { + mHoverTimer.stop(); + gFocusMgr.setTopCtrl(NULL); + } +} + +/*virtual*/ +void LLPanelVolumePulldown::onTopLost() +{ + setVisible(FALSE); +} + +void LLPanelVolumePulldown::onAdvancedButtonClick(const LLSD& user_data) +{ + // close the global volume minicontrol, we're bringing up the big one + setVisible(FALSE); + + // bring up the prefs floater + LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*> + (LLFloaterReg::showInstance("preferences")); + if (prefsfloater) + { + // grab the 'audio' panel from the preferences floater and + // bring it the front! + LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core"); + LLPanel* audiopanel = prefsfloater->getChild<LLPanel>("audio"); + if (tabcontainer && audiopanel) + { + tabcontainer->selectTabPanel(audiopanel); + } + } +} + +void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data) +{ + std::string control_name = user_data.asString(); + LLControlVariable* control = findControl(control_name); + + if (control) + control->set(LLSD(FALSE)); +} + +//virtual +void LLPanelVolumePulldown::draw() +{ + F32 alpha = mHoverTimer.getStarted() + ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), sAutoCloseFadeStartTimeSec, sAutoCloseTotalTimeSec, 1.f, 0.f) + : 1.0f; + LLViewDrawContext context(alpha); + + LLPanel::draw(); + + if (alpha == 0.f) + { + setVisible(FALSE); + } +} + diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h new file mode 100644 index 0000000000..9f20caa1a8 --- /dev/null +++ b/indra/newview/llpanelvolumepulldown.h @@ -0,0 +1,64 @@ +/** + * @file llpanelvolumepulldown.h + * @author Tofu Linden + * @brief A panel showing the master volume pull-down + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELVOLUMEPULLDOWN_H +#define LL_LLPANELVOLUMEPULLDOWN_H + +#include "linden_common.h" + +#include "llpanel.h" + +class LLFrameTimer; + +class LLPanelVolumePulldown : public LLPanel +{ + public: + LLPanelVolumePulldown(); + /*virtual*/ void draw(); + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onTopLost(); + /*virtual*/ BOOL postBuild(); + + private: + void setControlFalse(const LLSD& user_data); + void onAdvancedButtonClick(const LLSD& user_data); + + LLFrameTimer mHoverTimer; + static const F32 sAutoCloseFadeStartTimeSec; + static const F32 sAutoCloseTotalTimeSec; +}; + + +#endif // LL_LLPANELVOLUMEPULLDOWN_H diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 0ae62843ac..77a370cc3f 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -62,6 +62,7 @@ public: { mPanel->inventoryFetched(); gInventory.removeObserver(this); + delete this; } private: LLSidepanelAppearance *mPanel; @@ -94,14 +95,12 @@ LLSidepanelAppearance::LLSidepanelAppearance() : mLookInfo(NULL), mCurrOutfitPanel(NULL) { - //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_appearance.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() - mFetchWorn = new LLCurrentlyWornFetchObserver(this); - - mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this); } LLSidepanelAppearance::~LLSidepanelAppearance() { + gInventory.removeObserver(mOutfitRenameWatcher); + delete mOutfitRenameWatcher; } // virtual @@ -156,6 +155,7 @@ BOOL LLSidepanelAppearance::postBuild() mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook"); + mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this); gInventory.addObserver(mOutfitRenameWatcher); return TRUE; @@ -389,16 +389,17 @@ void LLSidepanelAppearance::fetchInventory() } } - mFetchWorn->fetchItems(ids); + LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(this); + fetch_worn->fetchItems(ids); // If no items to be fetched, done will never be triggered. // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. - if (mFetchWorn->isEverythingComplete()) + if (fetch_worn->isEverythingComplete()) { - mFetchWorn->done(); + fetch_worn->done(); } else { - gInventory.addObserver(mFetchWorn); + gInventory.addObserver(fetch_worn); } } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 6ca6734598..514d8facb4 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2460,7 +2460,6 @@ void renderOctree(LLSpatialGroup* group) gGL.color4fv(col.mV); drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); - glDepthMask(GL_TRUE); gGL.setSceneBlendType(LLRender::BT_ALPHA); if (group->mBuilt <= 0.f) diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 5ce3bbb9f6..b3b2b9ee5d 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -42,7 +42,7 @@ #include "llfloaterbuycurrency.h" #include "llfloaterchat.h" #include "llfloaterlagmeter.h" -#include "llfloatervolumepulldown.h" +#include "llpanelvolumepulldown.h" #include "llfloaterregioninfo.h" #include "llfloaterscriptdebug.h" #include "llhudicon.h" @@ -204,6 +204,21 @@ LLStatusBar::LLStatusBar(const LLRect& rect) addChild(mSGPacketLoss); childSetActionTextbox("stat_btn", onClickStatGraph); + + mPanelVolumePulldown = new LLPanelVolumePulldown(); + addChild(mPanelVolumePulldown); + + LLRect volume_pulldown_rect = mPanelVolumePulldown->getRect(); + LLButton* volbtn = getChild<LLButton>( "volume_btn" ); + volume_pulldown_rect.setLeftTopAndSize(volbtn->getRect().mLeft - + (volume_pulldown_rect.getWidth() - volbtn->getRect().getWidth())/2, + volbtn->calcScreenRect().mBottom, + volume_pulldown_rect.getWidth(), + volume_pulldown_rect.getHeight()); + + mPanelVolumePulldown->setShape(volume_pulldown_rect); + mPanelVolumePulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); + mPanelVolumePulldown->setVisible(FALSE); } LLStatusBar::~LLStatusBar() @@ -501,7 +516,7 @@ static void onClickScriptDebug(void*) void LLStatusBar::onMouseEnterVolume(LLUICtrl* ctrl) { // show the master volume pull-down - LLFloaterReg::showInstance("volume_pulldown"); + gStatusBar->mPanelVolumePulldown->setVisible(TRUE); } static void onClickVolume(void* data) diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index f77cc1acb8..0e98da0fe4 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -112,7 +112,7 @@ private: S32 mSquareMetersCommitted; LLFrameTimer* mBalanceTimer; LLFrameTimer* mHealthTimer; - + LLPanelVolumePulldown* mPanelVolumePulldown; static std::vector<std::string> sDays; static std::vector<std::string> sMonths; static const U32 MAX_DATE_STRING_LENGTH; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 3dac0ee452..4d559e2ca7 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1011,7 +1011,7 @@ void render_hud_attachments() LLRect get_whole_screen_region() { - LLRect whole_screen = gViewerWindow->getWindowRectScaled(); + LLRect whole_screen = gViewerWindow->getWorldViewRectScaled(); // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); @@ -1019,13 +1019,13 @@ LLRect get_whole_screen_region() if (zoom_factor > 1.f) { S32 num_horizontal_tiles = llceil(zoom_factor); - S32 tile_width = llround((F32)gViewerWindow->getWindowWidthScaled() / zoom_factor); - S32 tile_height = llround((F32)gViewerWindow->getWindowHeightScaled() / zoom_factor); + S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor); + S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor); int tile_y = sub_region / num_horizontal_tiles; int tile_x = sub_region - (tile_y * num_horizontal_tiles); glh::matrix4f mat; - whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeightScaled() - (tile_y * tile_height), tile_width, tile_height); + whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height); } return whole_screen; } @@ -1045,12 +1045,12 @@ bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::mat F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); glh::matrix4f mat; - F32 scale_x = (F32)gViewerWindow->getWindowWidthScaled() / (F32)screen_region.getWidth(); - F32 scale_y = (F32)gViewerWindow->getWindowHeightScaled() / (F32)screen_region.getHeight(); + F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth(); + F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight(); mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); mat.set_translate( - glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), - clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), + glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), + clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), 0.f)); proj *= mat; @@ -1300,8 +1300,8 @@ void render_ui_2d() if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f) { glPushMatrix(); - S32 half_width = (gViewerWindow->getWindowWidthScaled() / 2); - S32 half_height = (gViewerWindow->getWindowHeightScaled() / 2); + S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); + S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); glTranslatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgent.mHUDCurZoom; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 23bdbc7381..f8d1f34f9d 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -106,7 +106,6 @@ #include "llfloateruipreview.h" #include "llfloaterurldisplay.h" #include "llfloatervoicedevicesettings.h" -#include "llfloatervolumepulldown.h" #include "llfloaterwater.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindlight.h" @@ -256,7 +255,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); - LLFloaterReg::add("volume_pulldown", "floater_volume_pulldown.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVolumePulldown>); LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>); LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7e8c8eb92e..9671b9e5dc 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -48,12 +48,15 @@ #include "llviewerwindow.h" #include "llfocusmgr.h" #include "llcallbacklist.h" +#include "llparcel.h" +#include "llaudioengine.h" // for gAudiop #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" #include "lluuid.h" #include "llkeyboard.h" #include "llmutelist.h" +#include "llfirstuse.h" #include <boost/bind.hpp> // for SkinFolder listener #include <boost/signals2.hpp> @@ -708,6 +711,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) std::vector<LLViewerMediaImpl*> proximity_order; + bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); + bool needs_first_run = LLViewerMedia::needsMediaFirstRun(); U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); @@ -822,6 +827,21 @@ void LLViewerMedia::updateMedia(void *dummy_arg) new_priority = LLPluginClassMedia::PRIORITY_LOW; } + if(!inworld_media_enabled) + { + // If inworld media is locked out, force all inworld media to stay unloaded. + if(!pimpl->getUsedInUI()) + { + new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; + if(needs_first_run) + { + // Don't do this more than once in this loop. + needs_first_run = false; + LLViewerMedia::displayMediaFirstRun(); + } + } + } + pimpl->setPriority(new_priority); if(pimpl->getUsedInUI()) @@ -888,6 +908,61 @@ void LLViewerMedia::cleanupClass() gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); } + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::needsMediaFirstRun() +{ + return gWarningSettings.getBOOL("FirstStreamingMedia"); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::displayMediaFirstRun() +{ + gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); + + LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), + boost::bind(firstRunCallback, _1, _2)); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // user has elected to automatically play media. + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); + gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); + gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); + gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); + + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if (parcel) + { + // play media right now, if available + LLViewerParcelMedia::play(parcel); + + // play music right now, if available + std::string music_url = parcel->getMusicURL(); + if (gAudiop && !music_url.empty()) + gAudiop->startInternetStream(music_url); + } + } + else + { + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE); + gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); + gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); + gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); + } + return false; +} + + ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 5e4dd8ff30..3ce9f1887c 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -115,6 +115,12 @@ class LLViewerMedia // This is the comparitor used to sort the list. static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2); + + // For displaying the media first-run dialog. + static bool needsMediaFirstRun(); + static void displayMediaFirstRun(); + static bool firstRunCallback(const LLSD& notification, const LLSD& response); + }; // Implementation functions not exported into header file @@ -123,7 +129,10 @@ class LLViewerMediaImpl { LOG_CLASS(LLViewerMediaImpl); public: - + + friend class LLViewerMedia; + friend class LLMimeDiscoveryResponder; + LLViewerMediaImpl( const LLUUID& texture_id, S32 media_width, @@ -202,11 +211,15 @@ public: bool isMediaPaused(); bool hasMedia() const; bool isMediaFailed() const { return mMediaSourceFailed; }; + void setMediaFailed(bool val) { mMediaSourceFailed = val; } void resetPreviousMediaState(); void setDisabled(bool disabled); bool isMediaDisabled() const { return mIsDisabled; }; - + + void setInNearbyMediaList(bool in_list) { mInNearbyMediaList = in_list; } + bool getInNearbyMediaList() { return mInNearbyMediaList; } + // returns true if this instance should not be loaded (disabled, muted object, crashed, etc.) bool isForcedUnloaded() const; @@ -311,7 +324,7 @@ public: void setNavState(EMediaNavState state); void cancelMimeTypeProbe(); -public: +private: // a single media url with some data and an impl. LLPluginClassMedia* mMediaSource; LLUUID mTextureId; diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 0f7903a7a5..56dee6b34c 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -56,10 +56,6 @@ LLUUID LLViewerParcelMedia::sMediaRegionID; viewer_media_t LLViewerParcelMedia::sMediaImpl; -// Local functions -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); - - // static void LLViewerParcelMedia::initClass() { @@ -112,12 +108,10 @@ void LLViewerParcelMedia::update(LLParcel* parcel) // First use warning if( (!mediaUrl.empty() || !parcel->getMusicURL().empty()) - && gWarningSettings.getBOOL("FirstStreamingMedia") ) + && LLViewerMedia::needsMediaFirstRun()) { - LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(callback_play_media, _1, _2, parcel)); + LLViewerMedia::displayMediaFirstRun(); return; - } // if we have a current (link sharing) url, use it instead @@ -591,36 +585,6 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; } -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - // user has elected to automatically play media. - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); - gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); - gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); - if(!gSavedSettings.getBOOL("AudioStreamingMedia")) - gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); - // play media right now, if available - LLViewerParcelMedia::play(parcel); - // play music right now, if available - if (parcel) - { - std::string music_url = parcel->getMusicURL(); - if (gAudiop && !music_url.empty()) - gAudiop->startInternetStream(music_url); - } - } - else - { - gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); - gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); - } - gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); - return false; -} - // TODO: observer /* void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in ) diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp index 1b79b47905..ad2723b66b 100644 --- a/indra/newview/llviewerparcelmediaautoplay.cpp +++ b/indra/newview/llviewerparcelmediaautoplay.cpp @@ -35,6 +35,7 @@ #include "llviewerparcelmedia.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "llviewerregion.h" #include "llparcel.h" #include "llviewerparcelmgr.h" #include "lluuid.h" @@ -48,6 +49,8 @@ const F32 AUTOPLAY_SPEED = 0.1f; // how slow should the agent be moving t LLViewerParcelMediaAutoPlay::LLViewerParcelMediaAutoPlay() : LLEventTimer(1), + + mLastParcelID(-1), mPlayed(FALSE), mTimeInParcel(0) { @@ -81,9 +84,18 @@ void LLViewerParcelMediaAutoPlay::playStarted() BOOL LLViewerParcelMediaAutoPlay::tick() { LLParcel *this_parcel = NULL; + LLViewerRegion *this_region = NULL; std::string this_media_url; LLUUID this_media_texture_id; S32 this_parcel_id = 0; + LLUUID this_region_id; + + this_region = gAgent.getRegion(); + + if (this_region) + { + this_region_id = this_region->getRegionID(); + } this_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -96,12 +108,14 @@ BOOL LLViewerParcelMediaAutoPlay::tick() this_parcel_id = this_parcel->getLocalID(); } - if (this_parcel_id != mLastParcelID) + if (this_parcel_id != mLastParcelID || + this_region_id != mLastRegionID) { // we've entered a new parcel mPlayed = FALSE; // we haven't autoplayed yet mTimeInParcel = 0; // reset our timer mLastParcelID = this_parcel_id; + mLastRegionID = this_region_id; } mTimeInParcel += mPeriod; // increase mTimeInParcel by the amount of time between ticks diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index 16279e7f1f..1d80b4756c 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -34,6 +34,7 @@ #define LLVIEWERPARCELMEDIAAUTOPLAY_H #include "lltimer.h" +#include "lluuid.h" // timer to automatically play media class LLViewerParcelMediaAutoPlay : LLEventTimer @@ -47,6 +48,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer private: S32 mLastParcelID; + LLUUID mLastRegionID; BOOL mPlayed; F32 mTimeInParcel; }; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index f825eaa8ab..1edaeec848 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3007,7 +3007,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep) LLViewerTexture::addFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -3024,7 +3024,10 @@ void LLViewerMediaTexture::addFace(LLFace* facep) return ; } - llerrs << "The face does not have a valid texture before media texture." << llendl ; + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "The face does not have a valid texture before media texture." << llendl ; + } } //virtual @@ -3033,7 +3036,7 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) LLViewerTexture::removeFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -3094,7 +3097,10 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) } } - llerrs << "mTextureList texture reference number is corrupted." << llendl ; + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "mTextureList texture reference number is corrupted." << llendl ; + } } void LLViewerMediaTexture::stopPlaying() @@ -3130,11 +3136,15 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) const LLTextureEntry* te = facep->getTextureEntry() ; if(te) { - LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ; if(!tex && te->getID() != mID)//try parcel media. { tex = gTextureList.findImage(mID) ; } + if(!tex) + { + tex = LLViewerFetchedTexture::sDefaultImagep ; + } facep->switchTexture(tex) ; } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 83cbc8a1f9..ddaf4a221c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -604,7 +604,6 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK { const char* buttonname = ""; const char* buttonstatestr = ""; - BOOL handled = FALSE; S32 x = pos.mX; S32 y = pos.mY; x = llround((F32)x / mDisplayScale.mV[VX]); @@ -699,7 +698,10 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK } else { - handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask); + if (top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask)) + { + return TRUE; + } } } @@ -717,34 +719,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; } - if (down) + // Do not allow tool manager to handle mouseclicks if we have disconnected + if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) { - if (gDisconnected) - { - return FALSE; - } - - if(LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) - { - return TRUE; - } + return TRUE; } - else - { - if( !handled ) - { - handled = mRootView->handleAnyMouseClick(x, y, mask, clicktype, down); - } - if( !handled ) - { - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (tool) - { - handled = tool->handleAnyMouseClick(x, y, mask, clicktype, down); - } - } - } // If we got this far on a down-click, it wasn't handled. // Up-clicks, though, are always handled as far as the OS is concerned. diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 55609621b3..d23bcf9006 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1852,12 +1852,22 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) if (mep && impl) { std::string url = mep->getCurrentURL(); - if (url.empty()) + // If the url we're trying to "bounce back" to is either empty or not + // allowed by the whitelist, try the home url. If *that* doesn't work, + // set the media as failed and unload it + if (url.empty() || !mep->checkCandidateUrl(url)) { url = mep->getHomeURL(); } - if (! url.empty()) - { + if (url.empty() || !mep->checkCandidateUrl(url)) + { + // The url to navigate back to is not good, and we have nowhere else + // to go. + LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; + impl->setMediaFailed(true); + } + else { + // Okay, navigate now LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; impl->navigateTo(url, "", false, true); } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 0044daf6b4..6da38fa0d4 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -292,7 +292,7 @@ reference="White" /> <color name="FilterBackgroundColor" - reference="MouseGray" /> + reference="Black" /> <color name="FilterTextColor" value="0.38 0.69 0.57 1" /> @@ -394,7 +394,7 @@ reference="White" /> <color name="InventoryBackgroundColor" - reference="Unused?" /> + reference="DkGray2" /> <color name="InventoryFocusOutlineColor" reference="EmphasisColor" /> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index dab11149b9..ef6df7df1b 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -224,7 +224,7 @@ with the same filename but different name scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" /> <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" /> <texture name="Inspector_I" file_name="windows/Inspector_I.png" preload="false" /> - + <texture name="Inv_Acessories" file_name="icons/Inv_Accessories.png" preload="false" /> <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" /> <texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" /> @@ -648,6 +648,12 @@ with the same filename but different name <texture name="PowerOff_Over" file_name="icons/PowerOff_Over.png" preload="false" /> <texture name="PowerOff_Press" file_name="icons/PowerOff_Press.png" preload="false" /> + <texture name="pixiesmall.j2c" use_mips="true" /> + <texture name="script_error.j2c" use_mips="true" /> + <texture name="silhouette.j2c" use_mips="true" /> + <texture name="foot_shadow.j2c" use_mips="true" /> + <texture name="cloud-particle.j2c" use_mips="true" /> + <!--WARNING OLD ART BELOW *do not use*--> <texture name="icn_chatbar.tga" /> <texture name="icn_media_web.tga" preload="true" /> @@ -676,8 +682,6 @@ with the same filename but different name <texture name="toggle_button_off" file_name="toggle_button_off.png" preload="true" /> <texture name="toggle_button_selected" file_name="toggle_button_selected.png" preload="true" /> - - <texture name="sm_rounded_corners_simple.tga" scale.left="4" scale.top="4" scale.bottom="4" scale.right="4" /> <texture name="color_swatch_alpha.tga" preload="true" /> <texture name="button_anim_pause.tga" /> @@ -696,7 +700,6 @@ with the same filename but different name <texture name="icon_event_mature.tga" /> <texture name="icon_for_sale.tga" /> <texture name="icon_place_for_sale.tga" /> - <texture name="icon_popular.tga" /> <texture name="icon_top_pick.tga" /> <texture name="lag_status_critical.tga" /> @@ -715,27 +718,10 @@ with the same filename but different name <texture name="map_telehub.tga" /> <texture name="map_track_16.tga" /> - <texture name="media_icon.tga" file_name="icn_label_media.tga" /> - <texture name="music_icon.tga" file_name="icn_label_music.tga" /> - - <texture name="notify_tip_icon.tga" /> <texture name="notify_caution_icon.tga" /> <texture name="notify_next.png" preload="true" /> <texture name="notify_box_icon.tga" /> - <texture name="pixiesmall.j2c" use_mips="true" /> - <texture name="script_error.j2c" use_mips="true" /> - <texture name="silhouette.j2c" use_mips="true" /> - <texture name="foot_shadow.j2c" use_mips="true" /> - <texture name="cloud-particle.j2c" use_mips="true" /> - - <texture name="status_no_build.tga" /> - <texture name="status_voice.tga" /> - <texture name="status_no_fly.tga" /> - <texture name="status_health.tga" /> - <texture name="status_no_push.tga" /> - <texture name="status_no_scripts.tga" /> - <texture name="icn_active-speakers-dot-lvl0.tga" /> <texture name="icn_active-speakers-dot-lvl1.tga" /> <texture name="icn_active-speakers-dot-lvl2.tga" /> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 2ff99dcf5a..fac7aef690 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -6,7 +6,7 @@ name="floater_about" help_topic="floater_about" save_rect="true" - title="ABOUT [APP_NAME]" + title="ABOUT [CAPITALIZED_APP_NAME]" width="470"> <floater.string name="AboutHeader"> diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index 953bd08dd4..f59badfcb4 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -47,7 +47,7 @@ label="Search" layout="topleft" left="6" - help_topic="avatarpicker_search_tab" + help_topic="avatarpicker" name="SearchPanel" top="150" width="132"> @@ -98,7 +98,7 @@ label="Friends" layout="topleft" left="6" - help_topic="avatarpicker_friends_tab" + help_topic="avatarpicker" name="FriendsPanel" top="150" width="132"> @@ -144,7 +144,7 @@ label="Near Me" layout="topleft" left="6" - help_topic="avatarpicker_near_me_tab" + help_topic="avatarpicker" name="NearMePanel" top="150" width="132"> diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index 920f0c909a..ae686d9ab7 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -4,8 +4,8 @@ border_drop_shadow_visible="false" drop_shadow_visible="false" border="false" - bg_opaque_image="Inspector_Background" - bg_alpha_image="Toast_Background" + bg_opaque_image="Window_Foreground" + bg_alpha_image="Window_Background" bg_alpha_color="0 0 0 0" legacy_header_height="18" can_minimize="true" diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml index 68bb500c78..bf61697a59 100644 --- a/indra/newview/skins/default/xui/en/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml @@ -190,7 +190,7 @@ function="TopObjects.GetByOwnerName" /> </button> <button - follows="top|left" + follows="bottom|right" height="22" image_overlay="Refresh_Off" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index a4ef807f06..ae198d69a3 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -3,11 +3,12 @@ can_resize="true" can_minimize="true" can_close="false" - height="270" + height="275" layout="topleft" - min_height="122" + min_height="100" min_width="190" name="floater_voice_controls" + help_topic="floater_voice_controls" title="Voice Controls" save_visibility="true" single_instance="true" @@ -32,27 +33,23 @@ name="no_one_near"> No one near has voice enabled </string> - <string - name="max_visible_items"> - 5 - </string> - <panel - bevel_style="out" - border="true" - follows="left|right|top" - height="62" - layout="topleft" - left="0" - name="control_panel" - top="0" - width="282"> - <panel - height="18" - follows="top|left|right" + <layout_stack + clip="false" + follows="all" + height="262" layout="topleft" left="10" - name="my_panel" + mouse_opaque="false" + name="my_call_stack" + orientation="vertical" width="263"> + <layout_panel + follows="top|left|right" + user_resize="false" + auto_resize="false" + layout="topleft" + height="26" + name="my_panel"> <avatar_icon enabled="false" follows="left|top" @@ -78,92 +75,57 @@ <output_monitor auto_update="true" draw_border="false" - follows="right" + follows="top|right" height="16" layout="topleft" name="speaking_indicator" - right="-1" - top="2" + left_pad="5" visible="true" width="20" /> - </panel> - <layout_stack - border_size="0" - clip="false" - follows="all" - height="28" - layout="topleft" - left="10" - mouse_opaque="false" - name="leave_call_stack" - orientation="horizontal" - top_pad="5" - width="263"> - <layout_panel - auto_resize="true" - follows="left|right" - height="26" - layout="topleft" - min_height="23" - min_width="5" - mouse_opaque="false" - name="left_anchor" - width="80"/> + </layout_panel> <layout_panel auto_resize="false" - follows="left|right" + user_resize="false" + follows="top|left" height="26" + visible="true" layout="topleft" - mouse_opaque="false" - min_height="24" - min_width="100" name="leave_call_btn_panel" width="100"> <button - follows="left|right" - height="24" + follows="right|top" + height="23" + top_pad="0" label="Leave Call" - left="0" name="leave_call_btn" - top="0" width="100" /> </layout_panel> - <layout_panel - auto_resize="true" - follows="left|right" - height="26" + <layout_panel + follows="all" + layout="topleft" + left="2" + top_pad="0" + height="205" + name="callers_panel" + user_resize="false" + width="280"> + <avatar_list + follows="all" + height="205" + ignore_online_status="true" layout="topleft" - mouse_opaque="false" - min_height="24" - min_width="5" - name="right_anchor" - width="80"/> - </layout_stack> - </panel> - <avatar_list - follows="all" - height="197" - ignore_online_status="true" - layout="topleft" - left="0" - multi_select="true" - name="speakers_list" - width="282" /> - <panel - filename="panel_avatar_list_item.xml" - follows="left|right|top" - height="24" - layout="topleft" - left="0" - name="non_avatar_caller" - top="70" - width="282" /> - <view_border - bevel_style="out" - follows="left|top|right|bottom" - height="206" - layout="topleft" - left="0" - top="63" - width="282" /> + multi_select="true" + name="speakers_list" + width="280" /> + <panel + filename="panel_avatar_list_item.xml" + follows="left|right|top" + height="24" + layout="topleft" + left="0" + name="non_avatar_caller" + top="10" + width="276" /> + </layout_panel> + </layout_stack> </floater> 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 4ece0fa3ba..897d959b98 100644 --- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml +++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml @@ -5,6 +5,9 @@ height="108" layout="topleft" name="whitelist_entry" + single_instance="true" + help_topic="whitelist_entry" + title="WHITELIST ENTRY" width="390"> <text type="string" length="1" bottom="20" follows="top|left" height="15" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 690167bc33..a0dec346a4 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -223,6 +223,7 @@ parameter="test_inspectors" /> </menu_item_call> </menu> +<!-- <menu_item_check label="Reg In Client Test (restart)" name="Reg In Client Test (restart)"> @@ -232,6 +233,7 @@ function="ToggleControl" parameter="RegInClient" /> </menu_item_check> +--> <menu_item_separator /> <menu_item_call label="Set Window Size..." diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index fa7e3e86a3..45100eb1ff 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -198,40 +198,6 @@ function="Floater.Toggle" parameter="nearby_media" /> </menu_item_check> - <!--menu_item_check - label="Block List" - layout="topleft" - name="Mute List"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="mute" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="mute" /> - </menu_item_check--> - <menu_item_separator - layout="topleft" /> - <menu_item_check - label="(Legacy) Communicate" - layout="topleft" - name="Instant Message" - shortcut="control|T"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="communicate" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="communicate" /> - </menu_item_check> - <menu_item_call - label="(Temp) Media Remote Ctrl" - layout="topleft" - name="Preferences" - shortcut="control|alt|M"> - <menu_item_call.on_click - function="Floater.Toggle" - parameter="media_remote_ctrl" /> - </menu_item_call> </menu> <menu label="World" @@ -283,7 +249,7 @@ </menu_item_call> <menu create_jump_keys="true" - label="About This Place" + label="Place Profile" layout="topleft" name="Land" tear_off="true"> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 970a2e6a8a..003e1baa7e 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -5,6 +5,7 @@ height="305" layout="topleft" name="block_list_panel" + help_topic="blocked_list" min_height="350" min_width="240" width="280"> diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index c899dcb750..039e1ae086 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -25,7 +25,7 @@ title="Favorites bar"> <places_inventory_panel allow_multi_select="true" - border="true" + border="false" bottom="0" follows="left|top|right|bottom" height="126" @@ -41,7 +41,7 @@ title="Landmarks"> <places_inventory_panel allow_multi_select="true" - border="true" + border="false" bottom="0" follows="left|top|right|bottom" height="126" @@ -57,7 +57,7 @@ title="My Inventory"> <places_inventory_panel allow_multi_select="true" - border="true" + border="false" bottom="0" follows="left|top|right|bottom" height="126" @@ -73,7 +73,7 @@ title="Library"> <places_inventory_panel allow_multi_select="true" - border="true" + border="false" bottom="0" follows="left|top|right|bottom" height="120" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index e2884dbedc..9ad99b1f13 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -47,7 +47,7 @@ left="10" name="back_btn" tool_tip="Go back to previous location" - top="3" + top="2" width="31" /> <button follows="left|top" @@ -92,7 +92,6 @@ width="20" /> --> </location_input> - <!-- <button --> <!-- follows="right|top" --> <!-- height="20" --> @@ -108,7 +107,6 @@ <!-- name="search_bg" --> <!-- top_delta="0" --> <!-- width="168" /> --> - <search_combo_box bevel_style="none" border_style="line" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index c98555735a..22c75a595e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -260,7 +260,7 @@ width="200"> My effects: </text> - <text + <text type="string" length="1" follows="left|top" @@ -270,16 +270,23 @@ name="title_afk_text" width="190"> Away timeout: - </text> + </text> <color_swatch - control_name="EffectColor" + can_apply_immediately="true" follows="left|top" height="50" layout="topleft" left="50" name="effect_color_swatch" tool_tip="Click to open Color Picker" - width="38" /> + width="38"> + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="EffectColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="EffectColor" /> + </color_swatch> <combo_box height="23" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 00f54feabd..bfca2f2e46 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -42,18 +42,36 @@ <button auto_resize="true" halign="right" + font="SansSerifSmall" + follows="right|top" + image_overlay="" + image_selected="spacer35.tga" + image_unselected="spacer35.tga" + image_pressed="spacer35.tga" + height="16" + right="-228" + label_shadow="false" + name="buycurrency" + tool_tip="My Balance" + top="5" + width="100" /> + <button + auto_resize="true" + halign="right" + font="SansSerifSmall" follows="right|top" image_selected="BuyArrow_Over" image_unselected="BuyArrow_Over" image_pressed="BuyArrow_Press" height="16" - right="-128" - label_color="White" + label="Buy L$" + label_color="EmphasisColor" + left_pad="0" label_shadow="false" - name="buycurrency" + name="buyL" pad_right="20px" - tool_tip="My Balance: Click to buy more L$" - top="3" + tool_tip="Click to buy more L$" + top="5" width="100" /> <text type="string" @@ -62,29 +80,27 @@ follows="right|bottom" halign="right" height="16" - top="4" + top="7" layout="topleft" left_pad="0" name="TimeText" - text_color="TimeTextColor" tool_tip="Current time (Pacific)" width="85"> 12:00 AM </text> <button follows="right|bottom" - height="16" + height="15" image_selected="AudioMute_Off" image_pressed="Audio_Press" image_unselected="Audio_Off" is_toggle="true" left_pad="18" - top="1" + top="4" name="volume_btn" tool_tip="Global Volume Control" width="16" /> <text - enabled="true" follows="right|bottom" halign="center" height="12" diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml new file mode 100644 index 0000000000..60d4a7e00b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_opaque="true" + background_visible="false" + border_visible="false" + border="false" + chrome="true" + follows="bottom" + height="150" + layout="topleft" + name="volumepulldown_floater" + width="32"> + <!-- floater background image --> + <icon + height="150" + image_name="Inspector_Background" + layout="topleft" + left="0" + name="normal_background" + top="0" + width="32" /> + <slider + control_name="AudioLevelMaster" + follows="left|top" + left="0" + top="1" + orientation="vertical" + height="120" + increment="0.05" + initial_value="0.5" + layout="topleft" + name="mastervolume" + show_text="false" + slider_label.halign="right" + top_pad="2" + volume="true"> + <slider.commit_callback + function="Vol.setControlFalse" + parameter="MuteAudio" /> + </slider> + <button + left="7" + top_pad="9" + width="18" + height="12" + follows="top|left" + name="prefs_btn" + image_unselected="Icon_Gear_Foreground" + image_disabled="Icon_Gear_Background" + image_pressed="Icon_Gear_Press" + scale_image="false"> + <button.commit_callback + function="Vol.GoAudioPrefs" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 447901f984..cf8f91bf51 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -8,6 +8,7 @@ <!-- Default Args - these arguments will be replaced in all strings --> <string name="SECOND_LIFE">Second Life</string> <string name="APP_NAME">Second Life</string> + <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> <string name="SECOND_LIFE_GRID">Second Life Grid</string> <string name="SUPPORT_SITE">Second Life Support Portal</string> @@ -1807,7 +1808,7 @@ Clears (deletes) the media and all params from the given face. <!-- inventory --> <string name="InventoryNoMatchingItems">No matching items found in inventory.</string> - <string name="FavoritesNoMatchingItems">Drag and drop a landmark here to add to your favorites.</string> + <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture"> You do not have a copy of this texture in your inventory diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml new file mode 100644 index 0000000000..93875d66e6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bg_opaque_color="InventoryBackgroundColor" + background_visible="true" + background_opaque="true" + /> diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 67bb7c1896..1c0a8ba7c5 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -96,7 +96,7 @@ name="damage_icon" width="14" height="13" - top="22" + top="25" left="2" follows="right|top" image_name="Parcel_Damage_Dark" @@ -112,17 +112,19 @@ font="SansSerifSmall" text_color="TextFgColor" /> - - <combo_button name="Location History" - label="" - pad_right="0"/> - <combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10" + <combo_button + name="Location History" + label="" + pad_right="0"/> + <combo_list + bg_writeable_color="MenuDefaultBgColor" + page_lines="10" scroll_bar_bg_visible="true" /> <combo_editor name="Combo Text Entry" - text_pad_left="22" + text_pad_left="27" select_on_focus="false" font="SansSerifSmall" bevel_style="none" border_style="line" - border.border_thickness="0"/> + border.border_thickness="0" /> </location_input> |