merge from PE's viewer-trunk

master
Tofu Linden 2010-06-05 10:48:25 +01:00
commit 033f0dbdef
39 changed files with 594 additions and 278 deletions

View File

@ -66,8 +66,12 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
, mAutoScrolling( false )
, mAutoScrollRate( 0.f )
, mSelectedTab( NULL )
, mTabComparator( NULL )
, mNoVisibleTabsHelpText(NULL)
{
mSingleExpansion = params.single_expansion;
initNoTabsWidget(params.empty_accordion_text);
mSingleExpansion = params.single_expansion;
if(mFitParent && !mSingleExpansion)
{
llinfos << "fit_parent works best when combined with single_expansion" << llendl;
@ -78,7 +82,10 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
, mAutoScrolling( false )
, mAutoScrollRate( 0.f )
, mSelectedTab( NULL )
, mNoVisibleTabsHelpText(NULL)
{
initNoTabsWidget(LLTextBox::Params());
mSingleExpansion = false;
mFitParent = false;
LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");
@ -168,6 +175,8 @@ BOOL LLAccordionCtrl::postBuild()
}
}
updateNoTabsHelpTextVisibility();
return TRUE;
}
@ -187,8 +196,15 @@ void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
rcLocal.mRight = rcLocal.mLeft + width;
rcLocal.mTop = rcLocal.mBottom + height;
// get textbox a chance to reshape its content
mNoVisibleTabsHelpText->reshape(width, height, called_from_parent);
setRect(rcLocal);
// assume that help text is always fit accordion.
// necessary text paddings can be set via h_pad and v_pad
mNoVisibleTabsHelpText->setRect(getLocalRect());
arrange();
}
@ -359,6 +375,31 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view)
}
}
void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params)
{
LLTextBox::Params tp = tb_params;
tp.rect(getLocalRect());
mNoVisibleTabsOrigString = tp.initial_value().asString();
mNoVisibleTabsHelpText = LLUICtrlFactory::create<LLTextBox>(tp, this);
}
void LLAccordionCtrl::updateNoTabsHelpTextVisibility()
{
bool visible_exists = false;
std::vector<LLAccordionCtrlTab*>::const_iterator it = mAccordionTabs.begin();
const std::vector<LLAccordionCtrlTab*>::const_iterator it_end = mAccordionTabs.end();
for (; it != it_end; ++it)
{
if ((*it)->getVisible())
{
visible_exists = true;
break;
}
}
mNoVisibleTabsHelpText->setVisible(!visible_exists);
}
void LLAccordionCtrl::arrangeSinge()
{
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
@ -737,6 +778,20 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 1;
}
else if (info.has("child_visibility_change"))
{
BOOL new_visibility = info["child_visibility_change"];
if (new_visibility)
{
// there is at least one visible tab
mNoVisibleTabsHelpText->setVisible(FALSE);
}
else
{
// it could be the latest visible tab, check all of them
updateNoTabsHelpTextVisibility();
}
}
return LLPanel::notifyParent(info);
}
void LLAccordionCtrl::reset ()
@ -745,6 +800,28 @@ void LLAccordionCtrl::reset ()
mScrollbar->setDocPos(0);
}
void LLAccordionCtrl::sort()
{
if (!mTabComparator)
{
llwarns << "No comparator specified for sorting accordion tabs." << llendl;
return;
}
std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator));
arrange();
}
void LLAccordionCtrl::setFilterSubString(const std::string& filter_string)
{
LLStringUtil::format_map_t args;
args["[SEARCH_TERM]"] = LLURI::escape(filter_string);
std::string text = mNoVisibleTabsOrigString;
LLStringUtil::format(text, args);
mNoVisibleTabsHelpText->setValue(text);
}
S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
{
if(tab_index < 0)

View File

@ -34,6 +34,7 @@
#define LL_ACCORDIONCTRL_H
#include "llpanel.h"
#include "lltextbox.h"
#include "llscrollbar.h"
#include <vector>
@ -56,6 +57,19 @@ private:
public:
/**
* Abstract comparator for accordion tabs.
*/
class LLTabComparator
{
public:
LLTabComparator() {};
virtual ~LLTabComparator() {};
/** Returns true if tab1 < tab2, false otherwise */
virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0;
};
struct Params
: public LLInitParam::Block<Params, LLPanel::Params>
{
@ -64,10 +78,12 @@ public:
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*/
Optional<LLTextBox::Params> empty_accordion_text;
Params()
: single_expansion("single_expansion",false)
, fit_parent("fit_parent", false)
, empty_accordion_text("empty_accordion_text")
{};
};
@ -105,7 +121,18 @@ public:
void reset ();
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
void sort();
/**
* Sets filter substring as a search_term for help text when there are no any visible tabs.
*/
void setFilterSubString(const std::string& filter_string);
private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();
void arrangeSinge();
void arrangeMultiple();
@ -123,6 +150,21 @@ private:
BOOL autoScroll (S32 x, S32 y);
/**
* An adaptor for LLTabComparator
*/
struct LLComparatorAdaptor
{
LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {};
bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2)
{
return mComparator.compare(tab1, tab2);
}
const LLTabComparator& mComparator;
};
private:
LLRect mInnerRect;
LLScrollbar* mScrollbar;
@ -130,7 +172,11 @@ private:
bool mFitParent;
bool mAutoScrolling;
F32 mAutoScrollRate;
LLAccordionCtrlTab* mSelectedTab;
LLTextBox* mNoVisibleTabsHelpText;
std::string mNoVisibleTabsOrigString;
LLAccordionCtrlTab* mSelectedTab;
const LLTabComparator* mTabComparator;
};

