flutter_switch_device 0.3.0 copy "flutter_switch_device: ^0.3.0" to clipboard
flutter_switch_device: ^0.3.0 copied to clipboard

A Flutter widget that renders network switch devices with ports, fully programmatic — no SVG assets required.

example/lib/main.dart

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_switch_device/flutter_switch_device.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatefulWidget {
  const ExampleApp({super.key});

  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  ThemeMode _themeMode = ThemeMode.dark;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'flutter_switch_device demo',
      themeMode: _themeMode,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blueGrey,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blueGrey,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: DemoPage(
        themeMode: _themeMode,
        onThemeModeChanged: (mode) => setState(() => _themeMode = mode),
      ),
    );
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({
    super.key,
    required this.themeMode,
    required this.onThemeModeChanged,
  });

  final ThemeMode themeMode;
  final ValueChanged<ThemeMode> onThemeModeChanged;

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  static const _scenarios = <String, SwitchFormat>{
    '6P': Switch6P(),
    '12P': Switch12P(),
    '24P': Switch24P(),
    '28P': Switch28P(),
    '48P Stacked': Switch48PStacked(),
    '30P Stacked': Switch30PStacked(),
  };

  String _selectedScenario = '24P';
  Map<int, PortStatus> _portStatuses = {};
  bool _isConfig = false;
  int _stackedPart = 1;
  Set<int> _selectedPorts = {};
  final List<String> _eventLog = [];

  SwitchFormat get _format => _scenarios[_selectedScenario]!;

  void _randomizeStatuses() {
    final rng = Random();
    final statuses = <int, PortStatus>{};
    final total = _format.totalPortsNum;
    for (int i = 1; i <= total; i++) {
      statuses[i] = PortStatus.values[rng.nextInt(PortStatus.values.length)];
    }
    setState(() => _portStatuses = statuses);
  }

  void _log(String event) {
    setState(() {
      _eventLog.insert(0, event);
      if (_eventLog.length > 20) _eventLog.removeLast();
    });
  }

  @override
  Widget build(BuildContext context) {
    final isStacked = _format.isStacked;

    return Scaffold(
      appBar: AppBar(title: const Text('flutter_switch_device demo')),
      body: Column(
        children: [
          // Controls
          Padding(
            padding: const EdgeInsets.all(12),
            child: Wrap(
              spacing: 12,
              runSpacing: 8,
              crossAxisAlignment: WrapCrossAlignment.center,
              children: [
                DropdownButton<String>(
                  value: _selectedScenario,
                  items: _scenarios.keys
                      .map((k) => DropdownMenuItem(value: k, child: Text(k)))
                      .toList(),
                  onChanged: (v) => setState(() {
                    _selectedScenario = v!;
                    _portStatuses = {};
                    _selectedPorts = {};
                    _stackedPart = _format.isStacked ? 1 : 0;
                  }),
                ),
                ElevatedButton(
                  onPressed: _randomizeStatuses,
                  child: const Text('Randomize statuses'),
                ),
                if (_selectedPorts.isNotEmpty)
                  ElevatedButton(
                    onPressed: () =>
                        setState(() => _selectedPorts = {}),
                    child: Text(
                        'Clear selection (${_selectedPorts.length})'),
                  ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Text('Config mode'),
                    Switch(
                      value: _isConfig,
                      onChanged: (v) => setState(() => _isConfig = v),
                    ),
                  ],
                ),
                SegmentedButton<ThemeMode>(
                  segments: const [
                    ButtonSegment(value: ThemeMode.dark, label: Text('Dark')),
                    ButtonSegment(value: ThemeMode.light, label: Text('Light')),
                    ButtonSegment(value: ThemeMode.system, label: Text('Auto')),
                  ],
                  selected: {widget.themeMode},
                  onSelectionChanged: (s) =>
                      widget.onThemeModeChanged(s.first),
                ),
                if (isStacked)
                  SegmentedButton<int>(
                    segments: const [
                      ButtonSegment(value: 1, label: Text('Upper')),
                      ButtonSegment(value: 2, label: Text('Lower')),
                    ],
                    selected: {_stackedPart},
                    onSelectionChanged: (s) =>
                        setState(() => _stackedPart = s.first),
                  ),
              ],
            ),
          ),

          // Switch icon (compact representation)
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 8),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text('Icon sizes:  ',
                    style: TextStyle(fontSize: 12)),
                const SwitchIconWidget(size: 72),
                const SizedBox(width: 16),
                const SwitchIconWidget(size: 68, elevation: 2),
                const SizedBox(width: 16),
                const SwitchIconWidget(size: 38, elevation: 1),
              ],
            ),
          ),

          // Switch view
          Expanded(
            child: Center(
              child: LayoutBuilder(
                builder: (context, constraints) {
                  final viewSize = Size(
                    constraints.maxWidth.clamp(400, 1500),
                    constraints.maxHeight.clamp(200, 800),
                  );
                  return SwitchDeviceView(
                    size: viewSize,
                    format: _format,
                    portStatuses: _portStatuses,
                    isConfig: _isConfig,
                    stackedPart: _stackedPart,
                    onStackedPartChanged: (part) {
                      setState(() => _stackedPart = part);
                      _log('Stacked part changed: $part');
                    },
                    onPortHover: (port) => _log('Hover: port $port'),
                    onPortHoverExit: () {},
                    onPortTap: (port) => _log('Tap: port $port'),
                    onSwitchHover: () {},
                    onSwitchHoverExit: () {},
                    selectedPorts: _selectedPorts,
                    onPortSelected: (port) {
                      setState(() {
                        _selectedPorts = Set.of(_selectedPorts);
                        if (_selectedPorts.contains(port)) {
                          _selectedPorts.remove(port);
                        } else {
                          _selectedPorts.add(port);
                        }
                      });
                      _log('Selected: $_selectedPorts');
                    },
                  );
                },
              ),
            ),
          ),

          // Event log
          Container(
            height: 120,
            width: double.infinity,
            color: Colors.grey.shade100,
            padding: const EdgeInsets.all(8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text('Event Log',
                    style: TextStyle(fontWeight: FontWeight.bold)),
                Expanded(
                  child: ListView(
                    children: _eventLog
                        .map((e) => Text(e,
                            style: const TextStyle(
                                fontSize: 12, fontFamily: 'monospace')))
                        .toList(),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
26
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter widget that renders network switch devices with ports, fully programmatic — no SVG assets required.

Repository (GitHub)
View/report issues

Topics

#widget #network #switch #visualization

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_switch_device