3030#include " llpanel.h"
3131#include " llscrollcontainer.h"
3232#include " lltextbox.h"
33+ #include " lluicolor.h"
3334
3435
3536/* *
@@ -106,12 +107,28 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
106107 /* * padding between items */
107108 Optional<U32 > item_pad;
108109
110+ /* * allow items to be reordered by dragging them with the mouse */
111+ Optional<bool > allow_reorder;
112+
113+ /* * colour of the insertion indicator drawn while reordering */
114+ Optional<LLUIColor> drag_indicator_color;
115+
109116 /* * textbox with info message when list is empty*/
110117 Optional<LLTextBox::Params> no_items_text;
111118
112119 Params ();
113120 };
114121
122+ /* * Fired after the user drags an item to a new position: (moved value, new visible index). */
123+ typedef boost::function<void (const LLSD & value, S32 new_index)> reorder_signal_t ;
124+
125+ /* *
126+ * Returns true if the dragged item is allowed to move past the given neighbour.
127+ * Lets owners constrain reordering (e.g. keep items within a group). Optional;
128+ * when unset any reorder is permitted.
129+ */
130+ typedef boost::function<bool (const LLSD & dragged, const LLSD & neighbour)> reorder_validate_signal_t ;
131+
115132 // disable traversal when finding widget to hand focus off to
116133 /* virtual*/ bool canFocusChildren () const override { return false ; }
117134
@@ -265,6 +282,12 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
265282 /* * Turn on/off selection support */
266283 void setAllowSelection (bool can_select) { mAllowSelection = can_select; }
267284
285+ /* * Turn on/off drag-to-reorder support */
286+ void setAllowReorder (bool allow) { mAllowReorder = allow; }
287+
288+ void setReorderCallback (reorder_signal_t cb) { mReorderCallback = cb; }
289+ void setReorderValidateCallback (reorder_validate_signal_t cb) { mReorderValidateCallback = cb; }
290+
268291 /* * Sets flag whether onCommit should be fired if selection was changed */
269292 // FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly.
270293 void setCommitOnSelectionChange (bool b) { mCommitOnSelectionChange = b; }
@@ -374,6 +397,12 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
374397
375398 virtual bool handleKeyHere (KEY key, MASK mask) override ;
376399
400+ virtual bool handleHover (S32 x, S32 y, MASK mask) override ;
401+
402+ virtual bool handleMouseUp (S32 x, S32 y, MASK mask) override ;
403+
404+ virtual void onMouseCaptureLost () override ;
405+
377406 virtual bool postBuild () override ;
378407
379408 virtual void onFocusReceived () override ;
@@ -390,6 +419,26 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
390419
391420private:
392421
422+ // Drag-to-reorder helpers.
423+ void armReorderDrag (item_pair_t * item_pair);
424+ void updateReorderDrag (S32 x, S32 y);
425+ void finishReorderDrag ();
426+ void cancelReorderDrag ();
427+ void clearReorderDragState ();
428+
429+ // Builds the set of pairs being dragged (the whole selection when the grabbed
430+ // row is part of a multi-selection, constrained to the validator's group).
431+ void buildReorderGroup ();
432+ bool isInReorderGroup (item_pair_t * item_pair) const ;
433+
434+ // The remaining visible pairs (those not being dragged), in visual order.
435+ void getReorderRemaining (pairs_list_t & remaining) const ;
436+ // Number of leading non-dragged items whose centre sits above (x, y).
437+ S32 getInsertIndexAt (S32 x, S32 y) const ;
438+ // Clamps an insertion boundary to the validator's contiguous group.
439+ S32 constrainInsertIndex (S32 dest_index) const ;
440+ void drawReorderIndicator ();
441+
393442 void setItemsNoScrollWidth (S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness ;}
394443
395444 void setNoItemsCommentVisible (bool visible) const ;
@@ -433,6 +482,20 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
433482
434483 bool mFocusOnItemClicked ;
435484
485+ /* * Drag-to-reorder state */
486+ bool mAllowReorder ;
487+ bool mIsReordering ; // a drag is currently in progress
488+ bool mProcessingRightClick ; // suppress drag arming during right-click handling
489+ item_pair_t * mReorderDragPair ; // the grabbed pair (drag anchor)
490+ pairs_list_t mReorderDragGroup ; // all pairs being dragged, in visual order
491+ item_pair_t * mDeferredSelectPair ; // collapse selection to this on mouse-up if no drag
492+ S32 mReorderMouseDownX ;
493+ S32 mReorderMouseDownY ;
494+ S32 mReorderInsertIndex ; // current drop boundary among the remaining (non-dragged) items
495+ LLUIColor mDragIndicatorColor ;
496+ reorder_signal_t mReorderCallback ;
497+ reorder_validate_signal_t mReorderValidateCallback ;
498+
436499 /* * All pairs of the list */
437500 pairs_list_t mItemPairs ;
438501
0 commit comments