@@ -110,7 +110,7 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
110110 }
111111
112112 // _4 is for MASK
113- item->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4));
113+ item->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4, CLICK_LEFT ));
114114 item->setRightMouseDownCallback (boost::bind (&LLFlatListView::onItemRightMouseClick, this , new_pair, _4));
115115
116116 // Children don't accept the focus
@@ -168,7 +168,7 @@ bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= tr
168168 mItemsPanel ->addChild (panel);
169169
170170 // _4 is for MASK
171- panel->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4));
171+ panel->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4, CLICK_LEFT ));
172172 panel->setRightMouseDownCallback (boost::bind (&LLFlatListView::onItemRightMouseClick, this , new_pair, _4));
173173 // Children don't accept the focus
174174 panel->setTabStop (false );
@@ -195,7 +195,7 @@ bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= tr
195195 mItemsPanel ->addChild (panel);
196196
197197 // _4 is for MASK
198- panel->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , item_pair, _4));
198+ panel->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , item_pair, _4, CLICK_LEFT ));
199199 panel->setRightMouseDownCallback (boost::bind (&LLFlatListView::onItemRightMouseClick, this , item_pair, _4));
200200 // Children don't accept the focus
201201 panel->setTabStop (false );
@@ -247,7 +247,7 @@ bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add,
247247 }
248248
249249 // _4 is for MASK
250- item_to_add->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4));
250+ item_to_add->setMouseDownCallback (boost::bind (&LLFlatListView::onItemMouseClick, this , new_pair, _4, CLICK_LEFT ));
251251 item_to_add->setRightMouseDownCallback (boost::bind (&LLFlatListView::onItemRightMouseClick, this , new_pair, _4));
252252
253253 rearrangeItems ();
@@ -504,9 +504,8 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
504504 , mFocusOnItemClicked(true )
505505 , mAllowReorder(p.allow_reorder)
506506 , mIsReordering(false )
507- , mProcessingRightClick(false )
508- , mReorderDragPair(NULL )
509- , mDeferredSelectPair(NULL )
507+ , mReorderDragPair(nullptr )
508+ , mDeferredSelectPair(nullptr )
510509 , mReorderMouseDownX(0 )
511510 , mReorderMouseDownY(0 )
512511 , mReorderInsertIndex(-1 )
@@ -672,7 +671,7 @@ void LLFlatListView::rearrangeItems()
672671 mSelectedItemsBorder ->setRect (getLastSelectedItemRect ().stretch (-1 ));
673672}
674673
675- void LLFlatListView::onItemMouseClick (item_pair_t * item_pair, MASK mask)
674+ void LLFlatListView::onItemMouseClick (item_pair_t * item_pair, MASK mask, EMouseClickType clicktype )
676675{
677676 if (!item_pair) return ;
678677
@@ -687,7 +686,7 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
687686 setFocus (true );
688687 }
689688
690- if (!(mask & (MASK_SHIFT | MASK_CONTROL )))
689+ if (clicktype == CLICK_LEFT && !(mask & (MASK_SHIFT | MASK_CONTROL )))
691690 {
692691 armReorderDrag (item_pair);
693692 }
@@ -801,16 +800,14 @@ void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask)
801800 return ;
802801
803802 // else got same behavior as at onItemMouseClick, but a right click must never start a drag
804- mProcessingRightClick = true ;
805- onItemMouseClick (item_pair, mask);
806- mProcessingRightClick = false ;
803+ onItemMouseClick (item_pair, mask, CLICK_RIGHT );
807804}
808805
809- static const S32 REORDER_DRAG_THRESHOLD = 5 ;
806+ static constexpr S32 REORDER_DRAG_THRESHOLD = 5 ;
810807
811808void LLFlatListView::armReorderDrag (item_pair_t * item_pair)
812809{
813- if (!mAllowReorder || mProcessingRightClick )
810+ if (!mAllowReorder )
814811 {
815812 return ;
816813 }
@@ -832,7 +829,7 @@ void LLFlatListView::armReorderDrag(item_pair_t* item_pair)
832829
833830 mReorderDragPair = item_pair;
834831 mReorderDragGroup .clear ();
835- mDeferredSelectPair = NULL ;
832+ mDeferredSelectPair = nullptr ;
836833 mIsReordering = false ;
837834 mReorderInsertIndex = -1 ;
838835
@@ -842,7 +839,8 @@ void LLFlatListView::armReorderDrag(item_pair_t* item_pair)
842839
843840void LLFlatListView::updateReorderDrag (S32 x, S32 y)
844841{
845- if (!mReorderDragPair ) return ;
842+ if (!mReorderDragPair )
843+ return ;
846844
847845 if (!mIsReordering )
848846 {
@@ -866,7 +864,8 @@ void LLFlatListView::buildReorderGroup()
866864
867865 for (item_pair_t * pair : mItemPairs )
868866 {
869- if (!pair->first ->getVisible ()) continue ;
867+ if (!pair->first ->getVisible ())
868+ continue ;
870869
871870 if (pair == mReorderDragPair )
872871 {
@@ -891,7 +890,8 @@ void LLFlatListView::getReorderRemaining(pairs_list_t& remaining) const
891890 remaining.clear ();
892891 for (item_pair_t * pair : mItemPairs )
893892 {
894- if (!pair->first ->getVisible () || isInReorderGroup (pair)) continue ;
893+ if (!pair->first ->getVisible () || isInReorderGroup (pair))
894+ continue ;
895895 remaining.push_back (pair);
896896 }
897897}
@@ -903,12 +903,16 @@ void LLFlatListView::finishReorderDrag()
903903 pairs_list_t remaining;
904904 getReorderRemaining (remaining);
905905
906- // Resolve the drop boundary to the remaining row it lands before (NULL = append).
907- item_pair_t * anchor = NULL ;
906+ // Resolve the drop boundary to the remaining row it lands before (nullptr = append).
907+ item_pair_t * anchor = nullptr ;
908908 S32 cur = 0 ;
909909 for (item_pair_t * pair : remaining)
910910 {
911- if (cur == mReorderInsertIndex ) { anchor = pair; break ; }
911+ if (cur == mReorderInsertIndex )
912+ {
913+ anchor = pair;
914+ break ;
915+ }
912916 ++cur;
913917 }
914918
@@ -919,7 +923,7 @@ void LLFlatListView::finishReorderDrag()
919923 mItemPairs .remove (pair);
920924 }
921925
922- pairs_iterator_t it = (anchor != NULL )
926+ pairs_iterator_t it = (anchor != nullptr )
923927 ? std::find (mItemPairs .begin (), mItemPairs .end (), anchor)
924928 : mItemPairs .end ();
925929 for (item_pair_t * pair : mReorderDragGroup )
@@ -931,7 +935,17 @@ void LLFlatListView::finishReorderDrag()
931935
932936 if (mReorderCallback )
933937 {
934- mReorderCallback (moved_value, mReorderInsertIndex );
938+ S32 visible_index = 0 ;
939+ for (item_pair_t * pair : mItemPairs )
940+ {
941+ if (!pair->first ->getVisible ())
942+ continue ;
943+ if (pair == mReorderDragPair )
944+ break ;
945+ ++visible_index;
946+ }
947+
948+ mReorderCallback (moved_value, visible_index);
935949 }
936950 }
937951
@@ -942,7 +956,7 @@ void LLFlatListView::cancelReorderDrag()
942956{
943957 if (hasMouseCapture ())
944958 {
945- gFocusMgr .setMouseCapture (NULL );
959+ gFocusMgr .setMouseCapture (nullptr );
946960 }
947961
948962 clearReorderDragState ();
@@ -954,18 +968,36 @@ void LLFlatListView::clearReorderDragState()
954968 {
955969 getWindow ()->setCursor (UI_CURSOR_ARROW );
956970 }
957- mReorderDragPair = NULL ;
971+
972+ bool was_armed = (mReorderDragPair != nullptr );
973+
974+ mReorderDragPair = nullptr ;
958975 mReorderDragGroup .clear ();
959- mDeferredSelectPair = NULL ;
976+ mDeferredSelectPair = nullptr ;
960977 mIsReordering = false ;
961978 mReorderInsertIndex = -1 ;
979+
980+ if (was_armed && mReorderEndedCallback )
981+ {
982+ mReorderEndedCallback ();
983+ }
962984}
963985
964986void LLFlatListView::onMouseCaptureLost ()
965987{
966988 clearReorderDragState ();
967989}
968990
991+ void LLFlatListView::onVisibilityChange (bool new_visibility)
992+ {
993+ if (!new_visibility && mReorderDragPair )
994+ {
995+ cancelReorderDrag ();
996+ }
997+
998+ LLScrollContainer::onVisibilityChange (new_visibility);
999+ }
1000+
9691001S32 LLFlatListView::getInsertIndexAt (S32 x, S32 y) const
9701002{
9711003 S32 panel_x, panel_y;
@@ -976,7 +1008,8 @@ S32 LLFlatListView::getInsertIndexAt(S32 x, S32 y) const
9761008 S32 index = 0 ;
9771009 for (item_pair_t * pair : mItemPairs )
9781010 {
979- if (!pair->first ->getVisible () || isInReorderGroup (pair)) continue ;
1011+ if (!pair->first ->getVisible () || isInReorderGroup (pair))
1012+ continue ;
9801013
9811014 if (pair->first ->getRect ().getCenterY () > panel_y)
9821015 {
@@ -986,9 +1019,31 @@ S32 LLFlatListView::getInsertIndexAt(S32 x, S32 y) const
9861019 return index;
9871020}
9881021
1022+ LLFlatListView::item_pair_t * LLFlatListView::getReorderPairAt (S32 x, S32 y) const
1023+ {
1024+ S32 panel_x, panel_y;
1025+ localPointToOtherView (x, y, &panel_x, &panel_y, mItemsPanel );
1026+
1027+ for (item_pair_t * pair : mItemPairs )
1028+ {
1029+ if (!pair->first ->getVisible ())
1030+ continue ;
1031+
1032+ // Claim the padding above each row so gap presses still resolve to a row.
1033+ LLRect rc = pair->first ->getRect ();
1034+ rc.mTop += mItemPad ;
1035+ if (rc.pointInRect (panel_x, panel_y))
1036+ {
1037+ return pair;
1038+ }
1039+ }
1040+ return nullptr ;
1041+ }
1042+
9891043S32 LLFlatListView::constrainInsertIndex (S32 dest_index) const
9901044{
991- if (!mReorderValidateCallback ) return dest_index;
1045+ if (!mReorderValidateCallback )
1046+ return dest_index;
9921047
9931048 // Clamp the boundary to the contiguous run of remaining rows that share the
9941049 // grabbed row's group, so a drag can't leave its group.
@@ -1003,24 +1058,29 @@ S32 LLFlatListView::constrainInsertIndex(S32 dest_index) const
10031058 {
10041059 if (mReorderValidateCallback (dragged, pair->second ))
10051060 {
1006- if (first_valid < 0 ) first_valid = i;
1061+ if (first_valid < 0 )
1062+ first_valid = i;
10071063 last_valid = i;
10081064 }
10091065 ++i;
10101066 }
10111067
1012- if (first_valid < 0 ) return -1 ; // no valid neighbour (whole group is being dragged)
1068+ if (first_valid < 0 )
1069+ return -1 ; // no valid neighbour (whole group is being dragged)
10131070
1014- if (dest_index < first_valid) return first_valid;
1015- if (dest_index > last_valid + 1 ) return last_valid + 1 ;
1071+ if (dest_index < first_valid)
1072+ return first_valid;
1073+ if (dest_index > last_valid + 1 )
1074+ return last_valid + 1 ;
10161075 return dest_index;
10171076}
10181077
10191078void LLFlatListView::drawReorderIndicator ()
10201079{
10211080 pairs_list_t remaining;
10221081 getReorderRemaining (remaining);
1023- if (remaining.empty ()) return ;
1082+ if (remaining.empty ())
1083+ return ;
10241084
10251085 const LLRect& panel_rc = mItemsPanel ->getRect ();
10261086 const LLColor4& color = mDragIndicatorColor .get ();
@@ -1039,21 +1099,27 @@ void LLFlatListView::drawReorderIndicator()
10391099 bool at_end = mReorderInsertIndex >= count;
10401100 S32 anchor_idx = at_end ? count - 1 : mReorderInsertIndex ;
10411101
1042- item_pair_t * anchor = NULL ;
1102+ item_pair_t * anchor = nullptr ;
10431103 S32 cur = 0 ;
10441104 for (item_pair_t * pair : remaining)
10451105 {
1046- if (cur == anchor_idx) { anchor = pair; break ; }
1106+ if (cur == anchor_idx)
1107+ {
1108+ anchor = pair;
1109+ break ;
1110+ }
10471111 ++cur;
10481112 }
1049- if (!anchor) return ;
1113+ if (!anchor)
1114+ return ;
10501115
10511116 const LLRect& item_rc = anchor->first ->getRect ();
10521117 S32 left = panel_rc.mLeft + item_rc.mLeft ;
10531118 S32 right = panel_rc.mLeft + item_rc.mRight ;
10541119 S32 line_y = panel_rc.mBottom + (at_end ? item_rc.mBottom : item_rc.mTop );
10551120
1056- if (line_y < 0 || line_y > getRect ().getHeight ()) return ;
1121+ if (line_y < 0 || line_y > getRect ().getHeight ())
1122+ return ;
10571123
10581124 gl_rect_2d (left, line_y, right, line_y - 1 , color, true );
10591125}
@@ -1072,13 +1138,31 @@ bool LLFlatListView::handleHover(S32 x, S32 y, MASK mask)
10721138 return LLScrollContainer::handleHover (x, y, mask);
10731139}
10741140
1141+ bool LLFlatListView::handleMouseDown (S32 x, S32 y, MASK mask)
1142+ {
1143+ bool handled = LLScrollContainer::handleMouseDown (x, y, mask);
1144+
1145+ // A press in the padding between rows misses every item, so the per-item
1146+ // mouse-down never arms a reorder. Map it to the nearest row and arm there;
1147+ // armReorderDrag's capture guard ignores presses a child control already took.
1148+ if (mAllowReorder && !mReorderDragPair && !(mask & (MASK_CONTROL | MASK_SHIFT )))
1149+ {
1150+ if (item_pair_t * pair = getReorderPairAt (x, y))
1151+ {
1152+ onItemMouseClick (pair, mask, CLICK_LEFT );
1153+ }
1154+ }
1155+
1156+ return handled || (mReorderDragPair != nullptr );
1157+ }
1158+
10751159bool LLFlatListView::handleMouseUp (S32 x, S32 y, MASK mask)
10761160{
10771161 if (mReorderDragPair && hasMouseCapture ())
10781162 {
10791163 bool was_reordering = mIsReordering ;
10801164 item_pair_t * deferred = mDeferredSelectPair ;
1081- mDeferredSelectPair = NULL ;
1165+ mDeferredSelectPair = nullptr ;
10821166
10831167 finishReorderDrag ();
10841168
@@ -1475,7 +1559,7 @@ bool LLFlatListView::removeItemPair(item_pair_t* item_pair, bool rearrange)
14751559 }
14761560 if (item_pair == mDeferredSelectPair )
14771561 {
1478- mDeferredSelectPair = NULL ;
1562+ mDeferredSelectPair = nullptr ;
14791563 }
14801564
14811565 bool deleted = false ;
0 commit comments