/
metaffoble
/
FitnessManager
Обзор
Документация
Войти
/
metaffoble
/
FitnessManager
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
Helpers/DragDropManager.cs
225 строк
8 KB
Артем Якушин
another version of FitnessManager
08 фев 2026, 15:15
08 фев 2026, 15:15
503d57a
Код
Авторство
О чём код?
using FitnessManager.Model.Data; using FitnessManager.Model.Services; using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace FitnessManager.Helpers { public class DragDropManager { private Border _draggedWorkout; private Point _dragStartPoint; private List<DateTime> _weekDates = new List<DateTime>(); private TranslateTransform _dragTransform = new TranslateTransform(); private readonly WorkoutManager _workoutManager; private readonly FitnessManagerEntities _context; private const double DragThreshold = 5.0; private bool _isDragging = false; public DragDropManager(WorkoutManager workoutManager, FitnessManagerEntities context) { _workoutManager = workoutManager; _context = context; } public void StartDrag(Border workoutControl, Point startPoint) { if (_isDragging) return; _draggedWorkout = workoutControl; _dragStartPoint = startPoint; _isDragging = true; // Настройка визуала для перетаскивания _draggedWorkout.RenderTransform = _dragTransform; _draggedWorkout.Opacity = 0.8; Panel.SetZIndex(_draggedWorkout, 1000); // Захват мыши _draggedWorkout.CaptureMouse(); } public bool HandleDrag(Point currentPosition) { if (!_isDragging || _draggedWorkout == null || !_draggedWorkout.IsMouseCaptured) return false; var offset = currentPosition - _dragStartPoint; // Проверяем порог начала перетаскивания if (!_isDragging && offset.Length < DragThreshold) return false; _dragTransform.X = offset.X; _dragTransform.Y = offset.Y; return true; } public void EndDrag(Grid scheduleGrid, Point endPosition, List<DateTime> weekDates, WorkoutManager workoutManager, FitnessManagerEntities context) { if (!_isDragging || _draggedWorkout == null) return; try { var workoutId = workoutManager.GetWorkoutId(_draggedWorkout); var workout = context.GroupWorkout.Find(workoutId); if (workout != null && workout.IsActive.Value && TryGetNewPosition(scheduleGrid, endPosition, out int newColumn, out int newRow)) { var newStartTime = CalculateNewStartTime(newColumn, newRow, weekDates); if (!IsValidMove(workout, newStartTime, context)) { MessageBox.Show("Не удалось перенести тренировку:\n" + "- Возможно время уже занято\n" + "- Или у тренера уже 4 тренировки в этот день\n" + "- Или тренер не работает в это время\n" + "- Или вы пытаетесь взаимодействовать с тренировками задним числом", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Warning); } if (IsValidMove(workout, newStartTime, context)) { UpdateWorkoutTime(workout, newStartTime, context); workoutManager.RepositionWorkout(_draggedWorkout, newColumn, newRow); } } } finally { ResetDragState(); } } private bool TryGetNewPosition(Grid scheduleGrid, Point position, out int column, out int row) { column = row = -1; // Проверка колонок double accumulatedWidth = 0; for (int i = 0; i < scheduleGrid.ColumnDefinitions.Count; i++) { accumulatedWidth += scheduleGrid.ColumnDefinitions[i].ActualWidth; if (accumulatedWidth > position.X) { column = i; break; } } // Проверка строк double accumulatedHeight = 0; for (int i = 0; i < scheduleGrid.RowDefinitions.Count; i++) { accumulatedHeight += scheduleGrid.RowDefinitions[i].ActualHeight; if (accumulatedHeight > position.Y) { row = i; break; } } return column >= 0 && row >= 0; } private DateTime CalculateNewStartTime(int column, int row, List<DateTime> weekDates) { if (column < 0 || column >= weekDates.Count || row < 0) throw new ArgumentOutOfRangeException(); var date = weekDates[column]; var hour = 9 + row / 2; var minute = (row % 2) * 30; if (hour < 9 || hour > 22) throw new ArgumentException("Invalid time slot"); return new DateTime(date.Year, date.Month, date.Day, hour, minute, 0); } private bool IsValidMove(GroupWorkout workout, DateTime newStartTime, FitnessManagerEntities context) { if (workout == null || !workout.IsActive.Value || workout.StartTime.Date < DateTime.Now || newStartTime < DateTime.Now) return false; var duration = workout.EndTime - workout.StartTime; var newEndTime = newStartTime.Add(duration); // Проверка лимита тренировок var trainerWorkoutsCount = _context.GroupWorkout .Count(gw => gw.TrainerId == workout.TrainerId && DbFunctions.TruncateTime(gw.StartTime) == newStartTime.Date && gw.IsActive.Value && gw.Id != workout.Id); if (trainerWorkoutsCount >= 4) return false; // Остальные проверки var trainerSchedule = _context.TrainerSchedule .FirstOrDefault(ts => ts.TrainerId == workout.TrainerId && ts.WorkDate == newStartTime.Date); if (trainerSchedule == null || !trainerSchedule.IsWorkDay.HasValue || !trainerSchedule.IsWorkDay.Value || newStartTime.TimeOfDay<trainerSchedule.StartTime || newEndTime.TimeOfDay> trainerSchedule.EndTime) { return false; } if (newStartTime.TimeOfDay < TimeSpan.FromHours(9) || newStartTime.TimeOfDay > TimeSpan.FromHours(22)) return false; return !_context.GroupWorkout.Any(gw => gw.Id != workout.Id && gw.IsActive.Value && ((gw.TrainerId == workout.TrainerId && gw.StartTime < newEndTime && gw.EndTime > newStartTime) || (gw.GymId == workout.GymId && gw.StartTime < newEndTime && gw.EndTime > newStartTime))); } private void UpdateWorkoutTime(GroupWorkout workout, DateTime newStartTime, FitnessManagerEntities context) { if (workout == null) return; var duration = workout.EndTime - workout.StartTime; workout.StartTime = newStartTime; workout.EndTime = newStartTime.Add(duration); _context.SaveChanges(); } public void ResetDragState() { if (_draggedWorkout != null) { _draggedWorkout.ReleaseMouseCapture(); _draggedWorkout.Opacity = 1.0; _draggedWorkout.RenderTransform = null; Panel.SetZIndex(_draggedWorkout, 0); } _isDragging = false; _draggedWorkout = null; _dragTransform.X = 0; _dragTransform.Y = 0; } } }