merge from PE's viewer-trunk

meow-7.2.2
Tofu Linden 2010-05-05 19:13:52 +01:00
commit f290e9e851
17 changed files with 451 additions and 163 deletions

View File

@ -379,6 +379,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
, mCommitOnSelectionChange(false)
, mPrevNotifyParentRect(LLRect())
, mNoItemsCommentTextbox(NULL)
, mIsConsecutiveSelection(false)
{
mBorderThickness = getBorderWidth();
@ -536,6 +537,7 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
return;
bool grab_items = false;
bool reverse = false;
pairs_list_t pairs_to_select;
// Pick out items from list between last selected and current clicked item_pair.
@ -547,6 +549,8 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
item_pair_t* cur = *iter;
if (cur == last_selected_pair || cur == item_pair)
{
// We've got reverse selection if last grabed item isn't a new selection.
reverse = grab_items && (cur != item_pair);
grab_items = !grab_items;
// Skip last selected and current clicked item pairs.
continue;
@ -562,26 +566,35 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
}
}
if (select_item)
if (reverse)
{
pairs_to_select.push_back(item_pair);
pairs_to_select.reverse();
}
pairs_to_select.push_back(item_pair);
for (pairs_iterator_t
iter = pairs_to_select.begin(),
iter_end = pairs_to_select.end();
iter != iter_end; ++iter)
{
item_pair_t* pair_to_select = *iter;
selectItemPair(pair_to_select, true);
if (isSelected(pair_to_select))
{
// Item was already selected but there is a need to keep order from last selected pair to new selection.
// Do it here to prevent extra mCommitOnSelectionChange in selectItemPair().
mSelectedItemPairs.remove(pair_to_select);
mSelectedItemPairs.push_back(pair_to_select);
}
else
{
selectItemPair(pair_to_select, true);
}
}
if (!select_item)
{
// Item was already selected but there is a need to update last selected item and its border.
// Do it here to prevent extra mCommitOnSelectionChange in selectItemPair().
mSelectedItemPairs.remove(item_pair);
mSelectedItemPairs.push_back(item_pair);
// Update last selected item border.
mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
}
return;
@ -749,6 +762,8 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
// Stretch selected item rect to ensure it won't be clipped
mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
// By default mark it as not consecutive selection
mIsConsecutiveSelection = false;
return true;
}
@ -823,6 +838,17 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti
if ( 0 == size() )
return false;
if (!mIsConsecutiveSelection)
{
// Leave only one item selected if list has not consecutive selection
if (mSelectedItemPairs.size() && !reset_selection)
{
item_pair_t* cur_sel_pair = mSelectedItemPairs.back();
resetSelection();
selectItemPair (cur_sel_pair, true);
}
}
if ( mSelectedItemPairs.size() )
{
item_pair_t* to_sel_pair = NULL;
@ -877,6 +903,8 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti
}
// Select/Deselect next item
selectItemPair(select ? to_sel_pair : cur_sel_pair, select);
// Mark it as consecutive selection
mIsConsecutiveSelection = true;
return true;
}
}
@ -888,6 +916,8 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti
selectLastItem();
else
selectFirstItem();
// Mark it as consecutive selection
mIsConsecutiveSelection = true;
return true;
}

View File

@ -410,6 +410,8 @@ private:
bool mKeepOneItemSelected;
bool mIsConsecutiveSelection;
/** All pairs of the list */
pairs_list_t mItemPairs;

View File

@ -1164,6 +1164,7 @@ void LLAgentWearables::createStandardWearablesAllDone()
mWearablesLoaded = TRUE;
checkWearablesLoaded();
mLoadedSignal();
updateServer();
@ -1567,6 +1568,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
// Start rendering & update the server
mWearablesLoaded = TRUE;
checkWearablesLoaded();
mLoadedSignal();
queryWearableCache();
updateServer();
@ -2012,6 +2014,10 @@ BOOL LLAgentWearables::areWearablesLoaded() const
void LLAgentWearables::updateWearablesLoaded()
{
mWearablesLoaded = (itemUpdatePendingCount()==0);
if (mWearablesLoaded)
{
mLoadedSignal();
}
}
bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const
@ -2091,3 +2097,8 @@ void LLAgentWearables::populateMyOutfitsFolder(void)
outfits->done();
}
}
boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_t cb)
{
return mLoadedSignal.connect(cb);
}

