EXP-1239 WIP make toolbars wrap when there is not enough room
added more toolbars to floater_test_toolbar.xml removed layout stack and got basic wrapping working reviewed by Lesliemaster
parent
e70714fcfe
commit
00f66ccf40
|
|
@ -57,8 +57,8 @@ LLToolBar::Params::Params()
|
|||
button_icon("button_icon"),
|
||||
button_icon_and_text("button_icon_and_text"),
|
||||
wrap("wrap", true),
|
||||
min_width("min_width", 0),
|
||||
max_width("max_width", S32_MAX),
|
||||
min_button_width("min_button_width", 0),
|
||||
max_button_width("max_button_width", S32_MAX),
|
||||
background_image("background_image")
|
||||
{}
|
||||
|
||||
|
|
@ -70,8 +70,8 @@ LLToolBar::LLToolBar(const Params& p)
|
|||
mNeedsLayout(false),
|
||||
mCenterPanel(NULL),
|
||||
mCenteringStack(NULL),
|
||||
mMinWidth(p.min_width),
|
||||
mMaxWidth(p.max_width),
|
||||
mMinButtonWidth(p.min_button_width),
|
||||
mMaxButtonWidth(p.max_button_width),
|
||||
mBackgroundImage(p.background_image)
|
||||
{
|
||||
}
|
||||
|
|
@ -108,120 +108,148 @@ void LLToolBar::initFromParams(const LLToolBar::Params& p)
|
|||
|
||||
mCenteringStack->addChild(LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p));
|
||||
|
||||
addRow();
|
||||
|
||||
BOOST_FOREACH (LLToolBarButton::Params button_p, p.buttons)
|
||||
{
|
||||
LLRect button_rect(button_p.rect);
|
||||
{ // remove any offset from button
|
||||
if (orientation == LLLayoutStack::HORIZONTAL)
|
||||
{
|
||||
button_rect.setOriginAndSize(0, 0, mMinWidth, getRect().getHeight());
|
||||
}
|
||||
else // VERTICAL
|
||||
{
|
||||
button_rect.setOriginAndSize(0, 0, mMinWidth, button_rect.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// buttons always follow left and top, for all orientations
|
||||
button_p.follows.flags = FOLLOWS_LEFT|FOLLOWS_TOP;
|
||||
button_p.fillFrom((mButtonType == BTNTYPE_ICONS_ONLY)
|
||||
? p.button_icon // icon only
|
||||
: p.button_icon_and_text); // icon + text
|
||||
|
||||
mButtons.push_back(LLUICtrlFactory::create<LLToolBarButton>(button_p));
|
||||
LLRect button_rect(button_p.rect);
|
||||
{ // remove any offset from button
|
||||
if (orientation == LLLayoutStack::HORIZONTAL)
|
||||
{
|
||||
button_rect.setOriginAndSize(0, 0, mMinButtonWidth, button_rect.getHeight());
|
||||
}
|
||||
else // VERTICAL
|
||||
{
|
||||
button_rect.setOriginAndSize(0, 0, mMinButtonWidth, button_rect.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// use our calculated rect
|
||||
button_p.rect = button_rect;
|
||||
LLToolBarButton* buttonp = LLUICtrlFactory::create<LLToolBarButton>(button_p);
|
||||
|
||||
mButtons.push_back(buttonp);
|
||||
mCenterPanel->addChild(buttonp);
|
||||
|
||||
mNeedsLayout = true;
|
||||
}
|
||||
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
void LLToolBar::addButton(LLToolBarButton* buttonp)
|
||||
void LLToolBar::updateLayoutAsNeeded()
|
||||
{
|
||||
LLLayoutPanel::Params panel_p;
|
||||
panel_p.name = buttonp->getName() + "_panel";
|
||||
panel_p.user_resize = false;
|
||||
panel_p.auto_resize= false;
|
||||
panel_p.fit_content = true;
|
||||
|
||||
LLLayoutPanel* panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
|
||||
|
||||
panel->addChild(buttonp);
|
||||
mStacks.back()->addChild(panel);
|
||||
}
|
||||
|
||||
void LLToolBar::updateLayout()
|
||||
{
|
||||
mCenteringStack->updateLayout();
|
||||
|
||||
if (!mNeedsLayout) return;
|
||||
mNeedsLayout = false;
|
||||
|
||||
{ // clean up existing rows
|
||||
BOOST_FOREACH(LLToolBarButton* button, mButtons)
|
||||
{
|
||||
if (button->getParent())
|
||||
{
|
||||
button->getParent()->removeChild(button);
|
||||
}
|
||||
}
|
||||
LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType);
|
||||
|
||||
BOOST_FOREACH(LLLayoutStack* stack, mStacks)
|
||||
{
|
||||
delete stack;
|
||||
}
|
||||
mStacks.clear();
|
||||
}
|
||||
// start with one row of buttons
|
||||
addRow();
|
||||
// our terminology for orientation-agnostic layout is 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 total_length = 0;
|
||||
S32 max_length = (orientation == LLLayoutStack::HORIZONTAL)
|
||||
? getRect().getWidth()
|
||||
: getRect().getHeight();
|
||||
S32 max_row_girth = 0;
|
||||
S32 cur_start = 0;
|
||||
S32 cur_row = 0;
|
||||
|
||||
LLRect panel_rect = mCenterPanel->getLocalRect();
|
||||
|
||||
std::vector<LLToolBarButton*> buttons_in_row;
|
||||
|
||||
S32 total_width = 0, total_height = 0;
|
||||
S32 max_total_width = 0, max_total_height = 0;
|
||||
S32 max_width = getRect().getWidth(), max_height = getRect().getHeight();
|
||||
BOOST_FOREACH(LLToolBarButton* button, mButtons)
|
||||
{
|
||||
S32 button_width = button->getRect().getWidth();
|
||||
S32 button_height = button->getRect().getHeight();
|
||||
S32 button_clamped_width = llclamp(button->getRect().getWidth(), mMinButtonWidth, mMaxButtonWidth);
|
||||
S32 button_length = (orientation == LLLayoutStack::HORIZONTAL)
|
||||
? button_clamped_width
|
||||
: button->getRect().getHeight();
|
||||
S32 button_girth = (orientation == LLLayoutStack::HORIZONTAL)
|
||||
? button->getRect().getHeight()
|
||||
: button_clamped_width;
|
||||
|
||||
// handle wrapping
|
||||
if (total_length + button_length > max_length
|
||||
&& cur_start != 0) // not first button in row
|
||||
{ // go ahead and wrap
|
||||
if (orientation == LLLayoutStack::VERTICAL)
|
||||
{
|
||||
// row girth is clamped to allowable button widths
|
||||
max_row_girth = llclamp(max_row_girth, mMinButtonWidth, mMaxButtonWidth);
|
||||
}
|
||||
// make buttons in current row all same girth
|
||||
BOOST_FOREACH(LLToolBarButton* button, buttons_in_row)
|
||||
{
|
||||
if (orientation == LLLayoutStack::HORIZONTAL)
|
||||
{
|
||||
button->reshape(llclamp(button->getRect().getWidth(), mMinButtonWidth, mMaxButtonWidth), max_row_girth);
|
||||
}
|
||||
else // VERTICAL
|
||||
{
|
||||
button->reshape(max_row_girth, button->getRect().getHeight());
|
||||
}
|
||||
}
|
||||
buttons_in_row.clear();
|
||||
|
||||
if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL
|
||||
&& total_width + button_height > getRect().getWidth())
|
||||
{
|
||||
addRow();
|
||||
total_width = 0;
|
||||
total_length = 0;
|
||||
cur_start = 0;
|
||||
cur_row += max_row_girth;
|
||||
max_row_girth = 0;
|
||||
}
|
||||
addButton(button);
|
||||
|
||||
total_width += button_width;
|
||||
total_height += button_height;
|
||||
max_total_width = llmax(max_total_width, total_width);
|
||||
max_total_height = llmax(max_total_height, total_height);
|
||||
max_width = llmax(button->getRect().getWidth(), max_width);
|
||||
max_height = llmax(button->getRect().getHeight(), max_height);
|
||||
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);
|
||||
|
||||
total_length += button_length;
|
||||
cur_start = total_length;
|
||||
max_row_girth = llmax(button_girth, max_row_girth);
|
||||
}
|
||||
|
||||
if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)
|
||||
// final resizing in "girth" direction
|
||||
S32 total_girth = cur_row + max_row_girth; // increment by size of final row
|
||||
|
||||
// grow and optionally shift toolbar to accomodate buttons
|
||||
if (orientation == LLLayoutStack::HORIZONTAL)
|
||||
{
|
||||
BOOST_FOREACH(LLLayoutStack* stack, mStacks)
|
||||
{
|
||||
stack->reshape(max_total_width, stack->getParent()->getRect().getHeight());
|
||||
stack->updateLayout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_FOREACH(LLLayoutStack* stack, mStacks)
|
||||
{
|
||||
stack->reshape(stack->getParent()->getRect().getWidth(), max_total_height);
|
||||
stack->updateLayout();
|
||||
if (mSideType == SIDE_TOP)
|
||||
{ // shift down to maintain top edge
|
||||
translate(0, getRect().getHeight() - total_girth);
|
||||
}
|
||||
|
||||
reshape(max_total_width, getRect().getHeight());
|
||||
reshape(getRect().getWidth(), 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());
|
||||
}
|
||||
|
||||
// recenter toolbar buttons
|
||||
mCenteringStack->updateLayout();
|
||||
|
||||
// don't clear flag until after we've resized ourselves, to avoid laying out every frame
|
||||
mNeedsLayout = false;
|
||||
}
|
||||
|
||||
|
||||
void LLToolBar::draw()
|
||||
{
|
||||
updateLayout();
|
||||
updateLayoutAsNeeded();
|
||||
|
||||
{ // draw background
|
||||
LLRect bg_rect;
|
||||
|
|
@ -231,22 +259,6 @@ void LLToolBar::draw()
|
|||
LLUICtrl::draw();
|
||||
}
|
||||
|
||||
void LLToolBar::addRow()
|
||||
{
|
||||
LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType);
|
||||
|
||||
LLLayoutStack::Params stack_p;
|
||||
stack_p.rect = getLocalRect();
|
||||
stack_p.name = llformat("button_stack_%d", mStacks.size());
|
||||
stack_p.orientation = orientation;
|
||||
stack_p.follows.flags = (orientation == LLLayoutStack::HORIZONTAL)
|
||||
? (FOLLOWS_TOP|FOLLOWS_BOTTOM) // horizontal
|
||||
: (FOLLOWS_LEFT|FOLLOWS_RIGHT); // vertical
|
||||
|
||||
mStacks.push_back(LLUICtrlFactory::create<LLLayoutStack>(stack_p));
|
||||
mCenterPanel->addChild(mStacks.back());
|
||||
}
|
||||
|
||||
void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
LLUICtrl::reshape(width, height, called_from_parent);
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ public:
|
|||
button_icon_and_text;
|
||||
|
||||
Optional<bool> wrap;
|
||||
Optional<S32> min_width,
|
||||
max_width;
|
||||
Optional<S32> min_button_width,
|
||||
max_button_width;
|
||||
// get rid of this
|
||||
Multiple<LLToolBarButton::Params> buttons;
|
||||
|
||||
|
|
@ -112,11 +112,9 @@ protected:
|
|||
LLToolBar(const Params&);
|
||||
|
||||
void initFromParams(const Params&);
|
||||
void addButton(LLToolBarButton* buttonp);
|
||||
void updateLayout();
|
||||
|
||||
private:
|
||||
void addRow();
|
||||
void updateLayoutAsNeeded();
|
||||
|
||||
std::list<LLToolBarButton*> mButtons;
|
||||
LLToolBarEnums::ButtonType mButtonType;
|
||||
|
|
@ -125,11 +123,10 @@ private:
|
|||
LLLayoutPanel* mCenterPanel;
|
||||
LLToolBarEnums::SideType mSideType;
|
||||
|
||||
std::vector<LLLayoutStack*> mStacks;
|
||||
bool mWrap;
|
||||
bool mNeedsLayout;
|
||||
S32 mMinWidth,
|
||||
mMaxWidth;
|
||||
S32 mMinButtonWidth,
|
||||
mMaxButtonWidth;
|
||||
|
||||
LLUIImagePtr mBackgroundImage;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,16 +31,9 @@
|
|||
|
||||
static LLDefaultChildRegistry::Register<LLDragAndDropButton> r("dnd_button");
|
||||
|
||||
LLDragAndDropButton::Params::Params()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLDragAndDropButton::LLDragAndDropButton(const Params& params)
|
||||
: LLButton(params)
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
|
||||
BOOL LLDragAndDropButton::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@
|
|||
class LLDragAndDropButton : public LLButton
|
||||
{
|
||||
public:
|
||||
struct Params : public LLInitParam::Block<Params, LLButton::Params>
|
||||
{
|
||||
Params();
|
||||
};
|
||||
struct Params : public LLInitParam::Block<Params, LLButton::Params> {};
|
||||
|
||||
LLDragAndDropButton(const Params& params);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,44 @@
|
|||
name="floater_test_toolbar"
|
||||
translate="false"
|
||||
width="500">
|
||||
<toolbar name="test_toolbar_horizontal"
|
||||
<toolbar name="test_toolbar_top"
|
||||
follows="left|right|top"
|
||||
height="50"
|
||||
width="500"
|
||||
left="0"
|
||||
top="20"
|
||||
min_width="100"
|
||||
side="top">
|
||||
<button auto_resize="true"
|
||||
label="Button"/>
|
||||
<button auto_resize="true"
|
||||
label="Button with long label"/>
|
||||
<button auto_resize="true"
|
||||
label="Button with longest label of all"/>
|
||||
</toolbar>
|
||||
<toolbar name="test_toolbar_left"
|
||||
follows="left|bottom|top"
|
||||
height="380"
|
||||
width="100"
|
||||
left="0"
|
||||
top="70"
|
||||
min_width="100"
|
||||
side="left">
|
||||
<button height="30"
|
||||
label="Button"/>
|
||||
<button height="50"
|
||||
label="Button with long label"/>
|
||||
<button height="60"
|
||||
label="Button with longest label of all"/>
|
||||
</toolbar>
|
||||
<toolbar name="test_toolbar_right"
|
||||
follows="right|bottom|top"
|
||||
height="380"
|
||||
width="100"
|
||||
right="500"
|
||||
top="70"
|
||||
min_width="100"
|
||||
side="right">
|
||||
<button auto_resize="true"
|
||||
label="Button 1"/>
|
||||
<button auto_resize="true"
|
||||
|
|
@ -21,19 +52,19 @@
|
|||
<button auto_resize="true"
|
||||
label="Button with longest label of all"/>
|
||||
</toolbar>
|
||||
<toolbar name="test_toolbar_vertical"
|
||||
follows="left|bottom|top"
|
||||
height="430"
|
||||
width="100"
|
||||
<toolbar name="test_toolbar_bottom"
|
||||
follows="left|right|bottom"
|
||||
height="50"
|
||||
width="500"
|
||||
left="0"
|
||||
top="70"
|
||||
side="left">
|
||||
<button height="30"
|
||||
label="Button 1"/>
|
||||
<button height="50"
|
||||
label="Button 2"/>
|
||||
<button height="60"
|
||||
label="Button 3"/>
|
||||
bottom="500"
|
||||
min_width="100"
|
||||
side="bottom">
|
||||
<button auto_resize="true"
|
||||
label="Button"/>
|
||||
<button auto_resize="true"
|
||||
label="Button with long label"/>
|
||||
<button auto_resize="true"
|
||||
label="Button with longest label of all"/>
|
||||
</toolbar>
|
||||
|
||||
</floater>
|
||||
|
|
|
|||
Loading…
Reference in New Issue