From fae705a1de1c559627d2ab18a43daeb91253e233 Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Sat, 7 Jan 2023 14:14:07 +0400 Subject: [PATCH] created EccLevel enum --- README.md | 2 +- lib/src/logic/barcode_encoder.dart | 22 +++-- lib/src/models/format.dart | 8 ++ lib/src/models/messages.dart | 13 ++- lib/src/models/params.dart | 25 +++++- lib/src/ui/writer_widget.dart | 124 +++++++++++++++++------------ lib/zxing_mobile.dart | 58 +++----------- 7 files changed, 134 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index b49bea6..adbe983 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ final Encode result = zx.encodeBarcode( width: 120, height: 120, margin: 10, - eccLevel: 0, + eccLevel: EccLevel.low, ), ); if (result.isValid) { diff --git a/lib/src/logic/barcode_encoder.dart b/lib/src/logic/barcode_encoder.dart index c96ebd5..35f9ba5 100644 --- a/lib/src/logic/barcode_encoder.dart +++ b/lib/src/logic/barcode_encoder.dart @@ -1,22 +1,18 @@ part of 'zxing.dart'; // Encode a string into a barcode -Encode zxingEncodeBarcode( - String contents, { - int format = Format.qrCode, - int width = 300, - int height = 300, - int margin = 0, - int eccLevel = 0, -}) { +Encode zxingEncodeBarcode({ + required String contents, + required EncodeParams params, + }) { return bindings .encodeBarcode( contents.toNativeUtf8().cast(), - width, - height, - format, - margin, - eccLevel, + params.width, + params.height, + params.format, + params.margin, + params.eccLevel.value, ) .toEncode(); } diff --git a/lib/src/models/format.dart b/lib/src/models/format.dart index 2d6e3d0..6d3fda9 100644 --- a/lib/src/models/format.dart +++ b/lib/src/models/format.dart @@ -35,6 +35,14 @@ abstract class Format { static const int any = oneDCodes | twoDCodes; } +extension EccSupportedExtension on int { + bool get isSupportedEccLevel => eccSupported.contains(this); + + static final List eccSupported = [ + Format.qrCode, + ]; +} + extension CodeFormat on Format { String get name => formatNames[this] ?? 'Unknown'; diff --git a/lib/src/models/messages.dart b/lib/src/models/messages.dart index f9915c1..0f70f75 100644 --- a/lib/src/models/messages.dart +++ b/lib/src/models/messages.dart @@ -3,28 +3,37 @@ class Messages { const Messages({ this.createButton = 'Create', this.textLabel = 'Enter barcode text here', + this.formatLabel = 'Format', this.marginLabel = 'Margin', this.eccLevelLabel = 'ECC Level', this.widthLabel = 'Width', this.heightLabel = 'Height', + this.lowEccLevel = 'Low (7%)', + this.mediumEccLevel = 'Medium (15%)', + this.quartileEccLevel = 'Quartile (25%)', + this.highEccLevel = 'High (30%)', this.invalidText = 'Please enter some text', this.invalidWidth = 'Invalid width', this.invalidHeight = 'Invalid height', this.invalidMargin = 'Invalid margin', - this.invalidEccLevel = 'Invalid ECC level', }); final String createButton; final String textLabel; + final String formatLabel; final String marginLabel; final String eccLevelLabel; final String widthLabel; final String heightLabel; + final String lowEccLevel; + final String mediumEccLevel; + final String quartileEccLevel; + final String highEccLevel; + final String invalidText; final String invalidWidth; final String invalidHeight; final String invalidMargin; - final String invalidEccLevel; } diff --git a/lib/src/models/params.dart b/lib/src/models/params.dart index fcbae88..c27c5a6 100644 --- a/lib/src/models/params.dart +++ b/lib/src/models/params.dart @@ -39,7 +39,7 @@ class EncodeParams { this.width = 120, this.height = 120, this.margin = 0, - this.eccLevel = 0, + this.eccLevel = EccLevel.low, }); // The barcode format to be generated. The default is QRCode. @@ -54,6 +54,25 @@ class EncodeParams { // Used for all formats, sets the minimum number of quiet zone pixels int margin; - // Used for Aztec, PDF417, and QRCode only, [0-8] - int eccLevel; + // The error correction level determines how much damage the QR code can withstand while still being readable. + // Used for Aztec, PDF417, and QRCode only + EccLevel eccLevel; +} + +enum EccLevel { + low, // Low error correction level. Can withstand up to 7% damage. + medium, // Medium error correction level. Can withstand up to 15% damage. + quartile, // Quartile error correction level. Can withstand up to 25% damage. + high, // High error correction level. Can withstand up to 30% damage. +} + +extension EccLevelExtension on EccLevel { + static const Map _valuesMap = { + EccLevel.low: 2, + EccLevel.medium: 4, + EccLevel.quartile: 6, + EccLevel.high: 8, + }; + + int get value => _valuesMap[this] ?? 0; } diff --git a/lib/src/ui/writer_widget.dart b/lib/src/ui/writer_widget.dart index 38942d1..e57dcff 100644 --- a/lib/src/ui/writer_widget.dart +++ b/lib/src/ui/writer_widget.dart @@ -14,7 +14,7 @@ class WriterWidget extends StatefulWidget { this.width = 120, this.height = 120, this.margin = 0, - this.eccLevel = 0, + this.eccLevel = EccLevel.low, this.messages = const Messages(), this.onSuccess, this.onError, @@ -25,7 +25,7 @@ class WriterWidget extends StatefulWidget { final int width; final int height; final int margin; - final int eccLevel; + final EccLevel eccLevel; final Messages messages; final Function(Encode result, Uint8List? bytes)? onSuccess; final Function(String error)? onError; @@ -41,13 +41,22 @@ class _WriterWidgetState extends State final TextEditingController _widthController = TextEditingController(); final TextEditingController _heightController = TextEditingController(); final TextEditingController _marginController = TextEditingController(); - final TextEditingController _eccController = TextEditingController(); bool isAndroid() => Theme.of(context).platform == TargetPlatform.android; final int _maxTextLength = 2000; final List _supportedFormats = CodeFormat.writerFormats; + int _codeFormat = Format.qrCode; + EccLevel _eccLevel = EccLevel.low; + + Messages get messages => widget.messages; + Map get _eccTitlesMap => { + EccLevel.low: messages.lowEccLevel, + EccLevel.medium: messages.mediumEccLevel, + EccLevel.quartile: messages.quartileEccLevel, + EccLevel.high: messages.highEccLevel, + }; @override void initState() { @@ -55,7 +64,7 @@ class _WriterWidgetState extends State _widthController.text = widget.width.toString(); _heightController.text = widget.height.toString(); _marginController.text = widget.margin.toString(); - _eccController.text = widget.eccLevel.toString(); + _eccLevel = widget.eccLevel; _codeFormat = widget.format; super.initState(); } @@ -66,13 +75,11 @@ class _WriterWidgetState extends State _widthController.dispose(); _heightController.dispose(); _marginController.dispose(); - _eccController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - final Messages m = widget.messages; return SingleChildScrollView( child: Form( key: _formKey, @@ -95,102 +102,116 @@ class _WriterWidgetState extends State decoration: InputDecoration( border: const OutlineInputBorder(), filled: true, - labelText: m.textLabel, + labelText: messages.textLabel, counterText: '${_textController.value.text.length} / $_maxTextLength', ), validator: (String? value) { if (value?.isEmpty ?? false) { - return m.invalidText; + return messages.invalidText; } return null; }, ), const SizedBox(height: 20), // Format DropDown button - DropdownButtonFormField( - value: _codeFormat, - items: _supportedFormats - .map((int format) => DropdownMenuItem( - value: format, - child: Text(zx.barcodeFormatName(format)), - )) - .toList(), - onChanged: (int? format) { - setState(() { - _codeFormat = format ?? Format.qrCode; - }); - }, - ), - const SizedBox(height: 20), Row( children: [ Flexible( - child: TextFormField( - controller: _widthController, - keyboardType: TextInputType.number, + child: DropdownButtonFormField( + value: _codeFormat, decoration: InputDecoration( - labelText: m.widthLabel, + border: const OutlineInputBorder(), + filled: true, + labelText: messages.formatLabel, ), - validator: (String? value) { - final int? width = int.tryParse(value ?? ''); - if (width == null) { - return m.invalidWidth; - } - return null; + items: _supportedFormats + .map((int format) => DropdownMenuItem( + value: format, + child: Text(zx.barcodeFormatName(format)), + )) + .toList(), + onChanged: (int? format) { + setState(() { + _codeFormat = format ?? Format.qrCode; + }); }, ), ), - const SizedBox(width: 8), + if (_codeFormat.isSupportedEccLevel) ...[ + const SizedBox(width: 10), + Flexible( + child: DropdownButtonFormField( + value: _eccLevel, + decoration: InputDecoration( + border: const OutlineInputBorder(), + filled: true, + labelText: messages.eccLevelLabel, + ), + items: _eccTitlesMap.entries + .map((MapEntry entry) => + DropdownMenuItem( + value: entry.key, + child: Text(entry.value), + )) + .toList(), + onChanged: (EccLevel? ecc) { + setState(() { + _eccLevel = ecc ?? EccLevel.low; + }); + }, + ), + ), + ] + ], + ), + const SizedBox(height: 20), + Row( + children: [ Flexible( child: TextFormField( - controller: _heightController, + controller: _widthController, keyboardType: TextInputType.number, decoration: InputDecoration( - labelText: m.heightLabel, + labelText: messages.widthLabel, ), validator: (String? value) { final int? width = int.tryParse(value ?? ''); if (width == null) { - return m.invalidHeight; + return messages.invalidWidth; } return null; }, ), ), - ], - ), - const SizedBox(height: 20), - Row( - children: [ + // const SizedBox(width: 8), Flexible( child: TextFormField( - controller: _marginController, + controller: _heightController, keyboardType: TextInputType.number, decoration: InputDecoration( - labelText: m.marginLabel, + labelText: messages.heightLabel, ), validator: (String? value) { final int? width = int.tryParse(value ?? ''); if (width == null) { - return m.invalidMargin; + return messages.invalidHeight; } return null; }, ), ), - const SizedBox(width: 8), Flexible( child: TextFormField( - controller: _eccController, + controller: _marginController, keyboardType: TextInputType.number, decoration: InputDecoration( - labelText: m.eccLevelLabel, + labelText: messages.marginLabel, ), validator: (String? value) { final int? width = int.tryParse(value ?? ''); if (width == null) { - return m.invalidEccLevel; + return messages.invalidMargin; } return null; }, @@ -198,11 +219,12 @@ class _WriterWidgetState extends State ), ], ), + const SizedBox(height: 20), // Write button ElevatedButton( onPressed: createBarcode, - child: Text(m.createButton), + child: Text(messages.createButton), ), const SizedBox(height: 10), ], @@ -220,7 +242,7 @@ class _WriterWidgetState extends State final int width = int.parse(_widthController.value.text); final int height = int.parse(_heightController.value.text); final int margin = int.parse(_marginController.value.text); - final int ecc = int.parse(_eccController.value.text); + final EccLevel ecc = _eccLevel; final Encode result = zx.encodeBarcode( contents: text, params: EncodeParams( diff --git a/lib/zxing_mobile.dart b/lib/zxing_mobile.dart index 14771d1..6d7677f 100644 --- a/lib/zxing_mobile.dart +++ b/lib/zxing_mobile.dart @@ -30,14 +30,7 @@ class ZxingMobile implements Zxing { required String contents, required EncodeParams params, }) => - zxingEncodeBarcode( - contents, - format: params.format, - width: params.width, - height: params.height, - margin: params.margin, - eccLevel: params.eccLevel, - ); + zxingEncodeBarcode(contents: contents, params: params); @override Future startCameraProcessing() => zxingStartCameraProcessing(); @@ -50,40 +43,28 @@ class ZxingMobile implements Zxing { CameraImage image, { DecodeParams? params, }) => - zxingProcessCameraImage( - image, - params: params, - ); + zxingProcessCameraImage(image, params: params); @override Future readBarcodeImagePathString( String path, { DecodeParams? params, }) => - zxingReadBarcodeImagePathString( - path, - params: params, - ); + zxingReadBarcodeImagePathString(path, params: params); @override Future readBarcodeImagePath( XFile path, { DecodeParams? params, }) => - zxingReadBarcodeImagePath( - path, - params: params, - ); + zxingReadBarcodeImagePath(path, params: params); @override Future readBarcodeImageUrl( String url, { DecodeParams? params, }) => - zxingReadBarcodeImageUrl( - url, - params: params, - ); + zxingReadBarcodeImageUrl(url, params: params); @override Code readBarcode( @@ -92,42 +73,28 @@ class ZxingMobile implements Zxing { required int height, DecodeParams? params, }) => - zxingReadBarcode( - bytes, - width: width, - height: height, - params: params, - ); + zxingReadBarcode(bytes, width: width, height: height, params: params); @override Future> readBarcodesImagePathString( String path, { DecodeParams? params, }) => - zxingReadBarcodesImagePathString( - path, - params: params, - ); + zxingReadBarcodesImagePathString(path, params: params); @override Future> readBarcodesImagePath( XFile path, { DecodeParams? params, }) => - zxingReadBarcodesImagePath( - path, - params: params, - ); + zxingReadBarcodesImagePath(path, params: params); @override Future> readBarcodesImageUrl( String url, { DecodeParams? params, }) => - zxingReadBarcodesImageUrl( - url, - params: params, - ); + zxingReadBarcodesImageUrl(url, params: params); @override List readBarcodes( @@ -136,10 +103,5 @@ class ZxingMobile implements Zxing { required int height, DecodeParams? params, }) => - zxingReadBarcodes( - bytes, - width: width, - height: height, - params: params, - ); + zxingReadBarcodes(bytes, width: width, height: height, params: params); }