phoenix-firestorm/indra/llui/lltoolbar.cpp

1595 lines
44 KiB
C++

/**
* @file lltoolbar.cpp
* @author Richard Nelson
* @brief User customizable toolbar class
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, 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 "linden_common.h"
#include <boost/foreach.hpp>
#include "lltoolbar.h"
#include "llcommandmanager.h"
#include "llmenugl.h"
#include "lltrans.h"
#include "llinventory.h"
#include "lliconctrl.h"
// uncomment this and remove the one in llui.cpp when there is an external reference to this translation unit
// thanks, MSVC!
//static LLDefaultChildRegistry::Register<LLToolBar> r1("toolbar");
namespace LLToolBarEnums
{
LLView::EOrientation getOrientation(SideType sideType)
{
LLView::EOrientation orientation = LLLayoutStack::HORIZONTAL;
if ((sideType == SIDE_LEFT) || (sideType == SIDE_RIGHT))
{
orientation = LLLayoutStack::VERTICAL;
}
return orientation;
}
}
using namespace LLToolBarEnums;
namespace LLInitParam
{
void TypeValues<ButtonType>::declareValues()
{
declare("icons_with_text", BTNTYPE_ICONS_WITH_TEXT);
declare("icons_only", BTNTYPE_ICONS_ONLY);
declare("text_only", BTNTYPE_TEXT_ONLY); // <FS:Zi> Add text only button type
}
void TypeValues<SideType>::declareValues()
{
declare("bottom", SIDE_BOTTOM);
declare("left", SIDE_LEFT);
declare("right", SIDE_RIGHT);
declare("top", SIDE_TOP);
}
// <FS:Zi> Add our alignment name to enum mappings for XUI load/save
void TypeValues<Alignment>::declareValues()
{
declare("left", ALIGN_START);
declare("top", ALIGN_START);
declare("center", ALIGN_CENTER);
declare("right", ALIGN_END);
declare("bottom", ALIGN_END);
}
// </FS:Zi>
// <FS:Zi> Add our layout name to enum mappings for XUI load/save
void TypeValues<LayoutStyle>::declareValues()
{
declare("none", LAYOUT_STYLE_NONE);
declare("equalize", LAYOUT_STYLE_EQUALIZE);
declare("fill", LAYOUT_STYLE_FILL);
}
// </FS:Zi>
}
LLToolBar::Params::Params()
: button_display_mode("button_display_mode"),
commands("command"),
side("side", SIDE_TOP),
button_icon("button_icon"),
button_icon_and_text("button_icon_and_text"),
read_only("read_only", false),
wrap("wrap", true),
pad_left("pad_left"),
pad_top("pad_top"),
pad_right("pad_right"),
pad_bottom("pad_bottom"),
pad_between("pad_between"),
min_girth("min_girth"),
// <FS:Zi> Add our button (text-only) and layout style parameters, as well as alignment settings
// button_panel("button_panel")
button_panel("button_panel"),
button("button"),
layout_style("layout_style",LLToolBarEnums::LAYOUT_STYLE_NONE),
alignment("alignment",LLToolBarEnums::ALIGN_CENTER),
max_rows("max_rows", 0)
// </FS:Zi>
{}
LLToolBar::LLToolBar(const LLToolBar::Params& p)
: LLUICtrl(p),
mReadOnly(p.read_only),
mButtonType(p.button_display_mode),
mSideType(p.side),
mWrap(p.wrap),
mNeedsLayout(false),
mModified(false),
mButtonPanel(NULL),
mCenteringStack(NULL),
mPadLeft(p.pad_left),
mPadRight(p.pad_right),
mPadTop(p.pad_top),
mPadBottom(p.pad_bottom),
mPadBetween(p.pad_between),
mMinGirth(p.min_girth),
mPopupMenuHandle(),
mRightMouseTargetButton(NULL),
mStartDragItemCallback(NULL),
mHandleDragItemCallback(NULL),
mHandleDropCallback(NULL),
mButtonAddSignal(NULL),
mButtonEnterSignal(NULL),
mButtonLeaveSignal(NULL),
mButtonRemoveSignal(NULL),
mDragAndDropTarget(false),
mCaretIcon(NULL),
// <FS:Zi> add layout style and alignment initialisation
//mCenterPanel(NULL)
mCenterPanel(NULL),
mLayoutStyle(p.layout_style),
mAlignment(p.alignment),
mMaxRows(p.max_rows)
// </FS:Zi>
{
mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_WITH_TEXT] = p.button_icon_and_text;
mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_ONLY] = p.button_icon;
mButtonParams[LLToolBarEnums::BTNTYPE_TEXT_ONLY] = p.button; // <FS:Zi> Add text only button
}
LLToolBar::~LLToolBar()
{
delete mPopupMenuHandle.get();
delete mButtonAddSignal;
delete mButtonEnterSignal;
delete mButtonLeaveSignal;
delete mButtonRemoveSignal;
}
void LLToolBar::createContextMenu()
{
if (!mPopupMenuHandle.get())
{
// Setup bindings specific to this instance for the context menu options
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit_reg;
commit_reg.add("Toolbars.EnableSetting", boost::bind(&LLToolBar::onSettingEnable, this, _2));
commit_reg.add("Toolbars.RemoveSelectedCommand", boost::bind(&LLToolBar::onRemoveSelectedCommand, this));
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_reg;
enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2));
std::string menu_xml_name; // <FS:Zi> Split menu XML files to have Horizontal and Vertical versions
// <FS:Zi> Add commit handlers for layout and alignment options in the context menu if this is a horizontal toolbar
LLView::EOrientation orientation = getOrientation(mSideType);
if(orientation == LLView::HORIZONTAL)
{
menu_xml_name="menu_toolbars_horizontal.xml";
commit_reg.add("Toolbars.SetLayoutStyle", boost::bind(&LLToolBar::onLayoutStyleChanged, this, _2));
enable_reg.add("Toolbars.CheckLayoutStyle", boost::bind(&LLToolBar::isLayoutStyle, this, _2));
}
else
{
menu_xml_name="menu_toolbars_vertical.xml";
}
commit_reg.add("Toolbars.SetAlignment", boost::bind(&LLToolBar::onAlignmentChanged, this, _2));
enable_reg.add("Toolbars.CheckAlignment", boost::bind(&LLToolBar::isAlignment, this, _2));
// </FS:Zi>
// Create the context menu
llassert(LLMenuGL::sMenuContainer != NULL);
// <FS:Zi> Load the context menu, using the previously defined XML file name
// LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_toolbars.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>(menu_xml_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
// </FS:Zi>
if (menu)
{
menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
mPopupMenuHandle = menu->getHandle();
mRemoveButtonHandle = menu->getChild<LLView>("Remove button")->getHandle();
}
else
{
LL_WARNS() << "Unable to load toolbars context menu." << LL_ENDL;
}
}
if (mRemoveButtonHandle.get())
{
// Disable/Enable the "Remove button" menu item depending on whether or not a button was clicked
mRemoveButtonHandle.get()->setEnabled(mRightMouseTargetButton != NULL);
}
}
void LLToolBar::initFromParams(const LLToolBar::Params& p)
{
// Initialize the base object
LLUICtrl::initFromParams(p);
LLView::EOrientation orientation = getOrientation(p.side);
LLLayoutStack::Params centering_stack_p;
centering_stack_p.name = "centering_stack";
centering_stack_p.rect = getLocalRect();
centering_stack_p.follows.flags = FOLLOWS_ALL;
centering_stack_p.orientation = orientation;
centering_stack_p.mouse_opaque = false;
mCenteringStack = LLUICtrlFactory::create<LLLayoutStack>(centering_stack_p);
addChild(mCenteringStack);
LLLayoutPanel::Params border_panel_p;
border_panel_p.name = "border_panel";
border_panel_p.rect = getLocalRect();
border_panel_p.auto_resize = true;
border_panel_p.user_resize = false;
border_panel_p.mouse_opaque = false;
// <FS:Zi> Add alignment options to toolbars
// mCenteringStack->addChild(LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p));
mStartCenteringPanel = LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p);
mCenteringStack->addChild(mStartCenteringPanel);
// </FS:Zi>
LLLayoutPanel::Params center_panel_p;
center_panel_p.name = "center_panel";
center_panel_p.rect = getLocalRect();
center_panel_p.auto_resize = false;
center_panel_p.user_resize = false;
center_panel_p.mouse_opaque = false;
mCenterPanel = LLUICtrlFactory::create<LLCenterLayoutPanel>(center_panel_p);
mCenteringStack->addChild(mCenterPanel);
LLPanel::Params button_panel_p(p.button_panel);
button_panel_p.rect = mCenterPanel->getLocalRect();
button_panel_p.follows.flags = FOLLOWS_BOTTOM|FOLLOWS_LEFT;
mButtonPanel = LLUICtrlFactory::create<LLPanel>(button_panel_p);
mCenterPanel->setButtonPanel(mButtonPanel);
mCenterPanel->addChild(mButtonPanel);
// <FS:Zi> Add alignment options to toolbars
// mCenteringStack->addChild(LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p));
mEndCenteringPanel = LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p);
mCenteringStack->addChild(mEndCenteringPanel);
// </FS:Zi>
BOOST_FOREACH(LLCommandId id, p.commands)
{
addCommand(id);
}
mNeedsLayout = true;
}
bool LLToolBar::addCommand(const LLCommandId& commandId, int rank)
{
LLCommand * command = LLCommandManager::instance().getCommand(commandId);
if (!command) return false;
// Create the button and do the things that don't need ordering
LLToolBarButton* button = createButton(commandId);
mButtonPanel->addChild(button);
mButtonMap.insert(std::make_pair(commandId.uuid(), button));
// Insert the command and button in the right place in their respective lists
if ((rank >= mButtonCommands.size()) || (rank == RANK_NONE))
{
// In that case, back load
mButtonCommands.push_back(command->id());
mButtons.push_back(button);
}
else
{
// Insert in place: iterate to the right spot...
std::list<LLToolBarButton*>::iterator it_button = mButtons.begin();
command_id_list_t::iterator it_command = mButtonCommands.begin();
while (rank > 0)
{
++it_button;
++it_command;
rank--;
}
// ...then insert
mButtonCommands.insert(it_command, command->id());
mButtons.insert(it_button,button);
}
mNeedsLayout = true;
updateLayoutAsNeeded();
if (mButtonAddSignal)
{
(*mButtonAddSignal)(button);
}
return true;
}
// Remove a command from the list
// Returns the rank of the command in the original list so that doing addCommand(id,rank) right after
// a removeCommand(id) would leave the list unchanged.
// Returns RANK_NONE if the command is not found in the list
int LLToolBar::removeCommand(const LLCommandId& commandId)
{
if (!hasCommand(commandId)) return RANK_NONE;
// First erase the map record
command_id_map::iterator it = mButtonMap.find(commandId.uuid());
mButtonMap.erase(it);
// Now iterate on the commands and buttons to identify the relevant records
int rank = 0;
std::list<LLToolBarButton*>::iterator it_button = mButtons.begin();
command_id_list_t::iterator it_command = mButtonCommands.begin();
while (*it_command != commandId)
{
++it_button;
++it_command;
++rank;
}
if (mButtonRemoveSignal)
{
(*mButtonRemoveSignal)(*it_button);
}
// Delete the button and erase the command and button records
delete (*it_button);
mButtonCommands.erase(it_command);
mButtons.erase(it_button);
mNeedsLayout = true;
return rank;
}
void LLToolBar::clearCommandsList()
{
// Clears the commands list
mButtonCommands.clear();
// This will clear the buttons
createButtons();
}
bool LLToolBar::hasCommand(const LLCommandId& commandId) const
{
if (commandId != LLCommandId::null)
{
command_id_map::const_iterator it = mButtonMap.find(commandId.uuid());
return (it != mButtonMap.end());
}
return false;
}
bool LLToolBar::enableCommand(const LLCommandId& commandId, bool enabled)
{
LLButton * command_button = NULL;
if (commandId != LLCommandId::null)
{
command_id_map::iterator it = mButtonMap.find(commandId.uuid());
if (it != mButtonMap.end())
{
command_button = it->second;
command_button->setEnabled(enabled);
}
}
return (command_button != NULL);
}
bool LLToolBar::stopCommandInProgress(const LLCommandId& commandId)
{
//
// Note from Leslie:
//
// This implementation was largely put in place to handle EXP-1348 which is related to
// dragging and dropping the "speak" button. The "speak" button can be in one of two
// modes, i.e., either a toggle action or a push-to-talk action. Because of this it
// responds to mouse down and mouse up in different ways, based on which behavior the
// button is currently set to obey. This was the simplest way of getting the button
// to turn off the microphone for both behaviors without risking duplicate state.
//
LLToolBarButton * command_button = NULL;
if (commandId != LLCommandId::null)
{
LLCommand* command = LLCommandManager::instance().getCommand(commandId);
llassert(command);
// If this command has an explicit function for execution stop
if (command->executeStopFunctionName().length() > 0)
{
command_id_map::iterator it = mButtonMap.find(commandId.uuid());
if (it != mButtonMap.end())
{
command_button = it->second;
llassert(command_button->mIsRunningSignal);
// Check to see if it is running
if ((*command_button->mIsRunningSignal)(command_button, command->isRunningParameters()))
{
// Trigger an additional button commit, which calls mouse down, mouse up and commit
command_button->onCommit();
}
}
}
}
return (command_button != NULL);
}
bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)
{
LLButton * command_button = NULL;
if (commandId != LLCommandId::null)
{
command_id_map::iterator it = mButtonMap.find(commandId.uuid());
if (it != mButtonMap.end())
{
command_button = it->second;
command_button->setFlashing((BOOL)(flash),(BOOL)(force_flashing));
}
}
return (command_button != NULL);
}
BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
LLRect button_panel_rect;
mButtonPanel->localRectToOtherView(mButtonPanel->getLocalRect(), &button_panel_rect, this);
BOOL handle_it_here = !mReadOnly && button_panel_rect.pointInRect(x, y);
if (handle_it_here)
{
// Determine which button the mouse was over during the click in case the context menu action
// is intended to affect the button.
mRightMouseTargetButton = NULL;
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
LLRect button_rect;
button->localRectToOtherView(button->getLocalRect(), &button_rect, this);
if (button_rect.pointInRect(x, y))
{
mRightMouseTargetButton = button;
break;
}
}
createContextMenu();
LLContextMenu * menu = (LLContextMenu *) mPopupMenuHandle.get();
if (menu)
{
menu->show(x, y);
LLMenuGL::showPopup(this, menu, x, y);
}
}
return handle_it_here;
}
BOOL LLToolBar::isSettingChecked(const LLSD& userdata)
{
BOOL retval = FALSE;
const std::string setting_name = userdata.asString();
if (setting_name == "icons_with_text")
{
retval = (mButtonType == BTNTYPE_ICONS_WITH_TEXT);
}
else if (setting_name == "icons_only")
{
retval = (mButtonType == BTNTYPE_ICONS_ONLY);
}
// <FS:Zi> Add text only buttons
else if (setting_name == "text_only")
{
retval = (mButtonType == BTNTYPE_TEXT_ONLY);
}
// </FS:Zi>
return retval;
}
void LLToolBar::onSettingEnable(const LLSD& userdata)
{
llassert(!mReadOnly);
const std::string setting_name = userdata.asString();
if (setting_name == "icons_with_text")
{
setButtonType(BTNTYPE_ICONS_WITH_TEXT);
}
else if (setting_name == "icons_only")
{
setButtonType(BTNTYPE_ICONS_ONLY);
}
// <FS:Zi> Add text only buttons
else if (setting_name == "text_only")
{
setButtonType(BTNTYPE_TEXT_ONLY);
}
// </FS:Zi>
}
void LLToolBar::onRemoveSelectedCommand()
{
llassert(!mReadOnly);
if (mRightMouseTargetButton)
{
removeCommand(mRightMouseTargetButton->getCommandId());
mRightMouseTargetButton = NULL;
}
}
void LLToolBar::setButtonType(LLToolBarEnums::ButtonType button_type)
{
bool regenerate_buttons = (mButtonType != button_type);
mButtonType = button_type;
if (regenerate_buttons)
{
createButtons();
}
}
void LLToolBar::resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row, S32 max_row_girth)
{
// make buttons in current row all same girth
BOOST_FOREACH(LLToolBarButton* button, buttons_in_row)
{
if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)
{
button->reshape(button->mWidthRange.clamp(button->getRect().getWidth()), max_row_girth);
}
else // VERTICAL
{
button->reshape(max_row_girth, button->getRect().getHeight());
}
}
}
// Returns the position of the coordinates as a rank in the button list.
// The rank is the position a tool dropped in (x,y) would assume in the button list.
// The returned value is between 0 and mButtons.size(), 0 being the first element to the left
// (or top) and mButtons.size() the last one to the right (or bottom).
// Various drag data are stored in the toolbar object though are not exposed outside (and shouldn't).
int LLToolBar::getRankFromPosition(S32 x, S32 y)
{
if (mButtons.empty())
{
return RANK_NONE;
}
int rank = 0;
// Convert the toolbar coord into button panel coords
LLView::EOrientation orientation = getOrientation(mSideType);
S32 button_panel_x = 0;
S32 button_panel_y = 0;
localPointToOtherView(x, y, &button_panel_x, &button_panel_y, mButtonPanel);
S32 dx = x - button_panel_x;
S32 dy = y - button_panel_y;
// Simply compare the passed coord with the buttons outbound box + padding
std::list<LLToolBarButton*>::iterator it_button = mButtons.begin();
std::list<LLToolBarButton*>::iterator end_button = mButtons.end();
LLRect button_rect;
while (it_button != end_button)
{
button_rect = (*it_button)->getRect();
S32 point_x = button_rect.mRight + mPadRight;
S32 point_y = button_rect.mBottom - mPadBottom;
if ((button_panel_x < point_x) && (button_panel_y > point_y))
{
break;
}
rank++;
++it_button;
}
// Update the passed coordinates to the hit button relevant corner
// (different depending on toolbar orientation)
if (rank < mButtons.size())
{
if (orientation == LLLayoutStack::HORIZONTAL)
{
// Horizontal
S32 mid_point = (button_rect.mRight + button_rect.mLeft) / 2;
if (button_panel_x < mid_point)
{
mDragx = button_rect.mLeft - mPadLeft;
mDragy = button_rect.mTop + mPadTop;
}
else
{
rank++;
mDragx = button_rect.mRight + mPadRight - 1;
mDragy = button_rect.mTop + mPadTop;
}
}
else
{
// Vertical
S32 mid_point = (button_rect.mTop + button_rect.mBottom) / 2;
if (button_panel_y > mid_point)
{
mDragx = button_rect.mLeft - mPadLeft;
mDragy = button_rect.mTop + mPadTop;
}
else
{
rank++;
mDragx = button_rect.mLeft - mPadLeft;
mDragy = button_rect.mBottom - mPadBottom + 1;
}
}
}
else
{
// We hit passed the end of the list so put the insertion point at the end
if (orientation == LLLayoutStack::HORIZONTAL)
{
mDragx = button_rect.mRight + mPadRight;
mDragy = button_rect.mTop + mPadTop;
}
else
{
mDragx = button_rect.mLeft - mPadLeft;
mDragy = button_rect.mBottom - mPadBottom;
}
}
// Update the "girth" of the caret, i.e. the width or height (depending of orientation)
if (orientation == LLLayoutStack::HORIZONTAL)
{
mDragGirth = button_rect.getHeight() + mPadBottom + mPadTop;
}
else
{
mDragGirth = button_rect.getWidth() + mPadLeft + mPadRight;
}
// The delta account for the coord model change (i.e. convert back to toolbar coord)
mDragx += dx;
mDragy += dy;
return rank;
}
int LLToolBar::getRankFromPosition(const LLCommandId& id)
{
if (!hasCommand(id))
{
return RANK_NONE;
}
int rank = 0;
std::list<LLToolBarButton*>::iterator it_button = mButtons.begin();
std::list<LLToolBarButton*>::iterator end_button = mButtons.end();
while (it_button != end_button)
{
if ((*it_button)->mId == id)
{
break;
}
rank++;
++it_button;
}
return rank;
}
void LLToolBar::updateLayoutAsNeeded()
{
if (!mNeedsLayout) return;
LLView::EOrientation orientation = getOrientation(mSideType);
// our terminology for orientation-agnostic layout is such that
// length refers to a distance in the direction we stack the buttons
// and girth refers to a distance in the direction buttons wrap
S32 max_row_girth = 0;
S32 max_row_length = 0;
S32 max_length;
S32 cur_start;
S32 cur_row ;
S32 row_pad_start;
S32 row_pad_end;
S32 girth_pad_end;
S32 row_running_length;
if (orientation == LLLayoutStack::HORIZONTAL)
{
max_length = getRect().getWidth() - mPadLeft - mPadRight;
row_pad_start = mPadLeft;
row_pad_end = mPadRight;
cur_row = mPadTop;
girth_pad_end = mPadBottom;
}
else // VERTICAL
{
max_length = getRect().getHeight() - mPadTop - mPadBottom;
row_pad_start = mPadTop;
row_pad_end = mPadBottom;
cur_row = mPadLeft;
girth_pad_end = mPadRight;
}
row_running_length = row_pad_start;
cur_start = row_pad_start;
LLRect panel_rect = mButtonPanel->getLocalRect();
std::vector<LLToolBarButton*> buttons_in_row;
// <FS:Zi> Add equalized and fill layout options
S32 full_screen_width = max_length;
S32 equalized_width = 0;
if (mLayoutStyle == LAYOUT_STYLE_FILL)
{
if (mButtons.size())
{
equalized_width = (full_screen_width - mPadBetween * (mButtons.size() + 1)) / mButtons.size();
}
}
else if (mLayoutStyle == LAYOUT_STYLE_EQUALIZE)
{
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
S32 width = button->getInitialWidth();
if (width > equalized_width)
{
equalized_width = width;
}
}
S32 total_button_width = mButtons.size() * equalized_width + (mButtons.size() + 1) * mPadBetween;
if (mMaxRows > 0 && orientation == LLLayoutStack::HORIZONTAL && total_button_width > full_screen_width)
{
S32 buttons_per_row = llceil((F32)mButtons.size() / (F32)mMaxRows);
equalized_width = (full_screen_width - mPadBetween * (buttons_per_row + 1)) / buttons_per_row;
}
}
// </FS:Zi>
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
// <FS:Zi> Add equalized and fill layout options
// button->reshape(button->mWidthRange.getMin(), button->mDesiredHeight);
if (equalized_width)
{
if (button->mWidthRange.getMin() > equalized_width)
{
button->mWidthRange.setRange(equalized_width, equalized_width);
}
else
{
button->mWidthRange.setRange(button->mWidthRange.getMin(), equalized_width);
}
button->reshape(equalized_width, button->mDesiredHeight);
}
else
{
button->reshape(button->mWidthRange.getMin(), button->mDesiredHeight);
}
// </FS:Zi>
button->autoResize();
// <FS:Zi> Add equalized and fill layout options
// button_clamped_width = button->mWidthRange.clamp(button->getRect().getWidth());
S32 button_clamped_width;
if (equalized_width)
{
button_clamped_width = equalized_width;
}
else
{
button_clamped_width = button->mWidthRange.clamp(button->getRect().getWidth());
}
// </FS:Zi>
S32 button_length = (orientation == LLLayoutStack::HORIZONTAL)
? button_clamped_width
: button->getRect().getHeight();
S32 button_girth = (orientation == LLLayoutStack::HORIZONTAL)
? button->getRect().getHeight()
: button_clamped_width;
// wrap if needed
if (mWrap
&& mLayoutStyle != LAYOUT_STYLE_FILL // <FS:Zi> Don't wrap in fill layout mode
&& row_running_length + button_length > max_length // out of room...
&& cur_start != row_pad_start) // ...and not first button in row
{
if (orientation == LLLayoutStack::VERTICAL)
{ // row girth (width in this case) is clamped to allowable button widths
max_row_girth = button->mWidthRange.clamp(max_row_girth);
}
// make buttons in current row all same girth
resizeButtonsInRow(buttons_in_row, max_row_girth);
buttons_in_row.clear();
max_row_length = llmax(max_row_length, row_running_length);
row_running_length = row_pad_start;
cur_start = row_pad_start;
cur_row += max_row_girth + mPadBetween;
max_row_girth = 0;
}
LLRect button_rect;
if (orientation == LLLayoutStack::HORIZONTAL)
{
button_rect.setLeftTopAndSize(cur_start, panel_rect.mTop - cur_row, button_clamped_width, button->getRect().getHeight());
}
else // VERTICAL
{
button_rect.setLeftTopAndSize(cur_row, panel_rect.mTop - cur_start, button_clamped_width, button->getRect().getHeight());
}
button->setShape(button_rect);
buttons_in_row.push_back(button);
row_running_length += button_length + mPadBetween;
cur_start = row_running_length;
max_row_girth = llmax(button_girth, max_row_girth);
}
// final resizing in "girth" direction
S32 total_girth = cur_row // current row position...
+ max_row_girth // ...incremented by size of final row...
+ girth_pad_end; // ...plus padding reserved on end
total_girth = llmax(total_girth,mMinGirth);
max_row_length = llmax(max_row_length, row_running_length - mPadBetween + row_pad_end);
// <FS:Zi> Add equalized and fill layout options
// resizeButtonsInRow(buttons_in_row, max_row_girth);
if (!equalized_width)
{
resizeButtonsInRow(buttons_in_row, max_row_girth);
}
// </FS:Zi>
// grow and optionally shift toolbar to accommodate buttons
if (orientation == LLLayoutStack::HORIZONTAL)
{
if (mSideType == SIDE_TOP)
{ // shift down to maintain top edge
translate(0, getRect().getHeight() - total_girth);
}
reshape(getRect().getWidth(), total_girth);
mButtonPanel->reshape(max_row_length, total_girth);
}
else // VERTICAL
{
if (mSideType == SIDE_RIGHT)
{ // shift left to maintain right edge
translate(getRect().getWidth() - total_girth, 0);
}
reshape(total_girth, getRect().getHeight());
mButtonPanel->reshape(total_girth, max_row_length);
}
// make parent fit button panel
mButtonPanel->getParent()->setShape(mButtonPanel->getLocalRect());
// re-center toolbar buttons
mCenteringStack->updateLayout();
// <FS:Zi> Apply alignment settings
if (mAlignment == ALIGN_CENTER)
{
mStartCenteringPanel->setVisible(TRUE);
mEndCenteringPanel->setVisible(TRUE);
}
else if (mAlignment == ALIGN_START)
{
mStartCenteringPanel->setVisible(FALSE);
mEndCenteringPanel->setVisible(TRUE);
}
else if (mAlignment == ALIGN_END)
{
mStartCenteringPanel->setVisible(TRUE);
mEndCenteringPanel->setVisible(FALSE);
}
// <FS:Zi>
// <FS:KC> Fix for bad edge snapping
if (mSideType == SIDE_BOTTOM)
{
gFloaterView->setSnapOffsetBottom(mButtons.empty() ? 0 : getRect().getHeight());
}
else if (mSideType == SIDE_LEFT)
{
gFloaterView->setSnapOffsetLeft(mButtons.empty() ? 0 : getRect().getWidth());
}
else if (mSideType == SIDE_RIGHT)
{
gFloaterView->setSnapOffsetRight(mButtons.empty() ? 0 : getRect().getWidth());
}
// </FS:KC> Fix for bad edge snapping
if (!mButtons.empty())
{
mButtonPanel->setVisible(TRUE);
mButtonPanel->setMouseOpaque(TRUE);
}
// don't clear flag until after we've resized ourselves, to avoid laying out every frame
mNeedsLayout = false;
}
void LLToolBar::draw()
{
if (mButtons.empty())
{
mButtonPanel->setVisible(FALSE);
mButtonPanel->setMouseOpaque(FALSE);
}
else
{
mButtonPanel->setVisible(TRUE);
mButtonPanel->setMouseOpaque(TRUE);
}
// Update enable/disable state and highlight state for editable toolbars
if (!mReadOnly)
{
for (toolbar_button_list::iterator btn_it = mButtons.begin(); btn_it != mButtons.end(); ++btn_it)
{
LLToolBarButton* btn = *btn_it;
LLCommand* command = LLCommandManager::instance().getCommand(btn->mId);
if (command && btn->mIsEnabledSignal)
{
const bool button_command_enabled = (*btn->mIsEnabledSignal)(btn, command->isEnabledParameters());
btn->setEnabled(button_command_enabled);
}
if (command && btn->mIsRunningSignal)
{
const bool button_command_running = (*btn->mIsRunningSignal)(btn, command->isRunningParameters());
btn->setToggleState(button_command_running);
}
}
}
updateLayoutAsNeeded();
// rect may have shifted during layout
LLUI::popMatrix();
LLUI::pushMatrix();
LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom);
// Position the caret
if (!mCaretIcon)
{
mCaretIcon = getChild<LLIconCtrl>("caret");
}
LLIconCtrl* caret = mCaretIcon;
caret->setVisible(FALSE);
if (mDragAndDropTarget && !mButtonCommands.empty())
{
LLRect caret_rect = caret->getRect();
if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)
{
caret->setRect(LLRect(mDragx-caret_rect.getWidth()/2+1,
mDragy,
mDragx+caret_rect.getWidth()/2+1,
mDragy-mDragGirth));
}
else
{
caret->setRect(LLRect(mDragx,
mDragy+caret_rect.getHeight()/2,
mDragx+mDragGirth,
mDragy-caret_rect.getHeight()/2));
}
caret->setVisible(TRUE);
}
LLUICtrl::draw();
caret->setVisible(FALSE);
mDragAndDropTarget = false;
}
void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLUICtrl::reshape(width, height, called_from_parent);
mNeedsLayout = true;
}
void LLToolBar::createButtons()
{
std::set<LLUUID> set_flashing;
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
if (button->getFlashTimer() && button->getFlashTimer()->isFlashingInProgress())
{
set_flashing.insert(button->getCommandId().uuid());
}
if (mButtonRemoveSignal)
{
(*mButtonRemoveSignal)(button);
}
delete button;
}
mButtons.clear();
mButtonMap.clear();
mRightMouseTargetButton = NULL;
BOOST_FOREACH(LLCommandId& command_id, mButtonCommands)
{
LLToolBarButton* button = createButton(command_id);
mButtons.push_back(button);
mButtonPanel->addChild(button);
mButtonMap.insert(std::make_pair(command_id.uuid(), button));
if (mButtonAddSignal)
{
(*mButtonAddSignal)(button);
}
if (set_flashing.find(button->getCommandId().uuid()) != set_flashing.end())
{
button->setFlashing(true);
}
}
mNeedsLayout = true;
}
void LLToolBarButton::callIfEnabled(LLUICtrl::commit_callback_t commit, LLUICtrl* ctrl, const LLSD& param )
{
LLCommand* command = LLCommandManager::instance().getCommand(mId);
if (!mIsEnabledSignal || (*mIsEnabledSignal)(this, command->isEnabledParameters()))
{
commit(ctrl, param);
}
}
LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
{
LLCommand* commandp = LLCommandManager::instance().getCommand(id);
if (!commandp) return NULL;
LLToolBarButton::Params button_p;
button_p.name = commandp->name();
button_p.label = LLTrans::getString(commandp->labelRef());
button_p.tool_tip = LLTrans::getString(commandp->tooltipRef());
// <FS:Zi> Add control_variable and checkbox_control to commands in toolbar if it's not read-only
if (!mReadOnly)
{
if (!commandp->controlVariableName().empty())
{
// set up button's control name and make it a toggle, so it works properly
button_p.control_name = commandp->controlVariableName();
button_p.is_toggle = TRUE;
}
if (!commandp->checkboxControlVariableName().empty())
{
button_p.checkbox_control = commandp->checkboxControlVariableName();
}
}
// </FS:Zi>
// <FS:Zi> Do not add an icon if we are using text only buttons
// button_p.image_overlay = LLUI::getUIImage(commandp->icon());
if (mButtonType != BTNTYPE_TEXT_ONLY)
{
button_p.image_overlay = LLUI::getUIImage(commandp->icon());
}
// </FS:Zi>
button_p.button_flash_enable = commandp->isFlashingAllowed();
button_p.overwriteFrom(mButtonParams[mButtonType]);
LLToolBarButton* button = LLUICtrlFactory::create<LLToolBarButton>(button_p);
if (!mReadOnly)
{
enable_callback_t isEnabledCB;
const std::string& isEnabledFunction = commandp->isEnabledFunctionName();
if (isEnabledFunction.length() > 0)
{
LLUICtrl::EnableCallbackParam isEnabledParam;
isEnabledParam.function_name = isEnabledFunction;
isEnabledParam.parameter = commandp->isEnabledParameters();
isEnabledCB = initEnableCallback(isEnabledParam);
if (NULL == button->mIsEnabledSignal)
{
button->mIsEnabledSignal = new enable_signal_t();
}
button->mIsEnabledSignal->connect(isEnabledCB);
}
LLUICtrl::CommitCallbackParam executeParam;
executeParam.function_name = commandp->executeFunctionName();
executeParam.parameter = commandp->executeParameters();
// If we have a "stop" function then we map the command to mouse down / mouse up otherwise commit
const std::string& executeStopFunction = commandp->executeStopFunctionName();
if (executeStopFunction.length() > 0)
{
LLUICtrl::CommitCallbackParam executeStopParam;
executeStopParam.function_name = executeStopFunction;
executeStopParam.parameter = commandp->executeStopParameters();
LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam);
button->setFunctionName(commandp->executeFunctionName());
LL_DEBUGS("UIUsage") << "button function name a -> " << commandp->executeFunctionName() << LL_ENDL;
LLUICtrl::commit_callback_t stop_func = initCommitCallback(executeStopParam);
button->setMouseDownCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2));
button->setMouseUpCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, stop_func, _1, _2));
}
else
{
button->setFunctionName(commandp->executeFunctionName());
LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL; // <FS:Ansariel> Check enabled state of button before executing!
//button->setCommitCallback(executeParam);
LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam);
button->setCommitCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2));
// </FS:Ansariel>
}
// Set up "is running" query callback
const std::string& isRunningFunction = commandp->isRunningFunctionName();
if (isRunningFunction.length() > 0)
{
LLUICtrl::EnableCallbackParam isRunningParam;
isRunningParam.function_name = isRunningFunction;
isRunningParam.parameter = commandp->isRunningParameters();
enable_signal_t::slot_type isRunningCB = initEnableCallback(isRunningParam);
if (NULL == button->mIsRunningSignal)
{
button->mIsRunningSignal = new enable_signal_t();
}
button->mIsRunningSignal->connect(isRunningCB);
}
}
// Drag and drop behavior must work also if provided in the Toybox and, potentially, any read-only toolbar
button->setStartDragCallback(mStartDragItemCallback);
button->setHandleDragCallback(mHandleDragItemCallback);
button->setCommandId(id);
return button;
}
boost::signals2::connection connectSignal(LLToolBar::button_signal_t*& signal, const LLToolBar::button_signal_t::slot_type& cb)
{
if (!signal)
{
signal = new LLToolBar::button_signal_t();
}
return signal->connect(cb);
}
boost::signals2::connection LLToolBar::setButtonAddCallback(const button_signal_t::slot_type& cb)
{
return connectSignal(mButtonAddSignal, cb);
}
boost::signals2::connection LLToolBar::setButtonEnterCallback(const button_signal_t::slot_type& cb)
{
return connectSignal(mButtonEnterSignal, cb);
}
boost::signals2::connection LLToolBar::setButtonLeaveCallback(const button_signal_t::slot_type& cb)
{
return connectSignal(mButtonLeaveSignal, cb);
}
boost::signals2::connection LLToolBar::setButtonRemoveCallback(const button_signal_t::slot_type& cb)
{
return connectSignal(mButtonRemoveSignal, cb);
}
BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
// If we have a drop callback, that means that we can handle the drop
BOOL handled = (mHandleDropCallback ? TRUE : FALSE);
// if drop is set, it's time to call the callback to get the operation done
if (handled && drop)
{
handled = mHandleDropCallback(cargo_data, x, y ,this);
}
// We accept only single tool drop on toolbars
*accept = (handled ? ACCEPT_YES_SINGLE : ACCEPT_NO);
// We'll use that flag to change the visual aspect of the toolbar target on draw()
mDragAndDropTarget = false;
// Convert drag position into insert position and rank
if (!isReadOnly() && handled && !drop)
{
if (cargo_type == DAD_WIDGET)
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
LLCommandId dragged_command(inv_item->getUUID());
int orig_rank = getRankFromPosition(dragged_command);
mDragRank = getRankFromPosition(x, y);
// Don't DaD if we're dragging a command on itself
mDragAndDropTarget = ((orig_rank != RANK_NONE) && ((mDragRank == orig_rank) || ((mDragRank-1) == orig_rank)) ? false : true);
//LL_INFOS() << "Merov debug : DaD, rank = " << mDragRank << ", dragged uui = " << inv_item->getUUID() << LL_ENDL;
/* Do the following if you want to animate the button itself
LLCommandId dragged_command(inv_item->getUUID());
removeCommand(dragged_command);
addCommand(dragged_command,rank);
*/
}
else
{
handled = FALSE;
}
}
return handled;
}
LLToolBarButton::LLToolBarButton(const Params& p)
: LLButton(p),
mMouseDownX(0),
mMouseDownY(0),
mWidthRange(p.button_width),
mDesiredHeight(p.desired_height),
mId(""),
mIsEnabledSignal(NULL),
mIsRunningSignal(NULL),
mIsStartingSignal(NULL),
mIsDragged(false),
mStartDragItemCallback(NULL),
mHandleDragItemCallback(NULL),
mOriginalImageSelected(p.image_selected),
mOriginalImageUnselected(p.image_unselected),
mOriginalImagePressed(p.image_pressed),
mOriginalImagePressedSelected(p.image_pressed_selected),
mOriginalLabelColor(p.label_color),
mOriginalLabelColorSelected(p.label_color_selected),
mOriginalImageOverlayColor(p.image_overlay_color),
// <FS:Zi> Added initial width initialisation
// mOriginalImageOverlaySelectedColor(p.image_overlay_selected_color)
mOriginalImageOverlaySelectedColor(p.image_overlay_selected_color),
mInitialWidth(0)
// </FS:Zi>
{
}
LLToolBarButton::~LLToolBarButton()
{
delete mIsEnabledSignal;
delete mIsRunningSignal;
delete mIsStartingSignal;
}
BOOL LLToolBarButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
mMouseDownX = x;
mMouseDownY = y;
return LLButton::handleMouseDown(x, y, mask);
}
BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY);
static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);
if (mouse_distance_squared > drag_threshold * drag_threshold
&& hasMouseCapture() &&
mStartDragItemCallback && mHandleDragItemCallback)
{
if (!mIsDragged)
{
mStartDragItemCallback(x, y, this);
mIsDragged = true;
handled = TRUE;
}
else
{
handled = mHandleDragItemCallback(x, y, mId.uuid(), LLAssetType::AT_WIDGET);
}
}
else
{
handled = LLButton::handleHover(x, y, mask);
}
return handled;
}
void LLToolBarButton::onMouseEnter(S32 x, S32 y, MASK mask)
{
LLUICtrl::onMouseEnter(x, y, mask);
// Always highlight toolbar buttons, even if they are disabled
if (!gFocusMgr.getMouseCapture() || gFocusMgr.getMouseCapture() == this)
{
mNeedsHighlight = TRUE;
}
LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
if (parent_toolbar && parent_toolbar->mButtonEnterSignal)
{
(*(parent_toolbar->mButtonEnterSignal))(this);
}
}
void LLToolBarButton::onMouseLeave(S32 x, S32 y, MASK mask)
{
LLButton::onMouseLeave(x, y, mask);
LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
if (parent_toolbar && parent_toolbar->mButtonLeaveSignal)
{
(*(parent_toolbar->mButtonLeaveSignal))(this);
}
}
void LLToolBarButton::onMouseCaptureLost()
{
mIsDragged = false;
}
void LLToolBarButton::onCommit()
{
LLCommand* command = LLCommandManager::instance().getCommand(mId);
if (!mIsEnabledSignal || (*mIsEnabledSignal)(this, command->isEnabledParameters()))
{
LLButton::onCommit();
}
}
void LLToolBarButton::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLButton::reshape(mWidthRange.clamp(width), height, called_from_parent);
// <FS:Zi> Remember first width this button was set to, so we can calculate the equalized layout
if (!mInitialWidth)
{
mInitialWidth = width;
}
// </FS:Zi>
}
void LLToolBarButton::setEnabled(BOOL enabled)
{
if (enabled)
{
mImageSelected = mOriginalImageSelected;
mImageUnselected = mOriginalImageUnselected;
mImagePressed = mOriginalImagePressed;
mImagePressedSelected = mOriginalImagePressedSelected;
mUnselectedLabelColor = mOriginalLabelColor;
mSelectedLabelColor = mOriginalLabelColorSelected;
mImageOverlayColor = mOriginalImageOverlayColor;
mImageOverlaySelectedColor = mOriginalImageOverlaySelectedColor;
}
else
{
mImageSelected = mImageDisabledSelected;
mImageUnselected = mImageDisabled;
mImagePressed = mImageDisabled;
mImagePressedSelected = mImageDisabledSelected;
mUnselectedLabelColor = mDisabledLabelColor;
mSelectedLabelColor = mDisabledSelectedLabelColor;
mImageOverlayColor = mImageOverlayDisabledColor;
mImageOverlaySelectedColor = mImageOverlayDisabledColor;
}
// [RLVa:KB] - Checked: 2011-12-17 (RLVa-1.4.5a) | Added: RLVa-1.4.5a
//LLButton::setEnabled(enabled); // Ansa: Disabled because of FIRE-5552
// [/RLVa:KB]
}
const std::string LLToolBarButton::getToolTip() const
{
std::string tooltip;
if (labelIsTruncated() || getCurrentLabel().empty())
{
tooltip = LLTrans::getString(LLCommandManager::instance().getCommand(mId)->labelRef()) + " -- " + LLView::getToolTip();
}
else
{
tooltip = LLView::getToolTip();
}
LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
if (parent_toolbar && parent_toolbar->mButtonTooltipSuffix.length() > 0)
{
tooltip = tooltip + "\n(" + parent_toolbar->mButtonTooltipSuffix + ")";
}
return tooltip;
}
void LLToolBar::LLCenterLayoutPanel::handleReshape(const LLRect& rect, bool by_user)
{
LLLayoutPanel::handleReshape(rect, by_user);
if (!mReshapeCallback.empty())
{
LLRect r;
localRectToOtherView(mButtonPanel->getRect(), &r, gFloaterView);
r.stretch(FLOATER_MIN_VISIBLE_PIXELS);
mReshapeCallback(mLocationId, r);
}
}
// <FS:Zi> Returns the current alignment for saving in XML settings
LLToolBarEnums::Alignment LLToolBar::getAlignment() const
{
return mAlignment;
}
// <FS:Zi> Sets the alignment for this panel when loading the XML settings
void LLToolBar::setAlignment(LLToolBarEnums::Alignment alignment)
{
mAlignment = alignment;
mNeedsLayout = true;
}
// <FS:Zi> Context menu callback function to display checkmarks on alignment options
BOOL LLToolBar::isAlignment(const LLSD& userdata)
{
BOOL retval = FALSE;
const std::string alignment = userdata.asString();
if (alignment == "center")
{
retval = (mAlignment == ALIGN_CENTER);
}
else if (alignment == "left" || alignment == "top")
{
retval = (mAlignment == ALIGN_START);
}
else if (alignment == "right" || alignment == "bottom")
{
retval = (mAlignment == ALIGN_END);
}
return retval;
}
// <FS:Zi> Context menu callback function to set the alignment on click
void LLToolBar::onAlignmentChanged(const LLSD& userdata)
{
const std::string alignment = userdata.asString();
if (alignment == "center")
{
setAlignment(ALIGN_CENTER);
}
else if(alignment == "left" || alignment == "top")
{
setAlignment(ALIGN_START);
}
else if(alignment == "right" || alignment == "bottom")
{
setAlignment(ALIGN_END);
}
}
// <FS:Zi> Returns the current layout style for saving in XML settings
LLToolBarEnums::LayoutStyle LLToolBar::getLayoutStyle() const
{
return mLayoutStyle;
}
// <FS:Zi> Sets the layout style for this panel when loading the XML settings
void LLToolBar::setLayoutStyle(LLToolBarEnums::LayoutStyle layout_style)
{
mLayoutStyle = layout_style;
mNeedsLayout = true;
}
// <FS:Zi> Context menu callback function to display checkmarks on layout style options
BOOL LLToolBar::isLayoutStyle(const LLSD& userdata)
{
BOOL retval = FALSE;
const std::string layout_style = userdata.asString();
if (layout_style == "none")
{
retval = (mLayoutStyle == LAYOUT_STYLE_NONE);
}
else if (layout_style == "equalize")
{
retval = (mLayoutStyle == LAYOUT_STYLE_EQUALIZE);
}
else if (layout_style == "fill")
{
retval = (mLayoutStyle == LAYOUT_STYLE_FILL);
}
return retval;
}
// <FS:Zi> Context menu callback function to set the layout style on click
void LLToolBar::onLayoutStyleChanged(const LLSD& userdata)
{
const std::string layout_style = userdata.asString();
if (layout_style == "none")
{
setLayoutStyle(LAYOUT_STYLE_NONE);
}
else if (layout_style == "equalize")
{
setLayoutStyle(LAYOUT_STYLE_EQUALIZE);
}
else if (layout_style == "fill")
{
setLayoutStyle(LAYOUT_STYLE_FILL);
}
}
// <FS:Zi> Returns the first width this button had, to make equalize layout work
S32 LLToolBarButton::getInitialWidth() const
{
return mInitialWidth;
}