From 2caad7ad5a78b615b45d3f1f3f9e3a7f2ff18acd Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Wed, 2 Sep 2026 00:30:05 +0200 Subject: [PATCH] Cleaned up preview app Signed-off-by: Hans Kokx --- example/lib/main.dart | 137 +++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 74 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 3f8d8d5..b21b2d6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,9 +1,9 @@ import "dart:async"; import "dart:io"; -import "dart:typed_data"; import "package:custom_cursor/custom_cursor.dart"; import "package:desktop_drop/desktop_drop.dart"; +import "package:flutter/foundation.dart"; import "package:flutter/material.dart"; import "package:flutter/services.dart" show rootBundle; @@ -41,7 +41,6 @@ class CursorGridScreen extends StatefulWidget { class _CursorGridScreenState extends State { static const _defaultAssets = ["normal", "move", "resize"]; - static const _sizePresets = [24, 30, 32, 36, 48, 64, 128]; Map _cursors = {}; final Map _rawFiles = {}; @@ -53,7 +52,6 @@ class _CursorGridScreenState extends State { bool _respectOsScale = true; bool _rtl = false; double _systemScale = 1.0; - String _customSize = ""; DecodeOptions get _options { return DecodeOptions( @@ -174,21 +172,13 @@ class _CursorGridScreenState extends State { setState(() { _cursors = {}; _loading = true; + _targetSize = 32; }); await _loadDefaults(); } void _setPreset(int? size) { _targetSize = size?.toDouble(); - if (size != null) _customSize = ""; - unawaited(_redecode()); - } - - void _applyCustomSize(String text) { - final parsed = double.tryParse(text); - if (parsed != null && parsed > 0) { - _targetSize = parsed; - } unawaited(_redecode()); } @@ -219,13 +209,11 @@ class _CursorGridScreenState extends State { children: [ _ScaleControls( preset: _targetSize, - customSize: _customSize, respectOsScale: _respectOsScale, osScale: _systemScale, rtl: _rtl, onPreset: (size) => setState(() => _setPreset(size)), - onCustomChanged: (text) => setState(() => _customSize = text), - onCustomSubmitted: _applyCustomSize, + onToggleOsScale: (value) => setState(() => _toggleOsScale(value)), onToggleRtl: (value) => setState(() => _rtl = value), @@ -262,25 +250,19 @@ class _CursorGridScreenState extends State { class _ScaleControls extends StatelessWidget { const _ScaleControls({ required this.preset, - required this.customSize, required this.respectOsScale, required this.osScale, required this.rtl, required this.onPreset, - required this.onCustomChanged, - required this.onCustomSubmitted, required this.onToggleOsScale, required this.onToggleRtl, }); final double? preset; - final String customSize; final bool respectOsScale; final double osScale; final bool rtl; final ValueChanged onPreset; - final ValueChanged onCustomChanged; - final ValueChanged onCustomSubmitted; final ValueChanged onToggleOsScale; final ValueChanged onToggleRtl; @@ -294,52 +276,51 @@ class _ScaleControls extends StatelessWidget { crossAxisAlignment: WrapCrossAlignment.center, children: [ Text("Size:", style: Theme.of(context).textTheme.titleSmall), - for (final size in _CursorGridScreenState._sizePresets) - ChoiceChip( - label: Text("$size"), - selected: preset == size, - onSelected: (_) => onPreset(size), - ), - SizedBox( - width: 72, - child: TextField( - decoration: const InputDecoration( - labelText: "Custom", - isDense: true, + Slider.adaptive( + min: 16, + max: 128, + value: preset ?? 32, + divisions: 8, + showValueIndicator: ShowValueIndicator.alwaysVisible, + onChanged: (value) { + onPreset(value.toInt()); + }, + ), + Row( + spacing: 8, + children: [ + Directionality( + textDirection: TextDirection.ltr, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text("Dir:", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(width: 8), + ChoiceChip( + label: const Text("LTR"), + selected: !rtl, + onSelected: (_) => onToggleRtl(false), + ), + const SizedBox(width: 4), + ChoiceChip( + label: const Text("RTL"), + selected: rtl, + onSelected: (_) => onToggleRtl(true), + ), + ], + ), ), - keyboardType: TextInputType.number, - onChanged: onCustomChanged, - onSubmitted: onCustomSubmitted, - ), - ), - Directionality( - textDirection: TextDirection.ltr, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text("Dir:", style: Theme.of(context).textTheme.titleSmall), - const SizedBox(width: 8), - ChoiceChip( - label: const Text("LTR"), - selected: !rtl, - onSelected: (_) => onToggleRtl(false), + Expanded( + child: SwitchListTile.adaptive( + contentPadding: EdgeInsets.zero, + title: Text( + "Respect OS pointer size (${osScale.toStringAsFixed(2)}x)", + ), + value: respectOsScale, + onChanged: onToggleOsScale, ), - const SizedBox(width: 4), - ChoiceChip( - label: const Text("RTL"), - selected: rtl, - onSelected: (_) => onToggleRtl(true), - ), - ], - ), - ), - SwitchListTile( - contentPadding: EdgeInsets.zero, - title: Text( - "Respect OS pointer size (${osScale.toStringAsFixed(2)}x)", - ), - value: respectOsScale, - onChanged: onToggleOsScale, + ), + ], ), ], ), @@ -361,12 +342,16 @@ class _DropRegion extends StatelessWidget { final ValueChanged onDragExited; final ValueChanged onDragDone; + bool get useDropTarget => + kIsWeb || Platform.isWindows || Platform.isLinux || Platform.isMacOS; + @override Widget build(BuildContext context) { final theme = Theme.of(context); return Padding( padding: const EdgeInsets.fromLTRB(24, 24, 24, 0), child: DropTarget( + enable: useDropTarget, onDragEntered: onDragEntered, onDragExited: onDragExited, onDragDone: onDragDone, @@ -387,9 +372,11 @@ class _DropRegion extends StatelessWidget { ), ), child: Text( - dragging - ? "Release to load cursors" - : "Drop cursor/image files here (cur, ani, PNG, GIF, SVG...)", + useDropTarget + ? dragging + ? "Release to load cursors" + : "Drop cursor/image files here (cur, ani, PNG, GIF, SVG...)" + : "Tap to load cursor/image files (cur, ani, PNG, GIF, SVG...)", style: theme.textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -467,10 +454,10 @@ class _CursorCardState extends State { ), ), child: Column( + spacing: 12, mainAxisAlignment: MainAxisAlignment.center, children: [ - AssetPreview(asset: widget.asset), - const SizedBox(height: 12), + Flexible(child: AssetPreview(asset: widget.asset)), Text(widget.name, style: theme.textTheme.titleMedium), ], ), @@ -558,12 +545,14 @@ class _CursorPreview extends StatelessWidget { final rtl = effectiveDirection(context) == TextDirection.rtl; final width = cursor.image.width.toDouble(); final height = cursor.image.height.toDouble(); - return SizedBox( - width: width, - height: height, + return Center( child: Transform.scale( scaleX: rtl ? -1 : 1, - child: RawImage(image: cursor.image, width: width, height: height), + child: RawImage( + image: cursor.image, + width: width, + height: height, + ), ), ); }