50 lines
2.1 KiB
Dart
50 lines
2.1 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
import 'path_label.dart' show textWidth;
|
||
|
||
/// 경로처럼 끝 (지금 폴더) 이 중요한 글 (관리자 지시 10/21, 28 지적): 다 들어가면 그대로, 모자라면 앞을 "…" 로 줄인다.
|
||
/// 구분 ([separators] - " › " · "\" · "/") 에서 자르는 것을 먼저 (가장 긴 뒤쪽), 마지막 조각도 안 들어가면 글자 단위로.
|
||
/// 지금 글꼴 · 글자 배율로 잰다
|
||
class TailText extends StatelessWidget {
|
||
final String text;
|
||
final TextStyle? style;
|
||
final List<String> separators;
|
||
const TailText(this.text, {super.key, this.style, this.separators = const [' › ', '\\', '/']});
|
||
|
||
/// [width] 에 들어가는 꼴 (시험에서 씀)
|
||
static String fit(String text, double width, double Function(String) measure, {List<String> separators = const [' › ', '\\', '/']}) {
|
||
if (measure(text) <= width) return text;
|
||
// 구분에서 시작하는 뒤쪽들 (긴 것부터)
|
||
final cuts = <int>[];
|
||
for (final s in separators) {
|
||
for (var i = text.indexOf(s); i >= 0; i = text.indexOf(s, i + 1)) {
|
||
cuts.add(i); // 구분 기호는 남김 ("… › 여름 휴가")
|
||
}
|
||
}
|
||
cuts.sort();
|
||
for (final c in cuts) {
|
||
final t = '…${text.substring(c)}';
|
||
if (measure(t) <= width) return t;
|
||
}
|
||
// 마지막 조각도 길면 글자 단위로 (뒤쪽 가장 길게)
|
||
var lo = 0, hi = text.length;
|
||
while (lo < hi) {
|
||
final mid = (lo + hi) ~/ 2;
|
||
if (measure('…${text.substring(mid)}') <= width) {
|
||
hi = mid;
|
||
} else {
|
||
lo = mid + 1;
|
||
}
|
||
}
|
||
return '…${text.substring(lo)}';
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) => LayoutBuilder(builder: (context, box) {
|
||
// 폭 재기는 path_label 의 textWidth 하나로 (지금 글꼴 · 글자 배율 · 글 방향, 다 쓴 TextPainter 는 놓음)
|
||
double measure(String t) => textWidth(context, t, style ?? const TextStyle());
|
||
final shown = box.maxWidth.isFinite ? fit(text, box.maxWidth, measure, separators: separators) : text;
|
||
return Text(shown, style: style, maxLines: 1, overflow: TextOverflow.clip, softWrap: false);
|
||
});
|
||
}
|