View File

@ -208,6 +208,17 @@ public:
BOOL itemUpdatePending(const LLUUID& item_id) const;
U32 itemUpdatePendingCount() const;
//--------------------------------------------------------------------
// Signals
//--------------------------------------------------------------------
public:
typedef boost::function<void()> loaded_callback_t;
typedef boost::signals2::signal<void()> loaded_signal_t;
boost::signals2::connection addLoadedCallback(loaded_callback_t cb);
private:
loaded_signal_t mLoadedSignal; // emitted when all agent wearables get loaded
//--------------------------------------------------------------------
// Member variables
//--------------------------------------------------------------------

View File

@ -230,6 +230,7 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); }
virtual void draw();
virtual void deleteAllChildren();

View File

@ -5525,3 +5525,67 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
/** Bridge Actions
**
********************************************************************************/
/************************************************************************/
/* Recent Inventory Panel related classes */
/************************************************************************/
void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
LLFolderBridge::buildContextMenu(menu, flags);
menuentry_vec_t disabled_items, items = getMenuItems();
items.erase(std::find(items.begin(), items.end(), std::string("New Folder")));
items.erase(std::find(items.begin(), items.end(), std::string("New Script")));
items.erase(std::find(items.begin(), items.end(), std::string("New Note")));
items.erase(std::find(items.begin(), items.end(), std::string("New Gesture")));
items.erase(std::find(items.begin(), items.end(), std::string("New Clothes")));
items.erase(std::find(items.begin(), items.end(), std::string("New Body Parts")));
hide_context_entries(menu, items, disabled_items);
}
LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
LLFolderView* root,
const LLUUID& uuid,
U32 flags /*= 0x00*/ ) const
{
LLInvFVBridge* new_listener = NULL;
switch(asset_type)
{
case LLAssetType::AT_CATEGORY:
if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
{
// *TODO: Create a link folder handler instead if it is necessary
new_listener = LLInventoryFVBridgeBuilder::createBridge(
asset_type,
actual_asset_type,
inv_type,
inventory,
root,
uuid,
flags);
break;
}
new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid);
break;
default:
new_listener = LLInventoryFVBridgeBuilder::createBridge(
asset_type,
actual_asset_type,
inv_type,
inventory,
root,
uuid,
flags);
}
return new_listener;
}
// EOF

View File

@ -349,6 +349,11 @@ protected:
void modifyOutfit(BOOL append);
void determineFolderType();
/**
* Returns a copy of current menu items.
*/
menuentry_vec_t getMenuItems() { return mItems; }
public:
static LLFolderBridge* sSelf;
static void staticFolderOptionsMenu();
@ -659,6 +664,58 @@ protected:
};
/************************************************************************/
/* Recent Inventory Panel related classes */
/************************************************************************/
class LLRecentInventoryBridgeBuilder;
/**
* Overridden version of the Inventory-Folder-View-Bridge for Folders
*/
class LLRecentItemsFolderBridge : public LLFolderBridge
{
friend class LLRecentInventoryBridgeBuilder;
public:
/**
* Creates context menu for Folders related to Recent Inventory Panel.
*
* It uses base logic and than removes from visible items "New..." menu items.
*/
/*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
protected:
LLRecentItemsFolderBridge(LLInventoryType::EType type,
LLInventoryPanel* inventory,
LLFolderView* root,
const LLUUID& uuid) :
LLFolderBridge(inventory, root, uuid)
{
mInvType = type;
}
};
/**
* Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel
*/
class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
{
/**
* Overrides FolderBridge for Recent Inventory Panel.
*
* It use base functionality for bridges other than FolderBridge.
*/
virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
LLFolderView* root,
const LLUUID& uuid,
U32 flags = 0x00) const;
};
void wear_inventory_item_on_avatar(LLInventoryItem* item);
void rez_attachment(LLViewerInventoryItem* item,

View File

@ -1001,3 +1001,30 @@ BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) co
{
return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());
}
/************************************************************************/
/* Recent Inventory Panel related class */
/************************************************************************/
class LLInventoryRecentItemsPanel;
static LLDefaultChildRegistry::Register<LLInventoryRecentItemsPanel> t_recent_inventory_panel("recent_inventory_panel");
static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER;
class LLInventoryRecentItemsPanel : public LLInventoryPanel
{
public:
struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
{};
protected:
LLInventoryRecentItemsPanel (const Params&);
friend class LLUICtrlFactory;
};
LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
: LLInventoryPanel(params)
{
// replace bridge builder to have necessary View bridges.
mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
}

