From 427fa3344639873579bb3b75a647463839227e6a Mon Sep 17 00:00:00 2001 From: gabriel lee Date: Fri, 8 Jan 2010 17:09:59 +0000 Subject: EXT-3630 & EXT-3893 added object owners to script information floater and corrected memory readout for attachments reviewed by H --- indra/newview/llfloaterscriptlimits.cpp | 101 ++++++++++++++++++++++++++++---- indra/newview/llfloaterscriptlimits.h | 14 +++-- 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 3042fbc6ec..0964ad7f91 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -64,6 +64,8 @@ // summary which only shows available & correct information #define USE_SIMPLE_SUMMARY +const S32 SIZE_OF_ONE_KB = 1024; + LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed) : LLFloater(seed) { @@ -130,7 +132,6 @@ void LLFloaterScriptLimits::refresh() } } - ///---------------------------------------------------------------------------- // Base class for panels ///---------------------------------------------------------------------------- @@ -331,6 +332,57 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<("scripts_list"); + std::vector::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + + // fill in the url's tab if needed, all urls must have memory so we can do it all here + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild("script_limits_region_urls_panel"); + + LLScrollListCtrl *list = panel->getChild("scripts_list"); + std::vector::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + } +} + void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) { LLScrollListCtrl *list = getChild("scripts_list"); @@ -345,22 +397,40 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; + std::vector names_requested; + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); - + LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); for(S32 j = 0; j < number_objects; j++) { - S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024; + S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; total_size += size; std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + + BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf); + if(!name_is_cached) + { + if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end()) + { + names_requested.push_back(owner_id); + gCacheName->get(owner_id, TRUE, + boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache, + this, _1, _2, _3)); + } + } LLSD element; element["id"] = task_id; + element["owner_id"] = owner_id; element["columns"][0]["column"] = "size"; element["columns"][0]["value"] = llformat("%d", size); element["columns"][0]["font"] = "SANSSERIF"; @@ -368,18 +438,18 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; - list->addElement(element); - mObjectListIDs.push_back(task_id); + list->addElement(element, ADD_SORTED); + mObjectListItems.push_back(element); total_objects++; } } - + mParcelMemoryUsed =total_size; mGotParcelMemoryUsed = TRUE; populateParcelMemoryText(); @@ -556,7 +626,7 @@ void LLPanelScriptLimitsRegionMemory::clearList() childSetValue("memory_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -728,7 +798,7 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; - + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); @@ -744,6 +814,10 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field LLSD element; @@ -755,14 +829,14 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; list->addElement(element); - mObjectListIDs.push_back(task_id); + mObjectListItems.push_back(element); total_objects++; } } @@ -868,7 +942,7 @@ void LLPanelScriptLimitsRegionURLs::clearList() childSetValue("urls_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -982,7 +1056,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) S32 size = 0; if(content["attachments"][i]["objects"][j]["resources"].has("memory")) { - size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger(); + size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; } S32 urls = 0; if(content["attachments"][i]["objects"][j]["resources"].has("urls")) @@ -1059,3 +1133,4 @@ void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata) return; } } + diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index 88239136e3..7e2b536eb6 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -54,12 +54,12 @@ public: // from LLPanel virtual void refresh(); - + private: - + LLFloaterScriptLimits(const LLSD& seed); ~LLFloaterScriptLimits(); - + protected: LLTabContainer* mTab; @@ -167,13 +167,17 @@ public: private: + void onNameCache( const LLUUID& id, + const std::string& first_name, + const std::string& last_name); + LLUUID mParcelId; BOOL mGotParcelMemoryUsed; BOOL mGotParcelMemoryMax; S32 mParcelMemoryMax; S32 mParcelMemoryUsed; - std::vector mObjectListIDs; + std::vector mObjectListItems; protected: @@ -218,7 +222,7 @@ private: S32 mParcelURLsMax; S32 mParcelURLsUsed; - std::vector mObjectListIDs; + std::vector mObjectListItems; protected: -- cgit v1.2.3 From 3d1843e92d825e00e3f7f8a2e56ceaeea75a8504 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 8 Jan 2010 14:35:23 -0800 Subject: fix for EXT-4094: Shared whiteboard script crashes viewer. --- indra/newview/llviewertexture.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index b1ad01f54f..95acf9fe22 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3007,7 +3007,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep) LLViewerTexture::addFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -3024,7 +3024,10 @@ void LLViewerMediaTexture::addFace(LLFace* facep) return ; } - llerrs << "The face does not have a valid texture before media texture." << llendl ; + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "The face does not have a valid texture before media texture." << llendl ; + } } //virtual @@ -3033,7 +3036,7 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) LLViewerTexture::removeFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -3094,7 +3097,10 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) } } - llerrs << "mTextureList texture reference number is corrupted." << llendl ; + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "mTextureList texture reference number is corrupted." << llendl ; + } } void LLViewerMediaTexture::stopPlaying() @@ -3130,11 +3136,15 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) const LLTextureEntry* te = facep->getTextureEntry() ; if(te) { - LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ; if(!tex && te->getID() != mID)//try parcel media. { tex = gTextureList.findImage(mID) ; } + if(!tex) + { + tex = LLViewerFetchedTexture::sDefaultImagep ; + } facep->switchTexture(tex) ; } } -- cgit v1.2.3 From e96d7af72a3a9e29459ededa1289f94425bbf4fa Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 8 Jan 2010 14:44:24 -0800 Subject: EXT-4099 Remove 'Reg in Client Test (restart)' item from Debug menu on Login Screen --- indra/newview/skins/default/xui/en/menu_login.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 690167bc33..a0dec346a4 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -223,6 +223,7 @@ parameter="test_inspectors" /> + Date: Fri, 8 Jan 2010 18:21:08 -0500 Subject: EXT-4038: Autopopulating My Outfits now happens correctly (creates links instead of folder copies). -Reviewed by Seraph --- indra/newview/llagentwearables.cpp | 227 +++++++++++++++++++++++++++++++++---- 1 file changed, 204 insertions(+), 23 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 29530c9c05..9842a3a8bb 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -95,19 +95,38 @@ public: enum ELibraryOutfitFetchStep { LOFS_FOLDER = 0, LOFS_OUTFITS, + LOFS_LIBRARY, + LOFS_IMPORTED, LOFS_CONTENTS }; - LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} + LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) + { + mMyOutfitsID = LLUUID::null; + mClothingID = LLUUID::null; + mLibraryClothingID = LLUUID::null; + mImportedClothingID = LLUUID::null; + mImportedClothingName = "Imported Library Clothing"; + } ~LLLibraryOutfitsFetch() {} - virtual void done(); + virtual void done(); void doneIdle(); + LLUUID mMyOutfitsID; + void importedFolderFetch(); protected: void folderDone(void); void outfitsDone(void); + void libraryDone(void); + void importedFolderDone(void); void contentsDone(void); enum ELibraryOutfitFetchStep mCurrFetchStep; - std::vector< std::pair< LLUUID, std::string > > mOutfits; + typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t; + cloth_folder_vec_t mLibraryClothingFolders; + cloth_folder_vec_t mImportedClothingFolders; bool mOutfitsPopulated; + LLUUID mClothingID; + LLUUID mLibraryClothingID; + LLUUID mImportedClothingID; + std::string mImportedClothingName; }; LLAgentWearables gAgentWearables; @@ -2126,11 +2145,15 @@ void LLAgentWearables::populateMyOutfitsFolder(void) // Get the complete information on the items in the inventory and // setup an observer that will wait for that to happen. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + outfits->mMyOutfitsID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - folders.push_back(my_outfits_id); + folders.push_back(outfits->mMyOutfitsID); gInventory.addObserver(outfits); outfits->fetchDescendents(folders); + if (outfits->isEverythingComplete()) + { + outfits->done(); + } } void LLLibraryOutfitsFetch::done() @@ -2144,13 +2167,24 @@ void LLLibraryOutfitsFetch::done() void LLLibraryOutfitsFetch::doneIdle() { gInventory.addObserver(this); // Add this back in since it was taken out during ::done() + switch (mCurrFetchStep) { case LOFS_FOLDER: folderDone(); + mCurrFetchStep = LOFS_OUTFITS; break; case LOFS_OUTFITS: outfitsDone(); + mCurrFetchStep = LOFS_LIBRARY; + break; + case LOFS_LIBRARY: + libraryDone(); + mCurrFetchStep = LOFS_IMPORTED; + break; + case LOFS_IMPORTED: + importedFolderDone(); + mCurrFetchStep = LOFS_CONTENTS; break; case LOFS_CONTENTS: contentsDone(); @@ -2172,67 +2206,214 @@ void LLLibraryOutfitsFetch::doneIdle() void LLLibraryOutfitsFetch::folderDone(void) { - // Early out if we already have items in My Outfits. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); + + // Early out if we already have items in My Outfits. if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; return; } - // Get the UUID of the library's clothing folder - const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); + mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); mCompleteFolders.clear(); // Get the complete information on the items in the inventory. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - folders.push_back(library_clothing_id); - mCurrFetchStep = LOFS_OUTFITS; + folders.push_back(mClothingID); + folders.push_back(mLibraryClothingID); fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } void LLLibraryOutfitsFetch::outfitsDone(void) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; + // Collect the contents of the Library's Clothing folder + gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + llassert(cat_array.count() > 0); for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); iter != cat_array.end(); ++iter) { const LLViewerInventoryCategory *cat = iter->get(); + + // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits. if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") { + // Get the name of every outfit in the library folders.push_back(cat->getUUID()); - mOutfits.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + } + } + + // Collect the contents of your Inventory Clothing folder + cat_array.clear(); + wearable_array.clear(); + gInventory.collectDescendents(mClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + // Check if you already have an "Imported Library Clothing" folder + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + if (cat->getName() == mImportedClothingName) + { + mImportedClothingID = cat->getUUID(); + } + } + + mCompleteFolders.clear(); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +class LLLibraryOutfitsCopyDone: public LLInventoryCallback +{ +public: + LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): + mFireCount(0), mLibraryOutftifsFetcher(fetcher) + { + } + + virtual ~LLLibraryOutfitsCopyDone() + { + if (mLibraryOutftifsFetcher) + { + mLibraryOutftifsFetcher->importedFolderFetch(); + } + } + + /* virtual */ void fire(const LLUUID& inv_item) + { + mFireCount++; + } +private: + U32 mFireCount; + LLLibraryOutfitsFetch * mLibraryOutftifsFetcher; +}; + +void LLLibraryOutfitsFetch::libraryDone(void) +{ + gInventory.removeObserver(this); + // Copy the clothing folders from the library into the imported clothing folder if necessary. + LLPointer copy_waiter = new LLLibraryOutfitsCopyDone(this); + + if (mImportedClothingID == LLUUID::null) + { + mImportedClothingID = gInventory.createNewCategory(mClothingID, + LLFolderType::FT_NONE, + mImportedClothingName); + + for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); + iter != mLibraryClothingFolders.end(); + ++iter) + { + LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID, + LLFolderType::FT_NONE, + iter->second); + LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter); } } +} + +void LLLibraryOutfitsFetch::importedFolderFetch(void) +{ + // Fetch the contents of the Imported Clothing Folder + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(mImportedClothingID); + mCompleteFolders.clear(); + + gInventory.addObserver(this); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} - mCurrFetchStep = LOFS_CONTENTS; +void LLLibraryOutfitsFetch::importedFolderDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + + // Collect the contents of the Imported Clothing folder + gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + + // Get the name of every imported outfit + folders.push_back(cat->getUUID()); + mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + } + + mCompleteFolders.clear(); fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } void LLLibraryOutfitsFetch::contentsDone(void) -{ - for(S32 i = 0; i < (S32)mOutfits.size(); ++i) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + + for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + folder_iter != mImportedClothingFolders.end(); + ++folder_iter) { // First, make a folder in the My Outfits directory. - const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLUUID folder_id = gInventory.createNewCategory(parent_id, - LLFolderType::FT_OUTFIT, - mOutfits[i].second); - LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second); + + cat_array.clear(); + wearable_array.clear(); + // Collect the contents of each imported clothing folder, so we can create new outfit links for it + gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); + wearable_iter != wearable_array.end(); + ++wearable_iter) + { + const LLViewerInventoryItem *item = wearable_iter->get(); + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + new_outfit_folder_id, + item->getName(), + LLAssetType::AT_LINK, + NULL); + } } + mOutfitsPopulated = true; } -- cgit v1.2.3 From 6aa46cc53f060c43781c95351df0e32ffdd0b75d Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 8 Jan 2010 15:57:33 -0800 Subject: EXT-4026 parcel media does not autoplay after arriving by teleport --- indra/newview/llviewerparcelmediaautoplay.cpp | 16 +++++++++++++++- indra/newview/llviewerparcelmediaautoplay.h | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp index 1b79b47905..ad2723b66b 100644 --- a/indra/newview/llviewerparcelmediaautoplay.cpp +++ b/indra/newview/llviewerparcelmediaautoplay.cpp @@ -35,6 +35,7 @@ #include "llviewerparcelmedia.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "llviewerregion.h" #include "llparcel.h" #include "llviewerparcelmgr.h" #include "lluuid.h" @@ -48,6 +49,8 @@ const F32 AUTOPLAY_SPEED = 0.1f; // how slow should the agent be moving t LLViewerParcelMediaAutoPlay::LLViewerParcelMediaAutoPlay() : LLEventTimer(1), + + mLastParcelID(-1), mPlayed(FALSE), mTimeInParcel(0) { @@ -81,9 +84,18 @@ void LLViewerParcelMediaAutoPlay::playStarted() BOOL LLViewerParcelMediaAutoPlay::tick() { LLParcel *this_parcel = NULL; + LLViewerRegion *this_region = NULL; std::string this_media_url; LLUUID this_media_texture_id; S32 this_parcel_id = 0; + LLUUID this_region_id; + + this_region = gAgent.getRegion(); + + if (this_region) + { + this_region_id = this_region->getRegionID(); + } this_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -96,12 +108,14 @@ BOOL LLViewerParcelMediaAutoPlay::tick() this_parcel_id = this_parcel->getLocalID(); } - if (this_parcel_id != mLastParcelID) + if (this_parcel_id != mLastParcelID || + this_region_id != mLastRegionID) { // we've entered a new parcel mPlayed = FALSE; // we haven't autoplayed yet mTimeInParcel = 0; // reset our timer mLastParcelID = this_parcel_id; + mLastRegionID = this_region_id; } mTimeInParcel += mPeriod; // increase mTimeInParcel by the amount of time between ticks diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index 16279e7f1f..1d80b4756c 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -34,6 +34,7 @@ #define LLVIEWERPARCELMEDIAAUTOPLAY_H #include "lltimer.h" +#include "lluuid.h" // timer to automatically play media class LLViewerParcelMediaAutoPlay : LLEventTimer @@ -47,6 +48,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer private: S32 mLastParcelID; + LLUUID mLastRegionID; BOOL mPlayed; F32 mTimeInParcel; }; -- cgit v1.2.3 From 6d27a9e28d0711c78066f3f4977cd92069090357 Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Fri, 8 Jan 2010 19:28:23 -0500 Subject: EXT-4038: Typo fix & proper handling of autopopulation if library clothing already imported -Reviewed by vir --- indra/newview/llagentwearables.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 63e12bd468..10a2dd132a 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2291,15 +2291,16 @@ class LLLibraryOutfitsCopyDone: public LLInventoryCallback { public: LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): - mFireCount(0), mLibraryOutftifsFetcher(fetcher) + mFireCount(0), mLibraryOutfitsFetcher(fetcher) { } virtual ~LLLibraryOutfitsCopyDone() { - if (mLibraryOutftifsFetcher) + if (mLibraryOutfitsFetcher) { - mLibraryOutftifsFetcher->importedFolderFetch(); + gInventory.addObserver(mLibraryOutfitsFetcher); + mLibraryOutfitsFetcher->done(); } } @@ -2309,17 +2310,16 @@ public: } private: U32 mFireCount; - LLLibraryOutfitsFetch * mLibraryOutftifsFetcher; + LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; }; void LLLibraryOutfitsFetch::libraryDone(void) { - gInventory.removeObserver(this); // Copy the clothing folders from the library into the imported clothing folder if necessary. - LLPointer copy_waiter = new LLLibraryOutfitsCopyDone(this); - if (mImportedClothingID == LLUUID::null) { + gInventory.removeObserver(this); + LLPointer copy_waiter = new LLLibraryOutfitsCopyDone(this); mImportedClothingID = gInventory.createNewCategory(mClothingID, LLFolderType::FT_NONE, mImportedClothingName); @@ -2334,6 +2334,11 @@ void LLLibraryOutfitsFetch::libraryDone(void) LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter); } } + else + { + // Skip straight to fetching the contents of the imported folder + importedFolderFetch(); + } } void LLLibraryOutfitsFetch::importedFolderFetch(void) @@ -2344,8 +2349,6 @@ void LLLibraryOutfitsFetch::importedFolderFetch(void) mCompleteFolders.clear(); - gInventory.addObserver(this); - fetchDescendents(folders); if (isEverythingComplete()) { -- cgit v1.2.3 From 0d09530d85772ee8072245da9259b73879c04530 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 8 Jan 2010 16:33:03 -0800 Subject: EXT-1847 Regression in the design spec: "You" should be replaced by your full avatar name in communication --- indra/newview/llchathistory.cpp | 4 ++-- indra/newview/llchatitemscontainerctrl.cpp | 5 +---- indra/newview/llimfloater.cpp | 2 +- indra/newview/lllogchat.cpp | 3 --- indra/newview/llnearbychat.cpp | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index dac3280575..cda3e3a419 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -576,10 +576,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ style_params.font.style = "ITALIC"; if (chat.mFromName.size() > 0) - mEditor->appendText(chat.mFromName + " ", TRUE, style_params); + mEditor->appendText(chat.mFromName, TRUE, style_params); // Ensure that message ends with NewLine, to avoid losing of new lines // while copy/paste from text chat. See EXT-3263. - mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); + mEditor->appendText(chat.mText.substr(3) + NEW_LINE, FALSE, style_params); } else { diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 60a37ac4af..9ce3f29853 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -170,10 +170,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification) std::string str_sender; - if(gAgentID != mFromID) - str_sender = fromName; - else - str_sender = LLTrans::getString("You"); + str_sender = fromName; str_sender+=" "; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index fdc5d14d97..b05568f353 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -595,7 +595,7 @@ void LLIMFloater::updateMessages() std::string time = msg["time"].asString(); LLUUID from_id = msg["from_id"].asUUID(); - std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You"); + std::string from = msg["from"].asString(); std::string message = msg["message"].asString(); LLChat chat; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index fc9654e9ad..92f19c9232 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -59,9 +59,6 @@ const static std::string NEW_LINE_SPACE_PREFIX("\n "); const static std::string TWO_SPACES(" "); const static std::string MULTI_LINE_PREFIX(" "); -//viewer 1.23 may have used "You" for Agent's entries -const static std::string YOU("You"); - /** * Chat log lines - timestamp and name are optional but message text is mandatory. * diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e7043b2d00..fc0e51b76d 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -178,7 +178,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive) if (!chat.mMuted) { - tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You"); + tmp_chat.mFromName = chat.mFromName; if (chat.mChatStyle == CHAT_STYLE_IRC) { -- cgit v1.2.3 From b88563b23bed940f44f863814ad12dac13f823da Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Fri, 8 Jan 2010 17:33:44 -0800 Subject: Made AudioStreamingMedia setting control loading of prim media as well as parcel media. Moved the media first-run dialog code from llviewerparcelmedia.cpp to llviewermedia.cpp, and made it come up for both prim and parcel media. --- indra/newview/llviewermedia.cpp | 73 +++++++++++++++++++++++++++++++++++ indra/newview/llviewermedia.h | 6 +++ indra/newview/llviewerparcelmedia.cpp | 40 +------------------ 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7e8c8eb92e..f91d126073 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,6 +54,7 @@ #include "lluuid.h" #include "llkeyboard.h" #include "llmutelist.h" +#include "llfirstuse.h" #include // for SkinFolder listener #include @@ -708,6 +709,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) std::vector proximity_order; + bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); + bool needs_first_run = LLViewerMedia::needsMediaFirstRun(); U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); @@ -822,6 +825,21 @@ void LLViewerMedia::updateMedia(void *dummy_arg) new_priority = LLPluginClassMedia::PRIORITY_LOW; } + if(!inworld_media_enabled) + { + // If inworld media is locked out, force all inworld media to stay unloaded. + if(!pimpl->getUsedInUI()) + { + new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; + if(needs_first_run) + { + // Don't do this more than once in this loop. + needs_first_run = false; + LLViewerMedia::displayMediaFirstRun(); + } + } + } + pimpl->setPriority(new_priority); if(pimpl->getUsedInUI()) @@ -888,6 +906,61 @@ void LLViewerMedia::cleanupClass() gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); } + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerParcelMedia::needsMediaFirstRun() +{ + return gWarningSettings.getBOOL("FirstStreamingMedia"); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerParcelMedia::displayMediaFirstRun() +{ + gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); + + LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), + boost::bind(firstRunCallback, _1, _2)); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerParcelMedia::firstRunCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // user has elected to automatically play media. + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); + gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); + gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); + gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); + + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if (parcel) + { + // play media right now, if available + LLViewerParcelMedia::play(parcel); + + // play music right now, if available + std::string music_url = parcel->getMusicURL(); + if (gAudiop && !music_url.empty()) + gAudiop->startInternetStream(music_url); + } + } + else + { + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE); + gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); + gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); + gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); + } + return false; +} + + ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index b103c48bd8..3ce9f1887c 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -115,6 +115,12 @@ class LLViewerMedia // This is the comparitor used to sort the list. static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2); + + // For displaying the media first-run dialog. + static bool needsMediaFirstRun(); + static void displayMediaFirstRun(); + static bool firstRunCallback(const LLSD& notification, const LLSD& response); + }; // Implementation functions not exported into header file diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 0f7903a7a5..56dee6b34c 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -56,10 +56,6 @@ LLUUID LLViewerParcelMedia::sMediaRegionID; viewer_media_t LLViewerParcelMedia::sMediaImpl; -// Local functions -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); - - // static void LLViewerParcelMedia::initClass() { @@ -112,12 +108,10 @@ void LLViewerParcelMedia::update(LLParcel* parcel) // First use warning if( (!mediaUrl.empty() || !parcel->getMusicURL().empty()) - && gWarningSettings.getBOOL("FirstStreamingMedia") ) + && LLViewerMedia::needsMediaFirstRun()) { - LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(callback_play_media, _1, _2, parcel)); + LLViewerMedia::displayMediaFirstRun(); return; - } // if we have a current (link sharing) url, use it instead @@ -591,36 +585,6 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; } -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - // user has elected to automatically play media. - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); - gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); - gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); - if(!gSavedSettings.getBOOL("AudioStreamingMedia")) - gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); - // play media right now, if available - LLViewerParcelMedia::play(parcel); - // play music right now, if available - if (parcel) - { - std::string music_url = parcel->getMusicURL(); - if (gAudiop && !music_url.empty()) - gAudiop->startInternetStream(music_url); - } - } - else - { - gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); - gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); - } - gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); - return false; -} - // TODO: observer /* void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in ) -- cgit v1.2.3 From 47dd146c43064a3637641d26db36ea58d26d8a43 Mon Sep 17 00:00:00 2001 From: Kent Quirk Date: Sun, 10 Jan 2010 15:28:09 -0500 Subject: Reverting change that broke the build so we can get a working build for QA --- indra/newview/llviewermedia.cpp | 73 ----------------------------------- indra/newview/llviewermedia.h | 6 --- indra/newview/llviewerparcelmedia.cpp | 40 ++++++++++++++++++- 3 files changed, 38 insertions(+), 81 deletions(-) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index f91d126073..7e8c8eb92e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,7 +54,6 @@ #include "lluuid.h" #include "llkeyboard.h" #include "llmutelist.h" -#include "llfirstuse.h" #include // for SkinFolder listener #include @@ -709,8 +708,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) std::vector proximity_order; - bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); - bool needs_first_run = LLViewerMedia::needsMediaFirstRun(); U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); @@ -825,21 +822,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) new_priority = LLPluginClassMedia::PRIORITY_LOW; } - if(!inworld_media_enabled) - { - // If inworld media is locked out, force all inworld media to stay unloaded. - if(!pimpl->getUsedInUI()) - { - new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; - if(needs_first_run) - { - // Don't do this more than once in this loop. - needs_first_run = false; - LLViewerMedia::displayMediaFirstRun(); - } - } - } - pimpl->setPriority(new_priority); if(pimpl->getUsedInUI()) @@ -906,61 +888,6 @@ void LLViewerMedia::cleanupClass() gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); } - -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerParcelMedia::needsMediaFirstRun() -{ - return gWarningSettings.getBOOL("FirstStreamingMedia"); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerParcelMedia::displayMediaFirstRun() -{ - gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); - - LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(firstRunCallback, _1, _2)); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerParcelMedia::firstRunCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - // user has elected to automatically play media. - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); - gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); - gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); - gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); - - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - - if (parcel) - { - // play media right now, if available - LLViewerParcelMedia::play(parcel); - - // play music right now, if available - std::string music_url = parcel->getMusicURL(); - if (gAudiop && !music_url.empty()) - gAudiop->startInternetStream(music_url); - } - } - else - { - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE); - gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); - gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); - gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); - } - return false; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 3ce9f1887c..b103c48bd8 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -115,12 +115,6 @@ class LLViewerMedia // This is the comparitor used to sort the list. static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2); - - // For displaying the media first-run dialog. - static bool needsMediaFirstRun(); - static void displayMediaFirstRun(); - static bool firstRunCallback(const LLSD& notification, const LLSD& response); - }; // Implementation functions not exported into header file diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 56dee6b34c..0f7903a7a5 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -56,6 +56,10 @@ LLUUID LLViewerParcelMedia::sMediaRegionID; viewer_media_t LLViewerParcelMedia::sMediaImpl; +// Local functions +bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); + + // static void LLViewerParcelMedia::initClass() { @@ -108,10 +112,12 @@ void LLViewerParcelMedia::update(LLParcel* parcel) // First use warning if( (!mediaUrl.empty() || !parcel->getMusicURL().empty()) - && LLViewerMedia::needsMediaFirstRun()) + && gWarningSettings.getBOOL("FirstStreamingMedia") ) { - LLViewerMedia::displayMediaFirstRun(); + LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), + boost::bind(callback_play_media, _1, _2, parcel)); return; + } // if we have a current (link sharing) url, use it instead @@ -585,6 +591,36 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; } +bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // user has elected to automatically play media. + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); + gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); + gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); + if(!gSavedSettings.getBOOL("AudioStreamingMedia")) + gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); + // play media right now, if available + LLViewerParcelMedia::play(parcel); + // play music right now, if available + if (parcel) + { + std::string music_url = parcel->getMusicURL(); + if (gAudiop && !music_url.empty()) + gAudiop->startInternetStream(music_url); + } + } + else + { + gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); + gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); + } + gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); + return false; +} + // TODO: observer /* void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in ) -- cgit v1.2.3 From 779bbe76d8829bb37d8e59f887ccfafafbfe4b3d Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 09:13:59 +0000 Subject: EXT-3911 EXT-3846: Added help ID for Blocked Residents & Objects. --- indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 970a2e6a8a..003e1baa7e 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -5,6 +5,7 @@ height="305" layout="topleft" name="block_list_panel" + help_topic="blocked_list" min_height="350" min_width="240" width="280"> -- cgit v1.2.3 From 6f978d732b56948b1da4b29b043287b68cecc72f Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 09:20:39 +0000 Subject: EXT-3902: Make all Choose Resident tabs use the same help ID. --- indra/newview/skins/default/xui/en/floater_avatar_picker.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index 953bd08dd4..f59badfcb4 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -47,7 +47,7 @@ label="Search" layout="topleft" left="6" - help_topic="avatarpicker_search_tab" + help_topic="avatarpicker" name="SearchPanel" top="150" width="132"> @@ -98,7 +98,7 @@ label="Friends" layout="topleft" left="6" - help_topic="avatarpicker_friends_tab" + help_topic="avatarpicker" name="FriendsPanel" top="150" width="132"> @@ -144,7 +144,7 @@ label="Near Me" layout="topleft" left="6" - help_topic="avatarpicker_near_me_tab" + help_topic="avatarpicker" name="NearMePanel" top="150" width="132"> -- cgit v1.2.3 From df08485cf840e21e2ec8d14664a45714e0a3ca96 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 09:32:21 +0000 Subject: EXT-3715: Added a help button to the speaker controls floater. --- indra/newview/skins/default/xui/en/floater_voice_controls.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index a4ef807f06..b9649e9c57 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -8,6 +8,7 @@ min_height="122" min_width="190" name="floater_voice_controls" + help_topic="floater_voice_controls" title="Voice Controls" save_visibility="true" single_instance="true" -- cgit v1.2.3 From a4baeed12f241f29c3f2e856b386eecf4ab46db6 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 10:05:37 +0000 Subject: EXT-3929: Moved LLAccordionCtrl to llui. Both LLAccordionCtrl and LLAccordionCtrlTab should live in llui, not newview. I need to make this happen in order to fix EXT-3929. No code change was necessary (other than to change #include for predefined headers) as these classes did not rely on any newview code. --- indra/llui/CMakeLists.txt | 4 + indra/llui/llaccordionctrl.cpp | 578 ++++++++++++++++++++++++++++++++++++ indra/llui/llaccordionctrl.h | 123 ++++++++ indra/llui/llaccordionctrltab.cpp | 599 ++++++++++++++++++++++++++++++++++++++ indra/llui/llaccordionctrltab.h | 191 ++++++++++++ indra/newview/CMakeLists.txt | 4 - 6 files changed, 1495 insertions(+), 4 deletions(-) create mode 100644 indra/llui/llaccordionctrl.cpp create mode 100644 indra/llui/llaccordionctrl.h create mode 100644 indra/llui/llaccordionctrltab.cpp create mode 100644 indra/llui/llaccordionctrltab.h diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 82ec02d2eb..ce068618e2 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -26,6 +26,8 @@ include_directories( ) set(llui_SOURCE_FILES + llaccordionctrl.cpp + llaccordionctrltab.cpp llbutton.cpp llcheckboxctrl.cpp llclipboard.cpp @@ -111,6 +113,8 @@ set(llui_SOURCE_FILES set(llui_HEADER_FILES CMakeLists.txt + llaccordionctrl.h + llaccordionctrltab.h llbutton.h llcallbackmap.h llcheckboxctrl.h diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp new file mode 100644 index 0000000000..b5e870228a --- /dev/null +++ b/indra/llui/llaccordionctrl.cpp @@ -0,0 +1,578 @@ +/** + * @file llaccordionctrl.cpp + * @brief Accordion panel implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" + +#include "lluictrlfactory.h" // builds floaters from XML + +#include "llwindow.h" +#include "llfocusmgr.h" +#include "lllocalcliprect.h" + +#include "boost/bind.hpp" + +static const S32 DRAGGER_BAR_MARGIN = 4; +static const S32 DRAGGER_BAR_HEIGHT = 5; +static const S32 BORDER_MARGIN = 2; +static const S32 PARENT_BORDER_MARGIN = 5; + +static const S32 panel_delta = DRAGGER_BAR_MARGIN; // Distanse between two panels + +static const S32 HORIZONTAL_MULTIPLE = 8; +static const S32 VERTICAL_MULTIPLE = 16; +static const F32 MIN_AUTO_SCROLL_RATE = 120.f; +static const F32 MAX_AUTO_SCROLL_RATE = 500.f; +static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; + + +// LLAccordionCtrl =================================================================| + +static LLDefaultChildRegistry::Register t2("accordion"); + + +LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) + , mFitParent(params.fit_parent) +{ + mSingleExpansion = params.single_expansion; + if(mFitParent && !mSingleExpansion) + { + llinfos << "fit_parent works best when combined with single_expansion" << llendl; + } +} + +LLAccordionCtrl::LLAccordionCtrl() : LLPanel() +{ + mSingleExpansion = false; + mFitParent = false; + LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml"); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::draw() +{ + LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + + LLLocalClipRect clip(local_rect); + + LLPanel::draw(); +} + + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::postBuild() +{ + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + LLRect scroll_rect; + scroll_rect.setOriginAndSize( + getRect().getWidth() - scrollbar_size, + 1, + scrollbar_size, + getRect().getHeight() - 1); + + + LLScrollbar::Params sbparams; + sbparams.name("scrollable vertical"); + sbparams.rect(scroll_rect); + sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(mInnerRect.getHeight()); + sbparams.doc_pos(0); + sbparams.page_size(mInnerRect.getHeight()); + sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2)); + + mScrollbar = LLUICtrlFactory::create (sbparams); + LLView::addChild( mScrollbar ); + mScrollbar->setVisible( false ); + mScrollbar->setFollowsRight(); + mScrollbar->setFollowsTop(); + mScrollbar->setFollowsBottom(); + + //if it was created from xml... + std::vector accordion_tabs; + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*it); + if(accordion_tab == NULL) + continue; + if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end()) + { + accordion_tabs.push_back(accordion_tab); + } + } + + for(std::vector::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it) + addCollapsibleCtrl(*it); + + arrange (); + + if(mSingleExpansion) + { + if(!mAccordionTabs[0]->getDisplayChildren()) + mAccordionTabs[0]->setDisplayChildren(true); + for(size_t i=1;igetDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + } + + return TRUE; +} + + +//--------------------------------------------------------------------------------- +LLAccordionCtrl::~LLAccordionCtrl() +{ + mAccordionTabs.clear(); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + // adjust our rectangle + LLRect rcLocal = getRect(); + rcLocal.mRight = rcLocal.mLeft + width; + rcLocal.mTop = rcLocal.mBottom + height; + + setRect(rcLocal); + + arrange(); +} + +//--------------------------------------------------------------------------------- +BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return LLPanel::handleRightMouseDown(x, y, mask); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta) +{ + for(size_t i = panel_num; i < mAccordionTabs.size(); i++ ) + { + ctrlShiftVertical(mAccordionTabs[i],delta); + } +} + + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) +{ + if(mSingleExpansion) + { + for(size_t i=0;igetDisplayChildren()) + mAccordionTabs[i]->setDisplayChildren(false); + } + + } + arrange(); +} + +void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height) +{ + calcRecuiredHeight(); + if(getRecuiredHeight() > height ) + showScrollbar(width,height); + else + hideScrollbar(width,height); +} + +void LLAccordionCtrl::showScrollbar(S32 width, S32 height) +{ + bool was_visible = mScrollbar->getVisible(); + + mScrollbar->setVisible(true); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + ctrlSetLeftTopAndSize(mScrollbar + ,width-scrollbar_size - PARENT_BORDER_MARGIN/2 + ,height-PARENT_BORDER_MARGIN + ,scrollbar_size + ,height-2*PARENT_BORDER_MARGIN); + + mScrollbar->setPageSize(height); + mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos()); + + if(was_visible) + { + S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); + mScrollbar->setDocPos(scroll_pos); + } +} + +void LLAccordionCtrl::hideScrollbar( S32 width, S32 height ) +{ + if(mScrollbar->getVisible() == false) + return; + mScrollbar->setVisible(false); + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + S32 panel_width = width - 2*BORDER_MARGIN; + + //reshape all accordeons and shift all draggers + for(size_t i=0;igetRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight()); + } + + mScrollbar->setDocPos(0); + + if(mAccordionTabs.size()>0) + { + S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel + S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop; + shiftAccordionTabs(0,diff); + } +} + + +//--------------------------------------------------------------------------------- +S32 LLAccordionCtrl::calcRecuiredHeight() +{ + S32 rec_height = 0; + + std::vector::iterator panel; + for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(*panel); + if(accordion_tab && accordion_tab->getVisible()) + { + rec_height += accordion_tab->getRect().getHeight(); + } + } + + mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); + + return mInnerRect.getHeight(); +} + +//--------------------------------------------------------------------------------- +void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) +{ + if(!panel) + return; + LLRect panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize( left, top, width, height); + panel->reshape( width, height, 1); + panel->setRect(panel_rect); +} + +void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta) +{ + if(!panel) + return; + panel->translate(0,delta); +} + +//--------------------------------------------------------------------------------- + +void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) +{ + LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); + if(!accordion_tab) + return; + if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end()) + addChild(accordion_tab); + mAccordionTabs.push_back(accordion_tab); + + accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) ); + +} + + +void LLAccordionCtrl::arrange() +{ + if( mAccordionTabs.size() == 0) + { + //We do not arrange if we do not have what should be arranged + return; + } + + //Calculate params + S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter + S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel + S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel + + + if(mAccordionTabs.size() == 1) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[0]); + + LLRect panel_rect = accordion_tab->getRect(); + + S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN; + + ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height); + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + return; + + } + + for(size_t i = 0; i < mAccordionTabs.size(); i++ ) + { + LLAccordionCtrlTab* accordion_tab = dynamic_cast(mAccordionTabs[i]); + + if(accordion_tab->getVisible() == false) //skip hidden accordion tabs + continue; + + if(!accordion_tab->isExpanded() ) + { + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight()); + panel_top-=mAccordionTabs[i]->getRect().getHeight(); + } + else + { + S32 panel_height = accordion_tab->getRect().getHeight(); + + if(mFitParent) + { + // all expanded tabs will have equal height + panel_height = calcExpandedTabHeight(i, panel_top); + ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height); + + // try to make accordion tab fit accordion view height. + // Accordion View should implement getRequiredRect() and provide valid height + S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight(); + optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN; + if(optimal_height < panel_height) + { + panel_height = optimal_height; + } + + // minimum tab height is equal to header height + if(mAccordionTabs[i]->getHeaderHeight() > panel_height) + { + panel_height = mAccordionTabs[i]->getHeaderHeight(); + } + } + + ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height); + panel_top-=panel_height; + + } + } + + show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); + + updateLayout(getRect().getWidth(),getRect().getHeight()); + +} + +//--------------------------------------------------------------------------------- + +BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +{ + if(LLPanel::handleScrollWheel(x,y,clicks)) + return TRUE; + if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + return TRUE; + return false; + +} + +BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask) +{ + if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) + return TRUE; + return LLPanel::handleKeyHere(key,mask); +} + +void LLAccordionCtrl::updateLayout (S32 width, S32 height) +{ + S32 panel_top = height - BORDER_MARGIN ; + if(mScrollbar->getVisible()) + panel_top+=mScrollbar->getDocPos(); + + S32 panel_width = width - 2*BORDER_MARGIN; + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + if(mScrollbar->getVisible()) + panel_width-=scrollbar_size; + + //set sizes for first panels and dragbars + for(size_t i=0;igetVisible()) + continue; + LLRect panel_rect = mAccordionTabs[i]->getRect(); + ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); + panel_top-=panel_rect.getHeight(); + } +} + +void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) +{ + updateLayout(getRect().getWidth(),getRect().getHeight()); +} +void LLAccordionCtrl::onOpen (const LLSD& key) +{ + for(size_t i=0;i(mAccordionTabs[i]); + LLPanel* panel = dynamic_cast(accordion_tab->getAccordionView()); + if(panel!=NULL) + { + panel->onOpen(key); + } + } +} +S32 LLAccordionCtrl::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + arrange(); + return 1; + } + else if(str_action == "select_next") + { + for(size_t i=0;i(mAccordionTabs[i]); + if(accordion_tab->hasFocus()) + { + while(++igetVisible()) + break; + } + if(i(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_first")); + return 1; + } + break; + } + } + return 0; + } + else if(str_action == "select_prev") + { + for(size_t i=0;i(mAccordionTabs[i]); + if(accordion_tab->hasFocus() && i>0) + { + while(i>0) + { + if(mAccordionTabs[--i]->getVisible()) + break; + } + + accordion_tab = dynamic_cast(mAccordionTabs[i]); + accordion_tab->notify(LLSD().with("action","select_last")); + return 1; + } + } + return 0; + } + } + else if (info.has("scrollToShowRect")) + { + LLRect screen_rc, local_rc; + screen_rc.setValue(info["scrollToShowRect"]); + screenRectToLocal(screen_rc, &local_rc); + + // Translate to parent coordinatess to check if we are in visible rectangle + local_rc.translate( getRect().mLeft, getRect().mBottom ); + + if ( !getRect().contains (local_rc) ) + { + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos( scroll_pos ); + } + return 1; + } + return LLPanel::notifyParent(info); +} +void LLAccordionCtrl::reset () +{ + if(mScrollbar) + mScrollbar->setDocPos(0); +} + +S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) +{ + if(tab_index < 0) + { + return available_height; + } + + S32 collapsed_tabs_height = 0; + S32 num_expanded = 0; + + for(size_t n = tab_index; n < mAccordionTabs.size(); ++n) + { + if(!mAccordionTabs[n]->isExpanded()) + { + collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight(); + } + else + { + ++num_expanded; + } + } + + if(0 == num_expanded) + { + return available_height; + } + + S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN + expanded_tab_height /= num_expanded; + return expanded_tab_height; +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h new file mode 100644 index 0000000000..4cb0f38281 --- /dev/null +++ b/indra/llui/llaccordionctrl.h @@ -0,0 +1,123 @@ +/** + * @file LLAccordionCtrl.h + * @brief Accordion Panel implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_ACCORDIONCTRL_H +#define LL_ACCORDIONCTRL_H + +#include "llpanel.h" +#include "llscrollbar.h" + +#include +#include +#include + +class LLAccordionCtrlTab; + +class LLAccordionCtrl: public LLPanel +{ +private: + + std::vector mAccordionTabs; + + void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height); + void ctrlShiftVertical(LLView* panel,S32 delta); + + void onCollapseCtrlCloseOpen(S16 panel_num); + void shiftAccordionTabs(S16 panel_num, S32 delta); + + +public: + struct Params + : public LLInitParam::Block + { + Optional single_expansion, + fit_parent; /* Accordion will fit its parent size, controls that are placed into + accordion tabs are responsible for scrolling their content. + *NOTE fit_parent works best when combined with single_expansion. + Accordion view should implement getRequiredRect() and provide valid height*/ + + Params() + : single_expansion("single_expansion",false) + , fit_parent("fit_parent", false) + {}; + }; + + LLAccordionCtrl(const Params& params); + + LLAccordionCtrl(); + virtual ~LLAccordionCtrl(); + + virtual BOOL postBuild(); + + virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks ); + virtual BOOL handleKeyHere (KEY key, MASK mask); + // + + // Call reshape after changing splitter's size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + void addCollapsibleCtrl(LLView* view); + void arrange(); + + + void draw(); + + void onScrollPosChangeCallback(S32, LLScrollbar*); + + void onOpen (const LLSD& key); + S32 notifyParent(const LLSD& info); + + void reset (); + +private: + // Calc Splitter's height that is necessary to display all child content + S32 calcRecuiredHeight(); + S32 getRecuiredHeight() const { return mInnerRect.getHeight(); } + S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0); + + void updateLayout (S32 width, S32 height); + + void show_hide_scrollbar (S32 width, S32 height); + + void showScrollbar (S32 width, S32 height); + void hideScrollbar (S32 width, S32 height); + +private: + LLRect mInnerRect; + LLScrollbar* mScrollbar; + bool mSingleExpansion; + bool mFitParent; +}; + + +#endif // LL_LLSPLITTER_H diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp new file mode 100644 index 0000000000..9d6ba57c29 --- /dev/null +++ b/indra/llui/llaccordionctrltab.cpp @@ -0,0 +1,599 @@ +/** + * @file LLAccordionCtrlTab.cpp + * @brief Collapsible control implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lluictrl.h" + +#include "llaccordionctrltab.h" + +#include "lltextbox.h" + +static const std::string DD_BUTTON_NAME = "dd_button"; +static const std::string DD_TEXTBOX_NAME = "dd_textbox"; +static const std::string DD_HEADER_NAME = "dd_header"; + +static const S32 HEADER_HEIGHT = 20; +static const S32 HEADER_IMAGE_LEFT_OFFSET = 5; +static const S32 HEADER_TEXT_LEFT_OFFSET = 30; + +static LLDefaultChildRegistry::Register t1("accordion_tab"); + +class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl +{ +public: + friend class LLUICtrlFactory; + + struct Params : public LLInitParam::Block + { + Params(); + }; + + LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p); + + virtual ~LLAccordionCtrlTabHeader(); + + virtual void draw(); + + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + virtual BOOL postBuild(); + + void setTitle(const std::string& title); + + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); +private: + + LLTextBox* mHeaderTextbox; + + // Overlay images (arrows) + LLPointer mImageCollapsed; + LLPointer mImageExpanded; + LLPointer mImageCollapsedPressed; + LLPointer mImageExpandedPressed; + + // Background images + LLPointer mImageHeader; + LLPointer mImageHeaderOver; + LLPointer mImageHeaderPressed; + LLPointer mImageHeaderFocused; + + LLUIColor mHeaderBGColor; + + bool mNeedsHighlight; +}; + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() +{ +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader( + const LLAccordionCtrlTabHeader::Params& p) +: LLUICtrl(p) +, mHeaderBGColor(p.header_bg_color()) +,mNeedsHighlight(false), + mImageCollapsed(p.header_collapse_img), + mImageCollapsedPressed(p.header_collapse_img_pressed), + mImageExpanded(p.header_expand_img), + mImageExpandedPressed(p.header_expand_img_pressed), + mImageHeader(p.header_image), + mImageHeaderOver(p.header_image_over), + mImageHeaderPressed(p.header_image_pressed), + mImageHeaderFocused(p.header_image_focused) +{ + LLTextBox::Params textboxParams; + textboxParams.name(DD_TEXTBOX_NAME); + textboxParams.initial_value(p.title()); + textboxParams.text_color(p.header_text_color()); + textboxParams.follows.flags(FOLLOWS_NONE); + textboxParams.font( p.font() ); + textboxParams.font_shadow(LLFontGL::NO_SHADOW); + textboxParams.use_ellipses = true; + textboxParams.bg_visible = false; + textboxParams.mouse_opaque = false; + mHeaderTextbox = LLUICtrlFactory::create(textboxParams); + addChild(mHeaderTextbox); +} + +LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader() +{ +} + +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() +{ + return TRUE; +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title) +{ + if(mHeaderTextbox) + mHeaderTextbox->setText(title); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() +{ + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + + gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true); + + LLAccordionCtrlTab* parent = dynamic_cast(getParent()); + bool collapsible = (parent && parent->getCollapsible()); + bool expanded = (parent && parent->getDisplayChildren()); + + // Handle overlay images, if needed + // Only show green "focus" background image if the accordion is open, + // because the user's mental model of focus is that it goes away after + // the accordion is closed. + if (getParent()->hasFocus() + && !(collapsible && !expanded)) + { + mImageHeaderFocused->draw(0,0,width,height); + } + else + { + mImageHeader->draw(0,0,width,height); + } + + if(mNeedsHighlight) + { + mImageHeaderOver->draw(0,0,width,height); + } + + + if(collapsible) + { + LLPointer overlay_image; + if(expanded) + { + overlay_image = mImageExpanded; + } + else + { + overlay_image = mImageCollapsed; + } + overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, + (height - overlay_image->getHeight()) / 2); + } + + LLUICtrl::draw(); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + S32 header_height = mHeaderTextbox->getTextPixelHeight(); + + LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2); + mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); + mHeaderTextbox->setRect(textboxRect); +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseEnter(x, y, mask); + mNeedsHighlight = true; +} +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseLeave(x, y, mask); + mNeedsHighlight = false; +} +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE) + { + return getParent()->handleKey(key, mask, called_from_parent); + } + return LLUICtrl::handleKey(key, mask, called_from_parent); +} + + +LLAccordionCtrlTab::Params::Params() + : title("title") + ,display_children("expanded", true) + ,header_height("header_height", HEADER_HEIGHT), + min_width("min_width", 0), + min_height("min_height", 0) + ,collapsible("collapsible", true) + ,header_bg_color("header_bg_color") + ,dropdown_bg_color("dropdown_bg_color") + ,header_visible("header_visible",true) + ,padding_left("padding_left",2) + ,padding_right("padding_right",2) + ,padding_top("padding_top",2) + ,padding_bottom("padding_bottom",2) + ,header_expand_img("header_expand_img") + ,header_expand_img_pressed("header_expand_img_pressed") + ,header_collapse_img("header_collapse_img") + ,header_collapse_img_pressed("header_collapse_img_pressed") + ,header_image("header_image") + ,header_image_over("header_image_over") + ,header_image_pressed("header_image_pressed") + ,header_image_focused("header_image_focused") + ,header_text_color("header_text_color") +{ + mouse_opaque(false); +} + +LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) + : LLUICtrl(p) + ,mDisplayChildren(p.display_children) + ,mCollapsible(p.collapsible) + ,mExpandedHeight(0) + ,mDropdownBGColor(p.dropdown_bg_color()) + ,mHeaderVisible(p.header_visible) + ,mPaddingLeft(p.padding_left) + ,mPaddingRight(p.padding_right) + ,mPaddingTop(p.padding_top) + ,mPaddingBottom(p.padding_bottom) + ,mCanOpenClose(true) +{ + mStoredOpenCloseState = false; + mWasStateStored = false; + + mDropdownBGColor = LLColor4::white; + LLAccordionCtrlTabHeader::Params headerParams; + headerParams.name(DD_HEADER_NAME); + headerParams.title(p.title); + mHeader = LLUICtrlFactory::create(headerParams); + addChild(mHeader, 1); + + reshape(100, 200,FALSE); +} + +LLAccordionCtrlTab::~LLAccordionCtrlTab() +{ +} + + +void LLAccordionCtrlTab::setDisplayChildren(bool display) +{ + mDisplayChildren = display; + LLRect rect = getRect(); + + rect.mBottom = rect.mTop - (getDisplayChildren() ? + mExpandedHeight : HEADER_HEIGHT); + setRect(rect); + + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + + child->setVisible(getDisplayChildren()); + } +} + +void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + LLRect headerRect; + + LLUICtrl::reshape(width, height, TRUE); + + headerRect.setLeftTopAndSize( + 0,height,width,HEADER_HEIGHT); + mHeader->setRect(headerRect); + mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + if(!child->getVisible()) + continue; + + LLRect childRect = child->getRect(); + S32 childWidth = width - getPaddingLeft() - getPaddingRight(); + S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom(); + + child->reshape(childWidth,childHeight); + + childRect.setLeftTopAndSize( + getPaddingLeft(), + childHeight + getPaddingBottom(), + childWidth, + childHeight); + + child->setRect(childRect); + + break;//suppose that there is only one panel + } + +} + +void LLAccordionCtrlTab::changeOpenClose(bool is_open) +{ + if(is_open) + mExpandedHeight = getRect().getHeight(); + + setDisplayChildren(!is_open); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + if (mCommitSignal) + { + (*mCommitSignal)(this, getDisplayChildren()); + } +} + +BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if(mCollapsible && mHeaderVisible && mCanOpenClose) + { + if(y >= (getRect().getHeight() - HEADER_HEIGHT) ) + { + LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); + header->setFocus(true); + changeOpenClose(getDisplayChildren()); + + //reset stored state + mWasStateStored = false; + return TRUE; + } + } + return LLUICtrl::handleMouseDown(x,y,mask); +} + +BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask) +{ + return LLUICtrl::handleMouseUp(x,y,mask); +} + +boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb) +{ + return setCommitCallback(cb); +} + +bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group) +{ + if(DD_HEADER_NAME != child->getName()) + { + reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT ); + mExpandedHeight = getRect().getHeight(); + } + + bool res = LLUICtrl::addChild(child, tab_group); + + if(DD_HEADER_NAME != child->getName()) + { + if(!mCollapsible) + setDisplayChildren(true); + else + setDisplayChildren(getDisplayChildren()); + } + + return res; +} + +void LLAccordionCtrlTab::setAccordionView(LLView* panel) +{ + addChild(panel,0); +} + + +LLView* LLAccordionCtrlTab::getAccordionView() +{ + for(child_list_const_iter_t it = getChildList()->begin(); + getChildList()->end() != it; ++it) + { + LLView* child = *it; + if(DD_HEADER_NAME == child->getName()) + continue; + if(!child->getVisible()) + continue; + return child; + } + return NULL; +} + + +S32 LLAccordionCtrlTab::getHeaderHeight() +{ + return mHeaderVisible?HEADER_HEIGHT:0; +} + +void LLAccordionCtrlTab::setHeaderVisible(bool value) +{ + if(mHeaderVisible == value) + return; + mHeaderVisible = value; + if(mHeader) + mHeader->setVisible(value); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); +}; + +//vurtual +BOOL LLAccordionCtrlTab::postBuild() +{ + mHeader->setVisible(mHeaderVisible); + return LLUICtrl::postBuild(); +} +bool LLAccordionCtrlTab::notifyChildren (const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "store_state") + { + storeOpenCloseState(); + return true; + } + if(str_action == "restore_state") + { + restoreOpenCloseState(); + return true; + } + } + return LLUICtrl::notifyChildren(info); +} + +S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "size_changes") + { + // + S32 height = info["height"]; + height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom(); + + mExpandedHeight = height; + + if(isExpanded()) + { + LLRect panel_rect = getRect(); + panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); + reshape(getRect().getWidth(),height); + setRect(panel_rect); + } + + //LLAccordionCtrl should rearrange accodion tab if one of accordion change its size + getParent()->notifyParent(info); + return 1; + } + else if(str_action == "select_prev") + { + showAndFocusHeader(); + return 1; + } + } + return LLUICtrl::notifyParent(info); +} + +S32 LLAccordionCtrlTab::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + showAndFocusHeader(); + return 1; + } + else if( str_action == "select_last" ) + { + if(getDisplayChildren() == false) + { + showAndFocusHeader(); + } + else + { + LLView* view = getAccordionView(); + if(view) + view->notify(LLSD().with("action","select_last")); + } + } + } + return 0; +} + +BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); + if( !header->hasFocus() ) + return LLUICtrl::handleKey(key, mask, called_from_parent); + + if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == false) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE) + { + if(getDisplayChildren() == true) + { + changeOpenClose(getDisplayChildren()); + return TRUE; + } + } + + if ( key == KEY_DOWN && mask == MASK_NONE) + { + //if collapsed go to the next accordion + if(getDisplayChildren() == false) + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_next")); + else + { + getAccordionView()->notify(LLSD().with("action","select_first")); + } + return TRUE; + } + + if ( key == KEY_UP && mask == MASK_NONE) + { + //go to the previous accordion + + //we processing notifyParent so let call parent directly + getParent()->notifyParent(LLSD().with("action","select_prev")); + return TRUE; + } + + return LLUICtrl::handleKey(key, mask, called_from_parent); +} + +void LLAccordionCtrlTab::showAndFocusHeader() +{ + LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); + header->setFocus(true); + + LLRect screen_rc; + LLRect selected_rc = header->getRect(); + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); + +} +void LLAccordionCtrlTab::storeOpenCloseState() +{ + if(mWasStateStored) + return; + mStoredOpenCloseState = getDisplayChildren(); + mWasStateStored = true; +} +void LLAccordionCtrlTab::restoreOpenCloseState() +{ + if(!mWasStateStored) + return; + if(getDisplayChildren() != mStoredOpenCloseState) + { + changeOpenClose(getDisplayChildren()); + } + mWasStateStored = false; +} diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h new file mode 100644 index 0000000000..b200d43438 --- /dev/null +++ b/indra/llui/llaccordionctrltab.h @@ -0,0 +1,191 @@ +/** + * @file LLAccordionCtrlTab.h + * @brief Collapsible box control implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_ACCORDIONCTRLTAB_H_ +#define LL_ACCORDIONCTRLTAB_H_ + +#include +#include "llrect.h" + +class LLUICtrl; +class LLUICtrlFactory; +class LLUIImage; +class LLButton; +class LLTextBox; + + + +// LLAccordionCtrlTab is a container for other controls. +// It has a Header, by clicking on which hosted controls are shown or hidden. +// When hosted controls are show - LLAccordionCtrlTab is expanded. +// When hosted controls are hidden - LLAccordionCtrlTab is collapsed. + +class LLAccordionCtrlTab : public LLUICtrl +{ +// Interface +public: + + struct Params + : public LLInitParam::Block + { + Optional display_children, //expanded or collapsed after initialization + collapsible; + + Optional title; + + Optional header_height, + min_width, + min_height; + + // Overlay images (arrows on the left) + Mandatory header_expand_img, + header_expand_img_pressed, + header_collapse_img, + header_collapse_img_pressed; + + // Background images for the accordion tabs + Mandatory header_image, + header_image_over, + header_image_pressed, + header_image_focused; + + Optional header_bg_color, + header_text_color, + dropdown_bg_color; + + Optional header_visible; + + Optional padding_left; + Optional padding_right; + Optional padding_top; + Optional padding_bottom; + + Params(); + }; + + typedef LLDefaultChildRegistry child_registry_t; + + virtual ~LLAccordionCtrlTab(); + + // Registers callback for expand/collapse events. + boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb); + + // Changes expand/collapse state + virtual void setDisplayChildren(bool display); + + // Returns expand/collapse state + virtual bool getDisplayChildren() const {return mDisplayChildren;}; + + //set LLAccordionCtrlTab panel + void setAccordionView(LLView* panel); + LLView* getAccordionView(); + + bool getCollapsible() {return mCollapsible;}; + + void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; + void changeOpenClose(bool is_open); + + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; + + virtual BOOL postBuild(); + + S32 notifyParent(const LLSD& info); + S32 notify(const LLSD& info); + bool notifyChildren(const LLSD& info); + + void storeOpenCloseState (); + void restoreOpenCloseState (); + +protected: + LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); + friend class LLUICtrlFactory; + +// Overrides +public: + + // Call reshape after changing size + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + // Changes expand/collapse state and triggers expand/collapse callbacks + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + virtual bool addChild(LLView* child, S32 tab_group); + + bool isExpanded() { return mDisplayChildren; } + + S32 getHeaderHeight(); + + // Min size functions + + void setHeaderVisible(bool value); + + bool getHeaderVisible() { return mHeaderVisible;} + + S32 mExpandedHeight; // Height of expanded ctrl. + // Used to restore height after expand. + + S32 getPaddingLeft() const { return mPaddingLeft;} + S32 getPaddingRight() const { return mPaddingRight;} + S32 getPaddingTop() const { return mPaddingTop;} + S32 getPaddingBottom() const { return mPaddingBottom;} + + void showAndFocusHeader(); + +private: + + + + class LLAccordionCtrlTabHeader; + LLAccordionCtrlTabHeader* mHeader; //Header + + bool mDisplayChildren; //Expanded/collapsed + bool mCollapsible; + bool mHeaderVisible; + + bool mCanOpenClose; + + S32 mPaddingLeft; + S32 mPaddingRight; + S32 mPaddingTop; + S32 mPaddingBottom; + + bool mStoredOpenCloseState; + bool mWasStateStored; + + + LLUIColor mDropdownBGColor; +}; + +#endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8918fc3018..62cb8380c0 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -63,8 +63,6 @@ include_directories( ) set(viewer_SOURCE_FILES - llaccordionctrl.cpp - llaccordionctrltab.cpp llagent.cpp llagentaccess.cpp llagentdata.cpp @@ -569,8 +567,6 @@ endif (LINUX) set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake - llaccordionctrl.h - llaccordionctrltab.h llagent.h llagentaccess.h llagentdata.h -- cgit v1.2.3 From d24cd96ef83263a0fe1f5853d6e5cd67f59ed16a Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 10:41:01 +0000 Subject: EXT-3929: Also look in accordion tabs for help topic. When the user clicks on the help "?" button, we try to find the currently active tab and see if there is a help topic for that tab. In addition, we now also look for a currently-visible accordion tab. --- indra/llui/llpanel.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index db32882438..143f19eea6 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -43,6 +43,7 @@ #include "llerror.h" #include "lltimer.h" +#include "llaccordionctrltab.h" #include "llbutton.h" #include "llmenugl.h" //#include "llstatusbar.h" @@ -851,14 +852,26 @@ static LLPanel *childGetVisibleTabWithHelp(LLView *parent) // look through immediate children first for an active tab with help for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) { + LLPanel *curTabPanel = NULL; + + // do we have a tab container? LLTabContainer *tab = dynamic_cast(child); if (tab && tab->getVisible()) { - LLPanel *curTabPanel = tab->getCurrentPanel(); - if (curTabPanel && !curTabPanel->getHelpTopic().empty()) - { - return curTabPanel; - } + curTabPanel = tab->getCurrentPanel(); + } + + // do we have an accordion tab? + LLAccordionCtrlTab* accordion = dynamic_cast(child); + if (accordion && accordion->getDisplayChildren()) + { + curTabPanel = dynamic_cast(accordion->getAccordionView()); + } + + // if we found a valid tab, does it have a help topic? + if (curTabPanel && !curTabPanel->getHelpTopic().empty()) + { + return curTabPanel; } } -- cgit v1.2.3 From 07aa9421e68163432a1c3022617675fc9065f180 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 11:39:37 +0000 Subject: EXT-4145: Added a secondlife:///app/search SLapp Displays the search floater and performs a search. You can specify an optional category and an optional search string. See the wiki docs for usage details: https://wiki.lindenlab.com/wiki/Viewer_2.0_SLapps --- indra/newview/llfloatersearch.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index c6d9fee630..a7401fdb6f 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -32,6 +32,9 @@ */ #include "llviewerprecompiledheaders.h" + +#include "llcommandhandler.h" +#include "llfloaterreg.h" #include "llfloatersearch.h" #include "llmediactrl.h" #include "lllogininstance.h" @@ -41,6 +44,42 @@ #include "llviewercontrol.h" #include "llweb.h" +// support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps +class LLSearchHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + const size_t parts = tokens.size(); + + // get the (optional) category for the search + std::string category; + if (parts > 0) + { + category = tokens[0].asString(); + } + + // get the (optional) search string + std::string search_text; + if (parts > 1) + { + search_text = tokens[1].asString(); + } + + // create the LLSD arguments for the search floater + LLSD args; + args["category"] = category; + args["id"] = LLURI::unescape(search_text); + + // open the search floater and perform the requested search + LLFloaterReg::showInstance("search", args); + return true; + } +}; +LLSearchHandler gSearchHandler; + LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), LLViewerMediaObserver(), -- cgit v1.2.3 From 1d9591afbe5946f0e3a75aea917097f6a08d8ce5 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 12:05:39 +0000 Subject: DEV-44732: Added some unit tests for URLs with no protocols. --- indra/llui/tests/llurlentry_test.cpp | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 128cd134c1..38cf7124ce 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -545,4 +545,50 @@ namespace tut "XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY", "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]"); } + + template<> template<> + void object::test<11>() + { + // + // test LLUrlEntryHTTPNoProtocol - general URLs without a protocol + // + LLUrlEntryHTTPNoProtocol url; + boost::regex r = url.getPattern(); + + testRegex("naked .com URL", r, + "see google.com", + "google.com"); + + testRegex("naked .org URL", r, + "see en.wikipedia.org for details", + "en.wikipedia.org"); + + testRegex("naked .net URL", r, + "example.net", + "example.net"); + + testRegex("naked .edu URL (2 instances)", r, + "MIT web site is at web.mit.edu and also www.mit.edu", + "web.mit.edu"); + + testRegex("invalid .com URL [1]", r, + "..com", + ""); + + testRegex("invalid .com URL [2]", r, + "you.come", + ""); + + testRegex("invalid .com URL [3]", r, + "recommended", + ""); + + testRegex("invalid .edu URL", r, + "hi there scheduled maitenance has begun", + ""); + + testRegex("invalid .net URL", r, + "foo.netty", + ""); + } } -- cgit v1.2.3 From 92b569a6079f55009dd9c291e9d7c56a00baf247 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 15:05:01 +0000 Subject: EXT-3928: Escape group names in the profile panel URLs. --- indra/llui/llurlentry.cpp | 2 +- indra/newview/llpanelavatar.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index f7528bc62a..1b6dd1b264 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -101,7 +101,7 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url) { start++; } - return url.substr(start, url.size()-start-1); + return unescapeUrl(url.substr(start, url.size()-start-1)); } std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string) diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index f3d6dbbb46..fb898f7cdf 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -594,8 +594,8 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g if (it != mGroups.begin()) groups += ", "; - - std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + it->first + "]"; + std::string group_name = LLURI::escape(it->first); + std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]"; groups += group_url; } -- cgit v1.2.3 From d258883b0c635ae10d9698217024dc5b7b168d96 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 11 Jan 2010 10:57:26 -0500 Subject: EXT-3952 save outfit button should be enabled on the wearing tab Enabled the button on the wearing tab of the appearance sidepanel and set its functionality to switch to the my outfits tab before the auto-rename happens. Reviewed by Seraph --- indra/newview/llpaneloutfitsinventory.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index a1c12412b5..550fee71bf 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -181,6 +181,10 @@ void LLPanelOutfitsInventory::onNew() { const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); + if (mAppearanceTabs) + { + mAppearanceTabs->selectTabByName("outfitslist_tab"); + } } void LLPanelOutfitsInventory::onSelectionChange(const std::deque &items, BOOL user_action) @@ -412,8 +416,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return (getCorrectListenerForAction() != NULL) && hasItemsSelected(); } - if (command_name == "wear" || - command_name == "make_outfit") + if (command_name == "wear") { const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab"); if (!is_my_outfits) @@ -421,6 +424,10 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return FALSE; } } + if (command_name == "make_outfit") + { + return TRUE; + } if (command_name == "edit" || command_name == "add" -- cgit v1.2.3 From a2c08d8e86a46fe37006a8086c56866445e57bf3 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Mon, 11 Jan 2010 16:59:28 +0000 Subject: EXT-3429: Don't display inspect slider when inappropriate. The avatar inspector has a volume slider and mute button. We make these widgets invisible when it does not makes sense to interact with them. That is, when the inspector is for your own avatar, or when voice is not active. --- indra/newview/llinspectavatar.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 72994a4371..a2b3a54f51 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -278,7 +278,7 @@ void LLInspectAvatar::onOpen(const LLSD& data) getChild("gear_self_btn")->setVisible(self); getChild("gear_btn")->setVisible(!self); - + // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned // See LLToolTipMgr::createToolTip @@ -518,13 +518,17 @@ void LLInspectAvatar::updateVolumeSlider() bool is_muted = LLMuteList::getInstance()-> isMuted(mAvatarID, LLMute::flagVoiceChat); bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID); + bool is_self = (mAvatarID == gAgent.getID()); LLUICtrl* mute_btn = getChild("mute_btn"); mute_btn->setEnabled( voice_enabled ); mute_btn->setValue( is_muted ); + mute_btn->setVisible( voice_enabled && !is_self ); LLUICtrl* volume_slider = getChild("volume_slider"); volume_slider->setEnabled( voice_enabled && !is_muted ); + volume_slider->setVisible( voice_enabled && !is_self ); + const F32 DEFAULT_VOLUME = 0.5f; F32 volume; if (is_muted) -- cgit v1.2.3 From 2a00a16f57daf7c3f99b0374901c03644a5b5f1b Mon Sep 17 00:00:00 2001 From: Runitai <> Date: Mon, 11 Jan 2010 11:21:52 -0600 Subject: EXT-3784 Fix for first menu item going blank when highlighted on ATI cards. --- indra/llrender/llgl.cpp | 37 ++++++++++++++++++++++++++++++++++++ indra/llrender/llglstates.h | 2 ++ indra/llrender/llrender.cpp | 2 ++ indra/llui/llmenugl.cpp | 2 ++ indra/newview/llspatialpartition.cpp | 1 - 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 3400a72385..187a9a984e 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1919,6 +1919,16 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) { stop_glerror(); + + checkState(); + + if (!depth_enabled) + { // always disable depth writes if depth testing is disabled + // GL spec defines this as a requirement, but some implementations allow depth writes with testing disabled + // The proper way to write to depth buffer with testing disabled is to enable testing and use a depth_func of GL_ALWAYS + write_enabled = FALSE; + } + if (depth_enabled != sDepthEnabled) { gGL.flush(); @@ -1942,6 +1952,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G LLGLDepthTest::~LLGLDepthTest() { + checkState(); if (sDepthEnabled != mPrevDepthEnabled ) { gGL.flush(); @@ -1963,6 +1974,32 @@ LLGLDepthTest::~LLGLDepthTest() } } +void LLGLDepthTest::checkState() +{ + if (gDebugGL) + { + GLint func = 0; + GLboolean mask = FALSE; + + glGetIntegerv(GL_DEPTH_FUNC, &func); + glGetBooleanv(GL_DEPTH_WRITEMASK, &mask); + + if (glIsEnabled(GL_DEPTH_TEST) != sDepthEnabled || + sWriteEnabled != mask || + sDepthFunc != func) + { + if (gDebugSession) + { + gFailLog << "Unexpected depth testing state." << std::endl; + } + else + { + LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL; + } + } + } +} + LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P) { for (U32 i = 0; i < 4; i++) diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 4a51cac438..968a37cab0 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -46,6 +46,8 @@ public: ~LLGLDepthTest(); + void checkState(); + GLboolean mPrevDepthEnabled; GLenum mPrevDepthFunc; GLboolean mPrevWriteEnabled; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index fc45df8153..f97d81126e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -162,6 +162,8 @@ void LLTexUnit::enable(eTextureType type) disable(); // Force a disable of a previous texture type if it's enabled. } mCurrTexType = type; + + gGL.flush(); glEnable(sGLTextureType[type]); } } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 527c0a1b87..bd67949c2a 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -46,6 +46,7 @@ #include "llmenugl.h" +#include "llgl.h" #include "llmath.h" #include "llrender.h" #include "llfocusmgr.h" @@ -477,6 +478,7 @@ void LLMenuItemGL::draw( void ) if (dynamic_cast(this)) debug_count++; gGL.color4fv( mHighlightBackground.get().mV ); + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 6ca6734598..514d8facb4 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2460,7 +2460,6 @@ void renderOctree(LLSpatialGroup* group) gGL.color4fv(col.mV); drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); - glDepthMask(GL_TRUE); gGL.setSceneBlendType(LLRender::BT_ALPHA); if (group->mBuilt <= 0.f) -- cgit v1.2.3 From 0b63977570221ae7ca0ad46c9f844603ff91eeb4 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Mon, 11 Jan 2010 09:53:24 -0800 Subject: Fix build issue with ba93e704bd4f --- indra/newview/llviewermedia.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index f91d126073..9671b9e5dc 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -48,6 +48,8 @@ #include "llviewerwindow.h" #include "llfocusmgr.h" #include "llcallbacklist.h" +#include "llparcel.h" +#include "llaudioengine.h" // for gAudiop #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" @@ -909,14 +911,14 @@ void LLViewerMedia::cleanupClass() ////////////////////////////////////////////////////////////////////////////////////////// // static -bool LLViewerParcelMedia::needsMediaFirstRun() +bool LLViewerMedia::needsMediaFirstRun() { return gWarningSettings.getBOOL("FirstStreamingMedia"); } ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerParcelMedia::displayMediaFirstRun() +void LLViewerMedia::displayMediaFirstRun() { gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); @@ -926,7 +928,7 @@ void LLViewerParcelMedia::displayMediaFirstRun() ////////////////////////////////////////////////////////////////////////////////////////// // static -bool LLViewerParcelMedia::firstRunCallback(const LLSD& notification, const LLSD& response) +bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) -- cgit v1.2.3 From dd861135677b54a797305bb92199ac614cae5070 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Mon, 11 Jan 2010 10:03:00 -0800 Subject: Backed out changeset b6030bb6ff40 --- indra/newview/llviewermedia.cpp | 73 +++++++++++++++++++++++++++++++++++ indra/newview/llviewermedia.h | 6 +++ indra/newview/llviewerparcelmedia.cpp | 40 +------------------ 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7e8c8eb92e..f91d126073 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,6 +54,7 @@ #include "lluuid.h" #include "llkeyboard.h" #include "llmutelist.h" +#include "llfirstuse.h" #include // for SkinFolder listener #include @@ -708,6 +709,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) std::vector proximity_order; + bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); + bool needs_first_run = LLViewerMedia::needsMediaFirstRun(); U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); @@ -822,6 +825,21 @@ void LLViewerMedia::updateMedia(void *dummy_arg) new_priority = LLPluginClassMedia::PRIORITY_LOW; } + if(!inworld_media_enabled) + { + // If inworld media is locked out, force all inworld media to stay unloaded. + if(!pimpl->getUsedInUI()) + { + new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; + if(needs_first_run) + { + // Don't do this more than once in this loop. + needs_first_run = false; + LLViewerMedia::displayMediaFirstRun(); + } + } + } + pimpl->setPriority(new_priority); if(pimpl->getUsedInUI()) @@ -888,6 +906,61 @@ void LLViewerMedia::cleanupClass() gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); } + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerParcelMedia::needsMediaFirstRun() +{ + return gWarningSettings.getBOOL("FirstStreamingMedia"); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerParcelMedia::displayMediaFirstRun() +{ + gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); + + LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), + boost::bind(firstRunCallback, _1, _2)); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerParcelMedia::firstRunCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // user has elected to automatically play media. + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); + gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); + gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); + gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); + + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if (parcel) + { + // play media right now, if available + LLViewerParcelMedia::play(parcel); + + // play music right now, if available + std::string music_url = parcel->getMusicURL(); + if (gAudiop && !music_url.empty()) + gAudiop->startInternetStream(music_url); + } + } + else + { + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE); + gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); + gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); + gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); + } + return false; +} + + ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index b103c48bd8..3ce9f1887c 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -115,6 +115,12 @@ class LLViewerMedia // This is the comparitor used to sort the list. static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2); + + // For displaying the media first-run dialog. + static bool needsMediaFirstRun(); + static void displayMediaFirstRun(); + static bool firstRunCallback(const LLSD& notification, const LLSD& response); + }; // Implementation functions not exported into header file diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 0f7903a7a5..56dee6b34c 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -56,10 +56,6 @@ LLUUID LLViewerParcelMedia::sMediaRegionID; viewer_media_t LLViewerParcelMedia::sMediaImpl; -// Local functions -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); - - // static void LLViewerParcelMedia::initClass() { @@ -112,12 +108,10 @@ void LLViewerParcelMedia::update(LLParcel* parcel) // First use warning if( (!mediaUrl.empty() || !parcel->getMusicURL().empty()) - && gWarningSettings.getBOOL("FirstStreamingMedia") ) + && LLViewerMedia::needsMediaFirstRun()) { - LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(callback_play_media, _1, _2, parcel)); + LLViewerMedia::displayMediaFirstRun(); return; - } // if we have a current (link sharing) url, use it instead @@ -591,36 +585,6 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; } -bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - // user has elected to automatically play media. - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); - gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); - gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); - if(!gSavedSettings.getBOOL("AudioStreamingMedia")) - gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); - // play media right now, if available - LLViewerParcelMedia::play(parcel); - // play music right now, if available - if (parcel) - { - std::string music_url = parcel->getMusicURL(); - if (gAudiop && !music_url.empty()) - gAudiop->startInternetStream(music_url); - } - } - else - { - gSavedSettings.setBOOL("AudioStreamingVideo", FALSE); - gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); - } - gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); - return false; -} - // TODO: observer /* void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in ) -- cgit v1.2.3 From a74d494dd7c13e0307ee5ba526ba021583b1f2b5 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Mon, 11 Jan 2010 16:41:08 -0800 Subject: Fix unposted bug: drag feedback didn't check whitelist http://codereview.lindenlab.com/274039/show --- indra/newview/llviewerwindow.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 81fcfc13c2..5dd640539f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -912,14 +912,18 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi } else { - if ( obj != mDragHoveredObject) + // Check the whitelist, if there's media (otherwise just show it) + if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) { - // Highlight the dragged object - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = obj; - LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); + if ( obj != mDragHoveredObject) + { + // Highlight the dragged object + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = obj; + LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); + } + result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; } - result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; } } } -- cgit v1.2.3