import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import '../../../../data/services/export_providers.dart'; import '../view_model/view_model.dart'; class PdfToolbar extends ConsumerStatefulWidget { const PdfToolbar({ super.key, required this.disabled, required this.onPickPdf, required this.onJumpToPage, required this.onZoomOut, required this.onZoomIn, this.zoomLevel, this.fileName, required this.showPagesSidebar, required this.showSignaturesSidebar, required this.onTogglePagesSidebar, required this.onToggleSignaturesSidebar, }); final bool disabled; final VoidCallback onPickPdf; final ValueChanged onJumpToPage; final String? fileName; final VoidCallback onZoomOut; final VoidCallback onZoomIn; // Current zoom level as a percentage (e.g., 100 for 100%) final int? zoomLevel; final bool showPagesSidebar; final bool showSignaturesSidebar; final VoidCallback onTogglePagesSidebar; final VoidCallback onToggleSignaturesSidebar; @override ConsumerState createState() => _PdfToolbarState(); } class _PdfToolbarState extends ConsumerState { final TextEditingController _goToController = TextEditingController(); @override void dispose() { _goToController.dispose(); super.dispose(); } void _submitGoTo() { final v = _goToController.text.trim(); final n = int.tryParse(v); if (n != null) widget.onJumpToPage(n); } @override Widget build(BuildContext context) { final pdf = ref.watch(pdfProvider); final dpi = ref.watch(exportDpiProvider); final l = AppLocalizations.of(context); final pageInfo = l.pageInfo(pdf.currentPage, pdf.pageCount); return LayoutBuilder( builder: (context, constraints) { final bool compact = constraints.maxWidth < 260; final double gotoWidth = 50; // Center content of the toolbar final center = Wrap( spacing: 8, runSpacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [ OutlinedButton( key: const Key('btn_open_pdf_picker'), onPressed: widget.disabled ? null : widget.onPickPdf, child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.insert_drive_file, size: 18), const SizedBox(width: 6), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 220), child: Text( // if filename not null widget.fileName != null ? widget.fileName! : 'No file selected', overflow: TextOverflow.ellipsis, ), ), ], ), ), if (pdf.loaded) ...[ Wrap( spacing: 8, children: [ IconButton( key: const Key('btn_prev'), onPressed: widget.disabled ? null : () => widget.onJumpToPage(pdf.currentPage - 1), icon: const Icon(Icons.chevron_left), tooltip: l.prev, ), // Current page label Text(pageInfo, key: const Key('lbl_page_info')), IconButton( key: const Key('btn_next'), onPressed: widget.disabled ? null : () => widget.onJumpToPage(pdf.currentPage + 1), icon: const Icon(Icons.chevron_right), tooltip: l.next, ), Wrap( spacing: 6, runSpacing: 4, crossAxisAlignment: WrapCrossAlignment.center, children: [ Text(l.goTo), SizedBox( width: gotoWidth, child: TextField( key: const Key('txt_goto'), controller: _goToController, keyboardType: TextInputType.number, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], enabled: !widget.disabled, decoration: InputDecoration( isDense: true, hintText: '1..${pdf.pageCount}', ), onSubmitted: (_) => _submitGoTo(), ), ), if (!compact) IconButton( key: const Key('btn_goto_apply'), tooltip: l.goTo, icon: const Icon(Icons.arrow_forward), onPressed: widget.disabled ? null : _submitGoTo, ), ], ), const SizedBox(width: 8), IconButton( key: const Key('btn_zoom_out'), tooltip: 'Zoom out', onPressed: widget.disabled ? null : widget.onZoomOut, icon: const Icon(Icons.zoom_out), ), Text( //if not null widget.zoomLevel != null ? '${widget.zoomLevel}%' : '', style: const TextStyle(fontSize: 12), ), IconButton( key: const Key('btn_zoom_in'), tooltip: 'Zoom in', onPressed: widget.disabled ? null : widget.onZoomIn, icon: const Icon(Icons.zoom_in), ), SizedBox(width: 6), // show zoom ratio Text(l.dpi), const SizedBox(width: 8), DropdownButton( key: const Key('ddl_export_dpi'), value: dpi, items: const [96.0, 144.0, 200.0, 300.0] .map( (v) => DropdownMenuItem( value: v, child: Text(v.toStringAsFixed(0)), ), ) .toList(), onChanged: widget.disabled ? null : (v) { if (v != null) { ref.read(exportDpiProvider.notifier).state = v; } }, ), ], ), ], ], ); return Row( children: [ IconButton( key: const Key('btn_toggle_pages_sidebar'), tooltip: 'Toggle pages overview', onPressed: widget.disabled ? null : widget.onTogglePagesSidebar, icon: Icon( Icons.view_sidebar, color: widget.showPagesSidebar ? Theme.of(context).colorScheme.primary : null, ), ), const SizedBox(width: 8), Expanded(child: center), const SizedBox(width: 8), IconButton( key: const Key('btn_toggle_signatures_sidebar'), tooltip: 'Toggle signatures drawer', onPressed: widget.disabled ? null : widget.onToggleSignaturesSidebar, icon: Icon( Icons.view_sidebar, color: widget.showSignaturesSidebar ? Theme.of(context).colorScheme.primary : null, ), ), ], ); }, ); } }