View File

@ -409,6 +409,13 @@ void LLAccordionCtrlTab::changeOpenClose(bool is_open)
}
}
void LLAccordionCtrlTab::handleVisibilityChange(BOOL new_visibility)
{
LLUICtrl::handleVisibilityChange(new_visibility);
notifyParent(LLSD().with("child_visibility_change", new_visibility));
}
BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
{
if(mCollapsible && mHeaderVisible && mCanOpenClose)
@ -466,7 +473,7 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)
addChild(panel,0);
}
std::string LLAccordionCtrlTab::getTitle()
std::string LLAccordionCtrlTab::getTitle() const
{
LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
if (header)

View File

@ -115,7 +115,7 @@ public:
void setAccordionView(LLView* panel);
LLView* getAccordionView() { return mContainerPanel; };
std::string getTitle();
std::string getTitle() const;
// Set text and highlight substring in LLAccordionCtrlTabHeader
void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null);
@ -154,6 +154,11 @@ public:
// Call reshape after changing size
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/**
* Raises notifyParent event with "child_visibility_change" = new_visibility
*/
void handleVisibilityChange(BOOL new_visibility);
// Changes expand/collapse state and triggers expand/collapse callbacks
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);

View File

@ -306,6 +306,7 @@ set(viewer_SOURCE_FILES
llnotificationstorage.cpp
llnotificationtiphandler.cpp
lloutfitslist.cpp
lloutfitobserver.cpp
lloutputmonitorctrl.cpp
llpanelavatar.cpp
llpanelavatartag.cpp
@ -822,6 +823,7 @@ set(viewer_HEADER_FILES
llnotificationmanager.h
llnotificationstorage.h
lloutfitslist.h
lloutfitobserver.h
lloutputmonitorctrl.h
llpanelavatar.h
llpanelavatartag.h

View File

@ -203,7 +203,9 @@ LLBottomTray::~LLBottomTray()
// override effect of save_visibility=true.
// this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:
// i.g when floater changes its visibility - button changes its toggle state.
getChild<LLUICtrl>("build_btn")->setControlValue(false);
getChild<LLUICtrl>("search_btn")->setControlValue(false);
getChild<LLUICtrl>("world_map_btn")->setControlValue(false);
}
// *TODO Vadim: why void* ?

View File

@ -387,13 +387,7 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory
item_panel->childSetAction("btn_edit", mCOFCallbacks.mEditWearable);
//turning on gray separator line for the last item in the items group of the same wearable type
if (last)
{
LLRect rect = item_panel->getRect();
item_panel->reshape(rect.getWidth(), rect.getHeight() +
item_panel->getChild<LLView>("wearable_type_separator_icon")->getRect().getHeight());
item_panel->childSetVisible("wearable_type_separator_icon", true);
}
item_panel->childSetVisible("wearable_type_separator_icon", last);
return item_panel;
}
@ -427,7 +421,7 @@ LLPanelDeletableWearableListItem* LLCOFWearables::buildAttachemntListItem(LLView
llassert(item);
if (!item) return NULL;
LLPanelDeletableWearableListItem* item_panel = LLPanelDeletableWearableListItem::create(item);
LLPanelAttachmentListItem* item_panel = LLPanelAttachmentListItem::create(item);
if (!item_panel) return NULL;
//setting callbacks

View File

@ -60,8 +60,14 @@
#include "llinventorymodel.h"
#include "llrootview.h"
#include "llspeakers.h"
#include "llsidetray.h"
static const S32 RECT_PADDING_NOT_INIT = -1;
static const S32 RECT_PADDING_NEED_RECALC = -2;
S32 LLIMFloater::sAllowedRectRightPadding = RECT_PADDING_NOT_INIT;
LLIMFloater::LLIMFloater(const LLUUID& session_id)
: LLTransientDockableFloater(NULL, true, session_id),
mControlPanel(NULL),
@ -444,19 +450,44 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
return floater;
}
//static
bool LLIMFloater::resetAllowedRectPadding(const LLSD& newvalue)
{
//reset allowed rect right padding if "SidebarCameraMovement" option
//or sidebar state changed
sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC ;
return true;
}
void LLIMFloater::getAllowedRect(LLRect& rect)
{
if (sAllowedRectRightPadding == RECT_PADDING_NOT_INIT) //wasn't initialized
{
gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
LLSideTray* side_bar = LLSideTray::getInstance();
side_bar->getCollapseSignal().connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC;
}
rect = gViewerWindow->getWorldViewRectScaled();
static S32 right_padding = 0;
if (right_padding == 0)
if (sAllowedRectRightPadding == RECT_PADDING_NEED_RECALC) //recalc allowed rect right padding
{
LLPanel* side_bar_tabs =
gViewerWindow->getRootView()->getChild<LLPanel> (
"side_bar_tabs");
right_padding = side_bar_tabs->getRect().getWidth();
sAllowedRectRightPadding = side_bar_tabs->getRect().getWidth();
LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs);
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE)
{
LLSideTray* side_bar = LLSideTray::getInstance();
if (side_bar->getVisible() && !side_bar->getCollapsed())
sAllowedRectRightPadding += side_bar->getRect().getWidth();
}
}
rect.mRight -= right_padding;
rect.mRight -= sAllowedRectRightPadding;
}
void LLIMFloater::setDocked(bool docked, bool pop_on_undock)

