summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llfloaterexperiencepicker.cpp380
-rw-r--r--indra/newview/llfloaterexperiencepicker.h44
-rw-r--r--indra/newview/llfloaterexperiences.cpp3
-rwxr-xr-xindra/newview/llfloaterregioninfo.cpp8
-rw-r--r--indra/newview/llpanelexperiencelisteditor.cpp5
-rw-r--r--indra/newview/llpanelexperiencepicker.cpp397
-rw-r--r--indra/newview/llpanelexperiencepicker.h91
-rwxr-xr-xindra/newview/llpanelgrouproles.cpp4
-rw-r--r--indra/newview/skins/default/xui/en/floater_experience_search.xml156
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml7
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml16
-rw-r--r--indra/newview/skins/default/xui/en/panel_experience_search.xml166
13 files changed, 694 insertions, 585 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 0a6f935930..fce9b16129 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -407,6 +407,7 @@ set(viewer_SOURCE_FILES
llpaneleditwearable.cpp
llpanelexperiencelisteditor.cpp
llpanelexperiencelog.cpp
+ llpanelexperiencepicker.cpp
llpanelexperiences.cpp
llpanelface.cpp
llpanelgenerictip.cpp
@@ -997,6 +998,7 @@ set(viewer_HEADER_FILES
llpaneleditwearable.h
llpanelexperiencelisteditor.h
llpanelexperiencelog.h
+ llpanelexperiencepicker.h
llpanelexperiences.h
llpanelface.h
llpanelgenerictip.h
diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp
index f68bf7f9a6..60a9bdfd98 100644
--- a/indra/newview/llfloaterexperiencepicker.cpp
+++ b/indra/newview/llfloaterexperiencepicker.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfloaterexperiencepicker.cpp
* @brief Implementation of llfloaterexperiencepicker
* @author dolphin@lindenlab.com
@@ -42,47 +42,9 @@
#include "llcombobox.h"
#include "llviewercontrol.h"
#include "lldraghandle.h"
+#include "llpanelexperiencepicker.h"
-#define BTN_FIND "find"
-#define BTN_OK "ok_btn"
-#define BTN_CANCEL "cancel_btn"
-#define BTN_PROFILE "profile_btn"
-#define TEXT_EDIT "edit"
-#define TEXT_MATURITY "maturity"
-#define LIST_RESULTS "search_results"
-#define PANEL_SEARCH "search_panel"
-
-const static std::string columnSpace = " ";
-
-class LLExperiencePickerResponder : public LLHTTPClient::Responder
-{
-public:
- LLUUID mQueryID;
- LLHandle<LLFloaterExperiencePicker> mParent;
-
- LLExperiencePickerResponder(const LLUUID& id, const LLHandle<LLFloaterExperiencePicker>& parent) : mQueryID(id), mParent(parent) { }
-
- void completed(U32 status, const std::string& reason, const LLSD& content)
- {
- if (isGoodStatus(status))
- {
- if(mParent.isDead())
- return;
-
- LLFloaterExperiencePicker* floater =mParent.get();
- if (floater)
- {
- floater->processResponse(mQueryID, content);
- }
- }
- else
- {
- llwarns << "avatar picker failed [status:" << status << "]: " << content << llendl;
-
- }
- }
-};
-LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL closeOnSelect, LLView * frustumOrigin )
+LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin )
{
LLFloaterExperiencePicker* floater =
LLFloaterReg::showTypedInstance<LLFloaterExperiencePicker>("experience_search", key);
@@ -92,9 +54,13 @@ LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t ca
return NULL;
}
- floater->mSelectionCallback = callback;
- floater->mCloseOnSelect = closeOnSelect;
- floater->setAllowMultiple(allow_multiple);
+ if (floater->mSearchPanel)
+ {
+ floater->mSearchPanel->mSelectionCallback = callback;
+ floater->mSearchPanel->mCloseOnSelect = close_on_select;
+ floater->mSearchPanel->setAllowMultiple(allow_multiple);
+ floater->mSearchPanel->addFilters(filters.begin(), filters.end());
+ }
if(frustumOrigin)
{
@@ -104,7 +70,6 @@ LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t ca
return floater;
}
-
void LLFloaterExperiencePicker::drawFrustum()
{
if(mFrustumOrigin.get())
@@ -170,13 +135,12 @@ void LLFloaterExperiencePicker::draw()
LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key )
:LLFloater(key)
- ,mContextConeOpacity (0.f)
+ ,mSearchPanel(NULL)
+ ,mContextConeOpacity(0.f)
,mContextConeInAlpha(0.f)
,mContextConeOutAlpha(0.f)
,mContextConeFadeTime(0.f)
{
- setDefaultFilters();
-
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
@@ -187,324 +151,8 @@ LLFloaterExperiencePicker::~LLFloaterExperiencePicker()
gFocusMgr.releaseFocusIfNeeded( this );
}
-
-
BOOL LLFloaterExperiencePicker::postBuild()
{
- getChild<LLLineEditor>(TEXT_EDIT)->setKeystrokeCallback( boost::bind(&LLFloaterExperiencePicker::editKeystroke, this, _1, _2),NULL);
-
- childSetAction(BTN_FIND, boost::bind(&LLFloaterExperiencePicker::onBtnFind, this));
- getChildView(BTN_FIND)->setEnabled(FALSE);
-
- LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>(LIST_RESULTS);
- searchresults->setDoubleClickCallback( boost::bind(&LLFloaterExperiencePicker::onBtnSelect, this));
- searchresults->setCommitCallback(boost::bind(&LLFloaterExperiencePicker::onList, this));
- getChildView(LIST_RESULTS)->setEnabled(FALSE);
- getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
-
- childSetAction(BTN_OK, boost::bind(&LLFloaterExperiencePicker::onBtnSelect, this));
- getChildView(BTN_OK)->setEnabled(FALSE);
- childSetAction(BTN_CANCEL, boost::bind(&LLFloaterExperiencePicker::onBtnClose, this));
- childSetAction(BTN_PROFILE, boost::bind(&LLFloaterExperiencePicker::onBtnProfile, this));
- getChildView(BTN_PROFILE)->setEnabled(FALSE);
-
- getChild<LLComboBox>(TEXT_MATURITY)->setCurrentByIndex(2);
- getChild<LLComboBox>(TEXT_MATURITY)->setCommitCallback(boost::bind(&LLFloaterExperiencePicker::onMaturity, this));
- getChild<LLUICtrl>(TEXT_EDIT)->setFocus(TRUE);
-
- LLPanel* search_panel = getChild<LLPanel>(PANEL_SEARCH);
- if (search_panel)
- {
- // Start searching when Return is pressed in the line editor.
- search_panel->setDefaultBtn(BTN_FIND);
- }
- return TRUE;
-}
-
-void LLFloaterExperiencePicker::editKeystroke( class LLLineEditor* caller, void* user_data )
-{
- getChildView(BTN_FIND)->setEnabled(caller->getText().size() > 0);
-}
-
-void LLFloaterExperiencePicker::onBtnFind()
-{
- find();
-}
-
-void LLFloaterExperiencePicker::onBtnSelect()
-{
- if(!isSelectButtonEnabled())
- {
- return;
- }
-
- if(mSelectionCallback)
- {
- const LLScrollListCtrl* results = getChild<LLScrollListCtrl>(LIST_RESULTS);
- uuid_vec_t experience_ids;
-
- getSelectedExperienceIds(results, experience_ids);
- mSelectionCallback(experience_ids);
- getChild<LLScrollListCtrl>(LIST_RESULTS)->deselectAllItems(TRUE);
- if(mCloseOnSelect)
- {
- mCloseOnSelect = FALSE;
- closeFloater();
- }
- }
- else
- {
- onBtnProfile();
- }
-}
-
-void LLFloaterExperiencePicker::onList()
-{
- bool enabled = isSelectButtonEnabled();
- getChildView(BTN_OK)->setEnabled(enabled);
-
- enabled = enabled && getChild<LLScrollListCtrl>(LIST_RESULTS)->getNumSelected() == 1;
- getChildView(BTN_PROFILE)->setEnabled(enabled);
-}
-
-
-void LLFloaterExperiencePicker::onBtnClose()
-{
- closeFloater();
-}
-
-
-void LLFloaterExperiencePicker::find()
-{
- std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
- mQueryID.generate();
- std::string url;
- url.reserve(128+text.size());
-
- LLViewerRegion* region = gAgent.getRegion();
- url = region->getCapability("FindExperienceByName");
- if (!url.empty())
- {
- url+="?query=";
- url+=LLURI::escape(text);
- LLHTTPClient::get(url, new LLExperiencePickerResponder(mQueryID, getDerivedHandle<LLFloaterExperiencePicker>()));
-
- }
-
-
- getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
- getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
-
- getChildView(BTN_OK)->setEnabled(FALSE);
- getChildView(BTN_PROFILE)->setEnabled(FALSE);
-}
-
-
-bool LLFloaterExperiencePicker::isSelectButtonEnabled()
-{
- LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS);
- return list->getFirstSelectedIndex() >=0;
-}
-
-void LLFloaterExperiencePicker::getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids )
-{
- std::vector<LLScrollListItem*> items = results->getAllSelected();
- for(std::vector<LLScrollListItem*>::iterator it = items.begin(); it != items.end(); ++it)
- {
- LLScrollListItem* item = *it;
- if (item->getUUID().notNull())
- {
- experience_ids.push_back(item->getUUID());
- }
- }
-}
-
-void LLFloaterExperiencePicker::setAllowMultiple( bool allow_multiple )
-{
- getChild<LLScrollListCtrl>(LIST_RESULTS)->setAllowMultipleSelection(allow_multiple);
+ mSearchPanel = static_cast<LLPanelExperiencePicker*>(getChild<LLUICtrl>("panel_experience_search"));
+ return LLFloater::postBuild();
}
-
-
-void name_callback(const LLHandle<LLFloaterExperiencePicker>& floater, const LLUUID& experience_id, const LLUUID& agent_id, const LLAvatarName& av_name)
-{
- if(floater.isDead())
- return;
- LLFloaterExperiencePicker* picker = floater.get();
- LLScrollListCtrl* search_results = picker->getChild<LLScrollListCtrl>(LIST_RESULTS);
-
- LLScrollListItem* item = search_results->getItem(experience_id);
- if(!item)
- return;
-
- item->getColumn(2)->setValue(columnSpace+av_name.getDisplayName());
-
-}
-
-void LLFloaterExperiencePicker::processResponse( const LLUUID& query_id, const LLSD& content )
-{
- if(query_id != mQueryID)
- {
- return;
- }
-
- mResponse = content;
-
- const LLSD& experiences=mResponse["experience_keys"];
- LLSD::array_const_iterator it = experiences.beginArray();
- for ( ; it != experiences.endArray(); ++it)
- {
- LLExperienceCache::insert(*it);
- }
-
- filterContent();
-
-}
-
-void LLFloaterExperiencePicker::onBtnProfile()
-{
- LLScrollListItem* item = getChild<LLScrollListCtrl>(LIST_RESULTS)->getFirstSelected();
- if(item)
- {
- LLFloaterReg::showInstance("experience_profile", item->getUUID(), true);
- }
-}
-
-std::string LLFloaterExperiencePicker::getMaturityString(int maturity)
-{
- if(maturity <= SIM_ACCESS_PG)
- {
- return getString("maturity_icon_general");
- }
- else if(maturity <= SIM_ACCESS_MATURE)
- {
- return getString("maturity_icon_moderate");
- }
- return getString("maturity_icon_adult");
-}
-
-void LLFloaterExperiencePicker::filterContent()
-{
- LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>(LIST_RESULTS);
-
- const LLSD& experiences=mResponse["experience_keys"];
-
- search_results->deleteAllItems();
-
- LLSD item;
- LLSD::array_const_iterator it = experiences.beginArray();
- for ( ; it != experiences.endArray(); ++it)
- {
- const LLSD& experience = *it;
-
- if(isExperienceHidden(experience))
- continue;
-
- item["id"]=experience[LLExperienceCache::EXPERIENCE_ID];
- LLSD& columns = item["columns"];
- columns[0]["column"] = "maturity";
- columns[0]["value"] = getMaturityString(experience[LLExperienceCache::MATURITY].asInteger());
- columns[0]["type"]="icon";
- columns[0]["halign"]="right";
- columns[1]["column"] = "experience_name";
- columns[1]["value"] = columnSpace+experience[LLExperienceCache::NAME].asString();
- columns[2]["column"] = "owner";
- columns[2]["value"] = columnSpace+getString("loading");
- search_results->addElement(item);
- LLAvatarNameCache::get(experience[LLExperienceCache::AGENT_ID], boost::bind(name_callback, getDerivedHandle<LLFloaterExperiencePicker>(), experience[LLExperienceCache::EXPERIENCE_ID], _1, _2));
- }
-
- if (search_results->isEmpty())
- {
- LLStringUtil::format_map_t map;
- std::string search_text = childGetText(TEXT_EDIT);
- map["[TEXT]"] = search_text;
- if (search_text.empty())
- {
- getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
- }
- else
- {
- getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("not_found", map));
- }
- search_results->setEnabled(false);
- getChildView(BTN_OK)->setEnabled(false);
- getChildView(BTN_PROFILE)->setEnabled(false);
- }
- else
- {
- getChildView(BTN_OK)->setEnabled(true);
- search_results->setEnabled(true);
- search_results->sortByColumnIndex(1, TRUE);
- std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
- if (!search_results->selectItemByLabel(text, TRUE, 1))
- {
- search_results->selectFirstItem();
- }
- onList();
- search_results->setFocus(TRUE);
- }
-}
-
-void LLFloaterExperiencePicker::onMaturity()
-{
- if(mResponse.has("experience_keys") && mResponse["experience_keys"].beginArray() != mResponse["experience_keys"].endArray())
- {
- filterContent();
- }
-}
-
-bool LLFloaterExperiencePicker::isExperienceHidden( const LLSD& experience) const
-{
- bool hide=false;
- filter_list::const_iterator it = mFilters.begin();
- for(/**/;it != mFilters.end(); ++it)
- {
- if((*it)(experience)){
- return true;
- }
- }
-
- return hide;
-}
-
-bool LLFloaterExperiencePicker::FilterOverRating( const LLSD& experience )
-{
- int maturity = getChild<LLComboBox>(TEXT_MATURITY)->getSelectedValue().asInteger();
- return experience[LLExperienceCache::MATURITY].asInteger() > maturity;
-}
-
-bool LLFloaterExperiencePicker::FilterWithProperty( const LLSD& experience, S32 prop)
-{
- return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) != 0;
-}
-
-bool LLFloaterExperiencePicker::FilterWithoutProperty( const LLSD& experience, S32 prop )
-{
- return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == 0;
-}
-
-void LLFloaterExperiencePicker::setDefaultFilters()
-{
- mFilters.clear();
- addFilter(boost::bind(&LLFloaterExperiencePicker::FilterOverRating, this, _1));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/indra/newview/llfloaterexperiencepicker.h b/indra/newview/llfloaterexperiencepicker.h
index ea0240d2ac..29054a57db 100644
--- a/indra/newview/llfloaterexperiencepicker.h
+++ b/indra/newview/llfloaterexperiencepicker.h
@@ -31,65 +31,29 @@
class LLScrollListCtrl;
class LLLineEditor;
+class LLPanelExperiencePicker;
class LLFloaterExperiencePicker : public LLFloater
{
public:
- friend class LLExperiencePickerResponder;
- // The callback function will be called with an avatar name and UUID.
typedef boost::function<void (const uuid_vec_t&)> select_callback_t;
// filter function for experiences, return true if the experience should be hidden.
typedef boost::function<bool (const LLSD&)> filter_function;
typedef std::vector<filter_function> filter_list;
- static LLFloaterExperiencePicker* show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL closeOnSelect, LLView * frustumOrigin);
+ static LLFloaterExperiencePicker* show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin);
LLFloaterExperiencePicker(const LLSD& key);
virtual ~LLFloaterExperiencePicker();
BOOL postBuild();
-
- void addFilter(filter_function func){mFilters.push_back(func);}
- template <class IT>
- void addFilters(IT begin, IT end){mFilters.insert(mFilters.end(), begin, end);}
- void setDefaultFilters();
-
- static bool FilterWithProperty(const LLSD& experience, S32 prop);
- static bool FilterWithoutProperty(const LLSD& experience, S32 prop);
- bool FilterOverRating(const LLSD& experience);
-
+
virtual void draw();
private:
- void editKeystroke(LLLineEditor* caller, void* user_data);
-
- void onBtnFind();
- void onBtnSelect();
- void onBtnProfile();
- void onBtnClose();
- void onList();
- void onMaturity();
-
- void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids );
- void setAllowMultiple(bool allow_multiple);
-
-
- void find();
- bool isSelectButtonEnabled();
- void processResponse( const LLUUID& query_id, const LLSD& content );
-
- void filterContent();
- bool isExperienceHidden(const LLSD& experience) const ;
- std::string getMaturityString(int maturity);
-
-
- select_callback_t mSelectionCallback;
- filter_list mFilters;
- LLUUID mQueryID;
- LLSD mResponse;
- bool mCloseOnSelect;
+ LLPanelExperiencePicker* mSearchPanel;
void drawFrustum();
LLHandle <LLView> mFrustumOrigin;
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index 1654419826..51e3996f3f 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -36,7 +36,7 @@
#include "llevents.h"
#include "llnotificationsutil.h"
#include "llpanelexperiencelog.h"
-
+#include "llpanelexperiencepicker.h"
#define SHOW_RECENT_TAB (0)
@@ -106,6 +106,7 @@ LLPanelExperiences* LLFloaterExperiences::addTab(const std::string& name, bool s
BOOL LLFloaterExperiences::postBuild()
{
+ getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperiencePicker());
addTab("Allowed_Experiences_Tab", true);
addTab("Blocked_Experiences_Tab", false);
addTab("Admin_Experiences_Tab", false);
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 2522b7bf18..6d8f8f5587 100755
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -94,7 +94,7 @@
#include "llfloaterregionrestarting.h"
#include "llpanelexperiencelisteditor.h"
#include <boost/function.hpp>
-#include "llfloaterexperiencepicker.h"
+#include "llpanelexperiencepicker.h"
#include "llexperiencecache.h"
#include "llpanelexperiences.h"
@@ -3634,14 +3634,14 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
mAllowed->loading();
mAllowed->setReadonly(!allow_modify);
// remove grid-wide experiences
- mAllowed->addFilter(boost::bind(LLFloaterExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID));
+ mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID));
mBlocked->loading();
mBlocked->setReadonly(!allow_modify);
// only grid-wide experiences
- mBlocked->addFilter(boost::bind(LLFloaterExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID));
+ mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID));
// but not privileged ones
- mBlocked->addFilter(boost::bind(LLFloaterExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED));
+ mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED));
mTrusted->loading();
mTrusted->setReadonly(!allow_modify);
diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp
index a4ceb3830c..6d47673849 100644
--- a/indra/newview/llpanelexperiencelisteditor.cpp
+++ b/indra/newview/llpanelexperiencelisteditor.cpp
@@ -107,9 +107,7 @@ void LLPanelExperienceListEditor::onAdd()
{
mKey.generateNewID();
- LLFloaterExperiencePicker* picker=LLFloaterExperiencePicker::show(boost::bind(&LLPanelExperienceListEditor::addExperienceIds, this, _1), mKey, FALSE, TRUE, mAdd);
- picker->addFilters(mFilters.begin(), mFilters.end());
-
+ LLFloaterExperiencePicker* picker=LLFloaterExperiencePicker::show(boost::bind(&LLPanelExperienceListEditor::addExperienceIds, this, _1), mKey, FALSE, TRUE, mFilters, mAdd);
mPicker = picker->getDerivedHandle<LLFloaterExperiencePicker>();
}
}
@@ -210,7 +208,6 @@ void LLPanelExperienceListEditor::loading()
void LLPanelExperienceListEditor::setReadonly( bool val )
{
mReadonly = val;
- setCtrlsEnabled(!mReadonly);
checkButtonsEnabled();
}
diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp
new file mode 100644
index 0000000000..8da41b59dd
--- /dev/null
+++ b/indra/newview/llpanelexperiencepicker.cpp
@@ -0,0 +1,397 @@
+/**
+* @file llpanelexperiencepicker.cpp
+* @brief Implementation of llpanelexperiencepicker
+* @author dolphin@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelexperiencepicker.h"
+
+
+#include "lllineeditor.h"
+#include "llfloaterreg.h"
+#include "llscrolllistctrl.h"
+#include "llviewerregion.h"
+#include "llagent.h"
+#include "llexperiencecache.h"
+#include "llslurl.h"
+#include "llavatarnamecache.h"
+#include "llcombobox.h"
+#include "llviewercontrol.h"
+#include "llfloater.h"
+
+#define BTN_FIND "find"
+#define BTN_OK "ok_btn"
+#define BTN_CANCEL "cancel_btn"
+#define BTN_PROFILE "profile_btn"
+#define TEXT_EDIT "edit"
+#define TEXT_MATURITY "maturity"
+#define LIST_RESULTS "search_results"
+#define PANEL_SEARCH "search_panel"
+
+const static std::string columnSpace = " ";
+
+static LLPanelInjector<LLPanelExperiencePicker> t_panel_status("llpanelexperiencepicker");
+
+class LLExperienceSearchResponder : public LLHTTPClient::Responder
+{
+public:
+ LLUUID mQueryID;
+ LLHandle<LLPanelExperiencePicker> mParent;
+
+ LLExperienceSearchResponder(const LLUUID& id, const LLHandle<LLPanelExperiencePicker>& parent) : mQueryID(id), mParent(parent) { }
+
+ void completed(U32 status, const std::string& reason, const LLSD& content)
+ {
+ if (isGoodStatus(status))
+ {
+ if(mParent.isDead())
+ return;
+
+ LLPanelExperiencePicker* panel =mParent.get();
+ if (panel)
+ {
+ panel->processResponse(mQueryID, content);
+ }
+ }
+ else
+ {
+ llwarns << "experience picker failed [status:" << status << "]: " << content << llendl;
+
+ }
+ }
+};
+
+LLPanelExperiencePicker::LLPanelExperiencePicker()
+ :LLPanel()
+{
+ buildFromFile("panel_experience_search.xml");
+ setDefaultFilters();
+}
+
+LLPanelExperiencePicker::~LLPanelExperiencePicker()
+{
+}
+
+BOOL LLPanelExperiencePicker::postBuild()
+{
+ getChild<LLLineEditor>(TEXT_EDIT)->setKeystrokeCallback( boost::bind(&LLPanelExperiencePicker::editKeystroke, this, _1, _2),NULL);
+
+ childSetAction(BTN_FIND, boost::bind(&LLPanelExperiencePicker::onBtnFind, this));
+ getChildView(BTN_FIND)->setEnabled(FALSE);
+
+ LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>(LIST_RESULTS);
+ searchresults->setDoubleClickCallback( boost::bind(&LLPanelExperiencePicker::onBtnSelect, this));
+ searchresults->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onList, this));
+ getChildView(LIST_RESULTS)->setEnabled(FALSE);
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
+
+ childSetAction(BTN_OK, boost::bind(&LLPanelExperiencePicker::onBtnSelect, this));
+ getChildView(BTN_OK)->setEnabled(FALSE);
+ childSetAction(BTN_CANCEL, boost::bind(&LLPanelExperiencePicker::onBtnClose, this));
+ childSetAction(BTN_PROFILE, boost::bind(&LLPanelExperiencePicker::onBtnProfile, this));
+ getChildView(BTN_PROFILE)->setEnabled(FALSE);
+
+ getChild<LLComboBox>(TEXT_MATURITY)->setCurrentByIndex(2);
+ getChild<LLComboBox>(TEXT_MATURITY)->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onMaturity, this));
+ getChild<LLUICtrl>(TEXT_EDIT)->setFocus(TRUE);
+
+ LLPanel* search_panel = getChild<LLPanel>(PANEL_SEARCH);
+ if (search_panel)
+ {
+ // Start searching when Return is pressed in the line editor.
+ search_panel->setDefaultBtn(BTN_FIND);
+ }
+ return TRUE;
+}
+
+void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* user_data )
+{
+ getChildView(BTN_FIND)->setEnabled(caller->getText().size() > 0);
+}
+
+void LLPanelExperiencePicker::onBtnFind()
+{
+ find();
+}
+
+void LLPanelExperiencePicker::onList()
+{
+ bool enabled = isSelectButtonEnabled();
+ getChildView(BTN_OK)->setEnabled(enabled);
+
+ enabled = enabled && getChild<LLScrollListCtrl>(LIST_RESULTS)->getNumSelected() == 1;
+ getChildView(BTN_PROFILE)->setEnabled(enabled);
+}
+
+void LLPanelExperiencePicker::find()
+{
+ std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
+ mQueryID.generate();
+ std::string url;
+ url.reserve(128+text.size());
+
+ LLViewerRegion* region = gAgent.getRegion();
+ url = region->getCapability("FindExperienceByName");
+ if (!url.empty())
+ {
+ url+="?query=";
+ url+=LLURI::escape(text);
+ LLHTTPClient::get(url, new LLExperienceSearchResponder(mQueryID, getDerivedHandle<LLPanelExperiencePicker>()));
+
+ }
+
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
+
+ getChildView(BTN_OK)->setEnabled(FALSE);
+ getChildView(BTN_PROFILE)->setEnabled(FALSE);
+}
+
+
+bool LLPanelExperiencePicker::isSelectButtonEnabled()
+{
+ LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS);
+ return list->getFirstSelectedIndex() >=0;
+}
+
+void LLPanelExperiencePicker::getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids )
+{
+ std::vector<LLScrollListItem*> items = results->getAllSelected();
+ for(std::vector<LLScrollListItem*>::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ LLScrollListItem* item = *it;
+ if (item->getUUID().notNull())
+ {
+ experience_ids.push_back(item->getUUID());
+ }
+ }
+}
+
+void LLPanelExperiencePicker::setAllowMultiple( bool allow_multiple )
+{
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setAllowMultipleSelection(allow_multiple);
+}
+
+
+void name_callback(const LLHandle<LLPanelExperiencePicker>& floater, const LLUUID& experience_id, const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+ if(floater.isDead())
+ return;
+ LLPanelExperiencePicker* picker = floater.get();
+ LLScrollListCtrl* search_results = picker->getChild<LLScrollListCtrl>(LIST_RESULTS);
+
+ LLScrollListItem* item = search_results->getItem(experience_id);
+ if(!item)
+ return;
+
+ item->getColumn(2)->setValue(columnSpace+av_name.getDisplayName());
+
+}
+
+void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLSD& content )
+{
+ if(query_id != mQueryID)
+ {
+ return;
+ }
+
+ mResponse = content;
+
+ const LLSD& experiences=mResponse["experience_keys"];
+ LLSD::array_const_iterator it = experiences.beginArray();
+ for ( ; it != experiences.endArray(); ++it)
+ {
+ LLExperienceCache::insert(*it);
+ }
+
+ filterContent();
+
+}
+
+void LLPanelExperiencePicker::onBtnSelect()
+{
+ if(!isSelectButtonEnabled())
+ {
+ return;
+ }
+
+ if(mSelectionCallback)
+ {
+ const LLScrollListCtrl* results = getChild<LLScrollListCtrl>(LIST_RESULTS);
+ uuid_vec_t experience_ids;
+
+ getSelectedExperienceIds(results, experience_ids);
+ mSelectionCallback(experience_ids);
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->deselectAllItems(TRUE);
+ if(mCloseOnSelect)
+ {
+ mCloseOnSelect = FALSE;
+ onBtnClose();
+ }
+ }
+ else
+ {
+ onBtnProfile();
+ }
+}
+
+void LLPanelExperiencePicker::onBtnClose()
+{
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
+ }
+}
+
+void LLPanelExperiencePicker::onBtnProfile()
+{
+ LLScrollListItem* item = getChild<LLScrollListCtrl>(LIST_RESULTS)->getFirstSelected();
+ if(item)
+ {
+ LLFloaterReg::showInstance("experience_profile", item->getUUID(), true);
+ }
+}
+
+std::string LLPanelExperiencePicker::getMaturityString(int maturity)
+{
+ if(maturity <= SIM_ACCESS_PG)
+ {
+ return getString("maturity_icon_general");
+ }
+ else if(maturity <= SIM_ACCESS_MATURE)
+ {
+ return getString("maturity_icon_moderate");
+ }
+ return getString("maturity_icon_adult");
+}
+
+void LLPanelExperiencePicker::filterContent()
+{
+ LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>(LIST_RESULTS);
+
+ const LLSD& experiences=mResponse["experience_keys"];
+
+ search_results->deleteAllItems();
+
+ LLSD item;
+ LLSD::array_const_iterator it = experiences.beginArray();
+ for ( ; it != experiences.endArray(); ++it)
+ {
+ const LLSD& experience = *it;
+
+ if(isExperienceHidden(experience))
+ continue;
+
+ item["id"]=experience[LLExperienceCache::EXPERIENCE_ID];
+ LLSD& columns = item["columns"];
+ columns[0]["column"] = "maturity";
+ columns[0]["value"] = getMaturityString(experience[LLExperienceCache::MATURITY].asInteger());
+ columns[0]["type"]="icon";
+ columns[0]["halign"]="right";
+ columns[1]["column"] = "experience_name";
+ columns[1]["value"] = columnSpace+experience[LLExperienceCache::NAME].asString();
+ columns[2]["column"] = "owner";
+ columns[2]["value"] = columnSpace+getString("loading");
+ search_results->addElement(item);
+ LLAvatarNameCache::get(experience[LLExperienceCache::AGENT_ID], boost::bind(name_callback, getDerivedHandle<LLPanelExperiencePicker>(), experience[LLExperienceCache::EXPERIENCE_ID], _1, _2));
+ }
+
+ if (search_results->isEmpty())
+ {
+ LLStringUtil::format_map_t map;
+ std::string search_text = childGetText(TEXT_EDIT);
+ map["[TEXT]"] = search_text;
+ if (search_text.empty())
+ {
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
+ }
+ else
+ {
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("not_found", map));
+ }
+ search_results->setEnabled(false);
+ getChildView(BTN_OK)->setEnabled(false);
+ getChildView(BTN_PROFILE)->setEnabled(false);
+ }
+ else
+ {
+ getChildView(BTN_OK)->setEnabled(true);
+ search_results->setEnabled(true);
+ search_results->sortByColumnIndex(1, TRUE);
+ std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
+ if (!search_results->selectItemByLabel(text, TRUE, 1))
+ {
+ search_results->selectFirstItem();
+ }
+ onList();
+ search_results->setFocus(TRUE);
+ }
+}
+
+void LLPanelExperiencePicker::onMaturity()
+{
+ if(mResponse.has("experience_keys") && mResponse["experience_keys"].beginArray() != mResponse["experience_keys"].endArray())
+ {
+ filterContent();
+ }
+}
+
+bool LLPanelExperiencePicker::isExperienceHidden( const LLSD& experience) const
+{
+ bool hide=false;
+ filter_list::const_iterator it = mFilters.begin();
+ for(/**/;it != mFilters.end(); ++it)
+ {
+ if((*it)(experience)){
+ return true;
+ }
+ }
+
+ return hide;
+}
+
+bool LLPanelExperiencePicker::FilterOverRating( const LLSD& experience )
+{
+ int maturity = getChild<LLComboBox>(TEXT_MATURITY)->getSelectedValue().asInteger();
+ return experience[LLExperienceCache::MATURITY].asInteger() > maturity;
+}
+
+bool LLPanelExperiencePicker::FilterWithProperty( const LLSD& experience, S32 prop)
+{
+ return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) != 0;
+}
+
+bool LLPanelExperiencePicker::FilterWithoutProperty( const LLSD& experience, S32 prop )
+{
+ return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == 0;
+}
+
+void LLPanelExperiencePicker::setDefaultFilters()
+{
+ mFilters.clear();
+ addFilter(boost::bind(&LLPanelExperiencePicker::FilterOverRating, this, _1));
+}
diff --git a/indra/newview/llpanelexperiencepicker.h b/indra/newview/llpanelexperiencepicker.h
new file mode 100644
index 0000000000..af0a30ceba
--- /dev/null
+++ b/indra/newview/llpanelexperiencepicker.h
@@ -0,0 +1,91 @@
+/**
+* @file llpanelexperiencepicker.h
+* @brief Header file for llpanelexperiencepicker
+* @author dolphin@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLPANELEXPERIENCEPICKER_H
+#define LL_LLPANELEXPERIENCEPICKER_H
+
+#include "llpanel.h"
+
+class LLScrollListCtrl;
+class LLLineEditor;
+
+
+class LLPanelExperiencePicker : public LLPanel
+{
+public:
+ friend class LLExperienceSearchResponder;
+ friend class LLFloaterExperiencePicker;
+
+ typedef boost::function<void (const uuid_vec_t&)> select_callback_t;
+ // filter function for experiences, return true if the experience should be hidden.
+ typedef boost::function<bool (const LLSD&)> filter_function;
+ typedef std::vector<filter_function> filter_list;
+
+ LLPanelExperiencePicker();
+ virtual ~LLPanelExperiencePicker();
+
+ BOOL postBuild();
+
+ void addFilter(filter_function func){mFilters.push_back(func);}
+ template <class IT>
+ void addFilters(IT begin, IT end){mFilters.insert(mFilters.end(), begin, end);}
+ void setDefaultFilters();
+
+ static bool FilterWithProperty(const LLSD& experience, S32 prop);
+ static bool FilterWithoutProperty(const LLSD& experience, S32 prop);
+ bool FilterOverRating(const LLSD& experience);
+
+private:
+ void editKeystroke(LLLineEditor* caller, void* user_data);
+
+ void onBtnFind();
+ void onBtnSelect();
+ void onBtnClose();
+ void onBtnProfile();
+ void onList();
+ void onMaturity();
+
+ void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids );
+ void setAllowMultiple(bool allow_multiple);
+
+
+ void find();
+ bool isSelectButtonEnabled();
+ void processResponse( const LLUUID& query_id, const LLSD& content );
+
+ void filterContent();
+ bool isExperienceHidden(const LLSD& experience) const ;
+ std::string getMaturityString(int maturity);
+
+
+ select_callback_t mSelectionCallback;
+ filter_list mFilters;
+ LLUUID mQueryID;
+ LLSD mResponse;
+ bool mCloseOnSelect;
+};
+
+#endif // LL_LLPANELEXPERIENCEPICKER_H
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index c30c932c41..234e60d1c1 100755
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -879,7 +879,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
// Build a vector of all selected members, and gather allowed actions.
uuid_vec_t selected_members;
- U64 allowed_by_all = 0xffffffffffffLL;
+ U64 allowed_by_all = GP_ALL_POWERS; //0xFFFFffffFFFFffffLL;
U64 allowed_by_some = 0;
std::vector<LLScrollListItem*>::iterator itor;
@@ -1183,7 +1183,7 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
//add that the user is requesting to change the roles for selected
//members
- U64 powers_all_have = 0xffffffffffffLL;
+ U64 powers_all_have = GP_ALL_POWERS;
U64 powers_some_have = 0;
BOOL is_owner_role = ( gdatap->mOwnerRole == role_id );
diff --git a/indra/newview/skins/default/xui/en/floater_experience_search.xml b/indra/newview/skins/default/xui/en/floater_experience_search.xml
index 8b44dada40..7d7e3ba95a 100644
--- a/indra/newview/skins/default/xui/en/floater_experience_search.xml
+++ b/indra/newview/skins/default/xui/en/floater_experience_search.xml
@@ -12,159 +12,9 @@
title="CHOOSE EXPERIENCE"
width="350">
- <floater.string
- name="not_found">
- &apos;[TEXT]&apos; not found
- </floater.string>
- <floater.string
- name="no_results">
- No results
- </floater.string>
- <floater.string
- name="searching">
- Searching...
- </floater.string>
- <floater.string
- name="loading">
- Loading...
- </floater.string>
- <floater.string
- name="maturity_icon_general">
- "Parcel_PG_Light"
- </floater.string>
- <floater.string
- name="maturity_icon_moderate">
- "Parcel_M_Light"
- </floater.string>
- <floater.string
- name="maturity_icon_adult">
- "Parcel_R_Light"
- </floater.string>
<panel
+ filename="panel_experience_search.xml"
+ class="llpanelexperiencepicker"
follows="all"
- left="5"
- right="-3"
- bottom="-2"
- top="18"
- name="search_panel">
- <text
- left="0"
- follows="top|left|right"
- right="-1">
- Enter part of the name:
- </text>
- <line_editor
- left="0"
- follows="left|top|right"
- name="edit"
- height="18"
- right="-60"/>
- <button label="Go"
- follows="top|right"
- top_pad="-18"
- left_pad="2"
- right="-1"
- height="18"
- name="find"/>
- <text
- top_pad="6"
- left="0"
- follows="top|left"
- width="180">
- Max Content Rating:
- </text>
- <icons_combo_box
- follows="left|top"
- height="20"
- label="Moderate"
- layout="topleft"
- name="maturity"
- top_pad="-13"
- left_pad="0"
- right="-1">
- <icons_combo_box.drop_down_button
- image_overlay="Parcel_M_Light"
- image_overlay_alignment="left"
- imgoverlay_label_space="3"
- pad_left="3"/>
- <icons_combo_box.item
- label="Adult"
- name="Adult"
- value="42">
- <item.columns
- halign="center"
- type="icon"
- value="Parcel_R_Light"
- width="20"/>
- </icons_combo_box.item>
- <icons_combo_box.item
- label="Moderate"
- name="Mature"
- value="21">
- <item.columns
- halign="center"
- type="icon"
- value="Parcel_M_Light"
- width="20"/>
- </icons_combo_box.item>
- <icons_combo_box.item
- label="General"
- name="PG"
- value="13">
- <item.columns
- halign="center"
- type="icon"
- value="Parcel_PG_Light"
- width="20"/>
- </icons_combo_box.item>
- </icons_combo_box>
- <scroll_list
- draw_heading="true"
- left="0"
- right="-1"
- height="239"
- top_pad="4"
- follows="all"
- column_padding="5"
- can_resize="true"
- name="search_results">
- <columns
- halign="center"
- width="24"
- name="maturity"
- label=""/>
- <columns
- user_resize="true"
- name="experience_name"
- label="Name"/>
- <columns
- user_resize="true"
- name="owner"
- label="Owner"/>
- </scroll_list>
-
- <button
- follows="left|bottom"
- height="23"
- label="OK"
- label_selected="OK"
- name="ok_btn"
- top_pad="3"
- left="0"
- width="100" />
- <button
- follows="left|bottom"
- height="23"
- label="Cancel"
- name="cancel_btn"
- width="100"
- left_pad="3" />
- <button
- follows="left|bottom"
- height="23"
- label="View Profile"
- name="profile_btn"
- width="100"
- left_pad="3" />
- </panel>
+ name="panel_experience_search"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index f33acc75b2..a9f83e751a 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -81,13 +81,6 @@
function="Floater.ToggleOrBringToFront"
parameter="experiences"/>
</menu_item_call>
- <menu_item_call
- label="Experience Search..."
- name="Experience Search">
- <menu_item_call.on_click
- function="Floater.ToggleOrBringToFront"
- parameter="experience_search"/>
- </menu_item_call>
<menu_item_separator/>
<menu_item_call
label="Camera Controls..."
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5e966395dc..ee007197d7 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7118,6 +7118,14 @@ Scripts associated with this experience will be able to do the following on regi
<tag>confirm</tag>
<form name="form">
<button
+ index="3"
+ name="BlockExperience"
+ text="Block Experience"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block Object"/>
+ <button
index="0"
name="Yes"
text="Yes"/>
@@ -7125,14 +7133,6 @@ Scripts associated with this experience will be able to do the following on regi
index="1"
name="No"
text="No"/>
- <button
- index="2"
- name="Mute"
- text="Block Object"/>
- <button
- index="3"
- name="BlockExperience"
- text="Block Experience"/>
</form>
</notification>
diff --git a/indra/newview/skins/default/xui/en/panel_experience_search.xml b/indra/newview/skins/default/xui/en/panel_experience_search.xml
new file mode 100644
index 0000000000..5ac7f6b239
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_experience_search.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ layout="topleft"
+ top="18"
+ left="0"
+ width="350"
+ height="330"
+ label="SEARCH"
+ follows="all">
+
+ <string
+ name="not_found">
+ &apos;[TEXT]&apos; not found
+ </string>
+ <string
+ name="no_results">
+ No results
+ </string>
+ <string
+ name="searching">
+ Searching...
+ </string>
+ <string
+ name="loading">
+ Loading...
+ </string>
+ <string
+ name="maturity_icon_general">
+ "Parcel_PG_Light"
+ </string>
+ <string
+ name="maturity_icon_moderate">
+ "Parcel_M_Light"
+ </string>
+ <string
+ name="maturity_icon_adult">
+ "Parcel_R_Light"
+ </string>
+ <panel
+ follows="all"
+ left="5"
+ right="-3"
+ bottom="-2"
+ top="0"
+ name="search_panel">
+ <text
+ left="0"
+ follows="top|left|right"
+ right="-1">
+ Enter part of the name:
+ </text>
+ <line_editor
+ left="0"
+ follows="left|top|right"
+ name="edit"
+ height="18"
+ right="-60"/>
+ <button label="Go"
+ follows="top|right"
+ top_pad="-18"
+ left_pad="2"
+ right="-1"
+ height="18"
+ name="find"/>
+ <text
+ top_pad="6"
+ left="0"
+ follows="top|left"
+ width="180">
+ Max Content Rating:
+ </text>
+ <icons_combo_box
+ follows="left|top"
+ height="20"
+ label="Moderate"
+ layout="topleft"
+ name="maturity"
+ top_pad="-13"
+ left_pad="0"
+ right="-1">
+ <icons_combo_box.drop_down_button
+ image_overlay="Parcel_M_Light"
+ image_overlay_alignment="left"
+ imgoverlay_label_space="3"
+ pad_left="3"/>
+ <icons_combo_box.item
+ label="Adult"
+ name="Adult"
+ value="42">
+ <item.columns
+ halign="center"
+ type="icon"
+ value="Parcel_R_Light"
+ width="20"/>
+ </icons_combo_box.item>
+ <icons_combo_box.item
+ label="Moderate"
+ name="Mature"
+ value="21">
+ <item.columns
+ halign="center"
+ type="icon"
+ value="Parcel_M_Light"
+ width="20"/>
+ </icons_combo_box.item>
+ <icons_combo_box.item
+ label="General"
+ name="PG"
+ value="13">
+ <item.columns
+ halign="center"
+ type="icon"
+ value="Parcel_PG_Light"
+ width="20"/>
+ </icons_combo_box.item>
+ </icons_combo_box>
+ <scroll_list
+ draw_heading="true"
+ left="0"
+ right="-1"
+ height="239"
+ top_pad="4"
+ follows="all"
+ column_padding="5"
+ can_resize="true"
+ name="search_results">
+ <columns
+ halign="center"
+ width="24"
+ name="maturity"
+ label=""/>
+ <columns
+ user_resize="true"
+ name="experience_name"
+ label="Name"/>
+ <columns
+ user_resize="true"
+ name="owner"
+ label="Owner"/>
+ </scroll_list>
+
+ <button
+ follows="left|bottom"
+ height="23"
+ label="OK"
+ label_selected="OK"
+ name="ok_btn"
+ top_pad="3"
+ left="0"
+ width="100" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Cancel"
+ name="cancel_btn"
+ width="100"
+ left_pad="3" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="View Profile"
+ name="profile_btn"
+ width="100"
+ left_pad="3" />
+ </panel>
+</panel>