endDrag method

void endDrag()

Implementation

void endDrag() {
  final config = manager.config;
  final blockHeight = config.blockHeight;

  // Absolute minutes from minHour for an event edge at grid-y [y], snapped to
  // the configured interval — the same primitive create uses, so a dragged
  // edge lands on the same grid as a freshly created event.
  int minutesAt(double y) =>
      manager.snapToInterval((y / blockHeight * 60).round());

  // The models are immutable (#27): each branch computes the new time and
  // swaps in a fresh entry via copyWith rather than mutating in place. The new
  // instance is what Manager.endDrag reports to onEntryMove.
  final time = entry.time;
  switch (_dragType) {
    case DragType.body:
      // Move: the column snaps to the nearest day, the start time snaps to the
      // configured interval, and the duration is unchanged. The day shifts by
      // the horizontal drag in whole columns — measured from the current day,
      // not canvasRect.left, which now carries a sub-column offset when the
      // event is split across overlapping neighbours (#20).
      final day = time.day + (_dragOffset.dx / config.blockWidth).round();
      final start = minutesAt(canvasRect.top + _dragOffset.dy);
      entry = entry.copyWith(
        time: time.copyWith(
          day: day,
          hour: config.minHour + start ~/ 60,
          minutes: start % 60,
        ),
      );
      break;
    case DragType.topHandle:
      // Resize from the top: the bottom edge stays put, so the snapped start
      // time is absorbed by the duration.
      final bottom =
          (time.hour - config.minHour) * 60 + time.minutes + time.duration;
      final start = minutesAt(canvasRect.top + _dragOffset.dy);
      entry = entry.copyWith(
        time: time.copyWith(
          hour: config.minHour + start ~/ 60,
          minutes: start % 60,
          duration: bottom - start,
        ),
      );
      break;
    case DragType.bottomHandle:
      // Resize from the bottom: the start stays put, the bottom edge snaps.
      final start = (time.hour - config.minHour) * 60 + time.minutes;
      entry = entry.copyWith(
        time: time.copyWith(
          duration: minutesAt(canvasRect.bottom + _dragOffset.dy) - start,
        ),
      );
      break;
    case DragType.none:
      break;
  }

  _calculateCanvasRect();

  _dragOffset = Offset.zero;
  _dragType = DragType.none;
}