View File

@ -155,6 +155,10 @@ private:
static void closeHiddenIMToasts();
static bool resetAllowedRectPadding(const LLSD& newvalue);
//need to keep this static for performance issues
static S32 sAllowedRectRightPadding;
static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response);
LLPanelChatControlPanel* mControlPanel;

View File

@ -177,7 +177,10 @@ protected:
void setIconImage(const LLUIImagePtr& image);
/** Set item title - inventory item name usually */
void setTitle(const std::string& title, const std::string& highlit_text);
virtual void setTitle(const std::string& title, const std::string& highlit_text);
LLViewerInventoryItem* mItem;
// force not showing link icon on item's icon
bool mForceNoLinksOnIcons;
@ -196,7 +199,6 @@ private:
/** reshape remaining widgets */
void reshapeMiddleWidgets();
LLViewerInventoryItem* mItem;
LLIconCtrl* mIconCtrl;
LLTextBox* mTitleCtrl;

View File

@ -0,0 +1,125 @@
/**
* @file lloutfitobserver.cpp
* @brief Outfit observer facade.
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llappearancemgr.h"
#include "lloutfitobserver.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
LLOutfitObserver::LLOutfitObserver() :
mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN)
{
gInventory.addObserver(this);
}
LLOutfitObserver::~LLOutfitObserver()
{
if (gInventory.containsObserver(this))
{
gInventory.removeObserver(this);
}
}
void LLOutfitObserver::changed(U32 mask)
{
if (!gInventory.isInventoryUsable())
return;
bool panel_updated = checkCOF();
if (!panel_updated)
{
checkBaseOutfit();
}
}
// static
S32 LLOutfitObserver::getCategoryVersion(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (!cat)
return LLViewerInventoryCategory::VERSION_UNKNOWN;
return cat->getVersion();
}
bool LLOutfitObserver::checkCOF()
{
LLUUID cof = LLAppearanceMgr::getInstance()->getCOF();
if (cof.isNull())
return false;
S32 cof_version = getCategoryVersion(cof);
if (cof_version == mCOFLastVersion)
return false;
mCOFLastVersion = cof_version;
LLAppearanceMgr::getInstance()->updateIsDirty();
mCOFChanged();
return true;
}
void LLOutfitObserver::checkBaseOutfit()
{
LLUUID baseoutfit_id =
LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
if (baseoutfit_id == mBaseOutfitId)
{
if (baseoutfit_id.isNull())
return;
const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id);
if (baseoutfit_ver == mBaseOutfitLastVersion)
return;
}
else
{
mBaseOutfitId = baseoutfit_id;
mBOFReplaced();
if (baseoutfit_id.isNull())
return;
mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId);
}
LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
app_mgr.updateIsDirty();
mBOFChanged();
}

View File

@ -0,0 +1,82 @@
/**
* @file lloutfitobserver.h
* @brief Outfit observer facade.
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, 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_OUTFITOBSERVER_H
#define LL_OUTFITOBSERVER_H
#include "llsingleton.h"
/**
* Outfit observer facade that provides simple possibility to subscribe on
* BOF(base outfit) replaced, BOF changed, COF(current outfit) changed events.
*/
class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver>
{
public:
virtual ~LLOutfitObserver();
friend class LLSingleton<LLOutfitObserver>;
virtual void changed(U32 mask);
typedef boost::signals2::signal<void (void)> signal_t;
void addBOFReplacedCallback(const signal_t::slot_type& cb) { mBOFReplaced.connect(cb); }
void addBOFChangedCallback(const signal_t::slot_type& cb) { mBOFChanged.connect(cb); }
void addCOFChangedCallback(const signal_t::slot_type& cb) { mCOFChanged.connect(cb); }
protected:
LLOutfitObserver();
/** Get a version of an inventory category specified by its UUID */
static S32 getCategoryVersion(const LLUUID& cat_id);
bool checkCOF();
void checkBaseOutfit();
//last version number of a COF category
S32 mCOFLastVersion;
LLUUID mBaseOutfitId;
S32 mBaseOutfitLastVersion;
private:
signal_t mBOFReplaced;
signal_t mBOFChanged;
signal_t mCOFChanged;
};
#endif /* LL_OUTFITOBSERVER_H */

