phoenix-firestorm/indra/newview/llinventorylistitem.cpp

527 lines
15 KiB
C++

/**
* @file llinventorylistitem.cpp
* @brief Inventory list item panel.
*
* Class LLPanelInventoryListItemBase displays inventory item as an element
* of LLInventoryItemsList.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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 "llinventorylistitem.h"
// llui
#include "lliconctrl.h"
#include "lltextbox.h"
#include "lltextutil.h"
// newview
#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
#include "llinspecttexture.h"
#include "lltooltip.h"
#include "llviewercontrol.h"
static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item");
static const S32 WIDGET_SPACING = 3;
LLPanelInventoryListItemBase::Params::Params()
: default_style("default_style"),
mismatch_style("mismatch_style"), // <FS:Ansariel> Better attachment list
worn_style("worn_style"),
hover_image("hover_image"),
selected_image("selected_image"),
separator_image("separator_image"),
item_icon("item_icon"),
item_name("item_name")
{};
LLPanelInventoryListItemBase* LLPanelInventoryListItemBase::create(LLViewerInventoryItem* item)
{
LLPanelInventoryListItemBase* list_item = NULL;
if (item)
{
const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelInventoryListItemBase>();
list_item = new LLPanelInventoryListItemBase(item, params);
list_item->initFromParams(params);
list_item->postBuild();
}
return list_item;
}
void LLPanelInventoryListItemBase::draw()
{
if (getNeedsRefresh())
{
LLViewerInventoryItem* inv_item = getItem();
if (inv_item)
{
updateItem(inv_item->getName());
}
setNeedsRefresh(false);
}
if (mHovered && mHoverImage)
{
mHoverImage->draw(getLocalRect());
}
if (mSelected && mSelectedImage)
{
mSelectedImage->draw(getLocalRect());
}
if (mSeparatorVisible && mSeparatorImage)
{
// place under bottom of listitem, using image height
// item_pad in list using the item should be >= image height
// to avoid cropping of top of the next item.
LLRect separator_rect = getLocalRect();
separator_rect.mTop = separator_rect.mBottom;
separator_rect.mBottom -= mSeparatorImage->getHeight();
F32 alpha = getCurrentTransparency();
mSeparatorImage->draw(separator_rect, UI_VERTEX_COLOR % alpha);
}
LLPanel::draw();
}
// virtual
void LLPanelInventoryListItemBase::updateItem(const std::string& name,
EItemState item_state)
{
setIconImage(mIconImage);
setTitle(name, mHighlightedText, item_state);
}
void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/)
{
LLUICtrl* ctrl = findChild<LLUICtrl>(name);
if(ctrl)
{
addWidgetToLeftSide(ctrl, show_widget);
}
}
void LLPanelInventoryListItemBase::addWidgetToLeftSide(LLUICtrl* ctrl, bool show_widget/* = true*/)
{
mLeftSideWidgets.push_back(ctrl);
setShowWidget(ctrl, show_widget);
}
void LLPanelInventoryListItemBase::addWidgetToRightSide(const std::string& name, bool show_widget/* = true*/)
{
LLUICtrl* ctrl = findChild<LLUICtrl>(name);
if(ctrl)
{
addWidgetToRightSide(ctrl, show_widget);
}
}
void LLPanelInventoryListItemBase::addWidgetToRightSide(LLUICtrl* ctrl, bool show_widget/* = true*/)
{
mRightSideWidgets.push_back(ctrl);
setShowWidget(ctrl, show_widget);
}
void LLPanelInventoryListItemBase::setShowWidget(const std::string& name, bool show)
{
LLUICtrl* widget = findChild<LLUICtrl>(name);
if(widget)
{
setShowWidget(widget, show);
}
}
void LLPanelInventoryListItemBase::setShowWidget(LLUICtrl* ctrl, bool show)
{
// Enable state determines whether widget may become visible in setWidgetsVisible()
ctrl->setEnabled(show);
}
bool LLPanelInventoryListItemBase::postBuild()
{
LLViewerInventoryItem* inv_item = getItem();
if (inv_item)
{
mIconImage = LLInventoryIcon::getIcon(inv_item->getType(), inv_item->getInventoryType(), inv_item->getFlags(), false);
updateItem(inv_item->getName());
}
setNeedsRefresh(true);
setWidgetsVisible(false);
reshapeWidgets();
return true;
}
void LLPanelInventoryListItemBase::setValue(const LLSD& value)
{
if (!value.isMap()) return;
if (!value.has("selected")) return;
mSelected = value["selected"];
}
bool LLPanelInventoryListItemBase::handleHover(S32 x, S32 y, MASK mask)
{
mHovered = true;
return LLPanel::handleHover(x, y, mask);
}
void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask)
{
mHovered = false;
LLPanel::onMouseLeave(x, y, mask);
}
const std::string& LLPanelInventoryListItemBase::getItemName() const
{
LLViewerInventoryItem* inv_item = getItem();
if (NULL == inv_item)
{
return LLStringUtil::null;
}
return inv_item->getName();
}
LLAssetType::EType LLPanelInventoryListItemBase::getType() const
{
LLViewerInventoryItem* inv_item = getItem();
if (NULL == inv_item)
{
return LLAssetType::AT_NONE;
}
return inv_item->getType();
}
LLWearableType::EType LLPanelInventoryListItemBase::getWearableType() const
{
LLViewerInventoryItem* inv_item = getItem();
if (NULL == inv_item)
{
return LLWearableType::WT_NONE;
}
return inv_item->getWearableType();
}
const std::string& LLPanelInventoryListItemBase::getDescription() const
{
LLViewerInventoryItem* inv_item = getItem();
if (NULL == inv_item)
{
return LLStringUtil::null;
}
return inv_item->getActualDescription();
}
time_t LLPanelInventoryListItemBase::getCreationDate() const
{
LLViewerInventoryItem* inv_item = getItem();
if (NULL == inv_item)
{
return 0;
}
return inv_item->getCreationDate();
}
LLViewerInventoryItem* LLPanelInventoryListItemBase::getItem() const
{
return gInventory.getItem(mInventoryItemUUID);
}
S32 LLPanelInventoryListItemBase::notify(const LLSD& info)
{
S32 rv = 0;
if(info.has("match_filter"))
{
mHighlightedText = info["match_filter"].asString();
std::string test(mTitleCtrl->getText());
LLStringUtil::toUpper(test);
if(mHighlightedText.empty() || std::string::npos != test.find(mHighlightedText))
{
rv = 0; // substring is found
}
else
{
rv = -1;
}
setNeedsRefresh(true);
}
else
{
rv = LLPanel::notify(info);
}
return rv;
}
LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem* item, const LLPanelInventoryListItemBase::Params& params)
: LLPanel(params),
mInventoryItemUUID(item ? item->getUUID() : LLUUID::null),
mIconCtrl(NULL),
mTitleCtrl(NULL),
mWidgetSpacing(WIDGET_SPACING),
mLeftWidgetsWidth(0),
mRightWidgetsWidth(0),
mNeedsRefresh(false),
mHovered(false),
mSelected(false),
mSeparatorVisible(false),
mHoverImage(params.hover_image),
mSelectedImage(params.selected_image),
mSeparatorImage(params.separator_image)
{
LLIconCtrl::Params icon_params(params.item_icon);
applyXUILayout(icon_params, this);
mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
if (!mIconCtrl)
{
LLIconCtrl::Params icon_params;
icon_params.name = "item_icon";
mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
}
if (mIconCtrl)
{
addChild(mIconCtrl);
}
else
{
LL_ERRS() << "Failed to create mIconCtrl" << LL_ENDL;
}
LLTextBox::Params text_params(params.item_name);
applyXUILayout(text_params, this);
mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params);
if (!mTitleCtrl)
{
LLTextBox::Params text_params;
text_params.name = "item_title";
mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params);
}
if (mTitleCtrl)
{
addChild(mTitleCtrl);
}
else
{
LL_ERRS() << "Failed to create mTitleCtrl" << LL_ENDL;
}
}
class WidgetVisibilityChanger
{
public:
WidgetVisibilityChanger(bool visible) : mVisible(visible){}
void operator()(LLUICtrl* widget)
{
// Disabled widgets never become visible. see LLPanelInventoryListItemBase::setShowWidget()
widget->setVisible(mVisible && widget->getEnabled());
}
private:
bool mVisible;
};
void LLPanelInventoryListItemBase::setWidgetsVisible(bool visible)
{
std::for_each(mLeftSideWidgets.begin(), mLeftSideWidgets.end(), WidgetVisibilityChanger(visible));
std::for_each(mRightSideWidgets.begin(), mRightSideWidgets.end(), WidgetVisibilityChanger(visible));
}
void LLPanelInventoryListItemBase::reshapeWidgets()
{
// disabled reshape left for now to reserve space for 'delete' button in LLPanelClothingListItem
/*reshapeLeftWidgets();*/
reshapeRightWidgets();
reshapeMiddleWidgets();
}
void LLPanelInventoryListItemBase::setIconImage(const LLUIImagePtr& image)
{
if(image)
{
mIconImage = image;
mIconCtrl->setImage(mIconImage);
}
}
// <FS:Ansariel> Better attachment list
//virtual
const LLPanelInventoryListItemBase::Params& LLPanelInventoryListItemBase::getDefaultParams() const
{
return LLUICtrlFactory::getDefaultParams<LLPanelInventoryListItemBase>();
}
// </FS:Ansariel>
void LLPanelInventoryListItemBase::setTitle(const std::string& title,
const std::string& highlit_text,
EItemState item_state)
{
mTitleCtrl->setToolTip(title);
LLStyle::Params style_params;
// <FS:Ansariel> Better attachment list
//const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelInventoryListItemBase>();
const LLPanelInventoryListItemBase::Params& params = getDefaultParams();
// </FS:Ansariel>
switch(item_state)
{
case IS_DEFAULT:
style_params = params.default_style();
break;
case IS_WORN:
style_params = params.worn_style();
break;
// <FS:Ansariel> Better attachment list
case IS_MISMATCH:
style_params = params.mismatch_style();
break;
// </FS:Ansariel>
default:;
}
LLTextUtil::textboxSetHighlightedVal(
mTitleCtrl,
style_params,
title,
highlit_text);
}
bool LLPanelInventoryListItemBase::handleToolTip( S32 x, S32 y, MASK mask)
{
const LLRect& text_box_rect = mTitleCtrl->getRect();
// <FS:Ansariel> Make inventory thumbnail tooltips work with inventory lists
static LLCachedControl<bool> showInventoryThumbnailTooltips(gSavedSettings, "FSShowInventoryThumbnailTooltips");
if (showInventoryThumbnailTooltips && text_box_rect.pointInRect(x, y))
{
if (auto inventoryItem = gInventory.getItem(mInventoryItemUUID); inventoryItem)
{
if (const LLUUID& thumbnailUUID = inventoryItem->getThumbnailUUID(); !thumbnailUUID.isNull())
{
static LLCachedControl<F32> inventoryThumbnailTooltipsDelay(gSavedSettings, "FSInventoryThumbnailTooltipsDelay");
static LLCachedControl<F32> tooltip_fast_delay(gSavedSettings, "ToolTipFastDelay");
F32 tooltipDelay = LLToolTipMgr::instance().toolTipVisible() ? tooltip_fast_delay() : inventoryThumbnailTooltipsDelay();
LLSD params;
params["thumbnail_id"] = thumbnailUUID;
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(inventoryItem->getName())
.sticky_rect(calcScreenRect())
.delay_time(tooltipDelay)
.create_callback(boost::bind(&LLInspectTextureUtil::createInventoryToolTip, _1))
.create_params(params));
return true;
}
}
}
// </FS:Ansariel>
if (text_box_rect.pointInRect(x, y) &&
mTitleCtrl->getTextPixelWidth() <= text_box_rect.getWidth())
{
return false;
}
return LLPanel::handleToolTip(x, y, mask);
}
void LLPanelInventoryListItemBase::reshapeLeftWidgets()
{
S32 widget_left = 0;
mLeftWidgetsWidth = 0;
widget_array_t::const_iterator it = mLeftSideWidgets.begin();
const widget_array_t::const_iterator it_end = mLeftSideWidgets.end();
for( ; it_end != it; ++it)
{
LLUICtrl* widget = *it;
if(!widget->getVisible())
{
continue;
}
LLRect widget_rect(widget->getRect());
widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight());
widget->setShape(widget_rect);
widget_left += widget_rect.getWidth() + getWidgetSpacing();
mLeftWidgetsWidth = widget_rect.mRight;
}
}
void LLPanelInventoryListItemBase::reshapeRightWidgets()
{
// <FS:Ansariel> Add some spacing at the right side
//S32 widget_right = getLocalRect().getWidth();
S32 widget_right = getLocalRect().getWidth() - getWidgetSpacing();
// </FS:Ansariel>
S32 widget_left = widget_right;
widget_array_t::const_reverse_iterator it = mRightSideWidgets.rbegin();
const widget_array_t::const_reverse_iterator it_end = mRightSideWidgets.rend();
for( ; it_end != it; ++it)
{
LLUICtrl* widget = *it;
if(!widget->getVisible())
{
continue;
}
LLRect widget_rect(widget->getRect());
widget_left = widget_right - widget_rect.getWidth();
widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight());
widget->setShape(widget_rect);
widget_right = widget_left - getWidgetSpacing();
}
mRightWidgetsWidth = getLocalRect().getWidth() - widget_left;
}
void LLPanelInventoryListItemBase::reshapeMiddleWidgets()
{
LLRect icon_rect(mIconCtrl->getRect());
icon_rect.setLeftTopAndSize(mLeftWidgetsWidth + getWidgetSpacing(), icon_rect.mTop,
icon_rect.getWidth(), icon_rect.getHeight());
mIconCtrl->setShape(icon_rect);
S32 name_left = icon_rect.mRight + getWidgetSpacing();
S32 name_right = getLocalRect().getWidth() - mRightWidgetsWidth - getWidgetSpacing();
LLRect name_rect(mTitleCtrl->getRect());
name_rect.set(name_left, name_rect.mTop, name_right, name_rect.mBottom);
mTitleCtrl->setShape(name_rect);
}
// EOF