269 lines
9.0 KiB
C#
269 lines
9.0 KiB
C#
using CtrEditor.ObjetosSim;
|
|
using System.Collections.ObjectModel;
|
|
using System.Windows;
|
|
|
|
namespace CtrEditor
|
|
{
|
|
public class ObjectAlignment
|
|
{
|
|
private readonly ObservableCollection<osBase> _selectedObjects;
|
|
private readonly osBase _referenceObject;
|
|
|
|
public ObjectAlignment(ObservableCollection<osBase> selectedObjects, osBase referenceObject = null)
|
|
{
|
|
_selectedObjects = selectedObjects;
|
|
_referenceObject = referenceObject ?? selectedObjects.FirstOrDefault();
|
|
}
|
|
|
|
public void AlignLeft()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float leftMost = _selectedObjects.Min(obj => obj.Left);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Left = leftMost;
|
|
}
|
|
}
|
|
|
|
public void AlignRight()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float rightMost = _selectedObjects.Max(obj => obj.Left + obj.Ancho);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Left = rightMost - obj.Ancho;
|
|
}
|
|
}
|
|
|
|
public void AlignTop()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float topMost = _selectedObjects.Min(obj => obj.Top);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Top = topMost;
|
|
}
|
|
}
|
|
|
|
public void AlignBottom()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float bottomMost = _selectedObjects.Max(obj => obj.Top + obj.Alto);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Top = bottomMost - obj.Alto;
|
|
}
|
|
}
|
|
|
|
public void AlignCenterHorizontally()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float averageY = _selectedObjects.Average(obj => obj.Top + obj.Alto / 2);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Top = averageY - obj.Alto / 2;
|
|
}
|
|
}
|
|
|
|
public void AlignCenterVertically()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float averageX = _selectedObjects.Average(obj => obj.Left + obj.Ancho / 2);
|
|
foreach (var obj in _selectedObjects)
|
|
{
|
|
obj.Left = averageX - obj.Ancho / 2;
|
|
}
|
|
}
|
|
|
|
public void DistributeHorizontally()
|
|
{
|
|
if (_selectedObjects.Count <= 2) return;
|
|
|
|
var objectsWithCenters = _selectedObjects
|
|
.Select(obj => new
|
|
{
|
|
Object = obj,
|
|
Center = GetObjectCenter(obj),
|
|
Dimensions = GetEffectiveDimensions(obj)
|
|
})
|
|
.OrderBy(x => x.Center.X)
|
|
.ToList();
|
|
|
|
float leftMost = (float)objectsWithCenters.First().Center.X;
|
|
float rightMost = (float)objectsWithCenters.Last().Center.X;
|
|
float totalDistance = rightMost - leftMost;
|
|
float spacing = totalDistance / (_selectedObjects.Count - 1);
|
|
|
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
|
{
|
|
var obj = objectsWithCenters[i];
|
|
var targetX = leftMost + (spacing * i);
|
|
float deltaX = (float)(targetX - obj.Center.X);
|
|
obj.Object.Left += deltaX;
|
|
}
|
|
}
|
|
|
|
public void DistributeVertically()
|
|
{
|
|
if (_selectedObjects.Count <= 2) return;
|
|
|
|
var objectsWithCenters = _selectedObjects
|
|
.Select(obj => new
|
|
{
|
|
Object = obj,
|
|
Center = GetObjectCenter(obj),
|
|
Dimensions = GetEffectiveDimensions(obj)
|
|
})
|
|
.OrderBy(x => x.Center.Y)
|
|
.ToList();
|
|
|
|
float topMost = (float)objectsWithCenters.First().Center.Y;
|
|
float bottomMost = (float)objectsWithCenters.Last().Center.Y;
|
|
float totalDistance = bottomMost - topMost;
|
|
float spacing = totalDistance / (_selectedObjects.Count - 1);
|
|
|
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
|
{
|
|
var obj = objectsWithCenters[i];
|
|
var targetY = topMost + (spacing * i);
|
|
float deltaY = (float)(targetY - obj.Center.Y);
|
|
obj.Object.Top += deltaY;
|
|
}
|
|
}
|
|
|
|
public void EqualWidth()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float referenceWidth = GetEffectiveDimensions(_referenceObject).Width;
|
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
|
{
|
|
var currentDims = GetEffectiveDimensions(obj);
|
|
SetEffectiveDimensions(obj, referenceWidth, currentDims.Height);
|
|
}
|
|
}
|
|
|
|
public void EqualHeight()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float referenceHeight = GetEffectiveDimensions(_referenceObject).Height;
|
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
|
{
|
|
var currentDims = GetEffectiveDimensions(obj);
|
|
SetEffectiveDimensions(obj, currentDims.Width, referenceHeight);
|
|
}
|
|
}
|
|
|
|
public void EqualAngle()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
float referenceAngle = _referenceObject.Angulo;
|
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
|
{
|
|
obj.Angulo = referenceAngle;
|
|
}
|
|
}
|
|
|
|
public void JoinHorizontally()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
var sortedObjects = _selectedObjects
|
|
.OrderBy(obj => GetObjectCenter(obj).X)
|
|
.ToList();
|
|
|
|
for (int i = 1; i < sortedObjects.Count; i++)
|
|
{
|
|
var previousObj = sortedObjects[i - 1];
|
|
var currentObj = sortedObjects[i];
|
|
var previousCenter = GetObjectCenter(previousObj);
|
|
var currentCenter = GetObjectCenter(currentObj);
|
|
var previousDims = GetEffectiveDimensions(previousObj);
|
|
|
|
float offset = previousDims.Width / 2;
|
|
float newX = (float)(previousCenter.X + offset);
|
|
float deltaX = (float)(newX - (currentCenter.X - GetEffectiveDimensions(currentObj).Width / 2));
|
|
currentObj.Left += deltaX;
|
|
}
|
|
}
|
|
|
|
public void JoinVertically()
|
|
{
|
|
if (_selectedObjects.Count <= 1) return;
|
|
|
|
var sortedObjects = _selectedObjects
|
|
.OrderBy(obj => GetObjectCenter(obj).Y)
|
|
.ToList();
|
|
|
|
for (int i = 1; i < sortedObjects.Count; i++)
|
|
{
|
|
var previousObj = sortedObjects[i - 1];
|
|
var currentObj = sortedObjects[i];
|
|
var previousCenter = GetObjectCenter(previousObj);
|
|
var currentCenter = GetObjectCenter(currentObj);
|
|
var previousDims = GetEffectiveDimensions(previousObj);
|
|
|
|
float offset = previousDims.Height / 2;
|
|
float newY = (float)(previousCenter.Y + offset);
|
|
float deltaY = (float)(newY - (currentCenter.Y - GetEffectiveDimensions(currentObj).Height / 2));
|
|
currentObj.Top += deltaY;
|
|
}
|
|
}
|
|
|
|
private Point GetObjectCenter(osBase obj)
|
|
{
|
|
double angleRad = obj.Angulo * Math.PI / 180.0;
|
|
float centerX = obj.Left + (obj.Ancho / 2);
|
|
float centerY = obj.Top + (obj.Alto / 2);
|
|
|
|
if (obj.Angulo != 0)
|
|
{
|
|
var rotatedX = obj.Left + (Math.Cos(angleRad) * obj.Ancho / 2 - Math.Sin(angleRad) * obj.Alto / 2);
|
|
var rotatedY = obj.Top + (Math.Sin(angleRad) * obj.Ancho / 2 + Math.Cos(angleRad) * obj.Alto / 2);
|
|
|
|
return new Point(rotatedX, rotatedY);
|
|
}
|
|
|
|
return new Point(centerX, centerY);
|
|
}
|
|
|
|
private bool IsObjectVertical(osBase obj)
|
|
{
|
|
double normalizedAngle = obj.Angulo % 180;
|
|
if (normalizedAngle < 0) normalizedAngle += 180;
|
|
return normalizedAngle >= 45 && normalizedAngle < 135;
|
|
}
|
|
|
|
private (float Width, float Height) GetEffectiveDimensions(osBase obj)
|
|
{
|
|
if (IsObjectVertical(obj))
|
|
{
|
|
return (obj.Alto, obj.Ancho);
|
|
}
|
|
return (obj.Ancho, obj.Alto);
|
|
}
|
|
|
|
private void SetEffectiveDimensions(osBase obj, float width, float height)
|
|
{
|
|
if (IsObjectVertical(obj))
|
|
{
|
|
obj.Alto = width;
|
|
obj.Ancho = height;
|
|
}
|
|
else
|
|
{
|
|
obj.Ancho = width;
|
|
obj.Alto = height;
|
|
}
|
|
}
|
|
}
|
|
}
|