View File

@ -53,6 +53,20 @@
static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y);
static const LLOutfitTabNameComparator OUTFIT_TAB_NAME_COMPARATOR;
/*virtual*/
bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const
{
std::string name1 = tab1->getTitle();
std::string name2 = tab2->getTitle();
LLStringUtil::toUpper(name1);
LLStringUtil::toUpper(name2);
return name1 < name2;
}
//////////////////////////////////////////////////////////////////////////
class OutfitContextMenu : public LLListContextMenu
@ -158,6 +172,7 @@ LLOutfitsList::~LLOutfitsList()
BOOL LLOutfitsList::postBuild()
{
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
return TRUE;
}
@ -328,7 +343,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
updateOutfitTab(*items_iter);
}
mAccordion->arrange();
mAccordion->sort();
}
void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
@ -500,6 +515,8 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
{
mAccordion->setFilterSubString(new_filter_substring);
for (outfits_map_t::iterator
iter = mOutfitsMap.begin(),
iter_end = mOutfitsMap.end();

View File

@ -32,17 +32,33 @@
#ifndef LL_LLOUTFITSLIST_H
#define LL_LLOUTFITSLIST_H
#include "llaccordionctrl.h"
#include "llpanel.h"
// newview
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
class LLAccordionCtrl;
class LLAccordionCtrlTab;
class LLWearableItemsList;
class LLListContextMenu;
/**
* @class LLOutfitTabNameComparator
*
* Comparator of outfit tabs.
*/
class LLOutfitTabNameComparator : public LLAccordionCtrl::LLTabComparator
{
LOG_CLASS(LLOutfitTabNameComparator);
public:
LLOutfitTabNameComparator() {};
virtual ~LLOutfitTabNameComparator() {};
/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;
};
/**
* @class LLOutfitsList
*

View File

@ -39,6 +39,7 @@
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "lloutfitobserver.h"
#include "llcofwearables.h"
#include "llfilteredwearablelist.h"
#include "llinventory.h"
@ -143,100 +144,6 @@ private:
}
};
class LLCOFObserver : public LLInventoryObserver
{
public:
LLCOFObserver(LLPanelOutfitEdit *panel) : mPanel(panel),
mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN)
{
gInventory.addObserver(this);
}
virtual ~LLCOFObserver()
{
if (gInventory.containsObserver(this))
{
gInventory.removeObserver(this);
}
}
virtual void changed(U32 mask)
{
if (!gInventory.isInventoryUsable()) return;
bool panel_updated = checkCOF();
if (!panel_updated)
{
checkBaseOutfit();
}
}
protected:
/** Get a version of an inventory category specified by its UUID */
static S32 getCategoryVersion(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (!cat) return LLViewerInventoryCategory::VERSION_UNKNOWN;
return cat->getVersion();
}
bool checkCOF()
{
LLUUID cof = LLAppearanceMgr::getInstance()->getCOF();
if (cof.isNull()) return false;
S32 cof_version = getCategoryVersion(cof);
if (cof_version == mCOFLastVersion) return false;
mCOFLastVersion = cof_version;
mPanel->update();
return true;
}
void checkBaseOutfit()
{
LLUUID baseoutfit_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
if (baseoutfit_id == mBaseOutfitId)
{
if (baseoutfit_id.isNull()) return;
const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id);
if (baseoutfit_ver == mBaseOutfitLastVersion) return;
}
else
{
mBaseOutfitId = baseoutfit_id;
mPanel->updateCurrentOutfitName();
if (baseoutfit_id.isNull()) return;
mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId);
}
mPanel->updateVerbs();
}
LLPanelOutfitEdit *mPanel;
//last version number of a COF category
S32 mCOFLastVersion;
LLUUID mBaseOutfitId;
S32 mBaseOutfitLastVersion;
};
class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver
{
public:
@ -277,7 +184,6 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
mSearchFilter(NULL),
mCOFWearables(NULL),
mInventoryItemsPanel(NULL),
mCOFObserver(NULL),
mGearMenu(NULL),
mCOFDragAndDropObserver(NULL),
mInitialized(false),
@ -288,7 +194,11 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
mCOFObserver = new LLCOFObserver(this);
LLOutfitObserver& observer = LLOutfitObserver::instance();
observer.addBOFReplacedCallback(boost::bind(&LLPanelOutfitEdit::updateCurrentOutfitName, this));
observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this));
observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::update, this));
mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES);
for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++)
@ -303,7 +213,6 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit()
{
delete mSavedFolderState;
delete mCOFObserver;
delete mCOFDragAndDropObserver;
delete mWearableListMaskCollector;
@ -756,9 +665,6 @@ void LLPanelOutfitEdit::updateCurrentOutfitName()
//private
void LLPanelOutfitEdit::updateVerbs()
{
//*TODO implement better handling of COF dirtiness
LLAppearanceMgr::getInstance()->updateIsDirty();
bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull();

View File

@ -49,7 +49,7 @@ class LLButton;
class LLCOFWearables;
class LLTextBox;
class LLInventoryCategory;
class LLCOFObserver;
class LLOutfitObserver;
class LLCOFDragAndDropObserver;
class LLInventoryPanel;
class LLSaveFolderState;
@ -153,7 +153,6 @@ private:
LLInventoryItemsList* mWearableItemsList;
LLPanel* mWearableItemsPanel;
LLCOFObserver* mCOFObserver;
LLCOFDragAndDropObserver* mCOFDragAndDropObserver;
std::vector<LLLookItemType> mLookItemTypes;

View File

@ -50,6 +50,7 @@
#include "lllineeditor.h"
#include "llmodaldialog.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
#include "lloutfitslist.h"
#include "llsaveoutfitcombobtn.h"
#include "llsidepanelappearance.h"
@ -204,6 +205,10 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));
LLOutfitObserver& observer = LLOutfitObserver::instance();
observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
}
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
@ -522,7 +527,7 @@ void LLPanelOutfitsInventory::updateListCommands()
mListCommands->childSetEnabled("trash_btn", trash_enabled);
mListCommands->childSetEnabled("wear_btn", wear_enabled);
mListCommands->childSetVisible("wear_btn", wear_enabled);
mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled);
mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled);
}
void LLPanelOutfitsInventory::showGearMenu()
@ -665,7 +670,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
}
if (command_name == "make_outfit")
{
return TRUE;
return LLAppearanceMgr::getInstance()->isOutfitDirty();
}
if (command_name == "edit" ||
@ -789,6 +794,7 @@ void LLPanelOutfitsInventory::onWearablesLoaded()
setWearablesLoading(false);
}
// static
LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP()
{
static LLSidepanelAppearance* panel_appearance =

View File

@ -75,7 +75,7 @@ public:
void setParent(LLSidepanelAppearance *parent);
LLFolderView* getRootFolder();
LLSidepanelAppearance* getAppearanceSP();
static LLSidepanelAppearance* getAppearanceSP();
static LLPanelOutfitsInventory* findInstance();

View File

@ -1450,6 +1450,8 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded()
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
accordion->arrange();
// *TODO: new empty_accordion_text attribute was implemented in accordion (EXT-7368).
// this code should be refactored to use it
// keep help text in a synchronization with accordions visibility.
updateFriendListHelpText();
}

