Mejorado de panning y zoom
This commit is contained in:
parent
67c6464ea1
commit
5ee91dd26a
|
@ -134,10 +134,12 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
_isDraggingCanvas = false;
|
_isDraggingCanvas = false;
|
||||||
ImagenEnTrabajoCanvas.ReleaseMouseCapture();
|
ImagenEnTrabajoCanvas.ReleaseMouseCapture();
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null)
|
if (_objectManager.SelectedObjects.Count > 0)
|
||||||
{
|
{
|
||||||
_objectManager.MakeResizeRectanglesNormal();
|
_objectManager.MakeResizeRectanglesNormal();
|
||||||
|
_objectManager.UpdateSelectionVisuals(); // Agregar esta línea
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
@ -147,12 +149,14 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
||||||
{
|
{
|
||||||
// Solo activar el panning si el clic fue directamente en el canvas
|
// Solo permitir el panning si el clic fue en el canvas o en la imagen de fondo
|
||||||
if (e.Source == ImagenEnTrabajoCanvas)
|
// y no en otros controles
|
||||||
|
if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo)
|
||||||
{
|
{
|
||||||
_isDraggingCanvas = true;
|
_isDraggingCanvas = true;
|
||||||
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||||
ImagenEnTrabajoCanvas.CaptureMouse();
|
ImagenEnTrabajoCanvas.CaptureMouse();
|
||||||
|
Mouse.OverrideCursor = Cursors.Hand;
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
|
@ -224,9 +228,10 @@ namespace CtrEditor
|
||||||
|
|
||||||
RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality);
|
RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality);
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null)
|
if (_objectManager.SelectedObjects.Count > 0)
|
||||||
{
|
{
|
||||||
_objectManager.MakeResizeRectanglesNormal();
|
_objectManager.MakeResizeRectanglesNormal();
|
||||||
|
_objectManager.UpdateSelectionVisuals(); // Agregar esta línea
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -298,8 +303,6 @@ namespace CtrEditor
|
||||||
_objectManager.ClearSelection();
|
_objectManager.ClearSelection();
|
||||||
_objectManager.RemoveResizeRectangles();
|
_objectManager.RemoveResizeRectangles();
|
||||||
|
|
||||||
// Desactivar el modo de selección múltiple
|
|
||||||
viewModel.IsMultiSelectionActive = false;
|
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
@ -373,9 +376,10 @@ namespace CtrEditor
|
||||||
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
// Aceptar el evento si viene del canvas o de la imagen de fondo
|
// Aceptar el evento si viene del canvas o de la imagen de fondo
|
||||||
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo) && DataContext is MainViewModel viewModel)
|
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo || e.Source is UserControl) &&
|
||||||
|
DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
e.Handled = true; // Importante: marcar el evento como manejado
|
e.Handled = true;
|
||||||
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
|
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +391,7 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
Header = "Modo Multi-Selección",
|
Header = "Modo Multi-Selección",
|
||||||
IsCheckable = true,
|
IsCheckable = true,
|
||||||
StaysOpenOnClick = false // Cerrar el menú al hacer clic
|
StaysOpenOnClick = false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
@ -397,6 +401,26 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
viewModel.IsMultiSelectionActive = multiSelectMenuItem.IsChecked;
|
viewModel.IsMultiSelectionActive = multiSelectMenuItem.IsChecked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Solo mostrar opciones de alineación si hay objetos seleccionados
|
||||||
|
if (_objectManager.SelectedObjects.Count > 1)
|
||||||
|
{
|
||||||
|
var alignmentMenu = new MenuItem { Header = "Alinear" };
|
||||||
|
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear a la Izquierda", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Left)) });
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear a la Derecha", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Right)) });
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear Arriba", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Top)) });
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear Abajo", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Bottom)) });
|
||||||
|
alignmentMenu.Items.Add(new Separator());
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Centrar Horizontalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.CenterHorizontally)) });
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Centrar Verticalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.CenterVertically)) });
|
||||||
|
alignmentMenu.Items.Add(new Separator());
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Distribuir Horizontalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.DistributeHorizontally)) });
|
||||||
|
alignmentMenu.Items.Add(new MenuItem { Header = "Distribuir Verticalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.DistributeVertically)) });
|
||||||
|
|
||||||
|
contextMenu.Items.Add(alignmentMenu);
|
||||||
|
contextMenu.Items.Add(new Separator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contextMenu.Items.Add(multiSelectMenuItem);
|
contextMenu.Items.Add(multiSelectMenuItem);
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
using CtrEditor.ObjetosSim;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace CtrEditor
|
||||||
|
{
|
||||||
|
public class ObjectAlignment
|
||||||
|
{
|
||||||
|
private readonly ObservableCollection<osBase> _selectedObjects;
|
||||||
|
|
||||||
|
public ObjectAlignment(ObservableCollection<osBase> selectedObjects)
|
||||||
|
{
|
||||||
|
_selectedObjects = selectedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Ordenar objetos por su centro X real (considerando rotación)
|
||||||
|
var objectsWithCenters = _selectedObjects
|
||||||
|
.Select(obj => new
|
||||||
|
{
|
||||||
|
Object = obj,
|
||||||
|
Center = GetObjectCenter(obj)
|
||||||
|
})
|
||||||
|
.OrderBy(x => x.Center.X)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Calcular el espacio total y el espaciado
|
||||||
|
float leftMost = (float)objectsWithCenters.First().Center.X;
|
||||||
|
float rightMost = (float)objectsWithCenters.Last().Center.X;
|
||||||
|
float totalWidth = rightMost - leftMost;
|
||||||
|
float spacing = totalWidth / (_selectedObjects.Count - 1);
|
||||||
|
|
||||||
|
// Distribuir objetos basados en sus centros
|
||||||
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
||||||
|
{
|
||||||
|
var obj = objectsWithCenters[i].Object;
|
||||||
|
var targetCenterX = leftMost + (spacing * i);
|
||||||
|
var currentCenter = GetObjectCenter(obj);
|
||||||
|
var deltaX = targetCenterX - currentCenter.X;
|
||||||
|
|
||||||
|
obj.Left += (float)deltaX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DistributeVertically()
|
||||||
|
{
|
||||||
|
if (_selectedObjects.Count <= 2) return;
|
||||||
|
|
||||||
|
// Ordenar objetos por su centro Y real (considerando rotación)
|
||||||
|
var objectsWithCenters = _selectedObjects
|
||||||
|
.Select(obj => new
|
||||||
|
{
|
||||||
|
Object = obj,
|
||||||
|
Center = GetObjectCenter(obj)
|
||||||
|
})
|
||||||
|
.OrderBy(x => x.Center.Y)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Calcular el espacio total y el espaciado
|
||||||
|
float topMost = (float)objectsWithCenters.First().Center.Y;
|
||||||
|
float bottomMost = (float)objectsWithCenters.Last().Center.Y;
|
||||||
|
float totalHeight = bottomMost - topMost;
|
||||||
|
float spacing = totalHeight / (_selectedObjects.Count - 1);
|
||||||
|
|
||||||
|
// Distribuir objetos basados en sus centros
|
||||||
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
||||||
|
{
|
||||||
|
var obj = objectsWithCenters[i].Object;
|
||||||
|
var targetCenterY = topMost + (spacing * i);
|
||||||
|
var currentCenter = GetObjectCenter(obj);
|
||||||
|
var deltaY = targetCenterY - currentCenter.Y;
|
||||||
|
|
||||||
|
obj.Top += (float)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);
|
||||||
|
|
||||||
|
// Si el objeto está rotado, calcular el centro real
|
||||||
|
if (obj.Angulo != 0)
|
||||||
|
{
|
||||||
|
// Obtener el centro después de la rotación
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,18 @@ using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace CtrEditor
|
namespace CtrEditor
|
||||||
{
|
{
|
||||||
|
public enum AlignmentType
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
CenterHorizontally,
|
||||||
|
CenterVertically,
|
||||||
|
DistributeHorizontally,
|
||||||
|
DistributeVertically
|
||||||
|
}
|
||||||
|
|
||||||
public class ObjectManipulationManager
|
public class ObjectManipulationManager
|
||||||
{
|
{
|
||||||
private enum ResizeMode
|
private enum ResizeMode
|
||||||
|
@ -69,7 +81,7 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSelectionVisuals()
|
public void UpdateSelectionVisuals()
|
||||||
{
|
{
|
||||||
RemoveResizeRectangles();
|
RemoveResizeRectangles();
|
||||||
if (_selectedObjects.Any())
|
if (_selectedObjects.Any())
|
||||||
|
@ -719,5 +731,43 @@ namespace CtrEditor
|
||||||
|
|
||||||
UpdateSelectionHighlights();
|
UpdateSelectionHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AlignObjects(AlignmentType alignmentType)
|
||||||
|
{
|
||||||
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
|
var alignment = new ObjectAlignment(_selectedObjects);
|
||||||
|
|
||||||
|
switch (alignmentType)
|
||||||
|
{
|
||||||
|
case AlignmentType.Left:
|
||||||
|
alignment.AlignLeft();
|
||||||
|
break;
|
||||||
|
case AlignmentType.Right:
|
||||||
|
alignment.AlignRight();
|
||||||
|
break;
|
||||||
|
case AlignmentType.Top:
|
||||||
|
alignment.AlignTop();
|
||||||
|
break;
|
||||||
|
case AlignmentType.Bottom:
|
||||||
|
alignment.AlignBottom();
|
||||||
|
break;
|
||||||
|
case AlignmentType.CenterHorizontally:
|
||||||
|
alignment.AlignCenterHorizontally();
|
||||||
|
break;
|
||||||
|
case AlignmentType.CenterVertically:
|
||||||
|
alignment.AlignCenterVertically();
|
||||||
|
break;
|
||||||
|
case AlignmentType.DistributeHorizontally:
|
||||||
|
alignment.DistributeHorizontally();
|
||||||
|
break;
|
||||||
|
case AlignmentType.DistributeVertically:
|
||||||
|
alignment.DistributeVertically();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the selection visuals after alignment
|
||||||
|
UpdateSelectionVisuals();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue