Agregado movimiento con flechas de los objetos seleccionados

This commit is contained in:
Miguel 2025-02-19 21:27:33 +01:00
parent 326c615887
commit 38ca212d9f
4 changed files with 195 additions and 42 deletions

View File

@ -153,9 +153,17 @@
</ToolBar> </ToolBar>
</ToolBarTray> </ToolBarTray>
<ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto" <ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer"
VerticalScrollBarVisibility="Auto" PanningMode="Both"> HorizontalScrollBarVisibility="Auto"
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="0" Background="Transparent"> VerticalScrollBarVisibility="Auto"
PanningMode="Both"
PreviewKeyDown="ScrollViewer_PreviewKeyDown">
<Canvas x:Name="ImagenEnTrabajoCanvas"
Margin="0"
Background="Transparent"
Focusable="True"
FocusVisualStyle="{x:Null}"
KeyDown="Canvas_KeyDown">
<!-- Agregar Background="Transparent" para que capture los eventos del mouse y --> <!-- Agregar Background="Transparent" para que capture los eventos del mouse y -->
<!-- asegurar que el Canvas reciba los eventos del botón derecho --> <!-- asegurar que el Canvas reciba los eventos del botón derecho -->
<Canvas.RenderTransform> <Canvas.RenderTransform>

View File

@ -151,6 +151,7 @@ namespace CtrEditor
// y no en otros controles // y no en otros controles
if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo) if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo)
{ {
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
_isDraggingCanvas = true; _isDraggingCanvas = true;
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer); _lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
ImagenEnTrabajoCanvas.CaptureMouse(); ImagenEnTrabajoCanvas.CaptureMouse();
@ -259,6 +260,7 @@ namespace CtrEditor
private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{ {
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion); UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject) if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
@ -285,6 +287,12 @@ namespace CtrEditor
private void MainWindow_KeyDown(object sender, KeyEventArgs e) private void MainWindow_KeyDown(object sender, KeyEventArgs e)
{ {
// Forzar el foco al canvas si no lo tiene
if (!ImagenEnTrabajoCanvas.IsFocused)
{
ImagenEnTrabajoCanvas.Focus();
}
if (DataContext is MainViewModel viewModel) if (DataContext is MainViewModel viewModel)
{ {
if (e.Key == Key.Delete) if (e.Key == Key.Delete)
@ -294,16 +302,55 @@ namespace CtrEditor
} }
else if (e.Key == Key.Escape) else if (e.Key == Key.Escape)
{ {
// Limpiar la selección en el ListBox
viewModel.SelectedItemOsList = null; viewModel.SelectedItemOsList = null;
// Limpiar la selección múltiple
_objectManager.ClearSelection(); _objectManager.ClearSelection();
_objectManager.RemoveResizeRectangles(); _objectManager.RemoveResizeRectangles();
e.Handled = true; e.Handled = true;
} }
else if (_objectManager.SelectedObjects.Any())
{
const float moveDistance = 0.1f;
switch (e.Key)
{
case Key.Left:
MoveSelectedObjects(-moveDistance, 0);
e.Handled = true;
break;
case Key.Right:
MoveSelectedObjects(moveDistance, 0);
e.Handled = true;
break;
case Key.Up:
MoveSelectedObjects(0, -moveDistance);
e.Handled = true;
break;
case Key.Down:
MoveSelectedObjects(0, moveDistance);
e.Handled = true;
break;
}
}
}
}
private void MoveSelectedObjects(float deltaX, float deltaY)
{
// Mover todos los objetos primero
foreach (var obj in _objectManager.SelectedObjects)
{
obj.Left += deltaX;
obj.Top += deltaY;
}
// Forzar una actualización del layout antes de actualizar los visuales
ImagenEnTrabajoCanvas.UpdateLayout();
// Ahora actualizar los visuales de selección
_objectManager.UpdateSelectionVisuals();
if (DataContext is MainViewModel viewModel)
{
viewModel.HasUnsavedChanges = true;
} }
} }
@ -377,6 +424,7 @@ namespace CtrEditor
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo || e.Source is UserControl) && if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo || e.Source is UserControl) &&
DataContext is MainViewModel viewModel) DataContext is MainViewModel viewModel)
{ {
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
e.Handled = true; e.Handled = true;
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas)); ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
} }
@ -440,6 +488,63 @@ namespace CtrEditor
contextMenu.IsOpen = true; contextMenu.IsOpen = true;
} }
} }
private void Canvas_KeyDown(object sender, KeyEventArgs e)
{
HandleKeyDown(e);
}
private void ScrollViewer_PreviewKeyDown(object sender, KeyEventArgs e)
{
// Prevenir que el ScrollViewer maneje las teclas de flecha
if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down)
{
HandleKeyDown(e);
e.Handled = true;
}
}
private void HandleKeyDown(KeyEventArgs e)
{
if (DataContext is MainViewModel viewModel)
{
if (e.Key == Key.Delete)
{
viewModel.EliminarObjetoSeleccionado();
e.Handled = true;
}
else if (e.Key == Key.Escape)
{
viewModel.SelectedItemOsList = null;
_objectManager.ClearSelection();
_objectManager.RemoveResizeRectangles();
e.Handled = true;
}
else if (_objectManager.SelectedObjects.Any())
{
const float moveDistance = 0.01f;
switch (e.Key)
{
case Key.Left:
MoveSelectedObjects(-moveDistance, 0);
e.Handled = true;
break;
case Key.Right:
MoveSelectedObjects(moveDistance, 0);
e.Handled = true;
break;
case Key.Up:
MoveSelectedObjects(0, -moveDistance);
e.Handled = true;
break;
case Key.Down:
MoveSelectedObjects(0, moveDistance);
e.Handled = true;
break;
}
}
}
}
} }
public class FloatValidationRule : ValidationRule public class FloatValidationRule : ValidationRule

