diff options
Diffstat (limited to 'indra')
186 files changed, 4787 insertions, 3202 deletions
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 20ff7bab34..e68672d46f 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -276,7 +276,7 @@ void LLCharacter::removeAnimationData(std::string name) BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL set_by_user) { S32 index = which_param->getID(); - VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { index_iter->second->setWeight(weight, set_by_user); @@ -293,7 +293,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL std::string tname(param_name); LLStringUtil::toLower(tname); char *tableptr = sVisualParamNames.checkString(tname); - VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr); + visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr); if (name_iter != mVisualParamNameMap.end()) { name_iter->second->setWeight(weight, set_by_user); @@ -308,7 +308,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL //----------------------------------------------------------------------------- BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user) { - VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { index_iter->second->setWeight(weight, set_by_user); @@ -324,7 +324,7 @@ BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user) F32 LLCharacter::getVisualParamWeight(LLVisualParam *which_param) { S32 index = which_param->getID(); - VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { return index_iter->second->getWeight(); @@ -344,7 +344,7 @@ F32 LLCharacter::getVisualParamWeight(const char* param_name) std::string tname(param_name); LLStringUtil::toLower(tname); char *tableptr = sVisualParamNames.checkString(tname); - VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr); + visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr); if (name_iter != mVisualParamNameMap.end()) { return name_iter->second->getWeight(); @@ -358,7 +358,7 @@ F32 LLCharacter::getVisualParamWeight(const char* param_name) //----------------------------------------------------------------------------- F32 LLCharacter::getVisualParamWeight(S32 index) { - VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { return index_iter->second->getWeight(); @@ -415,7 +415,7 @@ LLVisualParam* LLCharacter::getVisualParam(const char *param_name) std::string tname(param_name); LLStringUtil::toLower(tname); char *tableptr = sVisualParamNames.checkString(tname); - VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr); + visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr); if (name_iter != mVisualParamNameMap.end()) { return name_iter->second; @@ -430,7 +430,7 @@ LLVisualParam* LLCharacter::getVisualParam(const char *param_name) void LLCharacter::addSharedVisualParam(LLVisualParam *param) { S32 index = param->getID(); - VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); LLVisualParam* current_param = 0; if (index_iter != mVisualParamIndexMap.end()) current_param = index_iter->second; @@ -457,13 +457,13 @@ void LLCharacter::addVisualParam(LLVisualParam *param) { S32 index = param->getID(); // Add Index map - std::pair<VisualParamIndexMap_t::iterator, bool> idxres; - idxres = mVisualParamIndexMap.insert(VisualParamIndexMap_t::value_type(index, param)); + std::pair<visual_param_index_map_t::iterator, bool> idxres; + idxres = mVisualParamIndexMap.insert(visual_param_index_map_t::value_type(index, param)); if (!idxres.second) { llwarns << "Visual parameter " << param->getName() << " already exists with same ID as " << param->getName() << llendl; - VisualParamIndexMap_t::iterator index_iter = idxres.first; + visual_param_index_map_t::iterator index_iter = idxres.first; index_iter->second = param; } @@ -473,12 +473,12 @@ void LLCharacter::addVisualParam(LLVisualParam *param) std::string tname(param->getName()); LLStringUtil::toLower(tname); char *tableptr = sVisualParamNames.addString(tname); - std::pair<VisualParamNameMap_t::iterator, bool> nameres; - nameres = mVisualParamNameMap.insert(VisualParamNameMap_t::value_type(tableptr, param)); + std::pair<visual_param_name_map_t::iterator, bool> nameres; + nameres = mVisualParamNameMap.insert(visual_param_name_map_t::value_type(tableptr, param)); if (!nameres.second) { // Already exists, copy param - VisualParamNameMap_t::iterator name_iter = nameres.first; + visual_param_name_map_t::iterator name_iter = nameres.first; name_iter->second = param; } } diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 1507686f67..cb44a32e8a 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -233,12 +233,12 @@ public: LLVisualParam* getVisualParam(S32 id) const { - VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(id); + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(id); return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second; } S32 getVisualParamID(LLVisualParam *id) { - VisualParamIndexMap_t::iterator iter; + visual_param_index_map_t::iterator iter; for (iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) { if (iter->second == id) @@ -276,11 +276,12 @@ protected: private: // visual parameter stuff - typedef std::map<S32, LLVisualParam *> VisualParamIndexMap_t; - VisualParamIndexMap_t mVisualParamIndexMap; - VisualParamIndexMap_t::iterator mCurIterator; - typedef std::map<char *, LLVisualParam *> VisualParamNameMap_t; - VisualParamNameMap_t mVisualParamNameMap; + typedef std::map<S32, LLVisualParam *> visual_param_index_map_t; + typedef std::map<char *, LLVisualParam *> visual_param_name_map_t; + + visual_param_index_map_t::iterator mCurIterator; + visual_param_index_map_t mVisualParamIndexMap; + visual_param_name_map_t mVisualParamNameMap; static LLStringTable sVisualParamNames; }; diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index c4763c6331..9e4957342c 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -305,7 +305,7 @@ void LLVisualParam::stopAnimating(BOOL set_by_user) } //virtual -BOOL LLVisualParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) +BOOL LLVisualParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params) { // nothing to do for non-driver parameters return TRUE; diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index e6503d611d..0b516b9374 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -96,10 +96,9 @@ protected: //----------------------------------------------------------------------------- class LLVisualParam { -protected: - typedef boost::function<LLVisualParam*(S32)> visual_param_mapper; - public: + typedef boost::function<LLVisualParam*(S32)> visual_param_mapper; + LLVisualParam(); virtual ~LLVisualParam(); @@ -119,7 +118,7 @@ public: virtual void animate(F32 delta, BOOL set_by_user); virtual void stopAnimating(BOOL set_by_user); - virtual BOOL linkDrivenParams(visual_param_mapper mapper, bool only_cross_params); + virtual BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); virtual void resetDrivenParams(); // Interface methods @@ -161,7 +160,6 @@ protected: S32 mID; // id for storing weight/morphtarget compares compactly LLVisualParamInfo *mInfo; - }; #endif // LL_LLVisualParam_H diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index a6421ac696..4bdfe5a867 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -126,6 +126,16 @@ void LLEventPumps::flush() } } +void LLEventPumps::reset() +{ + // Reset every known LLEventPump instance. Leave it up to each instance to + // decide what to do with the reset() call. + for (PumpMap::iterator pmi = mPumpMap.begin(), pmend = mPumpMap.end(); pmi != pmend; ++pmi) + { + pmi->second->reset(); + } +} + std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string& name, bool tweak) { std::pair<PumpMap::iterator, bool> inserted = @@ -242,6 +252,7 @@ LLEventPumps::~LLEventPumps() LLEventPump::LLEventPump(const std::string& name, bool tweak): // Register every new instance with LLEventPumps mName(LLEventPumps::instance().registerNew(*this, name, tweak)), + mSignal(new LLStandardSignal()), mEnabled(true) {} @@ -264,6 +275,13 @@ std::string LLEventPump::inventName(const std::string& pfx) return STRINGIZE(pfx << suffix++); } +void LLEventPump::reset() +{ + mSignal.reset(); + mConnections.clear(); + //mDeps.clear(); +} + LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventListener& listener, const NameList& after, const NameList& before) @@ -405,7 +423,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL } // Now that newNode has a value that places it appropriately in mSignal, // connect it. - LLBoundListener bound = mSignal.connect(newNode, listener); + LLBoundListener bound = mSignal->connect(newNode, listener); mConnections[name] = bound; return bound; } @@ -445,7 +463,7 @@ bool LLEventStream::post(const LLSD& event) // Let caller know if any one listener handled the event. This is mostly // useful when using LLEventStream as a listener for an upstream // LLEventPump. - return mSignal(event); + return (*mSignal)(event); } /***************************************************************************** @@ -476,7 +494,7 @@ void LLEventQueue::flush() mEventQueue.clear(); for ( ; ! queue.empty(); queue.pop_front()) { - mSignal(queue.front()); + (*mSignal)(queue.front()); } } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index b999bfafa7..64e5cb5da7 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -202,6 +202,12 @@ public: */
void flush();
+ /**
+ * Reset all known LLEventPump instances
+ * workaround for DEV-35406 crash on shutdown
+ */
+ void reset();
+
private:
friend class LLEventPump;
/**
@@ -504,6 +510,8 @@ private: /// flush queued events
virtual void flush() {}
+ virtual void reset();
+
private:
virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
const NameList& after,
@@ -512,7 +520,8 @@ private: protected:
/// implement the dispatching
- LLStandardSignal mSignal;
+ boost::scoped_ptr<LLStandardSignal> mSignal;
+
/// valve open?
bool mEnabled;
/// Map of named listeners. This tracks the listeners that actually exist
diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp index e0c562dbf4..7e5c3a117b 100644 --- a/indra/llmessage/tests/llhost_test.cpp +++ b/indra/llmessage/tests/llhost_test.cpp @@ -157,8 +157,8 @@ namespace tut template<> template<> void host_object::test<9>() { - skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\""); - std::string hostStr = "google.com"; +// skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\""); + std::string hostStr = "linux.org"; LLHost host; host.setHostByName(hostStr); diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 4bd5a83e37..f0b4436df5 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -1,230 +1,228 @@ -# -*- cmake -*-
-
-project(llui)
-
-include(00-Common)
-include(LLCommon)
-include(LLImage)
-include(LLMath)
-include(LLMessage)
-include(LLRender)
-include(LLWindow)
-include(LLVFS)
-include(LLXML)
-include(LLXUIXML)
-
-include_directories(
- ${LLCOMMON_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
- ${LLMATH_INCLUDE_DIRS}
- ${LLMESSAGE_INCLUDE_DIRS}
- ${LLRENDER_INCLUDE_DIRS}
- ${LLWINDOW_INCLUDE_DIRS}
- ${LLVFS_INCLUDE_DIRS}
- ${LLXML_INCLUDE_DIRS}
- ${LLXUIXML_INCLUDE_DIRS}
- )
-
-set(llui_SOURCE_FILES
- llalertdialog.cpp
- llbutton.cpp
- llcheckboxctrl.cpp
- llclipboard.cpp
- llcombobox.cpp
- llconsole.cpp
- llcontainerview.cpp
- llctrlselectioninterface.cpp
- lldockablefloater.cpp
- lldockcontrol.cpp
- lldraghandle.cpp
- lleditmenuhandler.cpp
- llf32uictrl.cpp
- llfiltereditor.cpp
- llflatlistview.cpp
- llfloater.cpp
- llfloaterreg.cpp
- llfloaterreglistener.cpp
- llflyoutbutton.cpp
- llfocusmgr.cpp
- llfunctorregistry.cpp
- lliconctrl.cpp
- llkeywords.cpp
- lllayoutstack.cpp
- lllineeditor.cpp
- lllocalcliprect.cpp
- llmenubutton.cpp
- llmenugl.cpp
- llmodaldialog.cpp
- llmultifloater.cpp
- llmultislider.cpp
- llmultisliderctrl.cpp
- llnotifications.cpp
- llnotificationslistener.cpp
- llpanel.cpp
- llprogressbar.cpp
- llradiogroup.cpp
- llresizebar.cpp
- llresizehandle.cpp
- llresmgr.cpp
- llrngwriter.cpp
- llscrollbar.cpp
- llscrollcontainer.cpp
- llscrollingpanellist.cpp
- llscrolllistcell.cpp
- llscrolllistcolumn.cpp
- llscrolllistctrl.cpp
- llscrolllistitem.cpp
- llsdparam.cpp
- llsearcheditor.cpp
- llslider.cpp
- llsliderctrl.cpp
- llspinctrl.cpp
- llstatbar.cpp
- llstatgraph.cpp
- llstatview.cpp
- llstyle.cpp
- lltabcontainer.cpp
- lltextbase.cpp
- lltextbox.cpp
- lltexteditor.cpp
- lltextparser.cpp
- lltransientfloatermgr.cpp
- lltransutil.cpp
- lltoggleablemenu.cpp
- lltooltip.cpp
- llui.cpp
- lluicolortable.cpp
- lluictrl.cpp
- lluictrlfactory.cpp
- lluiimage.cpp
- lluistring.cpp
- llundo.cpp
- llurlaction.cpp
- llurlentry.cpp
- llurlmatch.cpp
- llurlregistry.cpp
- llviewborder.cpp
- llviewmodel.cpp
- llview.cpp
- llviewquery.cpp
- )
-
-set(llui_HEADER_FILES
- CMakeLists.txt
-
- llalertdialog.h
- llbutton.h
- llcallbackmap.h
- llcheckboxctrl.h
- llclipboard.h
- llcombobox.h
- llconsole.h
- llcontainerview.h
- llctrlselectioninterface.h
- lldraghandle.h
- lldockablefloater.h
- lldockcontrol.h
- lleditmenuhandler.h
- llf32uictrl.h
- llfiltereditor.h
- llflatlistview.h
- llfloater.h
- llfloaterreg.h
- llfloaterreglistener.h
- llflyoutbutton.h
- llfocusmgr.h
- llfunctorregistry.h
- llhandle.h
- llhelp.h
- lliconctrl.h
- llkeywords.h
- lllayoutstack.h
- lllazyvalue.h
- lllineeditor.h
- lllocalcliprect.h
- llmenubutton.h
- llmenugl.h
- llmodaldialog.h
- llmultifloater.h
- llmultisliderctrl.h
- llmultislider.h
- llnotifications.h
- llnotificationslistener.h
- llpanel.h
- llprogressbar.h
- llradiogroup.h
- llresizebar.h
- llresizehandle.h
- llresmgr.h
- llrngwriter.h
- llsearcheditor.h
- llscrollbar.h
- llscrollcontainer.h
- llscrollingpanellist.h
- llscrolllistcell.h
- llscrolllistcolumn.h
- llscrolllistctrl.h
- llscrolllistitem.h
- llsdparam.h
- llsliderctrl.h
- llslider.h
- llspinctrl.h
- llstatbar.h
- llstatgraph.h
- llstatview.h
- llstyle.h
- lltabcontainer.h
- lltextbase.h
- lltextbox.h
- lltexteditor.h
- lltextparser.h
- lltoggleablemenu.h
- lltooltip.h
- lltransientfloatermgr.h
- lltransutil.h
- lluicolortable.h
- lluiconstants.h
- lluictrlfactory.h
- lluictrl.h
- lluifwd.h
- llui.h
- lluiimage.h
- lluistring.h
- llundo.h
- llurlaction.h
- llurlentry.h
- llurlmatch.h
- llurlregistry.h
- llviewborder.h
- llviewmodel.h
- llview.h
- llviewquery.h
- )
-
-set_source_files_properties(${llui_HEADER_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
-list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES})
-
-add_library (llui ${llui_SOURCE_FILES})
-# Libraries on which this library depends, needed for Linux builds
-# Sort by high-level to low-level
-target_link_libraries(llui
- ${LLMESSAGE_LIBRARIES}
- ${LLRENDER_LIBRARIES}
- ${LLWINDOW_LIBRARIES}
- ${LLIMAGE_LIBRARIES}
- ${LLVFS_LIBRARIES} # ugh, just for LLDir
- ${LLXUIXML_LIBRARIES}
- ${LLXML_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender
- )
-
-# Add tests
-include(LLAddBuildTest)
-SET(llui_TEST_SOURCE_FILES
- llurlmatch.cpp
- llurlentry.cpp
- )
-LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+# -*- cmake -*- + +project(llui) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLMath) +include(LLMessage) +include(LLRender) +include(LLWindow) +include(LLVFS) +include(LLXML) +include(LLXUIXML) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLMESSAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ${LLXUIXML_INCLUDE_DIRS} + ) + +set(llui_SOURCE_FILES + llalertdialog.cpp + llbutton.cpp + llcheckboxctrl.cpp + llclipboard.cpp + llcombobox.cpp + llconsole.cpp + llcontainerview.cpp + llctrlselectioninterface.cpp + lldockablefloater.cpp + lldockcontrol.cpp + lldraghandle.cpp + lleditmenuhandler.cpp + llf32uictrl.cpp + llfiltereditor.cpp + llflatlistview.cpp + llfloater.cpp + llfloaterreg.cpp + llfloaterreglistener.cpp + llflyoutbutton.cpp + llfocusmgr.cpp + llfunctorregistry.cpp + lliconctrl.cpp + llkeywords.cpp + lllayoutstack.cpp + lllineeditor.cpp + lllocalcliprect.cpp + llmenubutton.cpp + llmenugl.cpp + llmodaldialog.cpp + llmultifloater.cpp + llmultislider.cpp + llmultisliderctrl.cpp + llnotifications.cpp + llnotificationslistener.cpp + llpanel.cpp + llprogressbar.cpp + llradiogroup.cpp + llresizebar.cpp + llresizehandle.cpp + llresmgr.cpp + llrngwriter.cpp + llscrollbar.cpp + llscrollcontainer.cpp + llscrollingpanellist.cpp + llscrolllistcell.cpp + llscrolllistcolumn.cpp + llscrolllistctrl.cpp + llscrolllistitem.cpp + llsdparam.cpp + llsearcheditor.cpp + llslider.cpp + llsliderctrl.cpp + llspinctrl.cpp + llstatbar.cpp + llstatgraph.cpp + llstatview.cpp + llstyle.cpp + lltabcontainer.cpp + lltextbase.cpp + lltextbox.cpp + lltexteditor.cpp + lltextparser.cpp + lltransutil.cpp + lltoggleablemenu.cpp + lltooltip.cpp + llui.cpp + lluicolortable.cpp + lluictrl.cpp + lluictrlfactory.cpp + lluiimage.cpp + lluistring.cpp + llundo.cpp + llurlaction.cpp + llurlentry.cpp + llurlmatch.cpp + llurlregistry.cpp + llviewborder.cpp + llviewmodel.cpp + llview.cpp + llviewquery.cpp + ) + +set(llui_HEADER_FILES + CMakeLists.txt + + llalertdialog.h + llbutton.h + llcallbackmap.h + llcheckboxctrl.h + llclipboard.h + llcombobox.h + llconsole.h + llcontainerview.h + llctrlselectioninterface.h + lldraghandle.h + lldockablefloater.h + lldockcontrol.h + lleditmenuhandler.h + llf32uictrl.h + llfiltereditor.h + llflatlistview.h + llfloater.h + llfloaterreg.h + llfloaterreglistener.h + llflyoutbutton.h + llfocusmgr.h + llfunctorregistry.h + llhandle.h + llhelp.h + lliconctrl.h + llkeywords.h + lllayoutstack.h + lllazyvalue.h + lllineeditor.h + lllocalcliprect.h + llmenubutton.h + llmenugl.h + llmodaldialog.h + llmultifloater.h + llmultisliderctrl.h + llmultislider.h + llnotifications.h + llnotificationslistener.h + llpanel.h + llprogressbar.h + llradiogroup.h + llresizebar.h + llresizehandle.h + llresmgr.h + llrngwriter.h + llsearcheditor.h + llscrollbar.h + llscrollcontainer.h + llscrollingpanellist.h + llscrolllistcell.h + llscrolllistcolumn.h + llscrolllistctrl.h + llscrolllistitem.h + llsdparam.h + llsliderctrl.h + llslider.h + llspinctrl.h + llstatbar.h + llstatgraph.h + llstatview.h + llstyle.h + lltabcontainer.h + lltextbase.h + lltextbox.h + lltexteditor.h + lltextparser.h + lltoggleablemenu.h + lltooltip.h + lltransutil.h + lluicolortable.h + lluiconstants.h + lluictrlfactory.h + lluictrl.h + lluifwd.h + llui.h + lluiimage.h + lluistring.h + llundo.h + llurlaction.h + llurlentry.h + llurlmatch.h + llurlregistry.h + llviewborder.h + llviewmodel.h + llview.h + llviewquery.h + ) + +set_source_files_properties(${llui_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES}) + +add_library (llui ${llui_SOURCE_FILES}) +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +target_link_libraries(llui + ${LLMESSAGE_LIBRARIES} + ${LLRENDER_LIBRARIES} + ${LLWINDOW_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLVFS_LIBRARIES} # ugh, just for LLDir + ${LLXUIXML_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender + ) + +# Add tests +include(LLAddBuildTest) +SET(llui_TEST_SOURCE_FILES + llurlmatch.cpp + llurlentry.cpp + ) +LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}") diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 228d0e701f..35b3e486af 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -99,7 +99,7 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname) { instance->setMinimized(FALSE); instance->setVisible(TRUE); - instance->setFocus(TRUE); + gFloaterView->bringToFront(instance); } } @@ -141,6 +141,16 @@ void LLDockableFloater::setMinimized(BOOL minimize) LLFloater::setMinimized(minimize); } +LLView * LLDockableFloater::getDockWidget() +{ + LLView * res = NULL; + if (getDockControl() != NULL) { + res = getDockControl()->getDock(); + } + + return res; +} + void LLDockableFloater::onDockHidden() { setCanDock(FALSE); diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 499ce9ae8d..46491d8a29 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -78,6 +78,8 @@ public: */ /*virtual*/ void setMinimized(BOOL minimize); + LLView * getDockWidget(); + virtual void onDockHidden(); virtual void onDockShown(); diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index e8ffcac0ac..756a2900d3 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -63,6 +63,10 @@ public: void on(); void off(); void setDock(LLView* dockWidget); + LLView* getDock() + { + return mDockWidget; + } void repositionDockable(); void drawToungue(); bool isDockVisible(); diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h index 10a7fd4544..899f6b9326 100644 --- a/indra/llui/llhandle.h +++ b/indra/llui/llhandle.h @@ -60,7 +60,7 @@ template <typename T> class LLHandle { public: - LLHandle() : mTombStone(sDefaultTombStone) {} + LLHandle() : mTombStone(getDefaultTombStone()) {} const LLHandle<T>& operator =(const LLHandle<T>& other) { mTombStone = other.mTombStone; @@ -74,7 +74,7 @@ public: void markDead() { - mTombStone = sDefaultTombStone; + mTombStone = getDefaultTombStone(); } T* get() const @@ -104,13 +104,13 @@ protected: LLPointer<LLTombStone<T> > mTombStone; private: - static LLPointer<LLTombStone<T> > sDefaultTombStone; + static LLPointer<LLTombStone<T> >& getDefaultTombStone() + { + static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>; + return sDefaultTombStone; + } }; -// initialize static "empty" tombstone pointer -template <typename T> LLPointer<LLTombStone<T> > LLHandle<T>::sDefaultTombStone = new LLTombStone<T>(); - - template <typename T> class LLRootHandle : public LLHandle<T> { diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 5eade72b61..24fd380bb1 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -229,7 +229,7 @@ static void get_attribute_bool_and_write(LLXMLNodePtr node, LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>()); - LLXUIParser::instance().readXUI(node, p); + LLXUIParser::instance().readXUI(node, p, LLUICtrlFactory::getInstance()->getCurFileName()); // Export must happen before setupParams() mungles rectangles and before // this item gets added to parent (otherwise screws up last_child_rect diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index a68b9cae57..ef222bad60 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1,1516 +1,1517 @@ -/**
-* @file llnotifications.cpp
-* @brief Non-UI queue manager for keeping a prioritized list of notifications
-*
-* $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 "linden_common.h"
-
-#include "llnotifications.h"
-
-#include "lluictrl.h"
-#include "lluictrlfactory.h"
-#include "lldir.h"
-#include "llsdserialize.h"
-#include "lltrans.h"
-#include "llnotificationslistener.h"
-
-#include <algorithm>
-#include <boost/regex.hpp>
-
-
-const std::string NOTIFICATION_PERSIST_VERSION = "0.93";
-
-// local channel for notification history
-class LLNotificationHistoryChannel : public LLNotificationChannel
-{
- LOG_CLASS(LLNotificationHistoryChannel);
-public:
- LLNotificationHistoryChannel(const std::string& filename) :
- LLNotificationChannel("History", "Visible", &historyFilter, LLNotificationComparators::orderByUUID()),
- mFileName(filename)
- {
- connectChanged(boost::bind(&LLNotificationHistoryChannel::historyHandler, this, _1));
- loadPersistentNotifications();
- }
-
-private:
- bool historyHandler(const LLSD& payload)
- {
- // we ignore "load" messages, but rewrite the persistence file on any other
- std::string sigtype = payload["sigtype"];
- if (sigtype != "load")
- {
- savePersistentNotifications();
- }
- return false;
- }
-
- // The history channel gets all notifications except those that have been cancelled
- static bool historyFilter(LLNotificationPtr pNotification)
- {
- return !pNotification->isCancelled();
- }
-
- void savePersistentNotifications()
- {
- llinfos << "Saving open notifications to " << mFileName << llendl;
-
- llofstream notify_file(mFileName.c_str());
- if (!notify_file.is_open())
- {
- llwarns << "Failed to open " << mFileName << llendl;
- return;
- }
-
- LLSD output;
- output["version"] = NOTIFICATION_PERSIST_VERSION;
- LLSD& data = output["data"];
-
- for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
- {
- if (!LLNotifications::instance().templateExists((*it)->getName())) continue;
-
- // only store notifications flagged as persisting
- LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate((*it)->getName());
- if (!templatep->mPersist) continue;
-
- data.append((*it)->asLLSD());
- }
-
- LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
- formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);
- }
-
- void loadPersistentNotifications()
- {
- llinfos << "Loading open notifications from " << mFileName << llendl;
-
- llifstream notify_file(mFileName.c_str());
- if (!notify_file.is_open())
- {
- llwarns << "Failed to open " << mFileName << llendl;
- return;
- }
-
- LLSD input;
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
- if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0)
- {
- llwarns << "Failed to parse open notifications" << llendl;
- return;
- }
-
- if (input.isUndefined()) return;
- std::string version = input["version"];
- if (version != NOTIFICATION_PERSIST_VERSION)
- {
- llwarns << "Bad open notifications version: " << version << llendl;
- return;
- }
- LLSD& data = input["data"];
- if (data.isUndefined()) return;
-
- LLNotifications& instance = LLNotifications::instance();
- for (LLSD::array_const_iterator notification_it = data.beginArray();
- notification_it != data.endArray();
- ++notification_it)
- {
- instance.add(LLNotificationPtr(new LLNotification(*notification_it)));
- }
- }
-
- //virtual
- void onDelete(LLNotificationPtr pNotification)
- {
- // we want to keep deleted notifications in our log
- mItems.insert(pNotification);
-
- return;
- }
-
-private:
- std::string mFileName;
-};
-
-bool filterIgnoredNotifications(LLNotificationPtr notification)
-{
- // filter everything if we are to ignore ALL
- if(LLNotifications::instance().getIgnoreAllNotifications())
- {
- return false;
- }
-
- LLNotificationFormPtr form = notification->getForm();
- // Check to see if the user wants to ignore this alert
- if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO)
- {
- return LLUI::sSettingGroups["ignores"]->getBOOL(notification->getName());
- }
-
- return true;
-}
-
-bool handleIgnoredNotification(const LLSD& payload)
-{
- if (payload["sigtype"].asString() == "add")
- {
- LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
- if (!pNotif) return false;
-
- LLNotificationFormPtr form = pNotif->getForm();
- LLSD response;
- switch(form->getIgnoreType())
- {
- case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE:
- response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON);
- break;
- case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE:
- response = LLUI::sSettingGroups["ignores"]->getLLSD("Default" + pNotif->getName());
- break;
- case LLNotificationForm::IGNORE_SHOW_AGAIN:
- break;
- default:
- return false;
- }
- pNotif->setIgnored(true);
- pNotif->respond(response);
- return true; // don't process this item any further
- }
- return false;
-}
-
-namespace LLNotificationFilters
-{
- // a sample filter
- bool includeEverything(LLNotificationPtr p)
- {
- return true;
- }
-};
-
-LLNotificationForm::LLNotificationForm()
-: mFormData(LLSD::emptyArray()),
- mIgnore(IGNORE_NO)
-{
-}
-
-
-LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node)
-: mFormData(LLSD::emptyArray()),
- mIgnore(IGNORE_NO)
-{
- if (!xml_node->hasName("form"))
- {
- llwarns << "Bad xml node for form: " << xml_node->getName() << llendl;
- }
- LLXMLNodePtr child = xml_node->getFirstChild();
- while(child)
- {
- child = LLNotifications::instance().checkForXMLTemplate(child);
-
- LLSD item_entry;
- std::string element_name = child->getName()->mString;
-
- if (element_name == "ignore" )
- {
- bool save_option = false;
- child->getAttribute_bool("save_option", save_option);
- if (!save_option)
- {
- mIgnore = IGNORE_WITH_DEFAULT_RESPONSE;
- }
- else
- {
- // remember last option chosen by user and automatically respond with that in the future
- mIgnore = IGNORE_WITH_LAST_RESPONSE;
- LLUI::sSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
- }
- child->getAttributeString("text", mIgnoreMsg);
- BOOL show_notification = TRUE;
- LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE);
- }
- else
- {
- // flatten xml form entry into single LLSD map with type==name
- item_entry["type"] = element_name;
- const LLXMLAttribList::iterator attrib_end = child->mAttributes.end();
- for(LLXMLAttribList::iterator attrib_it = child->mAttributes.begin();
- attrib_it != attrib_end;
- ++attrib_it)
- {
- item_entry[std::string(attrib_it->second->getName()->mString)] = attrib_it->second->getValue();
- }
- item_entry["value"] = child->getTextContents();
- mFormData.append(item_entry);
- }
-
- child = child->getNextSibling();
- }
-}
-
-LLNotificationForm::LLNotificationForm(const LLSD& sd)
-{
- if (sd.isArray())
- {
- mFormData = sd;
- }
- else
- {
- llwarns << "Invalid form data " << sd << llendl;
- mFormData = LLSD::emptyArray();
- }
-}
-
-LLSD LLNotificationForm::asLLSD() const
-{
- return mFormData;
-}
-
-LLSD LLNotificationForm::getElement(const std::string& element_name)
-{
- for (LLSD::array_const_iterator it = mFormData.beginArray();
- it != mFormData.endArray();
- ++it)
- {
- if ((*it)["name"].asString() == element_name) return (*it);
- }
- return LLSD();
-}
-
-
-bool LLNotificationForm::hasElement(const std::string& element_name)
-{
- for (LLSD::array_const_iterator it = mFormData.beginArray();
- it != mFormData.endArray();
- ++it)
- {
- if ((*it)["name"].asString() == element_name) return true;
- }
- return false;
-}
-
-void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value)
-{
- LLSD element;
- element["type"] = type;
- element["name"] = name;
- element["text"] = name;
- element["value"] = value;
- element["index"] = mFormData.size();
- mFormData.append(element);
-}
-
-void LLNotificationForm::append(const LLSD& sub_form)
-{
- if (sub_form.isArray())
- {
- for (LLSD::array_const_iterator it = sub_form.beginArray();
- it != sub_form.endArray();
- ++it)
- {
- mFormData.append(*it);
- }
- }
-}
-
-void LLNotificationForm::formatElements(const LLSD& substitutions)
-{
- for (LLSD::array_iterator it = mFormData.beginArray();
- it != mFormData.endArray();
- ++it)
- {
- // format "text" component of each form element
- if ((*it).has("text"))
- {
- std::string text = (*it)["text"].asString();
- LLStringUtil::format(text, substitutions);
- (*it)["text"] = text;
- }
- if ((*it)["type"].asString() == "text" && (*it).has("value"))
- {
- std::string value = (*it)["value"].asString();
- LLStringUtil::format(value, substitutions);
- (*it)["value"] = value;
- }
- }
-}
-
-std::string LLNotificationForm::getDefaultOption()
-{
- for (LLSD::array_const_iterator it = mFormData.beginArray();
- it != mFormData.endArray();
- ++it)
- {
- if ((*it)["default"]) return (*it)["name"].asString();
- }
- return "";
-}
-
-LLNotificationTemplate::LLNotificationTemplate() :
- mExpireSeconds(0),
- mExpireOption(-1),
- mURLOption(-1),
- mURLOpenExternally(-1),
- mUnique(false),
- mPriority(NOTIFICATION_PRIORITY_NORMAL)
-{
- mForm = LLNotificationFormPtr(new LLNotificationForm());
-}
-
-LLNotification::LLNotification(const LLNotification::Params& p) :
- mTimestamp(p.time_stamp),
- mSubstitutions(p.substitutions),
- mPayload(p.payload),
- mExpiresAt(0),
- mTemporaryResponder(false),
- mRespondedTo(false),
- mPriority(p.priority),
- mCancelled(false),
- mIgnored(false)
-{
- if (p.functor.name.isChosen())
- {
- mResponseFunctorName = p.functor.name;
- }
- else if (p.functor.function.isChosen())
- {
- mResponseFunctorName = LLUUID::generateNewID().asString();
- LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, p.functor.function());
-
- mTemporaryResponder = true;
- }
-
- mId.generate();
- init(p.name, p.form_elements);
-}
-
-
-LLNotification::LLNotification(const LLSD& sd) :
- mTemporaryResponder(false),
- mRespondedTo(false),
- mCancelled(false),
- mIgnored(false)
-{
- mId.generate();
- mSubstitutions = sd["substitutions"];
- mPayload = sd["payload"];
- mTimestamp = sd["time"];
- mExpiresAt = sd["expiry"];
- mPriority = (ENotificationPriority)sd["priority"].asInteger();
- mResponseFunctorName = sd["responseFunctor"].asString();
- std::string templatename = sd["name"].asString();
- init(templatename, LLSD());
- // replace form with serialized version
- mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"]));
-}
-
-
-LLSD LLNotification::asLLSD()
-{
- LLSD output;
- output["name"] = mTemplatep->mName;
- output["form"] = getForm()->asLLSD();
- output["substitutions"] = mSubstitutions;
- output["payload"] = mPayload;
- output["time"] = mTimestamp;
- output["expiry"] = mExpiresAt;
- output["priority"] = (S32)mPriority;
- output["responseFunctor"] = mResponseFunctorName;
- return output;
-}
-
-void LLNotification::update()
-{
- LLNotifications::instance().update(shared_from_this());
-}
-
-void LLNotification::updateFrom(LLNotificationPtr other)
-{
- // can only update from the same notification type
- if (mTemplatep != other->mTemplatep) return;
-
- // NOTE: do NOT change the ID, since it is the key to
- // this given instance, just update all the metadata
- //mId = other->mId;
-
- mPayload = other->mPayload;
- mSubstitutions = other->mSubstitutions;
- mTimestamp = other->mTimestamp;
- mExpiresAt = other->mExpiresAt;
- mCancelled = other->mCancelled;
- mIgnored = other->mIgnored;
- mPriority = other->mPriority;
- mForm = other->mForm;
- mResponseFunctorName = other->mResponseFunctorName;
- mRespondedTo = other->mRespondedTo;
- mTemporaryResponder = other->mTemporaryResponder;
-
- update();
-}
-
-const LLNotificationFormPtr LLNotification::getForm()
-{
- return mForm;
-}
-
-void LLNotification::cancel()
-{
- mCancelled = true;
-}
-
-LLSD LLNotification::getResponseTemplate(EResponseTemplateType type)
-{
- LLSD response = LLSD::emptyMap();
- for (S32 element_idx = 0;
- element_idx < mForm->getNumElements();
- ++element_idx)
- {
- LLSD element = mForm->getElement(element_idx);
- if (element.has("name"))
- {
- response[element["name"].asString()] = element["value"];
- }
-
- if ((type == WITH_DEFAULT_BUTTON)
- && element["default"].asBoolean())
- {
- response[element["name"].asString()] = true;
- }
- }
- return response;
-}
-
-//static
-S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
-{
- LLNotificationForm form(notification["form"]);
-
- for (S32 element_idx = 0;
- element_idx < form.getNumElements();
- ++element_idx)
- {
- LLSD element = form.getElement(element_idx);
-
- // only look at buttons
- if (element["type"].asString() == "button"
- && response[element["name"].asString()].asBoolean())
- {
- return element["index"].asInteger();
- }
- }
-
- return -1;
-}
-
-//static
-std::string LLNotification::getSelectedOptionName(const LLSD& response)
-{
- for (LLSD::map_const_iterator response_it = response.beginMap();
- response_it != response.endMap();
- ++response_it)
- {
- if (response_it->second.isBoolean() && response_it->second.asBoolean())
- {
- return response_it->first;
- }
- }
- return "";
-}
-
-
-void LLNotification::respond(const LLSD& response)
-{
- mRespondedTo = true;
- // look up the functor
- LLNotificationFunctorRegistry::ResponseFunctor functor =
- LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName);
- // and then call it
- functor(asLLSD(), response);
-
- if (mTemporaryResponder)
- {
- LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
- mResponseFunctorName = "";
- mTemporaryResponder = false;
- }
-
- if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
- {
- BOOL show_notification = mIgnored ? FALSE : TRUE;
- LLUI::sSettingGroups["ignores"]->setBOOL(getName(), show_notification);
- if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
- {
- LLUI::sSettingGroups["ignores"]->setLLSD("Default" + getName(), response);
- }
- }
-
- update();
-}
-
-void LLNotification::setIgnored(bool ignore)
-{
- mIgnored = ignore;
-}
-
-void LLNotification::setResponseFunctor(std::string const &responseFunctorName)
-{
- if (mTemporaryResponder)
- // get rid of the old one
- LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
- mResponseFunctorName = responseFunctorName;
- mTemporaryResponder = false;
-}
-
-bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const
-{
- for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin();
- required_fields_it != required_fields.end();
- required_fields_it++)
- {
- std::string required_field_name = *required_fields_it;
- if( ! getPayload().has(required_field_name))
- {
- return false; // a required field was not found
- }
- }
- return true; // all required fields were found
-}
-
-bool LLNotification::isEquivalentTo(LLNotificationPtr that) const
-{
- if (this->mTemplatep->mName != that->mTemplatep->mName)
- {
- return false; // must have the same template name or forget it
- }
- if (this->mTemplatep->mUnique)
- {
- // highlander bit sez there can only be one of these
- return
- this->payloadContainsAll(that->mTemplatep->mUniqueContext) &&
- that->payloadContainsAll(this->mTemplatep->mUniqueContext);
- }
- return false;
-}
-
-void LLNotification::init(const std::string& template_name, const LLSD& form_elements)
-{
- mTemplatep = LLNotifications::instance().getTemplate(template_name);
- if (!mTemplatep) return;
-
- // add default substitutions
- const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs();
- for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin();
- iter != default_args.end(); ++iter)
- {
- mSubstitutions[iter->first] = iter->second;
- }
- mSubstitutions["_URL"] = getURL();
- mSubstitutions["_NAME"] = template_name;
- // TODO: something like this so that a missing alert is sensible:
- //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions);
-
- mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm));
- mForm->append(form_elements);
-
- // apply substitution to form labels
- mForm->formatElements(mSubstitutions);
-
- LLDate rightnow = LLDate::now();
- if (mTemplatep->mExpireSeconds)
- {
- mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds);
- }
-
- if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED)
- {
- mPriority = mTemplatep->mPriority;
- }
-}
-
-std::string LLNotification::summarize() const
-{
- std::string s = "Notification(";
- s += getName();
- s += ") : ";
- s += mTemplatep ? mTemplatep->mMessage : "";
- // should also include timestamp and expiration time (but probably not payload)
- return s;
-}
-
-std::string LLNotification::getMessage() const
-{
- // all our callers cache this result, so it gives us more flexibility
- // to do the substitution at call time rather than attempting to
- // cache it in the notification
- if (!mTemplatep)
- return std::string();
-
- std::string message = mTemplatep->mMessage;
- LLStringUtil::format(message, mSubstitutions);
- return message;
-}
-
-std::string LLNotification::getLabel() const
-{
- std::string label = mTemplatep->mLabel;
- LLStringUtil::format(label, mSubstitutions);
- return (mTemplatep ? label : "");
-}
-
-std::string LLNotification::getURL() const
-{
- if (!mTemplatep)
- return std::string();
- std::string url = mTemplatep->mURL;
- LLStringUtil::format(url, mSubstitutions);
- return (mTemplatep ? url : "");
-}
-
-// =========================================================
-// LLNotificationChannel implementation
-// ---
-LLBoundListener LLNotificationChannelBase::connectChangedImpl(const LLEventListener& slot)
-{
- // when someone wants to connect to a channel, we first throw them
- // all of the notifications that are already in the channel
- // we use a special signal called "load" in case the channel wants to care
- // only about new notifications
- for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
- {
- slot(LLSD().insert("sigtype", "load").insert("id", (*it)->id()));
- }
- // and then connect the signal so that all future notifications will also be
- // forwarded.
- return mChanged.connect(slot);
-}
-
-LLBoundListener LLNotificationChannelBase::connectAtFrontChangedImpl(const LLEventListener& slot)
-{
- for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
- {
- slot(LLSD().insert("sigtype", "load").insert("id", (*it)->id()));
- }
- return mChanged.connect(slot, boost::signals2::at_front);
-}
-
-LLBoundListener LLNotificationChannelBase::connectPassedFilterImpl(const LLEventListener& slot)
-{
- // these two filters only fire for notifications added after the current one, because
- // they don't participate in the hierarchy.
- return mPassedFilter.connect(slot);
-}
-
-LLBoundListener LLNotificationChannelBase::connectFailedFilterImpl(const LLEventListener& slot)
-{
- return mFailedFilter.connect(slot);
-}
-
-// external call, conforms to our standard signature
-bool LLNotificationChannelBase::updateItem(const LLSD& payload)
-{
- // first check to see if it's in the master list
- LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]);
- if (!pNotification)
- return false; // not found
-
- return updateItem(payload, pNotification);
-}
-
-
-//FIX QUIT NOT WORKING
-
-
-// internal call, for use in avoiding lookup
-bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPtr pNotification)
-{
- std::string cmd = payload["sigtype"];
- LLNotificationSet::iterator foundItem = mItems.find(pNotification);
- bool wasFound = (foundItem != mItems.end());
- bool passesFilter = mFilter(pNotification);
-
- // first, we offer the result of the filter test to the simple
- // signals for pass/fail. One of these is guaranteed to be called.
- // If either signal returns true, the change processing is NOT performed
- // (so don't return true unless you know what you're doing!)
- bool abortProcessing = false;
- if (passesFilter)
- {
- abortProcessing = mPassedFilter(payload);
- }
- else
- {
- abortProcessing = mFailedFilter(payload);
- }
-
- if (abortProcessing)
- {
- return true;
- }
-
- if (cmd == "load")
- {
- // should be no reason we'd ever get a load if we already have it
- // if passes filter send a load message, else do nothing
- assert(!wasFound);
- if (passesFilter)
- {
- // not in our list, add it and say so
- mItems.insert(pNotification);
- abortProcessing = mChanged(payload);
- onLoad(pNotification);
- }
- }
- else if (cmd == "change")
- {
- // if it passes filter now and was found, we just send a change message
- // if it passes filter now and wasn't found, we have to add it
- // if it doesn't pass filter and wasn't found, we do nothing
- // if it doesn't pass filter and was found, we need to delete it
- if (passesFilter)
- {
- if (wasFound)
- {
- // it already existed, so this is a change
- // since it changed in place, all we have to do is resend the signal
- abortProcessing = mChanged(payload);
- onChange(pNotification);
- }
- else
- {
- // not in our list, add it and say so
- mItems.insert(pNotification);
- // our payload is const, so make a copy before changing it
- LLSD newpayload = payload;
- newpayload["sigtype"] = "add";
- abortProcessing = mChanged(newpayload);
- onChange(pNotification);
- }
- }
- else
- {
- if (wasFound)
- {
- // it already existed, so this is a delete
- mItems.erase(pNotification);
- // our payload is const, so make a copy before changing it
- LLSD newpayload = payload;
- newpayload["sigtype"] = "delete";
- abortProcessing = mChanged(newpayload);
- onChange(pNotification);
- }
- // didn't pass, not on our list, do nothing
- }
- }
- else if (cmd == "add")
- {
- // should be no reason we'd ever get an add if we already have it
- // if passes filter send an add message, else do nothing
- assert(!wasFound);
- if (passesFilter)
- {
- // not in our list, add it and say so
- mItems.insert(pNotification);
- abortProcessing = mChanged(payload);
- onAdd(pNotification);
- }
- }
- else if (cmd == "delete")
- {
- // if we have it in our list, pass on the delete, then delete it, else do nothing
- if (wasFound)
- {
- abortProcessing = mChanged(payload);
- mItems.erase(pNotification);
- onDelete(pNotification);
- }
- }
- return abortProcessing;
-}
-
-/* static */
-LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name,
- const std::string& parent,
- LLNotificationFilter filter,
- LLNotificationComparator comparator)
-{
- // note: this is not a leak; notifications are self-registering.
- // This factory helps to prevent excess deletions by making sure all smart
- // pointers to notification channels come from the same source
- new LLNotificationChannel(name, parent, filter, comparator);
- return LLNotifications::instance().getChannel(name);
-}
-
-
-LLNotificationChannel::LLNotificationChannel(const std::string& name,
- const std::string& parent,
- LLNotificationFilter filter,
- LLNotificationComparator comparator) :
-LLNotificationChannelBase(filter, comparator),
-mName(name),
-mParent(parent)
-{
- // store myself in the channel map
- LLNotifications::instance().addChannel(LLNotificationChannelPtr(this));
- // bind to notification broadcast
- if (parent.empty())
- {
- LLNotifications::instance().connectChanged(
- boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
- }
- else
- {
- LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent);
- p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
- }
-}
-
-
-void LLNotificationChannel::setComparator(LLNotificationComparator comparator)
-{
- mComparator = comparator;
- LLNotificationSet s2(mComparator);
- s2.insert(mItems.begin(), mItems.end());
- mItems.swap(s2);
-
- // notify clients that we've been resorted
- mChanged(LLSD().insert("sigtype", "sort"));
-}
-
-bool LLNotificationChannel::isEmpty() const
-{
- return mItems.empty();
-}
-
-LLNotificationChannel::Iterator LLNotificationChannel::begin()
-{
- return mItems.begin();
-}
-
-LLNotificationChannel::Iterator LLNotificationChannel::end()
-{
- return mItems.end();
-}
-
-std::string LLNotificationChannel::summarize()
-{
- std::string s("Channel '");
- s += mName;
- s += "'\n ";
- for (LLNotificationChannel::Iterator it = begin(); it != end(); ++it)
- {
- s += (*it)->summarize();
- s += "\n ";
- }
- return s;
-}
-
-
-// ---
-// END OF LLNotificationChannel implementation
-// =========================================================
-
-
-// =========================================================
-// LLNotifications implementation
-// ---
-LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
- LLNotificationComparators::orderByUUID()),
- mIgnoreAllNotifications(false)
-{
- LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
-
- mListener.reset(new LLNotificationsListener(*this));
-}
-
-
-// The expiration channel gets all notifications that are cancelled
-bool LLNotifications::expirationFilter(LLNotificationPtr pNotification)
-{
- return pNotification->isCancelled() || pNotification->isRespondedTo();
-}
-
-bool LLNotifications::expirationHandler(const LLSD& payload)
-{
- if (payload["sigtype"].asString() != "delete")
- {
- // anything added to this channel actually should be deleted from the master
- cancel(find(payload["id"]));
- return true; // don't process this item any further
- }
- return false;
-}
-
-bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)
-{
- if (!pNotif->hasUniquenessConstraints())
- {
- return true;
- }
-
- // checks against existing unique notifications
- for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
- existing_it != mUniqueNotifications.end();
- ++existing_it)
- {
- LLNotificationPtr existing_notification = existing_it->second;
- if (pNotif != existing_notification
- && pNotif->isEquivalentTo(existing_notification))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool LLNotifications::uniqueHandler(const LLSD& payload)
-{
- LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
- if (pNotif && pNotif->hasUniquenessConstraints())
- {
- if (payload["sigtype"].asString() == "add")
- {
- // not a duplicate according to uniqueness criteria, so we keep it
- // and store it for future uniqueness checks
- mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif));
- }
- else if (payload["sigtype"].asString() == "delete")
- {
- mUniqueNotifications.erase(pNotif->getName());
- }
- }
-
- return false;
-}
-
-bool LLNotifications::failedUniquenessTest(const LLSD& payload)
-{
- LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
-
- if (!pNotif || !pNotif->hasUniquenessConstraints())
- {
- return false;
- }
-
- // checks against existing unique notifications
- for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
- existing_it != mUniqueNotifications.end();
- ++existing_it)
- {
- LLNotificationPtr existing_notification = existing_it->second;
- if (pNotif != existing_notification
- && pNotif->isEquivalentTo(existing_notification))
- {
- // copy notification instance data over to oldest instance
- // of this unique notification and update it
- existing_notification->updateFrom(pNotif);
- // then delete the new one
- pNotif->cancel();
- }
- }
-
- return false;
-}
-
-
-void LLNotifications::addChannel(LLNotificationChannelPtr pChan)
-{
- mChannels[pChan->getName()] = pChan;
-}
-
-LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)
-{
- ChannelMap::iterator p = mChannels.find(channelName);
- if(p == mChannels.end())
- {
- llerrs << "Did not find channel named " << channelName << llendl;
- }
- return p->second;
-}
-
-
-// this function is called once at construction time, after the object is constructed.
-void LLNotifications::initSingleton()
-{
- loadTemplates();
- createDefaultChannels();
-}
-
-void LLNotifications::createDefaultChannels()
-{
- // now construct the various channels AFTER loading the notifications,
- // because the history channel is going to rewrite the stored notifications file
- LLNotificationChannel::buildChannel("Expiration", "",
- boost::bind(&LLNotifications::expirationFilter, this, _1));
- LLNotificationChannel::buildChannel("Unexpired", "",
- !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind
- LLNotificationChannel::buildChannel("Unique", "Unexpired",
- boost::bind(&LLNotifications::uniqueFilter, this, _1));
- LLNotificationChannel::buildChannel("Ignore", "Unique",
- filterIgnoredNotifications);
- LLNotificationChannel::buildChannel("Visible", "Ignore",
- &LLNotificationFilters::includeEverything);
-
- // create special history channel
- //std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" );
- // use ^^^ when done debugging notifications serialization
- std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" );
- // this isn't a leak, don't worry about the empty "new"
- new LLNotificationHistoryChannel(notifications_log_file);
-
- // connect action methods to these channels
- LLNotifications::instance().getChannel("Expiration")->
- connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1));
- // uniqueHandler slot should be added as first slot of the signal due to
- // usage LLStopWhenHandled combiner in LLStandardSignal
- LLNotifications::instance().getChannel("Unique")->
- connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1));
-// failedUniquenessTest slot isn't necessary
-// LLNotifications::instance().getChannel("Unique")->
-// connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1));
- LLNotifications::instance().getChannel("Ignore")->
- connectFailedFilter(&handleIgnoredNotification);
-}
-
-bool LLNotifications::addTemplate(const std::string &name,
- LLNotificationTemplatePtr theTemplate)
-{
- if (mTemplates.count(name))
- {
- llwarns << "LLNotifications -- attempted to add template '" << name << "' twice." << llendl;
- return false;
- }
- mTemplates[name] = theTemplate;
- return true;
-}
-
-LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name)
-{
- if (mTemplates.count(name))
- {
- return mTemplates[name];
- }
- else
- {
- return mTemplates["MissingAlert"];
- }
-}
-
-bool LLNotifications::templateExists(const std::string& name)
-{
- return (mTemplates.count(name) != 0);
-}
-
-void LLNotifications::clearTemplates()
-{
- mTemplates.clear();
-}
-
-void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option)
-{
- LLNotificationPtr temp_notify(new LLNotification(params));
- LLSD response = temp_notify->getResponseTemplate();
- LLSD selected_item = temp_notify->getForm()->getElement(option);
-
- if (selected_item.isUndefined())
- {
- llwarns << "Invalid option" << option << " for notification " << (std::string)params.name << llendl;
- return;
- }
- response[selected_item["name"].asString()] = true;
-
- temp_notify->respond(response);
-}
-
-LLNotifications::TemplateNames LLNotifications::getTemplateNames() const
-{
- TemplateNames names;
- for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it)
- {
- names.push_back(it->first);
- }
- return names;
-}
-
-typedef std::map<std::string, std::string> StringMap;
-void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
-{
- //llwarns << "replaceSubstitutionStrings" << llendl;
- // walk the list of attributes looking for replacements
- for (LLXMLAttribList::iterator it=node->mAttributes.begin();
- it != node->mAttributes.end(); ++it)
- {
- std::string value = it->second->getValue();
- if (value[0] == '$')
- {
- value.erase(0, 1); // trim off the $
- std::string replacement;
- StringMap::const_iterator found = replacements.find(value);
- if (found != replacements.end())
- {
- replacement = found->second;
- //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl;
-
- it->second->setValue(replacement);
- }
- else
- {
- llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl;
- }
- }
- }
-
- // now walk the list of children and call this recursively.
- for (LLXMLNodePtr child = node->getFirstChild();
- child.notNull(); child = child->getNextSibling())
- {
- replaceSubstitutionStrings(child, replacements);
- }
-}
-
-// private to this file
-// returns true if the template request was invalid and there's nothing else we
-// can do with this node, false if you should keep processing (it may have
-// replaced the contents of the node referred to)
-LLXMLNodePtr LLNotifications::checkForXMLTemplate(LLXMLNodePtr item)
-{
- if (item->hasName("usetemplate"))
- {
- std::string replacementName;
- if (item->getAttributeString("name", replacementName))
- {
- StringMap replacements;
- for (LLXMLAttribList::const_iterator it=item->mAttributes.begin();
- it != item->mAttributes.end(); ++it)
- {
- replacements[it->second->getName()->mString] = it->second->getValue();
- }
- if (mXmlTemplates.count(replacementName))
- {
- item=LLXMLNode::replaceNode(item, mXmlTemplates[replacementName]);
-
- // walk the nodes looking for $(substitution) here and replace
- replaceSubstitutionStrings(item, replacements);
- }
- else
- {
- llwarns << "XML template lookup failure on '" << replacementName << "' " << llendl;
- }
- }
- }
- return item;
-}
-
-bool LLNotifications::loadTemplates()
-{
- const std::string xml_filename = "notifications.xml";
- LLXMLNodePtr root;
-
- BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
-
- if (!success || root.isNull() || !root->hasName( "notifications" ))
- {
- llerrs << "Problem reading UI Notifications file: " << xml_filename << llendl;
- return false;
- }
-
- clearTemplates();
-
- for (LLXMLNodePtr item = root->getFirstChild();
- item.notNull(); item = item->getNextSibling())
- {
- // we do this FIRST so that item can be changed if we
- // encounter a usetemplate -- we just replace the
- // current xml node and keep processing
- item = checkForXMLTemplate(item);
-
- if (item->hasName("global"))
- {
- std::string global_name;
- if (item->getAttributeString("name", global_name))
- {
- mGlobalStrings[global_name] = item->getTextContents();
- }
- continue;
- }
-
- if (item->hasName("template"))
- {
- // store an xml template; templates must have a single node (can contain
- // other nodes)
- std::string name;
- item->getAttributeString("name", name);
- LLXMLNodePtr ptr = item->getFirstChild();
- mXmlTemplates[name] = ptr;
- continue;
- }
-
- if (!item->hasName("notification"))
- {
- llwarns << "Unexpected entity " << item->getName()->mString <<
- " found in " << xml_filename << llendl;
- continue;
- }
-
- // now we know we have a notification entry, so let's build it
- LLNotificationTemplatePtr pTemplate(new LLNotificationTemplate());
-
- if (!item->getAttributeString("name", pTemplate->mName))
- {
- llwarns << "Unable to parse notification with no name" << llendl;
- continue;
- }
-
- //llinfos << "Parsing " << pTemplate->mName << llendl;
-
- pTemplate->mMessage = item->getTextContents();
- pTemplate->mDefaultFunctor = pTemplate->mName;
- item->getAttributeString("type", pTemplate->mType);
- item->getAttributeString("icon", pTemplate->mIcon);
- item->getAttributeString("label", pTemplate->mLabel);
- item->getAttributeU32("duration", pTemplate->mExpireSeconds);
- item->getAttributeU32("expireOption", pTemplate->mExpireOption);
-
- std::string priority;
- item->getAttributeString("priority", priority);
- pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
- if (!priority.empty())
- {
- if (priority == "low") pTemplate->mPriority = NOTIFICATION_PRIORITY_LOW;
- if (priority == "normal") pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
- if (priority == "high") pTemplate->mPriority = NOTIFICATION_PRIORITY_HIGH;
- if (priority == "critical") pTemplate->mPriority = NOTIFICATION_PRIORITY_CRITICAL;
- }
-
- item->getAttributeString("functor", pTemplate->mDefaultFunctor);
-
- BOOL persist = false;
- item->getAttributeBOOL("persist", persist);
- pTemplate->mPersist = persist;
-
- std::string sound;
- item->getAttributeString("sound", sound);
- if (!sound.empty())
- {
- // test for bad sound effect name / missing effect
- if (LLUI::sSettingGroups["config"]->controlExists(sound))
- {
- pTemplate->mSoundEffect =
- LLUUID(LLUI::sSettingGroups["config"]->getString(sound));
- }
- else
- {
- llwarns << "Unknown sound effect control name " << sound
- << llendl;
- }
- }
-
- for (LLXMLNodePtr child = item->getFirstChild();
- !child.isNull(); child = child->getNextSibling())
- {
- child = checkForXMLTemplate(child);
-
- // <url>
- if (child->hasName("url"))
- {
- pTemplate->mURL = child->getTextContents();
- child->getAttributeU32("option", pTemplate->mURLOption);
- child->getAttributeU32("openexternally", pTemplate->mURLOpenExternally);
- }
-
- if (child->hasName("unique"))
- {
- pTemplate->mUnique = true;
- for (LLXMLNodePtr formitem = child->getFirstChild();
- !formitem.isNull(); formitem = formitem->getNextSibling())
- {
- if (formitem->hasName("context"))
- {
- std::string key;
- formitem->getAttributeString("key", key);
- pTemplate->mUniqueContext.push_back(key);
- //llwarns << "adding " << key << " to unique context" << llendl;
- }
- else
- {
- llwarns << "'unique' has unrecognized subelement "
- << formitem->getName()->mString << llendl;
- }
- }
- }
-
- // <form>
- if (child->hasName("form"))
- {
- pTemplate->mForm = LLNotificationFormPtr(new LLNotificationForm(pTemplate->mName, child));
- }
- }
- addTemplate(pTemplate->mName, pTemplate);
- }
-
- //std::ostringstream ostream;
- //root->writeToOstream(ostream, "\n ");
- //llwarns << ostream.str() << llendl;
-
- return true;
-}
-
-// Add a simple notification (from XUI)
-void LLNotifications::addFromCallback(const LLSD& name)
-{
- add(LLNotification::Params().name(name.asString()));
-}
-
-// we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line
-LLNotificationPtr LLNotifications::add(const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload)
-{
- LLNotification::Params::Functor functor_p;
- functor_p.name = name;
- return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
-}
-
-LLNotificationPtr LLNotifications::add(const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload,
- const std::string& functor_name)
-{
- LLNotification::Params::Functor functor_p;
- functor_p.name = functor_name;
- return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
-}
-
-LLNotificationPtr LLNotifications::add(const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload,
- LLNotificationFunctorRegistry::ResponseFunctor functor)
-{
- LLNotification::Params::Functor functor_p;
- functor_p.function = functor;
- return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
-}
-
-// generalized add function that takes a parameter block object for more complex instantiations
-LLNotificationPtr LLNotifications::add(const LLNotification::Params& p)
-{
- LLNotificationPtr pNotif(new LLNotification(p));
- add(pNotif);
- return pNotif;
-}
-
-
-void LLNotifications::add(const LLNotificationPtr pNotif)
-{
- // first see if we already have it -- if so, that's a problem
- LLNotificationSet::iterator it=mItems.find(pNotif);
- if (it != mItems.end())
- {
- llerrs << "Notification added a second time to the master notification channel." << llendl;
- }
-
- updateItem(LLSD().insert("sigtype", "add").insert("id", pNotif->id()), pNotif);
-}
-
-void LLNotifications::cancel(LLNotificationPtr pNotif)
-{
- LLNotificationSet::iterator it=mItems.find(pNotif);
- if (it == mItems.end())
- {
- llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl;
- }
- pNotif->cancel();
- updateItem(LLSD().insert("sigtype", "delete").insert("id", pNotif->id()), pNotif);
-}
-
-void LLNotifications::update(const LLNotificationPtr pNotif)
-{
- LLNotificationSet::iterator it=mItems.find(pNotif);
- if (it != mItems.end())
- {
- updateItem(LLSD().insert("sigtype", "change").insert("id", pNotif->id()), pNotif);
- }
-}
-
-
-LLNotificationPtr LLNotifications::find(LLUUID uuid)
-{
- LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid));
- LLNotificationSet::iterator it=mItems.find(target);
- if (it == mItems.end())
- {
- llwarns << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl;
- return LLNotificationPtr((LLNotification*)NULL);
- }
- else
- {
- return *it;
- }
-}
-
-void LLNotifications::forEachNotification(NotificationProcess process)
-{
- std::for_each(mItems.begin(), mItems.end(), process);
-}
-
-std::string LLNotifications::getGlobalString(const std::string& key) const
-{
- GlobalStringMap::const_iterator it = mGlobalStrings.find(key);
- if (it != mGlobalStrings.end())
- {
- return it->second;
- }
- else
- {
- // if we don't have the key as a global, return the key itself so that the error
- // is self-diagnosing.
- return key;
- }
-}
-
-void LLNotifications::setIgnoreAllNotifications(bool setting)
-{
- mIgnoreAllNotifications = setting;
-}
-bool LLNotifications::getIgnoreAllNotifications()
-{
- return mIgnoreAllNotifications;
-}
-
-// ---
-// END OF LLNotifications implementation
-// =========================================================
-
-std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
-{
- s << notification.summarize();
- return s;
-}
-
+/** +* @file llnotifications.cpp +* @brief Non-UI queue manager for keeping a prioritized list of notifications +* +* $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 "linden_common.h" + +#include "llnotifications.h" + +#include "llxmlnode.h" +#include "lluictrl.h" +#include "lluictrlfactory.h" +#include "lldir.h" +#include "llsdserialize.h" +#include "lltrans.h" +#include "llnotificationslistener.h" + +#include <algorithm> +#include <boost/regex.hpp> + + +const std::string NOTIFICATION_PERSIST_VERSION = "0.93"; + +// local channel for notification history +class LLNotificationHistoryChannel : public LLNotificationChannel +{ + LOG_CLASS(LLNotificationHistoryChannel); +public: + LLNotificationHistoryChannel(const std::string& filename) : + LLNotificationChannel("History", "Visible", &historyFilter, LLNotificationComparators::orderByUUID()), + mFileName(filename) + { + connectChanged(boost::bind(&LLNotificationHistoryChannel::historyHandler, this, _1)); + loadPersistentNotifications(); + } + +private: + bool historyHandler(const LLSD& payload) + { + // we ignore "load" messages, but rewrite the persistence file on any other + std::string sigtype = payload["sigtype"]; + if (sigtype != "load") + { + savePersistentNotifications(); + } + return false; + } + + // The history channel gets all notifications except those that have been cancelled + static bool historyFilter(LLNotificationPtr pNotification) + { + return !pNotification->isCancelled(); + } + + void savePersistentNotifications() + { + llinfos << "Saving open notifications to " << mFileName << llendl; + + llofstream notify_file(mFileName.c_str()); + if (!notify_file.is_open()) + { + llwarns << "Failed to open " << mFileName << llendl; + return; + } + + LLSD output; + output["version"] = NOTIFICATION_PERSIST_VERSION; + LLSD& data = output["data"]; + + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + if (!LLNotifications::instance().templateExists((*it)->getName())) continue; + + // only store notifications flagged as persisting + LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate((*it)->getName()); + if (!templatep->mPersist) continue; + + data.append((*it)->asLLSD()); + } + + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); + } + + void loadPersistentNotifications() + { + llinfos << "Loading open notifications from " << mFileName << llendl; + + llifstream notify_file(mFileName.c_str()); + if (!notify_file.is_open()) + { + llwarns << "Failed to open " << mFileName << llendl; + return; + } + + LLSD input; + LLPointer<LLSDParser> parser = new LLSDXMLParser(); + if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) + { + llwarns << "Failed to parse open notifications" << llendl; + return; + } + + if (input.isUndefined()) return; + std::string version = input["version"]; + if (version != NOTIFICATION_PERSIST_VERSION) + { + llwarns << "Bad open notifications version: " << version << llendl; + return; + } + LLSD& data = input["data"]; + if (data.isUndefined()) return; + + LLNotifications& instance = LLNotifications::instance(); + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + instance.add(LLNotificationPtr(new LLNotification(*notification_it))); + } + } + + //virtual + void onDelete(LLNotificationPtr pNotification) + { + // we want to keep deleted notifications in our log + mItems.insert(pNotification); + + return; + } + +private: + std::string mFileName; +}; + +bool filterIgnoredNotifications(LLNotificationPtr notification) +{ + // filter everything if we are to ignore ALL + if(LLNotifications::instance().getIgnoreAllNotifications()) + { + return false; + } + + LLNotificationFormPtr form = notification->getForm(); + // Check to see if the user wants to ignore this alert + if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO) + { + return LLUI::sSettingGroups["ignores"]->getBOOL(notification->getName()); + } + + return true; +} + +bool handleIgnoredNotification(const LLSD& payload) +{ + if (payload["sigtype"].asString() == "add") + { + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + if (!pNotif) return false; + + LLNotificationFormPtr form = pNotif->getForm(); + LLSD response; + switch(form->getIgnoreType()) + { + case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE: + response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON); + break; + case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE: + response = LLUI::sSettingGroups["ignores"]->getLLSD("Default" + pNotif->getName()); + break; + case LLNotificationForm::IGNORE_SHOW_AGAIN: + break; + default: + return false; + } + pNotif->setIgnored(true); + pNotif->respond(response); + return true; // don't process this item any further + } + return false; +} + +namespace LLNotificationFilters +{ + // a sample filter + bool includeEverything(LLNotificationPtr p) + { + return true; + } +}; + +LLNotificationForm::LLNotificationForm() +: mFormData(LLSD::emptyArray()), + mIgnore(IGNORE_NO) +{ +} + + +LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node) +: mFormData(LLSD::emptyArray()), + mIgnore(IGNORE_NO) +{ + if (!xml_node->hasName("form")) + { + llwarns << "Bad xml node for form: " << xml_node->getName() << llendl; + } + LLXMLNodePtr child = xml_node->getFirstChild(); + while(child) + { + child = LLNotifications::instance().checkForXMLTemplate(child); + + LLSD item_entry; + std::string element_name = child->getName()->mString; + + if (element_name == "ignore" ) + { + bool save_option = false; + child->getAttribute_bool("save_option", save_option); + if (!save_option) + { + mIgnore = IGNORE_WITH_DEFAULT_RESPONSE; + } + else + { + // remember last option chosen by user and automatically respond with that in the future + mIgnore = IGNORE_WITH_LAST_RESPONSE; + LLUI::sSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name)); + } + child->getAttributeString("text", mIgnoreMsg); + BOOL show_notification = TRUE; + LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE); + } + else + { + // flatten xml form entry into single LLSD map with type==name + item_entry["type"] = element_name; + const LLXMLAttribList::iterator attrib_end = child->mAttributes.end(); + for(LLXMLAttribList::iterator attrib_it = child->mAttributes.begin(); + attrib_it != attrib_end; + ++attrib_it) + { + item_entry[std::string(attrib_it->second->getName()->mString)] = attrib_it->second->getValue(); + } + item_entry["value"] = child->getTextContents(); + mFormData.append(item_entry); + } + + child = child->getNextSibling(); + } +} + +LLNotificationForm::LLNotificationForm(const LLSD& sd) +{ + if (sd.isArray()) + { + mFormData = sd; + } + else + { + llwarns << "Invalid form data " << sd << llendl; + mFormData = LLSD::emptyArray(); + } +} + +LLSD LLNotificationForm::asLLSD() const +{ + return mFormData; +} + +LLSD LLNotificationForm::getElement(const std::string& element_name) +{ + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) return (*it); + } + return LLSD(); +} + + +bool LLNotificationForm::hasElement(const std::string& element_name) +{ + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) return true; + } + return false; +} + +void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) +{ + LLSD element; + element["type"] = type; + element["name"] = name; + element["text"] = name; + element["value"] = value; + element["index"] = mFormData.size(); + mFormData.append(element); +} + +void LLNotificationForm::append(const LLSD& sub_form) +{ + if (sub_form.isArray()) + { + for (LLSD::array_const_iterator it = sub_form.beginArray(); + it != sub_form.endArray(); + ++it) + { + mFormData.append(*it); + } + } +} + +void LLNotificationForm::formatElements(const LLSD& substitutions) +{ + for (LLSD::array_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + // format "text" component of each form element + if ((*it).has("text")) + { + std::string text = (*it)["text"].asString(); + LLStringUtil::format(text, substitutions); + (*it)["text"] = text; + } + if ((*it)["type"].asString() == "text" && (*it).has("value")) + { + std::string value = (*it)["value"].asString(); + LLStringUtil::format(value, substitutions); + (*it)["value"] = value; + } + } +} + +std::string LLNotificationForm::getDefaultOption() +{ + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["default"]) return (*it)["name"].asString(); + } + return ""; +} + +LLNotificationTemplate::LLNotificationTemplate() : + mExpireSeconds(0), + mExpireOption(-1), + mURLOption(-1), + mURLOpenExternally(-1), + mUnique(false), + mPriority(NOTIFICATION_PRIORITY_NORMAL) +{ + mForm = LLNotificationFormPtr(new LLNotificationForm()); +} + +LLNotification::LLNotification(const LLNotification::Params& p) : + mTimestamp(p.time_stamp), + mSubstitutions(p.substitutions), + mPayload(p.payload), + mExpiresAt(0), + mTemporaryResponder(false), + mRespondedTo(false), + mPriority(p.priority), + mCancelled(false), + mIgnored(false) +{ + if (p.functor.name.isChosen()) + { + mResponseFunctorName = p.functor.name; + } + else if (p.functor.function.isChosen()) + { + mResponseFunctorName = LLUUID::generateNewID().asString(); + LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, p.functor.function()); + + mTemporaryResponder = true; + } + + mId.generate(); + init(p.name, p.form_elements); +} + + +LLNotification::LLNotification(const LLSD& sd) : + mTemporaryResponder(false), + mRespondedTo(false), + mCancelled(false), + mIgnored(false) +{ + mId.generate(); + mSubstitutions = sd["substitutions"]; + mPayload = sd["payload"]; + mTimestamp = sd["time"]; + mExpiresAt = sd["expiry"]; + mPriority = (ENotificationPriority)sd["priority"].asInteger(); + mResponseFunctorName = sd["responseFunctor"].asString(); + std::string templatename = sd["name"].asString(); + init(templatename, LLSD()); + // replace form with serialized version + mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"])); +} + + +LLSD LLNotification::asLLSD() +{ + LLSD output; + output["name"] = mTemplatep->mName; + output["form"] = getForm()->asLLSD(); + output["substitutions"] = mSubstitutions; + output["payload"] = mPayload; + output["time"] = mTimestamp; + output["expiry"] = mExpiresAt; + output["priority"] = (S32)mPriority; + output["responseFunctor"] = mResponseFunctorName; + return output; +} + +void LLNotification::update() +{ + LLNotifications::instance().update(shared_from_this()); +} + +void LLNotification::updateFrom(LLNotificationPtr other) +{ + // can only update from the same notification type + if (mTemplatep != other->mTemplatep) return; + + // NOTE: do NOT change the ID, since it is the key to + // this given instance, just update all the metadata + //mId = other->mId; + + mPayload = other->mPayload; + mSubstitutions = other->mSubstitutions; + mTimestamp = other->mTimestamp; + mExpiresAt = other->mExpiresAt; + mCancelled = other->mCancelled; + mIgnored = other->mIgnored; + mPriority = other->mPriority; + mForm = other->mForm; + mResponseFunctorName = other->mResponseFunctorName; + mRespondedTo = other->mRespondedTo; + mTemporaryResponder = other->mTemporaryResponder; + + update(); +} + +const LLNotificationFormPtr LLNotification::getForm() +{ + return mForm; +} + +void LLNotification::cancel() +{ + mCancelled = true; +} + +LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) +{ + LLSD response = LLSD::emptyMap(); + for (S32 element_idx = 0; + element_idx < mForm->getNumElements(); + ++element_idx) + { + LLSD element = mForm->getElement(element_idx); + if (element.has("name")) + { + response[element["name"].asString()] = element["value"]; + } + + if ((type == WITH_DEFAULT_BUTTON) + && element["default"].asBoolean()) + { + response[element["name"].asString()] = true; + } + } + return response; +} + +//static +S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) +{ + LLNotificationForm form(notification["form"]); + + for (S32 element_idx = 0; + element_idx < form.getNumElements(); + ++element_idx) + { + LLSD element = form.getElement(element_idx); + + // only look at buttons + if (element["type"].asString() == "button" + && response[element["name"].asString()].asBoolean()) + { + return element["index"].asInteger(); + } + } + + return -1; +} + +//static +std::string LLNotification::getSelectedOptionName(const LLSD& response) +{ + for (LLSD::map_const_iterator response_it = response.beginMap(); + response_it != response.endMap(); + ++response_it) + { + if (response_it->second.isBoolean() && response_it->second.asBoolean()) + { + return response_it->first; + } + } + return ""; +} + + +void LLNotification::respond(const LLSD& response) +{ + mRespondedTo = true; + // look up the functor + LLNotificationFunctorRegistry::ResponseFunctor functor = + LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName); + // and then call it + functor(asLLSD(), response); + + if (mTemporaryResponder) + { + LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); + mResponseFunctorName = ""; + mTemporaryResponder = false; + } + + if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) + { + BOOL show_notification = mIgnored ? FALSE : TRUE; + LLUI::sSettingGroups["ignores"]->setBOOL(getName(), show_notification); + if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) + { + LLUI::sSettingGroups["ignores"]->setLLSD("Default" + getName(), response); + } + } + + update(); +} + +void LLNotification::setIgnored(bool ignore) +{ + mIgnored = ignore; +} + +void LLNotification::setResponseFunctor(std::string const &responseFunctorName) +{ + if (mTemporaryResponder) + // get rid of the old one + LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); + mResponseFunctorName = responseFunctorName; + mTemporaryResponder = false; +} + +bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const +{ + for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin(); + required_fields_it != required_fields.end(); + required_fields_it++) + { + std::string required_field_name = *required_fields_it; + if( ! getPayload().has(required_field_name)) + { + return false; // a required field was not found + } + } + return true; // all required fields were found +} + +bool LLNotification::isEquivalentTo(LLNotificationPtr that) const +{ + if (this->mTemplatep->mName != that->mTemplatep->mName) + { + return false; // must have the same template name or forget it + } + if (this->mTemplatep->mUnique) + { + // highlander bit sez there can only be one of these + return + this->payloadContainsAll(that->mTemplatep->mUniqueContext) && + that->payloadContainsAll(this->mTemplatep->mUniqueContext); + } + return false; +} + +void LLNotification::init(const std::string& template_name, const LLSD& form_elements) +{ + mTemplatep = LLNotifications::instance().getTemplate(template_name); + if (!mTemplatep) return; + + // add default substitutions + const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs(); + for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin(); + iter != default_args.end(); ++iter) + { + mSubstitutions[iter->first] = iter->second; + } + mSubstitutions["_URL"] = getURL(); + mSubstitutions["_NAME"] = template_name; + // TODO: something like this so that a missing alert is sensible: + //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); + + mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); + mForm->append(form_elements); + + // apply substitution to form labels + mForm->formatElements(mSubstitutions); + + LLDate rightnow = LLDate::now(); + if (mTemplatep->mExpireSeconds) + { + mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds); + } + + if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED) + { + mPriority = mTemplatep->mPriority; + } +} + +std::string LLNotification::summarize() const +{ + std::string s = "Notification("; + s += getName(); + s += ") : "; + s += mTemplatep ? mTemplatep->mMessage : ""; + // should also include timestamp and expiration time (but probably not payload) + return s; +} + +std::string LLNotification::getMessage() const +{ + // all our callers cache this result, so it gives us more flexibility + // to do the substitution at call time rather than attempting to + // cache it in the notification + if (!mTemplatep) + return std::string(); + + std::string message = mTemplatep->mMessage; + LLStringUtil::format(message, mSubstitutions); + return message; +} + +std::string LLNotification::getLabel() const +{ + std::string label = mTemplatep->mLabel; + LLStringUtil::format(label, mSubstitutions); + return (mTemplatep ? label : ""); +} + +std::string LLNotification::getURL() const +{ + if (!mTemplatep) + return std::string(); + std::string url = mTemplatep->mURL; + LLStringUtil::format(url, mSubstitutions); + return (mTemplatep ? url : ""); +} + +// ========================================================= +// LLNotificationChannel implementation +// --- +LLBoundListener LLNotificationChannelBase::connectChangedImpl(const LLEventListener& slot) +{ + // when someone wants to connect to a channel, we first throw them + // all of the notifications that are already in the channel + // we use a special signal called "load" in case the channel wants to care + // only about new notifications + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + slot(LLSD().insert("sigtype", "load").insert("id", (*it)->id())); + } + // and then connect the signal so that all future notifications will also be + // forwarded. + return mChanged.connect(slot); +} + +LLBoundListener LLNotificationChannelBase::connectAtFrontChangedImpl(const LLEventListener& slot) +{ + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + slot(LLSD().insert("sigtype", "load").insert("id", (*it)->id())); + } + return mChanged.connect(slot, boost::signals2::at_front); +} + +LLBoundListener LLNotificationChannelBase::connectPassedFilterImpl(const LLEventListener& slot) +{ + // these two filters only fire for notifications added after the current one, because + // they don't participate in the hierarchy. + return mPassedFilter.connect(slot); +} + +LLBoundListener LLNotificationChannelBase::connectFailedFilterImpl(const LLEventListener& slot) +{ + return mFailedFilter.connect(slot); +} + +// external call, conforms to our standard signature +bool LLNotificationChannelBase::updateItem(const LLSD& payload) +{ + // first check to see if it's in the master list + LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]); + if (!pNotification) + return false; // not found + + return updateItem(payload, pNotification); +} + + +//FIX QUIT NOT WORKING + + +// internal call, for use in avoiding lookup +bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPtr pNotification) +{ + std::string cmd = payload["sigtype"]; + LLNotificationSet::iterator foundItem = mItems.find(pNotification); + bool wasFound = (foundItem != mItems.end()); + bool passesFilter = mFilter(pNotification); + + // first, we offer the result of the filter test to the simple + // signals for pass/fail. One of these is guaranteed to be called. + // If either signal returns true, the change processing is NOT performed + // (so don't return true unless you know what you're doing!) + bool abortProcessing = false; + if (passesFilter) + { + abortProcessing = mPassedFilter(payload); + } + else + { + abortProcessing = mFailedFilter(payload); + } + + if (abortProcessing) + { + return true; + } + + if (cmd == "load") + { + // should be no reason we'd ever get a load if we already have it + // if passes filter send a load message, else do nothing + assert(!wasFound); + if (passesFilter) + { + // not in our list, add it and say so + mItems.insert(pNotification); + abortProcessing = mChanged(payload); + onLoad(pNotification); + } + } + else if (cmd == "change") + { + // if it passes filter now and was found, we just send a change message + // if it passes filter now and wasn't found, we have to add it + // if it doesn't pass filter and wasn't found, we do nothing + // if it doesn't pass filter and was found, we need to delete it + if (passesFilter) + { + if (wasFound) + { + // it already existed, so this is a change + // since it changed in place, all we have to do is resend the signal + abortProcessing = mChanged(payload); + onChange(pNotification); + } + else + { + // not in our list, add it and say so + mItems.insert(pNotification); + // our payload is const, so make a copy before changing it + LLSD newpayload = payload; + newpayload["sigtype"] = "add"; + abortProcessing = mChanged(newpayload); + onChange(pNotification); + } + } + else + { + if (wasFound) + { + // it already existed, so this is a delete + mItems.erase(pNotification); + // our payload is const, so make a copy before changing it + LLSD newpayload = payload; + newpayload["sigtype"] = "delete"; + abortProcessing = mChanged(newpayload); + onChange(pNotification); + } + // didn't pass, not on our list, do nothing + } + } + else if (cmd == "add") + { + // should be no reason we'd ever get an add if we already have it + // if passes filter send an add message, else do nothing + assert(!wasFound); + if (passesFilter) + { + // not in our list, add it and say so + mItems.insert(pNotification); + abortProcessing = mChanged(payload); + onAdd(pNotification); + } + } + else if (cmd == "delete") + { + // if we have it in our list, pass on the delete, then delete it, else do nothing + if (wasFound) + { + abortProcessing = mChanged(payload); + mItems.erase(pNotification); + onDelete(pNotification); + } + } + return abortProcessing; +} + +/* static */ +LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name, + const std::string& parent, + LLNotificationFilter filter, + LLNotificationComparator comparator) +{ + // note: this is not a leak; notifications are self-registering. + // This factory helps to prevent excess deletions by making sure all smart + // pointers to notification channels come from the same source + new LLNotificationChannel(name, parent, filter, comparator); + return LLNotifications::instance().getChannel(name); +} + + +LLNotificationChannel::LLNotificationChannel(const std::string& name, + const std::string& parent, + LLNotificationFilter filter, + LLNotificationComparator comparator) : +LLNotificationChannelBase(filter, comparator), +mName(name), +mParent(parent) +{ + // store myself in the channel map + LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); + // bind to notification broadcast + if (parent.empty()) + { + LLNotifications::instance().connectChanged( + boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } + else + { + LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); + p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } +} + + +void LLNotificationChannel::setComparator(LLNotificationComparator comparator) +{ + mComparator = comparator; + LLNotificationSet s2(mComparator); + s2.insert(mItems.begin(), mItems.end()); + mItems.swap(s2); + + // notify clients that we've been resorted + mChanged(LLSD().insert("sigtype", "sort")); +} + +bool LLNotificationChannel::isEmpty() const +{ + return mItems.empty(); +} + +LLNotificationChannel::Iterator LLNotificationChannel::begin() +{ + return mItems.begin(); +} + +LLNotificationChannel::Iterator LLNotificationChannel::end() +{ + return mItems.end(); +} + +std::string LLNotificationChannel::summarize() +{ + std::string s("Channel '"); + s += mName; + s += "'\n "; + for (LLNotificationChannel::Iterator it = begin(); it != end(); ++it) + { + s += (*it)->summarize(); + s += "\n "; + } + return s; +} + + +// --- +// END OF LLNotificationChannel implementation +// ========================================================= + + +// ========================================================= +// LLNotifications implementation +// --- +LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything, + LLNotificationComparators::orderByUUID()), + mIgnoreAllNotifications(false) +{ + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); + + mListener.reset(new LLNotificationsListener(*this)); +} + + +// The expiration channel gets all notifications that are cancelled +bool LLNotifications::expirationFilter(LLNotificationPtr pNotification) +{ + return pNotification->isCancelled() || pNotification->isRespondedTo(); +} + +bool LLNotifications::expirationHandler(const LLSD& payload) +{ + if (payload["sigtype"].asString() != "delete") + { + // anything added to this channel actually should be deleted from the master + cancel(find(payload["id"])); + return true; // don't process this item any further + } + return false; +} + +bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) +{ + if (!pNotif->hasUniquenessConstraints()) + { + return true; + } + + // checks against existing unique notifications + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) + { + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + return false; + } + } + + return true; +} + +bool LLNotifications::uniqueHandler(const LLSD& payload) +{ + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + if (pNotif && pNotif->hasUniquenessConstraints()) + { + if (payload["sigtype"].asString() == "add") + { + // not a duplicate according to uniqueness criteria, so we keep it + // and store it for future uniqueness checks + mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); + } + else if (payload["sigtype"].asString() == "delete") + { + mUniqueNotifications.erase(pNotif->getName()); + } + } + + return false; +} + +bool LLNotifications::failedUniquenessTest(const LLSD& payload) +{ + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); + + if (!pNotif || !pNotif->hasUniquenessConstraints()) + { + return false; + } + + // checks against existing unique notifications + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) + { + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy notification instance data over to oldest instance + // of this unique notification and update it + existing_notification->updateFrom(pNotif); + // then delete the new one + pNotif->cancel(); + } + } + + return false; +} + + +void LLNotifications::addChannel(LLNotificationChannelPtr pChan) +{ + mChannels[pChan->getName()] = pChan; +} + +LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) +{ + ChannelMap::iterator p = mChannels.find(channelName); + if(p == mChannels.end()) + { + llerrs << "Did not find channel named " << channelName << llendl; + } + return p->second; +} + + +// this function is called once at construction time, after the object is constructed. +void LLNotifications::initSingleton() +{ + loadTemplates(); + createDefaultChannels(); +} + +void LLNotifications::createDefaultChannels() +{ + // now construct the various channels AFTER loading the notifications, + // because the history channel is going to rewrite the stored notifications file + LLNotificationChannel::buildChannel("Expiration", "", + boost::bind(&LLNotifications::expirationFilter, this, _1)); + LLNotificationChannel::buildChannel("Unexpired", "", + !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind + LLNotificationChannel::buildChannel("Unique", "Unexpired", + boost::bind(&LLNotifications::uniqueFilter, this, _1)); + LLNotificationChannel::buildChannel("Ignore", "Unique", + filterIgnoredNotifications); + LLNotificationChannel::buildChannel("Visible", "Ignore", + &LLNotificationFilters::includeEverything); + + // create special history channel + //std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); + // use ^^^ when done debugging notifications serialization + std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" ); + // this isn't a leak, don't worry about the empty "new" + new LLNotificationHistoryChannel(notifications_log_file); + + // connect action methods to these channels + LLNotifications::instance().getChannel("Expiration")-> + connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); + // uniqueHandler slot should be added as first slot of the signal due to + // usage LLStopWhenHandled combiner in LLStandardSignal + LLNotifications::instance().getChannel("Unique")-> + connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); +// failedUniquenessTest slot isn't necessary +// LLNotifications::instance().getChannel("Unique")-> +// connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); + LLNotifications::instance().getChannel("Ignore")-> + connectFailedFilter(&handleIgnoredNotification); +} + +bool LLNotifications::addTemplate(const std::string &name, + LLNotificationTemplatePtr theTemplate) +{ + if (mTemplates.count(name)) + { + llwarns << "LLNotifications -- attempted to add template '" << name << "' twice." << llendl; + return false; + } + mTemplates[name] = theTemplate; + return true; +} + +LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name) +{ + if (mTemplates.count(name)) + { + return mTemplates[name]; + } + else + { + return mTemplates["MissingAlert"]; + } +} + +bool LLNotifications::templateExists(const std::string& name) +{ + return (mTemplates.count(name) != 0); +} + +void LLNotifications::clearTemplates() +{ + mTemplates.clear(); +} + +void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) +{ + LLNotificationPtr temp_notify(new LLNotification(params)); + LLSD response = temp_notify->getResponseTemplate(); + LLSD selected_item = temp_notify->getForm()->getElement(option); + + if (selected_item.isUndefined()) + { + llwarns << "Invalid option" << option << " for notification " << (std::string)params.name << llendl; + return; + } + response[selected_item["name"].asString()] = true; + + temp_notify->respond(response); +} + +LLNotifications::TemplateNames LLNotifications::getTemplateNames() const +{ + TemplateNames names; + for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it) + { + names.push_back(it->first); + } + return names; +} + +typedef std::map<std::string, std::string> StringMap; +void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements) +{ + //llwarns << "replaceSubstitutionStrings" << llendl; + // walk the list of attributes looking for replacements + for (LLXMLAttribList::iterator it=node->mAttributes.begin(); + it != node->mAttributes.end(); ++it) + { + std::string value = it->second->getValue(); + if (value[0] == '$') + { + value.erase(0, 1); // trim off the $ + std::string replacement; + StringMap::const_iterator found = replacements.find(value); + if (found != replacements.end()) + { + replacement = found->second; + //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl; + + it->second->setValue(replacement); + } + else + { + llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl; + } + } + } + + // now walk the list of children and call this recursively. + for (LLXMLNodePtr child = node->getFirstChild(); + child.notNull(); child = child->getNextSibling()) + { + replaceSubstitutionStrings(child, replacements); + } +} + +// private to this file +// returns true if the template request was invalid and there's nothing else we +// can do with this node, false if you should keep processing (it may have +// replaced the contents of the node referred to) +LLXMLNodePtr LLNotifications::checkForXMLTemplate(LLXMLNodePtr item) +{ + if (item->hasName("usetemplate")) + { + std::string replacementName; + if (item->getAttributeString("name", replacementName)) + { + StringMap replacements; + for (LLXMLAttribList::const_iterator it=item->mAttributes.begin(); + it != item->mAttributes.end(); ++it) + { + replacements[it->second->getName()->mString] = it->second->getValue(); + } + if (mXmlTemplates.count(replacementName)) + { + item=LLXMLNode::replaceNode(item, mXmlTemplates[replacementName]); + + // walk the nodes looking for $(substitution) here and replace + replaceSubstitutionStrings(item, replacements); + } + else + { + llwarns << "XML template lookup failure on '" << replacementName << "' " << llendl; + } + } + } + return item; +} + +bool LLNotifications::loadTemplates() +{ + const std::string xml_filename = "notifications.xml"; + LLXMLNodePtr root; + + BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + + if (!success || root.isNull() || !root->hasName( "notifications" )) + { + llerrs << "Problem reading UI Notifications file: " << xml_filename << llendl; + return false; + } + + clearTemplates(); + + for (LLXMLNodePtr item = root->getFirstChild(); + item.notNull(); item = item->getNextSibling()) + { + // we do this FIRST so that item can be changed if we + // encounter a usetemplate -- we just replace the + // current xml node and keep processing + item = checkForXMLTemplate(item); + + if (item->hasName("global")) + { + std::string global_name; + if (item->getAttributeString("name", global_name)) + { + mGlobalStrings[global_name] = item->getTextContents(); + } + continue; + } + + if (item->hasName("template")) + { + // store an xml template; templates must have a single node (can contain + // other nodes) + std::string name; + item->getAttributeString("name", name); + LLXMLNodePtr ptr = item->getFirstChild(); + mXmlTemplates[name] = ptr; + continue; + } + + if (!item->hasName("notification")) + { + llwarns << "Unexpected entity " << item->getName()->mString << + " found in " << xml_filename << llendl; + continue; + } + + // now we know we have a notification entry, so let's build it + LLNotificationTemplatePtr pTemplate(new LLNotificationTemplate()); + + if (!item->getAttributeString("name", pTemplate->mName)) + { + llwarns << "Unable to parse notification with no name" << llendl; + continue; + } + + //llinfos << "Parsing " << pTemplate->mName << llendl; + + pTemplate->mMessage = item->getTextContents(); + pTemplate->mDefaultFunctor = pTemplate->mName; + item->getAttributeString("type", pTemplate->mType); + item->getAttributeString("icon", pTemplate->mIcon); + item->getAttributeString("label", pTemplate->mLabel); + item->getAttributeU32("duration", pTemplate->mExpireSeconds); + item->getAttributeU32("expireOption", pTemplate->mExpireOption); + + std::string priority; + item->getAttributeString("priority", priority); + pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL; + if (!priority.empty()) + { + if (priority == "low") pTemplate->mPriority = NOTIFICATION_PRIORITY_LOW; + if (priority == "normal") pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL; + if (priority == "high") pTemplate->mPriority = NOTIFICATION_PRIORITY_HIGH; + if (priority == "critical") pTemplate->mPriority = NOTIFICATION_PRIORITY_CRITICAL; + } + + item->getAttributeString("functor", pTemplate->mDefaultFunctor); + + BOOL persist = false; + item->getAttributeBOOL("persist", persist); + pTemplate->mPersist = persist; + + std::string sound; + item->getAttributeString("sound", sound); + if (!sound.empty()) + { + // test for bad sound effect name / missing effect + if (LLUI::sSettingGroups["config"]->controlExists(sound)) + { + pTemplate->mSoundEffect = + LLUUID(LLUI::sSettingGroups["config"]->getString(sound)); + } + else + { + llwarns << "Unknown sound effect control name " << sound + << llendl; + } + } + + for (LLXMLNodePtr child = item->getFirstChild(); + !child.isNull(); child = child->getNextSibling()) + { + child = checkForXMLTemplate(child); + + // <url> + if (child->hasName("url")) + { + pTemplate->mURL = child->getTextContents(); + child->getAttributeU32("option", pTemplate->mURLOption); + child->getAttributeU32("openexternally", pTemplate->mURLOpenExternally); + } + + if (child->hasName("unique")) + { + pTemplate->mUnique = true; + for (LLXMLNodePtr formitem = child->getFirstChild(); + !formitem.isNull(); formitem = formitem->getNextSibling()) + { + if (formitem->hasName("context")) + { + std::string key; + formitem->getAttributeString("key", key); + pTemplate->mUniqueContext.push_back(key); + //llwarns << "adding " << key << " to unique context" << llendl; + } + else + { + llwarns << "'unique' has unrecognized subelement " + << formitem->getName()->mString << llendl; + } + } + } + + // <form> + if (child->hasName("form")) + { + pTemplate->mForm = LLNotificationFormPtr(new LLNotificationForm(pTemplate->mName, child)); + } + } + addTemplate(pTemplate->mName, pTemplate); + } + + //std::ostringstream ostream; + //root->writeToOstream(ostream, "\n "); + //llwarns << ostream.str() << llendl; + + return true; +} + +// Add a simple notification (from XUI) +void LLNotifications::addFromCallback(const LLSD& name) +{ + add(LLNotification::Params().name(name.asString())); +} + +// we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line +LLNotificationPtr LLNotifications::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +LLNotificationPtr LLNotifications::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = functor_name; + return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +LLNotificationPtr LLNotifications::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) +{ + LLNotification::Params::Functor functor_p; + functor_p.function = functor; + return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +// generalized add function that takes a parameter block object for more complex instantiations +LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) +{ + LLNotificationPtr pNotif(new LLNotification(p)); + add(pNotif); + return pNotif; +} + + +void LLNotifications::add(const LLNotificationPtr pNotif) +{ + // first see if we already have it -- if so, that's a problem + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + llerrs << "Notification added a second time to the master notification channel." << llendl; + } + + updateItem(LLSD().insert("sigtype", "add").insert("id", pNotif->id()), pNotif); +} + +void LLNotifications::cancel(LLNotificationPtr pNotif) +{ + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it == mItems.end()) + { + llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; + } + pNotif->cancel(); + updateItem(LLSD().insert("sigtype", "delete").insert("id", pNotif->id()), pNotif); +} + +void LLNotifications::update(const LLNotificationPtr pNotif) +{ + LLNotificationSet::iterator it=mItems.find(pNotif); + if (it != mItems.end()) + { + updateItem(LLSD().insert("sigtype", "change").insert("id", pNotif->id()), pNotif); + } +} + + +LLNotificationPtr LLNotifications::find(LLUUID uuid) +{ + LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid)); + LLNotificationSet::iterator it=mItems.find(target); + if (it == mItems.end()) + { + llwarns << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl; + return LLNotificationPtr((LLNotification*)NULL); + } + else + { + return *it; + } +} + +void LLNotifications::forEachNotification(NotificationProcess process) +{ + std::for_each(mItems.begin(), mItems.end(), process); +} + +std::string LLNotifications::getGlobalString(const std::string& key) const +{ + GlobalStringMap::const_iterator it = mGlobalStrings.find(key); + if (it != mGlobalStrings.end()) + { + return it->second; + } + else + { + // if we don't have the key as a global, return the key itself so that the error + // is self-diagnosing. + return key; + } +} + +void LLNotifications::setIgnoreAllNotifications(bool setting) +{ + mIgnoreAllNotifications = setting; +} +bool LLNotifications::getIgnoreAllNotifications() +{ + return mIgnoreAllNotifications; +} + +// --- +// END OF LLNotifications implementation +// ========================================================= + +std::ostream& operator<<(std::ostream& s, const LLNotification& notification) +{ + s << notification.summarize(); + return s; +} + diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 0335a265b6..0d7cb74f70 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -102,7 +102,6 @@ #include "llfunctorregistry.h" #include "llpointer.h" #include "llinitparam.h" -#include "llxmlnode.h" #include "llnotificationslistener.h" class LLNotification; @@ -161,7 +160,7 @@ public: LLNotificationForm(); LLNotificationForm(const LLSD& sd); LLNotificationForm(const std::string& name, - const LLPointer<LLXMLNode> xml_node); + const LLPointer<class LLXMLNode> xml_node); LLSD asLLSD() const; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 742427525b..095200ddc3 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -474,7 +474,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu { //if we are exporting, we want to export the current xml //not the referenced xml - LLXUIParser::instance().readXUI(node, params); + LLXUIParser::instance().readXUI(node, params, xml_filename); Params output_params(params); setupParamsForExport(output_params, parent); output_node->setName(node->getName()->mString); @@ -490,14 +490,15 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu return FALSE; } - LLXUIParser::instance().readXUI(referenced_xml, params); + LLXUIParser::instance().readXUI(referenced_xml, params, xml_filename); // add children using dimensions from referenced xml for consistent layout setShape(params.rect); LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); } - LLXUIParser::instance().readXUI(node, params); + // ask LLUICtrlFactory for filename, since xml_filename might be empty + LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName()); if (output_node) { diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp index cf23e3af15..7e3d4b92d3 100644 --- a/indra/llui/llrngwriter.cpp +++ b/indra/llui/llrngwriter.cpp @@ -108,7 +108,8 @@ void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam: LLXMLNodePtr old_element_node = mElementNode; LLXMLNodePtr old_child_node = mChildrenNode; - addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))()); + //FIXME: add LLDefaultParamBlockRegistry back when working on schema generation + //addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))()); mElementNode = old_element_node; mChildrenNode = old_child_node; diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 0d674528dc..dfd315d451 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -149,7 +149,8 @@ void LLScrollbar::setDocParams( S32 size, S32 pos ) updateThumbRect(); } -void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) +// returns true if document position really changed +bool LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) { pos = llclamp(pos, 0, getDocPosMax()); if (pos != mDocPos) @@ -166,7 +167,9 @@ void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) { updateThumbRect(); } + return true; } + return false; } void LLScrollbar::setDocSize(S32 size) @@ -409,13 +412,8 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks) { - S32 pos = llclamp(mDocPos + clicks * mStepSize, 0, getDocPosMax()); - if (pos != mDocPos) - { - setDocPos(pos, TRUE); - return TRUE; - } - return FALSE; + BOOL handled = changeLine( clicks * mStepSize, TRUE ); + return handled; } BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -578,9 +576,9 @@ void LLScrollbar::draw() } // end draw -void LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) +bool LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) { - setDocPos(mDocPos + delta, update_thumb); + return setDocPos(mDocPos + delta, update_thumb); } void LLScrollbar::setValue(const LLSD& value) diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 865a1db409..a9f028f9ae 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -109,7 +109,7 @@ public: // How many "lines" the "document" has scrolled. // 0 <= DocPos <= DocSize - DocVisibile - void setDocPos( S32 pos, BOOL update_thumb = TRUE ); + bool setDocPos( S32 pos, BOOL update_thumb = TRUE ); S32 getDocPos() const { return mDocPos; } BOOL isAtBeginning(); @@ -133,7 +133,7 @@ public: private: void updateThumbRect(); - void changeLine(S32 delta, BOOL update_thumb ); + bool changeLine(S32 delta, BOOL update_thumb ); callback_t mChangeCallback; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 1d36a16ea7..22cce755b0 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1825,27 +1825,26 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round return pos; } -LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const +// returns rectangle of insertion caret +// in document coordinate frame from given index into text +LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const { - LLRect local_rect; if (mLineInfoList.empty()) { - local_rect = mTextRect; - local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); - return local_rect; + return LLRect(); } + LLRect doc_rect; + // clamp pos to valid values pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1); - // find line that contains cursor line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare()); - LLRect scrolled_view_rect = getVisibleDocumentRect(); - local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft; - local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom); - local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom); + doc_rect.mLeft = line_iter->mRect.mLeft; + doc_rect.mBottom = line_iter->mRect.mBottom; + doc_rect.mTop = line_iter->mRect.mTop; segment_set_t::iterator line_seg_iter; S32 line_seg_offset; @@ -1863,7 +1862,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const // cursor advanced to right based on difference in offset of cursor to start of line S32 segment_width, segment_height; segmentp->getDimensions(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height); - local_rect.mLeft += segment_width; + doc_rect.mLeft += segment_width; break; } @@ -1872,7 +1871,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const // add remainder of current text segment to cursor position S32 segment_width, segment_height; segmentp->getDimensions(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height); - local_rect.mLeft += segment_width; + doc_rect.mLeft += segment_width; // offset will be 0 for all segments after the first line_seg_offset = 0; // go to next text segment on this line @@ -1880,7 +1879,31 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const } } - local_rect.mRight = local_rect.mLeft; + // set rect to 0 width + doc_rect.mRight = doc_rect.mLeft; + + return doc_rect; +} + +LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const +{ + LLRect local_rect; + if (mLineInfoList.empty()) + { + // return default height rect in upper left + local_rect = mTextRect; + local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); + return local_rect; + } + + // get the rect in document coordinates + LLRect doc_rect = getDocRectFromDocIndex(pos); + + // compensate for scrolled, inset view of doc + LLRect scrolled_view_rect = getVisibleDocumentRect(); + local_rect = doc_rect; + local_rect.translate(mTextRect.mLeft - scrolled_view_rect.mLeft, + mTextRect.mBottom - scrolled_view_rect.mBottom); return local_rect; } @@ -2416,10 +2439,12 @@ void LLNormalTextSegment::dump() const // LLInlineViewSegment // -LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line) +LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line, S32 hpad, S32 vpad) : LLTextSegment(start, end), mView(view), - mForceNewLine(force_new_line) + mForceNewLine(force_new_line), + mHPad(hpad), // one sided padding (applied to left and right) + mVPad(vpad) { } @@ -2439,8 +2464,8 @@ void LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt } else { - width = mView->getRect().getWidth(); - height = mView->getRect().getHeight(); + width = mHPad * 2 + mView->getRect().getWidth(); + height = mVPad * 2 + mView->getRect().getHeight(); } } @@ -2462,14 +2487,15 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin void LLInlineViewSegment::updateLayout(const LLTextBase& editor) { - LLRect start_rect = editor.getLocalRectFromDocIndex(mStart); - LLRect doc_rect = editor.getDocumentView()->getRect(); - mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom); + LLRect start_rect = editor.getDocRectFromDocIndex(mStart); + mView->setOrigin(start_rect.mLeft + mHPad, start_rect.mBottom + mVPad); } F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { - return (F32)(draw_rect.mLeft + mView->getRect().getWidth()); + // return padded width of widget + // widget is actually drawn during mDocumentView's draw() + return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mHPad * 2); } void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor) diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index c05a31baec..f0b8878491 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -157,6 +157,7 @@ public: S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const; LLRect getLocalRectFromDocIndex(S32 pos) const; + LLRect getDocRectFromDocIndex(S32 pos) const; void setReadOnly(bool read_only) { mReadOnly = read_only; } bool getReadOnly() { return mReadOnly; } @@ -458,7 +459,7 @@ public: class LLInlineViewSegment : public LLTextSegment { public: - LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line); + LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line, S32 hpad = 0, S32 vpad = 0); ~LLInlineViewSegment(); /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; @@ -469,6 +470,8 @@ public: /*virtual*/ void linkToDocument(class LLTextBase* editor); private: + S32 mHPad; + S32 mVPad; LLView* mView; bool mForceNewLine; }; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 953c5b292f..d507cf7ce4 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2276,7 +2276,7 @@ void LLTextEditor::insertText(const std::string &new_text) setEnabled( enabled ); } -void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line) +void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line, S32 hpad, S32 vpad) { // Save old state S32 selection_start = mSelectionStart; @@ -2295,7 +2295,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, // Add carriage return if not first line widget_wide_text = utf8str_to_wstring(widget_text); - LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line); + LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line, hpad, vpad); insert(getLength(), widget_wide_text, FALSE, segment); needsReflow(); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 82f3956855..481a4d1a78 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -165,7 +165,7 @@ public: // inserts text at cursor void insertText(const std::string &text); - void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline); + void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline, S32 hpad, S32 vpad); // Non-undoable void setText(const LLStringExplicit &utf8str); diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 087a99c2b0..5827c0d627 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -278,7 +278,7 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename) } Params params; - LLXUIParser::instance().readXUI(root, params); + LLXUIParser::instance().readXUI(root, params, filename); if(params.validateBlock()) { diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 209ee76940..c3c0daed0f 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -34,6 +34,8 @@ #include "lluictrlfactory.h" +#include "llxmlnode.h" + #include <fstream> #include <boost/tokenizer.hpp> @@ -83,8 +85,9 @@ LLUICtrlFactory::LLUICtrlFactory() LLUICtrlFactory::~LLUICtrlFactory() { - delete mDummyPanel; - mDummyPanel = NULL; + // go ahead and leak mDummyPanel since this is static destructor time + //delete mDummyPanel; + //mDummyPanel = NULL; } void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block) @@ -94,7 +97,7 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) { - LLXUIParser::instance().readXUI(root_node, block); + LLXUIParser::instance().readXUI(root_node, block, filename); } } @@ -410,3 +413,39 @@ void LLUICtrlFactory::popFactoryFunctions() mFactoryStack.pop_back(); } } + +//static +void LLUICtrlFactory::copyName(LLXMLNodePtr src, LLXMLNodePtr dest) +{ + dest->setName(src->getName()->mString); +} + +// adds a widget and its param block to various registries +//static +void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag) +{ + // associate parameter block type with template .xml file + std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type); + if (existing_tag != NULL && *existing_tag != tag) + { + llerrs << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << llendl; + } + LLWidgetNameRegistry ::instance().defaultRegistrar().add(param_block_type, tag); + // associate widget type with factory function + LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type, creator_func); + LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type); + //FIXME: comment this in when working on schema generation + //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &getEmptyParamBlock<T>); +} + +//static +dummy_widget_creator_func_t* LLUICtrlFactory::getDefaultWidgetFunc(const std::type_info* widget_type) +{ + return LLDefaultWidgetRegistry::instance().getValue(widget_type); +} + +//static +const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type) +{ + return LLWidgetNameRegistry::instance().getValue(widget_type); +} diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 5e6dad312c..17e32dc7a9 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -36,7 +36,7 @@ #include "llcallbackmap.h" #include "llinitparam.h" #include "llregistry.h" -#include "llxmlnode.h" +#include "v4color.h" #include "llfasttimer.h" #include "llxuiparser.h" @@ -98,10 +98,11 @@ class LLDefaultWidgetRegistry {}; // lookup function for generating empty param block by widget type -typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)(); -class LLDefaultParamBlockRegistry -: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID> -{}; +// this is used for schema generation +//typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)(); +//class LLDefaultParamBlockRegistry +//: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID> +//{}; extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION; @@ -124,7 +125,7 @@ private: // recursively initialize from base class param block ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); // after initializing base classes, look up template file for this param block - std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); + const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); if (param_block_tag) { LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype); @@ -241,7 +242,7 @@ fail: template<class T> static T* getDefaultWidget(const std::string& name) { - dummy_widget_creator_func_t* dummy_func = LLDefaultWidgetRegistry::instance().getValue(&typeid(T)); + dummy_widget_creator_func_t* dummy_func = getDefaultWidgetFunc(&typeid(T)); return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL; } @@ -254,6 +255,8 @@ fail: return create<T>(params); } + static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest); + template<typename T> static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { @@ -262,7 +265,7 @@ fail: //#pragma message("Generating LLUICtrlFactory::defaultBuilder") typename T::Params params(getDefaultParams<T>()); - LLXUIParser::instance().readXUI(node, params); + LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName()); if (output_node) { @@ -271,7 +274,7 @@ fail: T::setupParamsForExport(output_params, parent); // Export only the differences between this any default params typename T::Params default_params(getDefaultParams<T>()); - output_node->setName(node->getName()->mString); + copyName(node, output_node); LLXUIParser::instance().writeXUI( output_node, output_params, &default_params); } @@ -320,7 +323,15 @@ fail: static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); + // helper function for adding widget type info to various registries + static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag); + private: + // return default widget instance factory func for a given type + static dummy_widget_creator_func_t* getDefaultWidgetFunc(const std::type_info* widget_type); + + static const std::string* getWidgetTag(const std::type_info* widget_type); + // this exists to get around dependency on llview static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); @@ -347,23 +358,12 @@ template<typename T> LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func) : LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func) { - const std::type_info* widget_type_infop = &typeid(T); - // associate parameter block type with template .xml file - std::string* existing_tag = LLWidgetNameRegistry ::instance().getValue(&typeid(typename T::Params)); - if (existing_tag != NULL && *existing_tag != tag) - { - // duplicate entry for T::Params - // try creating empty param block in derived classes that inherit T::Params - int* crash = 0; - *crash = 0; - } - LLWidgetNameRegistry ::instance().defaultRegistrar().add(&typeid(typename T::Params), tag); - // associate widget type with factory function - LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type_infop, &LLUICtrlFactory::createDefaultWidget<T>); - LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type_infop); - LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type_infop, &getEmptyParamBlock<T>); + // add this widget to various registries + LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), &LLUICtrlFactory::createDefaultWidget<T>, tag); + + // since registry_t depends on T, do this in line here typedef typename T::child_registry_t registry_t; - LLChildRegistryRegistry::instance().defaultRegistrar().add(widget_type_infop, registry_t::instance()); + LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance()); } diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 20ff71378e..3a1e656364 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -35,8 +35,6 @@ #include "llsd.h" #include "lltrans.h" -const LLStringUtil::format_map_t LLUIString::sNullArgs; - LLFastTimer::DeclareTimer FTM_UI_STRING("UI String"); diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 195f21a6a7..763de4d6a3 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -95,8 +95,6 @@ public: void insert(S32 charidx, const LLWString& wchars); void replace(S32 charidx, llwchar wc); - static const LLStringUtil::format_map_t sNullArgs; - private: void format(); diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 6dd1f93baf..318a0348a2 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -38,8 +38,6 @@ namespace LLInitParam { - BlockDescriptor BaseBlock::sBlockDescriptor; - // // Param // diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 4c936197c9..9fb464ca7b 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -46,6 +46,7 @@ namespace LLInitParam { + template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value > struct ParamCompare { @@ -474,7 +475,11 @@ namespace LLInitParam BlockDescriptor* mBlockDescriptor; // most derived block descriptor - static BlockDescriptor sBlockDescriptor; + static BlockDescriptor& blockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; @@ -493,13 +498,13 @@ namespace LLInitParam // that derive from BaseBlock and those that don't // this is supposedly faster than boost::is_convertible and its ilk template<typename T, typename Void = void> - struct is_BaseBlock + struct IsBaseBlock { static const bool value = false; }; template<typename T> - struct is_BaseBlock<T, typename T::baseblock_base_class_t> + struct IsBaseBlock<T, typename T::baseblock_base_class_t> { static const bool value = true; }; @@ -509,7 +514,7 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = is_BaseBlock<T>::value> + bool VALUE_IS_BLOCK = IsBaseBlock<T>::value> class TypedParam : public Param { @@ -1246,7 +1251,7 @@ namespace LLInitParam bool overwriteFrom(const self_t& other) { mCurChoice = other.mCurChoice; - return BaseBlock::overwriteFromImpl(sBlockDescriptor, other); + return BaseBlock::overwriteFromImpl(blockDescriptor(), other); } // take all provided params that are not already provided, and apply to self @@ -1277,7 +1282,7 @@ namespace LLInitParam Choice() : mCurChoice(0) { - BaseBlock::init(sBlockDescriptor, BaseBlock::sBlockDescriptor, sizeof(DERIVED_BLOCK)); + BaseBlock::init(blockDescriptor(), BaseBlock::blockDescriptor(), sizeof(DERIVED_BLOCK)); } // Alternatives are mutually exclusive wrt other Alternatives in the same block. @@ -1290,16 +1295,16 @@ namespace LLInitParam friend class Choice<DERIVED_BLOCK>; typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, is_BaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; explicit Alternative(const char* name, value_assignment_t val = DefaultInitializer<T>::get()) - : super_t(DERIVED_BLOCK::sBlockDescriptor, name, val, NULL, 0, 1), + : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { // assign initial choice to first declared option - DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::sBlockDescriptor.mCurrentBlockPtr); - if (DERIVED_BLOCK::sBlockDescriptor.mInitializationState == BlockDescriptor::INITIALIZING + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::blockDescriptor().mCurrentBlockPtr); + if (DERIVED_BLOCK::blockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING && blockp->mCurChoice == 0) { blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); @@ -1345,7 +1350,11 @@ namespace LLInitParam }; protected: - static BlockDescriptor sBlockDescriptor; + static BlockDescriptor& blockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } private: param_handle_t mCurChoice; @@ -1356,15 +1365,6 @@ namespace LLInitParam } }; - template<typename DERIVED_BLOCK> - BlockDescriptor - Choice<DERIVED_BLOCK>::sBlockDescriptor; - - //struct CardinalityConstraint - //{ - // virtual std::pair<S32, S32> getRange() = 0; - //}; - struct AnyAmount { static U32 minCount() { return 0; } @@ -1412,19 +1412,19 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return BaseBlock::overwriteFromImpl(sBlockDescriptor, other); + return BaseBlock::overwriteFromImpl(blockDescriptor(), other); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return BaseBlock::fillFromImpl(sBlockDescriptor, other); + return BaseBlock::fillFromImpl(blockDescriptor(), other); } protected: Block() { //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(sBlockDescriptor, BASE_BLOCK::sBlockDescriptor, sizeof(DERIVED_BLOCK)); + BaseBlock::init(blockDescriptor(), BASE_BLOCK::blockDescriptor(), sizeof(DERIVED_BLOCK)); } // @@ -1434,11 +1434,11 @@ namespace LLInitParam class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, is_BaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; explicit Optional(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) - : super_t(DERIVED_BLOCK::sBlockDescriptor, name, val, NULL, 0, 1) + : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") } @@ -1461,13 +1461,13 @@ namespace LLInitParam class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, is_BaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::value_assignment_t value_assignment_t; // mandatory parameters require a name to be parseable explicit Mandatory(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) - : super_t(DERIVED_BLOCK::sBlockDescriptor, name, val, &validate, 1, 1) + : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, 1, 1) {} Mandatory& operator=(value_assignment_t val) @@ -1495,7 +1495,7 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, true, is_BaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBaseBlock<T>::value> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1503,7 +1503,7 @@ namespace LLInitParam typedef typename container_t::const_iterator const_iterator; explicit Multiple(const char* name = "", value_assignment_t val = DefaultInitializer<container_t>::get()) - : super_t(DERIVED_BLOCK::sBlockDescriptor, name, val, &validate, RANGE::minCount(), RANGE::maxCount()) + : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount()) {} using super_t::operator(); @@ -1531,9 +1531,9 @@ namespace LLInitParam { public: explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::sBlockDescriptor.mCurrentBlockPtr) + : Param(DERIVED_BLOCK::blockDescriptor().mCurrentBlockPtr) { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::sBlockDescriptor; + BlockDescriptor& block_descriptor = DERIVED_BLOCK::blockDescriptor(); if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING) { ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), @@ -1563,13 +1563,13 @@ namespace LLInitParam typedef Deprecated Ignored; protected: - static BlockDescriptor sBlockDescriptor; + static BlockDescriptor& blockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } }; - template<typename DERIVED_BLOCK, typename BASE_BLOCK> - BlockDescriptor - Block<DERIVED_BLOCK, BASE_BLOCK>::sBlockDescriptor; - template<typename T, typename DERIVED = TypedParam<T> > class BlockValue : public Block<TypedParam<T, TypeValues<T>, false> >, @@ -1803,11 +1803,11 @@ namespace LLInitParam // assign individual parameters if (overwrite) { - dst_typed_param.BaseBlock::overwriteFromImpl(block_t::sBlockDescriptor, src_param); + dst_typed_param.BaseBlock::overwriteFromImpl(block_t::blockDescriptor(), src_param); } else { - dst_typed_param.BaseBlock::fillFromImpl(block_t::sBlockDescriptor, src_param); + dst_typed_param.BaseBlock::fillFromImpl(block_t::blockDescriptor(), src_param); } // then copy actual value dst_typed_param.mData.mValue = src_param.get(); diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp index e974dbd0ba..4c800a502d 100644 --- a/indra/llxuixml/lltrans.cpp +++ b/indra/llxuixml/lltrans.cpp @@ -72,7 +72,7 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa } StringTable string_table; - LLXUIParser::instance().readXUI(root, string_table); + LLXUIParser::instance().readXUI(root, string_table, xml_filename); if (!string_table.validateBlock()) { @@ -115,7 +115,7 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root) } StringTable string_table; - LLXUIParser::instance().readXUI(root, string_table); + LLXUIParser::instance().readXUI(root, string_table, xml_filename); if (!string_table.validateBlock()) { diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index e28e52fd16..17399865e5 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -34,6 +34,7 @@ #include "llxuiparser.h" +#include "llxmlnode.h" #include <fstream> #include <boost/tokenizer.hpp> @@ -401,10 +402,11 @@ LLXUIParser::LLXUIParser() static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); -void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent) +void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent) { LLFastTimer timer(FTM_PARSE_XUI); mNameStack.clear(); + mCurFileName = filename; mCurReadDepth = 0; setParseSilently(silent); @@ -946,9 +948,9 @@ bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack) void LLXUIParser::parserWarning(const std::string& message) { -#if 0 //#ifdef LL_WINDOWS +#ifdef LL_WINDOWS // use Visual Studo friendly formatting of output message for easy access to originating xml - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); utf16str += '\n'; OutputDebugString(utf16str.c_str()); #else @@ -958,8 +960,8 @@ void LLXUIParser::parserWarning(const std::string& message) void LLXUIParser::parserError(const std::string& message) { -#if 0 //#ifdef LL_WINDOWS - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); +#ifdef LL_WINDOWS + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); utf16str += '\n'; OutputDebugString(utf16str.c_str()); #else diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index 6f000f2422..884f4f7578 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -34,9 +34,9 @@ #define LLXUIPARSER_H #include "llinitparam.h" -#include "llxmlnode.h" #include "llfasttimer.h" #include "llregistry.h" +#include "llpointer.h" #include <boost/function.hpp> #include <iosfwd> @@ -48,6 +48,8 @@ class LLView; +typedef LLPointer<class LLXMLNode> LLXMLNodePtr; + // lookup widget type by name class LLWidgetTypeRegistry @@ -114,7 +116,7 @@ public: /*virtual*/ void parserWarning(const std::string& message); /*virtual*/ void parserError(const std::string& message); - void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent=false); + void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false); void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); private: @@ -168,6 +170,7 @@ private: S32 mLastWriteGeneration; LLXMLNodePtr mLastWrittenChild; S32 mCurReadDepth; + std::string mCurFileName; }; diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt index 5c0ce3ee17..a9f7938b41 100644 --- a/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -42,12 +42,12 @@ set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamertriviallogging.h ) -if (${CXX_VERSION} MATCHES "4.[23]") +if (${CXX_VERSION} MATCHES "4[23].") # Work around a bad interaction between broken gstreamer headers and # g++ 4.3's increased strictness. set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES - COMPILE_FLAGS -Wno-error=write-strings) -endif (${CXX_VERSION} MATCHES "4.[23]") + COMPILE_FLAGS -Wno-write-strings) +endif (${CXX_VERSION} MATCHES "4[23].") add_library(media_plugin_gstreamer010 SHARED diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1e5a798202..5fdf13b078 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -70,6 +70,7 @@ set(viewer_SOURCE_FILES llagentaccess.cpp llagentdata.cpp llagentlanguage.cpp + llagentpicksinfo.cpp llagentpilot.cpp llagentui.cpp llagentwearables.cpp @@ -113,6 +114,7 @@ set(viewer_SOURCE_FILES lldebugview.cpp lldelayedgestureerror.cpp lldirpicker.cpp + lldndbutton.cpp lldrawable.cpp lldrawpoolalpha.cpp lldrawpoolavatar.cpp @@ -341,6 +343,7 @@ set(viewer_SOURCE_FILES llpanelteleporthistory.cpp llpanelvolume.cpp llparcelselection.cpp + llparticipantlist.cpp llpatchvertexarray.cpp llplacesinventorybridge.cpp llpolymesh.cpp @@ -414,6 +417,8 @@ set(viewer_SOURCE_FILES lltoolselectland.cpp lltoolselectrect.cpp lltracker.cpp + lltransientdockablefloater.cpp + lltransientfloatermgr.cpp lluilistener.cpp lluploaddialog.cpp llurl.cpp @@ -540,6 +545,7 @@ set(viewer_HEADER_FILES llagentaccess.h llagentdata.h llagentlanguage.h + llagentpicksinfo.h llagentpilot.h llagentui.h llagentwearables.h @@ -585,6 +591,7 @@ set(viewer_HEADER_FILES lldebugview.h lldelayedgestureerror.h lldirpicker.h + lldndbutton.h lldrawable.h lldrawpool.h lldrawpoolalpha.h @@ -810,6 +817,7 @@ set(viewer_HEADER_FILES llpanelteleporthistory.h llpanelvolume.h llparcelselection.h + llparticipantlist.h llpatchvertexarray.h llplacesinventorybridge.h llpolymesh.h @@ -886,6 +894,8 @@ set(viewer_HEADER_FILES lltoolselectland.h lltoolselectrect.h lltracker.h + lltransientdockablefloater.h + lltransientfloatermgr.h lluiconstants.h lluilistener.h lluploaddialog.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9adf893e4b..30ba9f6e2c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4842,10 +4842,10 @@ <key>Value</key> <integer>350</integer> </map> - <key>NotificationToastTime</key> + <key>NotificationToastLifeTime</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Number of seconds while a notification toast exists</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4853,21 +4853,32 @@ <key>Value</key> <integer>5</integer> </map> + <key>NotificationTipToastLifeTime</key> + <map> + <key>Comment</key> + <string>Number of seconds while a notification tip toast exist</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>10</integer> + </map> <key>ToastOpaqueTime</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Number of seconds while a toast is fading </string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>S32</string> <key>Value</key> - <integer>4</integer> + <integer>1</integer> </map> - <key>StartUpToastTime</key> + <key>StartUpToastLifeTime</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Number of seconds while a StartUp toast exist</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4875,10 +4886,10 @@ <key>Value</key> <integer>5</integer> </map> - <key>ToastMargin</key> + <key>ToastGap</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Gap between toasts on a screen</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4889,7 +4900,7 @@ <key>ChannelBottomPanelMargin</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Space from a lower toast to the Bottom Tray</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4900,7 +4911,7 @@ <key>NotificationChannelRightMargin</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Space between toasts and a right border of an area where they can appear</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4911,7 +4922,7 @@ <key>OverflowToastHeight</key> <map> <key>Comment</key> - <string>Width of notification messages</string> + <string>Height of an overflow toast</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -8570,13 +8581,13 @@ <key>ToolTipVisibleTimeNear</key> <map> <key>Comment</key> - <string>Fade tooltip after after time passes (seconds) while mouse near tooltip</string> + <string>Fade tooltip after after time passes (seconds) while mouse near tooltip or original position</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>5.0</real> + <real>10.0</real> </map> <key>ToolTipVisibleTimeOver</key> <map> @@ -10537,6 +10548,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>ShowDeviceSettings</key> + <map> + <key>Comment</key> + <string>Show device settings</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>soundsbeacon</key> <map> <key>Comment</key> diff --git a/indra/newview/llagentpicksinfo.cpp b/indra/newview/llagentpicksinfo.cpp new file mode 100644 index 0000000000..6e5835bace --- /dev/null +++ b/indra/newview/llagentpicksinfo.cpp @@ -0,0 +1,130 @@ +/** + * @file llagentpicksinfo.cpp + * @brief LLAgentPicksInfo class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-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 "llagentpicksinfo.h" + +#include "llagent.h" +#include "llavatarconstants.h" +#include "llavatarpropertiesprocessor.h" + +class LLAgentPicksInfo::LLAgentPicksObserver : public LLAvatarPropertiesObserver +{ +public: + LLAgentPicksObserver() + { + LLAvatarPropertiesProcessor::getInstance()->addObserver(gAgent.getID(), this); + } + + ~LLAgentPicksObserver() + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(gAgent.getID(), this); + } + + void sendAgentPicksRequest() + { + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(gAgent.getID()); + } + + typedef boost::function<void(LLAvatarPicks*)> server_respond_callback_t; + + void setServerRespondCallback(const server_respond_callback_t& cb) + { + mServerRespondCallback = cb; + } + + virtual void processProperties(void* data, EAvatarProcessorType type) + { + if(APT_PICKS == type) + { + LLAvatarPicks* picks = static_cast<LLAvatarPicks*>(data); + if(picks && gAgent.getID() == picks->target_id) + { + if(mServerRespondCallback) + { + mServerRespondCallback(picks); + } + } + } + } + +private: + + server_respond_callback_t mServerRespondCallback; +}; + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLAgentPicksInfo::LLAgentPicksInfo() + : mAgentPicksObserver(NULL) + , mMaxNumberOfPicks(MAX_AVATAR_PICKS) + // Disable Pick creation until we get number of Picks from server - in case + // avatar has maximum number of Picks. + , mNumberOfPicks(mMaxNumberOfPicks) +{ +} + +LLAgentPicksInfo::~LLAgentPicksInfo() +{ + delete mAgentPicksObserver; +} + +void LLAgentPicksInfo::requestNumberOfPicks() +{ + if(!mAgentPicksObserver) + { + mAgentPicksObserver = new LLAgentPicksObserver(); + + mAgentPicksObserver->setServerRespondCallback(boost::bind( + &LLAgentPicksInfo::onServerRespond, this, _1)); + } + + mAgentPicksObserver->sendAgentPicksRequest(); +} + +bool LLAgentPicksInfo::isPickLimitReached() +{ + return getNumberOfPicks() >= getMaxNumberOfPicks(); +} + +void LLAgentPicksInfo::onServerRespond(LLAvatarPicks* picks) +{ + if(!picks) + { + llerrs << "Unexpected value" << llendl; + return; + } + + setNumberOfPicks(picks->picks_list.size()); +} diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h new file mode 100644 index 0000000000..0e30f2c5a0 --- /dev/null +++ b/indra/newview/llagentpicksinfo.h @@ -0,0 +1,106 @@ +/** + * @file llagentpicksinfo.h + * @brief LLAgentPicksInfo class header file + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-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_LLAGENTPICKS_H +#define LL_LLAGENTPICKS_H + +#include "llsingleton.h" + +struct LLAvatarPicks; + +/** + * Class that provides information about Agent Picks + */ +class LLAgentPicksInfo : public LLSingleton<LLAgentPicksInfo> +{ + class LLAgentPicksObserver; + +public: + + LLAgentPicksInfo(); + + virtual ~LLAgentPicksInfo(); + + /** + * Requests number of picks from server. + * + * Number of Picks is requested from server, thus it is not available immediately. + */ + void requestNumberOfPicks(); + + /** + * Returns number of Picks. + */ + S32 getNumberOfPicks() { return mNumberOfPicks; } + + /** + * Returns maximum number of Picks. + */ + S32 getMaxNumberOfPicks() { return mMaxNumberOfPicks; } + + /** + * Returns TRUE if Agent has maximum allowed number of Picks. + */ + bool isPickLimitReached(); + + /** + * After creating or deleting a Pick we can assume operation on server will be + * completed successfully. Incrementing/decrementing number of picks makes new number + * of picks available immediately. Actual number of picks will be updated when we receive + * response from server. + */ + void incrementNumberOfPicks() { ++mNumberOfPicks; } + + void decrementNumberOfPicks() { --mNumberOfPicks; } + +private: + + void onServerRespond(LLAvatarPicks* picks); + + /** + * Sets number of Picks. + */ + void setNumberOfPicks(S32 number) { mNumberOfPicks = number; } + + /** + * Sets maximum number of Picks. + */ + void setMaxNumberOfPicks(S32 max_picks) { mMaxNumberOfPicks = max_picks; } + +private: + + LLAgentPicksObserver* mAgentPicksObserver; + S32 mMaxNumberOfPicks; + S32 mNumberOfPicks; +}; + +#endif //LL_LLAGENTPICKS_H diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 34d2c00007..bb00468d40 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -68,8 +68,11 @@ public: EWearableType mType; LLUUID mItemID; LLUUID mAssetID; - InitialWearableData(EWearableType type, LLUUID itemID, LLUUID assetID) : - mType(type), mItemID(itemID), mAssetID(assetID) { } + InitialWearableData(EWearableType type, LLUUID& itemID, LLUUID& assetID) : + mType(type), + mItemID(itemID), + mAssetID(assetID) + {} }; typedef std::vector<InitialWearableData> initial_wearable_data_vec_t; @@ -654,7 +657,7 @@ U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearabl if (wearable == NULL) { // no null wearables please! - //TODO: insert llwarns + llwarns << "Null wearable sent for type " << type << llendl; return MAX_WEARABLES_PER_TYPE; } if (type < WT_COUNT || mWearableDatas[type].size() < MAX_WEARABLES_PER_TYPE) @@ -1090,7 +1093,7 @@ void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables) { for( S32 i = 0; i < WT_COUNT; ++i ) { - if (getWearableCount( (EWearableType) i) != 0 ) + if (getWearableCount((EWearableType) i) != 0) { wearables.push_back(i); } @@ -1300,8 +1303,8 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_all, U32 index) { - if ((gAgent.isTeen()) - && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) + if (gAgent.isTeen() && + (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) { // Can't take off underclothing in simple UI mode or on PG accounts // TODO: enable the removing of a single undershirt/underpants if multiple are worn. - Nyx diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0cf28f590a..1eaabd7ec3 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -966,7 +966,7 @@ void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update } /* static */ -void LLAppearanceManager::removeItemLinks(LLUUID& item_id, bool do_update) +void LLAppearanceManager::removeItemLinks(const LLUUID& item_id, bool do_update) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 928b5f2bcd..828af32101 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -62,7 +62,7 @@ public: static LLUUID getCOF(); // Remove COF entries - static void removeItemLinks(LLUUID& item_id, bool do_update = true); + static void removeItemLinks(const LLUUID& item_id, bool do_update = true); // For debugging - could be moved elsewhere. static void dumpCat(const LLUUID& cat_id, std::string str); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5b769dcab4..923a66ee8e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1206,6 +1206,9 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { + // workaround for DEV-35406 crash on shutdown + LLEventPumps::instance().reset(); + // *TODO - generalize this and move DSO wrangling to a helper class -brad std::set<struct apr_dso_handle_t *>::const_iterator i; for(i = mPlugins.begin(); i != mPlugins.end(); ++i) @@ -1214,9 +1217,7 @@ bool LLAppViewer::cleanup() apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); ll_plugin_stop_func(); - // *NOTE - disabled unloading as partial solution to DEV-35406 crash on shutdown - //rv = apr_dso_unload(*i); - (void)rv; + rv = apr_dso_unload(*i); } mPlugins.clear(); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index ef48420490..2034f98517 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -57,17 +57,13 @@ static const LLAvatarItemNameComparator NAME_COMPARATOR; static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR); LLAvatarList::Params::Params() -: -volume_column_width("volume_column_width", 0) -, online_go_first("online_go_first", true) +: ignore_online_status("ignore_online_status", false) { } - - LLAvatarList::LLAvatarList(const Params& p) : LLFlatListView(p) -, mOnlineGoFirst(p.online_go_first) +, mIgnoreOnlineStatus(p.ignore_online_status) , mContextMenu(NULL) , mDirty(true) // to force initial update { @@ -194,15 +190,15 @@ void LLAvatarList::refresh() } -void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos) +void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); item->showStatus(false); item->showInfoBtn(true); item->showSpeakingIndicator(true); item->setName(name); - item->setAvatarId(id); - item->setOnline(is_bold); + item->setAvatarId(id, mIgnoreOnlineStatus); + item->setOnline(mIgnoreOnlineStatus ? true : is_online); item->setContextMenu(mContextMenu); item->childSetVisible("info_btn", false); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index ec801645fe..7372538006 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -55,8 +55,7 @@ public: struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> { - Optional<S32> volume_column_width; - Optional<bool> online_go_first; + Optional<bool> ignore_online_status; // show all items as online Params(); }; @@ -76,7 +75,7 @@ public: protected: void refresh(); - void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + void addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos = ADD_BOTTOM); void computeDifference( const std::vector<LLUUID>& vnew, std::vector<LLUUID>& vadded, @@ -84,7 +83,7 @@ protected: private: - bool mOnlineGoFirst; + bool mIgnoreOnlineStatus; bool mDirty; std::string mNameFilter; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 90408beca0..732db90cdb 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -180,7 +180,7 @@ void LLAvatarListItem::setName(const std::string& name) mAvatarName->setToolTip(name); } -void LLAvatarListItem::setAvatarId(const LLUUID& id) +void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes) { if (mAvatarId.notNull()) LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this); @@ -190,7 +190,7 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id) mSpeakingIndicator->setSpeakerId(id); // We'll be notified on avatar online status changes - if (mAvatarId.notNull()) + if (!ignore_status_changes && mAvatarId.notNull()) LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this); // Set avatar name. diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 2330db5249..ca75e3898f 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -64,7 +64,7 @@ public: void setStatus(const std::string& status); void setOnline(bool online); void setName(const std::string& name); - void setAvatarId(const LLUUID& id); + void setAvatarId(const LLUUID& id, bool ignore_status_changes = false); const LLUUID& getAvatarId() const; const std::string getAvatarName() const; diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index f58c85d8c5..fb43b5a7d7 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -36,6 +36,7 @@ // Viewer includes #include "llagent.h" +#include "llagentpicksinfo.h" #include "llviewergenericmessage.h" // Linden library includes @@ -438,6 +439,9 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id ) msg->nextBlock(_PREHASH_Data); msg->addUUID(_PREHASH_PickID, pick_id); gAgent.sendReliableMessage(); + + LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); + LLAgentPicksInfo::getInstance()->decrementNumberOfPicks(); } void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) @@ -470,6 +474,8 @@ void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) msg->addBOOL(_PREHASH_Enabled, new_pick->enabled); gAgent.sendReliableMessage(); + + LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); } void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id) diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 8987f14e97..da84303863 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -134,8 +134,9 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id) case LLIMChiclet::TYPE_IM: return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id); case LLIMChiclet::TYPE_GROUP: - case LLIMChiclet::TYPE_AD_HOC: return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id); + case LLIMChiclet::TYPE_AD_HOC: + return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id); case LLIMChiclet::TYPE_UNKNOWN: break; } diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index c4619dc57a..77f941eef0 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -39,6 +39,7 @@ #include "llimview.h" #include "llbottomtray.h" #include "llviewerwindow.h" +#include "llrootview.h" #include <algorithm> @@ -121,6 +122,8 @@ void LLChannelManager::onLoginCompleted() return; } + gViewerWindow->getRootView()->addChild(mStartUpChannel); + // init channel's position and size S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); @@ -128,7 +131,7 @@ void LLChannelManager::onLoginCompleted() mStartUpChannel->setShowToasts(true); mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this)); - mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastTime")); + mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime")); } //-------------------------------------------------------------------------- @@ -139,19 +142,11 @@ void LLChannelManager::onStartUpToastClose() mStartUpChannel->setVisible(FALSE); mStartUpChannel->closeStartUpToast(); removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID"))); - delete mStartUpChannel; mStartUpChannel = NULL; } // set StartUp Toast Flag to allow all other channels to show incoming toasts LLScreenChannel::setStartUpToastShown(); - - // force NEARBY CHAT CHANNEL to repost all toasts if present - //LLScreenChannelBase* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - //!!!!!!!!!!!!!! - //FIXME - //nearby_channel->loadStoredToastsToChannel(); - //nearby_channel->setCanStoreToasts(false); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index cc21b636f1..ebf46a6e3f 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -101,12 +101,12 @@ void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& fr if (mLastFromName == from) { view = getSeparator(); - view_text = "\n"; + view_text = " "; } else { view = getHeader(avatar_id, from, time); - view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time; + view_text = "\n" + from + MESSAGE_USERNAME_DATE_SEPARATOR + time; } //Prepare the rect for the view LLRect target_rect = getDocumentView()->getRect(); @@ -115,12 +115,12 @@ void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& fr view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); - this->appendWidget(view, view_text, FALSE, TRUE); + appendWidget(view, view_text, FALSE, TRUE, mLeftWidgetPad, 0); //Append the text message - this->appendText(message, TRUE, style_params); + appendText(message, TRUE, style_params); mLastFromName = from; - this->blockUndo(); - this->setCursorAndScrollToEnd(); + blockUndo(); + setCursorAndScrollToEnd(); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 340b0fa22c..2ebbae33ad 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -468,6 +468,115 @@ void LLIMP2PChiclet::setShowSpeaker(bool show) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +LLAdHocChiclet::Params::Params() +: avatar_icon("avatar_icon") +, unread_notifications("unread_notifications") +, speaker("speaker") +, show_speaker("show_speaker") +{ + // *TODO Vadim: Get rid of hardcoded values. + rect(LLRect(0, 25, 45, 0)); + + avatar_icon.name("avatar_icon"); + avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + + // *NOTE dzaporozhan + // Changed icon height from 25 to 24 to fix ticket EXT-794. + // In some cases(after changing UI scale) 25 pixel height icon was + // drawn incorrectly, i'm not sure why. + avatar_icon.rect(LLRect(0, 24, 25, 0)); + avatar_icon.mouse_opaque(false); + + unread_notifications.name("unread"); + unread_notifications.rect(LLRect(25, 25, 45, 0)); + unread_notifications.font(LLFontGL::getFontSansSerif()); + unread_notifications.font_halign(LLFontGL::HCENTER); + unread_notifications.v_pad(5); + unread_notifications.text_color(LLColor4::white); + unread_notifications.mouse_opaque(false); + + speaker.name("speaker"); + speaker.rect(LLRect(45, 25, 65, 0)); + + show_speaker = false; +} + +LLAdHocChiclet::LLAdHocChiclet(const Params& p) +: LLIMChiclet(p) +, mChicletIconCtrl(NULL) +, mCounterCtrl(NULL) +, mSpeakerCtrl(NULL) +, mPopupMenu(NULL) +{ + LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; + mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); + addChild(mChicletIconCtrl); + + LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; + mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); + addChild(mCounterCtrl); + + setCounter(getCounter()); + setShowCounter(getShowCounter()); + + LLChicletSpeakerCtrl::Params speaker_params = p.speaker; + mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); + addChild(mSpeakerCtrl); + + setShowSpeaker(p.show_speaker); +} + +void LLAdHocChiclet::setSessionId(const LLUUID& session_id) +{ + LLChiclet::setSessionId(session_id); + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); + mChicletIconCtrl->setValue(im_session->mOtherParticipantID); +} + +void LLAdHocChiclet::setCounter(S32 counter) +{ + mCounterCtrl->setCounter(counter); + + if(getShowCounter()) + { + LLRect counter_rect = mCounterCtrl->getRect(); + LLRect required_rect = mCounterCtrl->getRequiredRect(); + bool needs_resize = required_rect.getWidth() != counter_rect.getWidth(); + + if(needs_resize) + { + counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth(); + mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight()); + mCounterCtrl->setRect(counter_rect); + + onChicletSizeChanged(); + } + } +} + +LLRect LLAdHocChiclet::getRequiredRect() +{ + LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); + if(getShowCounter()) + { + rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); + } + if(getShowSpeaker()) + { + rect.mRight += mSpeakerCtrl->getRect().getWidth(); + } + return rect; +} + +BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return TRUE; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + LLIMGroupChiclet::Params::Params() : group_icon("group_icon") { @@ -752,25 +861,36 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ BOOL LLChicletPanel::postBuild() { LLPanel::postBuild(); - LLIMModel::instance().addChangedCallback(boost::bind(im_chiclet_callback, this, _1)); + LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1)); + LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); return TRUE; } +S32 LLChicletPanel::calcChickletPanleWidth() +{ + S32 res = 0; + + for (chiclet_list_t::iterator it = mChicletList.begin(); it + != mChicletList.end(); it++) + { + res = (*it)->getRect().getWidth() + getChicletPadding(); + } + return res; +} + bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) { if(mScrollArea->addChild(chiclet)) { + // chicklets should be aligned to right edge of scroll panel S32 offset = 0; - // if index == 0 and chickelt list isn't empty insert chiclet before first in the list - // without scrolling, so other visible chicklets aren't change screen position - if (0 == index && !mChicletList.empty()) + if (!canScrollLeft()) { - offset = getChiclet(0)->getRect().mLeft - - (chiclet->getRequiredRect().getWidth() - + getChicletPadding()); + offset = mScrollArea->getRect().getWidth() + - chiclet->getRect().getWidth() - calcChickletPanleWidth(); } mChicletList.insert(mChicletList.begin() + index, chiclet); @@ -963,25 +1083,16 @@ void LLChicletPanel::arrange() void LLChicletPanel::trimChiclets() { // trim right - if(canScrollLeft() && !canScrollRight()) + if(!mChicletList.empty()) { S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight; + S32 first_chiclet_left = getChiclet(0)->getRect().mLeft; S32 scroll_width = mScrollArea->getRect().getWidth(); - if(last_chiclet_right < scroll_width) + if(last_chiclet_right < scroll_width || first_chiclet_left > 0) { shiftChiclets(scroll_width - last_chiclet_right); } } - - // trim left - if(!mChicletList.empty()) - { - LLRect first_chiclet_rect = getChiclet(0)->getRect(); - if(first_chiclet_rect.mLeft > 0) - { - shiftChiclets( - first_chiclet_rect.mLeft); - } - } } void LLChicletPanel::showScrollButtonsIfNeeded() diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 458bc73bc4..1713c0258d 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -442,6 +442,65 @@ private: }; /** + * Implements AD-HOC chiclet. + */ +class LLAdHocChiclet : public LLIMChiclet +{ +public: + struct Params : public LLInitParam::Block<Params, LLChiclet::Params> + { + Optional<LLChicletAvatarIconCtrl::Params> avatar_icon; + + Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; + + Optional<LLChicletSpeakerCtrl::Params> speaker; + + Optional<bool> show_speaker; + + Params(); + }; + + /** + * Sets session id. + * Session ID for group chat is actually Group ID. + */ + /*virtual*/ void setSessionId(const LLUUID& session_id); + + /* + * Sets number of unread messages. Will update chiclet's width if number text + * exceeds size of counter and notify it's parent about size change. + */ + /*virtual*/ void setCounter(S32); + + /* + * Returns number of unread messages. + */ + /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + + /* + * Returns rect, required to display chiclet. + * Width is the only valid value. + */ + /*virtual*/ LLRect getRequiredRect(); + +protected: + LLAdHocChiclet(const Params& p); + friend class LLUICtrlFactory; + + /* + * Displays popup menu. + */ + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + +private: + + LLChicletAvatarIconCtrl* mChicletIconCtrl; + LLChicletNotificationCounterCtrl* mCounterCtrl; + LLChicletSpeakerCtrl* mSpeakerCtrl; + LLMenuGL* mPopupMenu; +}; + +/** * Implements Group chat chiclet. */ class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver @@ -594,9 +653,14 @@ public: virtual ~LLChicletPanel(); /* - * Creates chiclet and adds it to chiclet list. + * Creates chiclet and adds it to chiclet list at specified index. */ - template<class T> T* createChiclet(const LLUUID& session_id = LLUUID::null, S32 index = 0); + template<class T> T* createChiclet(const LLUUID& session_id, S32 index); + + /* + * Creates chiclet and adds it to chiclet list at right. + */ + template<class T> T* createChiclet(const LLUUID& session_id); /* * Returns pointer to chiclet of specified type at specified index. @@ -664,6 +728,8 @@ protected: LLChicletPanel(const Params&p); friend class LLUICtrlFactory; + S32 calcChickletPanleWidth(); + /* * Adds chiclet to list and rearranges all chiclets. */ @@ -804,7 +870,7 @@ private: }; template<class T> -T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S32 index /*= 0*/) +T* LLChicletPanel::createChiclet(const LLUUID& session_id, S32 index) { typename T::Params params; T* chiclet = LLUICtrlFactory::create<T>(params); @@ -831,6 +897,12 @@ T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S3 } template<class T> +T* LLChicletPanel::createChiclet(const LLUUID& session_id) +{ + return createChiclet<T>(session_id, mChicletList.size()); +} + +template<class T> T* LLChicletPanel::findChiclet(const LLUUID& im_session_id) { if(im_session_id.isNull()) diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp index 225f177546..5813943ad3 100644 --- a/indra/newview/llconfirmationmanager.cpp +++ b/indra/newview/llconfirmationmanager.cpp @@ -39,6 +39,7 @@ // viewer includes #include "llnotifications.h" #include "llstring.h" +#include "llxmlnode.h" LLConfirmationManager::ListenerBase::~ListenerBase() { diff --git a/indra/newview/lldndbutton.cpp b/indra/newview/lldndbutton.cpp new file mode 100644 index 0000000000..22f2bb1d16 --- /dev/null +++ b/indra/newview/lldndbutton.cpp @@ -0,0 +1,60 @@ +/** + * @file lldndbutton.cpp + * @brief Implementation of the drag-n-drop button. + * + * $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 "llviewerprecompiledheaders.h" + +#include "lldndbutton.h" + + +static LLDefaultChildRegistry::Register<LLDragAndDropButton> r("dnd_button"); + +LLDragAndDropButton::Params::Params() +{ + +} + +LLDragAndDropButton::LLDragAndDropButton(Params& params) +: LLButton(params) +{ + +} + +BOOL LLDragAndDropButton::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) +{ + if (mDragDropHandler) + { + return mDragDropHandler(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + return false; +} + +// EOF diff --git a/indra/newview/lldndbutton.h b/indra/newview/lldndbutton.h new file mode 100644 index 0000000000..c888268187 --- /dev/null +++ b/indra/newview/lldndbutton.h @@ -0,0 +1,89 @@ +/** + * @file lldndbutton.h + * @brief Declaration of the drag-n-drop button. + * + * $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$ + */ + +#ifndef LL_LLDNDBUTTON_H +#define LL_LLDNDBUTTON_H + +#include "llbutton.h" + +/** + * Class representing a button which can handle Drag-And-Drop event. + * + * LLDragAndDropButton does not contain any logic to handle Drag-And-Drop itself. + * Instead it provides drag_drop_handler_t which can be set to the button. + * Then each Drag-And-Drop will be delegated to this handler without any pre/post processing. + * + * All xml parameters are the same as LLButton has. + * + * @see LLLandmarksPanel for example of usage of this class. + */ +class LLDragAndDropButton : public LLButton +{ +public: + struct Params : public LLInitParam::Block<Params, LLButton::Params> + { + Params(); + }; + + LLDragAndDropButton(Params& params); + + typedef boost::function<bool ( + S32 /*x*/, S32 /*y*/, MASK /*mask*/, BOOL /*drop*/, + EDragAndDropType /*cargo_type*/, + void* /*cargo_data*/, + EAcceptance* /*accept*/, + std::string& /*tooltip_msg*/)> drag_drop_handler_t; + + + /** + * Sets a handler which should process Drag-And-Drop. + */ + void setDragAndDropHandler(drag_drop_handler_t handler) { mDragDropHandler = handler; } + + + /** + * Process Drag-And-Drop by delegating the event to drag_drop_handler_t. + * + * @return BOOL - value returned by drag_drop_handler_t if it is set, FALSE otherwise. + */ + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + +private: + drag_drop_handler_t mDragDropHandler; +}; + + +#endif // LL_LLDNDBUTTON_H diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index e7295512c1..45f4b4fbd0 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -156,13 +156,17 @@ void LLDriverParamInfo::toStream(std::ostream &out) // LLDriverParam //----------------------------------------------------------------------------- -LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) - : mCurrentDistortionParam( NULL ), mAvatarp(avatarp), mWearablep(NULL) +LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : + mCurrentDistortionParam( NULL ), + mAvatarp(avatarp), + mWearablep(NULL) { } -LLDriverParam::LLDriverParam(LLWearable *wearablep) - : mCurrentDistortionParam( NULL ), mAvatarp(NULL), mWearablep(wearablep) +LLDriverParam::LLDriverParam(LLWearable *wearablep) : + mCurrentDistortionParam( NULL ), + mAvatarp(NULL), + mWearablep(wearablep) { } @@ -201,7 +205,7 @@ void LLDriverParam::setAvatar(LLVOAvatar *avatarp) } } -/*virtual*/ LLViewerVisualParam * LLDriverParam::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const { LLDriverParam *new_param; if (wearable) @@ -481,7 +485,7 @@ void LLDriverParam::stopAnimating(BOOL set_by_user) } /*virtual*/ -BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) +BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params) { BOOL success = TRUE; LLDriverParamInfo::entry_info_list_t::iterator iter; @@ -584,7 +588,8 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool set_by_user) { LLVOAvatarSelf *avatar_self = gAgent.getAvatarObject(); - if(mWearablep && driven->mParam->getCrossWearable() && + if(mWearablep && + driven->mParam->getCrossWearable() && mWearablep->isOnTop()) { // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index c73e740574..069e71a2cb 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -94,7 +94,7 @@ public: void setWearable(LLWearable *wearablep); void setAvatar(LLVOAvatar *avatarp); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); @@ -102,7 +102,7 @@ public: /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); /*virtual*/ void setAnimationTarget( F32 target_value, BOOL set_by_user ); /*virtual*/ void stopAnimating(BOOL set_by_user); - /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, bool only_cross_params); + /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); /*virtual*/ void resetDrivenParams(); // LLViewerVisualParam Virtual functions diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index de079b7123..893b12ec35 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -272,6 +272,8 @@ void LLFirstUse::useMedia() { gWarningSettings.setBOOL("FirstMedia", FALSE); - LLNotifications::instance().add("FirstMedia"); + // Popup removed as a short-term fix for EXT-1643. + // Ultimately, the plan is to kill all First Use dialogs + //LLNotifications::instance().add("FirstMedia"); } } diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index db20b11efd..fc661772a6 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -125,9 +125,15 @@ void LLFloaterCamera::onOpen(const LLSD& key) } +void LLFloaterCamera::onClose(bool app_quitting) +{ + //We don't care of camera mode if app is quitting + if(!app_quitting) + switchMode(CAMERA_CTRL_MODE_ORBIT); +} LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLDockableFloater(NULL, val), +: LLTransientDockableFloater(NULL, true, val), mCurrMode(CAMERA_CTRL_MODE_ORBIT), mPrevMode(CAMERA_CTRL_MODE_ORBIT) { @@ -286,7 +292,7 @@ void LLFloaterCamera::updateState() //-------------LLFloaterCameraPresets------------------------ LLFloaterCameraPresets::LLFloaterCameraPresets(const LLSD& key): -LLDockableFloater(NULL, key) +LLTransientDockableFloater(NULL, true, key) {} BOOL LLFloaterCameraPresets::postBuild() diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 69df861a20..ba943e66ed 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -33,7 +33,7 @@ #ifndef LLFLOATERCAMERA_H #define LLFLOATERCAMERA_H -#include "lldockablefloater.h" +#include "lltransientdockablefloater.h" class LLJoystickCameraRotate; class LLJoystickCameraZoom; @@ -49,7 +49,7 @@ enum ECameraControlMode }; class LLFloaterCamera - : public LLDockableFloater + : public LLTransientDockableFloater { friend class LLFloaterReg; @@ -69,6 +69,7 @@ public: static void updateIfNotInAvatarViewMode(); virtual void onOpen(const LLSD& key); + virtual void onClose(bool app_quitting); LLJoystickCameraRotate* mRotate; LLJoystickCameraZoom* mZoom; @@ -111,7 +112,7 @@ private: }; -class LLFloaterCameraPresets : public LLDockableFloater +class LLFloaterCameraPresets : public LLTransientDockableFloater { friend class LLFloaterReg; public: diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index a33a605f50..4596ae7739 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -1174,7 +1174,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) mHasInventoryConnection(false), mStartFolderString(p.start_folder) , mBuildDefaultHierarchy(true) -, mRootInventoryItemUUID(LLUUID::null) , mInvFVBridgeBuilder(NULL) { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; @@ -1241,7 +1240,19 @@ BOOL LLInventoryPanel::postBuild() // determine the root folder, if any, so inventory contents show just the children // of that folder (i.e. not including the folder itself). const LLAssetType::EType preferred_type = LLAssetType::lookupHumanReadable(mStartFolderString); - mStartFolderID = (preferred_type != LLAssetType::AT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); + + if ("inventory" == mStartFolderString) + { + mStartFolderID = gInventory.getRootFolderID(); + } + else if ("library" == mStartFolderString) + { + mStartFolderID = gInventory.getLibraryRootFolderID(); + } + else + { + mStartFolderID = (preferred_type != LLAssetType::AT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); + } // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection) @@ -1462,24 +1473,6 @@ void LLInventoryPanel::modelChanged(U32 mask) } } -void LLInventoryPanel::setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder) -{ - if (NULL == bridge_builder) - { - llwarns << "NULL is passed as Inventory Bridge Builder. Default will be used." << llendl; - } - else - { - mInvFVBridgeBuilder = bridge_builder; - } - - if (mInventory->isInventoryUsable() && !mHasInventoryConnection) - { - rebuildViewsFor(mRootInventoryItemUUID); - mHasInventoryConnection = true; - } -} - void LLInventoryPanel::rebuildViewsFor(const LLUUID& id) { @@ -1508,14 +1501,28 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) objectp = gInventory.getObject(id); if (objectp) { + const LLUUID &parent_id = objectp->getParentUUID(); + // If this item's parent is the starting folder, then just add it to the top level (recall that + // the starting folder isn't actually represented in the view, parent_folder would be NULL in + // this case otherwise). + LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ? + mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id)); + + // This item exists outside the inventory's hierarchy, so don't add it. + if (!parent_folder) + { + return; + } + if (objectp->getType() <= LLAssetType::AT_NONE || objectp->getType() >= LLAssetType::AT_COUNT) { - llwarns << "LLInventoryPanel::buildNewViews called with objectp->mType == " - << ((S32) objectp->getType()) - << " (shouldn't happen)" << llendl; + llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " << + ((S32) objectp->getType()) << llendl; + return; } - else if (objectp->getType() == LLAssetType::AT_CATEGORY && + + if (objectp->getType() == LLAssetType::AT_CATEGORY && objectp->getActualType() != LLAssetType::AT_LINK_FOLDER) { LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), @@ -1563,27 +1570,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) if (itemp) { - - const LLUUID &parent_id = objectp->getParentUUID(); - LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(parent_id); - - // If this item's parent is the starting folder, then just add it to the top level (recall that - // the starting folder isn't actually represented in the view, parent_folder would be NULL in - // this case otherwise). - if (parent_id == mStartFolderID) - { - parent_folder = mFolders; - } - - if (parent_folder) - { - itemp->addToFolder(parent_folder, mFolders); - } - else - { - llwarns << "Couldn't find parent folder for child " << itemp->getLabel() << llendl; - delete itemp; - } + itemp->addToFolder(parent_folder, mFolders); } } } diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h index 1666f18c05..4c9ac5d4c6 100644 --- a/indra/newview/llfloaterinventory.h +++ b/indra/newview/llfloaterinventory.h @@ -175,9 +175,6 @@ protected: void rebuildViewsFor(const LLUUID& id); virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 - // Be sure that passed pointer will be destroyed where it was created. - void setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder); - protected: LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; @@ -187,6 +184,12 @@ protected: //private: // Can not make these private - needed by llinventorysubtreepanel LLFolderView* mFolders; std::string mStartFolderString; + + /** + * Contains UUID of Inventory item from which hierarchy should be built. + * Can be set with the "start_folder" xml property. + * Default is LLUUID::null that means total Inventory hierarchy. + */ LLUUID mStartFolderID; LLScrollContainer* mScroller; bool mHasInventoryConnection; @@ -196,11 +199,6 @@ protected: */ bool mBuildDefaultHierarchy; - /** - * Contains UUID of Inventory item from which hierarchy should be built. - * Should be set by derived class before modelChanged() is called. - * Default is LLUUID::null that means total Inventory hierarchy. - */ LLUUID mRootInventoryItemUUID; /** diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index de0b995f8f..ac743df4f1 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -553,32 +553,33 @@ void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl) void LLFloaterUIPreview::onClickExportSchema() { - gViewerWindow->setCursor(UI_CURSOR_WAIT); - std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema"); - - typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it; - registry_it end_it = LLWidgetTypeRegistry::defaultRegistrar().endItems(); - for(registry_it it = LLWidgetTypeRegistry::defaultRegistrar().beginItems(); - it != end_it; - ++it) - { - std::string widget_name = it->first; - const LLInitParam::BaseBlock& block = - (*LLDefaultParamBlockRegistry::instance().getValue(*LLWidgetTypeRegistry::instance().getValue(widget_name)))(); - LLXMLNodePtr root_nodep = new LLXMLNode(); - LLRNGWriter().writeRNG(widget_name, root_nodep, block, "http://www.lindenlab.com/xui"); - - std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng"); - - LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w"); - { - LLXMLNode::writeHeaderToFile(rng_file); - const bool use_type_decorations = false; - root_nodep->writeToFile(rng_file, std::string(), use_type_decorations); - } - fclose(rng_file); - } - gViewerWindow->setCursor(UI_CURSOR_ARROW); + //NOTE: schema generation not complete + //gViewerWindow->setCursor(UI_CURSOR_WAIT); + //std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema"); + + //typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it; + //registry_it end_it = LLWidgetTypeRegistry::defaultRegistrar().endItems(); + //for(registry_it it = LLWidgetTypeRegistry::defaultRegistrar().beginItems(); + // it != end_it; + // ++it) + //{ + // std::string widget_name = it->first; + // const LLInitParam::BaseBlock& block = + // (*LLDefaultParamBlockRegistry::instance().getValue(*LLWidgetTypeRegistry::instance().getValue(widget_name)))(); + // LLXMLNodePtr root_nodep = new LLXMLNode(); + // LLRNGWriter().writeRNG(widget_name, root_nodep, block, "http://www.lindenlab.com/xui"); + + // std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng"); + + // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w"); + // { + // LLXMLNode::writeHeaderToFile(rng_file); + // const bool use_type_decorations = false; + // root_nodep->writeToFile(rng_file, std::string(), use_type_decorations); + // } + // fclose(rng_file); + //} + //gViewerWindow->setCursor(UI_CURSOR_ARROW); } void LLFloaterUIPreview::onClickShowRectangles(const LLSD& data) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 155262ee13..de18e74752 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -189,9 +189,9 @@ LLFolderView::LLFolderView(const Params& p) mMinWidth(0), mDragAndDropThisFrame(FALSE), mCallbackRegistrar(NULL), - mParentPanel(p.parent_panel) -, mUseEllipses(false) -, mDraggingOverItem(NULL) + mParentPanel(p.parent_panel), + mUseEllipses(false), + mDraggingOverItem(NULL) { LLRect rect = p.rect; LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); @@ -1240,7 +1240,9 @@ BOOL LLFolderView::canCut() const { const LLFolderViewItem* item = *selected_it; const LLFolderViewEventListener* listener = item->getListener(); - if (!listener || !listener->isItemMovable()) + + // *WARKAROUND: it is too many places where the "isItemRemovable" method should be changed with "const" modifier + if (!listener || !(const_cast<LLFolderViewEventListener*>(listener))->isItemRemovable()) { return FALSE; } diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 9208beec9e..f83a426cda 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -890,11 +890,11 @@ void LLFolderViewItem::draw() llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), sHighlightFgColor, FALSE); } - if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 2) + if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 4) { gl_rect_2d( 0, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4, getRect().getWidth() - 2, 2, sHighlightFgColor, FALSE); @@ -902,7 +902,7 @@ void LLFolderViewItem::draw() { gl_rect_2d( 0, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, + llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4, getRect().getWidth() - 2, 2, sHighlightBgColor, TRUE); diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 90c346b381..62a4b9a187 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -202,6 +202,7 @@ public: virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); virtual S32 getItemHeight(); void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarhy = dont_show; } + bool getDontShowInHierarchy() { return mDontShowInHierarhy; } // applies filters to control visibility of inventory items virtual void filter( LLInventoryFilter& filter); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 97b7f3e9ad..fbcaeee01f 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -166,6 +166,93 @@ bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* i return items.count() > 0; } + +bool LLFriendCardsManager::isObjDirectDescendentOfCategory(const LLInventoryObject* obj, + const LLViewerInventoryCategory* cat) const +{ + // we need both params to proceed. + if ( !obj || !cat ) + return false; + + // Need to check that target category is in the Calling Card/Friends folder. + // In other case function returns unpredictable result. + if ( !isCategoryInFriendFolder(cat) ) + return false; + + bool result = false; + + LLInventoryModel::item_array_t* items; + LLInventoryModel::cat_array_t* cats; + + gInventory.lockDirectDescendentArrays(cat->getUUID(), cats, items); + if ( items ) + { + if ( obj->getType() == LLAssetType::AT_CALLINGCARD ) + { + // For CALLINGCARD compare items by creator's id, if they are equal assume + // that it is same card and return true. Note: UUID's of compared items + // may be not equal. Also, we already know that obj should be type of LLInventoryItem, + // but in case inventory database is broken check what dynamic_cast returns. + const LLInventoryItem* item = dynamic_cast < const LLInventoryItem* > (obj); + if ( item ) + { + LLUUID creator_id = item->getCreatorUUID(); + LLViewerInventoryItem* cur_item = NULL; + for ( S32 i = items->count() - 1; i >= 0; --i ) + { + cur_item = items->get(i); + if ( creator_id == cur_item->getCreatorUUID() ) + { + result = true; + break; + } + } + } + } + else + { + // Else check that items have same type and name. + // Note: UUID's of compared items also may be not equal. + std::string obj_name = obj->getName(); + LLViewerInventoryItem* cur_item = NULL; + for ( S32 i = items->count() - 1; i >= 0; --i ) + { + cur_item = items->get(i); + if ( obj->getType() != cur_item->getType() ) + continue; + if ( obj_name == cur_item->getName() ) + { + result = true; + break; + } + } + } + } + if ( !result && cats ) + { + // There is no direct descendent in items, so check categories. + // If target obj and descendent category have same type and name + // then return true. Note: UUID's of compared items also may be not equal. + std::string obj_name = obj->getName(); + LLViewerInventoryCategory* cur_cat = NULL; + for ( S32 i = cats->count() - 1; i >= 0; --i ) + { + cur_cat = cats->get(i); + if ( obj->getType() != cur_cat->getType() ) + continue; + if ( obj_name == cur_cat->getName() ) + { + result = true; + break; + } + } + } + gInventory.unlockDirectDescendentArrays(cat->getUUID()); + + return result; +} + + bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const { if (NULL == cat) diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index aa391ce2c1..6ada342831 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -72,6 +72,12 @@ public: bool isItemInAnyFriendsList(const LLViewerInventoryItem* item); /** + * Checks if specified category is contained in the Calling Card/Friends folder and + * determines if specified Inventory Object exists in that category. + */ + bool isObjDirectDescendentOfCategory(const LLInventoryObject* obj, const LLViewerInventoryCategory* cat) const; + + /** * Checks is the specified category is in the Calling Card/Friends folder */ bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a35c04440b..8f0186ce24 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -55,7 +55,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) - : LLDockableFloater(NULL, session_id), + : LLTransientDockableFloater(NULL, true, session_id), mControlPanel(NULL), mSessionID(session_id), mLastMessageIndex(-1), @@ -81,17 +81,22 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); } } +} + +void LLIMFloater::onFocusLost() +{ + LLIMModel::getInstance()->resetActiveSessionID(); +} - LLTransientFloaterMgr::getInstance()->registerTransientFloater(this); +void LLIMFloater::onFocusReceived() +{ + LLIMModel::getInstance()->setActiveSessionID(mSessionID); } // virtual void LLIMFloater::onClose(bool app_quitting) { - LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID); - - //*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB) - gIMMgr->removeSession(mSessionID); + gIMMgr->leaveSession(mSessionID); } /* static */ @@ -116,6 +121,23 @@ void LLIMFloater::newIMCallback(const LLSD& data){ } } +void LLIMFloater::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (visible && voice_channel && + voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + { + LLFloaterReg::showInstance("voice_call", mSessionID); + } + else + { + LLFloaterReg::hideInstance("voice_call", mSessionID); + } +} + void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) { LLIMFloater* self = (LLIMFloater*) userdata; @@ -163,7 +185,6 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { - LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); } //virtual @@ -297,7 +318,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) (LLNotificationsUI::LLChannelManager::getInstance()-> findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - LLDockableFloater::setDocked(docked, pop_on_undock); + LLTransientDockableFloater::setDocked(docked, pop_on_undock); // update notification channel state if(channel) @@ -311,7 +332,7 @@ void LLIMFloater::setVisible(BOOL visible) LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - LLDockableFloater::setVisible(visible); + LLTransientDockableFloater::setVisible(visible); // update notification channel state if(channel) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 9b519ee7e3..8fd0c7cde9 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -33,7 +33,7 @@ #ifndef LL_IMFLOATER_H #define LL_IMFLOATER_H -#include "lldockablefloater.h" +#include "lltransientdockablefloater.h" #include "lllogchat.h" class LLLineEditor; @@ -45,7 +45,7 @@ class LLViewerTextEditor; * Individual IM window that appears at the bottom of the screen, * optionally "docked" to the bottom tray. */ -class LLIMFloater : public LLDockableFloater +class LLIMFloater : public LLTransientDockableFloater { public: LLIMFloater(const LLUUID& session_id); @@ -84,7 +84,12 @@ public: // called when docked floater's position has been set by chiclet void setPositioned(bool b) { mPositioned = b; }; + void onVisibilityChange(const LLSD& new_visibility); + private: + // process focus events to set a currently active session + /* virtual */ void onFocusLost(); + /* virtual */ void onFocusReceived(); static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0ff3bd24e9..163984f740 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -951,7 +951,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mSentTypingState(TRUE), mNumUnreadMessages(0), mShowSpeakersOnConnect(TRUE), - mAutoConnect(FALSE), mTextIMPossible(TRUE), mProfileButtonEnabled(TRUE), mCallBackEnabled(TRUE), @@ -1179,12 +1178,6 @@ void LLFloaterIMPanel::draw() mInputEditor->setLabel(getString("default_text_label")); } - if (mAutoConnect && enable_connect) - { - onClickStartCall(this); - mAutoConnect = FALSE; - } - // show speakers window when voice first connects if (mShowSpeakersOnConnect && voice_channel->isActive()) { @@ -1525,7 +1518,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->activate(); + gIMMgr->startCall(self->mSessionUUID); } // static @@ -1533,7 +1526,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->deactivate(); + gIMMgr->endCall(self->mSessionUUID); } // static @@ -1593,9 +1586,7 @@ void LLFloaterIMPanel::onClose(bool app_quitting) { setTyping(FALSE); - LLIMModel::instance().sendLeaveSession(mSessionUUID, mOtherParticipantUUID); - - gIMMgr->removeSession(mSessionUUID); + gIMMgr->leaveSession(mSessionUUID); // *HACK hide the voice floater LLFloaterReg::hideInstance("voice_call", mSessionUUID); @@ -1712,11 +1703,6 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) } } -void LLFloaterIMPanel::requestAutoConnect() -{ - mAutoConnect = TRUE; -} - void LLFloaterIMPanel::setTyping(BOOL typing) { LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID); diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 57379b2c0d..4e306c7fab 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -250,8 +250,6 @@ public: EInstantMessage getDialogType() const { return mDialog; } void setDialogType(EInstantMessage dialog) { mDialog = dialog; } - void requestAutoConnect(); - void sessionInitReplyReceived(const LLUUID& im_session_id); // Handle other participant in the session typing. @@ -336,8 +334,6 @@ private: BOOL mShowSpeakersOnConnect; - BOOL mAutoConnect; - BOOL mTextIMPossible; BOOL mProfileButtonEnabled; BOOL mCallBackEnabled; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 619e7044b4..9486698c89 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -93,30 +93,45 @@ std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap; void toast_callback(const LLSD& msg){ - // do not show toast in busy mode - if (gAgent.getBusy()) + // do not show toast in busy mode or it goes from agent + if (gAgent.getBusy() || gAgent.getID() == msg["from_id"]) { return; } - - //we send notifications to reset counter also - if (msg["num_unread"].asInteger()) + + // check whether incoming IM belongs to an active session or not + if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"]) { - LLSD args; - args["MESSAGE"] = msg["message"]; - args["TIME"] = msg["time"]; - args["FROM"] = msg["from"]; - args["FROM_ID"] = msg["from_id"]; - args["SESSION_ID"] = msg["session_id"]; + return; + } + + LLSD args; + args["MESSAGE"] = msg["message"]; + args["TIME"] = msg["time"]; + args["FROM"] = msg["from"]; + args["FROM_ID"] = msg["from_id"]; + args["SESSION_ID"] = msg["session_id"]; - LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID())); + LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID())); +} + +void LLIMModel::setActiveSessionID(const LLUUID& session_id) +{ + // check if such an ID really exists + if (!findIMSession(session_id)) + { + llwarns << "Trying to set as active a non-existent session!" << llendl; + return; } + + mActiveSessionID = session_id; } LLIMModel::LLIMModel() { - addChangedCallback(LLIMFloater::newIMCallback); - addChangedCallback(toast_callback); + addNewMsgCallback(LLIMFloater::newIMCallback); + addNoUnreadMsgsCallback(LLIMFloater::newIMCallback); + addNewMsgCallback(toast_callback); } @@ -311,7 +326,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index) LLSD arg; arg["session_id"] = session_id; arg["num_unread"] = 0; - mChangedSignal(arg); + mNoUnreadMsgsSignal(arg); // TODO: in the future is there a more efficient way to return these //of course there is - return as parameter (IB) @@ -390,7 +405,7 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, arg["from"] = from; arg["from_id"] = from_id; arg["time"] = LLLogChat::timestamp(false); - mChangedSignal(arg); + mNewMsgSignal(arg); return true; } @@ -620,14 +635,8 @@ void LLIMModel::sendMessage(const std::string& utf8_text, } // Add the recipient to the recent people list. - //*TODO should be deleted, because speaker manager updates through callback the recent list LLRecentPeople::instance().add(other_participant_id); } - -boost::signals2::connection LLIMModel::addChangedCallback( boost::function<void (const LLSD& data)> cb ) -{ - return mChangedSignal.connect(cb); -} void session_starter_helper( const LLUUID& temp_session_id, @@ -854,23 +863,18 @@ public: //in case of race conditions speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID)); } - - LLFloaterIMPanel* floaterp = - gIMMgr->findFloaterBySession(mSessionID); - if (floaterp) + if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType) { - if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE ) - { - floaterp->requestAutoConnect(); - LLFloaterIMPanel::onClickStartCall(floaterp); - // always open IM window when connecting to voice - LLFloaterReg::showInstance("communicate", LLSD(), TRUE); - } - else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE ) - { - LLFloaterReg::showInstance("communicate", LLSD(), TRUE); - } + gIMMgr->startCall(mSessionID); + } + + if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE + || mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE) + && LLIMModel::getInstance()->findIMSession(mSessionID)) + { + // always open IM window when connecting to voice + LLIMFloater::show(mSessionID); } gIMMgr->clearPendingAgentListUpdates(mSessionID); @@ -1041,20 +1045,13 @@ void LLIncomingCallDialog::processCallResponse(S32 response) if (voice) { - LLFloaterIMPanel* im_floater = - gIMMgr->findFloaterBySession( - session_id); - - if (im_floater) + if (gIMMgr->startCall(session_id)) { - im_floater->requestAutoConnect(); - LLFloaterIMPanel::onClickStartCall(im_floater); + // always open IM window when connecting to voice + LLIMFloater::show(session_id); } } - // always open IM window when connecting to voice - LLFloaterReg::showInstance("communicate", session_id); - gIMMgr->clearPendingAgentListUpdates(session_id); gIMMgr->clearPendingInvitation(session_id); } @@ -1159,15 +1156,10 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) payload["session_handle"].asString(), payload["session_uri"].asString()); - LLFloaterIMPanel* im_floater = - gIMMgr->findFloaterBySession( - session_id); - if (im_floater) + if (gIMMgr->startCall(session_id)) { - im_floater->requestAutoConnect(); - LLFloaterIMPanel::onClickStartCall(im_floater); // always open IM window when connecting to voice - LLFloaterReg::showInstance("communicate", session_id, TRUE); + LLIMFloater::show(session_id); } gIMMgr->clearPendingAgentListUpdates(session_id); @@ -1291,13 +1283,6 @@ void LLIMMgr::addMessage( return; } - //not sure why...but if it is from ourselves we set the target_id - //to be NULL - if( other_participant_id == gAgent.getID() ) - { - other_participant_id = LLUUID::null; - } - LLFloaterIMPanel* floater; LLUUID new_session_id = session_id; if (new_session_id.isNull()) @@ -1429,12 +1414,10 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess } else // going to IM session { - LLFloaterIMPanel* floaterp = findFloaterBySession(session_id); - if (floaterp) + if (hasSession(session_id)) { - message = floaterp->getString(message_name); + message = LLTrans::getString(message_name + "-im"); message.setArgs(args); - gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString()); } } @@ -1566,6 +1549,16 @@ LLUUID LLIMMgr::addSession( return session_id; } +bool LLIMMgr::leaveSession(const LLUUID& session_id) +{ + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); + if (!im_session) return false; + + LLIMModel::getInstance()->sendLeaveSession(session_id, im_session->mOtherParticipantID); + gIMMgr->removeSession(session_id); + return true; +} + // This removes the panel referenced by the uuid, and then restores // internal consistency. The internal pointer is not deleted? Did you mean // a pointer to the corresponding LLIMSession? Session data is cleared now. @@ -1779,7 +1772,7 @@ LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id) BOOL LLIMMgr::hasSession(const LLUUID& session_id) { - return (findFloaterBySession(session_id) != NULL); + return LLIMModel::getInstance()->findIMSession(session_id) != NULL; } void LLIMMgr::clearPendingInvitation(const LLUUID& session_id) @@ -1905,6 +1898,24 @@ void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer) mSessionObservers.remove(observer); } +bool LLIMMgr::startCall(const LLUUID& session_id) +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id); + if (!voice_channel) return false; + + voice_channel->activate(); + return true; +} + +bool LLIMMgr::endCall(const LLUUID& session_id) +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id); + if (!voice_channel) return false; + + voice_channel->deactivate(); + return true; +} + // create a floater and update internal representation for // consistency. Returns the pointer, caller (the class instance since // it is a private method) is not responsible for deleting the diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 84646a9a6f..f9db6d8ed2 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -75,10 +75,20 @@ public: LLIMModel(); + + //we should control the currently active session + LLUUID mActiveSessionID; + void setActiveSessionID(const LLUUID& session_id); + void resetActiveSessionID() { mActiveSessionID.setNull(); } + LLUUID getActiveSessionID() { return mActiveSessionID; } + //*TODO make it non-static as LLIMMOdel is a singleton (IB) static std::map<LLUUID, LLIMSession*> sSessionsMap; //mapping session_id to session - boost::signals2::signal<void(const LLSD&)> mChangedSignal; + typedef boost::signals2::signal<void(const LLSD&)> session_signal_t; + typedef boost::function<void(const LLSD&)> session_callback_t; + session_signal_t mNewMsgSignal; + session_signal_t mNoUnreadMsgsSignal; /** * Find an IM Session corresponding to session_id @@ -91,7 +101,8 @@ public: */ void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id); - boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb ); + boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); } + boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); } bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, const std::vector<LLUUID>& ids = std::vector<LLUUID>()); @@ -219,10 +230,12 @@ public: const std::string& voice_session_handle, const std::string& caller_uri = LLStringUtil::null); - // This removes the panel referenced by the uuid, and then - // restores internal consistency. The internal pointer is not - // deleted. - void removeSession(LLUUID session_id); + /** + * Leave the session with session id. Send leave session notification + * to the server and removes all associated session data + * @return false if the session with specified id was not exist + */ + bool leaveSession(const LLUUID& session_id); void inviteToSession( const LLUUID& session_id, @@ -282,7 +295,24 @@ public: void addSessionObserver(LLIMSessionObserver *); void removeSessionObserver(LLIMSessionObserver *); + /** + * Start call in a session + * @return false if voice channel doesn't exist + **/ + bool startCall(const LLUUID& session_id); + + /** + * End call in a session + * @return false if voice channel doesn't exist + **/ + bool endCall(const LLUUID& session_id); + private: + // This removes the panel referenced by the uuid, and then + // restores internal consistency. The internal pointer is not + // deleted. + void removeSession(LLUUID session_id); + // create a panel and update internal representation for // consistency. Returns the pointer, caller (the class instance // since it is a private method) is not responsible for deleting diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index db7d4f4c8f..d876647692 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1462,6 +1462,39 @@ BOOL LLFolderBridge::copyToClipboard() const return FALSE; } +BOOL LLFolderBridge::isClipboardPasteable() const +{ + if ( ! LLInvFVBridge::isClipboardPasteable() ) + return FALSE; + + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) + { + LLInventoryModel* model = getInventoryModel(); + if ( !model ) + { + return FALSE; + } + + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + const LLViewerInventoryCategory *current_cat = getCategory(); + + // Search for the direct descendent of current Friends subfolder among all pasted items, + // and return false if is found. + for(S32 i = objects.count() - 1; i >= 0; --i) + { + const LLUUID &obj_id = objects.get(i); + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + + } + return TRUE; +} + BOOL LLFolderBridge::isClipboardPasteableAsLink() const { // Check normal paste-as-link permissions @@ -1479,13 +1512,15 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const const LLViewerInventoryCategory *current_cat = getCategory(); if (current_cat) { + const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); const LLUUID ¤t_cat_id = current_cat->getUUID(); LLDynamicArray<LLUUID> objects; LLInventoryClipboard::instance().retrieve(objects); S32 count = objects.count(); for(S32 i = 0; i < count; i++) { - const LLInventoryCategory *cat = model->getCategory(objects.get(i)); + const LLUUID &obj_id = objects.get(i); + const LLInventoryCategory *cat = model->getCategory(obj_id); if (cat) { const LLUUID &cat_id = cat->getUUID(); @@ -1496,6 +1531,17 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const return FALSE; } } + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( is_in_friend_folder ) + { + // If object is direct descendent of current Friends subfolder than return false. + // Note: We can't use 'const LLInventoryCategory *cat', because it may be null + // in case type of obj_id is LLInventoryItem. + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } } } return TRUE; @@ -1547,6 +1593,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // BAP - restrictions? is_movable = true; } + + if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE)) + { + is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 + } + if( is_movable ) { gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); @@ -2813,6 +2865,17 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, break; } } + + if ( is_movable ) + { + // Don't allow creating duplicates in the Calling Card/Friends + // subfolders, see bug EXT-1599. Check is item direct descendent + // of target folder and forbid item's movement if it so. + // Note: isItemDirectDescendentOfCategory checks if + // passed category is in the Calling Card/Friends folder + is_movable = ! LLFriendCardsManager::instance() + .isObjDirectDescendentOfCategory (inv_item, getCategory()); + } LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); @@ -3755,12 +3818,14 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model else if ("detach" == action) { LLInventoryItem* item = gInventory.getItem(mUUID); - if( item ) + // In case we clicked on a link, detach the base object instead of the link. + LLInventoryItem* base_item = gInventory.getItem(item->getLinkedUUID()); + if(base_item) { gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, base_item->getUUID() ); gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d1d2c57f07..6b2a2d32de 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -315,6 +315,7 @@ public: virtual BOOL isItemMovable() const ; virtual BOOL isUpToDate() const; virtual BOOL isItemCopyable() const; + virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual BOOL copyToClipboard() const; diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp index 99c98ec16e..6bcbe6f58c 100644 --- a/indra/newview/lllocaltextureobject.cpp +++ b/indra/newview/lllocaltextureobject.cpp @@ -47,18 +47,18 @@ LLLocalTextureObject::LLLocalTextureObject() : mImage = NULL; } -LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture *image, LLUUID id) +LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id) { mImage = image; gGL.getTexUnit(0)->bind(mImage); mID = id; } -LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject <o) : -mImage(lto.mImage), -mID(lto.mID), -mIsBakedReady(lto.mIsBakedReady), -mDiscard(lto.mDiscard) +LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : + mImage(lto.mImage), + mID(lto.mID), + mIsBakedReady(lto.mIsBakedReady), + mDiscard(lto.mDiscard) { U32 num_layers = lto.getNumTexLayers(); mTexLayers.reserve(num_layers); @@ -97,7 +97,7 @@ LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) { - for( tex_layer_p::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++) + for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++) { LLTexLayer *layer = *iter; if (layer->getName().compare(name) == 0) @@ -190,7 +190,7 @@ BOOL LLLocalTextureObject::removeTexLayer(U32 index) { return FALSE; } - tex_layer_p::iterator iter = mTexLayers.begin(); + tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter += index; delete *iter; diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h index 138bbad677..c8b8aa924b 100644 --- a/indra/newview/lllocaltextureobject.h +++ b/indra/newview/lllocaltextureobject.h @@ -35,7 +35,8 @@ #include <boost/shared_ptr.hpp> -class LLViewerFetchedTexture; +#include "llviewertexture.h" + class LLUUID; class LLTexLayer; class LLTextureEntry; @@ -49,8 +50,8 @@ class LLLocalTextureObject { public: LLLocalTextureObject(); - LLLocalTextureObject(LLViewerFetchedTexture *image, LLUUID id); - LLLocalTextureObject(const LLLocalTextureObject <o); + LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id); + LLLocalTextureObject(const LLLocalTextureObject& lto); ~LLLocalTextureObject(); LLViewerFetchedTexture* getImage() const; @@ -79,8 +80,8 @@ private: // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer // using shared pointers here only for smart assignment & cleanup // do NOT create new shared pointers to these objects, or keep pointers to them around - typedef std::vector<LLTexLayer*> tex_layer_p; - tex_layer_p mTexLayers; + typedef std::vector<LLTexLayer*> tex_layer_vec_t; + tex_layer_vec_t mTexLayers; LLUUID mID; diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 42838b311b..00f12ae2eb 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -264,6 +264,8 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) mAddLandmarkTooltip = LLTrans::getString("LocationCtrlAddLandmarkTooltip"); mEditLandmarkTooltip = LLTrans::getString("LocationCtrlEditLandmarkTooltip"); + getChild<LLView>("Location History")->setToolTip(LLTrans::getString("LocationCtrlComboBtnTooltip")); + getChild<LLView>("Place Information")->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip")); } LLLocationInputCtrl::~LLLocationInputCtrl() diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 8005cd1180..15efd0100a 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -321,36 +321,9 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) { BOOL result = FALSE; - // FIXME: THIS IS SO WRONG. - // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if (mMediaSource) { - if( MASK_CONTROL & mask ) - { - if( 'C' == key ) - { - mMediaSource->copy(); - result = TRUE; - } - else - if( 'V' == key ) - { - mMediaSource->paste(); - result = TRUE; - } - else - if( 'X' == key ) - { - mMediaSource->cut(); - result = TRUE; - } - } - - if(!result) - { - result = mMediaSource->handleKeyHere(key, mask); - } + result = mMediaSource->handleKeyHere(key, mask); } return result; @@ -373,12 +346,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { BOOL result = FALSE; - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. + if (mMediaSource) { - if (mMediaSource) - result = mMediaSource->handleUnicodeCharHere(uni_char); + result = mMediaSource->handleUnicodeCharHere(uni_char); } return result; diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp index 525e89cdff..235487cf46 100644 --- a/indra/newview/llmimetypes.cpp +++ b/indra/newview/llmimetypes.cpp @@ -34,6 +34,7 @@ #include "llviewerprecompiledheaders.h" #include "llmimetypes.h" +#include "llxmlnode.h" #include "lluictrlfactory.h" diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 1bbcc3f98e..4fc552c8b1 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -70,7 +70,7 @@ const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn"; // protected LLFloaterMove::LLFloaterMove(const LLSD& key) -: LLDockableFloater(NULL, key), +: LLTransientDockableFloater(NULL, true, key), mForwardButton(NULL), mBackwardButton(NULL), mTurnLeftButton(NULL), @@ -499,6 +499,8 @@ void LLFloaterMove::setDocked(bool docked, bool pop_on_undock/* = true*/) LLDockableFloater::setDocked(docked, pop_on_undock); bool show_mode_buttons = isDocked() || !gAgent.getFlying(); updateHeight(show_mode_buttons); + + LLTransientDockableFloater::setDocked(docked, pop_on_undock); } void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode) diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h index cbed36f10d..cee6078ee9 100644 --- a/indra/newview/llmoveview.h +++ b/indra/newview/llmoveview.h @@ -34,7 +34,7 @@ #define LL_LLMOVEVIEW_H // Library includes -#include "lldockablefloater.h" +#include "lltransientdockablefloater.h" class LLButton; class LLJoystickAgentTurn; @@ -44,7 +44,7 @@ class LLJoystickAgentSlide; // Classes // class LLFloaterMove -: public LLDockableFloater +: public LLTransientDockableFloater { friend class LLFloaterReg; diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index dec8d7576e..409b637bf2 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -153,7 +153,13 @@ private: { bool operator()(const LLMute& a, const LLMute& b) const { - return a.mName < b.mName; + std::string name1 = a.mName; + std::string name2 = b.mName; + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; } }; struct compare_by_id diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 7160cce5cb..6e90d22d89 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -54,17 +54,15 @@ #include "llstylemap.h" #include "lldraghandle.h" - +#include "lltrans.h" static const S32 RESIZE_BAR_THICKNESS = 3; LLNearbyChat::LLNearbyChat(const LLSD& key) : - LLFloater(key), - mEChatTearofState(CHAT_PINNED), - mChatCaptionPanel(NULL), - mChatHistory(NULL) + LLFloater(key) + ,mChatHistory(NULL) { - m_isDirty = false; + } LLNearbyChat::~LLNearbyChat() @@ -73,25 +71,6 @@ LLNearbyChat::~LLNearbyChat() BOOL LLNearbyChat::postBuild() { - //resize bars - setCanResize(true); - - mResizeBar[LLResizeBar::BOTTOM]->setVisible(false); - mResizeBar[LLResizeBar::LEFT]->setVisible(false); - mResizeBar[LLResizeBar::RIGHT]->setVisible(false); - - mResizeBar[LLResizeBar::BOTTOM]->setResizeLimits(120,500); - mResizeBar[LLResizeBar::TOP]->setResizeLimits(120,500); - mResizeBar[LLResizeBar::LEFT]->setResizeLimits(220,600); - mResizeBar[LLResizeBar::RIGHT]->setResizeLimits(220,600); - - mResizeHandle[0]->setVisible(false); - mResizeHandle[1]->setVisible(false); - mResizeHandle[2]->setVisible(false); - mResizeHandle[3]->setVisible(false); - - getDragHandle()->setVisible(false); - //menu LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; @@ -101,17 +80,15 @@ BOOL LLNearbyChat::postBuild() LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) mPopupMenuHandle = menu->getHandle(); gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); - mChatCaptionPanel = getChild<LLPanel>("chat_caption", false); mChatHistory = getChild<LLChatHistory>("chat_history"); - reshape(getRect().getWidth(), getRect().getHeight(), FALSE); - + setCanResize(true); + return LLFloater::postBuild(); } @@ -181,6 +158,22 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat) return text_color; } +std::string formatCurrentTime() +{ + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"] "; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + + return timeStr; +} + + void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color) { S32 font_size = gSavedSettings.getS32("ChatFontSize"); @@ -205,7 +198,7 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo style_params.font(fontp); LLUUID uuid = chat.mFromID; std::string from = chat.mFromName; - std::string time = ""; + std::string time = formatCurrentTime(); std::string message = chat.mText; mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params); } @@ -239,193 +232,6 @@ void LLNearbyChat::onNearbySpeakers() LLSideTray::getInstance()->showPanel("panel_people",param); } -void LLNearbyChat::onTearOff() -{ - if(mEChatTearofState == CHAT_PINNED) - float_panel(); - else - pinn_panel(); -} - -void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - - LLFloater::reshape(width, height, called_from_parent); - - LLRect resize_rect; - resize_rect.setLeftTopAndSize( 0, height, width, RESIZE_BAR_THICKNESS); - if (mResizeBar[LLResizeBar::TOP]) - { - mResizeBar[LLResizeBar::TOP]->reshape(width,RESIZE_BAR_THICKNESS); - mResizeBar[LLResizeBar::TOP]->setRect(resize_rect); - } - - resize_rect.setLeftTopAndSize( 0, RESIZE_BAR_THICKNESS, width, RESIZE_BAR_THICKNESS); - if (mResizeBar[LLResizeBar::BOTTOM]) - { - mResizeBar[LLResizeBar::BOTTOM]->reshape(width,RESIZE_BAR_THICKNESS); - mResizeBar[LLResizeBar::BOTTOM]->setRect(resize_rect); - } - - resize_rect.setLeftTopAndSize( 0, height, RESIZE_BAR_THICKNESS, height); - if (mResizeBar[LLResizeBar::LEFT]) - { - mResizeBar[LLResizeBar::LEFT]->reshape(RESIZE_BAR_THICKNESS,height); - mResizeBar[LLResizeBar::LEFT]->setRect(resize_rect); - } - - resize_rect.setLeftTopAndSize( width - RESIZE_BAR_THICKNESS, height, RESIZE_BAR_THICKNESS, height); - if (mResizeBar[LLResizeBar::RIGHT]) - { - mResizeBar[LLResizeBar::RIGHT]->reshape(RESIZE_BAR_THICKNESS,height); - mResizeBar[LLResizeBar::RIGHT]->setRect(resize_rect); - } - - // *NOTE: we must check mChatCaptionPanel and mChatHistory against NULL because reshape is called from the - // LLView::initFromParams BEFORE postBuild is called and child controls are not exist yet - LLRect caption_rect; - if (NULL != mChatCaptionPanel) - { - caption_rect = mChatCaptionPanel->getRect(); - caption_rect.setLeftTopAndSize( 2, height - RESIZE_BAR_THICKNESS, width - 4, caption_rect.getHeight()); - mChatCaptionPanel->reshape( width - 4, caption_rect.getHeight(), 1); - mChatCaptionPanel->setRect(caption_rect); - } - - if (NULL != mChatHistory) - { - LLRect scroll_rect = mChatHistory->getRect(); - scroll_rect.setLeftTopAndSize( 2, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS, width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2); - mChatHistory->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1); - mChatHistory->setRect(scroll_rect); - } - - // - if(mEChatTearofState == CHAT_PINNED) - { - const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); - - LLRect panel_rect; - panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+height+4, width, height); - setRect(panel_rect); - } - else - { - LLRect panel_rect; - panel_rect.setLeftTopAndSize( getRect().mLeft, getRect().mTop, width, height); - setRect(panel_rect); - } - -} - -BOOL LLNearbyChat::handleMouseDown (S32 x, S32 y, MASK mask) -{ - LLUICtrl* nearby_speakers_btn = mChatCaptionPanel->getChild<LLUICtrl>("nearby_speakers_btn"); - LLUICtrl* tearoff_btn = mChatCaptionPanel->getChild<LLUICtrl>("tearoff_btn"); - LLUICtrl* close_btn = mChatCaptionPanel->getChild<LLUICtrl>("close_btn"); - - S32 caption_local_x = x - mChatCaptionPanel->getRect().mLeft; - S32 caption_local_y = y - mChatCaptionPanel->getRect().mBottom; - - S32 local_x = caption_local_x - nearby_speakers_btn->getRect().mLeft; - S32 local_y = caption_local_y - nearby_speakers_btn->getRect().mBottom; - if(nearby_speakers_btn->pointInView(local_x, local_y)) - { - - onNearbySpeakers(); - bringToFront( x, y ); - return true; - } - local_x = caption_local_x - tearoff_btn->getRect().mLeft; - local_y = caption_local_y- tearoff_btn->getRect().mBottom; - if(tearoff_btn->pointInView(local_x, local_y)) - { - onTearOff(); - bringToFront( x, y ); - return true; - } - - local_x = caption_local_x - close_btn->getRect().mLeft; - local_y = caption_local_y - close_btn->getRect().mBottom; - if(close_btn->pointInView(local_x, local_y)) - { - setVisible(false); - bringToFront( x, y ); - return true; - } - - if(mEChatTearofState == CHAT_UNPINNED && mChatCaptionPanel->pointInView(caption_local_x, caption_local_y) ) - { - //start draggind - gFocusMgr.setMouseCapture(this); - mStart_Y = y; - mStart_X = x; - bringToFront( x, y ); - return true; - } - - return LLFloater::handleMouseDown(x,y,mask); -} - -BOOL LLNearbyChat::handleMouseUp(S32 x, S32 y, MASK mask) -{ - if( hasMouseCapture() ) - { - // Release the mouse - gFocusMgr.setMouseCapture( NULL ); - mStart_X = 0; - mStart_Y = 0; - return true; - } - - return LLFloater::handleMouseUp(x,y,mask); -} - -BOOL LLNearbyChat::handleHover(S32 x, S32 y, MASK mask) -{ - if( hasMouseCapture() ) - { - translate(x-mStart_X,y-mStart_Y); - return true; - } - return LLFloater::handleHover(x,y,mask); -} - -void LLNearbyChat::pinn_panel() -{ - mEChatTearofState = CHAT_PINNED; - LLIconCtrl* tearoff_btn = mChatCaptionPanel->getChild<LLIconCtrl>("tearoff_btn",false); - - tearoff_btn->setValue("Inv_Landmark"); - - const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); - - LLRect panel_rect; - panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+getRect().getHeight()+4, getRect().getWidth(), getRect().getHeight()); - setRect(panel_rect); - - mResizeBar[LLResizeBar::BOTTOM]->setVisible(false); - mResizeBar[LLResizeBar::LEFT]->setVisible(false); - mResizeBar[LLResizeBar::RIGHT]->setVisible(false); - - getDragHandle()->setVisible(false); - -} - -void LLNearbyChat::float_panel() -{ - mEChatTearofState = CHAT_UNPINNED; - LLIconCtrl* tearoff_btn = mChatCaptionPanel->getChild<LLIconCtrl>("tearoff_btn", false); - - tearoff_btn->setValue("Inv_Landmark"); - mResizeBar[LLResizeBar::BOTTOM]->setVisible(true); - mResizeBar[LLResizeBar::LEFT]->setVisible(true); - mResizeBar[LLResizeBar::RIGHT]->setVisible(true); - - getDragHandle()->setVisible(true); - - translate(4,4); -} void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) { @@ -438,23 +244,6 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) return false; } -BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - if(mChatCaptionPanel->pointInView(x - mChatCaptionPanel->getRect().mLeft, y - mChatCaptionPanel->getRect().mBottom) ) - { - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - - if(menu) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - } - return true; - } - return LLFloater::handleRightMouseDown(x, y, mask); -} - void LLNearbyChat::onOpen(const LLSD& key ) { LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); @@ -464,9 +253,15 @@ void LLNearbyChat::onOpen(const LLSD& key ) } } -void LLNearbyChat::draw () +void LLNearbyChat::setDocked (bool docked, bool pop_on_undock) { - LLFloater::draw(); -} + LLFloater::setDocked(docked, pop_on_undock); + if(docked) + { + //move nearby_chat to right bottom + LLRect rect = gFloaterView->getRect(); + setRect(LLRect(rect.mLeft,getRect().getHeight(),rect.mLeft+getRect().getWidth(),0)); + } +} diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 47cae8ed0d..63e780c4bf 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -43,55 +43,27 @@ class LLChatHistory; class LLNearbyChat: public LLFloater { public: - // enumerations used by the chat system - typedef enum e_chat_tearof_state - { - CHAT_PINNED = 0, - CHAT_UNPINNED = 1, - } EChatTearofState; - - enum { RESIZE_BAR_COUNT=4 }; - LLNearbyChat(const LLSD& key); ~LLNearbyChat(); BOOL postBuild (); - void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); - - BOOL handleMouseDown (S32 x, S32 y, MASK mask); - BOOL handleMouseUp (S32 x, S32 y, MASK mask); - BOOL handleHover (S32 x, S32 y, MASK mask); - - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - void addMessage (const LLChat& message); - void onNearbySpeakers (); - void onTearOff(); - void onNearbyChatContextMenuItemClicked(const LLSD& userdata); bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - /*virtual*/ void onOpen (const LLSD& key); + void setDocked (bool docked, bool pop_on_undock); - /*virtual*/ void draw (); + /*virtual*/ void onOpen (const LLSD& key); private: + void onNearbySpeakers (); void add_timestamped_line(const LLChat& chat, const LLColor4& color); - void pinn_panel(); - void float_panel(); private: - EChatTearofState mEChatTearofState; - S32 mStart_X; - S32 mStart_Y; - LLHandle<LLView> mPopupMenuHandle; - LLPanel* mChatCaptionPanel; LLChatHistory* mChatHistory; - - bool m_isDirty; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 59b19b6dcb..4aefbd1a33 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -225,7 +225,7 @@ void LLNearbyChatScreenChannel::showToastsBottom() LLRect toast_rect; S32 bottom = getRect().mBottom; - S32 margin = gSavedSettings.getS32("ToastMargin"); + S32 margin = gSavedSettings.getS32("ToastGap"); for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) { diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index c08f92b983..7239f49b7f 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -91,6 +91,7 @@ bool LLTipHandler::processNotification(const LLSD& notify) LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; + p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); p.panel = notify_box; p.is_tip = true; p.can_be_stored = false; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 7670a5120c..1a2ef8e1bb 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -336,10 +336,10 @@ BOOL LLPanelAvatarProfile::postBuild() childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL); LLTextureCtrl* pic = getChild<LLTextureCtrl>("2nd_life_pic"); - pic->setFallbackImageName("default_land_picture.j2c"); + pic->setFallbackImageName("default_profile_picture.j2c"); pic = getChild<LLTextureCtrl>("real_world_pic"); - pic->setFallbackImageName("default_land_picture.j2c"); + pic->setFallbackImageName("default_profile_picture.j2c"); resetControls(); resetData(); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index c2c32527fb..e2057bbbd7 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -601,15 +601,14 @@ LLPanel* LLPanelEditWearable::getPanel(EWearableType type) void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group) { - LLWearable::visualParamCluster_t param_list; + LLWearable::visual_param_vec_t param_list; ESex avatar_sex = gAgent.getAvatarObject()->getSex(); mWearablePtr->getVisualParams(param_list); - LLWearable::visualParamCluster_t::iterator iter = param_list.begin(); - LLWearable::visualParamCluster_t::iterator end = param_list.end(); - - for (; iter != end; ++iter) + for (LLWearable::visual_param_vec_t::iterator iter = param_list.begin(); + iter != param_list.end(); + ++iter) { LLViewerVisualParam *param = (LLViewerVisualParam*) *iter; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 521e145816..d81cbb3e5d 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -40,7 +40,9 @@ #include "llaccordionctrltab.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llagentui.h" +#include "lldndbutton.h" #include "llfloaterworldmap.h" #include "llfolderviewitem.h" #include "llinventorysubtreepanel.h" @@ -58,7 +60,6 @@ static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn"; static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn"; static const std::string TRASH_BUTTON_NAME = "trash_btn"; -static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER; // helper functions static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); @@ -214,6 +215,17 @@ bool LLLandmarksPanel::isLandmarkSelected() const return false; } +bool LLLandmarksPanel::isReceivedFolderSelected() const +{ + // Received Folder can be only in Landmarks accordion + if (mCurrentSelectedList != mLandmarksInventoryPanel) return false; + + // *TODO: it should be filled with logic when EXT-976 is done. + + llwarns << "Not implemented yet until EXT-976 is done." << llendl; + + return false; +} LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const { @@ -317,9 +329,7 @@ void LLLandmarksPanel::initFavoritesInventroyPanel() { mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); - LLUUID start_folder_id = mFavoritesInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); - - initLandmarksPanel(mFavoritesInventoryPanel, start_folder_id); + initLandmarksPanel(mFavoritesInventoryPanel); initAccordion("tab_favorites", mFavoritesInventoryPanel); } @@ -328,9 +338,8 @@ void LLLandmarksPanel::initLandmarksInventroyPanel() { mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); - LLUUID start_folder_id = mLandmarksInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + initLandmarksPanel(mLandmarksInventoryPanel); - initLandmarksPanel(mLandmarksInventoryPanel, start_folder_id); mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); // subscribe to have auto-rename functionality while creating New Folder @@ -343,9 +352,7 @@ void LLLandmarksPanel::initMyInventroyPanel() { mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); - LLUUID start_folder_id = mMyInventoryPanel->getModel()->getRootFolderID(); - - initLandmarksPanel(mMyInventoryPanel, start_folder_id); + initLandmarksPanel(mMyInventoryPanel); initAccordion("tab_inventory", mMyInventoryPanel); } @@ -354,18 +361,13 @@ void LLLandmarksPanel::initLibraryInventroyPanel() { mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); - LLUUID start_folder_id = mLibraryInventoryPanel->getModel()->getLibraryRootFolderID(); - - initLandmarksPanel(mLibraryInventoryPanel, start_folder_id); + initLandmarksPanel(mLibraryInventoryPanel); initAccordion("tab_library", mLibraryInventoryPanel); } - -void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id) +void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list) { - inventory_list->buildSubtreeViewsFor(start_folder_id, &PLACES_INVENTORY_BUILDER); - inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); @@ -378,6 +380,10 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle()); root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle()); } + + // save initial folder state to avoid incorrect work while switching between Landmarks & Teleport History tabs + // See EXT-1609. + inventory_list->saveFolderState(); } void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) @@ -432,8 +438,15 @@ void LLLandmarksPanel::initListCommandsHandlers() mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this)); + LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME); + trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this + , _4 // BOOL drop + , _5 // EDragAndDropType cargo_type + , _7 // EAcceptance* accept + )); + mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2)); - mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onCopyPasteAction, this, _2)); + mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2)); mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2)); mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2)); mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2)); @@ -444,20 +457,8 @@ void LLLandmarksPanel::initListCommandsHandlers() void LLLandmarksPanel::updateListCommands() { - // TODO: should be false when "Received" folder is selected - bool add_folder_enabled = mCurrentSelectedList == mLandmarksInventoryPanel; - bool trash_enabled = false; // TODO: should be false when "Received" folder is selected - - LLFolderViewItem* current_item = getCurSelectedItem(); - - if (current_item) - { - LLFolderViewEventListener* listenerp = current_item->getListener(); - if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) - { - trash_enabled = mCurrentSelectedList != mLibraryInventoryPanel; - } - } + bool add_folder_enabled = isActionEnabled("category"); + bool trash_enabled = isActionEnabled("delete"); // keep Options & Add Landmark buttons always enabled mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled); @@ -515,31 +516,29 @@ void LLLandmarksPanel::onAddFolderButtonClick() const LLFolderViewItem* item = getCurSelectedItem(); if(item && mCurrentSelectedList == mLandmarksInventoryPanel) { - LLFolderBridge *parentBridge = NULL; + LLFolderViewEventListener* folder_bridge = NULL; if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) { - parentBridge = dynamic_cast<LLFolderBridge*>(item->getParentFolder()->getListener()); - /*WORKAROUND:* - LLFolderView::doIdle() is calling in each frame, - it changes selected items before LLFolderView::startRenamingSelectedItem. - To avoid it we have to change keyboardFocus. - */ - gFocusMgr.setKeyboardFocus(item->getParentFolder()); + // for a landmark get parent folder bridge + folder_bridge = item->getParentFolder()->getListener(); } else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY) { - parentBridge = dynamic_cast<LLFolderBridge*>(item->getListener()); - gFocusMgr.setKeyboardFocus(item); + // for a folder get its own bridge + folder_bridge = item->getListener(); } - menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),parentBridge, LLSD("category")); + + menu_create_inventory_item(mCurrentSelectedList->getRootFolder() + , dynamic_cast<LLFolderBridge*>(folder_bridge) + , LLSD("category") + , gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK) + ); } } void LLLandmarksPanel::onTrashButtonClick() const { - if(!mCurrentSelectedList) return; - - mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(), "delete"); + onClipboardAction("delete"); } void LLLandmarksPanel::onAddAction(const LLSD& userdata) const @@ -555,7 +554,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const } } -void LLLandmarksPanel::onCopyPasteAction(const LLSD& userdata) const +void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const { if(!mCurrentSelectedList) return; @@ -613,13 +612,25 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { std::string command_name = userdata.asString(); + + LLPlacesFolderView* rootFolderView = mCurrentSelectedList ? + static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL; + + if (NULL == rootFolderView) return false; + if("category" == command_name) { - return mCurrentSelectedList == mLandmarksInventoryPanel; + // we can add folder only in Landmarks Accordion + if (mCurrentSelectedList == mLandmarksInventoryPanel) + { + // ... but except Received folder + return !isReceivedFolderSelected(); + } + else return false; } - else if("paste" == command_name) + else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name) { - return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->canPaste() : false; + return canSelectedBeModified(command_name); } else if ( "sort_by_date" == command_name) { @@ -628,13 +639,15 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const // do not allow teleport and more info for multi-selections else if ("teleport" == command_name || "more_info" == command_name) { - return mCurrentSelectedList ? - static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder())->getSelectedCount() == 1 : false; + return rootFolderView->getSelectedCount() == 1; } - // we can add folder, or change item/folder only in Landmarks Accordion - else if ("add_folder" == command_name || "rename" == command_name || "delete" == command_name) + else if("create_pick" == command_name) { - return mLandmarksInventoryPanel == mCurrentSelectedList; + return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); + } + else + { + llwarns << "Unprocessed command has come: " << command_name << llendl; } return true; @@ -699,6 +712,75 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata) } } +/* +Processes such actions: cut/rename/delete/paste actions + +Rules: + 1. We can't perform any action in Library + 2. For Landmarks we can: + - cut/rename/delete in any other accordions + - paste - only in Favorites, Landmarks accordions + 3. For Folders we can: perform any action in Landmarks accordion, except Received folder + 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste()) + 5. Check LLFolderView/Inventory Bridges rules + */ +bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const +{ + // validate own rules first + + // nothing can be modified in Library + if (mLibraryInventoryPanel == mCurrentSelectedList) return false; + + bool can_be_modified = false; + + // landmarks can be modified in any other accordion... + if (isLandmarkSelected()) + { + can_be_modified = true; + + // we can modify landmarks anywhere except paste to My Inventory + if ("paste" == command_name) + { + can_be_modified = (mCurrentSelectedList != mMyInventoryPanel); + } + } + else + { + // ...folders only in the Landmarks accordion... + can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList; + + // ...except "Received" folder + can_be_modified &= !isReceivedFolderSelected(); + } + + // then ask LLFolderView permissions + if (can_be_modified) + { + if ("cut" == command_name) + { + can_be_modified = mCurrentSelectedList->getRootFolder()->canCut(); + } + else if ("rename" == command_name) + { + can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable(); + } + else if ("delete" == command_name) + { + can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable(); + } + else if("paste" == command_name) + { + return mCurrentSelectedList->getRootFolder()->canPaste(); + } + else + { + llwarns << "Unprocessed command has come: " << command_name << llendl; + } + } + + return can_be_modified; +} + void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params) { pick_panel->setVisible(FALSE); @@ -710,6 +792,33 @@ void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* own pick_panel = NULL; } +bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept) +{ + *accept = ACCEPT_NO; + + switch (cargo_type) + { + + case DAD_LANDMARK: + case DAD_CATEGORY: + { + bool is_enabled = isActionEnabled("delete"); + + if (is_enabled) *accept = ACCEPT_YES_MULTI; + + if (is_enabled && drop) + { + onClipboardAction("delete"); + } + } + break; + default: + break; + } + + return true; +} + ////////////////////////////////////////////////////////////////////////// // HELPER FUNCTIONS diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 389a04a76f..11d703dcde 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -66,6 +66,7 @@ protected: * @return true - if current selected panel is not null and selected item is a landmark */ bool isLandmarkSelected() const; + bool isReceivedFolderSelected() const; LLLandmark* getCurSelectedLandmark() const; LLFolderViewItem* getCurSelectedItem () const; void updateSortOrder(LLInventoryPanel* panel, bool byDate); @@ -80,7 +81,7 @@ private: void initLandmarksInventroyPanel(); void initMyInventroyPanel(); void initLibraryInventroyPanel(); - void initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id); + void initLandmarksPanel(LLInventorySubTreePanel* inventory_list); void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list); void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list); void deselectOtherThan(const LLInventorySubTreePanel* inventory_list); @@ -93,12 +94,25 @@ private: void onAddFolderButtonClick() const; void onTrashButtonClick() const; void onAddAction(const LLSD& command_name) const; - void onCopyPasteAction(const LLSD& command_name) const; + void onClipboardAction(const LLSD& command_name) const; void onFoldingAction(const LLSD& command_name); bool isActionEnabled(const LLSD& command_name) const; void onCustomAction(const LLSD& command_name); + + /** + * Determines if selected item can be modified via context/gear menu. + * + * It validates Places Landmarks rules first. And then LLFolderView permissions. + * For now it checks cut/rename/delete/paste actions. + */ + bool canSelectedBeModified(const std::string& command_name) const; void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params); + /** + * Processes drag-n-drop of the Landmarks and folders into trash button. + */ + bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept); + private: LLInventorySubTreePanel* mFavoritesInventoryPanel; LLInventorySubTreePanel* mLandmarksInventoryPanel; diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 664ebfd7a4..cb9f641bf8 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -38,6 +38,7 @@ #include "llpanel.h" #include "message.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llbutton.h" #include "lllineeditor.h" #include "llparcel.h" @@ -310,6 +311,7 @@ LLPanelPickEdit::LLPanelPickEdit() : LLPanelPickInfo() , mLocationChanged(false) , mNeedData(true) + , mNewPick(false) { } @@ -325,6 +327,8 @@ void LLPanelPickEdit::onOpen(const LLSD& key) // creating new Pick if(pick_id.isNull()) { + mNewPick = true; + setAvatarId(gAgent.getID()); resetData(); @@ -356,6 +360,7 @@ void LLPanelPickEdit::onOpen(const LLSD& key) // editing existing pick else { + mNewPick = false; LLPanelPickInfo::onOpen(key); enableSaveButton(false); @@ -463,6 +468,14 @@ void LLPanelPickEdit::sendUpdate() pick_data.enabled = TRUE; LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); + + if(mNewPick) + { + // Assume a successful create pick operation, make new number of picks + // available immediately. Actual number of picks will be requested in + // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. + LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); + } } void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl) diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index c5b13c69ea..9b605cd6b1 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -235,6 +235,7 @@ protected: bool mLocationChanged; bool mNeedData; + bool mNewPick; }; #endif // LL_LLPANELPICK_H diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 073da5cc06..1219a08c6c 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llavatarconstants.h" #include "llflatlistview.h" #include "llfloaterreg.h" @@ -91,7 +92,12 @@ void* LLPanelPicks::create(void* data /* = NULL */) void LLPanelPicks::updateData() { - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); + // Send Picks request only when we need to, not on every onOpen(during tab switch). + if(isDirty()) + { + mPicksList->clear(); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); + } } void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) @@ -134,6 +140,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); } + resetDirty(); LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); updateButtons(); } @@ -183,8 +190,6 @@ void LLPanelPicks::onOpen(const LLSD& key) // Disable buttons when viewing profile for first time if(getAvatarId() != id) { - clear(); - childSetEnabled(XML_BTN_INFO,FALSE); childSetEnabled(XML_BTN_TELEPORT,FALSE); childSetEnabled(XML_BTN_SHOW_ON_MAP,FALSE); @@ -204,6 +209,8 @@ void LLPanelPicks::onOpen(const LLSD& key) if(getAvatarId() != id) { mPicksList->goToTop(); + // Set dummy value to make panel dirty and make it reload picks + setValue(LLSD()); } LLPanelProfileTab::onOpen(key); @@ -296,14 +303,13 @@ void LLPanelPicks::onDoubleClickItem(LLUICtrl* item) void LLPanelPicks::updateButtons() { - int picks_num = mPicksList->size(); bool has_selected = mPicksList->numSelected(); childSetEnabled(XML_BTN_INFO, has_selected); if (getAvatarId() == gAgentID) { - childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS); + childSetEnabled(XML_BTN_NEW, !LLAgentPicksInfo::getInstance()->isPickLimitReached()); childSetEnabled(XML_BTN_DELETE, has_selected); } @@ -358,6 +364,12 @@ void LLPanelPicks::onPanelPickClose(LLPanel* panel) panel->setVisible(FALSE); } +void LLPanelPicks::onPanelPickSave(LLPanel* panel) +{ + onPanelPickClose(panel); + updateButtons(); +} + void LLPanelPicks::createPickInfoPanel() { if(!mPanelPickInfo) @@ -375,7 +387,7 @@ void LLPanelPicks::createPickEditPanel() { mPanelPickEdit = LLPanelPickEdit::create(); mPanelPickEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); - mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); + mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickSave, this, mPanelPickEdit)); mPanelPickEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); mPanelPickEdit->setVisible(FALSE); } diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 6264a19318..7cf8f2de2a 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -86,6 +86,7 @@ private: void onClickNew(); void onClickInfo(); void onPanelPickClose(LLPanel* panel); + void onPanelPickSave(LLPanel* panel); void onPanelPickEdit(); void onClickMenuEdit(); diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 6d1a5fb184..cb9f7184f0 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -56,10 +56,12 @@ #include "llagentui.h" #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" +#include "llfloaterbuycurrency.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" #include "llpanelpick.h" #include "lltexturectrl.h" +#include "llstatusbar.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" @@ -88,7 +90,10 @@ LLPanelPlaceInfo::LLPanelPlaceInfo() mMinHeight(0), mScrollingPanel(NULL), mInfoPanel(NULL), - mMediaPanel(NULL) + mMediaPanel(NULL), + mForSalePanel(NULL), + mYouAreHerePanel(NULL), + mSelectedParcelID(-1) {} LLPanelPlaceInfo::~LLPanelPlaceInfo() @@ -104,14 +109,15 @@ BOOL LLPanelPlaceInfo::postBuild() mTitle = getChild<LLTextBox>("panel_title"); mCurrentTitle = mTitle->getText(); - mForSaleIcon = getChild<LLIconCtrl>("icon_for_sale"); + mForSalePanel = getChild<LLPanel>("for_sale_panel"); + mYouAreHerePanel = getChild<LLPanel>("here_panel"); + LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLPanelPlaceInfo::updateYouAreHereBanner,this)); + + //Icon value should contain sale price of last selected parcel. + mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")-> + setMouseDownCallback(boost::bind(&LLPanelPlaceInfo::onForSaleBannerClick, this)); - // Since this is only used in the directory browser, always - // disable the snapshot control. Otherwise clicking on it will - // open a texture picker. mSnapshotCtrl = getChild<LLTextureCtrl>("logo"); - mSnapshotCtrl->setEnabled(FALSE); - mRegionName = getChild<LLTextBox>("region_title"); mParcelName = getChild<LLTextBox>("parcel_title"); mDescEditor = getChild<LLTextEditor>("description"); @@ -267,7 +273,8 @@ void LLPanelPlaceInfo::resetLocation() mRequestedID.setNull(); mLandmarkID.setNull(); mPosRegion.clearVec(); - mForSaleIcon->setVisible(FALSE); + mForSalePanel->setVisible(FALSE); + mYouAreHerePanel->setVisible(FALSE); std::string not_available = getString("not_available"); mMaturityRatingText->setValue(not_available); mParcelOwner->setValue(not_available); @@ -480,9 +487,9 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) //update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE //because we deal with remote parcel response format - bool isForSale = (parcel_data.flags & DFQ_FOR_SALE) && + bool is_for_sale = (parcel_data.flags & DFQ_FOR_SALE) && mInfoType == AGENT ? TRUE : FALSE; - mForSaleIcon->setVisible(isForSale); + mForSalePanel->setVisible(is_for_sale); S32 region_x; S32 region_y; @@ -798,11 +805,11 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel, } } + mSelectedParcelID = parcel->getLocalID(); + mLastSelectedRegionID = region->getRegionID(); processParcelInfo(parcel_data); - // TODO: If agent is in currently within the selected parcel - // show the "You Are Here" banner. - + mYouAreHerePanel->setVisible(is_current_parcel); getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale); } @@ -979,6 +986,50 @@ void LLPanelPlaceInfo::populateFoldersList() mFolderCombo->add(it->second, LLSD(it->first)); } +void LLPanelPlaceInfo::updateYouAreHereBanner() +{ + //YouAreHere Banner should be displayed only for selected places, + // If you want to display it for landmark or teleport history item, you should check by mParcelId + + bool is_you_are_here = false; + if (mSelectedParcelID != S32(-1) && !mLastSelectedRegionID.isNull()) + { + is_you_are_here = gAgent.getRegion()->getRegionID()== mLastSelectedRegionID && + mSelectedParcelID == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID(); + } + mYouAreHerePanel->setVisible(is_you_are_here); +} + +void LLPanelPlaceInfo::onForSaleBannerClick() +{ + LLViewerParcelMgr* mgr = LLViewerParcelMgr::getInstance(); + LLParcelSelectionHandle hParcel = mgr->getFloatingParcelSelection(); + LLViewerRegion* selected_region = mgr->getSelectionRegion(); + if(!hParcel.isNull() && selected_region) + { + if(hParcel->getParcel()->getLocalID() == mSelectedParcelID && + mLastSelectedRegionID ==selected_region->getRegionID()) + { + if(hParcel->getParcel()->getSalePrice() - gStatusBar->getBalance() > 0) + { + LLFloaterBuyCurrency::buyCurrency("Buying selected land ", hParcel->getParcel()->getSalePrice()); + } + else + { + LLViewerParcelMgr::getInstance()->startBuyLand(); + } + } + else + { + LL_WARNS("Places") << "User is trying to buy remote parcel.Operation is not supported"<< LL_ENDL; + } + + } + + +} + + static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) { return left.second < right.second; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 06fee2224e..7b3a8f050b 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -135,7 +135,12 @@ public: private: void populateFoldersList(); + void updateYouAreHereBanner(); + void onForSaleBannerClick(); + /** + * mParcelID is valid only for remote places, in other cases it's null. See resetLocation() + */ LLUUID mParcelID; LLUUID mRequestedID; LLUUID mLandmarkID; @@ -144,8 +149,15 @@ private: S32 mMinHeight; INFO_TYPE mInfoType; + /** + * Hold last displayed parcel. Needs for YouAreHere banner. + */ + S32 mSelectedParcelID; + LLUUID mLastSelectedRegionID; + LLTextBox* mTitle; - LLIconCtrl* mForSaleIcon; + LLPanel* mForSalePanel; + LLPanel* mYouAreHerePanel; LLTextureCtrl* mSnapshotCtrl; LLTextBox* mRegionName; LLTextBox* mParcelName; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index f30bb1a0a6..5ab823b6e5 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -50,6 +50,7 @@ #include "lluictrlfactory.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" #include "llinventorybridge.h" @@ -178,6 +179,8 @@ BOOL LLPanelPlaces::postBuild() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Places.OverflowMenu.Action", boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2)); + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("Places.OverflowMenu.Enable", boost::bind(&LLPanelPlaces::onOverflowMenuItemEnable, this, _2)); mPlaceMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if (!mPlaceMenu) @@ -606,6 +609,16 @@ void LLPanelPlaces::onOverflowButtonClicked() LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop); } +bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param) +{ + std::string value = param.asString(); + if("can_create_pick" == value) + { + return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); + } + return true; +} + void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) { std::string item = param.asString(); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 70c50b2058..e2d281dd84 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -77,6 +77,7 @@ private: void onCancelButtonClicked(); void onOverflowButtonClicked(); void onOverflowMenuItemClicked(const LLSD& param); + bool onOverflowMenuItemEnable(const LLSD& param); void onCreateLandmarkButtonClicked(const LLUUID& folder_id); void onBackButtonClicked(); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 08d2baf6cd..bec670cdaa 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -192,8 +192,9 @@ void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params) void LLPanelProfile::notifyParent(const LLSD& info) { + std::string action = info["action"]; // lets update Picks list after Pick was saved - if("save_new_pick" == info["action"]) + if("save_new_pick" == action) { onOpen(info); return; diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index f1db2416e4..1d16c4ef5e 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -46,6 +46,7 @@ static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("p static std::string PANEL_NOTES = "panel_notes"; static const std::string PANEL_PROFILE = "panel_profile"; +static const std::string PANEL_PICKS = "panel_picks"; LLPanelProfileView::LLPanelProfileView() : LLPanelProfile() @@ -103,6 +104,10 @@ BOOL LLPanelProfileView::postBuild() void LLPanelProfileView::onBackBtnClick() { + // Set dummy value to make picks panel dirty, + // This will make Picks reload on next open. + getTabContainer()[PANEL_PICKS]->setValue(LLSD()); + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); if(parent) { diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 207ed723b2..7dd9df674c 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -60,6 +60,7 @@ public: virtual BOOL postBuild(); S32 getIndex() { return mIndex; } + void setIndex(S32 index) { mIndex = index; } const std::string& getRegionName() { return mRegionName;} /*virtual*/ void setValue(const LLSD& value); @@ -180,7 +181,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu() registrar.add("TeleportHistory.Teleport", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this)); registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this)); - registrar.add("TeleportHistory.Copy", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopy, this)); + registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this)); // create the context menu from the XUI return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( @@ -203,11 +204,11 @@ void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& sl gClipboard.copyFromString(utf8str_to_wstring(slurl)); } -void LLTeleportHistoryPanel::ContextMenu::onCopy() +void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard() { LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos; LLLandmarkActions::getSLURLfromPosGlobal(globalPos, - boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1), false); + boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1)); } // Not yet implemented; need to remove buildPanel() from constructor when we switch @@ -237,7 +238,7 @@ BOOL LLTeleportHistoryPanel::postBuild() mTeleportHistory = LLTeleportHistoryStorage::getInstance(); if (mTeleportHistory) { - mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this)); + mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1)); } mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion"); @@ -488,7 +489,7 @@ void LLTeleportHistoryPanel::refresh() if (mLastSelectedItemIndex == mCurrentItem) curr_flat_view->selectItem(item, true); } - + mCurrentItem--; if (++added_items >= ADD_LIMIT) @@ -503,10 +504,75 @@ void LLTeleportHistoryPanel::refresh() mDirty = false; } -void LLTeleportHistoryPanel::onTeleportHistoryChange() +void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index) { mLastSelectedItemIndex = -1; - showTeleportHistory(); + + if (-1 == removed_index) + showTeleportHistory(); // recreate all items + else + replaceItem(removed_index); // replace removed item by most recent +} + +void LLTeleportHistoryPanel::replaceItem(S32 removed_index) +{ + // Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order) + LLFlatListView* fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]); + + // Empty flat list for 'Today' means that other flat lists are empty as well, + // so all items from teleport history should be added. + if (!fv || fv->size() == 0) + { + showTeleportHistory(); + return; + } + + const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems(); + LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below + &mContextMenu, + history_items[history_items.size() - 1].mTitle); // Most recent item, it was + // added instead of removed + fv->addItem(item, LLUUID::null, ADD_TOP); + + // Index of each item, from last to removed item should be decremented + // to point to the right item in LLTeleportHistoryStorage + for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx) + { + LLAccordionCtrlTab* tab = mItemContainers.get(tab_idx); + if (!tab->getVisible()) + continue; + + fv = getFlatListViewFromTab(tab); + if (!fv) + { + showTeleportHistory(); + return; + } + + std::vector<LLPanel*> items; + fv->getItems(items); + + S32 items_cnt = items.size(); + for (S32 n = 0; n < items_cnt; ++n) + { + LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n]; + + if (item->getIndex() == removed_index) + { + fv->removeItem(item); + + // If flat list becames empty, then accordion tab should be hidden + if (fv->size() == 0) + tab->setVisible(false); + + mHistoryAccordion->arrange(); + + return; // No need to decrement idexes for the rest of items + } + + item->setIndex(item->getIndex() - 1); + } + } } void LLTeleportHistoryPanel::showTeleportHistory() diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index 49a97c5022..7c1b403432 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -57,7 +57,7 @@ public: LLContextMenu* createMenu(); void onTeleport(); void onInfo(); - void onCopy(); + void onCopyToClipboard(); static void gotSLURLCallback(const std::string& slurl); @@ -90,7 +90,8 @@ private: void refresh(); void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date); - void onTeleportHistoryChange(); + void onTeleportHistoryChange(S32 removed_index); + void replaceItem(S32 removed_index); void showTeleportHistory(); void handleItemSelect(LLFlatListView* ); LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp new file mode 100644 index 0000000000..f1e585f285 --- /dev/null +++ b/indra/newview/llparticipantlist.cpp @@ -0,0 +1,56 @@ +/** + * @file llparticipantlist.cpp + * @brief LLParticipantList implementing LLSimpleListener listener + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-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 "llparticipantlist.h" +#include "llavatarlist.h" +#include "llfloateractivespeakers.h" + + +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list): + mSpeakerMgr(data_source), + mAvatarList(avatar_list) +{ + mSpeakerMgr->addListener(this, "add"); + mSpeakerMgr->addListener(this, "remove"); + mSpeakerMgr->addListener(this, "clear"); + std::string str = "test"; + mAvatarList->setNoItemsCommentText(str); + + //LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); +} + +bool LLParticipantList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + return true; +} diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h new file mode 100644 index 0000000000..2ec563a356 --- /dev/null +++ b/indra/newview/llparticipantlist.h @@ -0,0 +1,48 @@ +/** + * @file llparticipantlist.h + * @brief LLParticipantList implementing LLSimpleListener listener + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-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 "llevent.h" + +class LLSpeakerMgr; +class LLAvatarList; + +class LLParticipantList: public LLOldEvents::LLSimpleListener +{ + public: + LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list); + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + + private: + LLSpeakerMgr* mSpeakerMgr; + LLAvatarList* mAvatarList; +}; diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 02e11cefad..d5a2d66bcf 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -1118,7 +1118,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) return TRUE; } -/*virtual*/ LLViewerVisualParam * LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const { LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar); *new_param = *this; diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index 709b176c8d..c2e5451dfe 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -417,7 +417,7 @@ public: // This sets mInfo and calls initialization functions BOOL setInfo(LLPolySkeletalDistortionInfo *info); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 924b1a4d6e..80983cad24 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -302,7 +302,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) return TRUE; } -/*virtual*/ LLViewerVisualParam * LLPolyMorphTarget::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const { LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh); *new_param = *this; diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index 5089fc2e8a..01731402df 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -154,7 +154,7 @@ public: // This sets mInfo and calls initialization functions BOOL setInfo(LLPolyMorphTargetInfo *info); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h index f704fecddd..760b1a7a4c 100644 --- a/indra/newview/llrootview.h +++ b/indra/newview/llrootview.h @@ -47,5 +47,27 @@ public: LLRootView(const Params& p) : LLView(p) {} + + // added to provide possibility to handle mouse click event inside all application + // window without creating any floater + typedef boost::signals2::signal<void(S32 x, S32 y, MASK mask)> + mouse_signal_t; + + private: + mouse_signal_t mMouseDownSignal; + + public: + /*virtual*/ + BOOL handleMouseDown(S32 x, S32 y, MASK mask) + { + mMouseDownSignal(x, y, mask); + return LLView::handleMouseDown(x, y, mask); + } + + boost::signals2::connection addMouseDownCallback( + const mouse_signal_t::slot_type& cb) + { + return mMouseDownSignal.connect(cb); + } }; #endif //LL_LLROOTVIEW_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index a72100a9b3..1683d113a9 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -138,7 +138,7 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo } //-------------------------------------------------------------------------- -void LLScreenChannel::addToast(LLToast::Params p) +void LLScreenChannel::addToast(const LLToast::Params& p) { bool store_toast = false, show_toast = false; @@ -381,7 +381,7 @@ void LLScreenChannel::showToastsBottom() if(it != mToastList.rbegin()) { bottom = (*(it-1)).toast->getRect().mTop; - toast_margin = gSavedSettings.getS32("ToastMargin"); + toast_margin = gSavedSettings.getS32("ToastGap"); } toast_rect = (*it).toast->getRect(); @@ -394,7 +394,7 @@ void LLScreenChannel::showToastsBottom() { if( it != mToastList.rend()-1) { - stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().mTop; + stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop; } } @@ -412,7 +412,7 @@ void LLScreenChannel::showToastsBottom() (*it).toast->stopTimer(); mHiddenToastsNum++; } - createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastTime")); + createOverflowToast(bottom, gSavedSettings.getS32("NotificationTipToastLifeTime")); } } @@ -426,7 +426,7 @@ void LLScreenChannel::showToastsCentre() for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { toast_rect = (*it).toast->getRect(); - toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight()); (*it).toast->setRect(toast_rect); (*it).toast->setVisible(TRUE); @@ -443,13 +443,13 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) { LLRect toast_rect; LLToast::Params p; - p.timer_period = timer; + p.lifetime_secs = timer; mOverflowToastPanel = new LLToast(p); if(!mOverflowToastPanel) return; - mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this)); + mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::closeOverflowToastPanel, this)); LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text"); LLIconCtrl* icon = mOverflowToastPanel->getChild<LLIconCtrl>("icon"); @@ -465,7 +465,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) toast_rect = mOverflowToastPanel->getRect(); mOverflowToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true); - toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight()); mOverflowToastPanel->setRect(toast_rect); text_box->setValue(text); @@ -514,11 +514,11 @@ void LLScreenChannel::closeOverflowToastPanel() } //-------------------------------------------------------------------------- -void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer) +void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer) { LLRect toast_rect; LLToast::Params p; - p.timer_period = timer; + p.lifetime_secs = timer; mStartUpToastPanel = new LLToast(p); if(!mStartUpToastPanel) @@ -545,13 +545,15 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer) toast_rect = mStartUpToastPanel->getRect(); mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true); - toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(0, toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight()); mStartUpToastPanel->setRect(toast_rect); text_box->setValue(text); text_box->setVisible(TRUE); icon->setVisible(TRUE); + addChild(mStartUpToastPanel); + mStartUpToastPanel->setVisible(TRUE); } @@ -572,7 +574,7 @@ void LLScreenChannel::closeStartUpToast() { if(mStartUpToastPanel != NULL) { - mStartUpToastPanel->closeFloater(); + mStartUpToastPanel->setVisible(FALSE); mStartUpToastPanel = NULL; } } @@ -703,7 +705,7 @@ void LLScreenChannel::updateShowToastsState() LLRect this_rect = getRect(); if(floater->getVisible() && floater->isDocked()) { - channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastMargin")); + channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap")); } if(channel_bottom != this_rect.mBottom) diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 459c28ac7c..987bc4b596 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -158,7 +158,7 @@ public: // Operating with toasts // add a toast to a channel - void addToast(LLToast::Params p); + void addToast(const LLToast::Params& p); // kill or modify a toast by its ID void killToastByNotificationID(LLUUID id); void modifyToastByNotificationID(LLUUID id, LLPanel* panel); @@ -256,7 +256,7 @@ private: void createOverflowToast(S32 bottom, F32 timer); // create the StartUp Toast - void createStartUpToast(S32 notif_num, S32 bottom, F32 timer); + void createStartUpToast(S32 notif_num, F32 timer); // Channel's flags static bool mWasStartUpToastShown; diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp index 5123d862ce..f95671685b 100644 --- a/indra/newview/llsearchcombobox.cpp +++ b/indra/newview/llsearchcombobox.cpp @@ -85,11 +85,6 @@ LLSearchComboBox::LLSearchComboBox(const Params&p) setSelectionCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this)); setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2)); mSearchButton->setCommitCallback(boost::bind(&LLSearchComboBox::onTextCommit, this, _2)); - - // set tooltip here for now since we don't want to parse /en/widgets - std::string tool_tip = LLTrans::getString("Search"); - getChild<LLView>("child1")->setToolTip(tool_tip); - getChild<LLView>("child3")->setToolTip(tool_tip); } void LLSearchComboBox::rebuildSearchHistory(const std::string& filter) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index ff95f8adce..329d7d26ee 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -144,12 +144,6 @@ BOOL LLSideTrayTab::postBuild() title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle); - static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor"); - static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor"); - - setTransparentColor(default_background_color); - setBackgroundColor(focus_background_color); - return true; } @@ -209,11 +203,6 @@ void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent ) void LLSideTrayTab::draw() { LLPanel::draw(); - - //border - gl_rect_2d(0,0,getRect().getWidth() - 1,getRect().getHeight() - 1,LLColor4::black,false); - - } void LLSideTrayTab::onOpen (const LLSD& key) @@ -548,17 +537,15 @@ void LLSideTray::expandSideBar () void LLSideTray::highlightFocused() { + /* uncomment in case something change if(!mActiveTab) return; - /* uncomment in case something change BOOL dependent_has_focus = gFocusMgr.childHasKeyboardFocus(this); setBackgroundOpaque( dependent_has_focus ); mActiveTab->setBackgroundOpaque( dependent_has_focus ); */ - mActiveTab->setBackgroundOpaque( true ); - - } + BOOL LLSideTray::handleScrollWheel(S32 x, S32 y, S32 mask) { BOOL ret = LLPanel::handleScrollWheel(x,y,mask); @@ -576,6 +563,7 @@ BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask) setFocus(true); return ret; } + void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent) { @@ -686,7 +674,7 @@ void LLSideTray::resetPanelRect () static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); S32 panel_width = sidetray_params.default_button_width; - panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth; + panel_width += mCollapsed ? 0 : mMaxBarWidth; S32 panel_height = parent_rect.getHeight()-fake_top_offset; @@ -703,7 +691,7 @@ void LLSideTray::setPanelRect () const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); S32 panel_width = sidetray_params.default_button_width; - panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth; + panel_width += mCollapsed ? 0 : mMaxBarWidth; S32 panel_height = parent_rect.getHeight()-fake_top_offset - nav_rect.getHeight(); S32 panel_top = parent_rect.mTop-fake_top_offset - nav_rect.getHeight(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3d0e25a734..43b039f94e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -83,6 +83,7 @@ #include "v3math.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llagentwearables.h" #include "llagentpilot.h" #include "llfloateravatarpicker.h" @@ -2088,7 +2089,7 @@ bool idle_startup() // reset timers now that we are running "logged in" logic LLFastTimer::reset(); - + LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); return TRUE; } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 6714fe908f..86290e6695 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -246,6 +246,10 @@ void LLSysWellWindow::toggleWindow() if(!getVisible() || isMinimized()) { + if(mChannel) + { + mChannel->removeAndStoreAllStorableToasts(); + } if(isWindowEmpty()) { return; @@ -524,7 +528,7 @@ LLSysWellWindow::RowPanel::~RowPanel() //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::onClosePanel() { - gIMMgr->removeSession(mChiclet->getSessionId()); + gIMMgr->leaveSession(mChiclet->getSessionId()); // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). } diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp index a588153ca2..d3bbda1c72 100644 --- a/indra/newview/llteleporthistorystorage.cpp +++ b/indra/newview/llteleporthistorystorage.cpp @@ -93,14 +93,12 @@ void LLTeleportHistoryStorage::onTeleportHistoryChange() addItem(item.mTitle, item.mGlobalPos); save(); - - mHistoryChangedSignal(); } void LLTeleportHistoryStorage::purgeItems() { mItems.clear(); - mHistoryChangedSignal(); + mHistoryChangedSignal(-1); } void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos) @@ -116,15 +114,16 @@ bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistor void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date) { - LLTeleportHistoryPersistentItem item(title, global_pos, date); slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(), boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item)); // If there is such item already, remove it, since new item is more recent + S32 removed_index = -1; if (item_iter != mItems.end()) { + removed_index = item_iter - mItems.begin(); mItems.erase(item_iter); } @@ -141,9 +140,12 @@ void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d // If second to last item is more recent than last, then resort items if (item_iter->mDate > item.mDate) { + removed_index = -1; std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate()); } } + + mHistoryChangedSignal(removed_index); } void LLTeleportHistoryStorage::removeItem(S32 idx) @@ -211,6 +213,8 @@ void LLTeleportHistoryStorage::load() file.close(); std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate()); + + mHistoryChangedSignal(-1); } void LLTeleportHistoryStorage::dump() const @@ -234,7 +238,6 @@ boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback( } void LLTeleportHistoryStorage::goToItem(S32 idx) - { // Validate specified index. if (idx < 0 || idx >= (S32)mItems.size()) diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h index f67c4e2fb9..2eaa94f2ed 100644 --- a/indra/newview/llteleporthistorystorage.h +++ b/indra/newview/llteleporthistorystorage.h @@ -80,8 +80,9 @@ public: typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t; - typedef boost::function<void()> history_callback_t; - typedef boost::signals2::signal<void()> history_signal_t; + // removed_index is index of removed item, which replaced by more recent + typedef boost::function<void(S32 removed_index)> history_callback_t; + typedef boost::signals2::signal<void(S32 removed_index)> history_signal_t; LLTeleportHistoryStorage(); ~LLTeleportHistoryStorage(); diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp index d0bb9e1cf1..595b24ad47 100644 --- a/indra/newview/lltexglobalcolor.cpp +++ b/indra/newview/lltexglobalcolor.cpp @@ -101,7 +101,7 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) { } -/*virtual*/ LLViewerVisualParam * LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const { LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor); *new_param = *this; diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h index f0d22d317c..1e6754133f 100644 --- a/indra/newview/lltexglobalcolor.h +++ b/indra/newview/lltexglobalcolor.h @@ -78,7 +78,7 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor { public: LLTexParamGlobalColor(LLTexGlobalColor *tex_color); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; protected: /*virtual*/ void onGlobalColorChanged(bool set_by_user); private: diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index de8458c0fa..17547cae39 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -1078,13 +1078,13 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab mInfo = info; //mID = info->mID; // No ID - mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); iter != mInfo->mParamColorInfoList.end(); iter++) { LLTexLayerParamColor* param_color; - if (!wearable) + if (!wearable) { param_color = new LLTexLayerParamColor(this); if (!param_color->setInfo(*iter, TRUE)) @@ -1105,7 +1105,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab mParamColorList.push_back( param_color ); } - mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); + mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); iter != mInfo->mParamAlphaInfoList.end(); iter++) @@ -1893,13 +1893,13 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) //----------------------------------------------------------------------------- // finds a specific layer based on a passed in name //----------------------------------------------------------------------------- -LLTexLayerInterface* LLTexLayerSet::findLayerByName(std::string name) +LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) { for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - if (layer->getName().compare(name) == 0) + if (layer->getName() == name) { return layer; } @@ -1908,7 +1908,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(std::string name) { LLTexLayerInterface* layer = *iter; - if (layer->getName().compare(name) == 0) + if (layer->getName() == name) { return layer; } diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 2269c3c9a5..e4a6e82ba5 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -60,6 +60,11 @@ typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t; typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t; typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t; + +//----------------------------------------------------------------------------- +// LLTexLayerInterface +// Interface class to generalize functionality shared by LLTexLayer and LLTexLayerTemplate. + class LLTexLayerInterface { public: @@ -256,7 +261,7 @@ public: void deleteCaches(); void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); - LLTexLayerInterface* findLayerByName(std::string name); + LLTexLayerInterface* findLayerByName(const std::string& name); void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); LLVOAvatarSelf* getAvatar() const { return mAvatar; } diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index 9cd73c4656..ca888899ed 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -140,7 +140,7 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha() sInstances.remove(this); } -/*virtual*/ LLViewerVisualParam * LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const { LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer); *new_param = *this; @@ -409,7 +409,7 @@ LLTexLayerParamColor::~LLTexLayerParamColor() { } -/*virtual*/ LLViewerVisualParam * LLTexLayerParamColor::cloneParam(LLWearable* wearable) const +/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const { LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer); *new_param = *this; diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 589bd41054..98365864f9 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -43,8 +43,8 @@ class LLTexLayerParam : public LLViewerVisualParam public: LLTexLayerParam(LLTexLayerInterface *layer); LLTexLayerParam(LLVOAvatar *avatar); - /* Virtual */ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const = 0; + /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; protected: LLTexLayerInterface* mTexLayer; @@ -61,7 +61,7 @@ public: LLTexLayerParamAlpha( LLVOAvatar* avatar ); /*virtual*/ ~LLTexLayerParamAlpha(); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable = NULL) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); @@ -138,7 +138,7 @@ public: LLTexLayerParamColor( LLVOAvatar* avatar ); /* virtual */ ~LLTexLayerParamColor(); - /*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable = NULL) const; + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 84931e4d2d..eba43d76a6 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -41,17 +41,29 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLToast::LLToast(LLToast::Params p) : LLModalDialog(LLSD(), p.is_modal), - mPanel(p.panel), - mTimerValue(p.timer_period), - mNotificationID(p.notif_id), - mSessionID(p.session_id), - mCanFade(p.can_fade), - mCanBeStored(p.can_be_stored), - mHideBtnEnabled(p.enable_hide_btn), - mHideBtn(NULL), - mNotification(p.notification), - mHideBtnPressed(false) +LLToast::Params::Params() +: can_fade("can_fade", true), + can_be_stored("can_be_stored", true), + is_modal("is_modal", false), + is_tip("is_tip", false), + enable_hide_btn("enable_hide_btn", true), + force_show("force_show", false), + force_store("force_store", false), + lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime")) +{}; + +LLToast::LLToast(const LLToast::Params& p) +: LLModalDialog(LLSD(), p.is_modal), + mPanel(p.panel), + mToastLifetime(p.lifetime_secs), + mNotificationID(p.notif_id), + mSessionID(p.session_id), + mCanFade(p.can_fade), + mCanBeStored(p.can_be_stored), + mHideBtnEnabled(p.enable_hide_btn), + mHideBtn(NULL), + mNotification(p.notification), + mHideBtnPressed(false) { LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL); @@ -67,11 +79,11 @@ LLToast::LLToast(LLToast::Params p) : LLModalDialog(LLSD(), p.is_modal), } // init callbacks if present - if(!p.on_delete_toast.empty()) - mOnDeleteToastSignal.connect(p.on_delete_toast); + if(!p.on_delete_toast().empty()) + mOnDeleteToastSignal.connect(p.on_delete_toast()); - if(!p.on_mouse_enter.empty()) - mOnMouseEnterSignal.connect(p.on_mouse_enter); + if(!p.on_mouse_enter().empty()) + mOnMouseEnterSignal.connect(p.on_mouse_enter()); } //-------------------------------------------------------------------------- @@ -103,22 +115,22 @@ void LLToast::setAndStartTimer(F32 period) { if(mCanFade) { - mTimerValue = period; + mToastLifetime = period; mTimer.start(); } } //-------------------------------------------------------------------------- -bool LLToast::timerHasExpired() +bool LLToast::lifetimeHasExpired() { if (mTimer.getStarted()) { F32 elapsed_time = mTimer.getElapsedTimeF32(); - if (elapsed_time > gSavedSettings.getS32("ToastOpaqueTime")) + if ((mToastLifetime - elapsed_time) <= gSavedSettings.getS32("ToastOpaqueTime")) { setBackgroundOpaque(FALSE); } - if (elapsed_time > mTimerValue) + if (elapsed_time > mToastLifetime) { return true; } @@ -183,7 +195,7 @@ void LLToast::insertPanel(LLPanel* panel) //-------------------------------------------------------------------------- void LLToast::draw() { - if(timerHasExpired()) + if(lifetimeHasExpired()) { tick(); } diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 29c231a01d..1826c13ebc 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -57,37 +57,28 @@ public: typedef boost::function<void (LLToast* toast)> toast_callback_t; typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t; - struct Params + struct Params : public LLInitParam::Block<Params> { - LLPanel* panel; - LLUUID notif_id; //notification ID - LLUUID session_id; //im session ID - LLNotificationPtr notification; - F32 timer_period; - toast_callback_t on_delete_toast; - toast_callback_t on_mouse_enter; - bool can_fade; - bool can_be_stored; - bool enable_hide_btn; - bool is_modal; - bool is_tip; - bool force_show; - bool force_store; - - Params() : can_fade(true), - can_be_stored(true), - is_modal(false), - is_tip(false), - enable_hide_btn(true), - force_show(false), - force_store(false), - panel(NULL), - timer_period(gSavedSettings.getS32("NotificationToastTime")) - - {}; + Mandatory<LLPanel*> panel; + Optional<LLUUID> notif_id, //notification ID + session_id; //im session ID + Optional<LLNotificationPtr> notification; + Optional<F32> lifetime_secs; + Optional<toast_callback_t> on_delete_toast, + on_mouse_enter; + Optional<bool> can_fade, + can_be_stored, + enable_hide_btn, + is_modal, + is_tip, + force_show, + force_store; + + + Params(); }; - LLToast(LLToast::Params p); + LLToast(const LLToast::Params& p); virtual ~LLToast(); BOOL postBuild(); @@ -153,7 +144,7 @@ public: private: // check timer - bool timerHasExpired(); + bool lifetimeHasExpired(); // on timer finished function void tick(); @@ -161,8 +152,9 @@ private: LLUUID mSessionID; LLNotificationPtr mNotification; + // timer counts a lifetime of a toast LLTimer mTimer; - F32 mTimerValue; + F32 mToastLifetime; // in seconds LLPanel* mPanel; LLButton* mHideBtn; diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp new file mode 100644 index 0000000000..7e4d4988d1 --- /dev/null +++ b/indra/newview/lltransientdockablefloater.cpp @@ -0,0 +1,96 @@ +/** + * @file lltransientdockablefloater.cpp + * @brief Creates a panel of a specific kind for a toast + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-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 "lltransientfloatermgr.h" +#include "lltransientdockablefloater.h" +#include "llfloaterreg.h" + + +LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockControl, bool uniqueDocking, + const LLSD& key, const Params& params) : + LLDockableFloater(dockControl, uniqueDocking, key, params) +{ + LLTransientFloaterMgr::getInstance()->registerTransientFloater(this); +} + +LLTransientDockableFloater::~LLTransientDockableFloater() +{ + LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); +} + +void LLTransientDockableFloater::setVisible(BOOL visible) +{ + LLView* dock = getDockWidget(); + if(visible && isDocked()) + { + LLTransientFloaterMgr::getInstance()->addControlView(this); + if (dock != NULL) + { + LLTransientFloaterMgr::getInstance()->addControlView(dock); + } + } + else + { + LLTransientFloaterMgr::getInstance()->removeControlView(this); + if (dock != NULL) + { + LLTransientFloaterMgr::getInstance()->removeControlView(dock); + } + } + + LLDockableFloater::setVisible(visible); +} + +void LLTransientDockableFloater::setDocked(bool docked, bool pop_on_undock) +{ + LLView* dock = getDockWidget(); + if(docked) + { + LLTransientFloaterMgr::getInstance()->addControlView(this); + if (dock != NULL) + { + LLTransientFloaterMgr::getInstance()->addControlView(dock); + } + } + else + { + LLTransientFloaterMgr::getInstance()->removeControlView(this); + if (dock != NULL) + { + LLTransientFloaterMgr::getInstance()->removeControlView(dock); + } + } + + LLDockableFloater::setDocked(docked, pop_on_undock); +} diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h new file mode 100644 index 0000000000..6e8a3afd22 --- /dev/null +++ b/indra/newview/lltransientdockablefloater.h @@ -0,0 +1,57 @@ +/** + * @file lltransientdockablefloater.h + * @brief Creates a panel of a specific kind for a toast. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-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_TRANSIENTDOCKABLEFLOATER_H +#define LL_TRANSIENTDOCKABLEFLOATER_H + +#include "llerror.h" +#include "llfloater.h" +#include "lldockcontrol.h" +#include "lldockablefloater.h" + +/** + * Represents floater that can dock and managed by transient floater manager. + * Transient floaters should be hidden if user click anywhere except defined view list. + */ +class LLTransientDockableFloater : public LLDockableFloater +{ +public: + LOG_CLASS(LLTransientDockableFloater); + LLTransientDockableFloater(LLDockControl* dockControl, bool uniqueDocking, + const LLSD& key, const Params& params = getDefaultParams()); + virtual ~LLTransientDockableFloater(); + + /*virtual*/ void setVisible(BOOL visible); + /* virtual */void setDocked(bool docked, bool pop_on_undock = true); +}; + +#endif /* LL_TRANSIENTDOCKABLEFLOATER_H */ diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp new file mode 100644 index 0000000000..7befb87248 --- /dev/null +++ b/indra/newview/lltransientfloatermgr.cpp @@ -0,0 +1,110 @@ +/** + * @file lltransientfloatermgr.cpp + * @brief LLFocusMgr base class + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-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 "lltransientfloatermgr.h" +#include "llfocusmgr.h" +#include "llrootview.h" +#include "llviewerwindow.h" +#include "lldockablefloater.h" + + +LLTransientFloaterMgr::LLTransientFloaterMgr() +{ + gViewerWindow->getRootView()->addMouseDownCallback(boost::bind( + &LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3)); +} + +void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater) +{ + mTransSet.insert(floater); +} + +void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater) +{ + mTransSet.erase(floater); +} + +void LLTransientFloaterMgr::addControlView(LLView* view) +{ + mControlsSet.insert(view); +} + +void LLTransientFloaterMgr::removeControlView(LLView* view) +{ + // we will still get focus lost callbacks on this view, but that's ok + // since we run sanity checking logic every time + mControlsSet.erase(view); +} + +void LLTransientFloaterMgr::hideTransientFloaters() +{ + for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it + != mTransSet.end(); it++) + { + LLFloater* floater = *it; + if (floater->isDocked()) + { + floater->setVisible(FALSE); + } + } +} + +void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y, + MASK mask) +{ + bool hide = true; + for (controls_set_t::iterator it = mControlsSet.begin(); it + != mControlsSet.end(); it++) + { + LLView* control_view = *it; + if (!control_view->getVisible()) + { + continue; + } + + LLRect rect = control_view->calcScreenRect(); + // if click inside view rect + if (rect.pointInRect(x, y)) + { + hide = false; + break; + } + } + + if (hide) + { + hideTransientFloaters(); + } +} + diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h new file mode 100644 index 0000000000..cef6e1fe45 --- /dev/null +++ b/indra/newview/lltransientfloatermgr.h @@ -0,0 +1,63 @@ +/** + * @file lltransientfloatermgr.h + * @brief LLFocusMgr base class + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-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_LLTRANSIENTFLOATERMGR_H +#define LL_LLTRANSIENTFLOATERMGR_H + +#include "llui.h" +#include "llsingleton.h" +#include "llfloater.h" + + +/** + * Provides functionality to hide transient floaters. + */ +class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr> +{ +public: + LLTransientFloaterMgr(); + void registerTransientFloater(LLFloater* floater); + void unregisterTransientFloater(LLFloater* floater); + void addControlView(LLView* view); + void removeControlView(LLView* view); + +private: + void hideTransientFloaters(); + void leftMouseClickCallback(S32 x, S32 y, MASK mask); + +private: + std::set<LLFloater*> mTransSet; + typedef std::set<LLView*> controls_set_t; + controls_set_t mControlsSet; +}; + +#endif // LL_LLTRANSIENTFLOATERMGR_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 81917ec76e..9ccff0c44e 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -190,7 +190,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>); LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); - LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 7e88320f49..1ad60d9a97 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -990,7 +990,7 @@ const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) -void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata) +void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) { std::string type = userdata.asString(); @@ -1003,15 +1003,22 @@ void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, co a_type = LLAssetType::AT_OUTFIT; if ("my_otfts" == type) a_type = LLAssetType::AT_MY_OUTFITS; - LLUUID category; + + LLUUID parent_id; if (bridge) { - category = gInventory.createNewCategory(bridge->getUUID(), a_type, LLStringUtil::null); + parent_id = bridge->getUUID(); + } + else if (default_parent_uuid.notNull()) + { + parent_id = default_parent_uuid; } else { - category = gInventory.createNewCategory(gInventory.getRootFolderID(), a_type, LLStringUtil::null); + parent_id = gInventory.getRootFolderID(); } + + LLUUID category = gInventory.createNewCategory(parent_id, a_type, LLStringUtil::null); gInventory.notifyObservers(); folder->setSelectionByID(category, TRUE); } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index f55a695652..d523bf2859 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -341,6 +341,7 @@ void copy_inventory_from_notecard(const LLUUID& object_id, void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge* bridge, - const LLSD& userdata); + const LLSD& userdata, + const LLUUID& default_parent_uuid = LLUUID::null); #endif // LL_LLVIEWERINVENTORY_H diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ba3d1914a7..5967b68e51 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1197,7 +1197,33 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if (mMediaSource) { - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + if( MASK_CONTROL & mask ) + { + if( 'C' == key ) + { + mMediaSource->copy(); + result = true; + } + else + if( 'V' == key ) + { + mMediaSource->paste(); + result = true; + } + else + if( 'X' == key ) + { + mMediaSource->cut(); + result = true; + } + } + + if(!result) + { + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + } } return result; @@ -1210,7 +1236,12 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) if (mMediaSource) { - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char))); + // only accept 'printable' characters, sigh... + if (uni_char >= 32 // discard 'control' characters + && uni_char != 127) // SDL thinks this is 'delete' - yuck. + { + mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char))); + } } return result; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index cb4f4de05e..01d45d0d49 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3450,6 +3450,15 @@ bool enable_standup_self() return new_value; } +// Used from the login screen to aid in UI work on side tray +void handle_show_side_tray() +{ + LLSideTray* side_tray = LLSideTray::getInstance(); + LLView* root = gViewerWindow->getRootView(); + // automatically removes and re-adds if there already + root->addChild(side_tray); +} + class LLSelfFriends : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -7934,7 +7943,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys"); view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc"); view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc"); - + commit.add("Advanced.ShowSideTray", boost::bind(&handle_show_side_tray)); // Advanced > XUI commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance())); diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index 21d4c72428..bb317aeb5f 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -105,7 +105,6 @@ #include "llstl.h" #include "llstrider.h" #include "llstring.h" -#include "llstringtable.h" #include "llsys.h" #include "llthread.h" #include "lltimer.h" diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index dac2331ca3..4ad4c8e1ea 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1474,7 +1474,7 @@ bool LLUIImageList::initFromFile() } UIImageDeclarations images; - LLXUIParser::instance().readXUI(root, images); + LLXUIParser::instance().readXUI(root, images, base_file_path); if (!images.validateBlock()) return false; diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index 82a694e277..3550a46fbf 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -83,7 +83,7 @@ public: // This sets mInfo and calls initialization functions BOOL setInfo(LLViewerVisualParamInfo *info); - virtual LLViewerVisualParam * cloneParam(LLWearable* wearable) const = 0; + virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 76e00db91c..0dcd164d83 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -792,7 +792,8 @@ LLVOAvatar::~LLVOAvatar() mMeshes.clear(); for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); jointIter++) + jointIter != mMeshLOD.end(); + ++jointIter) { LLViewerJoint* joint = (LLViewerJoint *) *jointIter; std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); @@ -943,7 +944,7 @@ void LLVOAvatar::dumpBakedStatus() for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; @@ -1135,7 +1136,7 @@ void LLVOAvatar::initInstance(void) for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - iter++) + ++iter) { const EMeshIndex mesh_index = iter->first; const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; @@ -1181,7 +1182,7 @@ void LLVOAvatar::initInstance(void) //------------------------------------------------------------------------- for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - iter++) + ++iter) { const EMeshIndex mesh_index = iter->first; const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; @@ -1190,7 +1191,8 @@ void LLVOAvatar::initInstance(void) if (baked_texture_index == BAKED_NUM_INDICES) continue; for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); - iter != mMeshLOD[mesh_index]->mMeshParts.end(); iter++) + iter != mMeshLOD[mesh_index]->mMeshParts.end(); + ++iter) { LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter; mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh); @@ -1576,7 +1578,7 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent // setup children LLVOAvatarBoneInfo::child_list_t::const_iterator iter; - for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++) + for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) { LLVOAvatarBoneInfo *child_info = *iter; if (!setupBone(child_info, joint, volume_num, joint_num)) @@ -1619,7 +1621,7 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) S32 current_joint_num = 0; S32 current_volume_num = 0; LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; - for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); iter++) + for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) { LLVOAvatarBoneInfo *info = *iter; if (!setupBone(info, NULL, current_volume_num, current_joint_num)) @@ -1682,11 +1684,11 @@ void LLVOAvatar::buildCharacter() // clear mesh data //------------------------------------------------------------------------- for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); jointIter++) + jointIter != mMeshLOD.end(); ++jointIter) { LLViewerJoint* joint = (LLViewerJoint*) *jointIter; for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); - meshIter != joint->mMeshParts.end(); meshIter++) + meshIter != joint->mMeshParts.end(); ++meshIter) { LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter; mesh->setMesh(NULL); @@ -1831,7 +1833,8 @@ void LLVOAvatar::releaseMeshData() // cleanup mesh data for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); iter++) + iter != mMeshLOD.end(); + ++iter) { LLViewerJoint* joint = (LLViewerJoint*) *iter; joint->setValid(FALSE, TRUE); @@ -1850,10 +1853,10 @@ void LLVOAvatar::releaseMeshData() } for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (!attachment->getIsHUDAttachment()) { attachment->setAttachmentVisibility(FALSE); @@ -1876,10 +1879,10 @@ void LLVOAvatar::restoreMeshData() updateJointLODs(); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (!attachment->getIsHUDAttachment()) { attachment->setAttachmentVisibility(TRUE); @@ -2328,10 +2331,10 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) { LLFastTimer t(FTM_ATTACHMENT_UPDATE); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); @@ -3554,10 +3557,10 @@ void LLVOAvatar::updateVisibility() /*llinfos << "SPA: " << sel_pos_agent << llendl; llinfos << "WPA: " << wrist_right_pos_agent << llendl;*/ for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); @@ -3989,32 +3992,32 @@ void LLVOAvatar::updateTextures(LLAgent &agent) mMaxPixelArea = 0.f; mMinPixelArea = 99999999.f; mHasGrey = FALSE; // debug - for (U32 texture = 0; texture < getNumTEs(); texture++) + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture); + EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); - const LLTextureEntry *te = getTE(texture); + const LLTextureEntry *te = getTE(texture_index); const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); LLViewerFetchedTexture *imagep = NULL; for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) { - imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture, wearable_index), TRUE); + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture); + const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index); const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; if (texture_dict->mIsLocalTexture) { - addLocalTextureStats((ETextureIndex)texture, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); + addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); } } } - if (isIndexBakedTexture((ETextureIndex) texture)) + if (isIndexBakedTexture((ETextureIndex) texture_index)) { const S32 boost_level = getAvatarBakedBoostLevel(); - imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture,0), TRUE); + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); // Spam if this is a baked texture, not set to default image, without valid host info - if (isIndexBakedTexture((ETextureIndex)texture) + if (isIndexBakedTexture((ETextureIndex)texture_index) && imagep->getID() != IMG_DEFAULT_AVATAR && !imagep->getTargetHost().isOk()) { @@ -4731,7 +4734,7 @@ BOOL LLVOAvatar::loadAvatar() // avatar_lad.xml : <morph_masks> for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin(); iter != sAvatarXmlInfo->mMorphMaskInfoList.end(); - iter++) + ++iter) { LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter; @@ -4755,7 +4758,7 @@ BOOL LLVOAvatar::loadAvatar() // avatar_lad.xml : <driver_parameters> for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); iter != sAvatarXmlInfo->mDriverInfoList.end(); - iter++) + ++iter) { LLDriverParamInfo *info = *iter; LLDriverParam* driver_param = new LLDriverParam( this ); @@ -4801,7 +4804,8 @@ BOOL LLVOAvatar::loadSkeletonNode () mRoot.addChild( &mSkeleton[0] ); for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); iter++) + iter != mMeshLOD.end(); + ++iter) { LLViewerJoint *joint = (LLViewerJoint *) *iter; joint->mUpdateXform = FALSE; @@ -4837,7 +4841,8 @@ BOOL LLVOAvatar::loadSkeletonNode () { LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); iter++) + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) { LLPolySkeletalDistortionInfo *info = *iter; LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); @@ -4857,7 +4862,8 @@ BOOL LLVOAvatar::loadSkeletonNode () { LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); - iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++) + iter != sAvatarXmlInfo->mAttachmentInfoList.end(); + ++iter) { LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter; if (!isSelf() && info->mJointName == "mScreen") @@ -4938,7 +4944,7 @@ BOOL LLVOAvatar::loadMeshNodes() { for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); - meshinfo_iter++) + ++meshinfo_iter) { const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter; const std::string &type = info->mType; @@ -4954,7 +4960,7 @@ BOOL LLVOAvatar::loadMeshNodes() mesh = &mHairMesh0; */ for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - mesh_iter++) + ++mesh_iter) { const EMeshIndex mesh_index = mesh_iter->first; const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second; @@ -5026,7 +5032,7 @@ BOOL LLVOAvatar::loadMeshNodes() for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); - xmlinfo_iter++) + ++xmlinfo_iter) { const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); @@ -5060,7 +5066,7 @@ BOOL LLVOAvatar::loadLayersets() BOOL success = TRUE; for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin(); layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); - layerset_iter++) + ++layerset_iter) { // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. LLTexLayerSetInfo *layerset_info = *layerset_iter; @@ -5467,7 +5473,7 @@ U32 LLVOAvatar::getNumAttachments() const U32 num_attachments = 0; for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); - iter++) + ++iter) { const LLViewerJointAttachment *attachment_pt = (*iter).second; num_attachments += attachment_pt->getNumObjects(); @@ -5508,10 +5514,10 @@ void LLVOAvatar::lazyAttach() void LLVOAvatar::resetHUDAttachments() { for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment()) { for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); @@ -5534,55 +5540,15 @@ void LLVOAvatar::resetHUDAttachments() BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) { for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->isObjectAttached(viewer_object)) { - LLUUID item_id = viewer_object->getItemID(); attachment->removeObject(viewer_object); - if (isSelf()) - { - // the simulator should automatically handle - // permission revocation - - stopMotionFromSource(viewer_object->getID()); - LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE); - - LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child_objectp = *iter; - // the simulator should automatically handle - // permissions revocation - - stopMotionFromSource(child_objectp->getID()); - LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE); - } - } lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl; - if (isSelf()) - { - // Then make sure the inventory is in sync with the avatar. - - // Update COF contents, don't trigger appearance update. - if (gAgent.getAvatarObject() == NULL) - { - llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; - } - else - { - LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:"); - LLAppearanceManager::removeItemLinks(item_id, false); - } - - // BAP - needs to change for label to track link. - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - gInventory.notifyObservers(); - } return TRUE; } } @@ -5667,7 +5633,7 @@ void LLVOAvatar::getOffObject() LLViewerObject::const_child_list_t& child_list = sit_object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) + iter != child_list.end(); ++iter) { LLViewerObject* child_objectp = *iter; @@ -6008,14 +5974,14 @@ void LLVOAvatar::updateMeshTextures() for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - baked_iter++) + ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { const ETextureIndex texture_index = *local_tex_iter; const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled; @@ -6039,7 +6005,7 @@ void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, B } //virtual -void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { // invalid for anyone but self llassert(0); @@ -6131,7 +6097,7 @@ void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com } for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); - iter != mBakedTextureDatas[index].mMaskedMorphs.end(); iter++) + iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) { const LLMaskedMorph* maskedMorph = (*iter); maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); @@ -6283,7 +6249,7 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl; for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; // TODO: handle multiple textures for self @@ -6332,7 +6298,7 @@ BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const indicator_te = TEX_UPPER_SHIRT; */ for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - tex_iter++) + ++tex_iter) { const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second; if (texture_dict->mWearableType == type) @@ -6363,10 +6329,10 @@ void LLVOAvatar::clampAttachmentPositions() return; } for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment) { attachment->clampObjectPosition(); @@ -6377,10 +6343,10 @@ void LLVOAvatar::clampAttachmentPositions() BOOL LLVOAvatar::hasHUDAttachment() const { for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::const_iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0) { return TRUE; @@ -6393,10 +6359,10 @@ LLBBox LLVOAvatar::getHUDBBox() const { LLBBox bbox; for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::const_iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment()) { for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); @@ -6410,7 +6376,8 @@ LLBBox LLVOAvatar::getHUDBBox() const bbox.addBBoxAgent(attached_object->getBoundingBoxAgent()); LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) + iter != child_list.end(); + ++iter) { const LLViewerObject* child_objectp = *iter; bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent()); @@ -6691,7 +6658,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture BOOL found_texture_id = false; for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; @@ -6802,9 +6769,9 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { - this->setBakedReady(*local_tex_iter, TRUE); + setBakedReady(*local_tex_iter, TRUE); } // ! BACKWARDS COMPATIBILITY ! @@ -7697,7 +7664,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const ETextureIndex index = iter->first; const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; @@ -7802,7 +7769,8 @@ U32 calc_shame(const LLVOVolume* volume, std::set<LLUUID> &textures) LLViewerObject::const_child_list_t& child_list = volume->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) + iter != child_list.end(); + ++iter) { const LLViewerObject* child_objectp = *iter; const LLDrawable* child_drawablep = child_objectp->mDrawable; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 1180d43438..27f2c77817 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -649,7 +649,7 @@ public: public: void clampAttachmentPositions(); virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); - BOOL detachObject(LLViewerObject *viewer_object); + virtual BOOL detachObject(LLViewerObject *viewer_object); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); protected: LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 99e358f409..de2c30f1a1 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -296,10 +296,10 @@ BOOL LLVOAvatarSelf::buildMenus() { BOOL attachment_found = FALSE; for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getGroup() == i) { LLMenuItemCallGL::Params item_params; @@ -315,9 +315,9 @@ BOOL LLVOAvatarSelf::buildMenus() } item_params.name =(item_params.label ); item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); gAttachPieMenu->addChild(item); @@ -342,10 +342,10 @@ BOOL LLVOAvatarSelf::buildMenus() { BOOL attachment_found = FALSE; for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getGroup() == i) { LLMenuItemCallGL::Params item_params; @@ -360,9 +360,9 @@ BOOL LLVOAvatarSelf::buildMenus() } item_params.name =(item_params.label ); item_params.on_click.function_name = "Attachment.Detach"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Attachment.EnableDetach"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); gDetachPieMenu->addChild(item); @@ -381,10 +381,10 @@ BOOL LLVOAvatarSelf::buildMenus() // add screen attachments for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getGroup() == 8) { LLMenuItemCallGL::Params item_params; @@ -399,16 +399,16 @@ BOOL LLVOAvatarSelf::buildMenus() } item_params.name =(item_params.label ); item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); gAttachScreenPieMenu->addChild(item); item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); gDetachScreenPieMenu->addChild(item); } @@ -422,10 +422,10 @@ BOOL LLVOAvatarSelf::buildMenus() break; } for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment() != (pass == 1)) { continue; @@ -442,12 +442,12 @@ BOOL LLVOAvatarSelf::buildMenus() } item_params.name =(item_params.label ); item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; //* TODO: Skinning: //LLSD params; - //params["index"] = curiter->first; + //params["index"] = iter->first; //params["label"] = attachment->getName(); //item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); @@ -455,9 +455,9 @@ BOOL LLVOAvatarSelf::buildMenus() gAttachSubMenu->addChild(item); item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = curiter->first; + item_params.on_click.parameter = iter->first; item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = curiter->first; + item_params.on_enable.parameter = iter->first; //* TODO: Skinning: item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); @@ -483,15 +483,15 @@ BOOL LLVOAvatarSelf::buildMenus() // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if(attachment->getGroup() == group) { // use multimap to provide a partial order off of the pie slice key S32 pie_index = attachment->getPieSlice(); - attachment_pie_menu_map.insert(std::make_pair(pie_index, curiter->first)); + attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first)); } } @@ -556,7 +556,7 @@ BOOL LLVOAvatarSelf::loadLayersets() BOOL success = TRUE; for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); iter != sAvatarXmlInfo->mLayerInfoList.end(); - iter++) + ++iter) { // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. const LLTexLayerSetInfo *info = *iter; @@ -574,7 +574,7 @@ BOOL LLVOAvatarSelf::loadLayersets() EBakedTextureIndex baked_index = BAKED_NUM_INDICES; for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - baked_iter++) + ++baked_iter) { const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; if (layer_set->isBodyRegion(baked_dict->mName)) @@ -597,7 +597,7 @@ BOOL LLVOAvatarSelf::loadLayersets() // scan morph masks and let any affected layers know they have an associated morph for (LLVOAvatar::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); - morph_iter++) + ++morph_iter) { LLMaskedMorph *morph = *morph_iter; LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); @@ -704,6 +704,13 @@ void LLVOAvatarSelf::updateVisualParams() } } + LLWearable *shape = gAgentWearables.getWearable(WT_SHAPE,0); + if (shape) + { + F32 gender = shape->getVisualParamWeight(80); // param 80 == gender + setVisualParamWeight("male",gender ,TRUE); + } + LLVOAvatar::updateVisualParams(); } @@ -907,10 +914,10 @@ void LLVOAvatarSelf::restoreMeshData() void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) { for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment()) { attachment->setAttachmentVisibility(TRUE); @@ -951,7 +958,7 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type ) { for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - baked_iter++) + ++baked_iter) { const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first; @@ -959,7 +966,7 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type ) { for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); type_iter != baked_dict->mWearables.end(); - type_iter++) + ++type_iter) { const EWearableType comp_type = *type_iter; if (comp_type == type) @@ -980,14 +987,16 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type ) // isWearingAttachment() //----------------------------------------------------------------------------- // Warning: include_linked_items = TRUE makes this operation expensive. -BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL include_linked_items ) const +BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id, BOOL include_linked_items) const { + const LLUUID& base_inv_item_id = getBaseAttachmentObject(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::const_iterator curiter = iter++; - const LLViewerJointAttachment* attachment = curiter->second; - if (attachment->getAttachedObject(inv_item_id)) + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) { return TRUE; } @@ -996,18 +1005,18 @@ BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL inclu if (include_linked_items) { LLInventoryModel::item_array_t item_array; - gInventory.collectLinkedItems(inv_item_id, item_array); + gInventory.collectLinkedItems(base_inv_item_id, item_array); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); iter != item_array.end(); - iter++) + ++iter) { const LLViewerInventoryItem *linked_item = (*iter); const LLUUID &item_id = linked_item->getUUID(); for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::const_iterator curiter = iter++; - const LLViewerJointAttachment* attachment = curiter->second; + const LLViewerJointAttachment* attachment = iter->second; if (attachment->getAttachedObject(item_id)) { return TRUE; @@ -1022,14 +1031,15 @@ BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL inclu //----------------------------------------------------------------------------- // getWornAttachment() //----------------------------------------------------------------------------- -LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id ) +LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + const LLUUID& base_inv_item_id = getBaseAttachmentObject(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - if (LLViewerObject *attached_object = attachment->getAttachedObject(inv_item_id)) + LLViewerJointAttachment* attachment = iter->second; + if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id)) { return attached_object; } @@ -1039,12 +1049,13 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id ) const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const { + const LLUUID& base_inv_item_id = getBaseAttachmentObject(inv_item_id); for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::const_iterator curiter = iter++; - const LLViewerJointAttachment* attachment = curiter->second; - if (attachment->getAttachedObject(inv_item_id)) + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) { return attachment->getName(); } @@ -1076,14 +1087,71 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:"); LLAppearanceManager::wearItem(item,false); // Add COF link for item. gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment_id); + gInventory.updateLinkedObjects(attachment_id); } } - gInventory.notifyObservers(); return attachment; } +//virtual +BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) +{ + const LLUUID item_id = viewer_object->getItemID(); + if (LLVOAvatar::detachObject(viewer_object)) + { + // the simulator should automatically handle permission revocation + + stopMotionFromSource(item_id); + LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE); + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); + ++iter) + { + LLViewerObject* child_objectp = *iter; + // the simulator should automatically handle + // permissions revocation + + stopMotionFromSource(child_objectp->getID()); + LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE); + } + + // Make sure the inventory is in sync with the avatar. + + // Update COF contents, don't trigger appearance update. + if (gAgent.getAvatarObject() == NULL) + { + llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; + } + else + { + LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:"); + LLAppearanceManager::removeItemLinks(item_id, false); + } + + // BAP - needs to change for label to track link. + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + gInventory.updateLinkedObjects(item_id); + gInventory.notifyObservers(); + return TRUE; + } + return FALSE; +} + +const LLUUID& LLVOAvatarSelf::getBaseAttachmentObject(const LLUUID &object_id) const +{ + const LLInventoryItem *item = gInventory.getItem(object_id); + if (!item) + return LLUUID::null; + + // Find the base object in case this a link (if it's not a link, + // this will just be inv_item_id) + return item->getLinkedUUID(); +} + void LLVOAvatarSelf::getAllAttachmentsArray(LLDynamicArray<S32>& attachments) { for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); @@ -1235,7 +1303,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - baked_iter++) + ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) @@ -1244,7 +1312,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); @@ -1276,7 +1344,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); @@ -1562,7 +1630,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te setBakedReady(type,baked_version_ready,index); } //virtual -void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { if (!isIndexLocalTexture(type)) return; LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); @@ -1583,7 +1651,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const if (isTextureDefined(baked_equiv[i])) */ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) @@ -1773,7 +1841,7 @@ BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); iter != baked_dict->mLocalTextures.end(); - iter++) + ++iter) { const ETextureIndex t_index = (*iter); lldebugs << "Checking index " << (U32) t_index << llendl; @@ -1949,7 +2017,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) TEX_UPPER_BAKED, */ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const ETextureIndex index = iter->first; const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 0b76d3e960..aaa261cea7 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -198,8 +198,8 @@ protected: private: static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); - /*virtual*/ void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); - /*virtual*/ LLViewerTexture* getImage(const U8 te, const U32 index) const; + /*virtual*/ void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); + /*virtual*/ LLViewerTexture* getImage(const U8 te, const U32 index) const; //-------------------------------------------------------------------- @@ -220,7 +220,6 @@ protected: public: void requestLayerSetUploads(); void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); -public: LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; //-------------------------------------------------------------------- @@ -267,8 +266,10 @@ protected: **/ public: - /*virtual*/ BOOL isWearingWearableType(EWearableType type ) const; - void wearableUpdated(EWearableType type); + /*virtual*/ BOOL isWearingWearableType(EWearableType type) const; + void wearableUpdated(EWearableType type); +protected: + U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; //-------------------------------------------------------------------- // Attachments @@ -276,17 +277,18 @@ public: public: void updateAttachmentVisibility(U32 camera_mode); BOOL isWearingAttachment(const LLUUID& inv_item_id, BOOL include_linked_items = FALSE) const; - LLViewerObject* getWornAttachment(const LLUUID& inv_item_id ); + LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); const std::string getAttachedPointName(const LLUUID& inv_item_id) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); + /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); void getAllAttachmentsArray(LLDynamicArray<S32>& attachments); +protected: + const LLUUID& getBaseAttachmentObject(const LLUUID &object_id) const; //-------------------------------------------------------------------- // HUDs //-------------------------------------------------------------------- private: - U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; - LLViewerJoint* mScreenp; // special purpose joint for HUD attachments /** Attachments diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 09e8c522b0..d1ad89442c 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentwearables.h" #include "llfloatercustomize.h" +#include "lllocaltextureobject.h" #include "llviewertexturelist.h" #include "llinventorymodel.h" #include "llviewerregion.h" @@ -138,11 +139,12 @@ BOOL LLWearable::exportFile(LLFILE* file) const return FALSE; } - for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); ++iter) + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) { S32 param_id = iter->first; - LLVisualParam* param = iter->second; + const LLVisualParam* param = iter->second; F32 param_weight = param->getWeight(); if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 ) { @@ -173,13 +175,13 @@ BOOL LLWearable::exportFile(LLFILE* file) const void LLWearable::createVisualParams() { LLVOAvatar* avatar = gAgent.getAvatarObject(); - for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) avatar->getNextVisualParam() ) + for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) avatar->getNextVisualParam()) { - if( (param->getWearableType() == mType) ) + if (param->getWearableType() == mType) { - if( mVisualParamIndexMap[param->getID()] ) + if (mVisualParamIndexMap[param->getID()]) { delete mVisualParamIndexMap[param->getID()]; } @@ -188,7 +190,9 @@ void LLWearable::createVisualParams() } // resync driver parameters to point to the newly cloned driven parameters - for( VisualParamIndexMap_t::iterator param_iter = mVisualParamIndexMap.begin(); param_iter != mVisualParamIndexMap.end(); param_iter++ ) + for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) { LLVisualParam* param = param_iter->second; LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; @@ -873,7 +877,7 @@ void LLWearable::setVisualParams() { LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) { S32 id = iter->first; LLVisualParam *wearable_param = iter->second; @@ -912,15 +916,15 @@ F32 LLWearable::getVisualParamWeight(S32 param_index) const LLVisualParam* LLWearable::getVisualParam(S32 index) const { - VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(index); + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; } -void LLWearable::getVisualParams(visualParamCluster_t &list) +void LLWearable::getVisualParams(visual_param_vec_t &list) { - VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.begin(); - VisualParamIndexMap_t::iterator end = mVisualParamIndexMap.end(); + visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); // add all visual params to the passed-in vector for( ; iter != end; ++iter ) @@ -929,7 +933,7 @@ void LLWearable::getVisualParams(visualParamCluster_t &list) } } -LLColor4 LLWearable::getClothesColor(S32 te) +LLColor4 LLWearable::getClothesColor(S32 te) const { LLColor4 color; U32 param_name[3]; @@ -973,7 +977,7 @@ void LLWearable::revertValues() } } -BOOL LLWearable::isOnTop() +BOOL LLWearable::isOnTop() const { return (this == gAgentWearables.getTopWearable(mType)); } @@ -996,7 +1000,7 @@ void LLWearable::saveValues() { //update saved settings so wearable is no longer dirty mSavedVisualParamMap.clear(); - for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) { S32 id = iter->first; LLVisualParam *wearable_param = iter->second; @@ -1174,7 +1178,7 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w) //w.mSaleInfo s << " Params:" << "\n"; - for (LLWearable::VisualParamIndexMap_t::const_iterator iter = w.mVisualParamIndexMap.begin(); + for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); iter != w.mVisualParamIndexMap.end(); ++iter) { S32 param_id = iter->first; diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 201f4f91ef..01bd9652a5 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -84,7 +84,7 @@ public: LLLocalTextureObject* getLocalTextureObject(S32 index) const; public: - typedef std::vector<LLVisualParam*> visualParamCluster_t; + typedef std::vector<LLVisualParam*> visual_param_vec_t; BOOL isDirty() const; BOOL isOldVersion() const; @@ -118,19 +118,19 @@ public: void setVisualParamWeight(S32 index, F32 value, BOOL set_by_user); F32 getVisualParamWeight(S32 index) const; LLVisualParam* getVisualParam(S32 index) const; - void getVisualParams(visualParamCluster_t &list); + void getVisualParams(visual_param_vec_t &list); - LLColor4 getClothesColor(S32 te); + LLColor4 getClothesColor(S32 te) const; void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user ); void revertValues(); - BOOL isOnTop(); + BOOL isOnTop() const; private: typedef std::map<S32, LLLocalTextureObject*> te_map_t; - typedef std::map<S32, LLVisualParam *> VisualParamIndexMap_t; + typedef std::map<S32, LLVisualParam *> visual_param_index_map_t; void createLayers(S32 te); void createVisualParams(); @@ -151,7 +151,7 @@ private: typedef std::map<S32, F32> param_map_t; param_map_t mSavedVisualParamMap; // last saved version of visual params - VisualParamIndexMap_t mVisualParamIndexMap; + visual_param_index_map_t mVisualParamIndexMap; te_map_t mTEMap; // maps TE to LocalTextureObject te_map_t mSavedTEMap; // last saved version of TEMap diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp index 10a9703d1a..7f0c1a13f3 100644 --- a/indra/newview/llwldaycycle.cpp +++ b/indra/newview/llwldaycycle.cpp @@ -36,6 +36,7 @@ #include "llsdserialize.h" #include "llwlparammanager.h" #include "llnotifications.h" +#include "llxmlnode.h" #include <map> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 546a06b93f..eca5130426 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -118,6 +118,8 @@ <texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" /> <texture name="Icon_For_Sale" file_name="icons/Icon_For_sale.png" preload="false" /> + <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" /> + <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" /> <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" /> <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml index a8d3f440c3..9cd7056866 100644 --- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml +++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml @@ -18,6 +18,6 @@ left="0" name="favorites_bar_btn" tab_stop="false" - top="10" + top="0" use_ellipses="true" width="120" /> diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml index 7d1a1113b0..5475a1cf6a 100644 --- a/indra/newview/skins/default/xui/en/floater_critical.xml +++ b/indra/newview/skins/default/xui/en/floater_critical.xml @@ -5,7 +5,6 @@ height="500" layout="topleft" name="modal container" - help_topic="modal_container" width="600"> <button height="20" diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 70468e7474..57f5800f2c 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -39,10 +39,10 @@ height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -335,10 +335,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -590,10 +590,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -818,10 +818,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -1006,10 +1006,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -1212,10 +1212,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -1418,10 +1418,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -1624,10 +1624,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -1830,10 +1830,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -2048,10 +2048,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -2254,10 +2254,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -2460,10 +2460,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -2666,10 +2666,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -2872,10 +2872,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" @@ -3159,10 +3159,10 @@ scratch and wear it. height="18" image_name="Lock" layout="topleft" - left="333" + left="315" mouse_opaque="true" name="square" - top="5" + top="4" width="18" /> <icon height="16" diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml index 2882f233c2..e3e2decef7 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml @@ -33,10 +33,10 @@ height="18" image_name="Lock" layout="topleft" - left="294" + left="276" mouse_opaque="true" name="IconLocked" - top="5" + top="4" width="18" /> <text type="string" 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 6fbfed5f60..90c5463aa7 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -1,47 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater - background_opaque="false" - background_visible="true" - bevel_style="in" - bg_alpha_color="0.3 0.3 0.3 1.0" + can_dock="true" + can_minimize="true" + can_close="true" + center_horiz="true" height="300" layout="topleft" name="nearby_chat" help_topic="nearby_chat" save_rect="true" title="Nearby Chat" - single_instance="true" + save_visibility="true" width="320"> - <panel top="20" width="320" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="chat_caption"> - <text - width="140" left="25" height="20" follows="left|right|top" - font="SansSerifBigBold" text_color="white" word_wrap="true" - mouse_opaque="true" name="sender_name" >NEARBY CHAT </text> - <icon top="5" left="250" - width="20" height="20" follows="top|right" - color="1 1 1 1" enabled="true" image_name="icn_voice-groupfocus.tga" - mouse_opaque="true" name="nearby_speakers_btn"/> - <icon top="5" left="275" - width="20" height="20" follows="top|right" - color="1 1 1 1" enabled="true" image_name="inv_item_landmark_visited.tga" - mouse_opaque="true" name="tearoff_btn"/> - <icon top="5" left="300" - width="15" height="15" follows="top|right" - color="1 1 1 1" enabled="true" image_name="closebox.tga" - name="close_btn"/> - </panel> <chat_history allow_html="true" bg_readonly_color="ChatHistoryBgColor" bg_writeable_color="ChatHistoryBgColor" - follows="left|top|right" + follows="all" + left="0" + top="15" font="SansSerif" layout="topleft" - height="320" + height="280" name="chat_history" parse_highlights="true" text_color="ChatHistoryTextColor" text_readonly_color="ChatHistoryTextColor" - width="250"/> + width="320"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index 448b0fa6af..8cdafe110a 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -33,10 +33,10 @@ height="18" image_name="Lock" layout="topleft" - left="340" + left="322" mouse_opaque="true" name="lock" - top="1" + top="4" width="18" /> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml index 54ab30124a..a415239867 100644 --- a/indra/newview/skins/default/xui/en/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml @@ -30,10 +30,10 @@ height="18" image_name="Lock" layout="topleft" - left="444" + left="426" mouse_opaque="true" name="lock" - top="3" + top="4" width="18" /> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml index 8e1317440e..b89af0ef3e 100644 --- a/indra/newview/skins/default/xui/en/floater_select_key.xml +++ b/indra/newview/skins/default/xui/en/floater_select_key.xml @@ -6,7 +6,6 @@ height="100" layout="topleft" name="modal container" - help_topic="modal_container" width="240"> <button height="20" diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml index b290a9c87d..54facbb659 100644 --- a/indra/newview/skins/default/xui/en/floater_tos.xml +++ b/indra/newview/skins/default/xui/en/floater_tos.xml @@ -5,7 +5,6 @@ height="500" layout="topleft" name="modal container" - help_topic="modal_container" width="600"> <floater.string name="real_url"> diff --git a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml index e698dfe2dc..ee67989d33 100644 --- a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml +++ b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml @@ -6,7 +6,6 @@ height="100" layout="topleft" name="modal container" - help_topic="modal_container" width="240"> <button height="20" diff --git a/indra/newview/skins/default/xui/en/menu_landmark.xml b/indra/newview/skins/default/xui/en/menu_landmark.xml index 54a4095967..93b6db222a 100644 --- a/indra/newview/skins/default/xui/en/menu_landmark.xml +++ b/indra/newview/skins/default/xui/en/menu_landmark.xml @@ -28,6 +28,9 @@ <menu_item_call.on_click function="Places.OverflowMenu.Action" parameter="pick" /> + <menu_item_call.on_enable + function="Places.OverflowMenu.Enable" + parameter="can_create_pick" /> </menu_item_call> <menu_item_call label="Add to Favorites Bar" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 8cb0a69906..c3ee6e250b 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -222,6 +222,12 @@ function="ShowFloater" parameter="test_inspectors" /> </menu_item_call> + <menu_item_call + label="Show Side Tray" + name="Show Side Tray"> + <menu_item_call.on_click + function="Advanced.ShowSideTray" /> + </menu_item_call> <menu_item_separator /> <menu_item_call label="Show TOS" diff --git a/indra/newview/skins/default/xui/en/menu_place.xml b/indra/newview/skins/default/xui/en/menu_place.xml index 01f62985ca..1b96eb51f0 100644 --- a/indra/newview/skins/default/xui/en/menu_place.xml +++ b/indra/newview/skins/default/xui/en/menu_place.xml @@ -20,6 +20,9 @@ <menu_item_call.on_click function="Places.OverflowMenu.Action" parameter="pick" /> + <menu_item_call.on_enable + function="Places.OverflowMenu.Enable" + parameter="can_create_pick" /> </menu_item_call> <menu_item_separator layout="topleft"/> diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml index c95cf32a5a..29fb4990d0 100644 --- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml @@ -34,6 +34,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="cut" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="cut" /> </menu_item_call> <menu_item_call label="Copy" @@ -61,6 +64,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="rename" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="rename" /> </menu_item_call> <menu_item_call label="Delete" @@ -69,6 +75,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="delete" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="delete" /> </menu_item_call> <menu_item_separator layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml index 0246d775ee..c60f670fa6 100644 --- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml +++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml @@ -66,6 +66,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="cut" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="cut" /> </menu_item_call> <menu_item_call label="Copy Landmark" @@ -101,6 +104,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="rename" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="rename" /> </menu_item_call> <menu_item_call label="Delete" @@ -109,6 +115,9 @@ <on_click function="Places.LandmarksGear.CopyPaste.Action" parameter="delete" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="delete" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -146,5 +155,8 @@ <on_click function="Places.LandmarksGear.Custom.Action" parameter="create_pick" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="create_pick" /> </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml index 515278c23d..0160d52b17 100644 --- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml @@ -17,10 +17,10 @@ function="TeleportHistory.MoreInformation" /> </menu_item_call> <menu_item_call - label="Copy" + label="Copy to Clipboard" layout="topleft" - name="Copy"> + name="CopyToClipboard"> <menu_item_call.on_click - function="TeleportHistory.Copy" /> + function="TeleportHistory.CopyToClipboard" /> </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 495795d14a..cbc94e5e74 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -56,7 +56,7 @@ function="Edit.EnableCustomizeAvatar" /> </menu_item_call> <menu_item_check - label="My Things" + label="My Inventory" layout="topleft" name="Inventory" shortcut="control|I"> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 2c9109449c..f747c557e2 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -69,14 +69,14 @@ name="speaking_indicator" visible="true" width="20" /> - <button + <button follows="right" height="16" image_pressed="Info_Press" image_hover="Info_Over" image_unselected="Info_Off" - layout="topleft" - left_pad="5" + left_pad="3" + right="-25" name="info_btn" picture_style="true" width="16" /> @@ -88,6 +88,7 @@ image_unselected="BuyArrow_Press" layout="topleft" left_pad="5" + right="-5" name="profile_btn" picture_style="true" width="16" /> diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index d268258f6f..b002034a08 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel + background_visible="true" class="edit_profile_panel" follows="all" height="535" @@ -301,76 +302,6 @@ width="285" word_wrap="true" /> </panel> - <text - type="string" - length="1" - follows="left|top" - font="SansSerifSmall" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_afk_text" - text_color="white" - top_pad="0" - width="190"> - Away Timeout: - </text> - <spinner - control_name="AFKTimeout" - decimal_digits="0" - follows="left|top" - halign="right" - height="15" - increment="1" - initial_value="300" - label="" - label_width="0" - layout="topleft" - max_val="600" - min_val="30" - name="afk_timeout_spinner" - left_pad="4" - width="50" /> - <text - type="string" - length="1" - follows="left|top" - halign="left" - height="15" - layout="topleft" - left_pad="2" - name="seconds_textbox" - width="70"> - seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - font="SansSerifSmall" - font.style="BOLD" - text_color="white" - left="10" - mouse_opaque="false" - name="text_box3" - width="240"> - Busy Mode Response: - </text> - <text_editor - control_name="BusyModeResponse2" - commit_on_focus_lost = "true" - follows="left|top" - height="56" - layout="topleft" - left="10" - name="busy_response" - width="285" - word_wrap="true"> - log_in_to_change - </text_editor> </panel> </panel> </scroll_container> diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index c18b625033..9bd240eccc 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -46,6 +46,7 @@ Hover your mouse over the options for more help. layout="topleft" left="5" name="text_owners_and_visible_members" + text_color="EmphasisColor" top_pad="10" width="270"> Members @@ -74,6 +75,7 @@ Hover your mouse over the options for more help. follows="left|top" height="16" type="string" + text_color="EmphasisColor" top_pad="10" font="SansSerifBig" layout="topleft" @@ -165,7 +167,7 @@ Hover your mouse over the options for more help. name="spin_enrollment_fee" tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked." top_delta="-2" - width="75" /> + width="105" /> <check_box height="16" initial_value="true" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index c3b277fb1d..da6cf8891a 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -151,16 +151,16 @@ visible="false" width="65" /> <accordion layout="topleft" left="2" width="296" top="135" height="500" follows="all" name="group_accordion"> - <accordion_tab min_height="445" title="Group General" name="group_general_tab"> + <accordion_tab min_height="445" title="General" name="group_general_tab"> <panel class="panel_group_general" filename="panel_group_general.xml" name="group_general_tab_panel"/> </accordion_tab> - <accordion_tab min_height="380" title="Group Roles" name="group_roles_tab" expanded="False" can_resize="false"> + <accordion_tab min_height="380" title="Members & Roles" name="group_roles_tab" expanded="False" can_resize="false"> <panel class="panel_group_roles" filename="panel_group_roles.xml" name="group_roles_tab_panel"/> </accordion_tab> - <accordion_tab min_height="530" title="Group Notices" name="group_notices_tab" expanded="False" can_resize="false"> + <accordion_tab min_height="530" title="Notices" name="group_notices_tab" expanded="False" can_resize="false"> <panel class="panel_group_notices" filename="panel_group_notices.xml" name="group_notices_tab_panel"/> </accordion_tab> - <accordion_tab min_height="270" title="Group Land Money" name="group_land_tab" expanded="False" can_resize="false"> + <accordion_tab min_height="270" title="Land & L$" name="group_land_tab" expanded="False" can_resize="false"> <panel class="panel_group_land_money" filename="panel_group_land_money.xml" name="group_land_tab_panel"/> </accordion_tab> </accordion> diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index d61fcf529a..0845ec014e 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -2,7 +2,7 @@ <panel border="true" follows="all" - height="410" + height="510" label="Land & L$" layout="topleft" left="1" @@ -194,7 +194,7 @@ left_pad="5" name="your_contribution_units" top_delta="2"> - ( m² ) + m² </text> <text type="string" @@ -239,13 +239,14 @@ layout="topleft" left="10" name="group_money_heading" + text_color="EmphasisColor" top_pad="0" width="150"> Group L$ </text> <tab_container follows="all" - height="100" + height="200" layout="topleft" left="10" name="group_money_tab_container" @@ -268,13 +269,14 @@ bg_readonly_color="0.784314 0.819608 0.8 1" follows="all" font="Monospace" - height="172" + height="168" layout="topleft" left="8" max_length="4096" name="group_money_planning_text" top="5" - width="250"> + width="250" + word_wrap="true"> Computing... </text_editor> </panel> @@ -300,7 +302,8 @@ max_length="4096" name="group_money_details_text" top="7" - width="250"> + width="250" + word_wrap="true"> Computing... </text_editor> <button @@ -346,7 +349,8 @@ max_length="4096" name="group_money_sales_text" top="7" - width="250"> + width="250" + word_wrap="true"> Computing... </text_editor> <button diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 6eec0ffe7a..7bdcaafe31 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -31,33 +31,44 @@ follows="top|left" height="20" image_name="Generic_Group" + name="group_icon" layout="topleft" left="5" mouse_opaque="true" - name="group_icon" - top="4" + top="2" width="20" /> - <text + <text follows="left|right" font="SansSerifSmall" - height="17" + height="15" layout="topleft" left_pad="5" name="group_name" - top="7" + top="6" use_ellipses="true" value="Unknown" - width="263" /> + width="246" /> <button follows="right" height="16" image_pressed="Info_Press" image_hover="Info_Over" image_unselected="Info_Off" - layout="topleft" + left_pad="3" + right="-25" name="info_btn" picture_style="true" + width="16" /> + <button + follows="right" + height="16" + image_selected="BuyArrow_Press" + image_pressed="BuyArrow_Press" + image_unselected="BuyArrow_Press" + layout="topleft" + left_pad="5" right="-5" - top="4" + name="profile_btn" + picture_style="true" width="16" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 82a3c98dd9..d9fb962998 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -52,6 +52,7 @@ the General tab. layout="topleft" left_delta="10" name="lbl2" + text_color="EmphasisColor" top_pad="10" width="270"> Notices are kept for 14 days. Notice lists are limited to 200 notices per group on a daily basis. @@ -135,6 +136,7 @@ the General tab. left="10" mouse_opaque="false" name="lbl" + text_color="EmphasisColor" top_pad="0" width="265"> Create a Notice @@ -147,6 +149,7 @@ the General tab. layout="topleft" left_delta="0" name="lbl2" + text_color="EmphasisColor" top_pad="4" width="195"> You can add a single item to a notice by dragging it from your inventory to this panel. Attached items must be copiable and transferrable, and you can't send a folder. @@ -289,6 +292,7 @@ the General tab. left="10" mouse_opaque="false" name="lbl" + text_color="EmphasisColor" top_pad="0" width="265"> Archived Notice @@ -302,7 +306,7 @@ the General tab. name="lbl2" top_pad="4" width="265"> - To send a new notice, click the 'Create New Notice' button above. + To send a new notice, click the 'New Notice' button above. </text> <text type="string" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index ad452b16a7..c33f68eaf7 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -31,6 +31,7 @@ left="0" mouse_opaque="true" name="favorites_list" + start_folder="favorite" width="380"/> </accordion_tab> <accordion_tab @@ -62,6 +63,7 @@ left="0" mouse_opaque="true" name="my_inventory_list" + start_folder="inventory" width="380"/> </accordion_tab> <accordion_tab @@ -77,6 +79,7 @@ left="0" mouse_opaque="true" name="library_list" + start_folder="library" width="380"/> </accordion_tab> </accordion> @@ -127,7 +130,7 @@ picture_style="true" tool_tip="Add new folder" width="18" /> - <button + <dnd_button follows="bottom|right" height="18" image_selected="TrashItem_Press" 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 00100693cc..4e1ea0f490 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -137,6 +137,6 @@ name="favorite" image_drag_indication="Arrow_Down" chevron_button_tool_tip="Show more of My Favorites" - top="32" + bottom="65" width="590" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 4d890b1d46..9c2829d92d 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -12,6 +12,7 @@ width="350"> <panel background_visible="true" + bg_alpha_color="0.3 0.3 0.3 0" follows="left|right|top" height="100" label="info_panel" @@ -70,6 +71,7 @@ </panel> <panel background_visible="true" + bg_alpha_color="0.3 0.3 0.3 0" follows="left|right|bottom" height="40" label="control_panel" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 8274beb538..085b732473 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Side tray panel --> <panel background_visible="true" - draw_border="false" follows="all" height="570" label="People" @@ -10,7 +10,6 @@ background_visible="true" name="people_panel" top="0" left="0" - bevel_style="none" width="333"> <string name="no_people" @@ -69,6 +68,7 @@ background_visible="true" <avatar_list follows="all" height="470" + ignore_online_status="true" layout="topleft" left="0" name="avatar_list" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index f7d7d52b68..16fdbd7045 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -196,7 +196,7 @@ Automatic positioning for: name="heading3" top_pad="10" width="270"> -My Avatar: +Avatars: </text> <check_box control_name="FirstPersonAvatarVisible" 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 a94cfbeec4..975d21aaa6 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -33,7 +33,7 @@ width="170"> <combo_box.item enabled="true" - label="System Default" + label="System default" name="System Default Language" value="default" /> <combo_box.item @@ -189,7 +189,7 @@ name="start_location_textbox" top_delta="20" width="394"> - Start Location: + Start location: </text> <combo_box control_name="LoginLocation" @@ -213,7 +213,7 @@ control_name="ShowStartLocation" height="16" initial_value="true" - label="Show on Login" + label="Show on login" layout="topleft" left_delta="175" name="show_location_checkbox" @@ -272,7 +272,7 @@ layout="topleft" left_delta="0" name="show_my_name_checkbox1" - top_pad="5" + top_pad="-7" width="300" /> <check_box enabled_control="AvatarNameTagMode" @@ -303,7 +303,7 @@ layout="topleft" left="30" name="effects_color_textbox" - top_pad="10" + top_pad="5" width="400"> My Effects: </text> @@ -316,7 +316,76 @@ left_delta="50" name="effect_color_swatch" tool_tip="Click to open Color Picker" - top_pad="10" + top_pad="5" width="32" /> + <text + type="string" + length="1" + follows="left|top" + height="15" + layout="topleft" + left="30" + name="title_afk_text" + text_color="white" + top_pad="-5" + width="190"> + Away timeout: + </text> + <spinner + control_name="AFKTimeout" + decimal_digits="0" + follows="left|top" + halign="right" + height="15" + increment="1" + initial_value="300" + label="" + label_width="0" + layout="topleft" + left_delta="50" + max_val="600" + min_val="30" + name="afk_timeout_spinner" + top_pad="5" + width="50" /> + <text + type="string" + length="1" + follows="left|top" + halign="left" + height="15" + layout="topleft" + left_pad="2" + name="seconds_textbox" + width="70"> + seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + text_color="white" + left="30" + mouse_opaque="false" + name="text_box3" + top_pad="10" + width="240"> + Busy mode response: + </text> + <text_editor + control_name="BusyModeResponse2" + commit_on_focus_lost = "true" + follows="left|top" + height="56" + layout="topleft" + left_delta="50" + name="busy_response" + width="400" + word_wrap="true" + top_pad="5"> + log_in_to_change + </text_editor> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 519b469868..b1308a1942 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -92,7 +92,7 @@ name="UI Size:" top_pad="4" width="300"> - UI Size: + UI size: </text> <slider can_edit_text="true" @@ -290,7 +290,7 @@ control_name="RenderObjectBump" height="16" initial_value="true" - label="Bump Mapping and Shiny" + label="Bump mapping and shiny" layout="topleft" left_delta="0" name="BumpShiny" @@ -300,7 +300,7 @@ control_name="VertexShaderEnable" height="16" initial_value="true" - label="Basic Shaders" + label="Basic shaders" layout="topleft" left_delta="0" name="BasicShaders" @@ -314,7 +314,7 @@ control_name="WindLightUseAtmosShaders" height="16" initial_value="true" - label="Atmospheric Shaders" + label="Atmospheric shaders" layout="topleft" left_delta="0" name="WindLightUseAtmosShaders" @@ -327,7 +327,7 @@ control_name="RenderWaterReflections" height="16" initial_value="true" - label="Water Reflections" + label="Water reflections" layout="topleft" left_delta="0" name="Reflections" @@ -346,7 +346,7 @@ name="ReflectionDetailText" top_pad="7" width="128"> - Reflection Detail: + Reflection detail: </text> <radio_group control_name="RenderReflectionDetail" @@ -359,7 +359,7 @@ width="321"> <radio_item height="16" - label="Terrain and Trees" + label="Terrain and trees" layout="topleft" left="3" name="0" @@ -367,7 +367,7 @@ width="315" /> <radio_item height="16" - label="All Static Objects" + label="All static objects" layout="topleft" left_delta="0" name="1" @@ -375,7 +375,7 @@ width="315" /> <radio_item height="16" - label="All Avatars and Objects" + label="All avatars and objects" layout="topleft" left_delta="0" name="2" @@ -400,13 +400,13 @@ name="AvatarRenderingText" top_pad="5" width="128"> - Avatar Rendering: + Avatar rendering: </text> <check_box control_name="RenderUseImpostors" height="16" initial_value="true" - label="Avatar Impostors" + label="Avatar impostors" layout="topleft" left_delta="0" name="AvatarImpostors" @@ -416,7 +416,7 @@ control_name="RenderAvatarVP" height="16" initial_value="true" - label="Hardware Skinning" + label="Hardware skinning" layout="topleft" left_delta="0" name="AvatarVertexProgram" @@ -429,7 +429,7 @@ control_name="RenderAvatarCloth" height="16" initial_value="true" - label="Avatar Cloth" + label="Avatar cloth" layout="topleft" left_delta="0" name="AvatarCloth" @@ -443,7 +443,7 @@ height="16" increment="8" initial_value="160" - label="Draw Distance:" + label="Draw distance:" label_width="140" layout="topleft" left="216" @@ -474,7 +474,7 @@ height="16" increment="256" initial_value="4096" - label="Max. Particle Count:" + label="Max. particle count:" label_width="140" layout="topleft" left="216" @@ -489,7 +489,7 @@ height="16" increment="1" initial_value="8" - label="Post Process Quality:" + label="Post process quality:" label_width="140" layout="topleft" left_delta="0" @@ -513,7 +513,7 @@ name="MeshDetailText" top_pad="5" width="128"> - Mesh Detail: + Mesh detail: </text> <slider control_name="RenderVolumeLODFactor" @@ -724,7 +724,7 @@ name="LightingDetailText" top_pad="8" width="128"> - Lighting Detail: + Lighting detail: </text> <radio_group control_name="RenderLightingDetail" @@ -762,7 +762,7 @@ name="TerrainDetailText" top="465" width="128"> - Terrain Detail: + Terrain detail: </text> <radio_group control_name="RenderTerrainDetail" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index df347cfb5f..9cf0bd26d8 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -141,7 +141,7 @@ height="16" increment="1" initial_value="80" - label="Port Number:" + label="Port number:" label_width="75" layout="topleft" left_delta="160" @@ -294,7 +294,7 @@ follows="left|top" height="16" initial_value="false" - label="Web Proxy" + label="Web proxy" left_delta="0" mouse_opaque="true" name="web_proxy_enabled" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index f5f9850a4e..8a28719d98 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -15,7 +15,7 @@ height="15" increment="0.05" initial_value="0.5" - label="Master Volume" + label="Master volume" label_width="125" layout="topleft" left="30" @@ -314,23 +314,27 @@ Sound out/in: </text> <button - enabled_control="EnableVoiceChat" + control_name="ShowDeviceSettings" follows="left|top" height="20" - label="Device Settings" + is_toggle="true" + label="Device settings" layout="topleft" left_delta="55" name="device_settings_btn" top_pad="0" - width="155"> - <button.commit_callback - function="Floater.Show" - parameter="pref_voicedevicesettings" /> - </button> - <panel.string - name="default_text"> - Default - </panel.string> + width="155" /> + <panel + visiblity_control="ShowDeviceSettings" + border="false" + follows="top|left" + height="260" + label="DeviceSettings" + layout="topleft" + left="0" + name="Device Settings" + top_pad="5" + width="485"> <text type="string" length="1" @@ -339,14 +343,14 @@ layout="topleft" left="30" name="Input device (microphone):" - top_pad="5" + top_pad="0" width="200"> Input device (microphone): </text> <combo_box height="18" layout="topleft" - left_delta="70" + left_delta="55" max_chars="128" name="voice_input_device" top_pad="2" @@ -366,7 +370,7 @@ <combo_box height="18" layout="topleft" - left_delta="70" + left_delta="55" max_chars="128" name="voice_output_device" top_pad="2" @@ -381,7 +385,7 @@ name="Input level:" top_pad="10" width="200"> - Input Level + Input level </text> <slider_bar follows="left|top" @@ -452,6 +456,6 @@ word_wrap="true"> Adjust the slider to control how loud you sound to other Residents. To test the input level, simply speak into your microphone. </text> - + </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index d3d45640cb..395b574425 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Side tray cannot show background because it is always + partially on screen to hold tab buttons. --> <side_tray name="sidebar" background_visible="false" @@ -6,6 +8,10 @@ width="333" collapsed="true" > + <!-- Individual tabs must show background to have seemless + appearance up to tray panel header word like "Home". + Embedded panels are inset by a pixel and so their + backgrounds will not block the world fully. --> <sidetray_tab name="sidebar_home" help_topic="sidebar_home" @@ -13,14 +19,12 @@ description="Home." image="TabIcon_Open_Off" mouse_opaque="false" - background_opaque="false" background_visible="true" > <panel name="panel_home" filename="panel_sidetray_home_tab.xml" label="home" - border="true" /> </sidetray_tab> @@ -31,7 +35,6 @@ description="Find your friends, contacts and people nearby." image="TabIcon_People_Off" mouse_opaque="false" - background_opaque="false" background_visible="true" > <panel_container @@ -42,20 +45,17 @@ class="panel_people" name="panel_people" filename="panel_people.xml" - border="true" /> <panel class="panel_profile_view" name="panel_profile_view" filename="panel_profile_view.xml" - border="true" /> <panel class="panel_group_info_sidetray" name="panel_group_info_sidetray" filename="panel_group_info_sidetray.xml" label="Group Info" - border="true" font="SansSerifBold" /> <panel @@ -63,12 +63,12 @@ name="panel_block_list_sidetray" filename="panel_block_list_sidetray.xml" label="Blocked Residents & Objects" - border="true" font="SansSerifBold" /> </panel_container> </sidetray_tab> + <sidetray_tab name="sidebar_places" help_topic="sidebar_places" @@ -84,7 +84,6 @@ name="panel_places" filename="panel_places.xml" label="Places" - border="true" font="SansSerifBold" /> </sidetray_tab> @@ -103,7 +102,6 @@ name="panel_me_profile" filename="panel_me_profile.xml" label="Me" - border="true" /> </sidetray_tab> @@ -114,18 +112,15 @@ description="Change your appearance and current look." image="TabIcon_Appearance_Off" mouse_opaque="false" - background_opaque="false" background_visible="true" > <panel class="panel_appearance" name="panel_appearance" filename="panel_appearance.xml" - border="true" label="Edit Appearance" font="SansSerifBold" /> </sidetray_tab> - </side_tray> diff --git a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml index e991861e94..247054772e 100644 --- a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml +++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Part of side tray, see that XML file for panel config --> <panel - background_visible="true" - bevel_style="out" follows="all" height="560" label="home_tab" diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 01fd84e09d..2e500fc2aa 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -7,7 +7,7 @@ visible="false" layout="topleft" width="350" - height="72" + height="40" left="100" top="500" follows="right|bottom" @@ -24,18 +24,18 @@ visible="false" follows="left|top|right|bottom" font="SansSerifBold" - height="40" + height="28" layout="topleft" left="60" name="toast_text" word_wrap="true" text_color="white" - top="20" + top="10" width="290"> Toast text; </text> <icon - top="20" + top="4" left="10" width="32" height="32" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0ca6c87585..a57c9cd97f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -16,7 +16,7 @@ <string name="StartupLoading">Loading</string> <!-- Legacy strings, almost never used --> - <string name="Fullbright">Fullbright (Legacy)</string> + <string name="Fullbright">Fullbright (Legacy)</string> <!-- used in the Build > materials dropdown--> <!-- Login --> <string name="LoginInProgress">Logging in. [APP_NAME] may appear frozen. Please wait.</string> @@ -130,7 +130,7 @@ <string name="AssetErrorPriceMismatch">Viewer and server do not agree on price</string> <string name="AssetErrorUnknownStatus">Unknown status</string> - <!-- Asset Type Human Names --> + <!-- Asset Type human readable names: these will replace variable [TYPE] in notification FailedToFindWearable* --> <string name="texture">texture</string> <string name="sound">sound</string> <string name="calling card">calling card</string> @@ -138,23 +138,23 @@ <string name="legacy script">legacy script</string> <string name="clothing">clothing</string> <string name="object">object</string> - <string name="note card">note card</string> + <string name="note card">notecard</string> <string name="folder">folder</string> <string name="root">root</string> - <string name="lsl2 script">lsl2 script</string> - <string name="lsl bytecode">lsl bytecode</string> + <string name="lsl2 script">LSL2 script</string> + <string name="lsl bytecode">LSL bytecode</string> <string name="tga texture">tga texture</string> - <string name="body part">body part</string> - <string name="snapshot">snapshot</string> - <string name="lost and found">lost and found</string> - <string name="targa image">targa image</string> - <string name="trash">trash</string> - <string name="jpeg image">jpeg image</string> - <string name="animation">animation</string> - <string name="gesture">gesture</string> - <string name="simstate">simstate</string> - <string name="favorite">favorite</string> - <string name="symbolic link">link</string> + <string name="body part">body part</string> + <string name="snapshot">snapshot</string> + <string name="lost and found">Lost and Found</string> + <string name="targa image">targa image</string> + <string name="trash">Trash</string> + <string name="jpeg image">jpeg image</string> + <string name="animation">animation</string> + <string name="gesture">gesture</string> + <string name="simstate">simstate</string> + <string name="favorite">favorite</string> + <string name="symbolic link">link</string> <!-- llvoavatar. Displayed in the avatar chat bubble --> <string name="AvatarEditingAppearance">(Editing Appearance)</string> @@ -2844,13 +2844,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Wide Lips">Wide Lips</string> <string name="Wild">Wild</string> <string name="Wrinkles">Wrinkles</string> - - <string name="Search">Search</string> <!-- Favorites Bar --> <string name="LocationCtrlAddLandmarkTooltip">Add to My Landmarks</string> <string name="LocationCtrlEditLandmarkTooltip">Edit My Landmark</string> - + <string name="LocationCtrlInfoBtnTooltip">See more info about the current location</string> + <string name="LocationCtrlComboBtnTooltip">My location history</string> + <!-- Strings used by the (currently Linux) auto-updater app --> <string name="UpdaterWindowTitle"> [APP_NAME] Update @@ -2884,6 +2884,22 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. </string> <!-- IM system messages --> + <string name="ringing-im"> + Joining Voice Chat... + </string> + <string name="connected-im"> + Connected, click End Call to hang up + </string> + <string name="hang_up-im"> + Left Voice Chat + </string> + <string name="answering-im"> + Connecting... + </string> + <string name="inventory_item_offered-im"> + Inventory item offered + </string> + <string name="only_user_message"> You are the only user in this session. </string> 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 1377a3c945..f2e48c517d 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -21,7 +21,6 @@ > <info_button name="Place Information" label="" - tool_tip="See more info about the current location" width="16" height="16" follows="left|top" @@ -43,8 +42,7 @@ left="-3" /> <combo_button name="Location History" label="" - pad_right="0" - tool_tip="My location history"/> + pad_right="0"/> <combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10" scroll_bar_bg_visible="true" /> <combo_editor name="Combo Text Entry" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 06eb1e1265..231a8e21a5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -573,6 +573,24 @@ class DarwinManifest(ViewerManifest): self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + # our apps dependencies on shared libs + if dylibs["llcommon"]: + mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources") + mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources") + for libfile in ("libllcommon.dylib", + "libapr-1.0.3.7.dylib", + "libaprutil-1.0.3.8.dylib", + "libexpat.0.5.0.dylib"): + target_lib = os.path.join('../../..', libfile) + self.run_command("ln -sf %(target)s '%(link)s'" % + {'target': target_lib, + 'link' : os.path.join(mac_crash_logger_res_path, libfile)} + ) + self.run_command("ln -sf %(target)s '%(link)s'" % + {'target': target_lib, + 'link' : os.path.join(mac_updater_res_path, libfile)} + ) + # plugin launcher self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") |