Add project files.

This commit is contained in:
Ankitkumar Satapara
2026-04-17 22:31:58 +05:30
commit 21aaef6776
473 changed files with 50152 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System;
using System.Linq;
using System.Windows;
namespace Nodify
{
internal static class AlignmentExtensions
{
public static void Align(this IEnumerable<ItemContainer> values, Alignment alignment, ItemContainer? relativeTo)
{
var containers = values as IReadOnlyCollection<ItemContainer> ?? values.ToList();
switch (alignment)
{
case Alignment.Top:
AlignTop(containers, relativeTo);
break;
case Alignment.Left:
AlignLeft(containers, relativeTo);
break;
case Alignment.Bottom:
AlignBottom(containers, relativeTo);
break;
case Alignment.Right:
AlignRight(containers, relativeTo);
break;
case Alignment.Middle:
AlignMiddle(containers, relativeTo);
break;
case Alignment.Center:
AlignCenter(containers, relativeTo);
break;
default:
throw new ArgumentOutOfRangeException(nameof(alignment), alignment, null);
}
}
private static void AlignTop(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double top = instigator?.Location.Y ?? containers.Min(x => x.Location.Y);
foreach (var c in containers)
{
c.Location = new Point(c.Location.X, top);
}
}
private static void AlignLeft(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double left = instigator?.Location.X ?? containers.Min(x => x.Location.X);
foreach (var c in containers)
{
c.Location = new Point(left, c.Location.Y);
}
}
private static void AlignBottom(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double bottom = instigator != null ? instigator.Location.Y + instigator.ActualHeight : containers.Max(x => x.Location.Y + x.ActualHeight);
foreach (var c in containers)
{
c.Location = new Point(c.Location.X, bottom - c.ActualHeight);
}
}
private static void AlignRight(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double right = instigator != null ? instigator.Location.X + instigator.ActualWidth : containers.Max(x => x.Location.X + x.ActualWidth);
foreach (var c in containers)
{
c.Location = new Point(right - c.ActualWidth, c.Location.Y);
}
}
private static void AlignMiddle(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double mid = instigator != null ? instigator.Location.Y + instigator.ActualHeight / 2 : containers.Average(c => c.Location.Y + c.ActualHeight / 2);
foreach (var c in containers)
{
c.Location = new Point(c.Location.X, mid - c.ActualHeight / 2);
}
}
private static void AlignCenter(IReadOnlyCollection<ItemContainer> containers, ItemContainer? instigator)
{
double center = instigator != null ? instigator.Location.X + instigator.ActualWidth / 2 : containers.Average(c => c.Location.X + c.ActualWidth / 2);
foreach (var c in containers)
{
c.Location = new Point(center - c.ActualWidth / 2, c.Location.Y);
}
}
}
}

View File

@@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
namespace Nodify
{
/// <summary>
/// Updates the RenderTransform to preview the container position and commits the position changes at the end of the operation.
/// </summary>
internal sealed class DraggingOptimized : IDraggingStrategy
{
private readonly uint _gridCellSize;
private readonly List<ItemContainer> _selectedContainers;
private Vector _dragAccumulator = new Vector(0, 0);
public Vector Offset { get; private set; }
public IReadOnlyCollection<ItemContainer> Containers => _selectedContainers;
public DraggingOptimized(IEnumerable<ItemContainer> containers, uint gridCellSize)
{
_gridCellSize = gridCellSize;
_selectedContainers = containers.Where(c => c.IsDraggable).ToList();
}
public void Abort()
{
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
var r = (TranslateTransform)container.RenderTransform;
r.X = 0;
r.Y = 0;
container.OnPreviewLocationChanged(container.Location);
}
_selectedContainers.Clear();
}
public void End()
{
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
var r = (TranslateTransform)container.RenderTransform;
Point result = container.Location + new Vector(r.X, r.Y);
// Correct the final position
if (NodifyEditor.EnableSnappingCorrection && (r.X != 0 || r.Y != 0))
{
result.X = (int)result.X / _gridCellSize * _gridCellSize;
result.Y = (int)result.Y / _gridCellSize * _gridCellSize;
}
container.Location = result;
r.X = 0;
r.Y = 0;
}
_selectedContainers.Clear();
}
public void Update(Vector change)
{
_dragAccumulator += change;
var delta = new Vector((int)_dragAccumulator.X / _gridCellSize * _gridCellSize, (int)_dragAccumulator.Y / _gridCellSize * _gridCellSize);
_dragAccumulator -= delta;
if (delta.X != 0 || delta.Y != 0)
{
Offset += delta;
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
var r = (TranslateTransform)container.RenderTransform;
r.X += delta.X; // Snapping without correction
r.Y += delta.Y; // Snapping without correction
container.OnPreviewLocationChanged(container.Location + new Vector(r.X, r.Y));
}
}
}
}
}

View File