View File

@ -83,31 +83,27 @@ namespace CtrEditor
{ {
if (_selectedObjects.Count <= 2) return; if (_selectedObjects.Count <= 2) return;
// Ordenar objetos por su centro X real (considerando rotación)
var objectsWithCenters = _selectedObjects var objectsWithCenters = _selectedObjects
.Select(obj => new .Select(obj => new
{ {
Object = obj, Object = obj,
Center = GetObjectCenter(obj) Center = GetObjectCenter(obj),
Dimensions = GetEffectiveDimensions(obj)
}) })
.OrderBy(x => x.Center.X) .OrderBy(x => x.Center.X)
.ToList(); .ToList();
// Calcular el espacio total y el espaciado
float leftMost = (float)objectsWithCenters.First().Center.X; float leftMost = (float)objectsWithCenters.First().Center.X;
float rightMost = (float)objectsWithCenters.Last().Center.X; float rightMost = (float)objectsWithCenters.Last().Center.X;
float totalWidth = rightMost - leftMost; float totalDistance = rightMost - leftMost;
float spacing = totalWidth / (_selectedObjects.Count - 1); float spacing = totalDistance / (_selectedObjects.Count - 1);
// Distribuir objetos basados en sus centros
for (int i = 1; i < objectsWithCenters.Count - 1; i++) for (int i = 1; i < objectsWithCenters.Count - 1; i++)
{ {
var obj = objectsWithCenters[i].Object; var obj = objectsWithCenters[i];
var targetCenterX = leftMost + (spacing * i); var targetX = leftMost + (spacing * i);
var currentCenter = GetObjectCenter(obj); float deltaX = (float)(targetX - obj.Center.X);
var deltaX = targetCenterX - currentCenter.X; obj.Object.Left += deltaX;
obj.Left += (float)deltaX;
} }
} }
@ -115,31 +111,27 @@ namespace CtrEditor
{ {
if (_selectedObjects.Count <= 2) return; if (_selectedObjects.Count <= 2) return;
// Ordenar objetos por su centro Y real (considerando rotación)
var objectsWithCenters = _selectedObjects var objectsWithCenters = _selectedObjects
.Select(obj => new .Select(obj => new
{ {
Object = obj, Object = obj,
Center = GetObjectCenter(obj) Center = GetObjectCenter(obj),
Dimensions = GetEffectiveDimensions(obj)
}) })
.OrderBy(x => x.Center.Y) .OrderBy(x => x.Center.Y)
.ToList(); .ToList();
// Calcular el espacio total y el espaciado
float topMost = (float)objectsWithCenters.First().Center.Y; float topMost = (float)objectsWithCenters.First().Center.Y;
float bottomMost = (float)objectsWithCenters.Last().Center.Y; float bottomMost = (float)objectsWithCenters.Last().Center.Y;
float totalHeight = bottomMost - topMost; float totalDistance = bottomMost - topMost;
float spacing = totalHeight / (_selectedObjects.Count - 1); float spacing = totalDistance / (_selectedObjects.Count - 1);
// Distribuir objetos basados en sus centros
for (int i = 1; i < objectsWithCenters.Count - 1; i++) for (int i = 1; i < objectsWithCenters.Count - 1; i++)
{ {
var obj = objectsWithCenters[i].Object; var obj = objectsWithCenters[i];
var targetCenterY = topMost + (spacing * i); var targetY = topMost + (spacing * i);
var currentCenter = GetObjectCenter(obj); float deltaY = (float)(targetY - obj.Center.Y);
var deltaY = targetCenterY - currentCenter.Y; obj.Object.Top += deltaY;
obj.Top += (float)deltaY;
} }
} }
@ -147,10 +139,11 @@ namespace CtrEditor
{ {
if (_selectedObjects.Count <= 1) return; if (_selectedObjects.Count <= 1) return;
float averageWidth = _selectedObjects.Average(obj => obj.Ancho); float averageWidth = _selectedObjects.Average(obj => GetEffectiveDimensions(obj).Width);
foreach (var obj in _selectedObjects) foreach (var obj in _selectedObjects)
{ {
obj.Ancho = averageWidth; var currentDims = GetEffectiveDimensions(obj);
SetEffectiveDimensions(obj, averageWidth, currentDims.Height);
} }
} }
@ -158,10 +151,11 @@ namespace CtrEditor
{ {
if (_selectedObjects.Count <= 1) return; if (_selectedObjects.Count <= 1) return;
float averageHeight = _selectedObjects.Average(obj => obj.Alto); float averageHeight = _selectedObjects.Average(obj => GetEffectiveDimensions(obj).Height);
foreach (var obj in _selectedObjects) foreach (var obj in _selectedObjects)
{ {
obj.Alto = averageHeight; var currentDims = GetEffectiveDimensions(obj);
SetEffectiveDimensions(obj, currentDims.Width, averageHeight);
} }
} }
@ -181,14 +175,21 @@ namespace CtrEditor
if (_selectedObjects.Count <= 1) return; if (_selectedObjects.Count <= 1) return;
var sortedObjects = _selectedObjects var sortedObjects = _selectedObjects
.OrderBy(obj => obj.Left) .OrderBy(obj => GetObjectCenter(obj).X)
.ToList(); .ToList();
for (int i = 1; i < sortedObjects.Count; i++) for (int i = 1; i < sortedObjects.Count; i++)
{ {
var previousObj = sortedObjects[i - 1]; var previousObj = sortedObjects[i - 1];
var currentObj = sortedObjects[i]; var currentObj = sortedObjects[i];
currentObj.Left = previousObj.Left + previousObj.Ancho; 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;
} }
} }
@ -197,14 +198,21 @@ namespace CtrEditor
if (_selectedObjects.Count <= 1) return; if (_selectedObjects.Count <= 1) return;
var sortedObjects = _selectedObjects var sortedObjects = _selectedObjects
.OrderBy(obj => obj.Top) .OrderBy(obj => GetObjectCenter(obj).Y)
.ToList(); .ToList();
for (int i = 1; i < sortedObjects.Count; i++) for (int i = 1; i < sortedObjects.Count; i++)
{ {
var previousObj = sortedObjects[i - 1]; var previousObj = sortedObjects[i - 1];
var currentObj = sortedObjects[i]; var currentObj = sortedObjects[i];
currentObj.Top = previousObj.Top + previousObj.Alto; 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;
} }
} }
@ -214,10 +222,8 @@ namespace CtrEditor
float centerX = obj.Left + (obj.Ancho / 2); float centerX = obj.Left + (obj.Ancho / 2);
float centerY = obj.Top + (obj.Alto / 2); float centerY = obj.Top + (obj.Alto / 2);
// Si el objeto está rotado, calcular el centro real
if (obj.Angulo != 0) 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 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); var rotatedY = obj.Top + (Math.Sin(angleRad) * obj.Ancho / 2 + Math.Cos(angleRad) * obj.Alto / 2);
@ -226,5 +232,35 @@ namespace CtrEditor
return new Point(centerX, centerY); 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;
}
}
} }
} }

View File

@ -87,10 +87,14 @@ namespace CtrEditor
public void UpdateSelectionVisuals() public void UpdateSelectionVisuals()
{ {
// Asegurarse de que el canvas haya actualizado su layout
_canvas.UpdateLayout();
RemoveResizeRectangles(); RemoveResizeRectangles();
if (_selectedObjects.Any()) if (_selectedObjects.Any())
{ {
AddResizeRectangles(_selectedObjects); AddResizeRectangles(_selectedObjects);
UpdateSelectionHighlights();
} }
} }