Skip to content

Commit

Permalink
Merge pull request #2519 from cwensley/curtis/wpf-scroll-grid-on-drag…
Browse files Browse the repository at this point in the history
…over

Wpf: Auto scroll Tree/GridView when cursor nears edge during drag/drop
  • Loading branch information
cwensley authored Jul 13, 2023
2 parents 4a3cdbc + ced4704 commit 2b141d2
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/Eto.Wpf/Forms/Controls/GridHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ public abstract class GridHandler<TWidget, TCallback> : WpfControl<EtoDataGrid,
where TWidget : Grid
where TCallback : Grid.ICallback
{
DateTime? startDragOverTime;
const int DragScrollSize = 12;
const int DragScrollFastSize = 6;
const double DragScrollDelay = 0.1;
const double DragScrollFastDelay = 0.01;

ContextMenu contextMenu;
bool hasFocus;
protected bool SkipSelectionChanged { get; set; }
Expand Down Expand Up @@ -993,5 +999,63 @@ public void OnColumnWidthChanged(GridColumnHandler gridColumnHandler)
var cellType = cellInfo.IsHeader ? GridCellType.ColumnHeader : rowIndex != -1 && columnIndex != -1 ? GridCellType.Data : GridCellType.None;
return (column, columnIndex, rowIndex, cellType, item);
}

swc.ScrollViewer ScrollViewer => Control.FindChild<swc.ScrollViewer>();

protected override void HandleDragOver(sw.DragEventArgs e, Eto.Forms.DragEventArgs args)
{
base.HandleDragOver(e, args);

var scrollViewer = ScrollViewer;
if (scrollViewer == null)
return;

void ScrollWithIncrement(bool fast, double increment)
{
var now = DateTime.Now;
if (startDragOverTime == null)
{
startDragOverTime = now;
return;
}

var diff = now - startDragOverTime;
if (diff > TimeSpan.FromSeconds(fast ? DragScrollFastDelay : DragScrollDelay))
{
startDragOverTime = now;
var oldOffset = scrollViewer.VerticalOffset;
var maxHeight = scrollViewer.ScrollableHeight;
var newOffset = Math.Min(maxHeight, Math.Max(0, oldOffset + increment));
if (newOffset != oldOffset)
scrollViewer.ScrollToVerticalOffset(newOffset);
}
}

var headerPart = ShowHeader ? Control.FindChild<swcp.DataGridColumnHeadersPresenter>("PART_ColumnHeadersPresenter") : null;
var headerHeight = headerPart?.ActualHeight ?? 0;

// scroll up or down when the user drags close to the edge
if (args.Location.Y < headerHeight + DragScrollSize)
{
ScrollWithIncrement(args.Location.Y < headerHeight + DragScrollFastSize, -1);
return;
}

var height = Control.ActualHeight;
if (scrollViewer.ComputedHorizontalScrollBarVisibility == Visibility.Visible)
{
var child = scrollViewer.FindChild<swcp.ScrollBar>("PART_HorizontalScrollBar");
height -= child.ActualHeight;
}

if (args.Location.Y > height - DragScrollSize)
{
ScrollWithIncrement(args.Location.Y > height - DragScrollFastSize, 1);
return;
}

// not in a drag scroll area, reset
startDragOverTime = null;
}
}
}

0 comments on commit 2b141d2

Please sign in to comment.