View File

@ -34,6 +34,7 @@
#include "llappearancemgr.h"
#include "llpaneloutfitsinventory.h"
#include "llsidepanelappearance.h"
#include "llsaveoutfitcombobtn.h"
#include "llviewermenu.h"

View File

@ -42,6 +42,7 @@
#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
#include "llfoldervieweventlistener.h"
#include "lloutfitobserver.h"
#include "llpaneleditwearable.h"
#include "llpaneloutfitsinventory.h"
#include "llsidetray.h"
@ -73,26 +74,6 @@ private:
LLSidepanelAppearance *mPanel;
};
class LLWatchForOutfitRenameObserver : public LLInventoryObserver
{
public:
LLWatchForOutfitRenameObserver(LLSidepanelAppearance *panel) :
mPanel(panel)
{}
virtual void changed(U32 mask);
private:
LLSidepanelAppearance *mPanel;
};
void LLWatchForOutfitRenameObserver::changed(U32 mask)
{
if (mask & LABEL)
{
mPanel->refreshCurrentOutfitName();
}
}
LLSidepanelAppearance::LLSidepanelAppearance() :
LLPanel(),
mFilterSubString(LLStringUtil::null),
@ -101,12 +82,13 @@ LLSidepanelAppearance::LLSidepanelAppearance() :
mCurrOutfitPanel(NULL),
mOpened(false)
{
LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
}
LLSidepanelAppearance::~LLSidepanelAppearance()
{
gInventory.removeObserver(mOutfitRenameWatcher);
delete mOutfitRenameWatcher;
}
// virtual
@ -160,8 +142,6 @@ BOOL LLSidepanelAppearance::postBuild()
mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook");
mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this);
gInventory.addObserver(mOutfitRenameWatcher);
setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2));

View File

