line numbers in editor

This commit is contained in:
2024-12-31 15:05:11 +08:00
parent 030007159d
commit 8eddab5e13

View File

@@ -16,6 +16,7 @@ class _CodeEditorState extends State<CodeEditor> {
late FocusNode _focusNode; late FocusNode _focusNode;
var horizontalScrollController = ScrollController(); var horizontalScrollController = ScrollController();
var verticalScrollController = ScrollController(); var verticalScrollController = ScrollController();
int lineCount = 1;
@override @override
void initState() { void initState() {
@@ -31,6 +32,13 @@ class _CodeEditorState extends State<CodeEditor> {
} }
return KeyEventResult.ignored; return KeyEventResult.ignored;
}; };
lineCount = calculateLineCount(widget.initialValue ?? '');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
future = _controller.init(context.brightness);
} }
void handleTab() { void handleTab() {
@@ -41,10 +49,40 @@ class _CodeEditorState extends State<CodeEditor> {
_controller.selection = TextSelection.collapsed(offset: start + 4); _controller.selection = TextSelection.collapsed(offset: start + 4);
} }
int calculateLineCount(String text) {
return text.split('\n').length;
}
Widget buildLineNumbers() {
return SizedBox(
width: 14 * 1.5,
child: Column(children: [
for (var i = 1; i <= lineCount; i++)
SizedBox(
height: 14 * 1.5,
child: Center(
child: Text(
i.toString(),
style: TextStyle(
color: context.colorScheme.outline,
fontSize: 14,
height: 1.0,
fontFamily: 'consolas',
fontFamilyFallback: ['Courier New', 'monospace'],
),
).paddingBottom(6),
),
),
],),
).paddingVertical(8);
}
late Future future;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
future: _controller.init(context.brightness), future: future,
builder: (context, value) { builder: (context, value) {
if (value.connectionState == ConnectionState.waiting) { if (value.connectionState == ConnectionState.waiting) {
return const SizedBox(); return const SizedBox();
@@ -64,22 +102,37 @@ class _CodeEditorState extends State<CodeEditor> {
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
controller: horizontalScrollController, controller: horizontalScrollController,
child: IntrinsicWidth( child: Row(
stepWidth: 100, children: [
child: TextField( buildLineNumbers(),
controller: _controller, IntrinsicWidth(
focusNode: _focusNode, stepWidth: 50,
maxLines: null, child: TextField(
expands: true, controller: _controller,
decoration: InputDecoration( focusNode: _focusNode,
border: InputBorder.none, maxLines: null,
contentPadding: EdgeInsets.all(8), expands: true,
cursorHeight: 1.5 * 14,
style: TextStyle(
height: 1.5,
fontSize: 14
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.all(8),
),
onChanged: (value) {
widget.onChanged?.call(value);
if (lineCount != calculateLineCount(value)) {
setState(() {
lineCount = calculateLineCount(value);
});
}
},
scrollController: verticalScrollController,
),
), ),
onChanged: (value) { ],
widget.onChanged?.call(value);
},
scrollController: verticalScrollController,
),
), ),
), ),
), ),
@@ -121,17 +174,19 @@ class _CodeTextEditingController extends TextEditingController {
); );
var result = highlighter.highlight(text); var result = highlighter.highlight(text);
style = TextStyle( style = TextStyle(
height: 1.5,
fontSize: 14,
fontFamily: 'consolas', fontFamily: 'consolas',
fontFamilyFallback: ['Courier New', 'monospace'], fontFamilyFallback: ['Courier New', 'monospace'],
); );
return setTextSpanFont(result, style); return mergeTextStyle(result, style);
} }
TextSpan setTextSpanFont(TextSpan span, TextStyle style) { TextSpan mergeTextStyle(TextSpan span, TextStyle style) {
var result = TextSpan( var result = TextSpan(
style: style.merge(span.style), style: style.merge(span.style),
children: span.children?.whereType().map((e) => setTextSpanFont(e, style)).toList(), children: span.children?.whereType().map((e) => mergeTextStyle(e, style)).toList(),
text: span.text, text: span.text,
); );
return result; return result;