|
|
|
|
@@ -486,7 +486,7 @@ BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK mask)
|
|
|
|
|
BOOL LLMenuItemGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
|
|
|
|
|
{
|
|
|
|
|
// If the menu is scrollable let it handle the wheel event.
|
|
|
|
|
return FALSE;//!getMenu()->isScrollable();
|
|
|
|
|
return !getMenu()->isScrollable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LLMenuItemGL::draw( void )
|
|
|
|
|
@@ -1805,6 +1805,117 @@ void LLMenuItemBranchDownGL::draw( void )
|
|
|
|
|
setHover(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LLMenuScrollItem : public LLMenuItemCallGL
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
enum EArrowType
|
|
|
|
|
{
|
|
|
|
|
ARROW_DOWN,
|
|
|
|
|
ARROW_UP
|
|
|
|
|
};
|
|
|
|
|
struct ArrowTypes : public LLInitParam::TypeValuesHelper<EArrowType, ArrowTypes>
|
|
|
|
|
{
|
|
|
|
|
static void declareValues()
|
|
|
|
|
{
|
|
|
|
|
declare("up", ARROW_UP);
|
|
|
|
|
declare("down", ARROW_DOWN);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
|
|
|
|
|
{
|
|
|
|
|
Optional<EArrowType, ArrowTypes> arrow_type;
|
|
|
|
|
Optional<CommitCallbackParam> scroll_callback;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
LLMenuScrollItem(const Params&);
|
|
|
|
|
friend class LLUICtrlFactory;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/*virtual*/ void draw();
|
|
|
|
|
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
|
|
|
|
|
/*virtual*/ void setEnabled(BOOL enabled);
|
|
|
|
|
virtual void doIt( void );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
LLButton* mArrowBtn;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LLMenuScrollItem::LLMenuScrollItem(const Params& p)
|
|
|
|
|
: LLMenuItemCallGL(p.name, NULL/*p*/)
|
|
|
|
|
{
|
|
|
|
|
std::string icon;
|
|
|
|
|
if (p.arrow_type.isProvided() && p.arrow_type == ARROW_UP)
|
|
|
|
|
{
|
|
|
|
|
icon = "arrow_up.tga";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
icon = "arrow_down.tga";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Singu TODO: LLButton::Params
|
|
|
|
|
LLButton::Params bparams;
|
|
|
|
|
|
|
|
|
|
// Disabled the Return key handling by LLMenuScrollItem instead of
|
|
|
|
|
// passing the key press to the currently selected menu item. See STORM-385.
|
|
|
|
|
bparams.commit_on_return(false);
|
|
|
|
|
bparams.mouse_opaque(true);
|
|
|
|
|
bparams.scale_image(false);
|
|
|
|
|
bparams.click_callback(p.scroll_callback);
|
|
|
|
|
bparams.mouse_held_callback(p.scroll_callback);
|
|
|
|
|
bparams.follows.flags(FOLLOWS_ALL);
|
|
|
|
|
std::string background = "transparent.j2c";
|
|
|
|
|
bparams.image_unselected.name(background);
|
|
|
|
|
bparams.image_disabled.name(background);
|
|
|
|
|
bparams.image_selected.name(background);
|
|
|
|
|
bparams.image_hover_selected.name(background);
|
|
|
|
|
bparams.image_disabled_selected.name(background);
|
|
|
|
|
bparams.image_hover_unselected.name(background);
|
|
|
|
|
bparams.image_overlay.name(icon);
|
|
|
|
|
|
|
|
|
|
mArrowBtn = LLUICtrlFactory::create<LLButton>(bparams);
|
|
|
|
|
*/
|
|
|
|
|
const LLRect rect = getRect();
|
|
|
|
|
const std::string background = "transparent.j2c";
|
|
|
|
|
mArrowBtn = new LLButton("", LLRect(0, 0, rect.getWidth(), rect.getHeight()), background, background, "", NULL);
|
|
|
|
|
mArrowBtn->setCommitOnReturn(false);
|
|
|
|
|
mArrowBtn->setMouseOpaque(true);
|
|
|
|
|
mArrowBtn->setScaleImage(false);
|
|
|
|
|
mArrowBtn->setClickedCallback(p.scroll_callback);
|
|
|
|
|
mArrowBtn->setHeldDownCallback(p.scroll_callback);
|
|
|
|
|
mArrowBtn->setFollows(FOLLOWS_ALL);
|
|
|
|
|
mArrowBtn->setImageOverlay(icon);
|
|
|
|
|
addChild(mArrowBtn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*virtual*/
|
|
|
|
|
void LLMenuScrollItem::draw()
|
|
|
|
|
{
|
|
|
|
|
LLUICtrl::draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*virtual*/
|
|
|
|
|
void LLMenuScrollItem::reshape(S32 width, S32 height, BOOL called_from_parent)
|
|
|
|
|
{
|
|
|
|
|
mArrowBtn->reshape(width, height, called_from_parent);
|
|
|
|
|
LLView::reshape(width, height, called_from_parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*virtual*/
|
|
|
|
|
void LLMenuScrollItem::setEnabled(BOOL enabled)
|
|
|
|
|
{
|
|
|
|
|
mArrowBtn->setEnabled(enabled);
|
|
|
|
|
LLView::setEnabled(enabled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LLMenuScrollItem::doIt( void )
|
|
|
|
|
{
|
|
|
|
|
LLUICtrl::onCommit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///============================================================================
|
|
|
|
|
/// Class LLMenuGL
|
|
|
|
|
///============================================================================
|
|
|
|
|
@@ -1816,10 +1927,12 @@ LLMenuGL::LLMenuGL( const std::string& name, const std::string& label )
|
|
|
|
|
: LLUICtrl( name, LLRect(), FALSE),
|
|
|
|
|
mBackgroundColor( sDefaultBackgroundColor ),
|
|
|
|
|
mBgVisible( TRUE ),
|
|
|
|
|
mHasSelection( FALSE ),
|
|
|
|
|
mHasSelection(false),
|
|
|
|
|
mHorizontalLayout(false),
|
|
|
|
|
mScrollable(mHorizontalLayout ? FALSE : /*p.scrollable*/false), // Scrolling is supported only for vertical layout
|
|
|
|
|
mMaxScrollableItems(/*p.max_scrollable_items*/ U32_MAX),
|
|
|
|
|
mLabel( label ),
|
|
|
|
|
mDropShadowed( TRUE ),
|
|
|
|
|
mHorizontalLayout( FALSE ),
|
|
|
|
|
mKeepFixedSize( FALSE ),
|
|
|
|
|
mLastMouseX(0),
|
|
|
|
|
mLastMouseY(0),
|
|
|
|
|
@@ -1829,9 +1942,12 @@ LLMenuGL::LLMenuGL( const std::string& name, const std::string& label )
|
|
|
|
|
mTearOffItem(NULL),
|
|
|
|
|
mSpilloverBranch(NULL),
|
|
|
|
|
mFirstVisibleItem(NULL),
|
|
|
|
|
mArrowUpItem(NULL),
|
|
|
|
|
mArrowDownItem(NULL),
|
|
|
|
|
mSpilloverMenu(NULL),
|
|
|
|
|
mJumpKey(KEY_NONE),
|
|
|
|
|
mNeedsArrange(FALSE),
|
|
|
|
|
mResetScrollPositionOnShow(true),
|
|
|
|
|
mShortcutPad(ACCEL_PAD_PIXELS)
|
|
|
|
|
{
|
|
|
|
|
mFadeTimer.stop();
|
|
|
|
|
@@ -1842,10 +1958,12 @@ LLMenuGL::LLMenuGL( const std::string& label)
|
|
|
|
|
: LLUICtrl( label, LLRect(), FALSE),
|
|
|
|
|
mBackgroundColor( sDefaultBackgroundColor ),
|
|
|
|
|
mBgVisible( TRUE ),
|
|
|
|
|
mHasSelection( FALSE ),
|
|
|
|
|
mHasSelection(false),
|
|
|
|
|
mHorizontalLayout(false),
|
|
|
|
|
mScrollable(mHorizontalLayout ? FALSE : /*p.scrollable*/false), // Scrolling is supported only for vertical layout
|
|
|
|
|
mMaxScrollableItems(/*p.max_scrollable_items*/ U32_MAX),
|
|
|
|
|
mLabel( label ),
|
|
|
|
|
mDropShadowed( TRUE ),
|
|
|
|
|
mHorizontalLayout( FALSE ),
|
|
|
|
|
mKeepFixedSize( FALSE ),
|
|
|
|
|
mLastMouseX(0),
|
|
|
|
|
mLastMouseY(0),
|
|
|
|
|
@@ -1856,8 +1974,11 @@ LLMenuGL::LLMenuGL( const std::string& label)
|
|
|
|
|
mSpilloverBranch(NULL),
|
|
|
|
|
mSpilloverMenu(NULL),
|
|
|
|
|
mFirstVisibleItem(NULL),
|
|
|
|
|
mArrowUpItem(NULL),
|
|
|
|
|
mArrowDownItem(NULL),
|
|
|
|
|
mJumpKey(KEY_NONE),
|
|
|
|
|
mNeedsArrange(FALSE),
|
|
|
|
|
mResetScrollPositionOnShow(true),
|
|
|
|
|
mShortcutPad(ACCEL_PAD_PIXELS)
|
|
|
|
|
{
|
|
|
|
|
mFadeTimer.stop();
|
|
|
|
|
@@ -2361,6 +2482,13 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
|
|
|
|
|
menu->parseChildXML(child, parent, factory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->hasAttribute("scrollable"))
|
|
|
|
|
{
|
|
|
|
|
bool b;
|
|
|
|
|
node->getAttribute_bool("scrollable", b);
|
|
|
|
|
setScrollable(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (create_jump_keys)
|
|
|
|
|
{
|
|
|
|
|
menu->createJumpKeys();
|
|
|
|
|
@@ -2369,6 +2497,117 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool LLMenuGL::scrollItems(EScrollingDirection direction)
|
|
|
|
|
{
|
|
|
|
|
// Slowing down items scrolling when arrow button is held
|
|
|
|
|
if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
mScrollItemsTimer.setTimerExpirySec(.033f);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case SD_UP:
|
|
|
|
|
{
|
|
|
|
|
item_list_t::iterator cur_item_iter;
|
|
|
|
|
item_list_t::iterator prev_item_iter;
|
|
|
|
|
for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
|
|
|
|
|
{
|
|
|
|
|
if( (*cur_item_iter) == mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((*cur_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
prev_item_iter = cur_item_iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((*prev_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
mFirstVisibleItem = *prev_item_iter;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SD_DOWN:
|
|
|
|
|
{
|
|
|
|
|
if (NULL == mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
mFirstVisibleItem = *mItems.begin();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item_list_t::iterator cur_item_iter;
|
|
|
|
|
|
|
|
|
|
for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
|
|
|
|
|
{
|
|
|
|
|
if( (*cur_item_iter) == mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item_list_t::iterator next_item_iter;
|
|
|
|
|
|
|
|
|
|
if (cur_item_iter != mItems.end())
|
|
|
|
|
{
|
|
|
|
|
for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
|
|
|
|
|
{
|
|
|
|
|
if( (*next_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (next_item_iter != mItems.end() &&
|
|
|
|
|
(*next_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
mFirstVisibleItem = *next_item_iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SD_BEGIN:
|
|
|
|
|
{
|
|
|
|
|
mFirstVisibleItem = *mItems.begin();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SD_END:
|
|
|
|
|
{
|
|
|
|
|
item_list_t::reverse_iterator first_visible_item_iter = mItems.rend();
|
|
|
|
|
|
|
|
|
|
// Need to scroll through number of actual existing items in menu.
|
|
|
|
|
// Otherwise viewer will hang for a time needed to scroll U32_MAX
|
|
|
|
|
// times in std::advance(). STORM-659.
|
|
|
|
|
size_t nitems = mItems.size();
|
|
|
|
|
U32 scrollable_items = nitems < mMaxScrollableItems ? nitems : mMaxScrollableItems;
|
|
|
|
|
|
|
|
|
|
// Advance by mMaxScrollableItems back from the end of the list
|
|
|
|
|
// to make the last item visible.
|
|
|
|
|
std::advance(first_visible_item_iter, scrollable_items);
|
|
|
|
|
mFirstVisibleItem = *first_visible_item_iter;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
//LL_WARNS() << "Unknown scrolling direction: " << direction << LL_ENDL;
|
|
|
|
|
llwarns << "Unknown scrolling direction: " << direction << llendl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mNeedsArrange = TRUE;
|
|
|
|
|
arrangeAndClear();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LLMenuGL::setScrollable(bool b)
|
|
|
|
|
{
|
|
|
|
|
mScrollable = b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rearrange the child rects so they fit the shape of the menu.
|
|
|
|
|
void LLMenuGL::arrange( void )
|
|
|
|
|
{
|
|
|
|
|
@@ -2402,9 +2641,10 @@ void LLMenuGL::arrange( void )
|
|
|
|
|
|
|
|
|
|
// Scrolling support
|
|
|
|
|
item_list_t::iterator first_visible_item_iter;
|
|
|
|
|
//S32 height_before_first_visible_item = -1;
|
|
|
|
|
//S32 visible_items_height = 0;
|
|
|
|
|
//U32 scrollable_items_cnt = 0;
|
|
|
|
|
item_list_t::iterator first_hidden_item_iter = mItems.end();
|
|
|
|
|
S32 height_before_first_visible_item = -1;
|
|
|
|
|
S32 visible_items_height = 0;
|
|
|
|
|
U32 scrollable_items_cnt = 0;
|
|
|
|
|
|
|
|
|
|
if (mHorizontalLayout)
|
|
|
|
|
{
|
|
|
|
|
@@ -2452,15 +2692,16 @@ void LLMenuGL::arrange( void )
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
item_list_t::iterator item_iter;
|
|
|
|
|
|
|
|
|
|
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
|
|
|
|
|
{
|
|
|
|
|
llassert_always((*item_iter)!=NULL);
|
|
|
|
|
// do first so LLMenuGLItemCall can call on_visible to determine if visible
|
|
|
|
|
(*item_iter)->buildDrawLabel();
|
|
|
|
|
|
|
|
|
|
if ((*item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
if (!getTornOff()
|
|
|
|
|
&& !mScrollable
|
|
|
|
|
&& *item_iter != mSpilloverBranch
|
|
|
|
|
&& height + (*item_iter)->getNominalHeight() > max_height - spillover_item_height)
|
|
|
|
|
{
|
|
|
|
|
@@ -2476,6 +2717,8 @@ void LLMenuGL::arrange( void )
|
|
|
|
|
removeChild(itemp);
|
|
|
|
|
mSpilloverMenu->addChild(itemp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addChild(mSpilloverBranch);
|
|
|
|
|
|
|
|
|
|
height += mSpilloverBranch->getNominalHeight();
|
|
|
|
|
@@ -2489,20 +2732,170 @@ void LLMenuGL::arrange( void )
|
|
|
|
|
height += (*item_iter)->getNominalHeight();
|
|
|
|
|
width = llmax( width, (*item_iter)->getNominalWidth() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mScrollable)
|
|
|
|
|
{
|
|
|
|
|
// Determining visible items boundaries
|
|
|
|
|
if (NULL == mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
mFirstVisibleItem = *item_iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*item_iter == mFirstVisibleItem)
|
|
|
|
|
{
|
|
|
|
|
height_before_first_visible_item = height - (*item_iter)->getNominalHeight();
|
|
|
|
|
first_visible_item_iter = item_iter;
|
|
|
|
|
scrollable_items_cnt = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (-1 != height_before_first_visible_item && 0 == visible_items_height &&
|
|
|
|
|
(++scrollable_items_cnt > mMaxScrollableItems ||
|
|
|
|
|
height - height_before_first_visible_item > max_height - spillover_item_height * 2 ))
|
|
|
|
|
{
|
|
|
|
|
first_hidden_item_iter = item_iter;
|
|
|
|
|
visible_items_height = height - height_before_first_visible_item - (*item_iter)->getNominalHeight();
|
|
|
|
|
scrollable_items_cnt--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mScrollable)
|
|
|
|
|
{
|
|
|
|
|
S32 max_items_height = max_height - spillover_item_height * 2;
|
|
|
|
|
|
|
|
|
|
if (visible_items_height == 0)
|
|
|
|
|
visible_items_height = height - height_before_first_visible_item;
|
|
|
|
|
|
|
|
|
|
// Fix mFirstVisibleItem value, if it doesn't allow to display all items, that can fit
|
|
|
|
|
if (visible_items_height < max_items_height && scrollable_items_cnt < mMaxScrollableItems)
|
|
|
|
|
{
|
|
|
|
|
item_list_t::iterator tmp_iter(first_visible_item_iter);
|
|
|
|
|
while (visible_items_height < max_items_height &&
|
|
|
|
|
scrollable_items_cnt < mMaxScrollableItems &&
|
|
|
|
|
first_visible_item_iter != mItems.begin())
|
|
|
|
|
{
|
|
|
|
|
if ((*first_visible_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
// It keeps visible item, after first_visible_item_iter
|
|
|
|
|
tmp_iter = first_visible_item_iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
first_visible_item_iter--;
|
|
|
|
|
|
|
|
|
|
if ((*first_visible_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
visible_items_height += (*first_visible_item_iter)->getNominalHeight();
|
|
|
|
|
height_before_first_visible_item -= (*first_visible_item_iter)->getNominalHeight();
|
|
|
|
|
scrollable_items_cnt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Roll back one item, that doesn't fit
|
|
|
|
|
if (visible_items_height > max_items_height)
|
|
|
|
|
{
|
|
|
|
|
visible_items_height -= (*first_visible_item_iter)->getNominalHeight();
|
|
|
|
|
height_before_first_visible_item += (*first_visible_item_iter)->getNominalHeight();
|
|
|
|
|
scrollable_items_cnt--;
|
|
|
|
|
first_visible_item_iter = tmp_iter;
|
|
|
|
|
}
|
|
|
|
|
if (!(*first_visible_item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
first_visible_item_iter = tmp_iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mFirstVisibleItem = *first_visible_item_iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
S32 cur_height = (S32)llmin(max_height, height);
|
|
|
|
|
|
|
|
|
|
if (mScrollable &&
|
|
|
|
|
(height_before_first_visible_item > MENU_ITEM_PADDING ||
|
|
|
|
|
height_before_first_visible_item + visible_items_height < (S32)height))
|
|
|
|
|
{
|
|
|
|
|
// Reserving 2 extra slots for arrow items
|
|
|
|
|
cur_height = visible_items_height + spillover_item_height * 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width, getRect().mTop - cur_height));
|
|
|
|
|
|
|
|
|
|
S32 cur_width = 0;
|
|
|
|
|
S32 offset = 0;
|
|
|
|
|
if (mScrollable)
|
|
|
|
|
{
|
|
|
|
|
// No space for all items, creating arrow items
|
|
|
|
|
if (height_before_first_visible_item > MENU_ITEM_PADDING ||
|
|
|
|
|
height_before_first_visible_item + visible_items_height < (S32)height)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == mArrowUpItem)
|
|
|
|
|
{
|
|
|
|
|
LLMenuScrollItem::Params item_params;
|
|
|
|
|
item_params.name(ARROW_UP);
|
|
|
|
|
item_params.arrow_type(LLMenuScrollItem::ARROW_UP);
|
|
|
|
|
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP));
|
|
|
|
|
|
|
|
|
|
mArrowUpItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
|
|
|
|
|
LLUICtrl::addChild(mArrowUpItem);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (NULL == mArrowDownItem)
|
|
|
|
|
{
|
|
|
|
|
LLMenuScrollItem::Params item_params;
|
|
|
|
|
item_params.name(ARROW_DOWN);
|
|
|
|
|
item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN);
|
|
|
|
|
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN));
|
|
|
|
|
|
|
|
|
|
mArrowDownItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
|
|
|
|
|
LLUICtrl::addChild(mArrowDownItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LLRect rect;
|
|
|
|
|
mArrowUpItem->setRect(rect.setLeftTopAndSize( 0, cur_height, width, mArrowUpItem->getNominalHeight()));
|
|
|
|
|
mArrowUpItem->setVisible(TRUE);
|
|
|
|
|
mArrowUpItem->setEnabled(height_before_first_visible_item > MENU_ITEM_PADDING);
|
|
|
|
|
mArrowUpItem->reshape(width, mArrowUpItem->getNominalHeight());
|
|
|
|
|
mArrowDownItem->setRect(rect.setLeftTopAndSize( 0, mArrowDownItem->getNominalHeight(), width, mArrowDownItem->getNominalHeight()));
|
|
|
|
|
mArrowDownItem->setVisible(TRUE);
|
|
|
|
|
mArrowDownItem->setEnabled(height_before_first_visible_item + visible_items_height < (S32)height);
|
|
|
|
|
mArrowDownItem->reshape(width, mArrowDownItem->getNominalHeight());
|
|
|
|
|
|
|
|
|
|
cur_height -= mArrowUpItem->getNominalHeight();
|
|
|
|
|
|
|
|
|
|
offset = menu_region_rect.mRight; // This moves items behind visible area
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (NULL != mArrowUpItem)
|
|
|
|
|
{
|
|
|
|
|
mArrowUpItem->setVisible(FALSE);
|
|
|
|
|
}
|
|
|
|
|
if (NULL != mArrowDownItem)
|
|
|
|
|
{
|
|
|
|
|
mArrowDownItem->setVisible(FALSE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item_list_t::iterator item_iter;
|
|
|
|
|
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
|
|
|
|
|
{
|
|
|
|
|
if ((*item_iter)->getVisible())
|
|
|
|
|
{
|
|
|
|
|
if (mScrollable)
|
|
|
|
|
{
|
|
|
|
|
if (item_iter == first_visible_item_iter)
|
|
|
|
|
{
|
|
|
|
|
offset = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (item_iter == first_hidden_item_iter)
|
|
|
|
|
{
|
|
|
|
|
offset = menu_region_rect.mRight; // This moves items behind visible area
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setup item rect to hold label
|
|
|
|
|
LLRect rect;
|
|
|
|
|
if (mHorizontalLayout)
|
|
|
|
|
@@ -2683,6 +3076,8 @@ void LLMenuGL::empty( void )
|
|
|
|
|
|
|
|
|
|
mItems.clear();
|
|
|
|
|
mFirstVisibleItem = NULL;
|
|
|
|
|
mArrowUpItem = NULL;
|
|
|
|
|
mArrowDownItem = NULL;
|
|
|
|
|
|
|
|
|
|
deleteAllChildren();
|
|
|
|
|
|
|
|
|
|
@@ -2899,9 +3294,36 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
|
|
|
|
|
next_item_iter = cur_item_iter;
|
|
|
|
|
next_item_iter++;
|
|
|
|
|
|
|
|
|
|
// First visible item position in the items list
|
|
|
|
|
item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem);
|
|
|
|
|
|
|
|
|
|
if (next_item_iter == mItems.end())
|
|
|
|
|
{
|
|
|
|
|
next_item_iter = mItems.begin();
|
|
|
|
|
|
|
|
|
|
// If current item is the last in the list, the menu is scrolled to the beginning
|
|
|
|
|
// and the first item is highlighted.
|
|
|
|
|
if (mScrollable && !scrollItems(SD_BEGIN))
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If current item is the last visible, the menu is scrolled one item down
|
|
|
|
|
// and the next item is highlighted.
|
|
|
|
|
else if (mScrollable &&
|
|
|
|
|
(U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems)
|
|
|
|
|
{
|
|
|
|
|
// Call highlightNextItem() recursively only if the menu was successfully scrolled down.
|
|
|
|
|
// If scroll timer hasn't expired yet the menu won't be scrolled and calling
|
|
|
|
|
// highlightNextItem() will result in an endless recursion.
|
|
|
|
|
if (scrollItems(SD_DOWN))
|
|
|
|
|
{
|
|
|
|
|
return highlightNextItem(cur_item, skip_disabled);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2974,9 +3396,36 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
|
|
|
|
|
prev_item_iter = cur_item_iter;
|
|
|
|
|
prev_item_iter++;
|
|
|
|
|
|
|
|
|
|
// First visible item reverse position in the items list
|
|
|
|
|
item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem);
|
|
|
|
|
|
|
|
|
|
if (prev_item_iter == mItems.rend())
|
|
|
|
|
{
|
|
|
|
|
prev_item_iter = mItems.rbegin();
|
|
|
|
|
|
|
|
|
|
// If current item is the first in the list, the menu is scrolled to the end
|
|
|
|
|
// and the last item is highlighted.
|
|
|
|
|
if (mScrollable && !scrollItems(SD_END))
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If current item is the first visible, the menu is scrolled one item up
|
|
|
|
|
// and the previous item is highlighted.
|
|
|
|
|
else if (mScrollable &&
|
|
|
|
|
std::distance(first_visible_item_iter, cur_item_iter) <= 0)
|
|
|
|
|
{
|
|
|
|
|
// Call highlightNextItem() only if the menu was successfully scrolled up.
|
|
|
|
|
// If scroll timer hasn't expired yet the menu won't be scrolled and calling
|
|
|
|
|
// highlightNextItem() will result in an endless recursion.
|
|
|
|
|
if (scrollItems(SD_UP))
|
|
|
|
|
{
|
|
|
|
|
return highlightPrevItem(cur_item, skip_disabled);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3141,7 +3590,21 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask )
|
|
|
|
|
|
|
|
|
|
BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
|
|
|
|
|
{
|
|
|
|
|
return blockMouseEvent(x, y);
|
|
|
|
|
if (!mScrollable)
|
|
|
|
|
return blockMouseEvent(x, y);
|
|
|
|
|
|
|
|
|
|
if( clicks > 0 )
|
|
|
|
|
{
|
|
|
|
|
while( clicks-- )
|
|
|
|
|
scrollItems(SD_DOWN);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while( clicks++ )
|
|
|
|
|
scrollItems(SD_UP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LLMenuGL::draw( void )
|
|
|
|
|
|