@@ -0,0 +1,80 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace Nodify
{
internal interface IDraggingStrategy
{
IReadOnlyCollection<ItemContainer> Containers { get; }
Vector Offset { get; }
void Update(Vector change);
void End();
void Abort();
}
internal sealed class DraggingSimple : IDraggingStrategy
{
private readonly uint _gridCellSize;
private readonly List<ItemContainer> _selectedContainers;
private Vector _dragAccumulator = new Vector(0, 0);
public Vector Offset { get; private set; }
public IReadOnlyCollection<ItemContainer> Containers => _selectedContainers;
public DraggingSimple(IEnumerable<ItemContainer> containers, uint gridCellSize)
{
_gridCellSize = gridCellSize;
_selectedContainers = containers.Where(c => c.IsDraggable).ToList();
}
public void Abort()
{
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
container.Location -= Offset;
}
_selectedContainers.Clear();
}
public void End()
{
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
Point result = container.Location;
// Correct the final position
if (NodifyEditor.EnableSnappingCorrection)
{
result.X = (int)result.X / _gridCellSize * _gridCellSize;
result.Y = (int)result.Y / _gridCellSize * _gridCellSize;
}
container.Location = result;
}
_selectedContainers.Clear();
}
public void Update(Vector change)
{
_dragAccumulator += change;
var delta = new Vector((int)_dragAccumulator.X / _gridCellSize * _gridCellSize, (int)_dragAccumulator.Y / _gridCellSize * _gridCellSize);
_dragAccumulator -= delta;
if (delta.X != 0 || delta.Y != 0)
{
Offset += delta;
for (var i = 0; i < _selectedContainers.Count; i++)
{
ItemContainer container = _selectedContainers[i];
container.Location = new Point(container.Location.X + delta.X, container.Location.Y + delta.Y);
}
}
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace Nodify
{
internal interface IPushStrategy
{
Rect Start(Point position);
Rect Push(Vector amount);
Rect End();
Rect Cancel();
Rect GetPushedArea();
}
internal abstract class BasePushStrategy : IPushStrategy
{
private const double _minOffset = 2;
private double _actualOffset;
private double _initialPosition;
protected readonly NodifyEditor Editor;
protected const double OffscreenOffset = 100d;
public BasePushStrategy(NodifyEditor editor)
{
Editor = editor;
}
public Rect Start(Point position)
{
var containers = GetFilteredContainers(position);
Editor.BeginDragging(containers);
_initialPosition = GetInitialPosition(position);
_actualOffset = 0;
return CalculatePushedArea(_initialPosition, _actualOffset);
}
public Rect Push(Vector amount)
{
var offset = GetPushOffset(amount);
Editor.UpdateDragging(offset);
_actualOffset += offset.X;
_actualOffset += offset.Y;
double newPosition = _actualOffset >= 0 ? _initialPosition : Editor.SnapToGrid(_initialPosition + _actualOffset);
double newOffset = Math.Max(_minOffset, Editor.SnapToGrid(_actualOffset));
return CalculatePushedArea(newPosition, newOffset);
}
public Rect End()
{
Editor.EndDragging();
return new Rect();
}
public Rect Cancel()
{
Editor.CancelDragging();
return new Rect();
}
protected abstract IEnumerable<ItemContainer> GetFilteredContainers(Point position);
protected abstract double GetInitialPosition(Point position);
protected abstract Vector GetPushOffset(Vector offset);
protected abstract Rect CalculatePushedArea(double position, double offset);
public abstract Rect GetPushedArea();
}
internal sealed class HorizontalPushStrategy : BasePushStrategy
{
public HorizontalPushStrategy(NodifyEditor editor) : base(editor)
{
}
protected override IEnumerable<ItemContainer> GetFilteredContainers(Point position)
=> Editor.ItemContainers.Where(item => item.Location.X >= position.X);
protected override double GetInitialPosition(Point position)
=> position.X;
protected override Vector GetPushOffset(Vector offset)
=> new Vector(offset.X, 0d);
protected override Rect CalculatePushedArea(double position, double offset)
=> new Rect(position, Editor.ViewportLocation.Y - OffscreenOffset, offset, Editor.ViewportSize.Height + OffscreenOffset * 2);
public override Rect GetPushedArea()
=> CalculatePushedArea(Editor.PushedArea.X, Editor.PushedArea.Width);
}
internal sealed class VerticalPushStrategy : BasePushStrategy
{
public VerticalPushStrategy(NodifyEditor editor) : base(editor)
{
}
protected override IEnumerable<ItemContainer> GetFilteredContainers(Point position)
=> Editor.ItemContainers.Where(item => item.Location.Y >= position.Y);
protected override double GetInitialPosition(Point position)
=> position.Y;
protected override Vector GetPushOffset(Vector offset)
=> new Vector(0d, offset.Y);
protected override Rect CalculatePushedArea(double position, double offset)
=> new Rect(Editor.ViewportLocation.X - OffscreenOffset, position, Editor.ViewportSize.Width + OffscreenOffset * 2, offset);
public override Rect GetPushedArea()
=> CalculatePushedArea(Editor.PushedArea.Y, Editor.PushedArea.Height);
}
}