@ -40,7 +40,6 @@
class LLFilterEditor;
class LLCurrentlyWornFetchObserver;
class LLWatchForOutfitRenameObserver;
class LLPanelEditWearable;
class LLWearable;
class LLPanelOutfitsInventory;
@ -97,9 +96,6 @@ private:
// Used to make sure the user's inventory is in memory.
LLCurrentlyWornFetchObserver* mFetchWorn;
// Used to update title when currently worn outfit gets renamed.
LLWatchForOutfitRenameObserver* mOutfitRenameWatcher;
// Search string for filtering landmarks and teleport
// history locations
std::string mFilterSubString;

View File

@ -469,6 +469,9 @@ void LLSideTray::reflectCollapseChange()
}
gFloaterView->refresh();
LLSD new_value = mCollapsed;
mCollapseSignal(this,new_value);
}
void LLSideTray::arrange()

View File

@ -159,6 +159,8 @@ public:
void updateSidetrayVisibility();
commit_signal_t& getCollapseSignal() { return mCollapseSignal; }
protected:
LLSideTrayTab* getTab (const std::string& name);
@ -187,6 +189,8 @@ private:
child_vector_t mTabs;
LLSideTrayTab* mActiveTab;
commit_signal_t mCollapseSignal;
LLButton* mCollapseButton;
bool mCollapsed;

View File

