From b3173fe8ef9d5c1972716339f3443df5c6ee8897 Mon Sep 17 00:00:00 2001 From: preetidas60 Date: Tue, 30 Sep 2025 21:40:17 +0530 Subject: [PATCH 1/4] Added Shadows Effect Feature --- lib/cubit/canvas_cubit.dart | 128 +++++++- lib/models/text_item_model.dart | 85 ++++- lib/ui/widgets/editable_text_widget.dart | 61 ++-- lib/ui/widgets/font_controls.dart | 199 ++++++------ lib/ui/widgets/shadows_controls.dart | 398 +++++++++++++++++++++++ 5 files changed, 740 insertions(+), 131 deletions(-) create mode 100644 lib/ui/widgets/shadows_controls.dart diff --git a/lib/cubit/canvas_cubit.dart b/lib/cubit/canvas_cubit.dart index 0f02ba0c..925f54e1 100644 --- a/lib/cubit/canvas_cubit.dart +++ b/lib/cubit/canvas_cubit.dart @@ -32,6 +32,116 @@ class CanvasCubit extends Cubit { } } + // Toggle text shadow on/off + void toggleTextShadow(int index) { + if (index < 0 || index >= state.textItems.length) return; + + final updatedItems = List.from(state.textItems); + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: !updatedItems[index].hasShadow, + ); + _updateState(textItems: updatedItems); + } + +// Change shadow color + void changeShadowColor(int index, Color color) { + if (index < 0 || index >= state.textItems.length) return; + + final updatedItems = List.from(state.textItems); + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, // Automatically enable shadow when changing color + shadowColor: color, + ); + _updateState(textItems: updatedItems); + } + +// Change shadow blur radius + void changeShadowBlur(int index, double blurRadius) { + if (index < 0 || index >= state.textItems.length) return; + + final updatedItems = List.from(state.textItems); + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowBlurRadius: blurRadius.clamp(0.0, 50.0), + ); + _updateState(textItems: updatedItems); + } + +// Change shadow offset + void changeShadowOffset(int index, Offset offset) { + if (index < 0 || index >= state.textItems.length) return; + + final updatedItems = List.from(state.textItems); + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowOffset: offset, + ); + _updateState(textItems: updatedItems); + } + +// Apply preset shadow styles + void applyShadowPreset(int index, ShadowPreset preset) { + if (index < 0 || index >= state.textItems.length) return; + + final updatedItems = List.from(state.textItems); + + switch (preset) { + case ShadowPreset.soft: + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: Colors.black.withValues(alpha: 0.3), + shadowBlurRadius: 8.0, + shadowOffset: const Offset(2.0, 2.0), + ); + break; + case ShadowPreset.medium: + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: Colors.black.withValues(alpha: 0.5), + shadowBlurRadius: 6.0, + shadowOffset: const Offset(3.0, 3.0), + ); + break; + case ShadowPreset.hard: + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: Colors.black.withValues(alpha: 0.7), + shadowBlurRadius: 2.0, + shadowOffset: const Offset(4.0, 4.0), + ); + break; + case ShadowPreset.glow: + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: Colors.white.withValues(alpha: 0.8), + shadowBlurRadius: 15.0, + shadowOffset: Offset.zero, + ); + break; + case ShadowPreset.coloredGlow: + // Use the text color for the glow + final textColor = updatedItems[index].color; + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: textColor.withValues(alpha: 0.6), + shadowBlurRadius: 12.0, + shadowOffset: Offset.zero, + ); + break; + case ShadowPreset.outline: + updatedItems[index] = updatedItems[index].copyWith( + hasShadow: true, + shadowColor: Colors.black, + shadowBlurRadius: 1.0, + shadowOffset: const Offset(1.0, 1.0), + ); + break; + } + + _updateState(textItems: updatedItems); + CustomSnackbar.showSuccess('${preset.name} shadow applied'); + } + // Add to your CanvasCubit class void fillCanvas(Color fillColor) { // Create a special "fill" path that covers the entire canvas @@ -116,9 +226,13 @@ class CanvasCubit extends Cubit { fontWeight: FontWeight.normal, fontFamily: 'Roboto', isUnderlined: false, - isHighlighted: false, // Add this line - highlightColor: null, // Add this line + isHighlighted: false, + highlightColor: null, color: ColorConstants.uiWhite, + hasShadow: false, // Reset shadow + shadowColor: Colors.black, + shadowBlurRadius: 4.0, + shadowOffset: const Offset(2.0, 2.0), ); _updateState(textItems: updatedItems); } @@ -909,3 +1023,13 @@ class CanvasCubit extends Cubit { CustomSnackbar.showInfo('Last stroke undone'); } } + +// Enum for shadow presets +enum ShadowPreset { + soft, + medium, + hard, + glow, + coloredGlow, + outline, +} diff --git a/lib/models/text_item_model.dart b/lib/models/text_item_model.dart index 1557e22e..6962cf7e 100644 --- a/lib/models/text_item_model.dart +++ b/lib/models/text_item_model.dart @@ -13,7 +13,13 @@ class TextItem { final Color color; final bool isHighlighted; final Color? highlightColor; - final TextAlign textAlign; + final TextAlign textAlign; + + // Shadow properties + final bool hasShadow; + final Color shadowColor; + final double shadowBlurRadius; + final Offset shadowOffset; TextItem({ required this.text, @@ -27,7 +33,11 @@ class TextItem { required this.color, this.isHighlighted = false, this.highlightColor, - this.textAlign = TextAlign.left, + this.textAlign = TextAlign.left, + this.hasShadow = false, + this.shadowColor = Colors.black, + this.shadowBlurRadius = 4.0, + this.shadowOffset = const Offset(2.0, 2.0), }); TextItem copyWith({ @@ -42,7 +52,11 @@ class TextItem { Color? color, bool? isHighlighted, Color? highlightColor, - TextAlign? textAlign, + TextAlign? textAlign, + bool? hasShadow, + Color? shadowColor, + double? shadowBlurRadius, + Offset? shadowOffset, }) { return TextItem( text: text ?? this.text, @@ -56,7 +70,11 @@ class TextItem { color: color ?? this.color, isHighlighted: isHighlighted ?? this.isHighlighted, highlightColor: highlightColor ?? this.highlightColor, - textAlign: textAlign ?? this.textAlign, + textAlign: textAlign ?? this.textAlign, + hasShadow: hasShadow ?? this.hasShadow, + shadowColor: shadowColor ?? this.shadowColor, + shadowBlurRadius: shadowBlurRadius ?? this.shadowBlurRadius, + shadowOffset: shadowOffset ?? this.shadowOffset, ); } @@ -69,9 +87,64 @@ class TextItem { final backgroundColor = isHighlighted && highlightColor != null ? 'background-color: #${highlightColor!.toARGB32().toRadixString(16).padLeft(8, '0').substring(2)}; ' : ''; + + final textShadow = hasShadow + ? 'text-shadow: ${shadowOffset.dx}px ${shadowOffset.dy}px ${shadowBlurRadius}px #${shadowColor.toARGB32().toRadixString(16).padLeft(8, '0').substring(2)}; ' + : ''; final style = - 'font-size: ${fontSize}px; font-family: $fontFamily; color: $cssColor; font-weight: $cssFontWeight; font-style: $cssFontStyle; $textDecoration$backgroundColor'; + 'font-size: ${fontSize}px; font-family: $fontFamily; color: $cssColor; font-weight: $cssFontWeight; font-style: $cssFontStyle; $textDecoration$backgroundColor$textShadow'; return '$text'; } -} + + // Convert to map for saving + Map toJson() { + return { + 'text': text, + 'x': x, + 'y': y, + 'fontSize': fontSize, + 'fontWeight': fontWeight.index, + 'fontStyle': fontStyle.index, + 'color': color.toARGB32(), + 'fontFamily': fontFamily, + 'isUnderlined': isUnderlined, + 'textAlign': textAlign.index, + 'isHighlighted': isHighlighted, + 'highlightColor': highlightColor?.toARGB32(), + 'hasShadow': hasShadow, + 'shadowColor': shadowColor.toARGB32(), + 'shadowBlurRadius': shadowBlurRadius, + 'shadowOffsetDx': shadowOffset.dx, + 'shadowOffsetDy': shadowOffset.dy, + }; + } + + // Create from map when loading + factory TextItem.fromJson(Map json) { + return TextItem( + text: json['text'], + x: json['x'].toDouble(), + y: json['y'].toDouble(), + fontSize: json['fontSize'].toDouble(), + fontWeight: FontWeight.values[json['fontWeight']], + fontStyle: FontStyle.values[json['fontStyle']], + color: Color(json['color']), + fontFamily: json['fontFamily'], + isUnderlined: json['isUnderlined'] ?? false, + textAlign: TextAlign.values[json['textAlign'] ?? 0], + isHighlighted: json['isHighlighted'] ?? false, + highlightColor: json['highlightColor'] != null + ? Color(json['highlightColor']) + : null, + hasShadow: json['hasShadow'] ?? false, + shadowColor: json['shadowColor'] != null + ? Color(json['shadowColor']) + : Colors.black, + shadowBlurRadius: json['shadowBlurRadius']?.toDouble() ?? 4.0, + shadowOffset: json['shadowOffsetDx'] != null && json['shadowOffsetDy'] != null + ? Offset(json['shadowOffsetDx'].toDouble(), json['shadowOffsetDy'].toDouble()) + : const Offset(2.0, 2.0), + ); + } +} \ No newline at end of file diff --git a/lib/ui/widgets/editable_text_widget.dart b/lib/ui/widgets/editable_text_widget.dart index 4a053aef..5ef7e2ed 100644 --- a/lib/ui/widgets/editable_text_widget.dart +++ b/lib/ui/widgets/editable_text_widget.dart @@ -39,29 +39,39 @@ class EditableTextWidget extends StatelessWidget { context.read().editText(index, result); } }, - // 4. onDoubleTap handler is now gone - child:SizedBox( + child: SizedBox( width: MediaQuery.of(context).size.width * 0.9, child: Text( - textItem.text, - textAlign: textItem.textAlign, - style: GoogleFonts.getFont( - textItem.fontFamily, - fontStyle: textItem.fontStyle, - fontWeight: textItem.fontWeight, - fontSize: textItem.fontSize, - decoration: textItem.isUnderlined - ? TextDecoration.underline - : TextDecoration.none, - color: textItem.color, - backgroundColor: - textItem.isHighlighted && textItem.highlightColor != null - ? textItem.highlightColor - : (isSelected - ? ColorConstants.highlightYellow.withAlpha((0.3 * 255).toInt()) - : null), + textItem.text, + textAlign: textItem.textAlign, + style: GoogleFonts.getFont( + textItem.fontFamily, + fontStyle: textItem.fontStyle, + fontWeight: textItem.fontWeight, + fontSize: textItem.fontSize, + decoration: textItem.isUnderlined + ? TextDecoration.underline + : TextDecoration.none, + color: textItem.color, + backgroundColor: + textItem.isHighlighted && textItem.highlightColor != null + ? textItem.highlightColor + : (isSelected + ? ColorConstants.highlightYellow + .withValues(alpha: 0.3) + : null), + shadows: textItem.hasShadow + ? [ + Shadow( + color: textItem.shadowColor, + offset: textItem.shadowOffset, + blurRadius: textItem.shadowBlurRadius, + ), + ] + : null, + ), ), - ),) + ), ); } } @@ -108,8 +118,8 @@ class EditTextDialog extends StatelessWidget { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), - borderSide: - const BorderSide(color: ColorConstants.dialogPurple, width: 2), + borderSide: const BorderSide( + color: ColorConstants.dialogPurple, width: 2), ), ), ), @@ -120,7 +130,7 @@ class EditTextDialog extends StatelessWidget { children: [ TextButton( onPressed: () => Navigator.pop(context, '_delete_'), - child: Text( + child: const Text( 'Remove', style: TextStyle(color: ColorConstants.gray600), ), @@ -137,7 +147,8 @@ class EditTextDialog extends StatelessWidget { } }, style: ElevatedButton.styleFrom( - backgroundColor: ColorConstants.dialogPurple.withAlpha((0.2 * 255).toInt()), + backgroundColor: + ColorConstants.dialogPurple.withValues(alpha: 0.2), foregroundColor: ColorConstants.dialogPurple, elevation: 0, padding: const EdgeInsets.symmetric( @@ -157,4 +168,4 @@ class EditTextDialog extends StatelessWidget { ), ); } -} +} \ No newline at end of file diff --git a/lib/ui/widgets/font_controls.dart b/lib/ui/widgets/font_controls.dart index 759610e3..5e6ffa89 100644 --- a/lib/ui/widgets/font_controls.dart +++ b/lib/ui/widgets/font_controls.dart @@ -7,6 +7,7 @@ import '../../constants/font_family_list.dart'; import '../../constants/color_constants.dart'; import '../../cubit/canvas_cubit.dart'; import '../../cubit/canvas_state.dart'; +import '../widgets/shadows_controls.dart'; class FontControls extends StatelessWidget { const FontControls({super.key}); @@ -36,7 +37,8 @@ class FontControls extends StatelessWidget { const SizedBox(width: 25), _buildAlignmentControls(context), const SizedBox(width: 25), - _buildHighlightControls(context), + _buildHighlightControls(context), + const ShadowControls(), const SizedBox(width: 25), _buildFontFamilyControls(context), const SizedBox(width: 25), @@ -75,8 +77,7 @@ class FontControls extends StatelessWidget { ), child: _buildStyleButton( icon: Icons.copy, - isSelected: - false, // This button is never in a "selected" state. + isSelected: false, onPressed: isDisabled ? null : () { @@ -114,7 +115,8 @@ class FontControls extends StatelessWidget { selectedIndex == null || selectedIndex >= state.textItems.length; final textItem = !isDisabled ? state.textItems[selectedIndex] : null; final isHighlighted = textItem?.isHighlighted ?? false; - final currentHighlightColor = textItem?.highlightColor ?? ColorConstants.highlightYellow; + final currentHighlightColor = + textItem?.highlightColor ?? ColorConstants.highlightYellow; return Row( mainAxisSize: MainAxisSize.min, @@ -324,98 +326,95 @@ class FontControls extends StatelessWidget { }, ); } - -Widget _buildAlignmentControls(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) { - // Only rebuild if selection changed or textAlign changed - final prevIndex = previous.selectedTextItemIndex; - final currIndex = current.selectedTextItemIndex; - - if (prevIndex != currIndex) return true; - - if (currIndex != null && - currIndex < previous.textItems.length && - currIndex < current.textItems.length) { - final prevItem = previous.textItems[currIndex]; - final currItem = current.textItems[currIndex]; - return prevItem.textAlign != currItem.textAlign; - } - - return false; - }, - builder: (context, state) { - final selectedIndex = state.selectedTextItemIndex; - final isDisabled = - selectedIndex == null || selectedIndex >= state.textItems.length; - - final textItem = !isDisabled ? state.textItems[selectedIndex] : null; - final currentAlign = textItem?.textAlign ?? TextAlign.left; - - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Text( - 'Align', - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), - ), - const SizedBox(width: 12), - Container( - padding: const EdgeInsets.symmetric(horizontal: 4), - decoration: BoxDecoration( - color: ColorConstants.gray100, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: ColorConstants.gray300), + + Widget _buildAlignmentControls(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + // Only rebuild if selection changed or textAlign changed + final prevIndex = previous.selectedTextItemIndex; + final currIndex = current.selectedTextItemIndex; + + if (prevIndex != currIndex) return true; + + if (currIndex != null && + currIndex < previous.textItems.length && + currIndex < current.textItems.length) { + final prevItem = previous.textItems[currIndex]; + final currItem = current.textItems[currIndex]; + return prevItem.textAlign != currItem.textAlign; + } + + return false; + }, + builder: (context, state) { + final selectedIndex = state.selectedTextItemIndex; + final isDisabled = + selectedIndex == null || selectedIndex >= state.textItems.length; + + final textItem = !isDisabled ? state.textItems[selectedIndex] : null; + final currentAlign = textItem?.textAlign ?? TextAlign.left; + + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + 'Align', + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), ), - child: Row( - children: [ - _buildStyleButton( - icon: Icons.format_align_left, - isSelected: currentAlign == TextAlign.left, - onPressed: isDisabled - ? null - : () => context - .read() - .changeTextAlignment(selectedIndex, TextAlign.left), - ), - const SizedBox(width: 8), - _buildStyleButton( - icon: Icons.format_align_center, - isSelected: currentAlign == TextAlign.center, - onPressed: isDisabled - ? null - : () => context - .read() - .changeTextAlignment(selectedIndex, TextAlign.center), - ), - const SizedBox(width: 8), - _buildStyleButton( - icon: Icons.format_align_right, - isSelected: currentAlign == TextAlign.right, - onPressed: isDisabled - ? null - : () => context - .read() - .changeTextAlignment(selectedIndex, TextAlign.right), - ), - const SizedBox(width: 8), - _buildStyleButton( - icon: Icons.format_align_justify, - isSelected: currentAlign == TextAlign.justify, - onPressed: isDisabled - ? null - : () => context - .read() - .changeTextAlignment(selectedIndex, TextAlign.justify), - ), - ], + const SizedBox(width: 12), + Container( + padding: const EdgeInsets.symmetric(horizontal: 4), + decoration: BoxDecoration( + color: ColorConstants.gray100, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: ColorConstants.gray300), + ), + child: Row( + children: [ + _buildStyleButton( + icon: Icons.format_align_left, + isSelected: currentAlign == TextAlign.left, + onPressed: isDisabled + ? null + : () => context + .read() + .changeTextAlignment(selectedIndex, TextAlign.left), + ), + const SizedBox(width: 8), + _buildStyleButton( + icon: Icons.format_align_center, + isSelected: currentAlign == TextAlign.center, + onPressed: isDisabled + ? null + : () => context.read().changeTextAlignment( + selectedIndex, TextAlign.center), + ), + const SizedBox(width: 8), + _buildStyleButton( + icon: Icons.format_align_right, + isSelected: currentAlign == TextAlign.right, + onPressed: isDisabled + ? null + : () => context.read().changeTextAlignment( + selectedIndex, TextAlign.right), + ), + const SizedBox(width: 8), + _buildStyleButton( + icon: Icons.format_align_justify, + isSelected: currentAlign == TextAlign.justify, + onPressed: isDisabled + ? null + : () => context.read().changeTextAlignment( + selectedIndex, TextAlign.justify), + ), + ], + ), ), - ), - ], - ); - }, - ); -} + ], + ); + }, + ); + } Widget _buildFontFamilyControls(BuildContext context) { return BlocBuilder( @@ -556,7 +555,8 @@ Widget _buildAlignmentControls(BuildContext context) { }), //More Colors Button ^_^ IconButton( - icon: const Icon(Icons.more_horiz, color: ColorConstants.gray600), + icon: const Icon(Icons.more_horiz, + color: ColorConstants.gray600), tooltip: 'More colors', onPressed: isDisabled ? null @@ -731,7 +731,7 @@ Widget _buildAlignmentControls(BuildContext context) { }) { return Material( color: isSelected - ? ColorConstants.uiBlueAccent.withAlpha((0.2 * 255).toInt()) + ? ColorConstants.uiBlueAccent.withValues(alpha: 0.2) : ColorConstants.transparent, borderRadius: BorderRadius.circular(4), child: InkWell( @@ -742,7 +742,9 @@ Widget _buildAlignmentControls(BuildContext context) { child: Icon( icon, size: 20, - color: isSelected ? ColorConstants.uiBlueAccent : ColorConstants.gray700, + color: isSelected + ? ColorConstants.uiBlueAccent + : ColorConstants.gray700, ), ), ), @@ -823,7 +825,8 @@ class _FontPickerContentState extends State<_FontPickerContent> { style: GoogleFonts.getFont(font, fontSize: 16), ), trailing: isSelected - ? const Icon(Icons.check, color: ColorConstants.dialogButtonBlue) + ? const Icon(Icons.check, + color: ColorConstants.dialogButtonBlue) : null, onTap: () { context diff --git a/lib/ui/widgets/shadows_controls.dart b/lib/ui/widgets/shadows_controls.dart new file mode 100644 index 00000000..32b757c8 --- /dev/null +++ b/lib/ui/widgets/shadows_controls.dart @@ -0,0 +1,398 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flex_color_picker/flex_color_picker.dart'; +import '../../cubit/canvas_cubit.dart'; +import '../../cubit/canvas_state.dart'; +import '../../constants/color_constants.dart'; + +class ShadowControls extends StatelessWidget { + const ShadowControls({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + if (previous.selectedTextItemIndex != current.selectedTextItemIndex) { + return true; + } + if (current.selectedTextItemIndex != null) { + final pItem = previous.textItems[current.selectedTextItemIndex!]; + final cItem = current.textItems[current.selectedTextItemIndex!]; + return pItem.hasShadow != cItem.hasShadow || + pItem.shadowColor != cItem.shadowColor || + pItem.shadowBlurRadius != cItem.shadowBlurRadius || + pItem.shadowOffset != cItem.shadowOffset; + } + return false; + }, + builder: (context, state) { + final selectedIndex = state.selectedTextItemIndex; + final isDisabled = + selectedIndex == null || selectedIndex >= state.textItems.length; + final textItem = !isDisabled ? state.textItems[selectedIndex] : null; + final hasShadow = textItem?.hasShadow ?? false; + final shadowColor = textItem?.shadowColor ?? Colors.black; + final shadowBlur = textItem?.shadowBlurRadius ?? 4.0; + final shadowOffset = textItem?.shadowOffset ?? const Offset(2.0, 2.0); + + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Shadow', + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), + const SizedBox(width: 12), + Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), + decoration: BoxDecoration( + color: ColorConstants.gray100, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: ColorConstants.gray300), + ), + child: Row( + children: [ + // Toggle shadow on/off + _buildStyleButton( + icon: Icons.blur_on, // ✅ valid alternative + isSelected: hasShadow, + onPressed: isDisabled + ? null + : () => context + .read() + .toggleTextShadow(selectedIndex), + ), + + const SizedBox(width: 8), + + // Shadow presets button + IconButton( + icon: const Icon(Icons.auto_awesome, size: 20), + tooltip: 'Shadow presets', + color: ColorConstants.gray700, + onPressed: isDisabled + ? null + : () => + _showShadowPresetsDialog(context, selectedIndex), + ), + const SizedBox(width: 8), + + // Advanced settings button (only show if shadow is enabled) + if (hasShadow) + IconButton( + icon: const Icon(Icons.tune, size: 20), + tooltip: 'Shadow settings', + color: ColorConstants.dialogButtonBlue, + onPressed: isDisabled + ? null + : () => _showShadowSettingsSheet( + context, + selectedIndex, + shadowColor, + shadowBlur, + shadowOffset, + ), + ), + ], + ), + ), + ], + ); + }, + ); + } + + Widget _buildStyleButton({ + required IconData icon, + required bool isSelected, + required VoidCallback? onPressed, + }) { + return Material( + color: isSelected + ? ColorConstants.uiBlueAccent.withValues(alpha: 0.2) + : ColorConstants.transparent, + borderRadius: BorderRadius.circular(4), + child: InkWell( + borderRadius: BorderRadius.circular(4), + onTap: onPressed, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + icon, + size: 20, + color: isSelected + ? ColorConstants.uiBlueAccent + : ColorConstants.gray700, + ), + ), + ), + ); + } + + void _showShadowPresetsDialog(BuildContext context, int selectedIndex) { + showDialog( + context: context, + builder: (dialogContext) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + title: const Row( + children: [ + Icon(Icons.auto_awesome, color: ColorConstants.dialogButtonBlue), + SizedBox(width: 8), + Text('Shadow Presets'), + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.soft, + 'Soft Shadow', + 'Light, subtle shadow', + Icons.wb_cloudy, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.medium, + 'Medium Shadow', + 'Balanced shadow effect', + Icons.filter_drama, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.hard, + 'Hard Shadow', + 'Strong, defined shadow', + Icons.wb_sunny, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.glow, + 'White Glow', + 'Soft white glow effect', + Icons.lightbulb_outline, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.coloredGlow, + 'Colored Glow', + 'Glow matching text color', + Icons.color_lens, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.outline, + 'Outline', + 'Sharp text outline', + Icons.border_outer, + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(dialogContext), + child: const Text('Close'), + ), + ], + ), + ); + } + + Widget _buildPresetTile( + BuildContext context, + int selectedIndex, + ShadowPreset preset, + String title, + String subtitle, + IconData icon, + ) { + return ListTile( + leading: Icon(icon, color: ColorConstants.dialogButtonBlue), + title: Text(title), + subtitle: Text(subtitle, style: const TextStyle(fontSize: 12)), + onTap: () { + context.read().applyShadowPreset(selectedIndex, preset); + Navigator.pop(context); + }, + ); + } + + void _showShadowSettingsSheet( + BuildContext context, + int selectedIndex, + Color currentColor, + double currentBlur, + Offset currentOffset, + ) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: ColorConstants.dialogWhite, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (sheetContext) => Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(sheetContext).viewInsets.bottom, + top: 16, + left: 16, + right: 16, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Shadow Settings', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 20), + + // Shadow color picker + const Text('Shadow Color', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: currentColor, + shape: BoxShape.circle, + border: Border.all(color: ColorConstants.gray300, width: 2), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton( + onPressed: () async { + final pickedColor = await showColorPickerDialog( + sheetContext, + currentColor, + title: const Text('Pick shadow color'), + showColorCode: true, + showRecentColors: false, + ); + if (sheetContext.mounted) { + context + .read() + .changeShadowColor(selectedIndex, pickedColor); + } + }, + child: const Text('Choose Color'), + ), + ), + ], + ), + const SizedBox(height: 20), + + // Blur radius slider + const Text('Blur Radius', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Slider( + value: currentBlur, + min: 0, + max: 50, + divisions: 50, + label: currentBlur.toStringAsFixed(1), + onChanged: (value) { + context + .read() + .changeShadowBlur(selectedIndex, value); + }, + ), + ), + SizedBox( + width: 50, + child: Text( + currentBlur.toStringAsFixed(1), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + ), + ], + ), + const SizedBox(height: 20), + + // Offset controls + const Text('Shadow Offset', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Horizontal', style: TextStyle(fontSize: 12)), + Slider( + value: currentOffset.dx, + min: -20, + max: 20, + divisions: 40, + label: currentOffset.dx.toStringAsFixed(1), + onChanged: (value) { + context.read().changeShadowOffset( + selectedIndex, Offset(value, currentOffset.dy)); + }, + ), + ], + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Vertical', style: TextStyle(fontSize: 12)), + Slider( + value: currentOffset.dy, + min: -20, + max: 20, + divisions: 40, + label: currentOffset.dy.toStringAsFixed(1), + onChanged: (value) { + context.read().changeShadowOffset( + selectedIndex, Offset(currentOffset.dx, value)); + }, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 20), + + // Close button + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () => Navigator.pop(sheetContext), + style: ElevatedButton.styleFrom( + backgroundColor: ColorConstants.dialogButtonBlue, + foregroundColor: ColorConstants.dialogWhite, + padding: const EdgeInsets.symmetric(vertical: 16), + ), + child: const Text('Done'), + ), + ), + const SizedBox(height: 16), + ], + ), + ), + ); + } +} From a4c36629b9e1ed4ddb65d6cfdc3ccb7c25501945 Mon Sep 17 00:00:00 2001 From: preetidas60 Date: Thu, 2 Oct 2025 22:57:11 +0530 Subject: [PATCH 2/4] Fix Issues with the Shadows Controls --- lib/ui/widgets/shadows_controls.dart | 624 +++++++++++++++++---------- 1 file changed, 389 insertions(+), 235 deletions(-) diff --git a/lib/ui/widgets/shadows_controls.dart b/lib/ui/widgets/shadows_controls.dart index 32b757c8..d1547687 100644 --- a/lib/ui/widgets/shadows_controls.dart +++ b/lib/ui/widgets/shadows_controls.dart @@ -8,6 +8,16 @@ import '../../constants/color_constants.dart'; class ShadowControls extends StatelessWidget { const ShadowControls({super.key}); + // Shadow color palette + static const shadowColors = [ + Colors.black, + Color(0xFF424242), + Color(0xFF757575), + Color(0xFF1976D2), + Color(0xFFD32F2F), + Color(0xFF388E3C), + ]; + @override Widget build(BuildContext context) { return BlocBuilder( @@ -52,7 +62,7 @@ class ShadowControls extends StatelessWidget { children: [ // Toggle shadow on/off _buildStyleButton( - icon: Icons.blur_on, // ✅ valid alternative + icon: Icons.blur_on, isSelected: hasShadow, onPressed: isDisabled ? null @@ -61,26 +71,65 @@ class ShadowControls extends StatelessWidget { .toggleTextShadow(selectedIndex), ), - const SizedBox(width: 8), - - // Shadow presets button - IconButton( - icon: const Icon(Icons.auto_awesome, size: 20), - tooltip: 'Shadow presets', - color: ColorConstants.gray700, - onPressed: isDisabled - ? null - : () => - _showShadowPresetsDialog(context, selectedIndex), - ), - const SizedBox(width: 8), - - // Advanced settings button (only show if shadow is enabled) - if (hasShadow) - IconButton( - icon: const Icon(Icons.tune, size: 20), + if (hasShadow) ...[ + const SizedBox(width: 8), + // Shadow color swatches + ...shadowColors.map((color) { + final isSelected = shadowColor == color; + return GestureDetector( + onTap: isDisabled + ? null + : () => context + .read() + .changeShadowColor(selectedIndex, color), + child: Container( + width: 24, + height: 24, + margin: const EdgeInsets.symmetric(horizontal: 2), + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + border: Border.all( + color: isSelected + ? ColorConstants.gray800 + : ColorConstants.gray400, + width: isSelected ? 2 : 1, + ), + ), + ), + ); + }), + const SizedBox(width: 4), + // More colors button + _buildStyleButton( + icon: Icons.colorize, + isSelected: false, + tooltip: 'More colors', + onPressed: isDisabled + ? null + : () => _showColorPicker( + context, + selectedIndex, + shadowColor, + ), + ), + const SizedBox(width: 8), + // Shadow presets button + _buildStyleButton( + icon: Icons.auto_awesome, + isSelected: false, + tooltip: 'Shadow presets', + onPressed: isDisabled + ? null + : () => + _showShadowPresetsDialog(context, selectedIndex), + ), + const SizedBox(width: 8), + // Advanced settings button + _buildStyleButton( + icon: Icons.tune, + isSelected: false, tooltip: 'Shadow settings', - color: ColorConstants.dialogButtonBlue, onPressed: isDisabled ? null : () => _showShadowSettingsSheet( @@ -91,6 +140,7 @@ class ShadowControls extends StatelessWidget { shadowOffset, ), ), + ], ], ), ), @@ -104,29 +154,51 @@ class ShadowControls extends StatelessWidget { required IconData icon, required bool isSelected, required VoidCallback? onPressed, + String? tooltip, }) { - return Material( - color: isSelected - ? ColorConstants.uiBlueAccent.withValues(alpha: 0.2) - : ColorConstants.transparent, - borderRadius: BorderRadius.circular(4), - child: InkWell( + return Tooltip( + message: tooltip ?? '', + child: Material( + color: isSelected + ? ColorConstants.gray800.withValues(alpha: 0.2) + : ColorConstants.transparent, borderRadius: BorderRadius.circular(4), - onTap: onPressed, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - icon, - size: 20, - color: isSelected - ? ColorConstants.uiBlueAccent - : ColorConstants.gray700, + child: InkWell( + borderRadius: BorderRadius.circular(4), + onTap: onPressed, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + icon, + size: 20, + color: isSelected + ? ColorConstants.gray800 + : ColorConstants.gray700, + ), ), ), ), ); } + void _showColorPicker( + BuildContext context, + int selectedIndex, + Color currentColor, + ) async { + final pickedColor = await showColorPickerDialog( + context, + currentColor, + title: const Text('Pick shadow color'), + showColorCode: true, + showRecentColors: false, + backgroundColor: ColorConstants.uiWhite, + ); + if (context.mounted) { + context.read().changeShadowColor(selectedIndex, pickedColor); + } + } + void _showShadowPresetsDialog(BuildContext context, int selectedIndex) { showDialog( context: context, @@ -136,67 +208,72 @@ class ShadowControls extends StatelessWidget { ), title: const Row( children: [ - Icon(Icons.auto_awesome, color: ColorConstants.dialogButtonBlue), + Icon(Icons.auto_awesome, color: ColorConstants.gray800), SizedBox(width: 8), Text('Shadow Presets'), ], ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.soft, - 'Soft Shadow', - 'Light, subtle shadow', - Icons.wb_cloudy, - ), - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.medium, - 'Medium Shadow', - 'Balanced shadow effect', - Icons.filter_drama, - ), - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.hard, - 'Hard Shadow', - 'Strong, defined shadow', - Icons.wb_sunny, - ), - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.glow, - 'White Glow', - 'Soft white glow effect', - Icons.lightbulb_outline, - ), - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.coloredGlow, - 'Colored Glow', - 'Glow matching text color', - Icons.color_lens, - ), - _buildPresetTile( - context, - selectedIndex, - ShadowPreset.outline, - 'Outline', - 'Sharp text outline', - Icons.border_outer, - ), - ], + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.soft, + 'Soft Shadow', + 'Light, subtle shadow', + Icons.wb_cloudy, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.medium, + 'Medium Shadow', + 'Balanced shadow effect', + Icons.filter_drama, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.hard, + 'Hard Shadow', + 'Strong, defined shadow', + Icons.wb_sunny, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.glow, + 'White Glow', + 'Soft white glow effect', + Icons.lightbulb_outline, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.coloredGlow, + 'Colored Glow', + 'Glow matching text color', + Icons.color_lens, + ), + _buildPresetTile( + context, + selectedIndex, + ShadowPreset.outline, + 'Outline', + 'Sharp text outline', + Icons.border_outer, + ), + ], + ), ), actions: [ TextButton( onPressed: () => Navigator.pop(dialogContext), + style: TextButton.styleFrom( + foregroundColor: ColorConstants.gray800, + ), child: const Text('Close'), ), ], @@ -212,14 +289,21 @@ class ShadowControls extends StatelessWidget { String subtitle, IconData icon, ) { - return ListTile( - leading: Icon(icon, color: ColorConstants.dialogButtonBlue), - title: Text(title), - subtitle: Text(subtitle, style: const TextStyle(fontSize: 12)), - onTap: () { - context.read().applyShadowPreset(selectedIndex, preset); - Navigator.pop(context); - }, + return Container( + margin: const EdgeInsets.only(bottom: 8), + decoration: BoxDecoration( + border: Border.all(color: ColorConstants.gray300), + borderRadius: BorderRadius.circular(8), + ), + child: ListTile( + leading: Icon(icon, color: ColorConstants.gray800), + title: Text(title, style: const TextStyle(fontWeight: FontWeight.w600)), + subtitle: Text(subtitle, style: const TextStyle(fontSize: 12)), + onTap: () { + context.read().applyShadowPreset(selectedIndex, preset); + Navigator.pop(context); + }, + ), ); } @@ -237,162 +321,232 @@ class ShadowControls extends StatelessWidget { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), - builder: (sheetContext) => Padding( - padding: EdgeInsets.only( - bottom: MediaQuery.of(sheetContext).viewInsets.bottom, - top: 16, - left: 16, - right: 16, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Shadow Settings', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 20), + builder: (sheetContext) => BlocProvider.value( + value: context.read(), + child: BlocBuilder( + builder: (builderContext, state) { + final textItem = state.selectedTextItemIndex != null && + state.selectedTextItemIndex! < state.textItems.length + ? state.textItems[state.selectedTextItemIndex!] + : null; - // Shadow color picker - const Text('Shadow Color', - style: TextStyle(fontWeight: FontWeight.w600)), - const SizedBox(height: 8), - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: currentColor, - shape: BoxShape.circle, - border: Border.all(color: ColorConstants.gray300, width: 2), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: () async { - final pickedColor = await showColorPickerDialog( - sheetContext, - currentColor, - title: const Text('Pick shadow color'), - showColorCode: true, - showRecentColors: false, - ); - if (sheetContext.mounted) { - context - .read() - .changeShadowColor(selectedIndex, pickedColor); - } - }, - child: const Text('Choose Color'), + final shadowColor = textItem?.shadowColor ?? currentColor; + final shadowBlur = textItem?.shadowBlurRadius ?? currentBlur; + final shadowOffset = textItem?.shadowOffset ?? currentOffset; + + return Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(sheetContext).viewInsets.bottom, + top: 16, + left: 16, + right: 16, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Shadow Settings', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + IconButton( + icon: const Icon(Icons.close), + onPressed: () => Navigator.pop(sheetContext), + ), + ], ), - ), - ], - ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // Blur radius slider - const Text('Blur Radius', - style: TextStyle(fontWeight: FontWeight.w600)), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Slider( - value: currentBlur, - min: 0, - max: 50, - divisions: 50, - label: currentBlur.toStringAsFixed(1), - onChanged: (value) { - context - .read() - .changeShadowBlur(selectedIndex, value); - }, + // Shadow color picker + const Text('Shadow Color', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: shadowColor, + shape: BoxShape.circle, + border: + Border.all(color: ColorConstants.gray300, width: 2), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton( + onPressed: () async { + final pickedColor = await showColorPickerDialog( + sheetContext, + shadowColor, + title: const Text('Pick shadow color'), + showColorCode: true, + showRecentColors: false, + ); + if (builderContext.mounted) { + builderContext + .read() + .changeShadowColor(selectedIndex, pickedColor); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: ColorConstants.gray800, + foregroundColor: ColorConstants.uiWhite, + ), + child: const Text('Choose Color'), + ), + ), + ], ), - ), - SizedBox( - width: 50, - child: Text( - currentBlur.toStringAsFixed(1), - style: const TextStyle(fontWeight: FontWeight.w500), + const SizedBox(height: 20), + + // Blur radius slider + const Text('Blur Radius', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Slider( + value: shadowBlur, + min: 0, + max: 50, + divisions: 50, + label: shadowBlur.toStringAsFixed(1), + activeColor: ColorConstants.gray800, + onChanged: (value) { + builderContext + .read() + .changeShadowBlur(selectedIndex, value); + }, + ), + ), + SizedBox( + width: 50, + child: Text( + shadowBlur.toStringAsFixed(1), + style: const TextStyle(fontWeight: FontWeight.w500), + textAlign: TextAlign.center, + ), + ), + ], ), - ), - ], - ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // Offset controls - const Text('Shadow Offset', - style: TextStyle(fontWeight: FontWeight.w600)), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + // Offset controls + const Text('Shadow Offset', + style: TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + Row( children: [ - const Text('Horizontal', style: TextStyle(fontSize: 12)), - Slider( - value: currentOffset.dx, - min: -20, - max: 20, - divisions: 40, - label: currentOffset.dx.toStringAsFixed(1), - onChanged: (value) { - context.read().changeShadowOffset( - selectedIndex, Offset(value, currentOffset.dy)); - }, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Horizontal', + style: TextStyle(fontSize: 12)), + Row( + children: [ + Expanded( + child: Slider( + value: shadowOffset.dx, + min: -20, + max: 20, + divisions: 40, + label: shadowOffset.dx.toStringAsFixed(1), + activeColor: ColorConstants.gray800, + onChanged: (value) { + builderContext + .read() + .changeShadowOffset(selectedIndex, + Offset(value, shadowOffset.dy)); + }, + ), + ), + SizedBox( + width: 40, + child: Text( + shadowOffset.dx.toStringAsFixed(1), + style: const TextStyle(fontSize: 12), + textAlign: TextAlign.center, + ), + ), + ], + ), + ], + ), ), ], ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + Row( children: [ - const Text('Vertical', style: TextStyle(fontSize: 12)), - Slider( - value: currentOffset.dy, - min: -20, - max: 20, - divisions: 40, - label: currentOffset.dy.toStringAsFixed(1), - onChanged: (value) { - context.read().changeShadowOffset( - selectedIndex, Offset(currentOffset.dx, value)); - }, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Vertical', style: TextStyle(fontSize: 12)), + Row( + children: [ + Expanded( + child: Slider( + value: shadowOffset.dy, + min: -20, + max: 20, + divisions: 40, + label: shadowOffset.dy.toStringAsFixed(1), + activeColor: ColorConstants.gray800, + onChanged: (value) { + builderContext + .read() + .changeShadowOffset(selectedIndex, + Offset(shadowOffset.dx, value)); + }, + ), + ), + SizedBox( + width: 40, + child: Text( + shadowOffset.dy.toStringAsFixed(1), + style: const TextStyle(fontSize: 12), + textAlign: TextAlign.center, + ), + ), + ], + ), + ], + ), ), ], ), - ), - ], - ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // Close button - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () => Navigator.pop(sheetContext), - style: ElevatedButton.styleFrom( - backgroundColor: ColorConstants.dialogButtonBlue, - foregroundColor: ColorConstants.dialogWhite, - padding: const EdgeInsets.symmetric(vertical: 16), - ), - child: const Text('Done'), + // Close button + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () => Navigator.pop(sheetContext), + style: ElevatedButton.styleFrom( + backgroundColor: ColorConstants.gray800, + foregroundColor: ColorConstants.dialogWhite, + padding: const EdgeInsets.symmetric(vertical: 16), + ), + child: const Text('Done'), + ), + ), + const SizedBox(height: 16), + ], ), - ), - const SizedBox(height: 16), - ], + ); + }, ), ), ); } -} +} \ No newline at end of file From f8fbb312d48e4fc8af7d877cc2514824158d339b Mon Sep 17 00:00:00 2001 From: preetidas60 Date: Sat, 4 Oct 2025 09:53:39 +0530 Subject: [PATCH 3/4] Added Spacing in Fonts Controls --- lib/ui/widgets/font_controls.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ui/widgets/font_controls.dart b/lib/ui/widgets/font_controls.dart index 5e6ffa89..17266331 100644 --- a/lib/ui/widgets/font_controls.dart +++ b/lib/ui/widgets/font_controls.dart @@ -38,6 +38,7 @@ class FontControls extends StatelessWidget { _buildAlignmentControls(context), const SizedBox(width: 25), _buildHighlightControls(context), + const SizedBox(width: 25), const ShadowControls(), const SizedBox(width: 25), _buildFontFamilyControls(context), From 8e0d61055ab5f732fc0f29c14a437aa79749c11f Mon Sep 17 00:00:00 2001 From: preetidas60 Date: Sat, 4 Oct 2025 12:38:29 +0530 Subject: [PATCH 4/4] Removed Colors Field from the Shadows Control --- lib/ui/widgets/shadows_controls.dart | 45 ---------------------------- 1 file changed, 45 deletions(-) diff --git a/lib/ui/widgets/shadows_controls.dart b/lib/ui/widgets/shadows_controls.dart index d1547687..d85041e7 100644 --- a/lib/ui/widgets/shadows_controls.dart +++ b/lib/ui/widgets/shadows_controls.dart @@ -330,7 +330,6 @@ class ShadowControls extends StatelessWidget { ? state.textItems[state.selectedTextItemIndex!] : null; - final shadowColor = textItem?.shadowColor ?? currentColor; final shadowBlur = textItem?.shadowBlurRadius ?? currentBlur; final shadowOffset = textItem?.shadowOffset ?? currentOffset; @@ -363,50 +362,6 @@ class ShadowControls extends StatelessWidget { ), const SizedBox(height: 20), - // Shadow color picker - const Text('Shadow Color', - style: TextStyle(fontWeight: FontWeight.w600)), - const SizedBox(height: 8), - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: shadowColor, - shape: BoxShape.circle, - border: - Border.all(color: ColorConstants.gray300, width: 2), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: () async { - final pickedColor = await showColorPickerDialog( - sheetContext, - shadowColor, - title: const Text('Pick shadow color'), - showColorCode: true, - showRecentColors: false, - ); - if (builderContext.mounted) { - builderContext - .read() - .changeShadowColor(selectedIndex, pickedColor); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: ColorConstants.gray800, - foregroundColor: ColorConstants.uiWhite, - ), - child: const Text('Choose Color'), - ), - ), - ], - ), - const SizedBox(height: 20), - // Blur radius slider const Text('Blur Radius', style: TextStyle(fontWeight: FontWeight.w600)),