PageRenderTime 20ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llpanelwearing.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 307 lines | 199 code | 64 blank | 44 comment | 36 complexity | 4c897c6444492562fedd9f8141bcd25a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpanelwearing.cpp
  3. * @brief List of agent's worn items.
  4. *
  5. * $LicenseInfo:firstyear=2010&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llpanelwearing.h"
  28. #include "lltoggleablemenu.h"
  29. #include "llappearancemgr.h"
  30. #include "llfloatersidepanelcontainer.h"
  31. #include "llinventoryfunctions.h"
  32. #include "llinventorymodel.h"
  33. #include "llinventoryobserver.h"
  34. #include "llmenubutton.h"
  35. #include "llviewermenu.h"
  36. #include "llwearableitemslist.h"
  37. #include "llsdserialize.h"
  38. #include "llclipboard.h"
  39. // Context menu and Gear menu helper.
  40. static void edit_outfit()
  41. {
  42. LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
  43. }
  44. //////////////////////////////////////////////////////////////////////////
  45. class LLWearingGearMenu
  46. {
  47. public:
  48. LLWearingGearMenu(LLPanelWearing* panel_wearing)
  49. : mMenu(NULL), mPanelWearing(panel_wearing)
  50. {
  51. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  52. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  53. registrar.add("Gear.Edit", boost::bind(&edit_outfit));
  54. registrar.add("Gear.TakeOff", boost::bind(&LLWearingGearMenu::onTakeOff, this));
  55. registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing));
  56. enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2));
  57. mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
  58. "menu_wearing_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  59. llassert(mMenu);
  60. }
  61. LLToggleableMenu* getMenu() { return mMenu; }
  62. private:
  63. void onTakeOff()
  64. {
  65. uuid_vec_t selected_uuids;
  66. mPanelWearing->getSelectedItemsUUIDs(selected_uuids);
  67. for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it)
  68. {
  69. LLAppearanceMgr::instance().removeItemFromAvatar(*it);
  70. }
  71. }
  72. LLToggleableMenu* mMenu;
  73. LLPanelWearing* mPanelWearing;
  74. };
  75. //////////////////////////////////////////////////////////////////////////
  76. class LLWearingContextMenu : public LLListContextMenu
  77. {
  78. protected:
  79. /* virtual */ LLContextMenu* createMenu()
  80. {
  81. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  82. functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
  83. registrar.add("Wearing.Edit", boost::bind(&edit_outfit));
  84. registrar.add("Wearing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs));
  85. registrar.add("Wearing.Detach", boost::bind(handleMultiple, take_off, mUUIDs));
  86. LLContextMenu* menu = createFromFile("menu_wearing_tab.xml");
  87. updateMenuItemsVisibility(menu);
  88. return menu;
  89. }
  90. void updateMenuItemsVisibility(LLContextMenu* menu)
  91. {
  92. bool bp_selected = false; // true if body parts selected
  93. bool clothes_selected = false;
  94. bool attachments_selected = false;
  95. // See what types of wearables are selected.
  96. for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it)
  97. {
  98. LLViewerInventoryItem* item = gInventory.getItem(*it);
  99. if (!item)
  100. {
  101. llwarns << "Invalid item" << llendl;
  102. continue;
  103. }
  104. LLAssetType::EType type = item->getType();
  105. if (type == LLAssetType::AT_CLOTHING)
  106. {
  107. clothes_selected = true;
  108. }
  109. else if (type == LLAssetType::AT_BODYPART)
  110. {
  111. bp_selected = true;
  112. }
  113. else if (type == LLAssetType::AT_OBJECT)
  114. {
  115. attachments_selected = true;
  116. }
  117. }
  118. // Enable/disable some menu items depending on the selection.
  119. bool allow_detach = !bp_selected && !clothes_selected && attachments_selected;
  120. bool allow_take_off = !bp_selected && clothes_selected && !attachments_selected;
  121. menu->setItemVisible("take_off", allow_take_off);
  122. menu->setItemVisible("detach", allow_detach);
  123. menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach);
  124. }
  125. };
  126. //////////////////////////////////////////////////////////////////////////
  127. std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null;
  128. static LLRegisterPanelClassWrapper<LLPanelWearing> t_panel_wearing("panel_wearing");
  129. LLPanelWearing::LLPanelWearing()
  130. : LLPanelAppearanceTab()
  131. , mCOFItemsList(NULL)
  132. , mIsInitialized(false)
  133. {
  134. mCategoriesObserver = new LLInventoryCategoriesObserver();
  135. mGearMenu = new LLWearingGearMenu(this);
  136. mContextMenu = new LLWearingContextMenu();
  137. }
  138. LLPanelWearing::~LLPanelWearing()
  139. {
  140. delete mGearMenu;
  141. delete mContextMenu;
  142. if (gInventory.containsObserver(mCategoriesObserver))
  143. {
  144. gInventory.removeObserver(mCategoriesObserver);
  145. }
  146. delete mCategoriesObserver;
  147. }
  148. BOOL LLPanelWearing::postBuild()
  149. {
  150. mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list");
  151. mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3));
  152. LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
  153. menu_gear_btn->setMenu(mGearMenu->getMenu());
  154. return TRUE;
  155. }
  156. //virtual
  157. void LLPanelWearing::onOpen(const LLSD& /*info*/)
  158. {
  159. if (!mIsInitialized)
  160. {
  161. // *TODO: I'm not sure is this check necessary but it never match while developing.
  162. if (!gInventory.isInventoryUsable())
  163. return;
  164. const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
  165. // *TODO: I'm not sure is this check necessary but it never match while developing.
  166. LLViewerInventoryCategory* category = gInventory.getCategory(cof);
  167. if (!category)
  168. return;
  169. gInventory.addObserver(mCategoriesObserver);
  170. // Start observing changes in Current Outfit category.
  171. mCategoriesObserver->addCategory(cof, boost::bind(&LLWearableItemsList::updateList, mCOFItemsList, cof));
  172. // Fetch Current Outfit contents and refresh the list to display
  173. // initially fetched items. If not all items are fetched now
  174. // the observer will refresh the list as soon as the new items
  175. // arrive.
  176. category->fetch();
  177. mCOFItemsList->updateList(cof);
  178. mIsInitialized = true;
  179. }
  180. }
  181. // virtual
  182. void LLPanelWearing::setFilterSubString(const std::string& string)
  183. {
  184. sFilterSubString = string;
  185. mCOFItemsList->setFilterSubString(sFilterSubString);
  186. }
  187. // virtual
  188. bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
  189. {
  190. const std::string command_name = userdata.asString();
  191. if (command_name == "save_outfit")
  192. {
  193. bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked();
  194. bool outfit_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
  195. // allow save only if outfit isn't locked and is dirty
  196. return !outfit_locked && outfit_dirty;
  197. }
  198. if (command_name == "take_off")
  199. {
  200. return hasItemSelected() && canTakeOffSelected();
  201. }
  202. return false;
  203. }
  204. boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb)
  205. {
  206. if (!mCOFItemsList) return boost::signals2::connection();
  207. return mCOFItemsList->setCommitCallback(cb);
  208. }
  209. void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
  210. {
  211. LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
  212. if (!list) return;
  213. uuid_vec_t selected_uuids;
  214. list->getSelectedUUIDs(selected_uuids);
  215. mContextMenu->show(ctrl, selected_uuids, x, y);
  216. }
  217. bool LLPanelWearing::hasItemSelected()
  218. {
  219. return mCOFItemsList->getSelectedItem() != NULL;
  220. }
  221. void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
  222. {
  223. mCOFItemsList->getSelectedUUIDs(selected_uuids);
  224. }
  225. void LLPanelWearing::copyToClipboard()
  226. {
  227. std::string text;
  228. std::vector<LLSD> data;
  229. mCOFItemsList->getValues(data);
  230. for(std::vector<LLSD>::const_iterator iter = data.begin(); iter != data.end();)
  231. {
  232. LLSD uuid = (*iter);
  233. LLViewerInventoryItem* item = gInventory.getItem(uuid);
  234. iter++;
  235. if (item != NULL)
  236. {
  237. // Append a newline to all but the last line
  238. text += iter != data.end() ? item->getName() + "\n" : item->getName();
  239. }
  240. }
  241. gClipboard.copyFromString(utf8str_to_wstring(text));
  242. }
  243. // EOF