From 0dd904d4a8c278ae19867ca040985446d42c1a5c Mon Sep 17 00:00:00 2001 From: doonfrs Date: Thu, 25 May 2023 03:58:54 +0300 Subject: [PATCH] enhance color picker, enter hex color and color palette option --- lib/src/translations/toolbar.i18n.dart | 9 ++ lib/src/widgets/toolbar/color_button.dart | 152 +++++++++++++++++++--- 2 files changed, 145 insertions(+), 16 deletions(-) diff --git a/lib/src/translations/toolbar.i18n.dart b/lib/src/translations/toolbar.i18n.dart index 77c0bd67..2e0cdca0 100644 --- a/lib/src/translations/toolbar.i18n.dart +++ b/lib/src/translations/toolbar.i18n.dart @@ -68,6 +68,9 @@ extension Localization on String { 'Enter media': 'Enter media', 'Edit': 'Edit', 'Apply': 'Apply', + 'Hex': 'Hex', + 'Material': 'Material', + 'Color': 'Color', }, 'en_us': { 'Paste a link': 'Paste a link', @@ -134,6 +137,9 @@ extension Localization on String { 'Enter media': 'Enter media', 'Edit': 'Edit', 'Apply': 'Apply', + 'Hex': 'Hex', + 'Material': 'Material', + 'Color': 'Color', }, 'ar': { 'Paste a link': 'نسخ الرابط', @@ -202,6 +208,9 @@ extension Localization on String { 'Enter media': 'ادخل وسائط', 'Edit': 'تعديل', 'Apply': 'تطبيق', + 'Hex': 'Hex', + 'Material': 'Material', + 'Color': 'اللون', }, 'da': { 'Paste a link': 'Indsæt link', diff --git a/lib/src/widgets/toolbar/color_button.dart b/lib/src/widgets/toolbar/color_button.dart index 60f0a591..65139629 100644 --- a/lib/src/widgets/toolbar/color_button.dart +++ b/lib/src/widgets/toolbar/color_button.dart @@ -136,29 +136,149 @@ class _ColorButtonState extends State { } void _changeColor(BuildContext context, Color color) { - var hex = color.value.toRadixString(16); - if (hex.startsWith('ff')) { - hex = hex.substring(2); - } + var hex = colorToHex(color); hex = '#$hex'; widget.controller.formatSelection( widget.background ? BackgroundAttribute(hex) : ColorAttribute(hex)); - Navigator.of(context).pop(); } void _showColorPicker() { - showDialog( + var pickerType = 'material'; + + var selectedColor = Colors.black; + + if (_isToggledColor) { + selectedColor = widget.background + ? hexToColor(_selectionStyle.attributes['background']?.value) + : hexToColor(_selectionStyle.attributes['color']?.value); + } + + final hexController = + TextEditingController(text: colorToHex(selectedColor)); + late void Function(void Function()) colorBoxSetState; + + showDialog( context: context, - builder: (context) => AlertDialog( - title: Text('Select Color'.i18n), - backgroundColor: Theme.of(context).canvasColor, - content: SingleChildScrollView( - child: MaterialPicker( - pickerColor: const Color(0x00000000), - onColorChanged: (color) => _changeColor(context, color), - ), - ), - ), + builder: (context) => StatefulBuilder(builder: (context, dlgSetState) { + return AlertDialog( + title: Text('Select Color'.i18n), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('OK'.i18n)), + ], + backgroundColor: Theme.of(context).canvasColor, + content: SizedBox( + height: 400, + child: Column( + children: [ + Row( + children: [ + TextButton( + onPressed: () { + dlgSetState(() { + pickerType = 'material'; + }); + }, + child: Text('Material'.i18n)), + TextButton( + onPressed: () { + dlgSetState(() { + pickerType = 'color'; + }); + }, + child: Text('Color'.i18n)), + ], + ), + Expanded( + child: Column(children: [ + if (pickerType == 'material') + MaterialPicker( + pickerColor: selectedColor, + onColorChanged: (color) { + _changeColor(context, color); + Navigator.of(context).pop(); + }, + ), + if (pickerType == 'color') + ColorPicker( + pickerColor: selectedColor, + onColorChanged: (color) { + _changeColor(context, color); + hexController.text = colorToHex(color); + selectedColor = color; + colorBoxSetState(() {}); + }, + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + SizedBox( + width: 100, + height: 60, + child: TextFormField( + controller: hexController, + onChanged: (value) { + selectedColor = hexToColor(value); + _changeColor(context, selectedColor); + + colorBoxSetState(() {}); + }, + decoration: InputDecoration( + labelText: 'Hex'.i18n, + border: const OutlineInputBorder(), + ), + ), + ), + const SizedBox( + width: 10, + ), + StatefulBuilder(builder: (context, mcolorBoxSetState) { + colorBoxSetState = mcolorBoxSetState; + return Container( + width: 25, + height: 25, + decoration: BoxDecoration( + border: Border.all( + color: Colors.black45, + ), + color: selectedColor, + borderRadius: BorderRadius.circular(5), + ), + ); + }), + ], + ), + ])) + ], + ), + )); + }), ); } + + Color hexToColor(String? hexString) { + if (hexString == null) { + return Colors.black; + } + final hexRegex = RegExp(r'([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$'); + + hexString = hexString.replaceAll('#', ''); + if (!hexRegex.hasMatch(hexString)) { + return Colors.black; + } + + final buffer = StringBuffer(); + if (hexString.length == 6 || hexString.length == 7) buffer.write('ff'); + buffer.write(hexString); + return Color(int.tryParse(buffer.toString(), radix: 16) ?? 0xFF000000); + } + + String colorToHex(Color color) { + return color.value.toRadixString(16).padLeft(8, '0').toUpperCase(); + } }