@ -42,6 +42,7 @@
#include "llmenugl.h" // for LLContextMenu
#include "lltransutil.h"
#include "llviewerattachmenu.h"
#include "llvoavatarself.h"
class LLFindOutfitItems : public LLInventoryCollectFunctor
{
@ -258,6 +259,31 @@ BOOL LLPanelDeletableWearableListItem::postBuild()
}
// static
LLPanelAttachmentListItem* LLPanelAttachmentListItem::create(LLViewerInventoryItem* item)
{
LLPanelAttachmentListItem* list_item = NULL;
if(item)
{
list_item = new LLPanelAttachmentListItem(item);
list_item->init();
}
return list_item;
}
void LLPanelAttachmentListItem::setTitle(const std::string& title, const std::string& highlit_text)
{
std::string title_joint = title;
if (mItem && isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(mItem->getLinkedUUID()))
{
std::string joint = LLTrans::getString(gAgentAvatarp->getAttachedPointName(mItem->getLinkedUUID()));
title_joint = title + " (" + joint + ")";
}
LLPanelDeletableWearableListItem::setTitle(title_joint, highlit_text);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

View File

@ -116,6 +116,21 @@ protected:
/*virtual*/ void init();
};
/** Outfit list item for an attachment */
class LLPanelAttachmentListItem : public LLPanelDeletableWearableListItem
{
LOG_CLASS(LLPanelAttachmentListItem);
public:
static LLPanelAttachmentListItem* create(LLViewerInventoryItem* item);
virtual ~LLPanelAttachmentListItem() {};
/** Set item title. Joint name is added to the title in parenthesis */
/*virtual*/ void setTitle(const std::string& title, const std::string& highlit_text);
protected:
LLPanelAttachmentListItem(LLViewerInventoryItem* item) : LLPanelDeletableWearableListItem(item) {};
};
/**
* @class LLPanelClothingListItem
*

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="top|right|left"
height="25"
height="23"
layout="topleft"
left="0"
name="wearable_item"
@ -45,7 +45,7 @@
use_ellipses="true"
name="item_name"
text_color="white"
top="4"
top="5"
value="..."
width="359" />
<panel
@ -74,10 +74,10 @@
name="btn_edit_panel"
layout="topleft"
follows="top|right"
top="0"
top="1"
left_pad="3"
height="24"
width="27"
height="23"
width="26"
tab_stop="false">
<button
name="btn_edit"
@ -86,8 +86,8 @@
image_overlay="Edit_Wrench"
top="0"
left="0"
height="24"
width="24"
height="23"
width="23"
tab_stop="false" />
</panel>
<icon
@ -97,7 +97,7 @@
layout="bottomleft"
left="0"
name="wearable_type_separator_icon"
top="3"
top="0"
visible="true"
width="380"/>
</panel>

View File

@ -33,7 +33,7 @@
follows="top|left"
image_unselected="Toast_CloseBtn"
image_selected="Toast_CloseBtn"
top="2"
top="3"
left="0"
height="18"
width="18"
@ -56,7 +56,7 @@
use_ellipses="true"
name="item_name"
text_color="white"
top="4"
top="5"
value="..."
width="359" />
<button
@ -64,20 +64,20 @@
layout="topleft"
follows="top|right"
image_overlay="UpArrow_Off"
top="0"
top="1"
left="0"
height="24"
width="24"
height="23"
width="23"
tab_stop="false" />
<button
name="btn_move_down"
layout="topleft"
follows="top|right"
image_overlay="DownArrow_Off"
top="0"
top="1"
left_pad="3"
height="24"
width="24"
height="23"
width="23"
tab_stop="false" />
<panel
background_visible="false"
@ -107,18 +107,18 @@
follows="top|right"
top="0"
left_pad="3"
height="24"
width="27"
height="23"
width="26"
tab_stop="false">
<button
name="btn_edit"
layout="topleft"
follows="top|right"
image_overlay="Edit_Wrench"
top="0"
top="1"
left="0"
height="24"
width="24"
height="23"
width="23"
tab_stop="false" />
</panel>
<icon

View File

@ -11,7 +11,7 @@
<accordion
fit_parent="true"
follows="all"
height="200"
height="198"
layout="topleft"
left="0"
single_expansion="true"
@ -28,6 +28,7 @@
allow_select="true"
follows="all"
height="10"
item_pad="2"
layout="topleft"
left="0"
multi_select="true"
@ -43,6 +44,7 @@
allow_select="true"
follows="all"
height="10"
item_pad="2"
layout="topleft"
left="0"
multi_select="true"
@ -58,6 +60,7 @@
allow_select="true"
follows="all"
height="10"
item_pad="2"
layout="topleft"
left="0"
multi_select="true"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="top|right|left"
height="25"
height="23"
layout="topleft"
left="0"
name="deletable_wearable_item"
@ -33,7 +33,7 @@
follows="top|left"
image_unselected="Toast_CloseBtn"
image_selected="Toast_CloseBtn"
top="2"
top="3"
left="0"
height="18"
width="18"
@ -56,7 +56,7 @@
use_ellipses="true"
name="item_name"
text_color="white"
top="4"
top="5"
value="..."
width="359" />
<icon
@ -66,7 +66,7 @@
layout="bottomleft"
left="0"
name="wearable_type_separator_icon"
top="3"
top="0"
visible="true"
width="380"/>
</panel>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="top|right|left"
height="25"
height="23"
layout="topleft"
left="0"
name="dummy_clothing_item"
@ -56,8 +56,8 @@
image_overlay="AddItem_Off"
top="0"
left="0"
height="24"
width="24"
height="23"
width="23"
tab_stop="false" />
<icon
follows="left|right|top"
@ -66,7 +66,7 @@
layout="bottomleft"
left="0"
name="wearable_type_separator_icon"
top="3"
top="0"
visible="true"
width="380"/>
</panel>

View File

@ -235,7 +235,7 @@ left="0"
</panel>
<panel
follows="all"
height="408"
height="433"
layout="topleft"
left="0"
name="edit_subpanel_container"
@ -246,7 +246,7 @@ left="0"
<panel
filename="panel_edit_shape.xml"
follows="all"
height="408"
height="433"
layout="topleft"
left="0"
name="edit_shape_panel"
@ -256,7 +256,7 @@ left="0"
<panel
filename="panel_edit_skin.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_skin_panel"
@ -266,7 +266,7 @@ left="0"
<panel
filename="panel_edit_hair.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_hair_panel"
@ -276,7 +276,7 @@ left="0"
<panel
filename="panel_edit_eyes.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_eyes_panel"
@ -286,7 +286,7 @@ left="0"
<panel
filename="panel_edit_shirt.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_shirt_panel"
@ -296,7 +296,7 @@ left="0"
<panel
filename="panel_edit_pants.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_pants_panel"
@ -306,7 +306,7 @@ left="0"
<panel
filename="panel_edit_shoes.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_shoes_panel"
@ -316,7 +316,7 @@ left="0"
<panel
filename="panel_edit_socks.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_socks_panel"
@ -326,7 +326,7 @@ left="0"
<panel
filename="panel_edit_jacket.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_jacket_panel"
@ -336,7 +336,7 @@ left="0"
<panel
filename="panel_edit_skirt.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_skirt_panel"
@ -346,7 +346,7 @@ left="0"
<panel
filename="panel_edit_gloves.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_gloves_panel"
@ -356,7 +356,7 @@ left="0"
<panel
filename="panel_edit_undershirt.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_undershirt_panel"
@ -366,7 +366,7 @@ left="0"
<panel
filename="panel_edit_underpants.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_underpants_panel"
@ -376,7 +376,7 @@ left="0"
<panel
filename="panel_edit_alpha.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_alpha_panel"
@ -386,7 +386,7 @@ left="0"
<panel
filename="panel_edit_tattoo.xml"
follows="all"
height="400"
height="425"
layout="topleft"
left="0"
name="edit_tattoo_panel"
@ -394,65 +394,7 @@ left="0"
visible="false"
width="333" />
</panel>
<panel
follows="bottom|left|right"
height="25"
label="gear_buttom_panel"
layout="topleft"
left="0"
name="gear_buttom_panel"
top_pad="0"
width="333">
<button
follows="bottom|left"
tool_tip="Options"
height="25"
image_hover_unselected="Toolbar_Left_Over"
image_disabled="OptionsMenu_Disabled"
image_overlay="OptionsMenu_Off"
image_selected="Toolbar_Left_Selected"
image_unselected="Toolbar_Left_Off"
layout="topleft"
left="10"
name="friends_viewsort_btn"
top="0"
width="31" />
<button
follows="bottom|left"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="AddItem_Off"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
image_disabled="AddItem_Disabled"
layout="topleft"
left_pad="1"
name="add_btn"
tool_tip="TODO"
width="31" />
<icon
follows="bottom|left|right"
height="25"
image_name="Toolbar_Middle_Off"
layout="topleft"
left_pad="1"
name="dummy_right_icon"
width="218" >
</icon>
<button
follows="bottom|right"
height="25"
image_hover_unselected="Toolbar_Right_Over"
image_overlay="TrashItem_Off"
image_selected="Toolbar_Right_Selected"
image_unselected="Toolbar_Right_Off"
image_disabled="TrashItem_Disabled"
layout="topleft"
left_pad="1"
name="del_btn"
tool_tip="TODO"
width="31" />
</panel>
<panel
follows="bottom|left|right"
height="23"

View File

@ -256,15 +256,14 @@ It is calculated as border_size + 2*UIResizeBarOverlap
background_image="TextField_Search_Off"
enabled="true"
follows="left|right|top"
font="SansSerif"
label="Filter"
label="Filter Inventory Wearables"
layout="topleft"
left="5"
width="290"
height="25"
name="look_item_filter"
search_button_visible="true"
text_color="black"
text_pad_left="25"
visible="true"/>
</layout_panel>

View File

@ -14,6 +14,7 @@
background_visible="true"
bg_alpha_color="DkGray2"
bg_opaque_color="DkGray2"
empty_accordion_text.value="Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]."
follows="all"
height="400"
layout="topleft"

View File

@ -2,7 +2,7 @@
<panel
background_visible="true"
follows="all"
height="570"
height="610"
layout="topleft"
left="0"
min_height="350"
@ -181,7 +181,7 @@
<scroll_container
color="DkGray2"
follows="all"
height="532"
height="572"
layout="topleft"
left="9"
name="place_scroll"
@ -191,7 +191,7 @@
<panel
bg_alpha_color="DkGray2"
follows="left|top|right"
height="540"
height="580"
layout="topleft"
left="0"
min_height="300"
@ -337,21 +337,22 @@
<accordion
fit_parent="true"
follows="all"
height="223"
height="268"
layout="topleft"
single_expansion="true"
left="0"
name="advanced_info_accordion"
top_pad="10"
top_pad="5"
width="313">
<accordion_tab
height="170"
fit_panel="false"
height="175"
layout="topleft"
name="parcel_characteristics_tab"
title="Parcel">
<panel
follows="all"
height="160"
height="175"
layout="topleft"
left="0"
name="parcel_characteristics_panel"
@ -548,8 +549,8 @@
name="about_land_btn"
right="-5"
tab_stop="false"
top="138"
width="90">
top_pad="2"
width="140">
<click_callback
function="Floater.Show"
parameter="about_land" />
@ -558,7 +559,8 @@
</accordion_tab>
<accordion_tab
expanded="false"
height="150"
fit_panel="false"
height="125"
layout="topleft"
name="region_information_tab"
title="Region">
@ -677,7 +679,8 @@
name="region_info_btn"
right="-5"
tab_stop="false"
width="105">
top_pad="2"
width="180">
<click_callback
function="Floater.Show"
parameter="region_info" />
@ -686,13 +689,14 @@
</accordion_tab>
<accordion_tab
expanded="false"
height="190"
fit_panel="false"
height="180"
layout="topleft"
name="estate_information_tab"
title="Estate">
<panel
follows="all"
height="189"
height="180"
layout="topleft"
left="0"
name="estate_information_panel"
@ -775,13 +779,14 @@
</accordion_tab>
<accordion_tab
expanded="false"
height="320"
fit_panel="false"
height="290"
layout="topleft"
name="sales_tab"
title="For Sale">
<panel
follows="all"
height="300"
height="290"
layout="topleft"
left="0"
name="sales_panel"

View File

@ -111,6 +111,7 @@ width="333">
label="Filter Outfits"
max_length="300"
name="Filter"
search_button_visible="true"
top_pad="10"
width="303" />
<panel

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<accordion
height="100"
name="accordion"
width="200">
<empty_accordion_text
follows="all"
height="100"
h_pad="10"
name="no_visible_items_msg"
value="There are no visible content here."
v_pad="15"
width="200"
wrap="true "/>
</accordion>

View File

@ -4,5 +4,6 @@
name="color_swatch">
<color_swatch.caption_text name="caption"
halign="center"
follows="left|right|bottom"/>
follows="left|right|bottom"
v_pad="2"/>
</color_swatch>

View File

@ -3,7 +3,8 @@
<multiselect_text font="SansSerifSmall"/>
<caption_text text="Multiple"
halign="center"
font="SansSerifSmall"/>
font="SansSerifSmall"
v_pad="2"/>
<border bevel_style="in"/>
</texture_picker>