build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Describes the part of the user interface represented by this widget.

Implementation

@override
Widget build(BuildContext context) {
  return Focus(
    onKeyEvent: (event) {
      if (event.type == evt.KeyType.escape) {
        PromptScope.of(context)?.done();
        widget.onClose();
        return true;
      }
      if (event.type == evt.KeyType.up) {
        if (filteredSpans.isNotEmpty) {
          setState(() {
            selectedIndex = (selectedIndex - 1).clamp(
              0,
              min(filteredSpans.length, 1000) - 1,
            );
          });
        }
        return true;
      }
      if (event.type == evt.KeyType.down) {
        if (filteredSpans.isNotEmpty) {
          setState(() {
            selectedIndex = (selectedIndex + 1).clamp(
              0,
              min(filteredSpans.length, 1000) - 1,
            );
          });
        }
        return true;
      }
      if (event.type == evt.KeyType.enter) {
        if (filteredSpans.isNotEmpty &&
            selectedIndex < filteredSpans.length) {
          widget.onMatchSelected(filteredSpans[selectedIndex]);
          return true;
        }
      }
      return false;
    },
    child: DecoratedBox(
      decoration: const BoxDecoration(
        border: Border(
          topChar: '─',
          bottomChar: '─',
          leftChar: '│',
          rightChar: '│',
          topLeftChar: '╔',
          topRightChar: '╗',
          bottomLeftChar: '╚',
          bottomRightChar: '╝',
          style: Style(foreground: Colors.white),
        ),
        backgroundColor: Color(30, 30, 30),
      ),
      child: Column([
        Row([
          Text(
            ' Search [Esc or X to close]',
            style: const Style(foreground: Color(0, 255, 255)),
          ),
          Expanded(child: const SizedBox()),
          InkwellButton(onPressed: widget.onClose, text: '[X]'),
        ]),
        SizedBox(
          height: 1,
          child: Text(
            '─' * 50,
            style: const Style(foreground: Color(128, 128, 128)),
          ),
        ),
        Row([
          Text(' > ', style: const Style(foreground: Colors.yellow)),
          Expanded(
            child: TextField(
              controller: searchController,
              focusNode: _focusNode,
              style: const Style(
                foreground: Colors.white,
                background: CharmColors.char,
              ),
            ),
          ),
        ]),
        SizedBox(
          height: 1,
          child: Text(
            '─' * 50,
            style: const Style(foreground: Color(128, 128, 128)),
          ),
        ),
        SizedBox(
          height: 1,
          child: Row([
            Text(
              ' Syntax: "foo", "-bar", "cat:blink", "dur:>=16ms", "/regex/"',
              style: const Style(foreground: Color(150, 150, 150)),
            ),
          ]),
        ),
        SizedBox(
          height: 1,
          child: Row([
            Text(
              ' Matches: ${filteredSpans.length} / ${searchController.text.isNotEmpty ? widget.spans.length : 0}',
              style: const Style(foreground: Colors.green),
            ),
          ]),
        ),
        Expanded(
          child: ListView.raw(
            showScrollbar: true,
            selectedIndex: selectedIndex,
            onSelect: (index) {
              setState(() {
                selectedIndex = index;
              });
              widget.onMatchSelected(filteredSpans[index]);
            },
            lines: filteredSpans.take(1000).map((span) {
              return ' • ${span.name} (${(span.endUs - span.startUs) / 1000.0}ms)';
            }).toList(),
          ),
        ),
      ]),
    ),
  );
}