Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add drag and drop reordering feature #53

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NoFences/FenceWindow.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 84 additions & 15 deletions NoFences/FenceWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public partial class FenceWindow : Form
private const int textHeight = 35;
private const int itemPadding = 15;
private const float shadowDist = 1.5f;
private const int mouseClickMaxOffset = 10;

private readonly FenceInfo fenceInfo;

Expand All @@ -28,6 +29,7 @@ public partial class FenceWindow : Form

private string selectedItem;
private string hoveringItem;
private string draggedItem;
private bool shouldUpdateSelection;
private bool shouldRunDoubleClick;
private bool hasSelectionUpdated;
Expand All @@ -38,6 +40,8 @@ public partial class FenceWindow : Form
private int scrollHeight;
private int scrollOffset;

private Point mouseDragStartingPosition;

private readonly ThrottledExecution throttledMove = new ThrottledExecution(TimeSpan.FromSeconds(4));
private readonly ThrottledExecution throttledResize = new ThrottledExecution(TimeSpan.FromSeconds(4));

Expand Down Expand Up @@ -111,7 +115,7 @@ protected override void WndProc(ref Message m)

// Prevent foreground
if (m.Msg == WM_SETFOCUS)
{
{
SetWindowPos(Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
return;
}
Expand Down Expand Up @@ -204,7 +208,18 @@ private void FenceWindow_Resize(object sender, EventArgs e)

private void FenceWindow_MouseMove(object sender, MouseEventArgs e)
{
Refresh();
if (!lockedToolStripMenuItem.Checked)
{
bool mouseIsDown = e.Button == MouseButtons.Left;
bool isDragging = mouseIsDown && Extensions.Distance(mouseDragStartingPosition, PointToClient(MousePosition)) > mouseClickMaxOffset;
if (isDragging && hoveringItem != null && draggedItem == null)
{

draggedItem = hoveringItem;
}
}

Refresh();
}

private void FenceWindow_MouseEnter(object sender, EventArgs e)
Expand Down Expand Up @@ -246,12 +261,46 @@ private void minifyToolStripMenuItem_Click(object sender, EventArgs e)

}

private void FenceWindow_Click(object sender, EventArgs e)
private void FenceWindow_Down(object sender, MouseEventArgs e)
{
if (!lockedToolStripMenuItem.Checked)
{
if (e.Button == MouseButtons.Left)
{
mouseDragStartingPosition = PointToClient(MousePosition);
}
}
shouldUpdateSelection = true;
Refresh();
}

private void FenceWindow_Up(object sender, MouseEventArgs e)
{

if (e.Button == MouseButtons.Left)
{
if (!lockedToolStripMenuItem.Checked && hoveringItem != null && draggedItem != hoveringItem)
{
fenceInfo.Files.Remove(draggedItem);
int hoveringItemIndex = fenceInfo.Files.IndexOf(hoveringItem);
fenceInfo.Files.Insert(hoveringItemIndex, draggedItem);
}

mouseDragStartingPosition = PointToClient(Point.Empty);
draggedItem = null;
}
Refresh();
}

private void FenceWindow_Click(object sender, EventArgs e)
{
double distanceFromMouseDown = Extensions.Distance(mouseDragStartingPosition, PointToClient(MousePosition));
if (distanceFromMouseDown <= mouseClickMaxOffset)
{
shouldUpdateSelection = true;
Refresh();
}
}
private void FenceWindow_DoubleClick(object sender, EventArgs e)
{
shouldRunDoubleClick = true;
Expand Down Expand Up @@ -340,6 +389,8 @@ private void RenderEntry(Graphics g, FenceEntry entry, int x, int y)
var mousePos = PointToClient(MousePosition);
var mouseOver = mousePos.X >= x && mousePos.Y >= y && mousePos.X < x + outlineRect.Width && mousePos.Y < y + outlineRect.Height;

var isBeingDragged = draggedItem == entry.Path;

if (mouseOver)
{
hoveringItem = entry.Path;
Expand All @@ -359,31 +410,50 @@ private void RenderEntry(Graphics g, FenceEntry entry, int x, int y)
entry.Open();
}

if (selectedItem == entry.Path)
if (draggedItem != null)
{
if (mouseOver)
if (isBeingDragged)
{
g.DrawRectangle(new Pen(Color.FromArgb(120, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(100, SystemColors.GradientActiveCaption)), outlineRect);
g.DrawRectangle(new Pen(Color.FromArgb(30, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(20, SystemColors.GradientActiveCaption)), outlineRect);
}
else
else if (mouseOver)
{
g.DrawRectangle(new Pen(Color.FromArgb(120, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(80, SystemColors.GradientInactiveCaption)), outlineRect);
int markerHeight = itemHeight / 2;
int markerX = x - itemPadding / 2;
int verticalCenter = y + 32;
g.DrawLine(
new Pen(Color.FromArgb(120, SystemColors.ActiveBorder), 1f),
new Point(markerX, verticalCenter - markerHeight / 2),
new Point(markerX, verticalCenter + markerHeight / 2)
);
}
}
else
else
{
if (mouseOver)
if (selectedItem == entry.Path)
{
if (mouseOver)
{
g.DrawRectangle(new Pen(Color.FromArgb(120, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(100, SystemColors.GradientActiveCaption)), outlineRect);
}
else
{
g.DrawRectangle(new Pen(Color.FromArgb(120, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(80, SystemColors.GradientInactiveCaption)), outlineRect);
}
}
else if (mouseOver)
{
g.DrawRectangle(new Pen(Color.FromArgb(120, SystemColors.ActiveBorder)), outlineRectInner);
g.FillRectangle(new SolidBrush(Color.FromArgb(80, SystemColors.ActiveCaption)), outlineRect);
}
}

g.DrawIcon(icon, x + itemWidth / 2 - icon.Width / 2, y);
g.DrawString(name, iconFont, new SolidBrush(Color.FromArgb(180, 15, 15, 15)), new RectangleF(textPosition.Move(shadowDist, shadowDist), textMaxSize), stringFormat);
g.DrawString(name, iconFont, Brushes.White, new RectangleF(textPosition, textMaxSize), stringFormat);
g.DrawString(name, iconFont, new SolidBrush(Color.FromArgb(isBeingDragged ? 50 : 180, 15, 15, 15)), new RectangleF(textPosition.Move(shadowDist, shadowDist), textMaxSize), stringFormat);
g.DrawString(name, iconFont, new SolidBrush(Color.FromArgb(isBeingDragged ? 100 : 255, 255, 255, 255)), new RectangleF(textPosition, textMaxSize), stringFormat);
}

private void renameToolStripMenuItem_Click(object sender, EventArgs e)
Expand Down Expand Up @@ -497,6 +567,5 @@ private bool ItemExists(string path)
return File.Exists(path) || Directory.Exists(path);
}
}

}

8 changes: 7 additions & 1 deletion NoFences/Util/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Drawing;
using System;
using System.Drawing;

namespace NoFences.Util
{
Expand All @@ -16,5 +17,10 @@ public static Rectangle Shrink(this Rectangle rect, int offset)
return new Rectangle(rect.X + offset, rect.Y + offset, rect.Width - offset * 2, rect.Height - offset * 2);
}

public static double Distance(this Point p1, Point p2)
{
return Math.Round(Math.Sqrt(Math.Pow((p2.X - p1.X), 2) + Math.Pow((p2.Y - p1.Y), 2)), 1);
}

}
}