/// 한 줄 · 두 줄 배치 판단 (관리자 지시 10/21: 화면마다 따로 재지 않고 이것 하나를 부른다 - d3 설계의 AdaptiveRow 자리). /// /// 약속 /// - 입력: [maxWidth] 쓸 수 있는 폭, [first] · [second] 앞 · 뒤 묶음 아이템의 최소 폭 (단추는 기본 누를 자리 그대로), /// [gap] 한 줄일 때 두 묶음 사이, 줄일 수 있는 아이템 하나의 폭 범위 [flexMin] ~ [flexMax] (없으면 0 · 0). /// - 출력: [RowFit.split] 이면 두 줄 (위 = first, 아래 = second + 줄일 수 있는 아이템), [RowFit.flexWidth] 줄일 수 있는 아이템의 폭 /// (0 이면 그 줄에 넣지 않는다 - 같은 일을 하는 다른 단추가 남아 있어야 한다). /// - 오류: 없음. 두 줄로도 [second] 가 들지 않으면 split = true · flexWidth = 0 이고 [RowFit.overflow] 에 모자란 폭. class RowFit { final bool split; final double flexWidth; final double overflow; const RowFit(this.split, this.flexWidth, this.overflow); } RowFit fitRow({ required double maxWidth, required List first, required List second, double gap = 0, double flexMin = 0, double flexMax = 0, bool forceSplit = false, }) { double sum(List xs) => xs.fold(0.0, (a, b) => a + b); final a = sum(first), b = sum(second); final split = forceSplit || a + gap + b + flexMax > maxWidth; final room = maxWidth - b - (split ? 0 : a + gap); var flex = room.clamp(0.0, flexMax); if (flex < flexMin) flex = 0; final over = (split ? [a, b].reduce((x, y) => x > y ? x : y) : a + gap + b) - maxWidth; return RowFit(split, flex, over > 0 ? over : 0); }