View File

@ -167,7 +167,7 @@ BOOL LLPanelMainInventory::postBuild()
// Now load the stored settings from disk, if available.
std::ostringstream filterSaveName;
filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl;
llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName.str() << llendl;
llifstream file(filterSaveName.str());
LLSD savedFilterState;
if (file.is_open())
@ -492,6 +492,10 @@ void LLPanelMainInventory::onFilterSelected()
{
return;
}
BOOL recent_active = ("Recent Items" == mActivePanel->getName());
childSetVisible("add_btn_panel", !recent_active);
setFilterSubString(mFilterSubString);
LLInventoryFilter* filter = mActivePanel->getFilter();
LLFloaterInventoryFinder *finder = getFinder();

View File

@ -77,6 +77,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
{
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));
}
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
@ -190,6 +191,7 @@ void LLPanelOutfitsInventory::onWearButtonClick()
if (!isCOFPanelActive())
{
mMyOutfitsPanel->performAction("replaceoutfit");
setWearablesLoading(true);
}
else
{
@ -642,3 +644,19 @@ BOOL LLPanelOutfitsInventory::isCOFPanelActive() const
{
return (childGetVisibleTab("appearance_tabs")->getName() == COF_TAB_NAME);
}
void LLPanelOutfitsInventory::setWearablesLoading(bool val)
{
mListCommands->childSetEnabled("wear_btn", !val);
llassert(mParent);
if (mParent)
{
mParent->setWearablesLoading(val);
}
}
void LLPanelOutfitsInventory::onWearablesLoaded()
{
setWearablesLoading(false);
}

View File

@ -123,6 +123,8 @@ protected:
void onCustomAction(const LLSD& command_name);
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
bool hasItemsSelected();
void setWearablesLoading(bool val);
void onWearablesLoaded();
private:
LLPanel* mListCommands;
LLMenuGL* mMenuGearDefault;

View File

@ -439,3 +439,9 @@ void LLSidepanelAppearance::inventoryFetched()
{
mNewOutfitBtn->setEnabled(true);
}
void LLSidepanelAppearance::setWearablesLoading(bool val)
{
childSetVisible("wearables_loading_indicator", val);
childSetVisible("edit_outfit_btn", !val);
}

View File

@ -65,6 +65,7 @@ public:
void showOutfitsInventoryPanel();
void showOutfitEditPanel();
void setWearablesLoading(bool val);
private:
void onFilterEdit(const std::string& search_string);

View File

@ -6,31 +6,31 @@
label="Sort by Name"
layout="topleft"
name="SortByName">
<menu_item_check.on_click
function="ParticipantList.Sort"
parameter="sort_by_name" />
<menu_item_check.on_check
<on_check
function="ParticipantList.CheckItem"
parameter="is_sorted_by_name" />
<on_click
function="ParticipantList.Sort"
parameter="sort_by_name" />
</menu_item_check>
<menu_item_check
label="Sort by Recent Speakers"
layout="topleft"
name="SortByRecentSpeakers">
<menu_item_check.on_click
function="ParticipantList.Sort"
parameter="sort_by_recent_speakers" />
<menu_item_check.on_check
<on_check
function="ParticipantList.CheckItem"
parameter="is_sorted_by_recent_speakers" />
<on_click
function="ParticipantList.Sort"
parameter="sort_by_recent_speakers" />
</menu_item_check>
<menu_item_call
label="View Profile"
layout="topleft"
name="View Profile">
<menu_item_call.on_click
<on_click
function="Avatar.Profile" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_view_profile" />
</menu_item_call>
@ -38,9 +38,9 @@
label="Add Friend"
layout="topleft"
name="Add Friend">
<menu_item_call.on_click
<on_click
function="Avatar.AddFriend" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_add" />
</menu_item_call>
@ -48,9 +48,9 @@
label="IM"
layout="topleft"
name="IM">
<menu_item_call.on_click
<on_click
function="Avatar.IM" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_im" />
</menu_item_call>
@ -58,20 +58,19 @@
label="Call"
layout="topleft"
name="Call">
<menu_item_call.on_click
<on_click
function="Avatar.Call" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_call" />
</menu_item_call>
<menu_item_call
enabled="true"
label="Share"
layout="topleft"
name="Share">
<menu_item_call.on_click
<on_click
function="Avatar.Share" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_share" />
</menu_item_call>
@ -79,37 +78,38 @@
label="Pay"
layout="topleft"
name="Pay">
<menu_item_call.on_click
<on_click
function="Avatar.Pay" />
<menu_item_call.on_enable
<on_enable
function="ParticipantList.EnableItem"
parameter="can_pay" />
</menu_item_call>
<menu_item_separator
layout="topleft"
name="View Icons Separator" />
layout="topleft"
name="View Icons Separator" />
<menu_item_check
label="View People Icons"
name="View Icons">
<on_click
function="ToggleControl"
parameter="ParticipantListShowIcons"/>
<on_check
function="CheckControl"
parameter="ParticipantListShowIcons" />
label="View People Icons"
layout="topleft"
name="View Icons">
<on_check
function="CheckControl"
parameter="ParticipantListShowIcons" />
<on_click
function="ToggleControl"
parameter="ParticipantListShowIcons" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
layout="topleft" />
<menu_item_check
label="Block Voice"
layout="topleft"
name="Block/Unblock">
<menu_item_check.on_click
function="Avatar.BlockUnblock" />
<menu_item_check.on_check
<on_check
function="ParticipantList.CheckItem"
parameter="is_blocked" />
<menu_item_check.on_enable
<on_click
function="Avatar.BlockUnblock" />
<on_enable
function="ParticipantList.EnableItem"
parameter="can_block" />
</menu_item_check>
@ -126,71 +126,71 @@
function="ParticipantList.EnableItem"
parameter="can_mute_text" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
<menu_item_separator
layout="topleft" />
<context_menu
label="Moderator Options &gt;"
layout="topleft"
name="Moderator Options" >
<menu_item_check
label="Allow text chat"
layout="topleft"
name="AllowTextChat">
<on_check
function="ParticipantList.CheckItem"
parameter="is_allowed_text_chat" />
<on_click
function="ParticipantList.ToggleAllowTextChat" />
<on_enable
function="ParticipantList.EnableItem"
parameter="can_allow_text_chat" />
</menu_item_check>
<menu_item_separator
layout="topleft"
name="moderate_voice_separator" />
<menu_item_call
label="Mute this participant"
layout="topleft"
name="ModerateVoiceMuteSelected">
<on_click
function="ParticipantList.ModerateVoice"
parameter="selected" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Mute everyone else"
layout="topleft"
name="ModerateVoiceMuteOthers">
<on_click
function="ParticipantList.ModerateVoice"
parameter="others" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Unmute this participant"
layout="topleft"
name="ModerateVoiceUnMuteSelected">
<on_click
function="ParticipantList.ModerateVoice"
parameter="selected" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Unmute everyone else"
layout="topleft"
name="ModerateVoiceUnMuteOthers">
<on_click
function="ParticipantList.ModerateVoice"
parameter="others" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
name="Moderator Options">
<menu_item_check
label="Allow text chat"
layout="topleft"
name="AllowTextChat">
<on_check
function="ParticipantList.CheckItem"
parameter="is_allowed_text_chat" />
<on_click
function="ParticipantList.ToggleAllowTextChat" />
<on_enable
function="ParticipantList.EnableItem"
parameter="can_allow_text_chat" />
</menu_item_check>
<menu_item_separator
layout="topleft"
name="moderate_voice_separator" />
<menu_item_call
label="Mute this participant"
layout="topleft"
name="ModerateVoiceMuteSelected">
<on_click
function="ParticipantList.ModerateVoice"
parameter="selected" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Mute everyone else"
layout="topleft"
name="ModerateVoiceMuteOthers">
<on_click
function="ParticipantList.ModerateVoice"
parameter="others" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Unmute this participant"
layout="topleft"
name="ModerateVoiceUnMuteSelected">
<on_click
function="ParticipantList.ModerateVoice"
parameter="selected" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
<menu_item_call
label="Unmute everyone else"
layout="topleft"
name="ModerateVoiceUnMuteOthers">
<on_click
function="ParticipantList.ModerateVoice"
parameter="others" />
<on_enable
function="ParticipantList.EnableItem.Moderate"
parameter="can_moderate_voice" />
</menu_item_call>
</context_menu>
</context_menu>

View File

@ -207,12 +207,26 @@ Maximum 200 per group daily
name="drop_icon"
top_delta="-10"
width="72" />
<button
follows="left|top"
layout="topleft"
left="20"
top_delta="50"
height="23"
width="100"
name="open_inventory"
label="Inventory"
tool_tip="Open Inventory">
<button.init_callback
function="Button.SetFloaterToggle"
parameter="inventory"/>
</button>
<button
follows="left|top"
layout="topleft"
left="140"
name="remove_attachment"
top_delta="50"
top_delta="0"
height="18"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
@ -230,7 +244,7 @@ Maximum 200 per group daily
name="send_notice"
width="100" />
<group_drop_target
height="95"
height="75"
top="160"
left="10"
layout="topleft"

View File

@ -84,7 +84,7 @@
sort_order_setting="InventorySortOrder"
top="16"
width="288" />
<inventory_panel
<recent_inventory_panel
bg_opaque_color="DkGray2"
bg_alpha_color="DkGray2"
background_visible="true"
@ -100,62 +100,94 @@
name="Recent Items"
width="290" />
</tab_container>
<panel
background_visible="true"
<layout_stack
animate="false"
background_visible="true"
bevel_style="none"
border_size="0"
follows="left|right|bottom"
height="27"
height="25"
layout="topleft"
top_pad="-1"
orientation="horizontal"
top_pad="0"
left="10"
name="bottom_panel"
width="310">
<button
follows="bottom|left"
tool_tip="Show additional options"
height="25"
image_hover_unselected="Toolbar_Left_Over"
image_overlay="OptionsMenu_Off"
image_selected="Toolbar_Left_Selected"
image_unselected="Toolbar_Left_Off"
layout="topleft"
left="0"
name="options_gear_btn"
top="1"
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"
layout="topleft"
left_pad="1"
name="add_btn"
tool_tip="Add new item"
width="31" />
<icon
follows="bottom|left"
height="25"
image_name="Toolbar_Middle_Off"
layout="topleft"
left_pad="1"
name="dummy_icon"
width="209"
/>
<dnd_button
follows="bottom|left"
height="25"
image_hover_unselected="Toolbar_Right_Over"
image_overlay="TrashItem_Off"
image_selected="Toolbar_Right_Selected"
image_unselected="Toolbar_Right_Off"
left_pad="1"
layout="topleft"
name="trash_btn"
tool_tip="Remove selected item"
width="31"/>
</panel>
width="307">
<layout_panel
auto_resize="false"
height="25"
layout="topleft"
name="options_gear_btn_panel"
width="32">
<button
follows="bottom|left"
tool_tip="Show additional options"
height="25"
image_hover_unselected="Toolbar_Left_Over"
image_overlay="OptionsMenu_Off"
image_selected="Toolbar_Left_Selected"
image_unselected="Toolbar_Left_Off"
layout="topleft"
left="0"
name="options_gear_btn"
top="0"
width="31" />
</layout_panel>
<layout_panel
auto_resize="false"
height="25"
layout="topleft"
name="add_btn_panel"
width="32">
<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"
layout="topleft"
left="0"
name="add_btn"
tool_tip="Add new item"
top="0"
width="31" />
</layout_panel>
<layout_panel
auto_resize="true"
height="25"
layout="topleft"
name="dummy_panel"
width="212">
<icon
follows="bottom|left|right"
height="25"
image_name="Toolbar_Middle_Off"
layout="topleft"
left="0"
top="0"
name="dummy_icon"
width="211" />
</layout_panel>
<layout_panel
auto_resize="false"
height="25"
layout="topleft"
name="trash_btn_panel"
width="31">
<dnd_button
follows="bottom|left"
height="25"
image_hover_unselected="Toolbar_Right_Over"
image_overlay="TrashItem_Off"
image_selected="Toolbar_Right_Selected"
image_unselected="Toolbar_Right_Off"
left="0"
layout="topleft"
name="trash_btn"
tool_tip="Remove selected item"
top="0"
width="31"/>
</layout_panel>
</layout_stack>
</panel>

View File

@ -94,6 +94,14 @@ width="333">
name="edit_outfit_btn"
top="7"
width="30" />
<loading_indicator
follows="left|top"
height="24"
layout="topleft"
left="268"
name="wearables_loading_indicator"
top="6"
width="24" />
</panel>
<filter_editor
height="23"