From 5a00eeafd9cc709388cd408f1f1fb3c8dbb84c2c Mon Sep 17 00:00:00 2001 From: hm21 Date: Fri, 27 Dec 2024 10:36:14 +0100 Subject: [PATCH] refactor(configs): reorganize file structure for better maintainability - Moved `custom widgets`, `icons`, and `theme` files to the `configs` directory. - Renamed all `theme` files to `styles` for better clarity and alignment with their purpose. - Updated paths for `custom widgets`, `icons`, and `styles`, now located under `configs` directory. - Renamed `theme` classes to end with `Style` for consistency. - Updated `README.md` and `CHANGELOG.md` with details of the restructuring. - Provided a link to the relevant [GitHub discussion](https://github.com/hm21/pro_image_editor/discussions/298). - Adjusted test files to match the updated file paths and naming conventions. --- .github/FUNDING.yml | 1 + CHANGELOG.md | 24 +- README.md | 410 ++------------- example/lib/common/example_constants.dart | 9 + example/lib/common/examples.dart | 150 ++++++ example/lib/main.dart | 265 ++++++---- example/lib/models/example_model.dart | 33 ++ example/lib/pages/crop_to_main_editor.dart | 76 +-- ...ample.dart => custom_widgets_example.dart} | 154 +++--- example/lib/pages/default_example.dart | 237 ++++----- .../pages/design_examples/design_example.dart | 130 ++--- .../frosted_glass_example.dart | 187 +++---- .../design_examples/grounded_example.dart | 252 ++++----- .../highly_configurable_example.dart | 486 +++++++++--------- .../design_examples/whatsapp_example.dart | 383 +++++++------- .../lib/pages/firebase_supabase_example.dart | 36 +- example/lib/pages/frame_example.dart | 185 ++++--- .../lib/pages/generation_configs_example.dart | 20 +- example/lib/pages/google_font_example.dart | 79 +-- .../pages/image_format_convert_example.dart | 37 +- example/lib/pages/import_export_example.dart | 86 ++-- .../lib/pages/movable_background_image.dart | 352 ++++++------- example/lib/pages/pick_image_example.dart | 259 +--------- example/lib/pages/preview_img.dart | 2 +- example/lib/pages/reorder_layer_example.dart | 45 +- example/lib/pages/round_cropper_example.dart | 50 +- .../lib/pages/selectable_layer_example.dart | 56 +- .../lib/pages/signature_drawing_example.dart | 198 ++++--- example/lib/pages/standalone_example.dart | 229 ++++----- example/lib/pages/stickers_example.dart | 40 +- example/lib/pages/zoom_example.dart | 80 +++ .../lib/pages/zoom_move_editor_example.dart | 93 ---- example/lib/utils/example_constants.dart | 43 -- example/lib/utils/example_helper.dart | 56 +- .../lib/utils/import_history_demo_data.dart | 6 +- example/lib/widgets/demo_build_stickers.dart | 2 +- example/lib/widgets/material_icon_button.dart | 127 +++++ example/lib/widgets/not_found_example.dart | 30 ++ example/lib/widgets/prepare_image_widget.dart | 46 ++ lib/common/editor_style_constants.dart | 31 ++ lib/common/editor_various_constants.dart | 2 + lib/designs/frosted_glass/frosted_glass.dart | 4 +- .../frosted_glass/frosted_glass_appbar.dart | 46 +- .../frosted_glass_blur_appbar.dart | 4 +- .../frosted_glass_crop_rotate_toolbar.dart | 19 +- .../frosted_glass_filter_appbar.dart | 4 +- ...r.dart => frosted_glass_paint_appbar.dart} | 30 +- ...art => frosted_glass_paint_bottombar.dart} | 20 +- .../frosted_glass_sticker_editor.dart | 10 +- .../frosted_glass_text_appbar.dart | 14 +- .../frosted_glass_text_bottombar.dart | 3 +- .../frosted_glass_tune_appbar.dart | 8 +- .../frosted_glass_tune_bottombar.dart | 2 +- lib/designs/grounded/grounded_blur_bar.dart | 2 +- lib/designs/grounded/grounded_bottom_bar.dart | 11 +- .../grounded/grounded_bottom_wrapper.dart | 2 +- .../grounded/grounded_crop_rotate_bar.dart | 11 +- lib/designs/grounded/grounded_design.dart | 2 +- .../grounded/grounded_emoji_editor.dart | 5 +- lib/designs/grounded/grounded_filter_bar.dart | 2 +- lib/designs/grounded/grounded_main_bar.dart | 28 +- ...nting_bar.dart => grounded_paint_bar.dart} | 47 +- .../grounded/grounded_sticker_editor.dart | 5 +- lib/designs/grounded/grounded_text_bar.dart | 15 +- lib/designs/grounded/grounded_tune_bar.dart | 5 +- lib/designs/whatsapp/whatsapp.dart | 4 +- lib/designs/whatsapp/whatsapp_appbar.dart | 24 +- .../whatsapp_crop_rotate_toolbar.dart | 24 +- ...appbar.dart => whatsapp_paint_appbar.dart} | 9 +- ...bar.dart => whatsapp_paint_bottombar.dart} | 16 +- .../whatsapp/whatsapp_paint_colorpicker.dart | 19 +- .../whatsapp/whatsapp_sticker_editor.dart | 30 +- .../whatsapp/whatsapp_text_appbar.dart | 11 +- .../whatsapp/whatsapp_text_bottombar.dart | 4 +- lib/mixins/converted_configs.dart | 38 +- .../main_editor/main_editor_global_keys.dart | 6 +- ...r_editor.dart => blur_editor_widgets.dart} | 13 +- ...r.dart => crop_rotate_editor_widgets.dart} | 12 +- lib/models/custom_widgets/custom_widgets.dart | 160 ------ lib/models/custom_widgets/dialog_widgets.dart | 83 +++ ...editor.dart => filter_editor_widgets.dart} | 10 +- ...on.dart => layer_interaction_widgets.dart} | 12 +- ...n_editor.dart => main_editor_widgets.dart} | 16 +- ..._editor.dart => paint_editor_widgets.dart} | 48 +- .../progress_indicator_widgets.dart | 22 + ...t_editor.dart => text_editor_widgets.dart} | 13 +- ...e_editor.dart => tune_editor_widgets.dart} | 13 +- .../editor_configs/blur_editor_configs.dart | 25 + .../crop_rotate_editor_configs.dart | 24 + lib/models/editor_configs/dialog_configs.dart | 31 ++ .../editor_configs/emoji_editor_configs.dart | 17 +- .../editor_configs/filter_editor_configs.dart | 25 + .../editor_configs/helper_lines_configs.dart | 30 +- .../image_generation_configs.dart | 2 +- .../layer_interaction_configs.dart | 43 +- .../editor_configs/main_editor_configs.dart | 33 +- .../editor_configs/paint_editor_configs.dart | 25 + .../pro_image_editor_configs.dart | 153 +++--- .../progress_indicator_configs.dart | 23 + .../sticker_editor_configs.dart | 22 +- .../editor_configs/text_editor_configs.dart | 25 + .../editor_configs/tune_editor_configs.dart | 25 + lib/models/i18n/i18n.dart | 26 +- ...ing_editor.dart => i18n_paint_editor.dart} | 36 +- ...lur_editor.dart => blur_editor_icons.dart} | 28 +- ...tor.dart => crop_rotate_editor_icons.dart} | 40 +- ...ji_editor.dart => emoji_editor_icons.dart} | 14 +- ...r_editor.dart => filter_editor_icons.dart} | 28 +- lib/models/icons/icons.dart | 204 -------- ...tion.dart => layer_interaction_icons.dart} | 14 +- lib/models/icons/main_editor_icons.dart | 63 +++ ...ng_editor.dart => paint_editor_icons.dart} | 44 +- ..._editor.dart => sticker_editor_icons.dart} | 12 +- ...ext_editor.dart => text_editor_icons.dart} | 28 +- ...une_editor.dart => tune_editor_icons.dart} | 38 +- .../import_export/export_state_history.dart | 6 +- .../export_state_history_configs.dart | 8 +- .../crop_rotate_editor_init_configs.dart | 6 + .../init_configs/editor_init_configs.dart | 4 + .../paint_editor_init_configs.dart | 2 +- lib/models/layer/layer.dart | 42 +- .../paint_editor/paint_bottom_bar_item.dart | 16 +- lib/models/paint_editor/painted_model.dart | 4 +- .../adaptive_dialog_style.dart} | 16 +- .../blur_editor_style.dart} | 42 +- .../crop_rotate_editor_style.dart} | 79 +-- lib/models/styles/dialog_style.dart | 31 ++ .../draggable_sheet_style.dart} | 16 +- .../emoji_editor_style.dart} | 36 +- .../filter_editor_style.dart} | 67 ++- .../helper_line_style.dart} | 28 +- .../layer_interaction_style.dart} | 18 +- .../loading_dialog_style.dart} | 23 +- lib/models/styles/main_editor_style.dart | 75 +++ .../paint_editor_style.dart} | 104 ++-- .../sticker_editor_style.dart} | 34 +- .../sub_editor_page_style.dart} | 16 +- .../text_editor_style.dart} | 67 +-- lib/models/styles/tune_editor_style.dart | 79 +++ .../types/style_types.dart} | 0 lib/models/theme/theme.dart | 253 --------- lib/models/theme/theme_shared_values.dart | 14 - lib/models/theme/theme_tune_editor.dart | 76 --- lib/modules/blur_editor/blur_editor.dart | 32 +- .../crop_rotate_editor.dart | 70 +-- .../utils/crop_area_history.dart | 4 +- .../widgets/crop_aspect_ratio_options.dart | 11 +- .../widgets/crop_corner_painter.dart | 45 +- lib/modules/emoji_editor/emoji_editor.dart | 26 +- .../emoji_editor_full_screen_search.dart | 2 +- .../widgets/emoji_editor_header_search.dart | 7 +- .../widgets/emoji_picker_view.dart | 22 +- lib/modules/filter_editor/filter_editor.dart | 32 +- .../widgets/filter_editor_item_list.dart | 24 +- lib/modules/main_editor/main_editor.dart | 240 ++++----- .../utils/desktop_interaction_manager.dart | 8 +- .../main_editor/utils/layer_copy_manager.dart | 12 +- .../utils/layer_interaction_manager.dart | 23 +- lib/modules/paint_editor/paint_editor.dart | 288 +++++------ .../paint_editor/utils/paint_controller.dart | 76 +-- .../paint_desktop_interaction_manager.dart | 2 +- .../paint_editor/utils/paint_editor_enum.dart | 4 +- .../paint_editor/utils/paint_element.dart | 4 +- ...raw_painting.dart => draw_paint_item.dart} | 8 +- ...painting_canvas.dart => paint_canvas.dart} | 76 +-- .../sticker_editor/sticker_editor.dart | 9 +- lib/modules/text_editor/text_editor.dart | 82 ++- .../widgets/text_editor_bottom_bar.dart | 11 +- lib/modules/tune_editor/tune_editor.dart | 54 +- .../tune_editor/utils/tune_presets.dart | 4 +- lib/pro_image_editor.dart | 1 + .../content_recorder_controller.dart | 67 ++- .../isolate/isolate_manager.dart | 4 +- .../web_worker/web_worker_manager.dart | 4 +- .../utils/generate_high_quality_image.dart | 2 +- lib/widgets/adaptive_dialog.dart | 21 +- .../extended/extended_custom_paint.dart | 22 +- .../layer_interaction_border_painter.dart | 4 +- .../layer_interaction_helper_widget.dart | 50 +- lib/widgets/layer_stack.dart | 11 +- lib/widgets/layer_widget.dart | 16 +- .../loading_dialog/loading_dialog.dart | 16 +- .../platform_circular_progress_indicator.dart | 3 +- .../transformed_content_generator.dart | 2 +- pubspec.yaml | 2 +- .../crop_rotate_editor_test.dart | 4 +- .../crop_aspect_ratio_options_test.dart | 3 +- .../widgets/crop_corner_painter_test.dart | 46 +- .../paint_editor/paint_editor_test.dart | 34 +- .../paint_editor/painting_canvas_test.dart | 24 +- .../utils/draw/draw_canvas_test.dart | 4 +- .../utils/paint_controller_test.dart | 18 +- test/modules/sticker_editor_test.dart | 2 +- test/pro_image_editor_test.dart | 119 +---- 194 files changed, 4742 insertions(+), 5026 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 example/lib/common/example_constants.dart create mode 100644 example/lib/common/examples.dart create mode 100644 example/lib/models/example_model.dart rename example/lib/pages/{custom_appbar_bottombar_example.dart => custom_widgets_example.dart} (89%) create mode 100644 example/lib/pages/zoom_example.dart delete mode 100644 example/lib/pages/zoom_move_editor_example.dart delete mode 100644 example/lib/utils/example_constants.dart create mode 100644 example/lib/widgets/material_icon_button.dart create mode 100644 example/lib/widgets/not_found_example.dart create mode 100644 example/lib/widgets/prepare_image_widget.dart create mode 100644 lib/common/editor_style_constants.dart create mode 100644 lib/common/editor_various_constants.dart rename lib/designs/frosted_glass/{frosted_glass_painting_appbar.dart => frosted_glass_paint_appbar.dart} (74%) rename lib/designs/frosted_glass/{frosted_glass_painting_bottombar.dart => frosted_glass_paint_bottombar.dart} (92%) rename lib/designs/grounded/{grounded_painting_bar.dart => grounded_paint_bar.dart} (84%) rename lib/designs/whatsapp/{whatsapp_painting_appbar.dart => whatsapp_paint_appbar.dart} (91%) rename lib/designs/whatsapp/{whatsapp_painting_bottombar.dart => whatsapp_paint_bottombar.dart} (94%) rename lib/models/custom_widgets/{custom_widgets_blur_editor.dart => blur_editor_widgets.dart} (86%) rename lib/models/custom_widgets/{custom_widgets_crop_rotate_editor.dart => crop_rotate_editor_widgets.dart} (89%) delete mode 100644 lib/models/custom_widgets/custom_widgets.dart create mode 100644 lib/models/custom_widgets/dialog_widgets.dart rename lib/models/custom_widgets/{custom_widgets_filter_editor.dart => filter_editor_widgets.dart} (93%) rename lib/models/custom_widgets/{custom_widgets_layer_interaction.dart => layer_interaction_widgets.dart} (87%) rename lib/models/custom_widgets/{custom_widgets_main_editor.dart => main_editor_widgets.dart} (92%) rename lib/models/custom_widgets/{custom_widgets_paint_editor.dart => paint_editor_widgets.dart} (66%) create mode 100644 lib/models/custom_widgets/progress_indicator_widgets.dart rename lib/models/custom_widgets/{custom_widgets_text_editor.dart => text_editor_widgets.dart} (90%) rename lib/models/custom_widgets/{custom_widgets_tune_editor.dart => tune_editor_widgets.dart} (87%) create mode 100644 lib/models/editor_configs/dialog_configs.dart create mode 100644 lib/models/editor_configs/progress_indicator_configs.dart rename lib/models/i18n/{i18n_painting_editor.dart => i18n_paint_editor.dart} (81%) rename lib/models/icons/{icons_blur_editor.dart => blur_editor_icons.dart} (53%) rename lib/models/icons/{icons_crop_rotate_editor.dart => crop_rotate_editor_icons.dart} (61%) rename lib/models/icons/{icons_emoji_editor.dart => emoji_editor_icons.dart} (78%) rename lib/models/icons/{icons_filter_editor.dart => filter_editor_icons.dart} (53%) delete mode 100644 lib/models/icons/icons.dart rename lib/models/icons/{icons_layer_interaction.dart => layer_interaction_icons.dart} (77%) create mode 100644 lib/models/icons/main_editor_icons.dart rename lib/models/icons/{icons_painting_editor.dart => paint_editor_icons.dart} (78%) rename lib/models/icons/{icons_sticker_editor.dart => sticker_editor_icons.dart} (80%) rename lib/models/icons/{icons_text_editor.dart => text_editor_icons.dart} (78%) rename lib/models/icons/{icons_tune_editor.dart => tune_editor_icons.dart} (72%) rename lib/models/{theme/theme_adaptive_dialog.dart => styles/adaptive_dialog_style.dart} (71%) rename lib/models/{theme/theme_blur_editor.dart => styles/blur_editor_style.dart} (58%) rename lib/models/{theme/theme_crop_rotate_editor.dart => styles/crop_rotate_editor_style.dart} (65%) create mode 100644 lib/models/styles/dialog_style.dart rename lib/models/{theme/theme_draggable_sheet.dart => styles/draggable_sheet_style.dart} (88%) rename lib/models/{theme/theme_emoji_editor.dart => styles/emoji_editor_style.dart} (87%) rename lib/models/{theme/theme_filter_editor.dart => styles/filter_editor_style.dart} (60%) rename lib/models/{theme/theme_helper_lines.dart => styles/helper_line_style.dart} (69%) rename lib/models/{theme/theme_layer_interaction.dart => styles/layer_interaction_style.dart} (94%) rename lib/models/{theme/theme_loading_dialog.dart => styles/loading_dialog_style.dart} (68%) create mode 100644 lib/models/styles/main_editor_style.dart rename lib/models/{theme/theme_painting_editor.dart => styles/paint_editor_style.dart} (58%) rename lib/models/{theme/theme_sticker_editor.dart => styles/sticker_editor_style.dart} (66%) rename lib/models/{theme/theme_sub_editor_page.dart => styles/sub_editor_page_style.dart} (89%) rename lib/models/{theme/theme_text_editor.dart => styles/text_editor_style.dart} (64%) create mode 100644 lib/models/styles/tune_editor_style.dart rename lib/models/{theme/types/theme_types.dart => styles/types/style_types.dart} (100%) delete mode 100644 lib/models/theme/theme.dart delete mode 100644 lib/models/theme/theme_shared_values.dart delete mode 100644 lib/models/theme/theme_tune_editor.dart rename lib/modules/paint_editor/widgets/{draw_painting.dart => draw_paint_item.dart} (98%) rename lib/modules/paint_editor/widgets/{painting_canvas.dart => paint_canvas.dart} (72%) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..2a355667 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [hm21] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ca2518..91a5b08f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,26 @@ # Changelog +## 7.0.0 +### Changed +- **File Structure Update**: + - Moved `custom widgets`, `icons`, and `theme` files into the `configs` directory for better organization. + - Renamed all `theme` files to `styles` to better reflect their purpose. + +### Breaking Changes +- File renaming and restructuring require updates to your configuration file: + - `custom widgets`, `icons`, and `theme` files are now located directly in the `configs` directory of the editor. + - All theme classes are renamed to end with `Style` for consistency. + + +For more details on why these breaking changes were made and what improvements they bring, check out that [GitHub discussion](https://github.com/hm21/pro_image_editor/discussions/298). + + + ## 6.2.3 - **FIX**(layer): Resolve issue that layer reposition correctly after screen rotation. This resolves issue [#283](https://github.com/hm21/pro_image_editor/issues/283) ## 6.2.2 -- fix(version): Set minimum Flutter version to `3.27.0`. This resolves issue [#287](https://github.com/hm21/pro_image_editor/issues/287) +- **Fix**(version): Set minimum Flutter version to `3.27.0`. This resolves issue [#287](https://github.com/hm21/pro_image_editor/issues/287) ## 6.2.1 - **FIX**(lint): Resolve lint issues after upgrading to Flutter `3.27.0` @@ -54,7 +70,7 @@ - **FIX**(Example): Resolve all linting issues in the example code. ## 5.4.2 -- **FIX**(Painting-Editor): Resolve issue where undo-redo action capturing the incorrect image. This resolves issue [#239](https://github.com/hm21/pro_image_editor/issues/239) +- **FIX**(Paint-Editor): Resolve issue where undo-redo action capturing the incorrect image. This resolves issue [#239](https://github.com/hm21/pro_image_editor/issues/239) ## 5.4.1 - **FEAT**(Emoji-Editor): Update the emoji-editor to version `3.1.0` with custom view order configuration support. @@ -419,7 +435,7 @@ configs: ProImageEditorConfigs( - More theme and configuration options - Hero animation for image and layers - Round "cropper" for profile pictures -- **FEAT**: Painting-Editor +- **FEAT**: Paint-Editor - Standalone drawing of signatures or paintings - **FEAT**: Emoji-Editor - Infinite scrolling through all categories @@ -706,7 +722,7 @@ configs: ProImageEditorConfigs( ## 1.0.0 -- **FEAT**: PaintingEditor +- **FEAT**: PaintEditor - **FEAT**: TextEditor - **FEAT**: CropRotateEditor - **FEAT**: FilterEditor diff --git a/README.md b/README.md index b749d650..9b7f32e0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ pub package + + Sponsor + License @@ -143,7 +146,7 @@ The ProImageEditor is a Flutter widget designed for image editing within your ap ## Features - ✅ Multiple-Editors - - ✅ Painting-Editor + - ✅ Paint-Editor - ✅ Color picker - ✅ Multiple forms like arrow, rectangle, circle and freestyle - ✅ Text-Editor @@ -186,9 +189,9 @@ The ProImageEditor is a Flutter widget designed for image editing within your ap #### Planned features -- ✨ Painting-Editor - - New painting style which pixelates the background - - Freestyle Painter with improved performance and hitbox +- ✨ Paint-Editor + - New mode which pixelates the background + - Freestyle-Painter with improved performance and hitbox - ✨ Text-Editor - Text-layer with an improved hit-box and ensure it's vertically centered on all devices - ✨ Emoji-Editor @@ -398,7 +401,7 @@ return Scaffold( ], i18n: const I18n( various: I18nVarious(), - paintEditor: I18nPaintingEditor(), + paintEditor: I18nPaintEditor(), textEditor: I18nTextEditor(), cropRotateEditor: I18nCropRotateEditor(), filterEditor: I18nFilterEditor(filters: I18nFilters()), @@ -420,7 +423,7 @@ return Scaffold( verticalColor: Color(0xFF1565C0), rotateColor: Color(0xFFE91E63), ), - paintingEditor: PaintingEditorTheme(), + paintEditor: PaintEditorTheme(), textEditor: TextEditorTheme(), cropRotateEditor: CropRotateEditorTheme(), filterEditor: FilterEditorTheme(), @@ -437,7 +440,7 @@ return Scaffold( ), ), icons: const ImageEditorIcons( - paintingEditor: IconsPaintingEditor(), + paintEditor: IconsPaintEditor(), textEditor: IconsTextEditor(), cropRotateEditor: IconsCropRotateEditor(), filterEditor: IconsFilterEditor(), @@ -632,7 +635,7 @@ class DemoState extends State { }), ], ), - appBarPaintingEditor: AppBar( + appBarPaintEditor: AppBar( automaticallyImplyLeading: false, foregroundColor: Colors.white, backgroundColor: Colors.black, @@ -643,7 +646,7 @@ class DemoState extends State { return IconButton( padding: const EdgeInsets.symmetric(horizontal: 8), icon: const Icon(Icons.arrow_back), - onPressed: _editorKey.currentState?.paintingEditor.currentState?.close, + onPressed: _editorKey.currentState?.paintEditor.currentState?.close, ); }), const SizedBox(width: 80), @@ -657,7 +660,7 @@ class DemoState extends State { Icons.line_weight_rounded, color: Colors.white, ), - onPressed: _editorKey.currentState?.paintingEditor.currentState?.openLineWeightBottomSheet, + onPressed: _editorKey.currentState?.paintEditor.currentState?.openLineWeightBottomSheet, ); }), StreamBuilder( @@ -666,12 +669,12 @@ class DemoState extends State { return IconButton( padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - _editorKey.currentState?.paintingEditor.currentState?.fillBackground == true + _editorKey.currentState?.paintEditor.currentState?.fillBackground == true ? Icons.format_color_reset : Icons.format_color_fill, color: Colors.white, ), - onPressed: _editorKey.currentState?.paintingEditor.currentState?.toggleFill); + onPressed: _editorKey.currentState?.paintEditor.currentState?.toggleFill); }), const Spacer(), IconButton( @@ -691,9 +694,9 @@ class DemoState extends State { padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( Icons.undo, - color: _editorKey.currentState?.paintingEditor.currentState?.canUndo == true ? Colors.white : Colors.white.withAlpha(80), + color: _editorKey.currentState?.paintEditor.currentState?.canUndo == true ? Colors.white : Colors.white.withAlpha(80), ), - onPressed: _editorKey.currentState?.paintingEditor.currentState?.undoAction, + onPressed: _editorKey.currentState?.paintEditor.currentState?.undoAction, ); }), StreamBuilder( @@ -704,9 +707,9 @@ class DemoState extends State { padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( Icons.redo, - color: _editorKey.currentState?.paintingEditor.currentState?.canRedo == true ? Colors.white : Colors.white.withAlpha(80), + color: _editorKey.currentState?.paintEditor.currentState?.canRedo == true ? Colors.white : Colors.white.withAlpha(80), ), - onPressed: _editorKey.currentState?.paintingEditor.currentState?.redoAction, + onPressed: _editorKey.currentState?.paintEditor.currentState?.redoAction, ); }), StreamBuilder( @@ -717,7 +720,7 @@ class DemoState extends State { padding: const EdgeInsets.symmetric(horizontal: 8), icon: const Icon(Icons.done), iconSize: 28, - onPressed: _editorKey.currentState?.paintingEditor.currentState?.done, + onPressed: _editorKey.currentState?.paintEditor.currentState?.done, ); }), ], @@ -959,7 +962,7 @@ The state history from the image editor can be exported and imported. However, i await _editor.currentState?.exportStateHistory( // All configurations are optional configs: const ExportEditorConfigs( - exportPainting: true, + exportPaint: true, exportText: true, exportCropRotate: false, exportFilter: true, @@ -1065,26 +1068,28 @@ Creates a `ProImageEditor` widget for editing an image from an asset. Creates a `ProImageEditor` widget for editing an image from a network URL. ### ProImageEditorConfigs + | Property Name | Description | Default Value | |-----------------------------------|----------------------------------------------------------------------------|------------------------------------| -| `i18n` | Internationalization settings for the Image Editor. | `I18n()` | -| `helperLines` | Configuration options for helper lines in the Image Editor. | `HelperLines()` | -| `customWidgets` | Custom widgets to be used in the Image Editor. | `ImageEditorCustomWidgets()` | -| `imageEditorTheme` | Theme settings for the Image Editor. | `ImageEditorTheme()` | -| `icons` | Icons to be used in the Image Editor. | `ImageEditorIcons()` | -| `paintEditorConfigs` | Configuration options for the Paint Editor. | `PaintEditorConfigs()` | -| `textEditorConfigs` | Configuration options for the Text Editor. | `TextEditorConfigs()` | -| `cropRotateEditorConfigs` | Configuration options for the Crop and Rotate Editor. | `CropRotateEditorConfigs()` | -| `filterEditorConfigs` | Configuration options for the Filter Editor. | `FilterEditorConfigs()` | -| `blurEditorConfigs` | Configuration options for the Blur Editor. | `BlurEditorConfigs()` | -| `emojiEditorConfigs` | Configuration options for the Emoji Editor. | `EmojiEditorConfigs()` | -| `stickerEditorConfigs` | Configuration options for the Sticker Editor. | `StickerEditorConfigs()` | +| `blurEditor` | Configuration options for the Blur Editor. | `BlurEditorConfigs()` | +| `cropRotateEditor` | Configuration options for the Crop and Rotate Editor. | `CropRotateEditorConfigs()` | | `designMode` | The design mode for the Image Editor. | `ImageEditorDesignModeE.material` | -| `theme` | The theme to be used for the Image Editor. | `null` | +| `dialogConfigs` | Configuration for the loading dialog used in the editor. | `DialogConfigs()` | +| `emojiEditor` | Configuration options for the Emoji Editor. | `EmojiEditorConfigs()` | +| `filterEditor` | Configuration options for the Filter Editor. | `FilterEditorConfigs()` | +| `helperLines` | Configuration options for helper lines in the Image Editor. | `HelperLineConfigs()` | | `heroTag` | A unique hero tag for the Image Editor widget. | `'Pro-Image-Editor-Hero'` | -| `layerInteraction` | Configuration options for the layer interaction behavior. | `LayerInteraction()` | -| `stateHistoryConfigs` | Holds the configurations related to state history management. | `StateHistoryConfigs()` | -| `imageGenerationConfigs` | Holds the configurations related to image generation. | `imageGenerationConfigs()` | +| `i18n` | Internationalization settings for the Image Editor. | `I18n()` | +| `imageGeneration` | Holds the configurations related to image generation. | `ImageGenerationConfigs()` | +| `layerInteraction` | Configuration options for the layer interaction behavior. | `LayerInteractionConfigs()` | +| `mainEditor` | Configuration options for the Main Editor. | `MainEditorConfigs()` | +| `paintEditor` | Configuration options for the Paint Editor. | `PaintEditorConfigs()` | +| `progressIndicatorConfigs` | Configuration for customizing progress indicators. | `ProgressIndicatorConfigs()` | +| `stateHistory` | Holds the configurations related to state history management. | `StateHistoryConfigs()` | +| `stickerEditor` | Configuration options for the Sticker Editor. | `StickerEditorConfigs()` | +| `textEditor` | Configuration options for the Text Editor. | `TextEditorConfigs()` | +| `theme` | The theme to be used for the Image Editor. | `null` | +| `tuneEditor` | Configuration options for the Tune Editor. | `TuneEditorConfigs()` | ### ProImageEditorCallbacks @@ -1227,343 +1232,6 @@ Creates a `ProImageEditor` widget for editing an image from a network URL. -
- helperLines - -| Property | Description | Default Value | -|----------------------|-----------------------------------------------------------------------------------------------|---------------| -| `showVerticalLine` | Specifies whether to show the vertical helper line. | `true` | -| `showHorizontalLine` | Specifies whether to show the horizontal helper line. | `true` | -| `showRotateLine` | Specifies whether to show the rotate helper line. | `true` | -| `hitVibration` | Controls whether haptic feedback is enabled when a layer intersects with a helper line. When set to `true`, haptic feedback is triggered when a layer's position or boundary intersects with a helper line, providing tactile feedback to the user. This feature enhances the user experience by providing feedback on layer alignment. By default, this option is set to `true`, enabling haptic feedback for hit detection with helper lines. You can set it to `false` to disable haptic feedback. | `true` | -
- - -
- imageEditorTheme - -| Property Name | Description | Default Value | -|------------------------------|---------------------------------------------------------------------|-------------------------------| -| `helperLine` | Theme for helper lines in the image editor. | `HelperLineTheme()` | -| `paintingEditor` | Theme for the painting editor. | `PaintingEditorTheme()` | -| `textEditor` | Theme for the text editor. | `TextEditorTheme()` | -| `cropRotateEditor` | Theme for the crop & rotate editor. | `CropRotateEditorTheme()` | -| `filterEditor` | Theme for the filter editor. | `FilterEditorTheme()` | -| `blurEditor` | Theme for the blur editor. | `BlurEditorTheme()` | -| `emojiEditor` | Theme for the emoji editor. | `EmojiEditorTheme()` | -| `stickerEditor` | Theme for the sticker editor. | `StickerEditorTheme()` | -| `background` | Background color for the image editor in the overview. | `imageEditorBackgroundColor` | -| `bottomBarBackgroundColor` | Background color for the BottomBar in the overview. | `Color(0xFF000000)` | -| `appBarBackgroundColor` | Background color for the AppBar in the overview. | `Color(0xFF000000)` | -| `appBarForegroundColor` | Foreground color for the AppBar in the overview. | `Color(0xFFFFFFFF)` | -| `loadingDialogTheme` | Theme for the loading dialog. | `LoadingDialogTheme()` | -| `adaptiveDialogTheme` | Theme for the adaptive dialog. | `AdaptiveDialogTheme()` | -| `uiOverlayStyle` | Defines the system UI overlay style for the image editor. | `SystemUiOverlayStyle(...)` | -| `layerInteraction` | Theme for the layer interaction settings. | `ThemeLayerInteraction()` | - - -#### Theme paintingEditor -| Property Name | Description | Default Value | -|------------------------------|----------------------------------------------------------|-------------------------------| -| `appBarBackgroundColor` | Background color of the app bar in the painting editor. | `imageEditorAppBarColor` | -| `appBarForegroundColor` | Foreground color (text and icons) of the app bar. | `Color(0xFFE1E1E1)` | -| `background` | Background color of the painting editor. | `imageEditorBackgroundColor` | -| `bottomBarColor` | Background color of the bottom navigation bar. | `imageEditorAppBarColor` | -| `bottomBarActiveItemColor` | Color of active items in the bottom navigation bar. | `imageEditorPrimaryColor` | -| `bottomBarInactiveItemColor` | Color of inactive items in the bottom navigation bar. | `Color(0xFFEEEEEE)` | -| `lineWidthBottomSheetColor` | Color of the bottom sheet used to select line width. | `Color(0xFF252728)` | - -#### Theme textEditor -| Property Name | Description | Default Value | -|------------------------------|---------------------------------------------------------|-------------------------------| -| `appBarBackgroundColor` | Background color of the app bar in the text editor. | `imageEditorAppBarColor` | -| `bottomBarBackgroundColor` | Background color of the bottom bar in the text editor. | `Color(0xFF000000)` | -| `appBarForegroundColor` | Foreground color (text and icons) of the app bar. | `Color(0xFFE1E1E1)` | -| `background` | Background color of the text editor. | `Color(0x9B000000)` | -| `inputHintColor` | Color of input hints in the text editor. | `Color(0xFFBDBDBD)` | -| `inputCursorColor` | Color of the input cursor in the text editor. | `imageEditorPrimaryColor` | - - -#### Theme cropRotateEditor -| Property Name | Description | Default Value | -|----------------------------------------|--------------------------------------------------------------------------------------------------|-------------------------------| -| `appBarBackgroundColor` | Background color of the app bar in the crop and rotate editor. | `imageEditorAppBarColor` | -| `appBarForegroundColor` | Foreground color (text and icons) of the app bar. | `Color(0xFFE1E1E1)` | -| `bottomBarBackgroundColor` | Background color of the bottom app bar. | `imageEditorAppBarColor` | -| `bottomBarForegroundColor` | Foreground color (text and icons) of the bottom app bar. | `Color(0xFFE1E1E1)` | -| `aspectRatioSheetBackgroundColor` | Background color of the bottom sheet for aspect ratios. | `Color(0xFF303030)` | -| `aspectRatioSheetForegroundColor` | Foreground color of the bottom sheet for aspect ratios. | `Color(0xFFFAFAFA)` | -| `background` | Background color of the crop and rotate editor. | `imageEditorBackgroundColor` | -| `cropCornerColor` | Color of the crop corners. | `imageEditorPrimaryColor` | -| `helperLineColor` | Color of the helper lines when moving the image. | `Color(0xFF000000)` | -| `cropOverlayColor` | Color of the overlay area atop the image when the cropping area is smaller than the image. | `Color(0xFF000000)` | - - -#### Theme filterEditor -| Property Name | Description | Default Value | -|------------------------------|----------------------------------------------------------------|-------------------------------| -| `appBarBackgroundColor` | Background color of the app bar in the filter editor. | `imageEditorAppBarColor` | -| `appBarForegroundColor` | Foreground color (text and icons) of the app bar. | `Color(0xFFE1E1E1)` | -| `background` | Background color of the filter editor. | `imageEditorBackgroundColor` | -| `previewTextColor` | Color of the preview text. | `Color(0xFFE1E1E1)` | - - - -#### Theme blurEditor -| Property | Description | Default Value | -| ------------------------------- | -----------------------------------------------------| ---------------------------------------------------| -| `appBarBackgroundColor` | Background color of the app bar in the blur editor. | `imageEditorAppBarColor` (Default theme value) | -| `appBarForegroundColor` | Foreground color (text and icons) of the app bar. | `Color(0xFFE1E1E1)` | -| `background` | Background color of the blur editor. | `imageEditorBackgroundColor` (Default theme value) | - - -#### Theme emojiEditor -| Property Name | Description | Default Value | -|----------------------------------------|------------------------------------------------------------------------------------------------------|------------------------------| -| `skinToneConfig` | Configuration for the skin tone, configuring the appearance and behavior of skin tones for emojis. | `SkinToneConfig(...)` | -| `bottomActionBarConfig` | Configuration for the bottom action bar, configuring its appearance and behavior. | `BottomActionBarConfig(...)` | -| `searchViewConfig` | Configuration for the search view, configuring its appearance and behavior. | `null` | -| `categoryViewConfig` | Configuration for the category view, configuring its appearance and behavior. | `null` | -| `emojiViewConfig` | Configuration for the emoji view, configuring its appearance and behavior. | `null` | -| `textStyle` | Custom emoji text style to apply to emoji characters in the grid. | `DefaultEmojiTextStyle` | -| `swapCategoryAndBottomBar` | Determines whether to swap the positions of the category view and the bottom action bar. | `true` | - - -#### Theme stickerEditor -| Property | Description | Default Value | -| ------------------------- | ----------------------------------------------------- | ------------------------------- | - - -#### Theme helperLine -| Property | Description | Default Value | -| -------------------- | ------------------------------------| ---------------- | -| `horizontalColor` | Color of horizontal helper lines. | `Color(0xFF1565C0)` (Blue) | -| `verticalColor` | Color of vertical helper lines. | `Color(0xFF1565C0)` (Blue) | -| `rotateColor` | Color of rotation helper lines. | `Color(0xFFE91E63)` (Pink) | -
- -
- icons - -| Property Name | Description | Default Value | -|-------------------------|-----------------------------------------------------------|----------------------------------| -| `closeEditor` | The icon for closing the editor without saving. | `Icons.clear` | -| `doneIcon` | The icon for applying changes and closing the editor. | `Icons.done` | -| `backButton` | The icon for the back button. | `Icons.arrow_back` | -| `applyChanges` | The icon for applying changes in the editor. | `Icons.done` | -| `undoAction` | The icon for undoing the last action. | `Icons.undo` | -| `redoAction` | The icon for redoing the last undone action. | `Icons.redo` | -| `removeElementZone` | The icon for removing an element/layer like an emoji. | `Icons.delete_outline_rounded` | -| `paintingEditor` | Icons for the Painting Editor component. | `IconsPaintingEditor(...)` | -| `textEditor` | Icons for the Text Editor component. | `IconsTextEditor(...)` | -| `cropRotateEditor` | Icons for the Crop and Rotate Editor component. | `IconsCropRotateEditor(...)` | -| `filterEditor` | Icons for the Filter Editor component. | `IconsFilterEditor(...)` | -| `blurEditor` | Icons for the Blur Editor component. | `IconsBlurEditor(...)` | -| `emojiEditor` | Icons for the Emoji Editor component. | `IconsEmojiEditor(...)` | -| `stickerEditor` | Icons for the Sticker Editor component. | `IconsStickerEditor(...)` | -| `layerInteraction` | Icons for the layer interaction settings. | `IconsLayerInteraction(...)` | - -#### icons paintingEditor -| Property Name | Description | Default Value | -|------------------------------|---------------------------------------------------------------------------|----------------------------------| -| `bottomNavBar` | The icon for the bottom navigation bar. | `Icons.edit_outlined` | -| `lineWeight` | The icon for adjusting line weight. | `Icons.line_weight_rounded` | -| `fill` | The icon representing a filled background. | `Icons.format_color_fill` | -| `noFill` | The icon representing an unfilled (transparent) background. | `Icons.format_color_reset` | -| `freeStyle` | The icon for the freehand drawing tool. | `Icons.edit` | -| `arrow` | The icon for the arrow drawing tool. | `Icons.arrow_right_alt_outlined` | -| `line` | The icon for the straight line drawing tool. | `Icons.horizontal_rule` | -| `rectangle` | The icon for the rectangle drawing tool. | `Icons.crop_free` | -| `circle` | The icon for the circle drawing tool. | `Icons.lens_outlined` | -| `dashLine` | The icon for the dashed line drawing tool. | `Icons.power_input` | - - -#### icons textEditor -| Property Name | Description | Default Value | -|-----------------------|--------------------------------------------------------|----------------------------------------| -| `bottomNavBar` | The icon for the bottom navigation bar. | `Icons.title_rounded` | -| `alignLeft` | The icon for aligning text to the left. | `Icons.align_horizontal_left_rounded` | -| `alignCenter` | The icon for aligning text to the center. | `Icons.align_horizontal_center_rounded`| -| `alignRight` | The icon for aligning text to the right. | `Icons.align_horizontal_right_rounded` | -| `fontScale` | The icon for changing font scale. | `Icons.format_size_rounded` | -| `resetFontScale` | The icon for resetting font scale to preset value. | `Icons.refresh_rounded` | -| `backgroundMode` | The icon for toggling background mode. | `Icons.layers_rounded` | - - -#### icons cropRotateEditor -| Property Name | Description | Default Value | -|-----------------------|--------------------------------------------------------|----------------------------------------| -| `bottomNavBar` | The icon to be displayed in the bottom navigation bar. | `Icons.crop_rotate_rounded` | -| `rotate` | The icon for the rotate action. | `Icons.rotate_90_degrees_ccw_outlined` | -| `aspectRatio` | The icon for the aspect ratio action. | `Icons.crop` | -| `flip` | The icon for the flip action. | `Icons.flip` | -| `reset` | The icon for the reset action. | `Icons.restore` | - - -#### icons filterEditor -| Property | Description | Default Value | -| --------------- | ------------------------------ | -------------- | -| `bottomNavBar` | Icon for bottom navigation bar | `Icons.filter` | - -#### icons blurEditor -| Property | Description | Default Value | -| --------------- | ------------------------------ | --------------- | -| `bottomNavBar` | Icon for bottom navigation bar | `Icons.blur_on` | - -#### icons emojiEditor -| Property | Description | Default Value | -| --------------- | ------------------------------------ | ----------------------------------------| -| `bottomNavBar` | Icon for bottom navigation bar | `Icons.sentiment_satisfied_alt_rounded` | - - -#### icons stickerEditor -| Property | Description | Default Value | -| --------------- | ------------------------------------ | ----------------------------------- | -| `bottomNavBar` | Icon for bottom navigation bar | `Icons.layers_outlined` | - -
- -
- paintEditorConfigs - -| Property Name | Description | Default Value | -|--------------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------------------------------------| -| `enabled` | Indicates whether the paint editor is enabled. | `true` | -| `hasOptionFreeStyle` | Indicating whether the free-style drawing option is available. | `true` | -| `hasOptionArrow` | Indicating whether the arrow drawing option is available. | `true` | -| `hasOptionLine` | Indicating whether the line drawing option is available. | `true` | -| `hasOptionRect` | Indicating whether the rectangle drawing option is available. | `true` | -| `hasOptionCircle` | Indicating whether the circle drawing option is available. | `true` | -| `hasOptionDashLine` | Indicating whether the dash line drawing option is available. | `true` | -| `showColorPicker` | Indicating whether the color picker is visible. | `true` | -| `canToggleFill` | Indicating whether the fill option can be toggled. | `true` | -| `canChangeLineWidth` | Indicating whether the line width can be changed. | `true` | -| `initialFill` | Indicates the initial fill state. | `false` | -| `freeStyleHighPerformanceScaling` | Enables high-performance scaling for free-style drawing. | `true` on mobile, `false` on desktop | -| `freeStyleHighPerformanceMoving` | Enables high-performance moving for free-style drawing. | `true` on mobile-web | -| `freeStyleHighPerformanceHero` | Enables high-performance hero-animations for free-style drawing. | `false` | -| `initialPaintMode` | Indicates the initial paint mode. | `PaintModeE.freeStyle` | -| `strokeWidthOnChanged` | A callback function that will be called when the stroke width changes. | `null` | -
- -
- textEditorConfigs - -| Property Name | Description | Default Value | -|----------------------------------------|--------------------------------------------------------------------------------------------------------|-------------------------------------------------| -| `enabled` | Indicates whether the text editor is enabled. | `true` | -| `canToggleTextAlign` | Determines if the text alignment options can be toggled. | `true` | -| `canChangeFontScale` | Determines if the font scale can be changed. | `true` | -| `canToggleBackgroundMode` | Determines if the background mode can be toggled. | `true` | -| `initFontSize` | The initial font size for text. | `24.0` | -| `initialTextAlign` | The initial text alignment for the layer. | `TextAlign.center` | -| `initFontScale` | The initial font scale for text. | `1.0` | -| `maxFontScale` | The max font scale for text. | `3.0` | -| `minFontScale` | The min font scale for text. | `0.3` | -| `initialBackgroundColorMode` | The initial background color mode for the layer. | `LayerBackgroundColorModeE.backgroundAndColor` | -| `customTextStyles` | Allow users to select a different font style. | `null` | -
- -
- cropRotateEditorConfigs - -| Property Name | Description | Default Value | -|-------------------------------------------------|------------------------------------------------------------------------------------------------------------------|-----------------------------------------| -| `enabled` | Indicates whether the editor is enabled. | `true` | -| `canRotate` | Indicating whether the image can be rotated. | `true` | -| `canFlip` | Indicating whether the image can be flipped. | `true` | -| `canChangeAspectRatio` | Indicating whether the aspect ratio of the image can be changed. | `true` | -| `canReset` | Indicating whether the editor can be reset. | `true` | -| `transformLayers` | Layers will also be transformed like the crop-rotate image. | `true` | -| `enableDoubleTap` | Enables double-tap zoom functionality when set to true. | `true` | -| `reverseMouseScroll` | Determines if the mouse scroll direction should be reversed. | `false` | -| `reverseDragDirection` | Determines if the drag direction should be reversed. | `false` | -| `roundCropper` | The cropper is round and not rectangular, optimal for cutting profile images. | `false` | -| `initAspectRatio` | The initial aspect ratio for cropping. | `null` (use `CropAspectRatios.custom`) | -| `maxScale` | The maximum scale allowed for the view. | `7` | -| `mouseScaleFactor` | The scaling factor applied to mouse scrolling. | `0.1` | -| `doubleTapScaleFactor` | The scaling factor applied when double-tapping. | `2` | -| `aspectRatios` | The allowed aspect ratios for cropping. | See below (list of aspect ratios) | -| `animationDuration` | The duration for the animation controller that handles rotation and scale animations. | `Duration(milliseconds: 250)` | -| `cropDragAnimationDuration` | The duration of drag-crop animations. | `Duration(milliseconds: 400)` | -| `fadeInOutsideCropAreaAnimationDuration` | Fade in animation from content outside the crop area. | `Duration(milliseconds: 350)` | -| `rotateAnimationCurve` | The curve used for the rotation animation. | `Curves.decelerate` | -| `scaleAnimationCurve` | The curve used for the scale animation, triggered when the image needs to resize due to rotation. | `Curves.decelerate` | -| `cropDragAnimationCurve` | The animation curve used for crop animations. | `Curves.decelerate` | -| `fadeInOutsideCropAreaAnimationCurve` | The animation curve used for the fade in animation from content outside the crop area. | `Curves.decelerate` | -| `rotateDirection` | The direction in which the image will be rotated. | `RotateDirection.left` | -| `desktopCornerDragArea` | Defines the size of the draggable area on corners of the crop rectangle for desktop devices. | `7` | -| `mobileCornerDragArea` | Defines the size of the draggable area on corners of the crop rectangle for mobile devices. | `kMinInteractiveDimension` | - -
- -
- filterEditorConfigs - -| Property Name | Description | Default Value | -|----------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------| -| `enabled` | Indicates whether the filter editor is enabled. | `true` | -| `showLayers` | Show also layers in the editor. | `true` | -| `filterList` | A list of color filter generators to apply to an image. | `null` (default contains all filters) | -
- -
- blurEditorConfigs - -| Property Name | Description | Default Value | -|------------------------|---------------------------------------------------------------------|---------------| -| `enabled` | Indicates whether the blur editor is enabled. | `true` | -| `showLayers` | Show also layers in the editor. | `true` | -| `maxBlur` | Maximum blur value. | `2.0` | -
- -
- emojiEditorConfigs - -| Property Name | Description | Default Value | -|---------------------------------|----------------------------------------------------------------------------------------------------------|----------------------------| -| `enabled` | Indicates whether the emoji editor is enabled. | `true` | -| `initScale` | The initial scale for displaying emojis. | `5.0` | -| `checkPlatformCompatibility` | Verify that emoji glyph is supported by the platform (Android only). | `true` | -| `emojiSet` | Custom emojis; if set, overrides default emojis provided by the library. | `defaultEmojiSet` | -
- -
- stickerEditorConfigs - -| Property Name | Description | Default Value | -|------------------------|----------------------------------------------------------------------------------------------------------|----------------------------| -| `enabled` | Indicates whether the sticker editor is enabled. | `false` | -| `initWidth` | The initial width of the stickers in the editor. | `100` | -| `buildStickers` | A callback that builds the stickers. | `required` | -
- -
- imageGenerationConfigs - -| Property Name | Description | Default Value | -|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------| -| `allowEmptyEditCompletion` | Whether the callback `onImageEditingComplete` is called with empty editing. | `false` | -| `generateIsolated` | Allows image generation to run in an isolated thread, preventing any impact on the UI. On web platforms, it runs in a separate web worker. Disabling this will also disable `captureImagesInBackground`. | `true` | -| `generateImageInBackground` | Captures the final image after each change, significantly speeding up the editor. On Dart native platforms, it runs on an isolate thread; on Dart web, it runs on a web worker. | `true` | -| `generateOnlyImageBounds` | Determines whether to capture only the content within the boundaries of the image when editing is complete. If set to `true`, it crops all content outside the image boundaries, returning only the content overlaid on the image. | `true` | -| `processorConfigs` | Configuration configs for background processors. | ProcessorConfigs() | - - - -
- -
- stateHistoryConfigs - -| Property Name | Description | Default Value | -|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------------| -| `stateHistoryLimit` | The maximum number of states that can be stored in the history. Setting a very high value can potentially overload the system's RAM. | `1000` | -| `initStateHistory` | Holds the initial state history of the Image Editor. | `null` | -
- - -
### Contributing diff --git a/example/lib/common/example_constants.dart b/example/lib/common/example_constants.dart new file mode 100644 index 00000000..d7718845 --- /dev/null +++ b/example/lib/common/example_constants.dart @@ -0,0 +1,9 @@ +/// A path to a demo image asset in the project. +final String kImageEditorExampleAssetPath = 'assets/demo.png'; + +/// A URL to a demo image hosted on a remote server. +final String kImageEditorExampleNetworkUrl = + 'https://picsum.photos/id/230/2000'; + +/// Breakpoint for desktop layout in the image editor example. +final kImageEditorExampleIsDesktopBreakPoint = 900; diff --git a/example/lib/common/examples.dart b/example/lib/common/examples.dart new file mode 100644 index 00000000..faaf584b --- /dev/null +++ b/example/lib/common/examples.dart @@ -0,0 +1,150 @@ +import 'package:example/pages/stickers_example.dart'; +import 'package:flutter/material.dart'; + +import '../models/example_model.dart'; +import '../pages/crop_to_main_editor.dart'; +import '../pages/custom_widgets_example.dart'; +import '../pages/default_example.dart'; +import '../pages/design_examples/design_example.dart'; +import '../pages/firebase_supabase_example.dart'; +import '../pages/frame_example.dart'; +import '../pages/generation_configs_example.dart'; +import '../pages/google_font_example.dart'; +import '../pages/image_format_convert_example.dart'; +import '../pages/import_export_example.dart'; +import '../pages/movable_background_image.dart'; +import '../pages/pick_image_example.dart'; +import '../pages/reorder_layer_example.dart'; +import '../pages/round_cropper_example.dart'; +import '../pages/selectable_layer_example.dart'; +import '../pages/signature_drawing_example.dart'; +import '../pages/standalone_example.dart'; +import '../pages/zoom_example.dart'; + +/// A predefined list of examples for the image editor application. +/// +/// Each [Example] in this list contains: +/// - [path]: A unique navigation route for the example. +/// - [name]: A user-friendly name for the example. +/// - [icon]: An [IconData] representing the example visually. +/// - [page]: A [Widget] representing the content of the example. +/// +/// These examples showcase various features of the image editor, such as +/// cropping, layering, importing/exporting, and integration with services +/// like Firebase or Supabase. +List kImageEditorExamples = const [ + Example( + path: '/default', + name: 'Default-Editor', + icon: Icons.dashboard_outlined, + page: DefaultExample(), + ), + Example( + path: '/designs', + name: 'Designs', + icon: Icons.palette_outlined, + page: DesignExample(), + ), + Example( + path: '/standalone', + name: 'Standalone-Editors', + icon: Icons.view_in_ar_outlined, + page: StandaloneExample(), + ), + Example( + path: '/init-crop-editor', + name: 'Start with Crop-Editor', + icon: Icons.crop, + page: CropToMainEditorExample(), + ), + Example( + path: '/signature-drawing', + name: 'Signature/ Drawing', + icon: Icons.draw_outlined, + page: SignatureDrawingExample(), + ), + Example( + path: '/stickers', + name: 'Stickers', + icon: Icons.image_outlined, + page: StickersExample(), + ), + Example( + path: '/firebase-supabase', + name: 'Firebase-Supabase', + icon: Icons.cloud_upload_outlined, + page: FirebaseSupabaseExample(), + ), + Example( + path: '/reorder', + name: 'Reorder-Layers', + icon: Icons.sort, + page: ReorderLayerExample(), + ), + Example( + path: '/round-cropper', + name: 'Round-Cropper', + icon: Icons.supervised_user_circle_outlined, + page: RoundCropperExample(), + ), + Example( + path: '/selectable-layers', + name: 'Selectable-Layers', + icon: Icons.select_all_rounded, + page: SelectableLayerExample(), + ), + Example( + path: '/generation-configs', + name: 'Generation-Configurations', + icon: Icons.memory_outlined, + page: GenerationConfigsExample(), + ), + Example( + path: '/camera-gallery-picker', + name: 'Camera-Gallery-Picker', + icon: Icons.attachment_rounded, + page: PickImageExample(), + ), + Example( + path: '/google-font', + name: 'Google-Font', + icon: Icons.emoji_emotions_outlined, + page: GoogleFontExample(), + ), + Example( + path: '/custom-widgets', + name: 'Custom-Widgets', + icon: Icons.dashboard_customize_outlined, + page: CustomWidgetsExample(), + ), + Example( + path: '/import-export', + name: 'Import-Export', + icon: Icons.import_export_rounded, + page: ImportExportExample(), + ), + Example( + path: '/movable', + name: 'Movable-Background', + icon: Icons.pan_tool_alt_outlined, + page: MovableBackgroundImageExample(), + ), + Example( + path: '/frame', + name: 'Frame', + icon: Icons.filter_frames_outlined, + page: FrameExample(), + ), + Example( + path: '/zoom', + name: 'Zoom', + icon: Icons.zoom_in_outlined, + page: ZoomExample(), + ), + Example( + path: '/output-format', + name: 'Output-Format', + icon: Icons.compare_outlined, + page: ImageFormatConvertExample(), + ), +]; diff --git a/example/lib/main.dart b/example/lib/main.dart index 8ee9e0f4..96a0e5d9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,33 +1,14 @@ -// Flutter imports: -import 'package:example/pages/crop_to_main_editor.dart'; -import 'package:example/pages/design_examples/design_example.dart'; -import 'package:example/pages/frame_example.dart'; -import 'package:example/pages/zoom_move_editor_example.dart'; +import 'package:example/widgets/not_found_example.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; + import 'package:pro_image_editor/pro_image_editor.dart'; -// Package imports: import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; -import '/pages/firebase_supabase_example.dart'; -import '/pages/import_export_example.dart'; -import '/pages/pick_image_example.dart'; -import '/pages/selectable_layer_example.dart'; -// Project imports: -import '/utils/example_constants.dart'; -import 'pages/custom_appbar_bottombar_example.dart'; -import 'pages/default_example.dart'; -import 'pages/generation_configs_example.dart'; -import 'pages/google_font_example.dart'; -import 'pages/image_format_convert_example.dart'; -import 'pages/movable_background_image.dart'; -import 'pages/reorder_layer_example.dart'; -import 'pages/round_cropper_example.dart'; -import 'pages/signature_drawing_example.dart'; -import 'pages/standalone_example.dart'; -import 'pages/stickers_example.dart'; +import 'common/example_constants.dart'; +import 'common/examples.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -52,10 +33,27 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Pro-Image-Editor', theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade800), + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.blue.shade800, + brightness: Brightness.dark, + ), useMaterial3: true, ), debugShowCheckedModeBanner: false, + onGenerateRoute: (settings) { + int index = kImageEditorExamples + .indexWhere((example) => example.path == settings.name); + + if (index < 0) { + return MaterialPageRoute( + builder: (_) => const NotFoundExample(), + ); + } + + return MaterialPageRoute( + builder: (_) => kImageEditorExamples[index].page, + ); + }, home: const MyHomePage(), ); } @@ -71,29 +69,11 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { + final _navigatorKey = GlobalKey(); late final ScrollController _scrollCtrl; - final List _examples = [ - const DefaultExample(), - const DesignExample(), - const StandaloneExample(), - const CropToMainEditorExample(), - const SignatureDrawingExample(), - const StickersExample(), - const FirebaseSupabaseExample(), - const ReorderLayerExample(), - const RoundCropperExample(), - const SelectableLayerExample(), - const GenerationConfigsExample(), - const PickImageExample(), - const GoogleFontExample(), - const CustomAppbarBottombarExample(), - const ImportExportExample(), - const MovableBackgroundImageExample(), - const FrameExample(), - const ZoomMoveEditorExample(), - const ImageFormatConvertExample(), - ]; + final String _initialRoute = kImageEditorExamples.first.path; + int _railIndex = 0; @override void initState() { @@ -107,40 +87,142 @@ class _MyHomePageState extends State { super.dispose(); } + void _openCodeInGithub() async { + String path = + 'https://github.com/hm21/pro_image_editor/tree/stable/example/lib/pages'; + Uri url = Uri.parse(path); + if (!await launchUrl(url)) { + throw Exception('Could not launch $url'); + } + } + @override Widget build(BuildContext context) { - return ExampleConstants( - child: AnnotatedRegion( - value: SystemUiOverlayStyle.dark, - child: ExtendedPopScope( - child: Scaffold( - body: SafeArea(child: _buildCard()), - ), + return AnnotatedRegion( + value: SystemUiOverlayStyle.dark, + child: ExtendedPopScope( + child: Scaffold( + body: Builder(builder: (_) { + if (MediaQuery.of(context).size.width >= + kImageEditorExampleIsDesktopBreakPoint) { + /// Build navigation-rail on large screens + return _buildTabletExamples(); + } else { + return _buildMobileExamples(); + } + }), ), ), ); } - Widget _buildCard() { - return Center( - child: LayoutBuilder(builder: (context, constraints) { - if (constraints.maxWidth >= 750) { - return Container( - constraints: const BoxConstraints(maxWidth: 700), - child: Card.outlined( - margin: const EdgeInsets.all(16), - clipBehavior: Clip.hardEdge, - child: _buildExamples(), + Widget _buildTabletExamples() { + return Row( + children: [ + _buildRailBar(), + const VerticalDivider(width: 1), + Expanded( + // Important that hero animations work correctly + child: HeroControllerScope( + controller: MaterialApp.createMaterialHeroController(), + child: Navigator( + key: _navigatorKey, + initialRoute: _initialRoute, + onGenerateRoute: (settings) { + int index = kImageEditorExamples + .indexWhere((example) => example.path == settings.name); + + if (index < 0) { + return MaterialPageRoute( + builder: (_) => const NotFoundExample(), + ); + } + + return PageRouteBuilder( + pageBuilder: (_, __, ___) => kImageEditorExamples[index].page, + transitionsBuilder: + (_, animation, secondaryAnimation, child) { + const begin = + Offset(0.0, 0.1); // Start offscreen to the right + const end = Offset.zero; // End at the center + const curve = Curves.easeInOut; + + var tween = Tween(begin: begin, end: end) + .chain(CurveTween(curve: curve)); + var offsetAnimation = animation.drive(tween); + return SlideTransition( + position: offsetAnimation, + transformHitTests: false, + child: FadeTransition( + opacity: animation, + child: child, + ), + ); + }, + ); + }, ), - ); - } else { - return _buildExamples(); - } - }), + ), + ), + ], ); } - Widget _buildExamples() { + Widget _buildRailBar() { + return LayoutBuilder(builder: (_, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: NavigationRail( + leading: Column( + spacing: 7, + children: [ + TextButton( + onPressed: _openCodeInGithub, + child: const Text('View code in Github'), + ), + Container( + height: 0.4, + width: 250, + color: Colors.white54, + ), + ], + ), + onDestinationSelected: (index) { + if (_railIndex == index) return; + + _navigatorKey.currentState!.pushNamedAndRemoveUntil( + kImageEditorExamples[index].path, + ModalRoute.withName(_initialRoute), + ); + _railIndex = index; + setState(() {}); + }, + extended: true, + destinations: kImageEditorExamples.map((example) { + return NavigationRailDestination( + icon: Icon( + example.icon, + color: const Color(0xFFF5F5F5), + ), + label: Text( + example.name, + style: const TextStyle( + color: Color(0xFFF5F5F5), + ), + ), + ); + }).toList(), + selectedIndex: _railIndex, + ), + ), + ), + ); + }); + } + + Widget _buildMobileExamples() { return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -157,26 +239,20 @@ class _MyHomePageState extends State { ), ), RichText( - text: TextSpan( - style: const TextStyle(color: Colors.black87), - children: [ - const TextSpan(text: 'Check out the example code '), - TextSpan( - recognizer: TapGestureRecognizer() - ..onTap = () async { - String path = - 'https://github.com/hm21/pro_image_editor/tree/stable/example/lib/pages'; - Uri url = Uri.parse(path); - if (!await launchUrl(url)) { - throw Exception('Could not launch $url'); - } - }, - text: 'here', - style: const TextStyle(color: Colors.blue), - ), - const TextSpan(text: '.'), - ], - )), + text: TextSpan( + style: const TextStyle(color: Colors.white), + children: [ + const TextSpan(text: 'Check out the example code '), + TextSpan( + recognizer: TapGestureRecognizer() + ..onTap = _openCodeInGithub, + text: 'here', + style: const TextStyle(color: Colors.blue), + ), + const TextSpan(text: '.'), + ], + ), + ), ], ), ), @@ -193,7 +269,18 @@ class _MyHomePageState extends State { mainAxisSize: MainAxisSize.min, children: ListTile.divideTiles( context: context, - tiles: _examples, + tiles: kImageEditorExamples.map( + (example) => ListTile( + onTap: () { + Navigator.of(context).pushNamed( + example.path, + ); + }, + leading: Icon(example.icon), + title: Text(example.name), + trailing: const Icon(Icons.chevron_right_rounded), + ), + ), ).toList(), ), ), diff --git a/example/lib/models/example_model.dart b/example/lib/models/example_model.dart new file mode 100644 index 00000000..b882f6bd --- /dev/null +++ b/example/lib/models/example_model.dart @@ -0,0 +1,33 @@ +import 'package:flutter/widgets.dart'; + +/// Represents an example item with a name, path, icon, and associated page. +/// +/// This class is typically used to define examples in an application, where +/// each example has: +/// - A [path]: The navigation route or identifier for the example. +/// - A [name]: A user-friendly name for the example. +/// - An [icon]: An icon representing the example. +/// - A [page]: The widget representing the content of the example. +class Example { + /// Creates an instance of [Example]. + /// + /// All fields are required. + const Example({ + required this.path, + required this.name, + required this.icon, + required this.page, + }); + + /// The navigation route or identifier for the example. + final String path; + + /// The user-friendly name of the example. + final String name; + + /// The icon representing the example. + final IconData icon; + + /// The widget representing the content of the example. + final Widget page; +} diff --git a/example/lib/pages/crop_to_main_editor.dart b/example/lib/pages/crop_to_main_editor.dart index daf641cd..f64b4b03 100644 --- a/example/lib/pages/crop_to_main_editor.dart +++ b/example/lib/pages/crop_to_main_editor.dart @@ -1,13 +1,12 @@ // Flutter imports: -import 'package:example/utils/example_constants.dart'; import 'package:flutter/material.dart'; // Package imports: import 'package:pro_image_editor/models/crop_rotate_editor/transform_factors.dart'; -import 'package:pro_image_editor/models/editor_configs/main_editor_configs.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: +import '../common/example_constants.dart'; import '../utils/example_helper.dart'; /// A widget that demonstrates cropping functionality in the main editor. @@ -41,34 +40,28 @@ class _CropToMainEditorExampleState extends State with ExampleHelperState { final ProImageEditorConfigs _editorConfigs = ProImageEditorConfigs( designMode: platformDesignMode, - cropRotateEditorConfigs: const CropRotateEditorConfigs( + cropRotateEditor: const CropRotateEditorConfigs( initAspectRatio: 1, provideImageInfos: true, canChangeAspectRatio: false, ), ); - void _openCropEditor() { - Navigator.push( - context, - PageRouteBuilder( - pageBuilder: (_, animation, secondaryAnimation) => - CropRotateEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, - initConfigs: CropRotateEditorInitConfigs( - theme: ThemeData.dark(), - configs: _editorConfigs, - onDone: (transformations, fitToScreenFactor, imageInfos) { - /// Skip one frame before opening the main editor, as the crop - /// editor will call Navigator.pop(context). - WidgetsBinding.instance.addPostFrameCallback((_) { - _openMainEditor(transformations, imageInfos!); - }); - }, - ), - ), - ), + final _cropEditorKey = GlobalKey(); + + @override + void initState() { + preCacheImage( + assetPath: kImageEditorExampleAssetPath, + onDone: () { + Future.delayed(const Duration(milliseconds: 100), () { + if (mounted) { + _cropEditorKey.currentState!.enableFakeHero = true; + } + }); + }, ); + super.initState(); } void _openMainEditor( @@ -79,21 +72,22 @@ class _CropToMainEditorExampleState extends State context, PageRouteBuilder( pageBuilder: (_, animation, secondaryAnimation) => ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: editorKey, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, - onCloseEditor: onCloseEditor, + onCloseEditor: () => + onCloseEditor(enablePop: !isDesktopMode(context)), onImageEditingComplete: onImageEditingComplete, ), configs: _editorConfigs.copyWith( - mainEditorConfigs: MainEditorConfigs( + mainEditor: MainEditorConfigs( transformSetup: MainEditorTransformSetup( transformConfigs: transformations, imageInfos: imageInfos, ), ), - cropRotateEditorConfigs: const CropRotateEditorConfigs( + cropRotateEditor: const CropRotateEditorConfigs( enabled: false, ), ), @@ -109,21 +103,27 @@ class _CropToMainEditorExampleState extends State return child; }, ), - ); + ).whenComplete(() { + if (mounted) Navigator.pop(context); + }); } @override Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - _openCropEditor(); - }, - leading: const Icon(Icons.crop), - title: const Text('Start with Crop-Editor'), - trailing: const Icon(Icons.chevron_right), + if (!isPreCached) return const PrepareImageWidget(); + + return CropRotateEditor.asset( + kImageEditorExampleAssetPath, + key: _cropEditorKey, + initConfigs: CropRotateEditorInitConfigs( + theme: Theme.of(context), + configs: _editorConfigs, + enablePopWhenDone: false, + enableCloseButton: !isDesktopMode(context), + onDone: (transformations, fitToScreenFactor, imageInfos) { + _openMainEditor(transformations, imageInfos!); + }, + ), ); } } diff --git a/example/lib/pages/custom_appbar_bottombar_example.dart b/example/lib/pages/custom_widgets_example.dart similarity index 89% rename from example/lib/pages/custom_appbar_bottombar_example.dart rename to example/lib/pages/custom_widgets_example.dart index 0c4a36f9..f853b354 100644 --- a/example/lib/pages/custom_appbar_bottombar_example.dart +++ b/example/lib/pages/custom_widgets_example.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; // Package imports: import 'package:google_fonts/google_fonts.dart'; -import 'package:pro_image_editor/models/custom_widgets/custom_widgets_layer_interaction.dart'; +import 'package:pro_image_editor/models/custom_widgets/layer_interaction_widgets.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: @@ -16,37 +16,35 @@ import '../utils/example_helper.dart'; /// A widget that demonstrates a custom app bar and bottom bar layout. /// -/// The [CustomAppbarBottombarExample] widget is a stateful widget that provides +/// The [CustomWidgetsExample] widget is a stateful widget that provides /// an example of how to implement a custom app bar at the top and a custom /// bottom bar at the bottom of the screen. This is useful in applications /// where a unique layout or custom controls are needed in both the app bar /// and the bottom bar. /// /// The state for this widget is managed by the -/// [_CustomAppbarBottombarExampleState] class. +/// [_CustomWidgetsExampleState] class. /// /// Example usage: /// ```dart /// CustomAppbarBottombarExample(); /// ``` -class CustomAppbarBottombarExample extends StatefulWidget { - /// Creates a new [CustomAppbarBottombarExample] widget. - const CustomAppbarBottombarExample({super.key}); +class CustomWidgetsExample extends StatefulWidget { + /// Creates a new [CustomWidgetsExample] widget. + const CustomWidgetsExample({super.key}); @override - State createState() => - _CustomAppbarBottombarExampleState(); + State createState() => _CustomWidgetsExampleState(); } -/// The state for the [CustomAppbarBottombarExample] widget. +/// The state for the [CustomWidgetsExample] widget. /// /// This class manages the layout and behavior of the custom app bar and -/// bottom bar within the [CustomAppbarBottombarExample] widget. -class _CustomAppbarBottombarExampleState - extends State - with ExampleHelperState { +/// bottom bar within the [CustomWidgetsExample] widget. +class _CustomWidgetsExampleState extends State + with ExampleHelperState { late ScrollController _bottomBarScrollCtrl; - late ScrollController _paintingBottomBarScrollCtrl; + late ScrollController _paintBottomBarScrollCtrl; late ScrollController _cropBottomBarScrollCtrl; final List _customTextStyles = [ @@ -99,8 +97,9 @@ class _CustomAppbarBottombarExampleState @override void initState() { + preCacheImage(networkUrl: _url); _bottomBarScrollCtrl = ScrollController(); - _paintingBottomBarScrollCtrl = ScrollController(); + _paintBottomBarScrollCtrl = ScrollController(); _cropBottomBarScrollCtrl = ScrollController(); super.initState(); } @@ -108,37 +107,15 @@ class _CustomAppbarBottombarExampleState @override void dispose() { _bottomBarScrollCtrl.dispose(); - _paintingBottomBarScrollCtrl.dispose(); + _paintBottomBarScrollCtrl.dispose(); _cropBottomBarScrollCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - return ListTile( - onTap: () async { - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); + if (!isPreCached) return const PrepareImageWidget(); - await precacheImage(NetworkImage(_url), context); - - LoadingDialog.instance.hide(); - - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute(builder: (context) => _buildEditor()), - ); - }, - leading: const Icon(Icons.dashboard_customize_outlined), - title: const Text('Custom AppBar and BottomBar'), - trailing: const Icon(Icons.chevron_right), - ); - } - - Widget _buildEditor() { return LayoutBuilder(builder: (context, constraints) { return ProImageEditor.network( _url, @@ -146,12 +123,14 @@ class _CustomAppbarBottombarExampleState callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => + onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - customWidgets: ImageEditorCustomWidgets( - mainEditor: CustomWidgetsMainEditor( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + widgets: MainEditorWidgets( appBar: (editor, rebuildStream) => ReactiveCustomAppbar( stream: rebuildStream, builder: (_) => _buildAppBar(editor)), bottomBar: (editor, rebuildStream, key) => ReactiveCustomWidget( @@ -159,34 +138,40 @@ class _CustomAppbarBottombarExampleState builder: (_) => _bottomNavigationBar(editor, key, constraints)), ), - paintEditor: CustomWidgetsPaintEditor( + ), + paintEditor: PaintEditorConfigs( + widgets: PaintEditorWidgets( appBar: (paintEditor, rebuildStream) => ReactiveCustomAppbar( stream: rebuildStream, - builder: (_) => _appBarPaintingEditor(paintEditor), + builder: (_) => _appBarPaintEditor(paintEditor), ), bottomBar: (paintEditor, rebuildStream) => ReactiveCustomWidget( stream: rebuildStream, - builder: (_) => - _bottomBarPaintingEditor(paintEditor, constraints), + builder: (_) => _bottomBarPaintEditor(paintEditor, constraints), ), ), - textEditor: CustomWidgetsTextEditor( - appBar: (textEditor, rebuildStream) => ReactiveCustomAppbar( - stream: rebuildStream, - builder: (_) => _appBarTextEditor(textEditor), - ), - bottomBar: (textEditor, rebuildStream) => null, - bodyItems: (textEditor, rebuildStream) { - return [ - ReactiveCustomWidget( - stream: rebuildStream, - builder: (_) => - _bottomBarTextEditor(textEditor, constraints), - ), - ]; - }, - ), - cropRotateEditor: CustomWidgetsCropRotateEditor( + ), + textEditor: TextEditorConfigs( + showSelectFontStyleBottomBar: true, + customTextStyles: _customTextStyles, + widgets: TextEditorWidgets( + appBar: (textEditor, rebuildStream) => ReactiveCustomAppbar( + stream: rebuildStream, + builder: (_) => _appBarTextEditor(textEditor), + ), + bottomBar: (textEditor, rebuildStream) => null, + bodyItems: (textEditor, rebuildStream) { + return [ + ReactiveCustomWidget( + stream: rebuildStream, + builder: (_) => + _bottomBarTextEditor(textEditor, constraints), + ), + ]; + }, + )), + cropRotateEditor: CropRotateEditorConfigs( + widgets: CropRotateEditorWidgets( appBar: (cropRotateEditor, rebuildStream) => ReactiveCustomAppbar( stream: rebuildStream, builder: (_) => _appBarCropRotateEditor(cropRotateEditor), @@ -198,19 +183,25 @@ class _CustomAppbarBottombarExampleState _bottomBarCropEditor(cropRotateEditor, constraints), ), ), - filterEditor: CustomWidgetsFilterEditor( + ), + filterEditor: FilterEditorConfigs( + widgets: FilterEditorWidgets( appBar: (filterEditor, rebuildStream) => ReactiveCustomAppbar( stream: rebuildStream, builder: (_) => _appBarFilterEditor(filterEditor), ), ), - blurEditor: CustomWidgetsBlurEditor( + ), + blurEditor: BlurEditorConfigs( + widgets: BlurEditorWidgets( appBar: (blurEditor, rebuildStream) => ReactiveCustomAppbar( stream: rebuildStream, builder: (_) => _appBarBlurEditor(blurEditor), ), ), - layerInteraction: CustomWidgetsLayerInteraction( + ), + layerInteraction: LayerInteractionConfigs( + widgets: LayerInteractionWidgets( editIcon: (rebuildStream, onTap, toggleTooltipVisibility, rotation) => ReactiveCustomWidget( @@ -324,10 +315,6 @@ class _CustomAppbarBottombarExampleState ), ), ), - textEditorConfigs: TextEditorConfigs( - showSelectFontStyleBottomBar: true, - customTextStyles: _customTextStyles, - ), ), ); }); @@ -339,12 +326,13 @@ class _CustomAppbarBottombarExampleState foregroundColor: Colors.white, backgroundColor: Colors.black, actions: [ - IconButton( - tooltip: 'Cancel', - padding: const EdgeInsets.symmetric(horizontal: 8), - icon: const Icon(Icons.close), - onPressed: editor.closeEditor, - ), + if (!isDesktopMode(context)) + IconButton( + tooltip: 'Cancel', + padding: const EdgeInsets.symmetric(horizontal: 8), + icon: const Icon(Icons.close), + onPressed: editor.closeEditor, + ), const Spacer(), IconButton( tooltip: 'My Button', @@ -389,7 +377,7 @@ class _CustomAppbarBottombarExampleState ); } - AppBar _appBarPaintingEditor(PaintingEditorState paintEditor) { + AppBar _appBarPaintEditor(PaintEditorState paintEditor) { return AppBar( automaticallyImplyLeading: false, foregroundColor: Colors.white, @@ -662,7 +650,7 @@ class _CustomAppbarBottombarExampleState size: 22.0, color: Colors.white, ), - onPressed: editor.openPaintingEditor, + onPressed: editor.openPaintEditor, ), FlatIconTextButton( label: Text('Text', style: _bottomTextStyle), @@ -734,10 +722,10 @@ class _CustomAppbarBottombarExampleState ); } - Widget _bottomBarPaintingEditor( - PaintingEditorState paintEditor, BoxConstraints constraints) { + Widget _bottomBarPaintEditor( + PaintEditorState paintEditor, BoxConstraints constraints) { return Scrollbar( - controller: _paintingBottomBarScrollCtrl, + controller: _paintBottomBarScrollCtrl, scrollbarOrientation: ScrollbarOrientation.top, thickness: isDesktop ? null : 0, child: BottomAppBar( @@ -746,7 +734,7 @@ class _CustomAppbarBottombarExampleState padding: EdgeInsets.zero, child: Center( child: SingleChildScrollView( - controller: _paintingBottomBarScrollCtrl, + controller: _paintBottomBarScrollCtrl, scrollDirection: Axis.horizontal, child: ConstrainedBox( constraints: BoxConstraints( @@ -773,7 +761,7 @@ class _CustomAppbarBottombarExampleState builder: (_) { var item = paintModes[index]; var color = paintEditor.paintMode == item.mode - ? imageEditorPrimaryColor + ? kImageEditorPrimaryColor : const Color(0xFFEEEEEE); return FlatIconTextButton( diff --git a/example/lib/pages/default_example.dart b/example/lib/pages/default_example.dart index 546b94e1..2c1d0636 100644 --- a/example/lib/pages/default_example.dart +++ b/example/lib/pages/default_example.dart @@ -2,6 +2,7 @@ import 'dart:io'; // Package imports: +import 'package:example/common/example_constants.dart'; import 'package:file_picker/file_picker.dart'; // Flutter imports: import 'package:flutter/foundation.dart'; @@ -9,7 +10,6 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; import '../utils/example_helper.dart'; /// A widget that provides a default example of a stateful widget. @@ -39,141 +39,116 @@ class _DefaultExampleState extends State with ExampleHelperState { @override Widget build(BuildContext context) { - return ListTile( - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext _) { - return ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 20), - children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text('Mode', - style: - TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), - ), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), - child: Text( - 'The editor support to directly open your type of data ' - 'without converting it first.'), - ), - const Divider(), - ListTile( - leading: const Icon(Icons.memory_outlined), - title: const Text('Editor from memory'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); - - var url = 'https://picsum.photos/5000'; - var bytes = await fetchImageAsUint8List(url); - - if (!context.mounted) return; - await precacheImage(MemoryImage(bytes), context); - - LoadingDialog.instance.hide(); - - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildMemoryEditor(bytes)), - ); - }, - ), - ListTile( - leading: const Icon(Icons.folder_outlined), - title: const Text('Editor from asset'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildAssetEditor()), - ); - }, - ), - ListTile( - leading: const Icon(Icons.public_outlined), - title: const Text('Editor from network'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); - - await precacheImage( - NetworkImage( - ExampleConstants.of(context)!.demoNetworkUrl), - context); - - LoadingDialog.instance.hide(); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildNetworkEditor()), - ); + return Scaffold( + appBar: AppBar( + title: const Text('Default Example'), + ), + body: ListView( + shrinkWrap: true, + padding: const EdgeInsets.symmetric(vertical: 20), + children: [ + const Padding( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: Text('The editor support to directly open your type of data ' + 'without converting it first.'), + ), + const Divider(), + ListTile( + leading: const Icon(Icons.memory_outlined), + title: const Text('Editor from memory'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + LoadingDialog.instance.show( + context, + configs: const ProImageEditorConfigs(), + theme: Theme.of(context), + ); + + var url = 'https://picsum.photos/5000'; + var bytes = await fetchImageAsUint8List(url); + + if (!context.mounted) return; + await precacheImage(MemoryImage(bytes), context); + + LoadingDialog.instance.hide(); + + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _buildMemoryEditor(bytes)), + ); + }, + ), + ListTile( + leading: const Icon(Icons.folder_outlined), + title: const Text('Editor from asset'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildAssetEditor()), + ); + }, + ), + ListTile( + leading: const Icon(Icons.public_outlined), + title: const Text('Editor from network'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + LoadingDialog.instance.show( + context, + configs: const ProImageEditorConfigs(), + theme: Theme.of(context), + ); + + await precacheImage( + NetworkImage(kImageEditorExampleNetworkUrl), context); + + LoadingDialog.instance.hide(); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildNetworkEditor()), + ); + }, + ), + ListTile( + leading: const Icon(Icons.sd_card_outlined), + title: const Text('Editor from file'), + trailing: const Icon(Icons.chevron_right), + subtitle: kIsWeb + ? const Text( + 'The file editor does not work in a web application ' + 'because Flutter does not support files in web ' + 'environments.') + : null, + enabled: !kIsWeb, + onTap: kIsWeb + ? null + : () async { + FilePickerResult? result = await FilePicker.platform + .pickFiles(type: FileType.image); + + if (result != null && context.mounted) { + File file = File(result.files.single.path!); + await precacheImage(FileImage(file), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _buildFileEditor(file)), + ); + } }, - ), - ListTile( - leading: const Icon(Icons.sd_card_outlined), - title: const Text('Editor from file'), - trailing: const Icon(Icons.chevron_right), - subtitle: kIsWeb - ? const Text( - 'The file editor does not work in a web application ' - 'because Flutter does not support files in web ' - 'environments.') - : null, - enabled: !kIsWeb, - onTap: kIsWeb - ? null - : () async { - Navigator.pop(context); - - FilePickerResult? result = await FilePicker.platform - .pickFiles(type: FileType.image); - - if (result != null && context.mounted) { - File file = File(result.files.single.path!); - await precacheImage(FileImage(file), context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildFileEditor(file)), - ); - } - }, - ), - ], - ); - }, - ); - }, - leading: const Icon(Icons.dashboard_outlined), - title: const Text('Default Editor'), - trailing: const Icon(Icons.chevron_right), + ), + ], + ), ); } Widget _buildAssetEditor() { return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, @@ -201,7 +176,7 @@ class _DefaultExampleState extends State Widget _buildNetworkEditor() { return ProImageEditor.network( - ExampleConstants.of(context)!.demoNetworkUrl, + kImageEditorExampleNetworkUrl, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, diff --git a/example/lib/pages/design_examples/design_example.dart b/example/lib/pages/design_examples/design_example.dart index 0240d68a..d58ccf07 100644 --- a/example/lib/pages/design_examples/design_example.dart +++ b/example/lib/pages/design_examples/design_example.dart @@ -1,4 +1,5 @@ // Flutter imports: +import 'package:example/common/example_constants.dart'; import 'package:example/pages/design_examples/frosted_glass_example.dart'; import 'package:example/pages/design_examples/grounded_example.dart'; import 'package:example/pages/design_examples/highly_configurable_example.dart'; @@ -8,7 +9,6 @@ import 'package:flutter/material.dart'; // Package imports: import 'package:pro_image_editor/pro_image_editor.dart'; -import '../../utils/example_constants.dart'; import 'whatsapp_example.dart'; /// The design example widget @@ -28,78 +28,60 @@ class _DesignExampleState extends State @override Widget build(BuildContext context) { - return ListTile( - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext _) { - return ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 20), - children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text( - 'Designs', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - ), - const Divider(), - ListTile( - leading: const Icon(Icons.grass_outlined), - title: const Text('Grounded'), - trailing: const Icon(Icons.chevron_right), - onTap: () { - _openExample( - GroundedDesignExample(url: _urlGrounded), - _urlGrounded, - ); - }, - ), - ListTile( - leading: const Icon(Icons.auto_awesome), - title: const Text('Frosted-Glass'), - trailing: const Icon(Icons.chevron_right), - onTap: () { - _openExample( - FrostedGlassExample(url: _urlFrostedGlass), - _urlFrostedGlass, - ); - }, - ), - ListTile( - leading: const Icon(Icons.chat_outlined), - title: const Text('WhatsApp'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - _openExample( - WhatsAppExample(url: _urlWhatsApp), - _urlWhatsApp, - ); - }, - ), - ListTile( - leading: const Icon(Icons.tune), - title: const Text('Custom'), - trailing: const Icon(Icons.chevron_right), - onTap: () { - _openExample( - HighlyConfigurableExample( - url: ExampleConstants.of(context)!.demoNetworkUrl), - ExampleConstants.of(context)!.demoNetworkUrl, - ); - }, - ), - ], - ); - }, - ); - }, - leading: const Icon(Icons.palette_outlined), - title: const Text('Multiple designs'), - subtitle: - const Text('Grounded, WhatsApp, Frosted-Glass or custom design'), - trailing: const Icon(Icons.chevron_right), + return Scaffold( + appBar: AppBar( + title: const Text('Designs'), + ), + body: ListView( + shrinkWrap: true, + padding: const EdgeInsets.symmetric(vertical: 20), + children: [ + ListTile( + leading: const Icon(Icons.grass_outlined), + title: const Text('Grounded'), + trailing: const Icon(Icons.chevron_right), + onTap: () { + _openExample( + GroundedDesignExample(url: _urlGrounded), + _urlGrounded, + ); + }, + ), + ListTile( + leading: const Icon(Icons.auto_awesome), + title: const Text('Frosted-Glass'), + trailing: const Icon(Icons.chevron_right), + onTap: () { + _openExample( + FrostedGlassExample(url: _urlFrostedGlass), + _urlFrostedGlass, + ); + }, + ), + ListTile( + leading: const Icon(Icons.chat_outlined), + title: const Text('WhatsApp'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + _openExample( + WhatsAppExample(url: _urlWhatsApp), + _urlWhatsApp, + ); + }, + ), + ListTile( + leading: const Icon(Icons.tune), + title: const Text('Custom'), + trailing: const Icon(Icons.chevron_right), + onTap: () { + _openExample( + HighlyConfigurableExample(url: kImageEditorExampleNetworkUrl), + kImageEditorExampleNetworkUrl, + ); + }, + ), + ], + ), ); } @@ -107,7 +89,7 @@ class _DesignExampleState extends State LoadingDialog.instance.show( context, configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), + theme: Theme.of(context), ); await precacheImage(NetworkImage(_urlFrostedGlass), context); diff --git a/example/lib/pages/design_examples/frosted_glass_example.dart b/example/lib/pages/design_examples/frosted_glass_example.dart index dee16469..a0f81a1b 100644 --- a/example/lib/pages/design_examples/frosted_glass_example.dart +++ b/example/lib/pages/design_examples/frosted_glass_example.dart @@ -43,7 +43,7 @@ class _FrostedGlassExampleState extends State if (layer == null || !mounted) return; if (layer.runtimeType != StickerLayerData) { - layer.scale = editor.configs.emojiEditorConfigs.initScale; + layer.scale = editor.configs.emojiEditor.initScale; } editor.addLayer(layer); @@ -75,79 +75,8 @@ class _FrostedGlassExampleState extends State theme: Theme.of(context).copyWith( iconTheme: Theme.of(context).iconTheme.copyWith(color: Colors.white)), - icons: const ImageEditorIcons( - paintingEditor: IconsPaintingEditor( - bottomNavBar: Icons.edit, - ), - ), - imageEditorTheme: ImageEditorTheme( - textEditor: TextEditorTheme( - textFieldMargin: const EdgeInsets.only(top: kToolbarHeight), - bottomBarBackgroundColor: Colors.transparent, - bottomBarMainAxisAlignment: !_useMaterialDesign - ? MainAxisAlignment.spaceEvenly - : MainAxisAlignment.start), - paintingEditor: const PaintingEditorTheme( - initialStrokeWidth: 5, - ), - filterEditor: const FilterEditorTheme( - filterListSpacing: 7, - filterListMargin: EdgeInsets.fromLTRB(8, 15, 8, 10), - ), - emojiEditor: EmojiEditorTheme( - backgroundColor: Colors.transparent, - textStyle: DefaultEmojiTextStyle.copyWith( - fontFamily: - !kIsWeb ? null : GoogleFonts.notoColorEmoji().fontFamily, - fontSize: _useMaterialDesign ? 48 : 30, - ), - emojiViewConfig: EmojiViewConfig( - gridPadding: EdgeInsets.zero, - horizontalSpacing: 0, - verticalSpacing: 0, - recentsLimit: 40, - backgroundColor: Colors.transparent, - buttonMode: !_useMaterialDesign - ? ButtonMode.CUPERTINO - : ButtonMode.MATERIAL, - loadingIndicator: - const Center(child: CircularProgressIndicator()), - columns: _calculateEmojiColumns(constraints), - emojiSizeMax: !_useMaterialDesign ? 32 : 64, - replaceEmojiOnLimitExceed: false, - ), - bottomActionBarConfig: - const BottomActionBarConfig(enabled: false), - ), - layerInteraction: const ThemeLayerInteraction( - removeAreaBackgroundInactive: Colors.black12, - ), - ), - textEditorConfigs: TextEditorConfigs( - customTextStyles: [ - GoogleFonts.roboto(), - GoogleFonts.averiaLibre(), - GoogleFonts.lato(), - GoogleFonts.comicNeue(), - GoogleFonts.actor(), - GoogleFonts.odorMeanChey(), - GoogleFonts.nabla(), - ], - ), - emojiEditorConfigs: const EmojiEditorConfigs( - checkPlatformCompatibility: !kIsWeb, - ), - stickerEditorConfigs: StickerEditorConfigs( - enabled: true, - buildStickers: (setLayer, scrollController) => DemoBuildStickers( - setLayer: setLayer, scrollController: scrollController), - ), - customWidgets: ImageEditorCustomWidgets( - loadingDialog: (message, configs) => FrostedGlassLoadingDialog( - message: message, - configs: configs, - ), - mainEditor: CustomWidgetsMainEditor( + mainEditor: MainEditorConfigs( + widgets: MainEditorWidgets( closeWarningDialog: (editor) async { if (!context.mounted) return false; return await showDialog( @@ -161,21 +90,49 @@ class _FrostedGlassExampleState extends State bottomBar: (editor, rebuildStream, key) => null, bodyItems: _buildMainBodyWidgets, ), - paintEditor: CustomWidgetsPaintEditor( + ), + paintEditor: PaintEditorConfigs( + icons: const PaintEditorIcons( + bottomNavBar: Icons.edit, + ), + widgets: PaintEditorWidgets( appBar: (paintEditor, rebuildStream) => null, bottomBar: (paintEditor, rebuildStream) => null, colorPicker: (paintEditor, rebuildStream, currentColor, setColor) => null, bodyItems: _buildPaintEditorBody, ), - textEditor: CustomWidgetsTextEditor( + style: const PaintEditorStyle( + initialStrokeWidth: 5, + ), + ), + textEditor: TextEditorConfigs( + customTextStyles: [ + GoogleFonts.roboto(), + GoogleFonts.averiaLibre(), + GoogleFonts.lato(), + GoogleFonts.comicNeue(), + GoogleFonts.actor(), + GoogleFonts.odorMeanChey(), + GoogleFonts.nabla(), + ], + style: TextEditorStyle( + textFieldMargin: const EdgeInsets.only(top: kToolbarHeight), + bottomBarBackground: Colors.transparent, + bottomBarMainAxisAlignment: !_useMaterialDesign + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.start, + ), + widgets: TextEditorWidgets( appBar: (textEditor, rebuildStream) => null, colorPicker: (textEditor, rebuildStream, currentColor, setColor) => null, bottomBar: (textEditor, rebuildStream) => null, bodyItems: _buildTextEditorBody, ), - cropRotateEditor: CustomWidgetsCropRotateEditor( + ), + cropRotateEditor: CropRotateEditorConfigs( + widgets: CropRotateEditorWidgets( appBar: (cropRotateEditor, rebuildStream) => null, bottomBar: (cropRotateEditor, rebuildStream) => ReactiveCustomWidget( @@ -190,12 +147,13 @@ class _FrostedGlassExampleState extends State ), ), ), - tuneEditor: CustomWidgetsTuneEditor( - appBar: (filterEditor, rebuildStream) => null, - bottomBar: (filterEditor, rebuildStream) => null, - bodyItems: _buildTuneEditorBody, + ), + filterEditor: FilterEditorConfigs( + style: const FilterEditorStyle( + filterListSpacing: 7, + filterListMargin: EdgeInsets.fromLTRB(8, 15, 8, 10), ), - filterEditor: CustomWidgetsFilterEditor( + widgets: FilterEditorWidgets( slider: (editorState, rebuildStream, value, onChanged, onChangeEnd) => ReactiveCustomWidget( @@ -216,7 +174,16 @@ class _FrostedGlassExampleState extends State ), ], ), - blurEditor: CustomWidgetsBlurEditor( + ), + tuneEditor: TuneEditorConfigs( + widgets: TuneEditorWidgets( + appBar: (filterEditor, rebuildStream) => null, + bottomBar: (filterEditor, rebuildStream) => null, + bodyItems: _buildTuneEditorBody, + ), + ), + blurEditor: BlurEditorConfigs( + widgets: BlurEditorWidgets( slider: (editorState, rebuildStream, value, onChanged, onChangeEnd) => ReactiveCustomWidget( @@ -225,7 +192,7 @@ class _FrostedGlassExampleState extends State onChanged: onChanged, onChangeEnd: onChangeEnd, value: value, - max: editorState.configs.blurEditorConfigs.maxBlur, + max: editorState.configs.blurEditor.maxBlur, activeColor: Colors.blue.shade200, ), ), @@ -239,6 +206,52 @@ class _FrostedGlassExampleState extends State ], ), ), + emojiEditor: EmojiEditorConfigs( + checkPlatformCompatibility: !kIsWeb, + style: EmojiEditorStyle( + backgroundColor: Colors.transparent, + textStyle: DefaultEmojiTextStyle.copyWith( + fontFamily: + !kIsWeb ? null : GoogleFonts.notoColorEmoji().fontFamily, + fontSize: _useMaterialDesign ? 48 : 30, + ), + emojiViewConfig: EmojiViewConfig( + gridPadding: EdgeInsets.zero, + horizontalSpacing: 0, + verticalSpacing: 0, + recentsLimit: 40, + backgroundColor: Colors.transparent, + buttonMode: !_useMaterialDesign + ? ButtonMode.CUPERTINO + : ButtonMode.MATERIAL, + loadingIndicator: + const Center(child: CircularProgressIndicator()), + columns: _calculateEmojiColumns(constraints), + emojiSizeMax: !_useMaterialDesign ? 32 : 64, + replaceEmojiOnLimitExceed: false, + ), + bottomActionBarConfig: + const BottomActionBarConfig(enabled: false), + ), + ), + stickerEditor: StickerEditorConfigs( + enabled: true, + buildStickers: (setLayer, scrollController) => DemoBuildStickers( + setLayer: setLayer, scrollController: scrollController), + ), + layerInteraction: const LayerInteractionConfigs( + style: LayerInteractionStyle( + removeAreaBackgroundInactive: Colors.black12, + ), + ), + dialogConfigs: DialogConfigs( + widgets: DialogWidgets( + loadingDialog: (message, configs) => FrostedGlassLoadingDialog( + message: message, + configs: configs, + ), + ), + ), ), ); }); @@ -261,7 +274,7 @@ class _FrostedGlassExampleState extends State } List _buildPaintEditorBody( - PaintingEditorState paintEditor, + PaintEditorState paintEditor, Stream rebuildStream, ) { return [ @@ -269,9 +282,9 @@ class _FrostedGlassExampleState extends State ReactiveCustomWidget( stream: rebuildStream, builder: (_) { - return paintEditor.activePainting + return paintEditor.isActive ? const SizedBox.shrink() - : FrostedGlassPaintingAppbar(paintEditor: paintEditor); + : FrostedGlassPaintAppbar(paintEditor: paintEditor); }, ), diff --git a/example/lib/pages/design_examples/grounded_example.dart b/example/lib/pages/design_examples/grounded_example.dart index cfd3d2b5..6ccf3da7 100644 --- a/example/lib/pages/design_examples/grounded_example.dart +++ b/example/lib/pages/design_examples/grounded_example.dart @@ -73,103 +73,11 @@ class _GroundedDesignExampleState extends State brightness: Brightness.dark, ), ), - layerInteraction: const LayerInteraction( + layerInteraction: const LayerInteractionConfigs( hideToolbarOnInteraction: false, ), - imageEditorTheme: ImageEditorTheme( - background: const Color(0xFF000000), - bottomBarBackgroundColor: const Color(0xFF161616), - textEditor: TextEditorTheme( - textFieldMargin: const EdgeInsets.only(top: kToolbarHeight), - bottomBarBackgroundColor: Colors.transparent, - bottomBarMainAxisAlignment: !_useMaterialDesign - ? MainAxisAlignment.spaceEvenly - : MainAxisAlignment.start), - paintingEditor: const PaintingEditorTheme( - background: Color(0xFF000000), - initialStrokeWidth: 5, - ), - cropRotateEditor: const CropRotateEditorTheme( - cropCornerColor: Color(0xFFFFFFFF), - cropCornerLength: 36, - cropCornerThickness: 4, - background: Color(0xFF000000), - helperLineColor: Color(0x25FFFFFF)), - filterEditor: const FilterEditorTheme( - filterListSpacing: 7, - filterListMargin: EdgeInsets.fromLTRB(8, 0, 8, 8), - background: Color(0xFF000000), - ), - blurEditor: const BlurEditorTheme( - background: Color(0xFF000000), - ), - emojiEditor: EmojiEditorTheme( - backgroundColor: Colors.transparent, - textStyle: DefaultEmojiTextStyle.copyWith( - fontFamily: - !kIsWeb ? null : GoogleFonts.notoColorEmoji().fontFamily, - fontSize: _useMaterialDesign ? 48 : 30, - ), - emojiViewConfig: EmojiViewConfig( - gridPadding: EdgeInsets.zero, - horizontalSpacing: 0, - verticalSpacing: 0, - recentsLimit: 40, - backgroundColor: Colors.transparent, - buttonMode: !_useMaterialDesign - ? ButtonMode.CUPERTINO - : ButtonMode.MATERIAL, - loadingIndicator: - const Center(child: CircularProgressIndicator()), - columns: _calculateEmojiColumns(constraints), - emojiSizeMax: !_useMaterialDesign ? 32 : 64, - replaceEmojiOnLimitExceed: false, - ), - bottomActionBarConfig: - const BottomActionBarConfig(enabled: false), - ), - ), - textEditorConfigs: TextEditorConfigs( - customTextStyles: [ - GoogleFonts.roboto(), - GoogleFonts.averiaLibre(), - GoogleFonts.lato(), - GoogleFonts.comicNeue(), - GoogleFonts.actor(), - GoogleFonts.odorMeanChey(), - GoogleFonts.nabla(), - ], - ), - filterEditorConfigs: const FilterEditorConfigs( - fadeInUpDuration: GROUNDED_FADE_IN_DURATION, - fadeInUpStaggerDelayDuration: GROUNDED_FADE_IN_STAGGER_DELAY, - ), - emojiEditorConfigs: const EmojiEditorConfigs( - checkPlatformCompatibility: !kIsWeb, - ), - i18n: const I18n( - paintEditor: I18nPaintingEditor( - changeOpacity: 'Opacity', - lineWidth: 'Thickness', - ), - textEditor: I18nTextEditor( - backgroundMode: 'Mode', - textAlign: 'Align', - ), - ), - stickerEditorConfigs: StickerEditorConfigs( - enabled: true, - buildStickers: (setLayer, scrollController) => DemoBuildStickers( - categoryColor: const Color(0xFF161616), - setLayer: setLayer, - scrollController: scrollController), - ), - customWidgets: ImageEditorCustomWidgets( - loadingDialog: (message, configs) => FrostedGlassLoadingDialog( - message: message, - configs: configs, - ), - mainEditor: CustomWidgetsMainEditor( + mainEditor: MainEditorConfigs( + widgets: MainEditorWidgets( appBar: (editor, rebuildStream) => null, bottomBar: (editor, rebuildStream, key) => ReactiveCustomWidget( key: key, @@ -184,14 +92,25 @@ class _GroundedDesignExampleState extends State stream: rebuildStream, ), ), - paintEditor: CustomWidgetsPaintEditor( + style: const MainEditorStyle( + background: Color(0xFF000000), + bottomBarBackground: Color(0xFF161616), + ), + ), + paintEditor: PaintEditorConfigs( + style: const PaintEditorStyle( + background: Color(0xFF000000), + bottomBarBackground: Color(0xFF161616), + initialStrokeWidth: 5, + ), + widgets: PaintEditorWidgets( appBar: (paintEditor, rebuildStream) => null, colorPicker: (paintEditor, rebuildStream, currentColor, setColor) => null, bottomBar: (editorState, rebuildStream) { return ReactiveCustomWidget( builder: (context) { - return GroundedPaintingBar( + return GroundedPaintBar( configs: editorState.configs, callbacks: editorState.callbacks, editor: editorState, @@ -229,7 +148,25 @@ class _GroundedDesignExampleState extends State ); }, ), - textEditor: CustomWidgetsTextEditor( + ), + textEditor: TextEditorConfigs( + customTextStyles: [ + GoogleFonts.roboto(), + GoogleFonts.averiaLibre(), + GoogleFonts.lato(), + GoogleFonts.comicNeue(), + GoogleFonts.actor(), + GoogleFonts.odorMeanChey(), + GoogleFonts.nabla(), + ], + style: TextEditorStyle( + textFieldMargin: const EdgeInsets.only(top: kToolbarHeight), + bottomBarBackground: const Color(0xFF161616), + bottomBarMainAxisAlignment: !_useMaterialDesign + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.start, + ), + widgets: TextEditorWidgets( appBar: (textEditor, rebuildStream) => null, colorPicker: (textEditor, rebuildStream, currentColor, setColor) => null, @@ -283,7 +220,17 @@ class _GroundedDesignExampleState extends State ), ], ), - cropRotateEditor: CustomWidgetsCropRotateEditor( + ), + cropRotateEditor: CropRotateEditorConfigs( + style: const CropRotateEditorStyle( + cropCornerColor: Color(0xFFFFFFFF), + cropCornerLength: 36, + cropCornerThickness: 4, + background: Color(0xFF000000), + bottomBarBackground: Color(0xFF161616), + helperLineColor: Color(0x25FFFFFF), + ), + widgets: CropRotateEditorWidgets( appBar: (cropRotateEditor, rebuildStream) => null, bottomBar: (cropRotateEditor, rebuildStream) => ReactiveCustomWidget( @@ -292,26 +239,20 @@ class _GroundedDesignExampleState extends State configs: cropRotateEditor.configs, callbacks: cropRotateEditor.callbacks, editor: cropRotateEditor, - selectedRatioColor: imageEditorPrimaryColor, + selectedRatioColor: kImageEditorPrimaryColor, ), ), ), - tuneEditor: CustomWidgetsTuneEditor( - appBar: (editor, rebuildStream) => null, - bottomBar: (editorState, rebuildStream) { - return ReactiveCustomWidget( - builder: (context) { - return GroundedTuneBar( - configs: editorState.configs, - callbacks: editorState.callbacks, - editor: editorState, - ); - }, - stream: rebuildStream, - ); - }, + ), + filterEditor: FilterEditorConfigs( + fadeInUpDuration: GROUNDED_FADE_IN_DURATION, + fadeInUpStaggerDelayDuration: GROUNDED_FADE_IN_STAGGER_DELAY, + style: const FilterEditorStyle( + filterListSpacing: 7, + filterListMargin: EdgeInsets.fromLTRB(8, 0, 8, 8), + background: Color(0xFF000000), ), - filterEditor: CustomWidgetsFilterEditor( + widgets: FilterEditorWidgets( slider: (editorState, rebuildStream, value, onChanged, onChangeEnd) => ReactiveCustomWidget( @@ -337,7 +278,33 @@ class _GroundedDesignExampleState extends State ); }, ), - blurEditor: CustomWidgetsBlurEditor( + ), + tuneEditor: TuneEditorConfigs( + style: const TuneEditorStyle( + background: Color(0xFF000000), + bottomBarBackground: Color(0xFF161616), + ), + widgets: TuneEditorWidgets( + appBar: (editor, rebuildStream) => null, + bottomBar: (editorState, rebuildStream) { + return ReactiveCustomWidget( + builder: (context) { + return GroundedTuneBar( + configs: editorState.configs, + callbacks: editorState.callbacks, + editor: editorState, + ); + }, + stream: rebuildStream, + ); + }, + ), + ), + blurEditor: BlurEditorConfigs( + style: const BlurEditorStyle( + background: Color(0xFF000000), + ), + widgets: BlurEditorWidgets( appBar: (blurEditor, rebuildStream) => null, bottomBar: (editorState, rebuildStream) { return ReactiveCustomWidget( @@ -353,6 +320,59 @@ class _GroundedDesignExampleState extends State }, ), ), + emojiEditor: EmojiEditorConfigs( + checkPlatformCompatibility: !kIsWeb, + style: EmojiEditorStyle( + backgroundColor: Colors.transparent, + textStyle: DefaultEmojiTextStyle.copyWith( + fontFamily: + !kIsWeb ? null : GoogleFonts.notoColorEmoji().fontFamily, + fontSize: _useMaterialDesign ? 48 : 30, + ), + emojiViewConfig: EmojiViewConfig( + gridPadding: EdgeInsets.zero, + horizontalSpacing: 0, + verticalSpacing: 0, + recentsLimit: 40, + backgroundColor: Colors.transparent, + buttonMode: !_useMaterialDesign + ? ButtonMode.CUPERTINO + : ButtonMode.MATERIAL, + loadingIndicator: + const Center(child: CircularProgressIndicator()), + columns: _calculateEmojiColumns(constraints), + emojiSizeMax: !_useMaterialDesign ? 32 : 64, + replaceEmojiOnLimitExceed: false, + ), + bottomActionBarConfig: + const BottomActionBarConfig(enabled: false), + ), + ), + i18n: const I18n( + paintEditor: I18nPaintEditor( + changeOpacity: 'Opacity', + lineWidth: 'Thickness', + ), + textEditor: I18nTextEditor( + backgroundMode: 'Mode', + textAlign: 'Align', + ), + ), + stickerEditor: StickerEditorConfigs( + enabled: true, + buildStickers: (setLayer, scrollController) => DemoBuildStickers( + categoryColor: const Color(0xFF161616), + setLayer: setLayer, + scrollController: scrollController), + ), + dialogConfigs: DialogConfigs( + widgets: DialogWidgets( + loadingDialog: (message, configs) => FrostedGlassLoadingDialog( + message: message, + configs: configs, + ), + ), + ), ), ); }); diff --git a/example/lib/pages/design_examples/highly_configurable_example.dart b/example/lib/pages/design_examples/highly_configurable_example.dart index 22928752..ab18c0c4 100644 --- a/example/lib/pages/design_examples/highly_configurable_example.dart +++ b/example/lib/pages/design_examples/highly_configurable_example.dart @@ -48,7 +48,7 @@ class _HighlyConfigurableExampleState extends State closeEditorWarningConfirmBtn: 'OK', closeEditorWarningCancelBtn: 'Cancel', ), - paintEditor: I18nPaintingEditor( + paintEditor: I18nPaintEditor( bottomNavigationBarText: 'Paint', freestyle: 'Freestyle', arrow: 'Arrow', @@ -165,154 +165,42 @@ class _HighlyConfigurableExampleState extends State remove: 'Remove', doneLoadingMsg: 'Changes are being applied', ), - helperLines: const HelperLines( + helperLines: const HelperLineConfigs( showVerticalLine: true, showHorizontalLine: true, showRotateLine: true, hitVibration: true, - ), - customWidgets: const ImageEditorCustomWidgets(), - imageEditorTheme: const ImageEditorTheme( - helperLine: HelperLineTheme( + style: HelperLineStyle( horizontalColor: Color.fromARGB(255, 15, 196, 60), verticalColor: Color.fromARGB(255, 15, 196, 60), rotateColor: Color.fromARGB(255, 231, 255, 11), ), - paintingEditor: PaintingEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 20, 99, 189), - lineWidthBottomSheetColor: Colors.green, - appBarForegroundColor: Color(0xFFE1E1E1), - background: Color.fromARGB(255, 255, 249, 196), - bottomBarColor: Color.fromARGB(255, 136, 0, 84), - bottomBarActiveItemColor: Color.fromARGB(255, 46, 0, 58), - bottomBarInactiveItemColor: Color.fromARGB(255, 223, 255, 210), - initialStrokeWidth: 5.0, - initialColor: Color.fromARGB(255, 8, 170, 49), - ), - textEditor: TextEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 0, 17, 255), - appBarForegroundColor: Color(0xFFE1E1E1), - background: Color.fromARGB(155, 255, 194, 252), - inputHintColor: Color.fromARGB(255, 255, 0, 0), - inputCursorColor: Color.fromARGB(255, 15, 182, 0), - ), - cropRotateEditor: CropRotateEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 85, 0, 0), - appBarForegroundColor: Color(0xFFE1E1E1), - bottomBarBackgroundColor: Color.fromARGB(255, 136, 0, 84), - bottomBarForegroundColor: Color.fromARGB(255, 223, 255, 210), - background: Color.fromARGB(255, 255, 203, 203), - cropCornerColor: Color.fromARGB(255, 0, 212, 195), - aspectRatioSheetBackgroundColor: Colors.green, - aspectRatioSheetForegroundColor: Color.fromARGB(255, 255, 210, 141), - cropOverlayColor: Colors.orange, - helperLineColor: Colors.blue, - ), - filterEditor: FilterEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 82, 0, 82), - appBarForegroundColor: Color(0xFFE1E1E1), - previewTextColor: Color.fromARGB(255, 255, 0, 0), - background: Color.fromARGB(255, 83, 78, 0), - ), - tuneEditor: TuneEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 160, 34, 160), - appBarForegroundColor: Color(0xFFE1E1E1), - background: Color.fromARGB(255, 0, 83, 32), - bottomBarColor: Color.fromARGB(255, 0, 136, 136), - bottomBarActiveItemColor: Color.fromARGB(255, 173, 231, 25), - bottomBarInactiveItemColor: Color.fromARGB(255, 255, 210, 216), - ), - blurEditor: BlurEditorTheme( - appBarBackgroundColor: Color.fromARGB(255, 56, 0, 0), - appBarForegroundColor: Color(0xFFE1E1E1), - background: Color.fromARGB(255, 187, 214, 255), - ), - emojiEditor: EmojiEditorTheme( - bottomActionBarConfig: BottomActionBarConfig( - buttonIconColor: Colors.blue, - backgroundColor: Colors.red, - buttonColor: Colors.amber, - showBackspaceButton: false, - ), - skinToneConfig: SkinToneConfig( - enabled: true, - dialogBackgroundColor: Colors.green, - indicatorColor: Colors.pink, - ), - categoryViewConfig: CategoryViewConfig( - backgroundColor: Colors.amber, - iconColor: Colors.purple, - ), - textStyle: TextStyle(fontFamilyFallback: ['Apple Color Emoji']), - ), - stickerEditor: StickerEditorTheme(), - background: Color.fromARGB(255, 255, 169, 169), - appBarBackgroundColor: Color.fromARGB(255, 255, 211, 77), - appBarForegroundColor: Colors.black, - bottomBarBackgroundColor: Colors.purple, - loadingDialogTheme: - LoadingDialogTheme(textColor: Color.fromARGB(255, 225, 255, 200)), - uiOverlayStyle: SystemUiOverlayStyle( - statusBarColor: Color.fromARGB(66, 60, 65, 41), - statusBarIconBrightness: Brightness.light, - systemNavigationBarIconBrightness: Brightness.light, - statusBarBrightness: Brightness.dark, - systemNavigationBarColor: Color.fromARGB(255, 255, 139, 216), - ), ), - icons: const ImageEditorIcons( - paintingEditor: IconsPaintingEditor( - bottomNavBar: Icons.palette, - lineWeight: Icons.line_weight_rounded, - freeStyle: Icons.roundabout_left, - arrow: Icons.arrow_downward_rounded, - line: Icons.horizontal_rule, - fill: Icons.format_color_fill, - noFill: Icons.format_color_reset, - rectangle: Icons.crop_free, - circle: Icons.lens_outlined, - dashLine: Icons.power_input, - ), - textEditor: IconsTextEditor( - bottomNavBar: Icons.title, - alignLeft: Icons.align_horizontal_left_rounded, - alignCenter: Icons.align_horizontal_center_rounded, - alignRight: Icons.align_horizontal_right_rounded, - backgroundMode: Icons.dashboard, - fontScale: Icons.text_increase_rounded, - resetFontScale: Icons.restore, - ), - cropRotateEditor: IconsCropRotateEditor( - bottomNavBar: Icons.crop_free_rounded, - rotate: Icons.rotate_left, - aspectRatio: Icons.crop, - flip: Icons.swap_horiz, - reset: Icons.reset_tv, - ), - filterEditor: IconsFilterEditor( - bottomNavBar: Icons.tungsten, - ), - tuneEditor: IconsTuneEditor( - bottomNavBar: Icons.filter_b_and_w_outlined, - ), - blurEditor: IconsBlurEditor( - bottomNavBar: Icons.blur_linear_outlined, - ), - emojiEditor: IconsEmojiEditor( - bottomNavBar: Icons.face_4_outlined, + mainEditor: const MainEditorConfigs( + style: MainEditorStyle( + background: Color.fromARGB(255, 255, 169, 169), + appBarColor: Color.fromARGB(255, 126, 14, 6), + appBarBackground: Color.fromARGB(255, 255, 211, 77), + bottomBarBackground: Colors.purple, + uiOverlayStyle: SystemUiOverlayStyle( + statusBarColor: Color.fromARGB(66, 60, 65, 41), + statusBarIconBrightness: Brightness.light, + systemNavigationBarIconBrightness: Brightness.light, + statusBarBrightness: Brightness.dark, + systemNavigationBarColor: Color.fromARGB(255, 255, 139, 216), + ), ), - stickerEditor: IconsStickerEditor( - bottomNavBar: Icons.layers_outlined, + icons: MainEditorIcons( + closeEditor: Icons.clear, + doneIcon: Icons.save_outlined, + applyChanges: Icons.check_circle_outlined, + backButton: Icons.arrow_back, + undoAction: Icons.turn_left_outlined, + redoAction: Icons.turn_right_outlined, + removeElementZone: Icons.delete_forever_outlined, ), - closeEditor: Icons.clear, - doneIcon: Icons.save_outlined, - applyChanges: Icons.check_circle_outlined, - backButton: Icons.arrow_back, - undoAction: Icons.turn_left_outlined, - redoAction: Icons.turn_right_outlined, - removeElementZone: Icons.delete_forever_outlined, ), - paintEditorConfigs: const PaintEditorConfigs( + paintEditor: const PaintEditorConfigs( enabled: true, hasOptionFreeStyle: true, hasOptionArrow: true, @@ -325,8 +213,31 @@ class _HighlyConfigurableExampleState extends State initialFill: true, freeStyleHighPerformanceScaling: true, initialPaintMode: PaintModeE.freeStyle, + style: PaintEditorStyle( + appBarColor: Color(0xFFE1E1E1), + appBarBackground: Color.fromARGB(255, 20, 99, 189), + lineWidthBottomSheetBackground: Colors.green, + background: Color.fromARGB(255, 255, 249, 196), + bottomBarBackground: Colors.blueGrey, + bottomBarActiveItemColor: Color.fromARGB(255, 154, 0, 192), + bottomBarInactiveItemColor: Color.fromARGB(255, 223, 255, 210), + initialStrokeWidth: 5.0, + initialColor: Color.fromARGB(255, 8, 170, 49), + ), + icons: PaintEditorIcons( + bottomNavBar: Icons.palette, + lineWeight: Icons.line_weight_rounded, + freeStyle: Icons.roundabout_left, + arrow: Icons.arrow_downward_rounded, + line: Icons.horizontal_rule, + fill: Icons.format_color_fill, + noFill: Icons.format_color_reset, + rectangle: Icons.crop_free, + circle: Icons.lens_outlined, + dashLine: Icons.power_input, + ), ), - textEditorConfigs: TextEditorConfigs( + textEditor: TextEditorConfigs( enabled: true, canToggleTextAlign: true, canToggleBackgroundMode: true, @@ -334,6 +245,23 @@ class _HighlyConfigurableExampleState extends State initialTextAlign: TextAlign.center, initialBackgroundColorMode: LayerBackgroundMode.background, showSelectFontStyleBottomBar: true, + style: const TextEditorStyle( + appBarBackground: Color.fromARGB(255, 0, 17, 255), + appBarColor: Color(0xFFE1E1E1), + bottomBarBackground: Colors.blueGrey, + background: Color.fromARGB(155, 255, 194, 252), + inputHintColor: Color.fromARGB(255, 255, 0, 0), + inputCursorColor: Color.fromARGB(255, 15, 182, 0), + ), + icons: const TextEditorIcons( + bottomNavBar: Icons.title, + alignLeft: Icons.align_horizontal_left_rounded, + alignCenter: Icons.align_horizontal_center_rounded, + alignRight: Icons.align_horizontal_right_rounded, + backgroundMode: Icons.dashboard, + fontScale: Icons.text_increase_rounded, + resetFontScale: Icons.restore, + ), customTextStyles: [ GoogleFonts.roboto(), GoogleFonts.averiaLibre(), @@ -344,7 +272,7 @@ class _HighlyConfigurableExampleState extends State GoogleFonts.nabla(), ], ), - cropRotateEditorConfigs: const CropRotateEditorConfigs( + cropRotateEditor: const CropRotateEditorConfigs( enabled: true, canRotate: true, canChangeAspectRatio: true, @@ -361,115 +289,199 @@ class _HighlyConfigurableExampleState extends State AspectRatioItem(text: '9*16', value: 9.0 / 16.0), AspectRatioItem(text: '3*5.5', value: 3.0 / 5.5), ], + style: CropRotateEditorStyle( + appBarBackground: Color.fromARGB(255, 85, 0, 0), + appBarColor: Color(0xFFE1E1E1), + bottomBarBackground: Color.fromARGB(255, 136, 0, 84), + bottomBarColor: Color.fromARGB(255, 223, 255, 210), + background: Color.fromARGB(255, 255, 203, 203), + cropCornerColor: Color.fromARGB(255, 0, 212, 195), + aspectRatioSheetBackgroundColor: Colors.green, + aspectRatioSheetForegroundColor: Color.fromARGB(255, 255, 210, 141), + cropOverlayColor: Colors.orange, + helperLineColor: Colors.blue, + ), + icons: CropRotateEditorIcons( + bottomNavBar: Icons.crop_free_rounded, + rotate: Icons.rotate_left, + aspectRatio: Icons.crop, + flip: Icons.swap_horiz, + reset: Icons.reset_tv, + ), ), - filterEditorConfigs: FilterEditorConfigs( + tuneEditor: TuneEditorConfigs( + enabled: true, + showLayers: true, + tuneAdjustmentOptions: [ + const TuneAdjustmentItem( + id: 'brightness', + icon: Icons.brightness_4_outlined, + label: 'Brightness', + min: -0.5, + max: 0.5, + divisions: 200, + labelMultiplier: 200, + toMatrix: ColorFilterAddons.brightness, + ), + const TuneAdjustmentItem( + id: 'contrast', + icon: Icons.contrast, + label: 'Contrast', + min: -0.5, + max: 0.5, + divisions: 200, + labelMultiplier: 200, + toMatrix: ColorFilterAddons.contrast, + ), + const TuneAdjustmentItem( + id: 'saturation', + icon: Icons.water_drop_outlined, + label: 'Saturation', + min: -0.5, + max: .5, + divisions: 200, + labelMultiplier: 200, + toMatrix: ColorFilterAddons.saturation, + ), + const TuneAdjustmentItem( + id: 'exposure', + icon: Icons.exposure, + label: 'Exposure', + min: -1, + max: 1, + divisions: 200, + toMatrix: ColorFilterAddons.exposure, + ), + const TuneAdjustmentItem( + id: 'hue', + icon: Icons.color_lens_outlined, + label: 'Hue', + min: -0.25, + max: .25, + divisions: 400, + labelMultiplier: 400, + toMatrix: ColorFilterAddons.hue, + ), + TuneAdjustmentItem( + id: 'temperature', + icon: Icons.thermostat_outlined, + label: 'Temperature', + min: -0.5, + max: .5, + divisions: 200, + labelMultiplier: 200, + toMatrix: (value) { + double r = value > 0 ? 1 : 1 + value; + double b = value < 0 ? 1 : 1 - value; + return ColorFilterAddons.rgbScale(r, 1, b); + }, + ), + const TuneAdjustmentItem( + id: 'sharpness', + icon: Icons.shutter_speed, + label: 'Sharpness', + min: 0, + max: 1, + divisions: 100, + toMatrix: ColorFilterAddons.sharpness, + ), + const TuneAdjustmentItem( + id: 'luminance', + icon: Icons.light_mode_outlined, + label: 'Luminance', + min: -1, + max: 1, + divisions: 200, + toMatrix: ColorFilterAddons.luminance, + ), + const TuneAdjustmentItem( + id: 'fade', + icon: Icons.blur_off_outlined, + label: 'Fade', + min: -1, + max: 1, + divisions: 200, + toMatrix: ColorFilterAddons.fade, + ), + ], + style: const TuneEditorStyle( + appBarBackground: Color.fromARGB(255, 160, 34, 160), + appBarColor: Color(0xFFE1E1E1), + background: Color.fromARGB(255, 0, 83, 32), + bottomBarBackground: Color.fromARGB(255, 0, 136, 136), + bottomBarActiveItemColor: Color.fromARGB(255, 173, 231, 25), + bottomBarInactiveItemColor: Color.fromARGB(255, 255, 210, 216), + ), + icons: const TuneEditorIcons( + bottomNavBar: Icons.filter_b_and_w_outlined, + ), + ), + filterEditor: FilterEditorConfigs( enabled: true, filterList: presetFiltersList, + style: const FilterEditorStyle( + appBarBackground: Color.fromARGB(255, 82, 0, 82), + appBarColor: Color(0xFFE1E1E1), + previewTextColor: Color.fromARGB(255, 255, 0, 0), + background: Color.fromARGB(255, 83, 78, 0), + ), + icons: const FilterEditorIcons( + bottomNavBar: Icons.tungsten, + ), ), - tuneEditorConfigs: TuneEditorConfigs( - enabled: true, - showLayers: true, - tuneAdjustmentOptions: [ - const TuneAdjustmentItem( - id: 'brightness', - icon: Icons.brightness_4_outlined, - label: 'Brightness', - min: -0.5, - max: 0.5, - divisions: 200, - labelMultiplier: 200, - toMatrix: ColorFilterAddons.brightness, - ), - const TuneAdjustmentItem( - id: 'contrast', - icon: Icons.contrast, - label: 'Contrast', - min: -0.5, - max: 0.5, - divisions: 200, - labelMultiplier: 200, - toMatrix: ColorFilterAddons.contrast, - ), - const TuneAdjustmentItem( - id: 'saturation', - icon: Icons.water_drop_outlined, - label: 'Saturation', - min: -0.5, - max: .5, - divisions: 200, - labelMultiplier: 200, - toMatrix: ColorFilterAddons.saturation, - ), - const TuneAdjustmentItem( - id: 'exposure', - icon: Icons.exposure, - label: 'Exposure', - min: -1, - max: 1, - divisions: 200, - toMatrix: ColorFilterAddons.exposure, - ), - const TuneAdjustmentItem( - id: 'hue', - icon: Icons.color_lens_outlined, - label: 'Hue', - min: -0.25, - max: .25, - divisions: 400, - labelMultiplier: 400, - toMatrix: ColorFilterAddons.hue, - ), - TuneAdjustmentItem( - id: 'temperature', - icon: Icons.thermostat_outlined, - label: 'Temperature', - min: -0.5, - max: .5, - divisions: 200, - labelMultiplier: 200, - toMatrix: (value) { - double r = value > 0 ? 1 : 1 + value; - double b = value < 0 ? 1 : 1 - value; - return ColorFilterAddons.rgbScale(r, 1, b); - }, - ), - const TuneAdjustmentItem( - id: 'sharpness', - icon: Icons.shutter_speed, - label: 'Sharpness', - min: 0, - max: 1, - divisions: 100, - toMatrix: ColorFilterAddons.sharpness, - ), - const TuneAdjustmentItem( - id: 'luminance', - icon: Icons.light_mode_outlined, - label: 'Luminance', - min: -1, - max: 1, - divisions: 200, - toMatrix: ColorFilterAddons.luminance, - ), - const TuneAdjustmentItem( - id: 'fade', - icon: Icons.blur_off_outlined, - label: 'Fade', - min: -1, - max: 1, - divisions: 200, - toMatrix: ColorFilterAddons.fade, - ), - ]), - blurEditorConfigs: const BlurEditorConfigs( + blurEditor: const BlurEditorConfigs( enabled: true, maxBlur: 20.0, + style: BlurEditorStyle( + appBarBackgroundColor: Color.fromARGB(255, 56, 0, 0), + appBarForegroundColor: Color(0xFFE1E1E1), + background: Color.fromARGB(255, 187, 214, 255), + ), + icons: BlurEditorIcons( + bottomNavBar: Icons.blur_linear_outlined, + ), ), - emojiEditorConfigs: const EmojiEditorConfigs( + emojiEditor: const EmojiEditorConfigs( enabled: true, initScale: 2.0, checkPlatformCompatibility: true, + style: EmojiEditorStyle( + bottomActionBarConfig: BottomActionBarConfig( + buttonIconColor: Colors.blue, + backgroundColor: Colors.red, + buttonColor: Colors.amber, + showBackspaceButton: false, + ), + skinToneConfig: SkinToneConfig( + enabled: true, + dialogBackgroundColor: Colors.green, + indicatorColor: Colors.pink, + ), + categoryViewConfig: CategoryViewConfig( + backgroundColor: Colors.amber, + iconColor: Colors.purple, + ), + textStyle: TextStyle(fontFamilyFallback: ['Apple Color Emoji']), + ), + icons: EmojiEditorIcons( + bottomNavBar: Icons.face_4_outlined, + ), ), + + dialogConfigs: const DialogConfigs( + style: DialogStyle( + loadingDialog: LoadingDialogStyle( + textColor: Color.fromARGB(255, 225, 255, 200), + ), + ), + ), + + /// stickerEditor: StickerEditorConfigs( + /// style: StickerEditorStyle() + /// icons: StickerEditorIcons( + /// bottomNavBar: Icons.layers_outlined, + /// ), + /// ), heroTag: 'hero', theme: ThemeData( useMaterial3: true, diff --git a/example/lib/pages/design_examples/whatsapp_example.dart b/example/lib/pages/design_examples/whatsapp_example.dart index 4145383d..da6eff41 100644 --- a/example/lib/pages/design_examples/whatsapp_example.dart +++ b/example/lib/pages/design_examples/whatsapp_example.dart @@ -101,7 +101,7 @@ class _WhatsAppExampleState extends State if (layer == null || !mounted) return; if (layer.runtimeType != StickerLayerData) { - layer.scale = editor.configs.emojiEditorConfigs.initScale; + layer.scale = editor.configs.emojiEditor.initScale; } editor.addLayer(layer); @@ -139,213 +139,218 @@ class _WhatsAppExampleState extends State }, )), configs: ProImageEditorConfigs( - designMode: platformDesignMode, - imageEditorTheme: ImageEditorTheme( - textEditor: TextEditorTheme( - textFieldMargin: EdgeInsets.zero, - bottomBarBackgroundColor: Colors.transparent, - bottomBarMainAxisAlignment: !_useMaterialDesign - ? MainAxisAlignment.spaceEvenly - : MainAxisAlignment.start), - paintingEditor: const PaintingEditorTheme( - initialColor: Color.fromARGB(255, 129, 218, 88), - initialStrokeWidth: 5, - ), - cropRotateEditor: const CropRotateEditorTheme( - cropCornerColor: Colors.white, - helperLineColor: Colors.white, - cropCornerLength: 28, - cropCornerThickness: 3, - ), - filterEditor: const FilterEditorTheme( - filterListSpacing: 7, - filterListMargin: EdgeInsets.fromLTRB(8, 15, 8, 10), + designMode: platformDesignMode, + mainEditor: MainEditorConfigs( + widgets: MainEditorWidgets( + appBar: (editor, rebuildStream) => null, + bottomBar: (editor, rebuildStream, key) => null, + wrapBody: (editor, rebuildStream, content) { + return Stack( + alignment: Alignment.center, + fit: StackFit.expand, + clipBehavior: Clip.none, + children: [ + Transform.scale( + transformHitTests: false, + scale: 1 / + constraints.maxHeight * + (constraints.maxHeight - + _whatsAppHelper.filterShowHelper * 2), + child: content, + ), + if (editor.selectedLayerIndex < 0) + ..._buildWhatsAppWidgets(editor), + ], + ); + }, + ), ), - emojiEditor: EmojiEditorTheme( - backgroundColor: Colors.transparent, - textStyle: DefaultEmojiTextStyle.copyWith( - fontFamily: - !kIsWeb ? null : GoogleFonts.notoColorEmoji().fontFamily, - fontSize: _useMaterialDesign ? 48 : 30, + paintEditor: PaintEditorConfigs( + style: const PaintEditorStyle( + initialColor: Color.fromARGB(255, 129, 218, 88), + initialStrokeWidth: 5, ), - emojiViewConfig: EmojiViewConfig( - gridPadding: EdgeInsets.zero, - horizontalSpacing: 0, - verticalSpacing: 0, - recentsLimit: 40, - backgroundColor: Colors.transparent, - buttonMode: !_useMaterialDesign - ? ButtonMode.CUPERTINO - : ButtonMode.MATERIAL, - loadingIndicator: - const Center(child: CircularProgressIndicator()), - columns: _calculateEmojiColumns(constraints), - emojiSizeMax: !_useMaterialDesign ? 32 : 64, - replaceEmojiOnLimitExceed: false, + widgets: PaintEditorWidgets( + appBar: (paintEditor, rebuildStream) => null, + bottomBar: (paintEditor, rebuildStream) => null, + colorPicker: + (paintEditor, rebuildStream, currentColor, setColor) => + null, + bodyItems: _buildPaintEditorBody, ), - bottomActionBarConfig: - const BottomActionBarConfig(enabled: false), - ), - layerInteraction: const ThemeLayerInteraction( - removeAreaBackgroundInactive: Colors.black12, - ), - helperLine: const HelperLineTheme( - horizontalColor: Color.fromARGB(255, 129, 218, 88), - verticalColor: Color.fromARGB(255, 129, 218, 88), ), - ), - textEditorConfigs: TextEditorConfigs( - customTextStyles: [ - GoogleFonts.roboto(), - GoogleFonts.averiaLibre(), - GoogleFonts.lato(), - GoogleFonts.comicNeue(), - GoogleFonts.actor(), - GoogleFonts.odorMeanChey(), - GoogleFonts.nabla(), - ], - ), - cropRotateEditorConfigs: const CropRotateEditorConfigs( - enableDoubleTap: false, - ), - filterEditorConfigs: FilterEditorConfigs( - filterList: [ - const FilterModel( - name: 'None', - filters: [], - ), - FilterModel( - name: 'Pop', - filters: [ - ColorFilterAddons.colorOverlay(255, 225, 80, 0.08), - ColorFilterAddons.saturation(0.1), - ColorFilterAddons.contrast(0.05), - ], + textEditor: TextEditorConfigs( + customTextStyles: [ + GoogleFonts.roboto(), + GoogleFonts.averiaLibre(), + GoogleFonts.lato(), + GoogleFonts.comicNeue(), + GoogleFonts.actor(), + GoogleFonts.odorMeanChey(), + GoogleFonts.nabla(), + ], + widgets: TextEditorWidgets( + appBar: (textEditor, rebuildStream) => null, + colorPicker: + (editor, rebuildStream, currentColor, setColor) => null, + bottomBar: (textEditor, rebuildStream) => null, + bodyItems: _buildTextEditorBody, ), - FilterModel( - name: 'B&W', - filters: [ - ColorFilterAddons.grayscale(), - ColorFilterAddons.colorOverlay(100, 28, 210, 0.03), - ColorFilterAddons.brightness(0.1), - ], + style: TextEditorStyle( + textFieldMargin: EdgeInsets.zero, + bottomBarBackground: Colors.transparent, + bottomBarMainAxisAlignment: !_useMaterialDesign + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.start), + ), + cropRotateEditor: CropRotateEditorConfigs( + enableDoubleTap: false, + widgets: CropRotateEditorWidgets( + appBar: (cropRotateEditor, rebuildStream) => null, + bottomBar: (cropRotateEditor, rebuildStream) => + ReactiveCustomWidget( + stream: rebuildStream, + builder: (_) => WhatsAppCropRotateToolbar( + bottomBarColor: const Color(0xFF303030), + configs: cropRotateEditor.configs, + onCancel: cropRotateEditor.close, + onRotate: cropRotateEditor.rotate, + onDone: cropRotateEditor.done, + onReset: cropRotateEditor.reset, + openAspectRatios: cropRotateEditor.openAspectRatioOptions, + ), + ), ), - FilterModel( - name: 'Cool', - filters: [ - ColorFilterAddons.addictiveColor(0, 0, 20), - ], + style: const CropRotateEditorStyle( + cropCornerColor: Colors.white, + helperLineColor: Colors.white, + cropCornerLength: 28, + cropCornerThickness: 3, ), - FilterModel( - name: 'Chrome', - filters: [ - ColorFilterAddons.contrast(0.15), - ColorFilterAddons.saturation(0.2), - ], + ), + filterEditor: FilterEditorConfigs( + filterList: [ + const FilterModel( + name: 'None', + filters: [], + ), + FilterModel( + name: 'Pop', + filters: [ + ColorFilterAddons.colorOverlay(255, 225, 80, 0.08), + ColorFilterAddons.saturation(0.1), + ColorFilterAddons.contrast(0.05), + ], + ), + FilterModel( + name: 'B&W', + filters: [ + ColorFilterAddons.grayscale(), + ColorFilterAddons.colorOverlay(100, 28, 210, 0.03), + ColorFilterAddons.brightness(0.1), + ], + ), + FilterModel( + name: 'Cool', + filters: [ + ColorFilterAddons.addictiveColor(0, 0, 20), + ], + ), + FilterModel( + name: 'Chrome', + filters: [ + ColorFilterAddons.contrast(0.15), + ColorFilterAddons.saturation(0.2), + ], + ), + FilterModel( + name: 'Film', + filters: [ + ColorFilterAddons.brightness(.05), + ColorFilterAddons.saturation(-0.03), + ], + ), + ], + widgets: FilterEditorWidgets( + filterButton: ( + filter, + isSelected, + scaleFactor, + onSelectFilter, + editorImage, + filterKey, + ) { + return WhatsAppFilterBtn( + filter: filter, + isSelected: isSelected, + onSelectFilter: () { + onSelectFilter.call(); + _editor!.setState(() {}); + }, + editorImage: editorImage, + filterKey: filterKey, + scaleFactor: scaleFactor, + ); + }, ), - FilterModel( - name: 'Film', - filters: [ - ColorFilterAddons.brightness(.05), - ColorFilterAddons.saturation(-0.03), - ], + style: const FilterEditorStyle( + filterListSpacing: 7, + filterListMargin: EdgeInsets.fromLTRB(8, 15, 8, 10), ), - ], - ), - emojiEditorConfigs: const EmojiEditorConfigs( - checkPlatformCompatibility: !kIsWeb, - ), - stickerEditorConfigs: StickerEditorConfigs( - enabled: true, - buildStickers: (setLayer, scrollController) => DemoBuildStickers( - setLayer: setLayer, scrollController: scrollController), - ), - customWidgets: ImageEditorCustomWidgets( - mainEditor: CustomWidgetsMainEditor( - appBar: (editor, rebuildStream) => null, - bottomBar: (editor, rebuildStream, key) => null, - wrapBody: (editor, rebuildStream, content) { - return Stack( - alignment: Alignment.center, - fit: StackFit.expand, - clipBehavior: Clip.none, - children: [ - Transform.scale( - transformHitTests: false, - scale: 1 / - constraints.maxHeight * - (constraints.maxHeight - - _whatsAppHelper.filterShowHelper * 2), - child: content, - ), - if (editor.selectedLayerIndex < 0) - ..._buildWhatsAppWidgets(editor), - ], - ); - }, ), - paintEditor: CustomWidgetsPaintEditor( - appBar: (paintEditor, rebuildStream) => null, - bottomBar: (paintEditor, rebuildStream) => null, - colorPicker: - (paintEditor, rebuildStream, currentColor, setColor) => - null, - bodyItems: _buildPaintEditorBody, - ), - textEditor: CustomWidgetsTextEditor( - appBar: (textEditor, rebuildStream) => null, - colorPicker: (editor, rebuildStream, currentColor, setColor) => - null, - bottomBar: (textEditor, rebuildStream) => null, - bodyItems: _buildTextEditorBody, - ), - cropRotateEditor: CustomWidgetsCropRotateEditor( - appBar: (cropRotateEditor, rebuildStream) => null, - bottomBar: (cropRotateEditor, rebuildStream) => - ReactiveCustomWidget( - stream: rebuildStream, - builder: (_) => WhatsAppCropRotateToolbar( - bottomBarColor: const Color(0xFF303030), - configs: cropRotateEditor.configs, - onCancel: cropRotateEditor.close, - onRotate: cropRotateEditor.rotate, - onDone: cropRotateEditor.done, - onReset: cropRotateEditor.reset, - openAspectRatios: cropRotateEditor.openAspectRatioOptions, + emojiEditor: EmojiEditorConfigs( + checkPlatformCompatibility: !kIsWeb, + style: EmojiEditorStyle( + backgroundColor: Colors.transparent, + textStyle: DefaultEmojiTextStyle.copyWith( + fontFamily: !kIsWeb + ? null + : GoogleFonts.notoColorEmoji().fontFamily, + fontSize: _useMaterialDesign ? 48 : 30, ), + emojiViewConfig: EmojiViewConfig( + gridPadding: EdgeInsets.zero, + horizontalSpacing: 0, + verticalSpacing: 0, + recentsLimit: 40, + backgroundColor: Colors.transparent, + buttonMode: !_useMaterialDesign + ? ButtonMode.CUPERTINO + : ButtonMode.MATERIAL, + loadingIndicator: + const Center(child: CircularProgressIndicator()), + columns: _calculateEmojiColumns(constraints), + emojiSizeMax: !_useMaterialDesign ? 32 : 64, + replaceEmojiOnLimitExceed: false, + ), + bottomActionBarConfig: + const BottomActionBarConfig(enabled: false), ), ), - filterEditor: CustomWidgetsFilterEditor( - filterButton: ( - filter, - isSelected, - scaleFactor, - onSelectFilter, - editorImage, - filterKey, - ) { - return WhatsAppFilterBtn( - filter: filter, - isSelected: isSelected, - onSelectFilter: () { - onSelectFilter.call(); - _editor!.setState(() {}); - }, - editorImage: editorImage, - filterKey: filterKey, - scaleFactor: scaleFactor, - ); - }, + stickerEditor: StickerEditorConfigs( + enabled: true, + buildStickers: (setLayer, scrollController) => + DemoBuildStickers( + setLayer: setLayer, scrollController: scrollController), ), - ), - ), + layerInteraction: const LayerInteractionConfigs( + style: LayerInteractionStyle( + removeAreaBackgroundInactive: Colors.black12, + ), + ), + helperLines: const HelperLineConfigs( + style: HelperLineStyle( + horizontalColor: Color.fromARGB(255, 129, 218, 88), + verticalColor: Color.fromARGB(255, 129, 218, 88), + ), + )), ); }, ); } List _buildPaintEditorBody( - PaintingEditorState paintEditor, + PaintEditorState paintEditor, Stream rebuildStream, ) { return [ @@ -441,7 +446,7 @@ class _WhatsAppExampleState extends State onClose: editor.closeEditor, onTapCropRotateEditor: editor.openCropRotateEditor, onTapStickerEditor: () => openWhatsAppStickerEditor(editor), - onTapPaintEditor: editor.openPaintingEditor, + onTapPaintEditor: editor.openPaintEditor, onTapTextEditor: editor.openTextEditor, onTapUndo: editor.undoAction, canUndo: editor.canUndo, diff --git a/example/lib/pages/firebase_supabase_example.dart b/example/lib/pages/firebase_supabase_example.dart index 2bf09b0c..72f40fcb 100644 --- a/example/lib/pages/firebase_supabase_example.dart +++ b/example/lib/pages/firebase_supabase_example.dart @@ -1,6 +1,3 @@ -// Flutter imports: -// Project imports: -import 'package:example/utils/example_constants.dart'; // Package imports: import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/foundation.dart'; @@ -8,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; +import '../common/example_constants.dart'; import '../utils/example_helper.dart'; /// The Firebase-Supabase example @@ -25,6 +23,12 @@ class _FirebaseSupabaseExampleState extends State final _supabase = Supabase.instance.client; final String _path = 'your-storage-path/my-image-name.jpg'; + @override + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); + } + Future _uploadFirebase(Uint8List bytes) async { try { Reference ref = FirebaseStorage.instance.ref(_path); @@ -51,27 +55,10 @@ class _FirebaseSupabaseExampleState extends State @override Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.cloud_upload_outlined), - title: const Text('Firebase and Supabase'), - trailing: const Icon(Icons.chevron_right), - ); - } + if (!isPreCached) return const PrepareImageWidget(); - Widget _buildEditor() { return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: (bytes) async { @@ -87,10 +74,13 @@ class _FirebaseSupabaseExampleState extends State } setGenerationTime(); }, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + ), i18n: const I18n(doneLoadingMsg: 'Uploading image...'), ), ); diff --git a/example/lib/pages/frame_example.dart b/example/lib/pages/frame_example.dart index aeb452f2..6a6b8d57 100644 --- a/example/lib/pages/frame_example.dart +++ b/example/lib/pages/frame_example.dart @@ -5,7 +5,6 @@ import 'dart:math'; import 'dart:ui' as ui; // Flutter imports: -import 'package:example/pages/pick_image_example.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -18,6 +17,7 @@ import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: import '../utils/example_helper.dart'; import '../utils/pixel_transparent_painter.dart'; +import '../widgets/material_icon_button.dart'; /// The example for a frame around the images class FrameExample extends StatefulWidget { @@ -40,9 +40,14 @@ class _FrameExampleState extends State final _bottomTextStyle = const TextStyle(fontSize: 10.0, color: Colors.white); + Uint8List? _transparentBytes; + @override void initState() { _bottomBarScrollCtrl = ScrollController(); + preCacheImage(assetPath: _frameUrl); + _createTransparentBackgroundImage(); + super.initState(); } @@ -203,16 +208,18 @@ class _FrameExampleState extends State el.broken = true; } + /// To allow users to switch between multiple frames efficiently, + /// consider caching the image bytes. + await _createTransparentBackgroundImage(); + /// Set the background bounds editorKey.currentState!.editorImage = EditorImage( - /// To allow users to switch between multiple frames efficiently, - /// consider caching the image bytes. - byteArray: await _createTransparentBackgroundImage(), + byteArray: _transparentBytes, ); await editorKey.currentState!.decodeImage(); } - Future _createTransparentBackgroundImage() async { + Future _createTransparentBackgroundImage() async { Size frameSize = await _frameSize; double width = frameSize.width; double height = frameSize.height; @@ -232,7 +239,8 @@ class _FrameExampleState extends State // ignore: use_build_context_synchronously await precacheImage(MemoryImage(bytes), context); - return bytes; + _transparentBytes = bytes; + if (mounted) setState(() {}); } Future get _frameSize async { @@ -258,75 +266,45 @@ class _FrameExampleState extends State @override Widget build(BuildContext context) { - return ListTile( - onTap: () async { - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); - - var transparentBytes = await _createTransparentBackgroundImage(); - - if (!context.mounted) return; - - /// Important to precache the frame before we add it to the editor - await precacheImage(AssetImage(_frameUrl), context); - - LoadingDialog.instance.hide(); - - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - LayoutBuilder(builder: (context, constraints) { - return CustomPaint( - size: Size(constraints.maxWidth, constraints.maxHeight), - painter: const PixelTransparentPainter( - primary: Colors.white, - secondary: Color(0xFFE2E2E2), - ), - child: _buildEditor(transparentBytes, constraints), - ); - }), - ), - ); - }, - leading: const Icon(Icons.filter_frames_outlined), - title: const Text('Image inside a frame'), - trailing: const Icon(Icons.chevron_right), - ); + if (!isPreCached || _transparentBytes == null) { + return const PrepareImageWidget(); + } + + return LayoutBuilder(builder: (context, constraints) { + return CustomPaint( + size: Size(constraints.maxWidth, constraints.maxHeight), + painter: const PixelTransparentPainter( + primary: Colors.white, + secondary: Color(0xFFE2E2E2), + ), + child: _buildEditor(constraints), + ); + }); } - Widget _buildEditor(Uint8List transparentBytes, BoxConstraints constraints) { + Widget _buildEditor(BoxConstraints constraints) { return ProImageEditor.memory( - transparentBytes, + _transparentBytes!, key: editorKey, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + imageGeneration: const ImageGenerationConfigs( enableUseOriginalBytes: false, /// Optional set the output format to png. Default format is jpeg /// outputFormat: OutputFormat.png, ), - layerInteraction: const LayerInteraction( + layerInteraction: const LayerInteractionConfigs( selectable: LayerInteractionSelectable.disabled, ), - - /// Crop-Rotate, Filter, Tune and Blur editors are not supported - cropRotateEditorConfigs: - const CropRotateEditorConfigs(enabled: false), - filterEditorConfigs: const FilterEditorConfigs(enabled: false), - blurEditorConfigs: const BlurEditorConfigs(enabled: false), - customWidgets: ImageEditorCustomWidgets( - mainEditor: CustomWidgetsMainEditor( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + widgets: MainEditorWidgets( bodyItemsRecorded: (editor, rebuildStream) => [ _buildFrame(editor.sizesManager.bodySize, rebuildStream), ], @@ -339,54 +317,63 @@ class _FrameExampleState extends State ), ), ), - paintEditor: CustomWidgetsPaintEditor( - bodyItemsRecorded: (editor, rebuildStream) => [ - _buildFrame(editor.editorBodySize, rebuildStream), - ], - ), - // textEditor: CustomWidgetsTextEditor( - // bodyItems: (editor, rebuildStream) => [ - // _buildFrame(editor.editorBodySize, rebuildStream), - // ], - // ), - cropRotateEditor: CustomWidgetsCropRotateEditor( - bodyItems: (editor, rebuildStream) => [ - _buildFrame(editor.editorBodySize, rebuildStream), - ], - ), - tuneEditor: CustomWidgetsTuneEditor( - bodyItemsRecorded: (editor, rebuildStream) => [ - _buildFrame(editor.editorBodySize, rebuildStream), - ], + style: const MainEditorStyle( + background: Colors.transparent, + uiOverlayStyle: + SystemUiOverlayStyle(statusBarColor: Colors.black), ), - filterEditor: CustomWidgetsFilterEditor( + ), + paintEditor: PaintEditorConfigs( + widgets: PaintEditorWidgets( bodyItemsRecorded: (editor, rebuildStream) => [ _buildFrame(editor.editorBodySize, rebuildStream), ], ), - blurEditor: CustomWidgetsBlurEditor( - bodyItemsRecorded: (editor, rebuildStream) => [ - _buildFrame(editor.editorBodySize, rebuildStream), - ], + style: const PaintEditorStyle( + background: Colors.transparent, + uiOverlayStyle: + SystemUiOverlayStyle(statusBarColor: Colors.black), ), ), - imageEditorTheme: const ImageEditorTheme( - uiOverlayStyle: SystemUiOverlayStyle( - statusBarColor: Colors.black, - ), - background: Colors.transparent, - paintingEditor: PaintingEditorTheme(background: Colors.transparent), - - /// Optionally remove background - /// cropRotateEditor: - /// CropRotateEditorTheme(background: - /// Colors.transparent), - /// filterEditor: - /// FilterEditorTheme(background: Colors.transparent), - /// blurEditor: - /// BlurEditorTheme(background: Colors.transparent), + + /// Crop-Rotate, Filter, Tune and Blur editors are not supported + cropRotateEditor: const CropRotateEditorConfigs( + enabled: false, + + /// widgets: CropRotateEditorWidgets( + /// bodyItems: (editor, rebuildStream) => [ + /// _buildFrame(editor.editorBodySize, rebuildStream), + /// ], + /// ), + ), + filterEditor: const FilterEditorConfigs( + enabled: false, + + /// widgets: FilterEditorWidgets( + /// bodyItemsRecorded: (editor, rebuildStream) => [ + /// _buildFrame(editor.editorBodySize, rebuildStream), + /// ], + /// ), + ), + blurEditor: const BlurEditorConfigs( + enabled: false, + + /// widgets: BlurEditorWidgets( + /// bodyItemsRecorded: (editor, rebuildStream) => [ + /// _buildFrame(editor.editorBodySize, rebuildStream), + /// ], + /// ), + ), + tuneEditor: const TuneEditorConfigs( + enabled: false, + + /// widgets: TuneEditorWidgets( + /// bodyItemsRecorded: (editor, rebuildStream) => [ + /// _buildFrame(editor.editorBodySize, rebuildStream), + /// ], + /// ), ), - stickerEditorConfigs: StickerEditorConfigs( + stickerEditor: StickerEditorConfigs( enabled: false, initWidth: _layerInitWidth / _initScale, buildStickers: (setLayer, scrollController) { @@ -465,7 +452,7 @@ class _FrameExampleState extends State size: 22.0, color: Colors.white, ), - onPressed: editor.openPaintingEditor, + onPressed: editor.openPaintEditor, ), FlatIconTextButton( label: Text('Text', style: _bottomTextStyle), diff --git a/example/lib/pages/generation_configs_example.dart b/example/lib/pages/generation_configs_example.dart index 0648bbe4..feade7ac 100644 --- a/example/lib/pages/generation_configs_example.dart +++ b/example/lib/pages/generation_configs_example.dart @@ -36,21 +36,7 @@ class GenerationConfigsExample extends StatefulWidget { class _GenerationConfigsExampleState extends State { @override Widget build(BuildContext context) { - return ListTile( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const GenerationConfig(), - ), - ); - }, - leading: const Icon(Icons.memory_outlined), - title: const Text('Generation Configurations'), - subtitle: - const Text('Adjust output format, set processor usage, and more'), - trailing: const Icon(Icons.chevron_right), - ); + return const GenerationConfig(); } } @@ -156,7 +142,7 @@ class _GenerationConfigState extends State Widget _buildGroupHeader(String title) { return ListTile( - tileColor: const Color.fromARGB(255, 201, 201, 201), + tileColor: const ui.Color.fromARGB(255, 30, 31, 36), title: Text( title, style: const TextStyle( @@ -544,7 +530,7 @@ class _GenerationConfigState extends State ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: generationConfigs, + imageGeneration: generationConfigs, ), ); } diff --git a/example/lib/pages/google_font_example.dart b/example/lib/pages/google_font_example.dart index 2cebe4ce..a71b28e6 100644 --- a/example/lib/pages/google_font_example.dart +++ b/example/lib/pages/google_font_example.dart @@ -1,5 +1,3 @@ -// ignore_for_file: depend_on_referenced_packages - // Dart imports: import 'dart:io'; @@ -12,7 +10,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; +import '../common/example_constants.dart'; import '../utils/example_helper.dart'; /// The google font example @@ -26,39 +24,55 @@ class GoogleFontExample extends StatefulWidget { class _GoogleFontExampleState extends State with ExampleHelperState { + bool _ignorePlatformIssue = false; + @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.emoji_emotions_outlined), - title: const Text('Google-Font Emojis'), - subtitle: !kIsWeb && Platform.isWindows - ? const Text('Windows didn\'t support "GoogleFonts.notoColorEmoji".') - : null, - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!kIsWeb && Platform.isWindows && !_ignorePlatformIssue) { + return Scaffold( + appBar: AppBar(), + body: Column( + spacing: 16, + children: [ + ElevatedButton( + onPressed: () { + setState(() { + _ignorePlatformIssue = true; + }); + }, + child: const Text('Ignore Error'), + ), + Expanded( + child: ErrorWidget( + 'Windows didn\'t support "GoogleFonts.notoColorEmoji"', + ), + ), + ], + ), + ); + } else if (!isPreCached) { + return const PrepareImageWidget(); + } + return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - textEditorConfigs: TextEditorConfigs( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + ), + textEditor: TextEditorConfigs( showSelectFontStyleBottomBar: true, customTextStyles: [ GoogleFonts.roboto(), @@ -70,14 +84,13 @@ class _GoogleFontExampleState extends State GoogleFonts.nabla(), ], ), - imageEditorTheme: ImageEditorTheme( - emojiEditor: EmojiEditorTheme( - textStyle: DefaultEmojiTextStyle.copyWith( - fontFamily: GoogleFonts.notoColorEmoji().fontFamily, - ), - )), - emojiEditorConfigs: const EmojiEditorConfigs( + emojiEditor: EmojiEditorConfigs( checkPlatformCompatibility: false, + style: EmojiEditorStyle( + textStyle: DefaultEmojiTextStyle.copyWith( + fontFamily: GoogleFonts.notoColorEmoji().fontFamily, + ), + ), ), ), ); diff --git a/example/lib/pages/image_format_convert_example.dart b/example/lib/pages/image_format_convert_example.dart index 2dc25828..dcfd27c7 100644 --- a/example/lib/pages/image_format_convert_example.dart +++ b/example/lib/pages/image_format_convert_example.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; +import '../common/example_constants.dart'; import '../utils/example_helper.dart'; /// The image-format-convert example @@ -51,29 +51,17 @@ class _ImageFormatConvertExampleState extends State } @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.compare_outlined), - title: const Text('Change output format'), - subtitle: const Text('Choose the output format like jpg or png'), - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: (bytes) async { @@ -85,11 +73,14 @@ class _ImageFormatConvertExampleState extends State setGenerationTime(); }, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + ), + imageGeneration: const ImageGenerationConfigs( /// Choose the output format below outputFormat: kIsWeb ? OutputFormat.png : OutputFormat.tiff, pngFilter: PngFilter.none, diff --git a/example/lib/pages/import_export_example.dart b/example/lib/pages/import_export_example.dart index 2e8d075b..ac7d939a 100644 --- a/example/lib/pages/import_export_example.dart +++ b/example/lib/pages/import_export_example.dart @@ -1,4 +1,5 @@ // Flutter imports: +import 'package:example/common/example_constants.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -7,7 +8,6 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; import '../utils/example_helper.dart'; import '../utils/import_history_demo_data.dart'; @@ -23,63 +23,34 @@ class ImportExportExample extends StatefulWidget { class _ImportExportExampleState extends State with ExampleHelperState { @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.import_export_outlined), - title: const Text('Import and Export state history'), - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return Stack( children: [ ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: editorKey, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => + onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( - imageGenerationConfigs: const ImageGenerationConfigs( - generateImageInBackground: false, - ), - designMode: platformDesignMode, - imageEditorTheme: ImageEditorTheme( - emojiEditor: kIsWeb - ? EmojiEditorTheme( - textStyle: DefaultEmojiTextStyle.copyWith( - fontFamily: GoogleFonts.notoColorEmoji().fontFamily, - ), - ) - : const EmojiEditorTheme(), - ), - emojiEditorConfigs: const EmojiEditorConfigs( - checkPlatformCompatibility: !kIsWeb, - ), - stateHistoryConfigs: StateHistoryConfigs( - initStateHistory: ImportStateHistory.fromMap( - importHistoryDemoData, - configs: const ImportEditorConfigs( - recalculateSizeAndPosition: true, - ), - ), - ), - customWidgets: - ImageEditorCustomWidgets(mainEditor: CustomWidgetsMainEditor( + imageGeneration: const ImageGenerationConfigs( + generateImageInBackground: false, + ), + designMode: platformDesignMode, + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + widgets: MainEditorWidgets( bodyItems: (editor, rebuildStream) { return [ ReactiveCustomWidget( @@ -115,7 +86,26 @@ class _ImportExportExampleState extends State stream: rebuildStream), ]; }, - ))), + ), + ), + emojiEditor: EmojiEditorConfigs( + checkPlatformCompatibility: !kIsWeb, + style: kIsWeb + ? EmojiEditorStyle( + textStyle: DefaultEmojiTextStyle.copyWith( + fontFamily: GoogleFonts.notoColorEmoji().fontFamily, + ), + ) + : const EmojiEditorStyle()), + stateHistory: StateHistoryConfigs( + initStateHistory: ImportStateHistory.fromMap( + importHistoryDemoData, + configs: const ImportEditorConfigs( + recalculateSizeAndPosition: true, + ), + ), + ), + ), ), ], ); diff --git a/example/lib/pages/movable_background_image.dart b/example/lib/pages/movable_background_image.dart index df75760a..f17378a4 100644 --- a/example/lib/pages/movable_background_image.dart +++ b/example/lib/pages/movable_background_image.dart @@ -5,7 +5,6 @@ import 'dart:math'; import 'dart:ui' as ui; // Flutter imports: -import 'package:example/pages/pick_image_example.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -18,6 +17,7 @@ import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: import '../utils/example_helper.dart'; import '../utils/pixel_transparent_painter.dart'; +import '../widgets/material_icon_button.dart'; import 'reorder_layer_example.dart'; /// The example for movableBackground @@ -34,16 +34,24 @@ class _MovableBackgroundImageExampleState extends State with ExampleHelperState { late final ScrollController _bottomBarScrollCtrl; - late Uint8List _transparentBytes; + Uint8List? _transparentBytes; double _transparentAspectRatio = -1; + final String _imageUrl = + 'https://picsum.photos/id/${Random().nextInt(200)}/2000'; + /// Better sense of scale when we start with a large number final double _initScale = 20; + /// set the aspect ratio from your image. + final double _imgRatio = 1; + final _bottomTextStyle = const TextStyle(fontSize: 10.0, color: Colors.white); @override void initState() { + preCacheImage(networkUrl: _imageUrl); + _createTransparentImage(_imgRatio); _bottomBarScrollCtrl = ScrollController(); super.initState(); } @@ -233,204 +241,164 @@ class _MovableBackgroundImageExampleState @override Widget build(BuildContext context) { - return ListTile( - onTap: () async { - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); - double imgRatio = 1; // set the aspect ratio from your image. - - await _createTransparentImage(_editorSize.aspectRatio); - - if (!context.mounted) return; - - String imageUrl = - 'https://picsum.photos/id/${Random().nextInt(200)}/2000'; - await precacheImage(NetworkImage(imageUrl), context); - - LoadingDialog.instance.hide(); + if (_transparentBytes == null || !isPreCached) { + return const PrepareImageWidget(); + } - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - LayoutBuilder(builder: (context, constraints) { - return CustomPaint( - size: Size(constraints.maxWidth, constraints.maxHeight), - painter: const PixelTransparentPainter( - primary: Colors.white, - secondary: Color(0xFFE2E2E2), - ), - child: ProImageEditor.memory( - _transparentBytes, - key: editorKey, - callbacks: ProImageEditorCallbacks( - onImageEditingStarted: onImageEditingStarted, - onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, - mainEditorCallbacks: MainEditorCallbacks( - onAfterViewInit: () { - editorKey.currentState!.addLayer( - StickerLayerData( - offset: Offset.zero, - scale: _initScale, - sticker: Image.network( - imageUrl, - width: _editorSize.width, - height: _editorSize.height, - fit: BoxFit.cover, - loadingBuilder: - (context, child, loadingProgress) { - return AnimatedSwitcher( - layoutBuilder: - (currentChild, previousChildren) { - return SizedBox( - width: 120, - height: 120, - child: Stack( - fit: StackFit.expand, - alignment: Alignment.center, - children: [ - ...previousChildren, - if (currentChild != null) - currentChild, - ], - ), - ); - }, - duration: const Duration(milliseconds: 200), - child: loadingProgress == null - ? child - : Center( - child: CircularProgressIndicator( - value: loadingProgress - .expectedTotalBytes != - null - ? loadingProgress - .cumulativeBytesLoaded / - loadingProgress - .expectedTotalBytes! - : null, - ), - ), - ); - }, - ), - ), + return LayoutBuilder(builder: (context, constraints) { + return CustomPaint( + size: Size(constraints.maxWidth, constraints.maxHeight), + painter: const PixelTransparentPainter( + primary: Colors.white, + secondary: Color(0xFFE2E2E2), + ), + child: ProImageEditor.memory( + _transparentBytes!, + key: editorKey, + callbacks: ProImageEditorCallbacks( + onImageEditingStarted: onImageEditingStarted, + onImageEditingComplete: onImageEditingComplete, + onCloseEditor: () => + onCloseEditor(enablePop: !isDesktopMode(context)), + mainEditorCallbacks: MainEditorCallbacks( + onAfterViewInit: () { + editorKey.currentState!.addLayer( + StickerLayerData( + offset: Offset.zero, + scale: _initScale, + sticker: Image.network( + _imageUrl, + width: _editorSize.width, + height: _editorSize.height, + fit: BoxFit.cover, + loadingBuilder: (context, child, loadingProgress) { + return AnimatedSwitcher( + layoutBuilder: (currentChild, previousChildren) { + return SizedBox( + width: 120, + height: 120, + child: Stack( + fit: StackFit.expand, + alignment: Alignment.center, + children: [ + ...previousChildren, + if (currentChild != null) currentChild, + ], + ), + ); + }, + duration: const Duration(milliseconds: 200), + child: loadingProgress == null + ? child + : Center( + child: CircularProgressIndicator( + value: loadingProgress.expectedTotalBytes != + null + ? loadingProgress + .cumulativeBytesLoaded / + loadingProgress.expectedTotalBytes! + : null, + ), + ), ); }, ), ), - configs: ProImageEditorConfigs( - designMode: platformDesignMode, - imageGenerationConfigs: ImageGenerationConfigs( - captureOnlyDrawingBounds: true, - captureOnlyBackgroundImageArea: false, - outputFormat: OutputFormat.png, - - /// Set the pixel ratio manually. You can also set this - /// value higher than the device pixel ratio for higher - /// quality. - customPixelRatio: max( - 2000 / MediaQuery.of(context).size.width, - MediaQuery.of(context).devicePixelRatio), - ), - - /// Crop-Rotate, Filter and Blur editors are not supported - cropRotateEditorConfigs: - const CropRotateEditorConfigs(enabled: false), - filterEditorConfigs: - const FilterEditorConfigs(enabled: false), - blurEditorConfigs: - const BlurEditorConfigs(enabled: false), - customWidgets: ImageEditorCustomWidgets( - mainEditor: CustomWidgetsMainEditor( - bodyItems: (editor, rebuildStream) { - return [ - ReactiveCustomWidget( - stream: rebuildStream, - builder: (_) => editor.selectedLayerIndex >= - 0 || - editor.isSubEditorOpen - ? const SizedBox.shrink() - : Positioned( - bottom: 20, - left: 0, - child: Container( - decoration: BoxDecoration( - color: Colors.lightBlue.shade200, - borderRadius: - const BorderRadius.only( - topRight: Radius.circular(100), - bottomRight: Radius.circular(100), - ), - ), - child: IconButton( - onPressed: () => - _openReorderSheet(editor), - icon: const Icon( - Icons.reorder, - color: Colors.white, - ), - ), - ), - ), + ); + }, + ), + ), + configs: ProImageEditorConfigs( + designMode: platformDesignMode, + imageGeneration: ImageGenerationConfigs( + captureOnlyDrawingBounds: true, + captureOnlyBackgroundImageArea: false, + outputFormat: OutputFormat.png, + + /// Set the pixel ratio manually. You can also set this + /// value higher than the device pixel ratio for higher + /// quality. + customPixelRatio: max(2000 / MediaQuery.of(context).size.width, + MediaQuery.of(context).devicePixelRatio), + ), + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + widgets: MainEditorWidgets( + bodyItems: (editor, rebuildStream) { + return [ + ReactiveCustomWidget( + stream: rebuildStream, + builder: (_) => editor.selectedLayerIndex >= 0 || + editor.isSubEditorOpen + ? const SizedBox.shrink() + : Positioned( + bottom: 20, + left: 0, + child: Container( + decoration: BoxDecoration( + color: Colors.lightBlue.shade200, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(100), + bottomRight: Radius.circular(100), + ), + ), + child: IconButton( + onPressed: () => _openReorderSheet(editor), + icon: const Icon( + Icons.reorder, + color: Colors.white, + ), + ), ), - ]; - }, - bottomBar: (editor, rebuildStream, key) => - ReactiveCustomWidget( - stream: rebuildStream, - key: key, - builder: (_) => _bottomNavigationBar( - editor, - constraints, ), - ), - ), - ), - imageEditorTheme: const ImageEditorTheme( - uiOverlayStyle: SystemUiOverlayStyle( - statusBarColor: Colors.black, - ), - background: Colors.transparent, - paintingEditor: - PaintingEditorTheme(background: Colors.transparent), - - /// Optionally remove background - /// cropRotateEditor: - /// CropRotateEditorTheme(background: - /// Colors.transparent), - /// filterEditor: - /// FilterEditorTheme(background: Colors.transparent), - /// blurEditor: - /// BlurEditorTheme(background: Colors.transparent), - ), - stickerEditorConfigs: StickerEditorConfigs( - enabled: false, - initWidth: (_editorSize.aspectRatio > imgRatio - ? _editorSize.height - : _editorSize.width) / - _initScale, - buildStickers: (setLayer, scrollController) { - // Optionally your code to pick layers - return const SizedBox(); - }, - )), + ), + ]; + }, + bottomBar: (editor, rebuildStream, key) => ReactiveCustomWidget( + stream: rebuildStream, + key: key, + builder: (_) => _bottomNavigationBar( + editor, + constraints, + ), + ), + ), + style: const MainEditorStyle( + uiOverlayStyle: SystemUiOverlayStyle( + statusBarColor: Colors.black, ), - ); - }), + background: Colors.transparent, + ), + ), + paintEditor: const PaintEditorConfigs( + style: PaintEditorStyle( + uiOverlayStyle: SystemUiOverlayStyle( + statusBarColor: Colors.black, + ), + background: Colors.transparent, + ), + ), + + /// Crop-Rotate, Filter and Blur editors are not supported + cropRotateEditor: const CropRotateEditorConfigs(enabled: false), + filterEditor: const FilterEditorConfigs(enabled: false), + blurEditor: const BlurEditorConfigs(enabled: false), + + stickerEditor: StickerEditorConfigs( + enabled: false, + initWidth: (_editorSize.aspectRatio > _imgRatio + ? _editorSize.height + : _editorSize.width) / + _initScale, + buildStickers: (setLayer, scrollController) { + // Optionally your code to pick layers + return const SizedBox(); + }, + ), ), - ); - }, - leading: const Icon(Icons.pan_tool_alt_outlined), - title: const Text('Movable background image'), - subtitle: const Text('Includes how to add multiple images.'), - trailing: const Icon(Icons.chevron_right), - ); + ), + ); + }); } Widget _bottomNavigationBar( @@ -477,7 +445,7 @@ class _MovableBackgroundImageExampleState size: 22.0, color: Colors.white, ), - onPressed: editor.openPaintingEditor, + onPressed: editor.openPaintEditor, ), FlatIconTextButton( label: Text('Text', style: _bottomTextStyle), diff --git a/example/lib/pages/pick_image_example.dart b/example/lib/pages/pick_image_example.dart index 8053399d..e72cef79 100644 --- a/example/lib/pages/pick_image_example.dart +++ b/example/lib/pages/pick_image_example.dart @@ -1,9 +1,7 @@ // Dart imports: import 'dart:io'; -import 'dart:math'; // Flutter imports: -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -25,6 +23,9 @@ class PickImageExample extends StatefulWidget { class _PickImageExampleState extends State with ExampleHelperState { + final bool _cameraIsSupported = + kIsWeb || (!Platform.isWindows && !Platform.isLinux && !Platform.isMacOS); + void _openPicker(ImageSource source) async { final ImagePicker picker = ImagePicker(); final XFile? image = await picker.pickImage(source: source); @@ -46,10 +47,6 @@ class _PickImageExampleState extends State } if (!mounted) return; - if (kIsWeb || - (!Platform.isWindows && !Platform.isLinux && !Platform.isMacOS)) { - Navigator.pop(context); - } await Navigator.push( context, @@ -59,109 +56,33 @@ class _PickImageExampleState extends State ); } - void _chooseCameraOrGallery() async { - /// Open directly the gallery if the camera is not supported - if (!kIsWeb && - (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) { - _openPicker(ImageSource.gallery); - return; - } - - if (!kIsWeb && Platform.isIOS) { - await showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => CupertinoTheme( - data: const CupertinoThemeData(), - child: CupertinoActionSheet( - actions: [ - CupertinoActionSheetAction( - onPressed: () => _openPicker(ImageSource.camera), - child: const Wrap( - spacing: 7, - runAlignment: WrapAlignment.center, - children: [ - Icon(CupertinoIcons.photo_camera), - Text('Camera'), - ], - ), - ), - CupertinoActionSheetAction( - onPressed: () => _openPicker(ImageSource.gallery), - child: const Wrap( - spacing: 7, - runAlignment: WrapAlignment.center, - children: [ - Icon(CupertinoIcons.photo), - Text('Gallery'), - ], - ), - ), - ], - cancelButton: CupertinoActionSheetAction( - isDefaultAction: true, - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Cancel'), - ), - ), - ), - ); - } else { - await showModalBottomSheet( - context: context, - showDragHandle: true, - constraints: BoxConstraints( - minWidth: min(MediaQuery.of(context).size.width, 360), - ), - builder: (context) { - return Material( - color: Colors.transparent, - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.only(bottom: 24, left: 16, right: 16), - child: Wrap( - spacing: 45, - runSpacing: 30, - crossAxisAlignment: WrapCrossAlignment.center, - runAlignment: WrapAlignment.center, - alignment: WrapAlignment.spaceAround, - children: [ - MaterialIconActionButton( - primaryColor: const Color(0xFFEC407A), - secondaryColor: const Color(0xFFD3396D), - icon: Icons.photo_camera, - text: 'Camera', - onTap: () => _openPicker(ImageSource.camera), - ), - MaterialIconActionButton( - primaryColor: const Color(0xFFBF59CF), - secondaryColor: const Color(0xFFAC44CF), - icon: Icons.image, - text: 'Gallery', - onTap: () => _openPicker(ImageSource.gallery), - ), - ], - ), - ), - ), - ); - }, - ); - } - } - @override Widget build(BuildContext context) { - return ListTile( - onTap: _chooseCameraOrGallery, - leading: const Icon(Icons.attachment_outlined), - title: const Text('Pick from Gallery or Camera'), - subtitle: !kIsWeb && - (Platform.isWindows || Platform.isLinux || Platform.isMacOS) - ? const Text('The camera is not supported on this platform.') - : null, - trailing: const Icon(Icons.chevron_right), + return Scaffold( + appBar: AppBar( + title: const Text('Pick from gallery or camera'), + ), + body: ListView( + children: [ + ListTile( + onTap: _cameraIsSupported + ? () => _openPicker(ImageSource.camera) + : null, + leading: const Icon(Icons.photo_camera_outlined), + title: const Text('Open with camera'), + subtitle: _cameraIsSupported + ? null + : const Text('The camera is not supported on this platform.'), + trailing: const Icon(Icons.chevron_right), + ), + ListTile( + onTap: () => _openPicker(ImageSource.gallery), + leading: const Icon(Icons.image_outlined), + title: const Text('Open from gallery'), + trailing: const Icon(Icons.chevron_right), + ), + ], + ), ); } @@ -193,127 +114,3 @@ class _PickImageExampleState extends State } } } - -/// A stateless widget that displays a material-styled icon button with a custom -/// circular background, half of which is a secondary color. Below the icon, -/// a label text is displayed. -/// -/// The [MaterialIconActionButton] widget requires a primary color, secondary -/// color, icon, text, and a callback function to handle taps. -/// -/// Example usage: -/// ```dart -/// MaterialIconActionButton( -/// primaryColor: Colors.blue, -/// secondaryColor: Colors.green, -/// icon: Icons.camera, -/// text: 'Camera', -/// onTap: () { -/// // Handle tap action -/// }, -/// ); -/// ``` -class MaterialIconActionButton extends StatelessWidget { - /// Creates a new [MaterialIconActionButton] widget. - /// - /// The [primaryColor] is the color of the circular background, while the - /// [secondaryColor] is used for the half-circle overlay. The [icon] is the - /// icon to display in the center, and [text] is the label displayed below - /// the icon. The [onTap] callback is triggered when the button is tapped. - const MaterialIconActionButton({ - super.key, - required this.primaryColor, - required this.secondaryColor, - required this.icon, - required this.text, - required this.onTap, - }); - - /// The primary color for the button's background. - final Color primaryColor; - - /// The secondary color for the half-circle overlay. - final Color secondaryColor; - - /// The icon to display in the center of the button. - final IconData icon; - - /// The label displayed below the icon. - final String text; - - /// The callback function triggered when the button is tapped. - final VoidCallback onTap; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 65, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - InkWell( - borderRadius: BorderRadius.circular(60), - onTap: onTap, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: primaryColor, - borderRadius: BorderRadius.circular(100), - ), - ), - CustomPaint( - painter: CircleHalf(secondaryColor), - size: const Size(60, 60), - ), - Icon(icon, color: Colors.white), - ], - ), - ), - const SizedBox(height: 7), - Text( - text, - overflow: TextOverflow.ellipsis, - maxLines: 1, - textAlign: TextAlign.center, - ), - ], - ), - ); - } -} - -/// A custom painter class that paints a half-circle. -/// -/// The [CircleHalf] class takes a [color] parameter and paints half of a circle -/// on a canvas, typically used as an overlay for the -/// [MaterialIconActionButton]. -class CircleHalf extends CustomPainter { - /// Creates a new [CircleHalf] painter with the given [color]. - CircleHalf(this.color); - - /// The color to use for painting the half-circle. - final Color color; - - @override - void paint(Canvas canvas, Size size) { - Paint paint = Paint()..color = color; - canvas.drawArc( - Rect.fromCenter( - center: Offset(size.height / 2, size.width / 2), - height: size.height, - width: size.width, - ), - pi, - pi, - false, - paint, - ); - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) => false; -} diff --git a/example/lib/pages/preview_img.dart b/example/lib/pages/preview_img.dart index c49e5fb1..b647ee8e 100644 --- a/example/lib/pages/preview_img.dart +++ b/example/lib/pages/preview_img.dart @@ -136,7 +136,7 @@ class _PreviewImgPageState extends State { }); } return Theme( - data: ThemeData.dark(), + data: Theme.of(context), child: Scaffold( appBar: AppBar( title: const Text('Result'), diff --git a/example/lib/pages/reorder_layer_example.dart b/example/lib/pages/reorder_layer_example.dart index df8dbdce..85978b23 100644 --- a/example/lib/pages/reorder_layer_example.dart +++ b/example/lib/pages/reorder_layer_example.dart @@ -1,4 +1,5 @@ // Flutter imports: +import 'package:example/common/example_constants.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -6,7 +7,6 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; import '../utils/example_helper.dart'; /// A widget that demonstrates the ability to reorder layers within a UI. @@ -38,38 +38,31 @@ class ReorderLayerExample extends StatefulWidget { class _ReorderLayerExampleState extends State with ExampleHelperState { @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.sort), - title: const Text('Reorder layer level'), - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: editorKey, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( + helperLines: const HelperLineConfigs( + hitVibration: false, + ), designMode: platformDesignMode, - customWidgets: ImageEditorCustomWidgets( - mainEditor: CustomWidgetsMainEditor( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + widgets: MainEditorWidgets( bodyItems: (editor, rebuildStream) { return [ ReactiveCustomWidget( @@ -198,17 +191,17 @@ class _ReorderLayerSheetState extends State { (layer as EmojiLayerData).emoji, style: const TextStyle(fontSize: 24), ) - : layer.runtimeType == PaintingLayerData + : layer.runtimeType == PaintLayerData ? SizedBox( height: 40, child: FittedBox( alignment: Alignment.centerLeft, child: CustomPaint( - size: (layer as PaintingLayerData).size, + size: (layer as PaintLayerData).size, willChange: true, isComplex: layer.item.mode == PaintModeE.freeStyle, - painter: DrawPainting( + painter: DrawPaintItem( item: layer.item, scale: layer.scale, enabledHitDetection: false, diff --git a/example/lib/pages/round_cropper_example.dart b/example/lib/pages/round_cropper_example.dart index 05a80e76..c70178a6 100644 --- a/example/lib/pages/round_cropper_example.dart +++ b/example/lib/pages/round_cropper_example.dart @@ -1,11 +1,11 @@ // Flutter imports: +import 'package:example/common/example_constants.dart'; import 'package:flutter/material.dart'; // Package imports: import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; import '../utils/example_helper.dart'; /// The example how to use the round cropper @@ -22,55 +22,33 @@ class _RoundCropperExampleState extends State final _cropRotateEditorKey = GlobalKey(); @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - - bool initialized = false; + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - LayoutBuilder(builder: (context, constraints) { - if (!initialized) { - initialized = true; - Future.delayed(const Duration(milliseconds: 1), () { - _cropRotateEditorKey.currentState!.enableFakeHero = true; - setState(() {}); - }); - } - return _buildEditor(); - }), - ), - ); - }, - leading: const Icon(Icons.supervised_user_circle_outlined), - title: const Text('Round Cropper'), - trailing: const Icon(Icons.chevron_right), - ); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return CropRotateEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: _cropRotateEditorKey, initConfigs: CropRotateEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), convertToUint8List: true, onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), + enableCloseButton: !isDesktopMode(context), configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + imageGeneration: const ImageGenerationConfigs( outputFormat: OutputFormat.png, pngFilter: PngFilter.average, ), - cropRotateEditorConfigs: const CropRotateEditorConfigs( + cropRotateEditor: const CropRotateEditorConfigs( roundCropper: true, canChangeAspectRatio: false, initAspectRatio: 1, diff --git a/example/lib/pages/selectable_layer_example.dart b/example/lib/pages/selectable_layer_example.dart index 6af07220..5b396d15 100644 --- a/example/lib/pages/selectable_layer_example.dart +++ b/example/lib/pages/selectable_layer_example.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; +import '../common/example_constants.dart'; import '../utils/example_helper.dart'; /// A widget that demonstrates a selectable layer functionality. @@ -37,44 +37,34 @@ class SelectableLayerExample extends StatefulWidget { class _SelectableLayerExampleState extends State with ExampleHelperState { @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.select_all_outlined), - title: const Text('Selectable layer'), - subtitle: const Text( - 'When you click on a layer, it will show interaction buttons.'), - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: editorKey, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + ), + imageGeneration: const ImageGenerationConfigs( processorConfigs: ProcessorConfigs( processorMode: ProcessorMode.auto, ), ), - layerInteraction: const LayerInteraction( + layerInteraction: const LayerInteractionConfigs( /// Choose between `auto`, `enabled` and `disabled`. /// /// Mode `auto`: @@ -84,9 +74,12 @@ class _SelectableLayerExampleState extends State /// otherwise, the layer is not selectable. selectable: LayerInteractionSelectable.enabled, initialSelected: true, - ), - imageEditorTheme: const ImageEditorTheme( - layerInteraction: ThemeLayerInteraction( + icons: LayerInteractionIcons( + remove: Icons.clear, + edit: Icons.edit_outlined, + rotateScale: Icons.sync, + ), + style: LayerInteractionStyle( buttonRadius: 10, strokeWidth: 1.2, borderElementWidth: 7, @@ -100,13 +93,6 @@ class _SelectableLayerExampleState extends State showTooltips: false, ), ), - icons: const ImageEditorIcons( - layerInteraction: IconsLayerInteraction( - remove: Icons.clear, - edit: Icons.edit_outlined, - rotateScale: Icons.sync, - ), - ), i18n: const I18n( layerInteraction: I18nLayerInteraction( remove: 'Remove', diff --git a/example/lib/pages/signature_drawing_example.dart b/example/lib/pages/signature_drawing_example.dart index 0a18cd5e..38cd32bd 100644 --- a/example/lib/pages/signature_drawing_example.dart +++ b/example/lib/pages/signature_drawing_example.dart @@ -37,125 +37,103 @@ class _SignatureDrawingExampleState extends State with ExampleHelperState { @override Widget build(BuildContext context) { - return ListTile( - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext _) { - return ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 20), - children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text('Mode', - style: - TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), - ), - const Divider(), - ListTile( - leading: const Icon(Icons.draw_outlined), - title: const Text('Signature'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PaintingEditor.drawing( - initConfigs: PaintEditorInitConfigs( - theme: ThemeData.dark(), - convertToUint8List: true, - onImageEditingStarted: onImageEditingStarted, - onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, - configs: ProImageEditorConfigs( - designMode: platformDesignMode, - imageEditorTheme: const ImageEditorTheme( - background: Colors.white, - paintingEditor: PaintingEditorTheme( - initialColor: Colors.black, - ), - ), - paintEditorConfigs: const PaintEditorConfigs( - hasOptionFreeStyle: false, - hasOptionArrow: false, - hasOptionLine: false, - hasOptionRect: false, - hasOptionCircle: false, - hasOptionDashLine: false, - canToggleFill: false, + return Scaffold( + appBar: AppBar( + title: const Text('Signature and Drawing'), + ), + body: ListView( + shrinkWrap: true, + padding: const EdgeInsets.symmetric(vertical: 20), + children: [ + ListTile( + leading: const Icon(Icons.draw_outlined), + title: const Text('Signature'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PaintEditor.drawing( + initConfigs: PaintEditorInitConfigs( + theme: Theme.of(context), + convertToUint8List: true, + onImageEditingStarted: onImageEditingStarted, + onImageEditingComplete: onImageEditingComplete, + onCloseEditor: onCloseEditor, + configs: ProImageEditorConfigs( + designMode: platformDesignMode, + paintEditor: PaintEditorConfigs( + hasOptionFreeStyle: false, + hasOptionArrow: false, + hasOptionLine: false, + hasOptionRect: false, + hasOptionCircle: false, + hasOptionDashLine: false, + canToggleFill: false, - /// Optional true - canChangeLineWidth: true, - ), - imageGenerationConfigs: ImageGenerationConfigs( - outputFormat: OutputFormat.png, - customPixelRatio: - MediaQuery.of(context).devicePixelRatio, - maxOutputSize: const Size(2000, 2000), - ), - customWidgets: ImageEditorCustomWidgets( - paintEditor: CustomWidgetsPaintEditor( - colorPicker: (paintEditor, rebuildStream, - currentColor, setColor) => - null, - ), - ), - ), + /// Optional true + canChangeLineWidth: true, + widgets: PaintEditorWidgets( + colorPicker: (paintEditor, rebuildStream, + currentColor, setColor) => + null, + ), + style: const PaintEditorStyle( + background: Colors.white, + initialColor: Colors.black, ), ), + imageGeneration: ImageGenerationConfigs( + outputFormat: OutputFormat.png, + customPixelRatio: + MediaQuery.of(context).devicePixelRatio, + maxOutputSize: const Size(2000, 2000), + ), ), - ); - }, + ), + ), ), - ListTile( - leading: const Icon(Icons.brush_outlined), - title: const Text('Drawing'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PaintingEditor.drawing( - initConfigs: PaintEditorInitConfigs( - theme: Theme.of(context), - convertToUint8List: true, - onImageEditingStarted: onImageEditingStarted, - onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, - configs: ProImageEditorConfigs( - designMode: platformDesignMode, - imageEditorTheme: const ImageEditorTheme( - background: Colors.white, - paintingEditor: PaintingEditorTheme( - initialColor: Colors.black, - ), - ), - imageGenerationConfigs: ImageGenerationConfigs( - outputFormat: OutputFormat.png, - customPixelRatio: - MediaQuery.of(context).devicePixelRatio, - maxOutputSize: const Size(2000, 2000), - ), - ), + ); + }, + ), + ListTile( + leading: const Icon(Icons.brush_outlined), + title: const Text('Drawing'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PaintEditor.drawing( + initConfigs: PaintEditorInitConfigs( + theme: Theme.of(context), + convertToUint8List: true, + onImageEditingStarted: onImageEditingStarted, + onImageEditingComplete: onImageEditingComplete, + onCloseEditor: onCloseEditor, + configs: ProImageEditorConfigs( + designMode: platformDesignMode, + paintEditor: const PaintEditorConfigs( + style: PaintEditorStyle( + background: Colors.white, + initialColor: Colors.black, ), ), + imageGeneration: ImageGenerationConfigs( + outputFormat: OutputFormat.png, + customPixelRatio: + MediaQuery.of(context).devicePixelRatio, + maxOutputSize: const Size(2000, 2000), + ), ), - ); - }, + ), + ), ), - ], - ); - }, - ); - }, - leading: const Icon(Icons.gesture_outlined), - title: const Text('Signature or Drawing'), - trailing: const Icon(Icons.chevron_right), + ); + }, + ), + ], + ), ); } } diff --git a/example/lib/pages/standalone_example.dart b/example/lib/pages/standalone_example.dart index 4e9a9b88..53ef2c28 100644 --- a/example/lib/pages/standalone_example.dart +++ b/example/lib/pages/standalone_example.dart @@ -1,11 +1,11 @@ // Flutter imports: +import 'package:example/common/example_constants.dart'; import 'package:flutter/material.dart'; // Package imports: import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: -import '../utils/example_constants.dart'; import '../utils/example_helper.dart'; /// A widget that demonstrates a standalone feature or functionality. @@ -38,135 +38,106 @@ class _StandaloneExampleState extends State @override Widget build(BuildContext context) { - return ListTile( - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext _) { - return ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 20), - children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text('Editor', - style: - TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), - ), - const Divider(), - ListTile( - leading: const Icon(Icons.edit_outlined), - title: const Text('Painting-Editor'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildPaintingEditor()), - ); - }, - ), - ListTile( - leading: const Icon(Icons.crop_rotate_rounded), - title: const Text('Crop-Rotate-Editor'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; + return Scaffold( + appBar: AppBar( + title: const Text('Standalone-Editors'), + ), + body: ListView( + shrinkWrap: true, + padding: const EdgeInsets.symmetric(vertical: 20), + children: [ + ListTile( + leading: const Icon(Icons.edit_outlined), + title: const Text('Paint-Editor'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildPaintEditor()), + ); + }, + ), + ListTile( + leading: const Icon(Icons.crop_rotate_rounded), + title: const Text('Crop-Rotate-Editor'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; - bool initialized = false; + bool initialized = false; - await Navigator.of(context).push( - MaterialPageRoute(builder: (context) { - if (!initialized) { - initialized = true; - Future.delayed(const Duration(milliseconds: 1), () { - _cropRotateEditorKey.currentState!.enableFakeHero = - true; - setState(() {}); - }); - } - return _buildCropRotateEditor(); - }), - ); - }, - ), - ListTile( - leading: const Icon(Icons.filter), - title: const Text('Filter-Editor'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildFilterEditor()), - ); - }, - ), - ListTile( - leading: const Icon(Icons.tune_rounded), - title: const Text('Tune-Adjustment-Editor'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildTuneEditor()), - ); - }, - ), - ListTile( - leading: const Icon(Icons.blur_on), - title: const Text('Blur-Editor'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - Navigator.pop(context); - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), - context); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildBlurEditor()), - ); - }, - ), - ], - ); - }, - ); - }, - leading: const Icon(Icons.view_in_ar_outlined), - title: const Text('Standalone Sub-Editor'), - trailing: const Icon(Icons.chevron_right), + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) { + if (!initialized) { + initialized = true; + Future.delayed(const Duration(milliseconds: 1), () { + _cropRotateEditorKey.currentState!.enableFakeHero = true; + setState(() {}); + }); + } + return _buildCropRotateEditor(); + }), + ); + }, + ), + ListTile( + leading: const Icon(Icons.filter), + title: const Text('Filter-Editor'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildFilterEditor()), + ); + }, + ), + ListTile( + leading: const Icon(Icons.tune_rounded), + title: const Text('Tune-Adjustment-Editor'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildTuneEditor()), + ); + }, + ), + ListTile( + leading: const Icon(Icons.blur_on), + title: const Text('Blur-Editor'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + await precacheImage( + AssetImage(kImageEditorExampleAssetPath), context); + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => _buildBlurEditor()), + ); + }, + ), + ], + ), ); } - Widget _buildPaintingEditor() { - return PaintingEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + Widget _buildPaintEditor() { + return PaintEditor.asset( + kImageEditorExampleAssetPath, initConfigs: PaintEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), enableFakeHero: true, convertToUint8List: true, configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + imageGeneration: const ImageGenerationConfigs( /// If your users paint a lot in a short time, you should disable /// this flag because it will overload the isolated thread which @@ -182,14 +153,14 @@ class _StandaloneExampleState extends State Widget _buildCropRotateEditor() { return CropRotateEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, key: _cropRotateEditorKey, initConfigs: CropRotateEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), convertToUint8List: true, configs: ProImageEditorConfigs( designMode: platformDesignMode, - imageGenerationConfigs: const ImageGenerationConfigs( + imageGeneration: const ImageGenerationConfigs( /// If your users change a lot stuff in a short time, you should /// disable this flag because it will overload the isolated @@ -206,9 +177,9 @@ class _StandaloneExampleState extends State Widget _buildFilterEditor() { return FilterEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, initConfigs: FilterEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), convertToUint8List: true, onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, @@ -222,9 +193,9 @@ class _StandaloneExampleState extends State Widget _buildTuneEditor() { return TuneEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, initConfigs: TuneEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), convertToUint8List: true, onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, @@ -238,9 +209,9 @@ class _StandaloneExampleState extends State Widget _buildBlurEditor() { return BlurEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, + kImageEditorExampleAssetPath, initConfigs: BlurEditorInitConfigs( - theme: ThemeData.dark(), + theme: Theme.of(context), convertToUint8List: true, onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, diff --git a/example/lib/pages/stickers_example.dart b/example/lib/pages/stickers_example.dart index 020b59e3..7b2ffb50 100644 --- a/example/lib/pages/stickers_example.dart +++ b/example/lib/pages/stickers_example.dart @@ -35,41 +35,29 @@ class _StickersExampleState extends State final String _url = 'https://picsum.photos/id/176/2000'; @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - LoadingDialog.instance.show( - context, - configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), - ); - await precacheImage(NetworkImage(_url), context); - LoadingDialog.instance.hide(); - if (!context.mounted) return; - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.image_outlined), - title: const Text('Custom Stickers'), - trailing: const Icon(Icons.chevron_right), - ); + void initState() { + preCacheImage(networkUrl: _url); + super.initState(); } - Widget _buildEditor() { + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + return ProImageEditor.network( _url, callbacks: ProImageEditorCallbacks( onImageEditingStarted: onImageEditingStarted, onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), ), configs: ProImageEditorConfigs( designMode: platformDesignMode, - blurEditorConfigs: const BlurEditorConfigs(enabled: false), - stickerEditorConfigs: StickerEditorConfigs( + blurEditor: const BlurEditorConfigs(enabled: false), + mainEditor: MainEditorConfigs( + enableCloseButton: !isDesktopMode(context), + ), + stickerEditor: StickerEditorConfigs( enabled: true, buildStickers: (setLayer, scrollController) { return ClipRRect( @@ -94,7 +82,7 @@ class _StickersExampleState extends State LoadingDialog.instance.show( context, configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), + theme: Theme.of(context), ); await precacheImage( NetworkImage( diff --git a/example/lib/pages/zoom_example.dart b/example/lib/pages/zoom_example.dart new file mode 100644 index 00000000..bcde6d24 --- /dev/null +++ b/example/lib/pages/zoom_example.dart @@ -0,0 +1,80 @@ +// Flutter imports: +import 'package:flutter/material.dart'; + +// Package imports: +import 'package:pro_image_editor/pro_image_editor.dart'; + +// Project imports: +import '../common/example_constants.dart'; +import '../utils/example_helper.dart'; + +/// A widget that demonstrates zoom and move functionality within an editor. +/// +/// The [ZoomExample] widget is a stateful widget that provides an +/// example of how to implement zooming and moving features, likely within an +/// image editor or a similar application that requires user interaction for +/// manipulating content. +/// +/// This widget holds the state, and the state class +/// [_ZoomExampleState] +/// will contain the logic to handle zoom and move gestures. +/// +/// Example usage: +/// ```dart +/// ZoomExample(); +/// ``` +class ZoomExample extends StatefulWidget { + /// Creates a new [ZoomExample] widget. + const ZoomExample({super.key}); + + @override + State createState() => _ZoomExampleState(); +} + +class _ZoomExampleState extends State + with ExampleHelperState { + @override + void initState() { + preCacheImage(assetPath: kImageEditorExampleAssetPath); + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (!isPreCached) return const PrepareImageWidget(); + + return ProImageEditor.asset( + kImageEditorExampleAssetPath, + key: editorKey, + callbacks: ProImageEditorCallbacks( + onImageEditingStarted: onImageEditingStarted, + onImageEditingComplete: onImageEditingComplete, + onCloseEditor: () => onCloseEditor(enablePop: !isDesktopMode(context)), + ), + configs: ProImageEditorConfigs( + designMode: platformDesignMode, + mainEditor: MainEditorConfigs( + enableZoom: true, + editorMinScale: 0.8, + editorMaxScale: 5, + boundaryMargin: const EdgeInsets.all(100), + enableCloseButton: !isDesktopMode(context), + ), + paintEditor: const PaintEditorConfigs( + enableZoom: true, + editorMinScale: 0.8, + editorMaxScale: 5, + boundaryMargin: EdgeInsets.all(100), + icons: PaintEditorIcons( + moveAndZoom: Icons.pinch_outlined, + ), + ), + i18n: const I18n( + paintEditor: I18nPaintEditor( + moveAndZoom: 'Zoom', + ), + ), + ), + ); + } +} diff --git a/example/lib/pages/zoom_move_editor_example.dart b/example/lib/pages/zoom_move_editor_example.dart deleted file mode 100644 index a9aa8e6f..00000000 --- a/example/lib/pages/zoom_move_editor_example.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Flutter imports: -import 'package:flutter/material.dart'; -import 'package:pro_image_editor/models/editor_configs/main_editor_configs.dart'; - -// Package imports: -import 'package:pro_image_editor/pro_image_editor.dart'; - -// Project imports: -import '../utils/example_constants.dart'; -import '../utils/example_helper.dart'; - -/// A widget that demonstrates zoom and move functionality within an editor. -/// -/// The [ZoomMoveEditorExample] widget is a stateful widget that provides an -/// example of how to implement zooming and moving features, likely within an -/// image editor or a similar application that requires user interaction for -/// manipulating content. -/// -/// This widget holds the state, and the state class -/// [_ZoomMoveEditorExampleState] -/// will contain the logic to handle zoom and move gestures. -/// -/// Example usage: -/// ```dart -/// ZoomMoveEditorExample(); -/// ``` -class ZoomMoveEditorExample extends StatefulWidget { - /// Creates a new [ZoomMoveEditorExample] widget. - const ZoomMoveEditorExample({super.key}); - - @override - State createState() => _ZoomMoveEditorExampleState(); -} - -class _ZoomMoveEditorExampleState extends State - with ExampleHelperState { - @override - Widget build(BuildContext context) { - return ListTile( - onTap: () async { - await precacheImage( - AssetImage(ExampleConstants.of(context)!.demoAssetPath), context); - if (!context.mounted) return; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => _buildEditor(), - ), - ); - }, - leading: const Icon(Icons.zoom_in), - title: const Text('Zoom in Paint and Main Editor'), - trailing: const Icon(Icons.chevron_right), - ); - } - - Widget _buildEditor() { - return ProImageEditor.asset( - ExampleConstants.of(context)!.demoAssetPath, - key: editorKey, - callbacks: ProImageEditorCallbacks( - onImageEditingStarted: onImageEditingStarted, - onImageEditingComplete: onImageEditingComplete, - onCloseEditor: onCloseEditor, - ), - configs: ProImageEditorConfigs( - designMode: platformDesignMode, - mainEditorConfigs: const MainEditorConfigs( - enableZoom: true, - editorMinScale: 0.8, - editorMaxScale: 5, - boundaryMargin: EdgeInsets.all(100), - ), - paintEditorConfigs: const PaintEditorConfigs( - enableZoom: true, - editorMinScale: 0.8, - editorMaxScale: 5, - boundaryMargin: EdgeInsets.all(100), - ), - icons: const ImageEditorIcons( - paintingEditor: IconsPaintingEditor( - moveAndZoom: Icons.pinch_outlined, - ), - ), - i18n: const I18n( - paintEditor: I18nPaintingEditor( - moveAndZoom: 'Zoom', - ), - ), - ), - ); - } -} diff --git a/example/lib/utils/example_constants.dart b/example/lib/utils/example_constants.dart deleted file mode 100644 index 7f40f744..00000000 --- a/example/lib/utils/example_constants.dart +++ /dev/null @@ -1,43 +0,0 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - -/// A class that provides constant values like asset paths and network URLs -/// using [InheritedWidget], allowing them to be accessed anywhere in the -/// widget tree. -/// -/// The [ExampleConstants] widget can be accessed using the `of` method, which -/// retrieves the nearest instance of this widget up the widget tree. -class ExampleConstants extends InheritedWidget { - /// Creates an [ExampleConstants] widget. - /// - /// [child] is the widget subtree that can access the constants provided by - /// this class. - const ExampleConstants({ - super.key, - required super.child, - }); - - /// A path to a demo image asset in the project. - final String demoAssetPath = 'assets/demo.png'; - - /// A URL to a demo image hosted on a remote server. - final String demoNetworkUrl = 'https://picsum.photos/id/230/2000'; - - /// Retrieves the nearest [ExampleConstants] instance from the widget tree. - /// - /// This method allows other widgets to access the constants (like asset paths - /// and URLs) defined in this widget. Returns `null` if no [ExampleConstants] - /// instance is found. - static ExampleConstants? of(BuildContext context) { - return context.dependOnInheritedWidgetOfExactType(); - } - - /// Determines whether the widget should notify its dependents when it - /// updates. - /// - /// In this case, since the constants won't change, it always returns `false`. - @override - bool updateShouldNotify(ExampleConstants oldWidget) { - return false; - } -} diff --git a/example/lib/utils/example_helper.dart b/example/lib/utils/example_helper.dart index 5e24591b..9b75823c 100644 --- a/example/lib/utils/example_helper.dart +++ b/example/lib/utils/example_helper.dart @@ -9,8 +9,11 @@ import 'package:flutter/material.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; // Project imports: +import '../common/example_constants.dart'; import '../pages/preview_img.dart'; +export '../widgets/prepare_image_widget.dart'; + /// A mixin that provides helper methods and state management for image editing /// using the [ProImageEditor]. It is intended to be used in a [StatefulWidget]. mixin ExampleHelperState on State { @@ -26,6 +29,18 @@ mixin ExampleHelperState on State { /// Records the start time of the editing process. DateTime? startEditingTime; + /// Indicates whether image-resources are pre-cached. + bool isPreCached = true; + + /// Determines if the current layout should use desktop mode based on the + /// screen width. + /// + /// Returns `true` if the screen width is greater than or equal to + /// [kImageEditorExampleIsDesktopBreakPoint], otherwise `false`. + bool isDesktopMode(BuildContext context) => + MediaQuery.of(context).size.width >= + kImageEditorExampleIsDesktopBreakPoint; + /// Called when the image editing process starts. /// Records the time when editing began. Future onImageEditingStarted() async { @@ -61,6 +76,7 @@ mixin ExampleHelperState on State { /// The [generationConfigs] can be used to pass additional configurations for /// generating the image. void onCloseEditor({ + bool enablePop = true, bool showThumbnail = false, ui.Image? rawOriginalImage, final ImageGenerationConfigs? generationConfigs, @@ -93,7 +109,43 @@ mixin ExampleHelperState on State { }); } - // Close the editor if no image editing is done. - if (mounted) Navigator.pop(context); + if (mounted && enablePop) { + Navigator.pop(context); + } + } + + /// Preloads an image into memory to improve performance. + /// + /// Supports both asset and network images. Once the image is cached, it + /// updates the + /// [isPreCached] flag, triggers a widget rebuild, and optionally executes a + /// callback. + /// + /// Parameters: + /// - [assetPath]: The file path of the asset image to be cached. + /// - [networkUrl]: The URL of the network image to be cached. + /// - [onDone]: An optional callback executed after caching is complete. + /// + /// Ensures the widget is still mounted before performing operations. + void preCacheImage({ + String? assetPath, + String? networkUrl, + Function()? onDone, + }) { + isPreCached = false; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + precacheImage( + assetPath != null + ? AssetImage(assetPath) + : NetworkImage(networkUrl!), + context) + .whenComplete(() { + if (!mounted) return; + isPreCached = true; + setState(() {}); + onDone?.call(); + }); + }); } } diff --git a/example/lib/utils/import_history_demo_data.dart b/example/lib/utils/import_history_demo_data.dart index 96663755..a4d75b4f 100644 --- a/example/lib/utils/import_history_demo_data.dart +++ b/example/lib/utils/import_history_demo_data.dart @@ -130,7 +130,7 @@ Map importHistoryDemoData = { 'scale': 1.0, 'flipX': false, 'flipY': false, - 'type': 'painting', + 'type': 'paint', 'item': { 'mode': 'arrow', 'offsets': [ @@ -183,7 +183,7 @@ Map importHistoryDemoData = { 'scale': 1.0, 'flipX': false, 'flipY': false, - 'type': 'painting', + 'type': 'paint', 'item': { 'mode': 'arrow', 'offsets': [ @@ -282,7 +282,7 @@ Map importHistoryDemoData = { 'scale': 1.0, 'flipX': false, 'flipY': false, - 'type': 'painting', + 'type': 'paint', 'item': { 'mode': 'arrow', 'offsets': [ diff --git a/example/lib/widgets/demo_build_stickers.dart b/example/lib/widgets/demo_build_stickers.dart index f9311689..cedbf86b 100644 --- a/example/lib/widgets/demo_build_stickers.dart +++ b/example/lib/widgets/demo_build_stickers.dart @@ -161,7 +161,7 @@ class DemoBuildStickers extends StatelessWidget { LoadingDialog.instance.show( context, configs: const ProImageEditorConfigs(), - theme: ThemeData.dark(), + theme: Theme.of(context), ); await precacheImage(NetworkImage(url), context); diff --git a/example/lib/widgets/material_icon_button.dart b/example/lib/widgets/material_icon_button.dart new file mode 100644 index 00000000..2a0cfb2f --- /dev/null +++ b/example/lib/widgets/material_icon_button.dart @@ -0,0 +1,127 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +/// A stateless widget that displays a material-styled icon button with a custom +/// circular background, half of which is a secondary color. Below the icon, +/// a label text is displayed. +/// +/// The [MaterialIconActionButton] widget requires a primary color, secondary +/// color, icon, text, and a callback function to handle taps. +/// +/// Example usage: +/// ```dart +/// MaterialIconActionButton( +/// primaryColor: Colors.blue, +/// secondaryColor: Colors.green, +/// icon: Icons.camera, +/// text: 'Camera', +/// onTap: () { +/// // Handle tap action +/// }, +/// ); +/// ``` +class MaterialIconActionButton extends StatelessWidget { + /// Creates a new [MaterialIconActionButton] widget. + /// + /// The [primaryColor] is the color of the circular background, while the + /// [secondaryColor] is used for the half-circle overlay. The [icon] is the + /// icon to display in the center, and [text] is the label displayed below + /// the icon. The [onTap] callback is triggered when the button is tapped. + const MaterialIconActionButton({ + super.key, + required this.primaryColor, + required this.secondaryColor, + required this.icon, + required this.text, + required this.onTap, + }); + + /// The primary color for the button's background. + final Color primaryColor; + + /// The secondary color for the half-circle overlay. + final Color secondaryColor; + + /// The icon to display in the center of the button. + final IconData icon; + + /// The label displayed below the icon. + final String text; + + /// The callback function triggered when the button is tapped. + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 65, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + InkWell( + borderRadius: BorderRadius.circular(60), + onTap: onTap, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: primaryColor, + borderRadius: BorderRadius.circular(100), + ), + ), + CustomPaint( + painter: CircleHalf(secondaryColor), + size: const Size(60, 60), + ), + Icon(icon, color: Colors.white), + ], + ), + ), + const SizedBox(height: 7), + Text( + text, + overflow: TextOverflow.ellipsis, + maxLines: 1, + textAlign: TextAlign.center, + ), + ], + ), + ); + } +} + +/// A custom painter class that paints a half-circle. +/// +/// The [CircleHalf] class takes a [color] parameter and paints half of a circle +/// on a canvas, typically used as an overlay for the +/// [MaterialIconActionButton]. +class CircleHalf extends CustomPainter { + /// Creates a new [CircleHalf] painter with the given [color]. + CircleHalf(this.color); + + /// The color to use for paint the half-circle. + final Color color; + + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint()..color = color; + canvas.drawArc( + Rect.fromCenter( + center: Offset(size.height / 2, size.width / 2), + height: size.height, + width: size.width, + ), + pi, + pi, + false, + paint, + ); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/example/lib/widgets/not_found_example.dart b/example/lib/widgets/not_found_example.dart new file mode 100644 index 00000000..6d0c8096 --- /dev/null +++ b/example/lib/widgets/not_found_example.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +/// A widget that displays a centered "Example not found" message. +/// +/// This widget is useful as a placeholder for screens or routes +/// that have not been implemented yet or when content is unavailable. +class NotFoundExample extends StatefulWidget { + /// Creates a `NotFoundExample` widget. + const NotFoundExample({super.key}); + + @override + State createState() => _NotFoundExampleState(); +} + +class _NotFoundExampleState extends State { + @override + Widget build(BuildContext context) { + return const Scaffold( + body: Center( + child: Text( + 'Example not found', + style: TextStyle( + fontSize: 20, + color: Colors.red, + ), + ), + ), + ); + } +} diff --git a/example/lib/widgets/prepare_image_widget.dart b/example/lib/widgets/prepare_image_widget.dart new file mode 100644 index 00000000..b82e1ee8 --- /dev/null +++ b/example/lib/widgets/prepare_image_widget.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; + +/// A widget that displays a loading screen with a progress indicator and a +/// message. +/// +/// Used to inform the user that the editor is preparing a demo image. +/// +/// The UI consists of: +/// - A circular progress indicator. +/// - A message prompting the user to wait, styled with white text on a dark +/// background. +class PrepareImageWidget extends StatelessWidget { + /// Creates a [PrepareImageWidget]. + /// + /// The widget is stateless and serves as a loading screen + /// with a progress indicator and a message. + const PrepareImageWidget({super.key}); + + @override + Widget build(BuildContext context) { + return const Material( + color: Color.fromARGB(255, 19, 21, 22), + child: Padding( + padding: EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator( + color: Colors.white, + ), + SizedBox(height: 24), // Spacing between the widgets + Text( + 'Please wait...\nThe editor is preparing the demo image', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 20, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/common/editor_style_constants.dart b/lib/common/editor_style_constants.dart new file mode 100644 index 00000000..d332f44e --- /dev/null +++ b/lib/common/editor_style_constants.dart @@ -0,0 +1,31 @@ +import 'package:flutter/services.dart'; + +/// Primary color used in the image editor interface. +const kImageEditorPrimaryColor = Color(0xFF004C9E); + +/// Color of the bottom bar in the image editor. +const kImageEditorBottomBarColor = Color(0xFFFFFFFF); + +/// Background color of the bottom bar in the image editor. +const kImageEditorBottomBarBackground = Color(0xFF000000); + +/// Color of the app bar in the image editor. +const kImageEditorAppBarColor = Color(0xFFFFFFFF); + +/// Background color of the app bar in the image editor. +const kImageEditorAppBarBackground = Color(0xFF000000); + +/// Background color for the image editor. +const kImageEditorBackground = Color(0xFF161616); + +/// Text color used in the image editor interface. +const kImageEditorTextColor = Color(0xFFE1E1E1); + +/// UI overlay style for the image editor. +const kImageEditorUiOverlayStyle = SystemUiOverlayStyle( + statusBarColor: Color(0x42000000), + statusBarIconBrightness: Brightness.light, + systemNavigationBarIconBrightness: Brightness.light, + statusBarBrightness: Brightness.dark, + systemNavigationBarColor: Color(0xFF000000), +); diff --git a/lib/common/editor_various_constants.dart b/lib/common/editor_various_constants.dart new file mode 100644 index 00000000..d112fe1a --- /dev/null +++ b/lib/common/editor_various_constants.dart @@ -0,0 +1,2 @@ +/// Hero tag used for transitions in the Pro Image Editor. +const kImageEditorHeroTag = 'Pro-Image-Editor-Hero'; diff --git a/lib/designs/frosted_glass/frosted_glass.dart b/lib/designs/frosted_glass/frosted_glass.dart index 6401e7d6..b29a7e15 100644 --- a/lib/designs/frosted_glass/frosted_glass.dart +++ b/lib/designs/frosted_glass/frosted_glass.dart @@ -5,8 +5,8 @@ export 'frosted_glass_crop_rotate_toolbar.dart'; export 'frosted_glass_effect.dart'; export 'frosted_glass_filter_appbar.dart'; export 'frosted_glass_loading_dialog.dart'; -export 'frosted_glass_painting_appbar.dart'; -export 'frosted_glass_painting_bottombar.dart'; +export 'frosted_glass_paint_appbar.dart'; +export 'frosted_glass_paint_bottombar.dart'; export 'frosted_glass_sticker_editor.dart'; export 'frosted_glass_text_appbar.dart'; export 'frosted_glass_text_bottombar.dart'; diff --git a/lib/designs/frosted_glass/frosted_glass_appbar.dart b/lib/designs/frosted_glass/frosted_glass_appbar.dart index 540cb44b..917ad6fb 100644 --- a/lib/designs/frosted_glass/frosted_glass_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_appbar.dart @@ -68,7 +68,8 @@ class _FrostedGlassActionBarState extends State { child: IconButton( tooltip: widget.editor.configs.i18n.cancel, onPressed: widget.editor.closeEditor, - icon: Icon(widget.editor.configs.icons.closeEditor), + icon: Icon( + widget.editor.mainEditorConfigs.icons.closeEditor), color: _foregroundColor, ), ), @@ -83,7 +84,7 @@ class _FrostedGlassActionBarState extends State { tooltip: widget.editor.configs.i18n.undo, onPressed: widget.editor.undoAction, icon: Icon( - widget.editor.configs.icons.undoAction, + widget.editor.mainEditorConfigs.icons.undoAction, color: widget.editor.canUndo ? _foregroundColor : _foregroundColor.withAlpha(80), @@ -94,7 +95,7 @@ class _FrostedGlassActionBarState extends State { tooltip: widget.editor.configs.i18n.redo, onPressed: widget.editor.redoAction, icon: Icon( - widget.editor.configs.icons.redoAction, + widget.editor.mainEditorConfigs.icons.redoAction, color: widget.editor.canRedo ? _foregroundColor : _foregroundColor.withAlpha(80), @@ -111,7 +112,7 @@ class _FrostedGlassActionBarState extends State { tooltip: widget.editor.configs.i18n.done, onPressed: widget.editor.doneEditing, icon: Icon( - widget.editor.configs.icons.doneIcon, + widget.editor.mainEditorConfigs.icons.doneIcon, color: _foregroundColor, ), ), @@ -140,15 +141,15 @@ class _FrostedGlassActionBarState extends State { spacing: 12, alignment: WrapAlignment.center, children: [ - if (widget.editor.configs.paintEditorConfigs.enabled) + if (widget.editor.configs.paintEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.paintEditor .bottomNavigationBarText, - onPressed: widget.editor.openPaintingEditor, - icon: Icon(widget.editor.configs.icons.paintingEditor - .bottomNavBar), + onPressed: widget.editor.openPaintEditor, + icon: Icon(widget + .editor.paintEditorConfigs.icons.bottomNavBar), ), - if (widget.editor.configs.textEditorConfigs.enabled) + if (widget.editor.configs.textEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.textEditor .bottomNavigationBarText, @@ -156,44 +157,43 @@ class _FrostedGlassActionBarState extends State { duration: const Duration(milliseconds: 150), ), icon: Icon(widget - .editor.configs.icons.textEditor.bottomNavBar), + .editor.textEditorConfigs.icons.bottomNavBar), ), - if (widget.editor.configs.cropRotateEditorConfigs.enabled) + if (widget.editor.configs.cropRotateEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.cropRotateEditor .bottomNavigationBarText, onPressed: widget.editor.openCropRotateEditor, - icon: Icon(widget.editor.configs.icons - .cropRotateEditor.bottomNavBar), + icon: Icon(widget.editor.cropRotateEditorConfigs.icons + .bottomNavBar), ), - if (widget.editor.configs.tuneEditorConfigs.enabled) + if (widget.editor.configs.tuneEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.tuneEditor .bottomNavigationBarText, onPressed: () => widget.editor.openTuneEditor(enableHero: false), icon: Icon(widget - .editor.configs.icons.tuneEditor.bottomNavBar), + .editor.tuneEditorConfigs.icons.bottomNavBar), ), - if (widget.editor.configs.filterEditorConfigs.enabled) + if (widget.editor.configs.filterEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.filterEditor .bottomNavigationBarText, onPressed: widget.editor.openFilterEditor, icon: Icon(widget - .editor.configs.icons.filterEditor.bottomNavBar), + .editor.filterEditorConfigs.icons.bottomNavBar), ), - if (widget.editor.configs.blurEditorConfigs.enabled) + if (widget.editor.configs.blurEditor.enabled) IconButton( tooltip: widget.editor.configs.i18n.blurEditor .bottomNavigationBarText, onPressed: widget.editor.openBlurEditor, icon: Icon(widget - .editor.configs.icons.blurEditor.bottomNavBar), + .editor.blurEditorConfigs.icons.bottomNavBar), ), - if (widget.editor.configs.stickerEditorConfigs?.enabled == - true || - widget.editor.configs.emojiEditorConfigs.enabled) + if (widget.editor.configs.stickerEditor.enabled || + widget.editor.configs.emojiEditor.enabled) IconButton( key: const ValueKey( 'whatsapp-open-sticker-editor-btn'), @@ -201,7 +201,7 @@ class _FrostedGlassActionBarState extends State { .bottomNavigationBarText, onPressed: widget.openStickerEditor, icon: Icon(widget - .editor.configs.icons.stickerEditor.bottomNavBar), + .editor.stickerEditorConfigs.icons.bottomNavBar), ), ], ), diff --git a/lib/designs/frosted_glass/frosted_glass_blur_appbar.dart b/lib/designs/frosted_glass/frosted_glass_blur_appbar.dart index 09e33f9f..1f7ba8e2 100644 --- a/lib/designs/frosted_glass/frosted_glass_blur_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_blur_appbar.dart @@ -53,7 +53,7 @@ class FrostedGlassBlurAppbar extends StatelessWidget { tooltip: blurEditor.configs.i18n.cancel, onPressed: blurEditor.close, icon: Icon( - blurEditor.configs.icons.closeEditor, + blurEditor.blurEditorConfigs.icons.backButton, color: Colors.white, ), ), @@ -66,7 +66,7 @@ class FrostedGlassBlurAppbar extends StatelessWidget { tooltip: blurEditor.configs.i18n.done, onPressed: blurEditor.done, icon: Icon( - blurEditor.configs.icons.doneIcon, + blurEditor.blurEditorConfigs.icons.applyChanges, color: Colors.white, ), ), diff --git a/lib/designs/frosted_glass/frosted_glass_crop_rotate_toolbar.dart b/lib/designs/frosted_glass/frosted_glass_crop_rotate_toolbar.dart index 3a806f10..0abf7c08 100644 --- a/lib/designs/frosted_glass/frosted_glass_crop_rotate_toolbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_crop_rotate_toolbar.dart @@ -53,8 +53,7 @@ class _FrostedGlassCropRotateToolbar Widget build(BuildContext context) { var padding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16); var style = TextStyle( - color: widget - .configs.imageEditorTheme.cropRotateEditor.appBarForegroundColor, + color: widget.configs.cropRotateEditor.style.appBarColor, fontSize: 16, ); @@ -69,17 +68,16 @@ class _FrostedGlassCropRotateToolbar crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (widget.configs.cropRotateEditorConfigs.canRotate) + if (widget.configs.cropRotateEditor.canRotate) IconButton( onPressed: widget.onRotate, tooltip: widget.configs.i18n.cropRotateEditor.rotate, - icon: Icon(widget.configs.icons.cropRotateEditor.rotate), - color: widget.configs.imageEditorTheme.cropRotateEditor - .appBarForegroundColor, + icon: Icon(widget.configs.cropRotateEditor.icons.rotate), + color: widget.configs.cropRotateEditor.style.appBarColor, ) else const SizedBox.shrink(), - if (widget.configs.cropRotateEditorConfigs.canReset) + if (widget.configs.cropRotateEditor.canReset) CupertinoButton( onPressed: widget.onReset, padding: padding, @@ -88,13 +86,12 @@ class _FrostedGlassCropRotateToolbar style: style, ), ), - if (widget.configs.cropRotateEditorConfigs.canChangeAspectRatio) + if (widget.configs.cropRotateEditor.canChangeAspectRatio) IconButton( onPressed: widget.openAspectRatios, tooltip: widget.configs.i18n.cropRotateEditor.ratio, - icon: Icon(widget.configs.icons.cropRotateEditor.aspectRatio), - color: widget.configs.imageEditorTheme.cropRotateEditor - .appBarForegroundColor, + icon: Icon(widget.configs.cropRotateEditor.icons.aspectRatio), + color: widget.configs.cropRotateEditor.style.appBarColor, ) else const SizedBox.shrink(), diff --git a/lib/designs/frosted_glass/frosted_glass_filter_appbar.dart b/lib/designs/frosted_glass/frosted_glass_filter_appbar.dart index 05aee771..7087f85f 100644 --- a/lib/designs/frosted_glass/frosted_glass_filter_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_filter_appbar.dart @@ -49,7 +49,7 @@ class FrostedGlassFilterAppbar extends StatelessWidget { tooltip: filterEditor.configs.i18n.cancel, onPressed: filterEditor.close, icon: Icon( - filterEditor.configs.icons.closeEditor, + filterEditor.filterEditorConfigs.icons.backButton, color: Colors.white, ), ), @@ -62,7 +62,7 @@ class FrostedGlassFilterAppbar extends StatelessWidget { tooltip: filterEditor.configs.i18n.done, onPressed: filterEditor.done, icon: Icon( - filterEditor.configs.icons.doneIcon, + filterEditor.filterEditorConfigs.icons.applyChanges, color: Colors.white, ), ), diff --git a/lib/designs/frosted_glass/frosted_glass_painting_appbar.dart b/lib/designs/frosted_glass/frosted_glass_paint_appbar.dart similarity index 74% rename from lib/designs/frosted_glass/frosted_glass_painting_appbar.dart rename to lib/designs/frosted_glass/frosted_glass_paint_appbar.dart index 3207d59d..4277aada 100644 --- a/lib/designs/frosted_glass/frosted_glass_painting_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_paint_appbar.dart @@ -7,30 +7,30 @@ import 'frosted_glass_effect.dart'; /// A stateless widget that represents an app bar with a frosted glass effect. /// -/// This app bar is designed for use in a painting editor interface, providing -/// a stylish and functional header that integrates with painting operations. -class FrostedGlassPaintingAppbar extends StatelessWidget { - /// Creates a [FrostedGlassPaintingAppbar]. +/// This app bar is designed for use in a paint editor interface, providing +/// a stylish and functional header that integrates with paint operations. +class FrostedGlassPaintAppbar extends StatelessWidget { + /// Creates a [FrostedGlassPaintAppbar]. /// /// This app bar utilizes a frosted glass effect to enhance the visual design - /// of a painting editor, offering controls and options relevant to painting. + /// of a paint editor, offering controls and options relevant to paint. /// /// Example: /// ``` - /// FrostedGlassPaintingAppbar( + /// FrostedGlassPaintAppbar( /// paintEditor: myPaintEditorState, /// ) /// ``` - const FrostedGlassPaintingAppbar({ + const FrostedGlassPaintAppbar({ super.key, required this.paintEditor, }); - /// The state of the painting editor associated with this app bar. + /// The state of the paint editor associated with this app bar. /// - /// This state allows the app bar to interact with the painting editor, - /// providing necessary controls and options to manage painting activities. - final PaintingEditorState paintEditor; + /// This state allows the app bar to interact with the paint editor, + /// providing necessary controls and options to manage paint activities. + final PaintEditorState paintEditor; @override Widget build(BuildContext context) { @@ -48,7 +48,7 @@ class FrostedGlassPaintingAppbar extends StatelessWidget { tooltip: paintEditor.configs.i18n.cancel, onPressed: paintEditor.close, icon: Icon( - paintEditor.configs.icons.closeEditor, + paintEditor.paintEditorConfigs.icons.backButton, color: Colors.white, ), ), @@ -64,7 +64,7 @@ class FrostedGlassPaintingAppbar extends StatelessWidget { tooltip: paintEditor.configs.i18n.undo, onPressed: paintEditor.undoAction, icon: Icon( - paintEditor.configs.icons.undoAction, + paintEditor.paintEditorConfigs.icons.undoAction, color: paintEditor.canUndo ? Colors.white : Colors.white.withAlpha(80), @@ -75,7 +75,7 @@ class FrostedGlassPaintingAppbar extends StatelessWidget { tooltip: paintEditor.configs.i18n.redo, onPressed: paintEditor.redoAction, icon: Icon( - paintEditor.configs.icons.redoAction, + paintEditor.paintEditorConfigs.icons.redoAction, color: paintEditor.canRedo ? Colors.white : Colors.white.withAlpha(80), @@ -92,7 +92,7 @@ class FrostedGlassPaintingAppbar extends StatelessWidget { tooltip: paintEditor.configs.i18n.done, onPressed: paintEditor.done, icon: Icon( - paintEditor.configs.icons.doneIcon, + paintEditor.paintEditorConfigs.icons.applyChanges, color: Colors.white, ), ), diff --git a/lib/designs/frosted_glass/frosted_glass_painting_bottombar.dart b/lib/designs/frosted_glass/frosted_glass_paint_bottombar.dart similarity index 92% rename from lib/designs/frosted_glass/frosted_glass_painting_bottombar.dart rename to lib/designs/frosted_glass/frosted_glass_paint_bottombar.dart index b310f13c..5fd513d8 100644 --- a/lib/designs/frosted_glass/frosted_glass_painting_bottombar.dart +++ b/lib/designs/frosted_glass/frosted_glass_paint_bottombar.dart @@ -9,13 +9,13 @@ import 'package:pro_image_editor/utils/pro_image_editor_icons.dart'; /// A stateful widget that represents a bottom bar with a frosted glass effect. /// -/// This bottom bar is designed for use in a painting editor interface, -/// providing controls and options for painting operations in a stylish manner. +/// This bottom bar is designed for use in a paint editor interface, +/// providing controls and options for paint operations in a stylish manner. class FrostedGlassPaintBottomBar extends StatefulWidget { /// Creates a [FrostedGlassPaintBottomBar]. /// /// This bottom bar utilizes a frosted glass effect to enhance the visual - /// design of a painting editor, offering controls relevant to painting. + /// design of a paint editor, offering controls relevant to paint. /// /// Example: /// ``` @@ -28,11 +28,11 @@ class FrostedGlassPaintBottomBar extends StatefulWidget { required this.paintEditor, }); - /// The state of the painting editor associated with this bottom bar. + /// The state of the paint editor associated with this bottom bar. /// - /// This state allows the bottom bar to interact with the painting editor, - /// providing necessary controls and options to manage painting activities. - final PaintingEditorState paintEditor; + /// This state allows the bottom bar to interact with the paint editor, + /// providing necessary controls and options to manage paint activities. + final PaintEditorState paintEditor; @override State createState() => @@ -49,8 +49,8 @@ class _FrostedGlassPaintBottomBarState void initState() { _buttonStyle = IconButton.styleFrom( backgroundColor: Colors.black38, - foregroundColor: widget.paintEditor.configs.imageEditorTheme - .paintingEditor.bottomBarInactiveItemColor, + foregroundColor: widget + .paintEditor.paintEditorConfigs.style.bottomBarInactiveItemColor, padding: const EdgeInsets.all(10), iconSize: 22, minimumSize: const Size.fromRadius(10), @@ -60,7 +60,7 @@ class _FrostedGlassPaintBottomBarState @override Widget build(BuildContext context) { - return widget.paintEditor.activePainting + return widget.paintEditor.isActive ? const SizedBox.shrink() : Positioned( bottom: 0, diff --git a/lib/designs/frosted_glass/frosted_glass_sticker_editor.dart b/lib/designs/frosted_glass/frosted_glass_sticker_editor.dart index af49772c..41b73889 100644 --- a/lib/designs/frosted_glass/frosted_glass_sticker_editor.dart +++ b/lib/designs/frosted_glass/frosted_glass_sticker_editor.dart @@ -60,7 +60,7 @@ class _FrostedGlassStickerPageState extends State { void initState() { _searchCtrl = TextEditingController(); _searchFocus = FocusNode(); - if (!widget.configs.emojiEditorConfigs.enabled) { + if (!widget.configs.emojiEditor.enabled) { temporaryStickerMode = FrostedGlassStickerMode.sticker; } super.initState(); @@ -96,7 +96,7 @@ class _FrostedGlassStickerPageState extends State { configs: widget.configs, ), ), - if (widget.configs.stickerEditorConfigs != null) + if (widget.configs.stickerEditor.enabled) Offstage( offstage: temporaryStickerMode != FrostedGlassStickerMode.sticker, @@ -142,7 +142,7 @@ class _FrostedGlassStickerPageState extends State { } }, icon: Icon( - widget.configs.icons.backButton, + widget.configs.mainEditor.icons.backButton, color: Colors.white, ), ), @@ -152,7 +152,7 @@ class _FrostedGlassStickerPageState extends State { ), onPressed: null, icon: Icon( - widget.configs.icons.stickerEditor.bottomNavBar, + widget.configs.stickerEditor.icons.bottomNavBar, color: Colors.white, ), ), @@ -181,7 +181,7 @@ class _FrostedGlassStickerPageState extends State { color: Colors.white, ), ), - if (widget.configs.stickerEditorConfigs != null) + if (widget.configs.stickerEditor.enabled) Align( alignment: Alignment.center, child: SegmentedButton( diff --git a/lib/designs/frosted_glass/frosted_glass_text_appbar.dart b/lib/designs/frosted_glass/frosted_glass_text_appbar.dart index cd44a009..edc410c2 100644 --- a/lib/designs/frosted_glass/frosted_glass_text_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_text_appbar.dart @@ -49,7 +49,7 @@ class FrostedGlassTextAppbar extends StatelessWidget { tooltip: textEditor.configs.i18n.cancel, onPressed: textEditor.close, icon: Icon( - textEditor.configs.icons.closeEditor, + textEditor.mainEditorConfigs.icons.closeEditor, color: Colors.white, ), ), @@ -66,16 +66,18 @@ class FrostedGlassTextAppbar extends StatelessWidget { tooltip: textEditor.i18n.textEditor.textAlign, onPressed: textEditor.toggleTextAlign, icon: Icon(textEditor.align == TextAlign.left - ? textEditor.icons.textEditor.alignLeft + ? textEditor.textEditorConfigs.icons.alignLeft : textEditor.align == TextAlign.right - ? textEditor.icons.textEditor.alignRight - : textEditor.icons.textEditor.alignCenter), + ? textEditor.textEditorConfigs.icons.alignRight + : textEditor + .textEditorConfigs.icons.alignCenter), ), const SizedBox(width: 3), IconButton( tooltip: textEditor.i18n.textEditor.backgroundMode, onPressed: textEditor.toggleBackgroundMode, - icon: Icon(textEditor.icons.textEditor.backgroundMode), + icon: Icon( + textEditor.textEditorConfigs.icons.backgroundMode), ), ], ), @@ -89,7 +91,7 @@ class FrostedGlassTextAppbar extends StatelessWidget { tooltip: textEditor.configs.i18n.done, onPressed: textEditor.done, icon: Icon( - textEditor.configs.icons.doneIcon, + textEditor.textEditorConfigs.icons.applyChanges, color: Colors.white, ), ), diff --git a/lib/designs/frosted_glass/frosted_glass_text_bottombar.dart b/lib/designs/frosted_glass/frosted_glass_text_bottombar.dart index f188ea59..d1b16667 100644 --- a/lib/designs/frosted_glass/frosted_glass_text_bottombar.dart +++ b/lib/designs/frosted_glass/frosted_glass_text_bottombar.dart @@ -94,8 +94,7 @@ class _FrostedGlassTextBottomBarState extends State { ? const Icon(Icons.color_lens) : Text( 'Aa', - style: widget - .configs.textEditorConfigs.customTextStyles?.first + style: widget.configs.textEditor.customTextStyles?.first .copyWith( color: Colors.white, ), diff --git a/lib/designs/frosted_glass/frosted_glass_tune_appbar.dart b/lib/designs/frosted_glass/frosted_glass_tune_appbar.dart index 3f470771..4b0cf5c7 100644 --- a/lib/designs/frosted_glass/frosted_glass_tune_appbar.dart +++ b/lib/designs/frosted_glass/frosted_glass_tune_appbar.dart @@ -43,7 +43,7 @@ class FrostedGlassTuneAppbar extends StatelessWidget { tooltip: tuneEditor.configs.i18n.cancel, onPressed: tuneEditor.close, icon: Icon( - tuneEditor.configs.icons.closeEditor, + tuneEditor.tuneEditorConfigs.icons.backButton, color: Colors.white, ), ), @@ -59,7 +59,7 @@ class FrostedGlassTuneAppbar extends StatelessWidget { tooltip: tuneEditor.configs.i18n.undo, onPressed: tuneEditor.undo, icon: Icon( - tuneEditor.configs.icons.undoAction, + tuneEditor.tuneEditorConfigs.icons.undoAction, color: tuneEditor.canUndo ? Colors.white : Colors.white.withAlpha(80), @@ -70,7 +70,7 @@ class FrostedGlassTuneAppbar extends StatelessWidget { tooltip: tuneEditor.configs.i18n.redo, onPressed: tuneEditor.redo, icon: Icon( - tuneEditor.configs.icons.redoAction, + tuneEditor.tuneEditorConfigs.icons.redoAction, color: tuneEditor.canRedo ? Colors.white : Colors.white.withAlpha(80), @@ -87,7 +87,7 @@ class FrostedGlassTuneAppbar extends StatelessWidget { tooltip: tuneEditor.configs.i18n.done, onPressed: tuneEditor.done, icon: Icon( - tuneEditor.configs.icons.doneIcon, + tuneEditor.tuneEditorConfigs.icons.applyChanges, color: Colors.white, ), ), diff --git a/lib/designs/frosted_glass/frosted_glass_tune_bottombar.dart b/lib/designs/frosted_glass/frosted_glass_tune_bottombar.dart index 026a1e46..e72623e2 100644 --- a/lib/designs/frosted_glass/frosted_glass_tune_bottombar.dart +++ b/lib/designs/frosted_glass/frosted_glass_tune_bottombar.dart @@ -95,7 +95,7 @@ class FrostedGlassTuneBottombar extends StatelessWidget { item.icon, size: bottomIconSize, color: tuneEditor.selectedIndex == index - ? imageEditorPrimaryColor + ? kImageEditorPrimaryColor : Colors.white, ), onPressed: () { diff --git a/lib/designs/grounded/grounded_blur_bar.dart b/lib/designs/grounded/grounded_blur_bar.dart index 8ad4465a..c9fff95a 100644 --- a/lib/designs/grounded/grounded_blur_bar.dart +++ b/lib/designs/grounded/grounded_blur_bar.dart @@ -57,7 +57,7 @@ class _GroundedBlurBarState extends State Widget _buildFunctions(BoxConstraints constraints) { return Container( - color: imageEditorTheme.bottomBarBackgroundColor, + color: blurEditorConfigs.style.appBarBackgroundColor, child: FadeInUp( duration: GROUNDED_FADE_IN_DURATION, child: Slider( diff --git a/lib/designs/grounded/grounded_bottom_bar.dart b/lib/designs/grounded/grounded_bottom_bar.dart index c6632321..5c8c5832 100644 --- a/lib/designs/grounded/grounded_bottom_bar.dart +++ b/lib/designs/grounded/grounded_bottom_bar.dart @@ -56,8 +56,7 @@ class GroundedBottomBar extends StatefulWidget { class _GroundedBottomBarState extends State { @override Widget build(BuildContext context) { - Color foreGroundColor = - widget.configs.imageEditorTheme.appBarForegroundColor; + Color foreGroundColor = widget.configs.mainEditor.style.appBarColor; return Container( padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 12), color: const Color(0xFF222222), @@ -68,7 +67,7 @@ class _GroundedBottomBarState extends State { tooltip: widget.configs.i18n.cancel, onPressed: widget.close, icon: Icon( - widget.configs.icons.closeEditor, + widget.configs.mainEditor.icons.closeEditor, color: foreGroundColor, ), ), @@ -79,7 +78,7 @@ class _GroundedBottomBarState extends State { tooltip: widget.configs.i18n.undo, onPressed: widget.undo, icon: Icon( - widget.configs.icons.undoAction, + widget.configs.mainEditor.icons.undoAction, color: widget.enableUndo ? foreGroundColor : foreGroundColor.withAlpha(80), @@ -90,7 +89,7 @@ class _GroundedBottomBarState extends State { tooltip: widget.configs.i18n.redo, onPressed: widget.redo, icon: Icon( - widget.configs.icons.redoAction, + widget.configs.mainEditor.icons.redoAction, color: widget.enableRedo ? foreGroundColor : foreGroundColor.withAlpha(80), @@ -102,7 +101,7 @@ class _GroundedBottomBarState extends State { tooltip: widget.configs.i18n.done, onPressed: widget.done, icon: Icon( - widget.configs.icons.doneIcon, + widget.configs.mainEditor.icons.doneIcon, color: foreGroundColor, ), ), diff --git a/lib/designs/grounded/grounded_bottom_wrapper.dart b/lib/designs/grounded/grounded_bottom_wrapper.dart index 7389c869..59f470a4 100644 --- a/lib/designs/grounded/grounded_bottom_wrapper.dart +++ b/lib/designs/grounded/grounded_bottom_wrapper.dart @@ -64,7 +64,7 @@ class _GroundedBottomWrapperState extends State { return LayoutBuilder( builder: (context, constraints) { return Theme( - data: widget.theme ?? ThemeData.dark(), + data: widget.theme ?? Theme.of(context), child: Column( mainAxisSize: MainAxisSize.min, children: widget.children(constraints), diff --git a/lib/designs/grounded/grounded_crop_rotate_bar.dart b/lib/designs/grounded/grounded_crop_rotate_bar.dart index cec611a6..136c6533 100644 --- a/lib/designs/grounded/grounded_crop_rotate_bar.dart +++ b/lib/designs/grounded/grounded_crop_rotate_bar.dart @@ -52,8 +52,7 @@ class _GroundedCropRotateBarState extends State with ImageEditorConvertedConfigs, SimpleConfigsAccessState { late final ScrollController _bottomBarScrollCtrl; - Color get _foreGroundColor => - imageEditorTheme.textEditor.appBarForegroundColor; + Color get _foreGroundColor => cropRotateEditorConfigs.style.appBarColor; Color get _foreGroundColorAccent => _foreGroundColor.withValues(alpha: 0.6); @override @@ -95,7 +94,7 @@ class _GroundedCropRotateBarState extends State Widget _buildFunctions(BoxConstraints constraints) { return BottomAppBar( height: GROUNDED_SUB_BAR_HEIGHT, - color: imageEditorTheme.bottomBarBackgroundColor, + color: cropRotateEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Align( alignment: Alignment.center, @@ -168,7 +167,7 @@ class _GroundedCropRotateBarState extends State ), ), icon: Icon( - configs.icons.cropRotateEditor.rotate, + cropRotateEditorConfigs.icons.rotate, color: _foreGroundColor, ), onPressed: () { @@ -184,7 +183,7 @@ class _GroundedCropRotateBarState extends State ), ), icon: Icon( - configs.icons.cropRotateEditor.flip, + cropRotateEditorConfigs.icons.flip, color: _foreGroundColor, ), onPressed: () { @@ -201,7 +200,7 @@ class _GroundedCropRotateBarState extends State width: 1, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: imageEditorTheme.paintingEditor.bottomBarInactiveItemColor, + color: paintEditorConfigs.style.bottomBarInactiveItemColor, ), ); } diff --git a/lib/designs/grounded/grounded_design.dart b/lib/designs/grounded/grounded_design.dart index 45f40b03..982b7074 100644 --- a/lib/designs/grounded/grounded_design.dart +++ b/lib/designs/grounded/grounded_design.dart @@ -5,7 +5,7 @@ export 'grounded_crop_rotate_bar.dart'; export 'grounded_emoji_editor.dart'; export 'grounded_filter_bar.dart'; export 'grounded_main_bar.dart'; -export 'grounded_painting_bar.dart'; +export 'grounded_paint_bar.dart'; export 'grounded_sticker_editor.dart'; export 'grounded_text_bar.dart'; export 'grounded_text_size_slider.dart'; diff --git a/lib/designs/grounded/grounded_emoji_editor.dart b/lib/designs/grounded/grounded_emoji_editor.dart index 0f42e4b1..ae4c93d4 100644 --- a/lib/designs/grounded/grounded_emoji_editor.dart +++ b/lib/designs/grounded/grounded_emoji_editor.dart @@ -64,8 +64,7 @@ class _GroundedEmojiEditorState extends State { @override Widget build(BuildContext context) { - Color foreGroundColor = - widget.configs.imageEditorTheme.appBarForegroundColor; + Color foreGroundColor = widget.configs.mainEditor.style.appBarColor; return FrostedGlassEffect( radius: BorderRadius.zero, child: Scaffold( @@ -100,7 +99,7 @@ class _GroundedEmojiEditorState extends State { } }, icon: Icon( - widget.configs.icons.closeEditor, + widget.configs.mainEditor.icons.closeEditor, color: foreGroundColor, ), ), diff --git a/lib/designs/grounded/grounded_filter_bar.dart b/lib/designs/grounded/grounded_filter_bar.dart index ceb8d9a5..a1b7319c 100644 --- a/lib/designs/grounded/grounded_filter_bar.dart +++ b/lib/designs/grounded/grounded_filter_bar.dart @@ -78,7 +78,7 @@ class _GroundedFilterBarState extends State Widget _buildFunctions(BoxConstraints constraints) { return Container( - color: imageEditorTheme.bottomBarBackgroundColor, + color: mainEditorConfigs.style.bottomBarBackground, padding: const EdgeInsets.only(bottom: 8), child: Column( children: [ diff --git a/lib/designs/grounded/grounded_main_bar.dart b/lib/designs/grounded/grounded_main_bar.dart index bfa5045e..59946661 100644 --- a/lib/designs/grounded/grounded_main_bar.dart +++ b/lib/designs/grounded/grounded_main_bar.dart @@ -12,7 +12,7 @@ import 'utils/grounded_configs.dart'; /// ProImageEditor. /// /// The [GroundedMainBar] allows users to access various editing features such -/// as painting, text editing, cropping, rotating, applying filters, blurring, +/// as paint, text editing, cropping, rotating, applying filters, blurring, /// and adding emojis or stickers to an image. It provides an interactive UI /// for switching between these editors and includes undo/redo and close actions. class GroundedMainBar extends StatefulWidget with SimpleConfigsAccess { @@ -48,7 +48,7 @@ class GroundedMainBarState extends State with ImageEditorConvertedConfigs, SimpleConfigsAccessState { late final ScrollController _bottomBarScrollCtrl; - Color get _foreGroundColor => imageEditorTheme.appBarForegroundColor; + Color get _foreGroundColor => mainEditorConfigs.style.appBarColor; Color get _foreGroundColorAccent => _foreGroundColor.withValues(alpha: 0.6); late final _bottomTextStyle = TextStyle( @@ -75,7 +75,7 @@ class GroundedMainBarState extends State callbacks: callbacks, )); if (layer == null || !mounted) return; - layer.scale = configs.emojiEditorConfigs.initScale; + layer.scale = configs.emojiEditor.initScale; widget.editor.addLayer(layer); } @@ -115,7 +115,7 @@ class GroundedMainBarState extends State Widget _buildFunctions(BoxConstraints constraints) { return BottomAppBar( height: GROUNDED_SUB_BAR_HEIGHT, - color: imageEditorTheme.bottomBarBackgroundColor, + color: mainEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, clipBehavior: Clip.none, child: AnimatedSwitcher( @@ -167,11 +167,11 @@ class GroundedMainBarState extends State i18n.paintEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.paintingEditor.bottomNavBar, + paintEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), - onPressed: widget.editor.openPaintingEditor, + onPressed: widget.editor.openPaintEditor, ), if (textEditorConfigs.enabled) FlatIconTextButton( @@ -179,7 +179,7 @@ class GroundedMainBarState extends State label: Text(i18n.textEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.textEditor.bottomNavBar, + textEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), @@ -192,7 +192,7 @@ class GroundedMainBarState extends State i18n.cropRotateEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.cropRotateEditor.bottomNavBar, + cropRotateEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), @@ -204,7 +204,7 @@ class GroundedMainBarState extends State label: Text(i18n.tuneEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.tuneEditor.bottomNavBar, + tuneEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), @@ -217,7 +217,7 @@ class GroundedMainBarState extends State i18n.filterEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.filterEditor.bottomNavBar, + filterEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), @@ -229,7 +229,7 @@ class GroundedMainBarState extends State label: Text(i18n.blurEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.blurEditor.bottomNavBar, + blurEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), @@ -242,20 +242,20 @@ class GroundedMainBarState extends State i18n.emojiEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.emojiEditor.bottomNavBar, + emojiEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), onPressed: _openEmojiEditor, ), - if (stickerEditorConfigs?.enabled == true) + if (stickerEditorConfigs.enabled) FlatIconTextButton( spacing: 7, label: Text( i18n.stickerEditor.bottomNavigationBarText, style: _bottomTextStyle), icon: Icon( - icons.stickerEditor.bottomNavBar, + stickerEditorConfigs.icons.bottomNavBar, size: _bottomIconSize, color: _foreGroundColor, ), diff --git a/lib/designs/grounded/grounded_painting_bar.dart b/lib/designs/grounded/grounded_paint_bar.dart similarity index 84% rename from lib/designs/grounded/grounded_painting_bar.dart rename to lib/designs/grounded/grounded_paint_bar.dart index 23b5d823..3968e204 100644 --- a/lib/designs/grounded/grounded_painting_bar.dart +++ b/lib/designs/grounded/grounded_paint_bar.dart @@ -6,18 +6,18 @@ import 'package:pro_image_editor/pro_image_editor.dart'; import 'grounded_design.dart'; import 'utils/grounded_configs.dart'; -/// A widget that provides the painting toolbar for the ProImageEditor. +/// A widget that provides the paint toolbar for the ProImageEditor. /// -/// The [GroundedPaintingBar] allows users to access painting-related tools +/// The [GroundedPaintBar] allows users to access paint-related tools /// such as changing colors, line width, opacity, and toggling fill options /// for shapes. It also integrates undo/redo functionality and provides zoom /// options if enabled in the configuration. -class GroundedPaintingBar extends StatefulWidget with SimpleConfigsAccess { - /// Constructor for the [GroundedPaintingBar]. +class GroundedPaintBar extends StatefulWidget with SimpleConfigsAccess { + /// Constructor for the [GroundedPaintBar]. /// /// Requires [configs], [callbacks], [editor], [i18nColor], and /// [showColorPicker] parameters. - const GroundedPaintingBar({ + const GroundedPaintBar({ super.key, required this.configs, required this.callbacks, @@ -26,8 +26,8 @@ class GroundedPaintingBar extends StatefulWidget with SimpleConfigsAccess { required this.showColorPicker, }); - /// The editor state that holds painting-related information. - final PaintingEditorState editor; + /// The editor state that holds paint-related information. + final PaintEditorState editor; @override final ProImageEditorConfigs configs; @@ -41,14 +41,14 @@ class GroundedPaintingBar extends StatefulWidget with SimpleConfigsAccess { final Function(Color currentColor) showColorPicker; @override - State createState() => _GroundedPaintingBarState(); + State createState() => _GroundedPaintBarState(); } -/// State class for [GroundedPaintingBar]. +/// State class for [GroundedPaintBar]. /// -/// This state manages the UI for the painting toolbar, including buttons +/// This state manages the UI for the paint toolbar, including buttons /// for selecting colors, line width, opacity, and shape fill options. -class _GroundedPaintingBarState extends State +class _GroundedPaintBarState extends State with ImageEditorConvertedConfigs, SimpleConfigsAccessState { late final ScrollController _bottomBarScrollCtrl; @@ -64,8 +64,7 @@ class _GroundedPaintingBarState extends State super.dispose(); } - Color get _foreGroundColor => - imageEditorTheme.paintingEditor.appBarForegroundColor; + Color get _foreGroundColor => paintEditorConfigs.style.appBarColor; Color get _foreGroundColorAccent => _foreGroundColor.withValues(alpha: 0.6); @override @@ -95,13 +94,13 @@ class _GroundedPaintingBarState extends State Widget _buildFunctions(BoxConstraints constraints) { Color getColor(PaintModeE mode) { return widget.editor.paintMode == mode - ? imageEditorTheme.paintingEditor.bottomBarActiveItemColor - : imageEditorTheme.paintingEditor.bottomBarInactiveItemColor; + ? paintEditorConfigs.style.bottomBarActiveItemColor + : paintEditorConfigs.style.bottomBarInactiveItemColor; } return BottomAppBar( height: GROUNDED_SUB_BAR_HEIGHT, - color: imageEditorTheme.bottomBarBackgroundColor, + color: paintEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Align( alignment: Alignment.center, @@ -130,7 +129,7 @@ class _GroundedPaintingBarState extends State ), ), icon: Icon( - icons.paintingEditor.moveAndZoom, + paintEditorConfigs.icons.moveAndZoom, color: getColor(PaintModeE.moveAndZoom), ), onPressed: () { @@ -154,8 +153,8 @@ class _GroundedPaintingBarState extends State style: TextStyle( fontSize: 10.0, color: widget.editor.paintMode == item.mode - ? imageEditorTheme - .paintingEditor.bottomBarActiveItemColor + ? paintEditorConfigs + .style.bottomBarActiveItemColor : _foreGroundColorAccent, ), ), @@ -202,7 +201,7 @@ class _GroundedPaintingBarState extends State ), ), icon: Icon( - configs.icons.paintingEditor.lineWeight, + paintEditorConfigs.icons.lineWeight, color: _foreGroundColor, ), onPressed: () { @@ -218,7 +217,7 @@ class _GroundedPaintingBarState extends State ), ), icon: Icon( - configs.icons.paintingEditor.changeOpacity, + paintEditorConfigs.icons.changeOpacity, color: _foreGroundColor, ), onPressed: () { @@ -249,8 +248,8 @@ class _GroundedPaintingBarState extends State ), icon: Icon( widget.editor.fillBackground - ? configs.icons.paintingEditor.fill - : configs.icons.paintingEditor.noFill, + ? paintEditorConfigs.icons.fill + : paintEditorConfigs.icons.noFill, color: _foreGroundColor, ), onPressed: () { @@ -270,7 +269,7 @@ class _GroundedPaintingBarState extends State width: 1, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: imageEditorTheme.paintingEditor.bottomBarInactiveItemColor, + color: paintEditorConfigs.style.bottomBarInactiveItemColor, ), ); } diff --git a/lib/designs/grounded/grounded_sticker_editor.dart b/lib/designs/grounded/grounded_sticker_editor.dart index a038c7ba..0318ae92 100644 --- a/lib/designs/grounded/grounded_sticker_editor.dart +++ b/lib/designs/grounded/grounded_sticker_editor.dart @@ -64,8 +64,7 @@ class _GroundedStickerEditorState extends State { @override Widget build(BuildContext context) { - Color foreGroundColor = - widget.configs.imageEditorTheme.appBarForegroundColor; + Color foreGroundColor = widget.configs.mainEditor.style.appBarColor; return FrostedGlassEffect( radius: BorderRadius.zero, child: Scaffold( @@ -103,7 +102,7 @@ class _GroundedStickerEditorState extends State { } }, icon: Icon( - widget.configs.icons.closeEditor, + widget.configs.mainEditor.icons.closeEditor, color: foreGroundColor, ), ), diff --git a/lib/designs/grounded/grounded_text_bar.dart b/lib/designs/grounded/grounded_text_bar.dart index 9070b2ac..523804b9 100644 --- a/lib/designs/grounded/grounded_text_bar.dart +++ b/lib/designs/grounded/grounded_text_bar.dart @@ -47,8 +47,7 @@ class _GroundedTextBarState extends State with ImageEditorConvertedConfigs, SimpleConfigsAccessState { late final ScrollController _bottomBarScrollCtrl; - Color get _foreGroundColor => - imageEditorTheme.textEditor.appBarForegroundColor; + Color get _foreGroundColor => textEditorConfigs.style.appBarColor; Color get _foreGroundColorAccent => _foreGroundColor.withValues(alpha: 0.6); @override @@ -90,7 +89,7 @@ class _GroundedTextBarState extends State Widget _buildFunctions(BoxConstraints constraints) { return BottomAppBar( height: GROUNDED_SUB_BAR_HEIGHT, - color: imageEditorTheme.bottomBarBackgroundColor, + color: textEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Align( alignment: Alignment.center, @@ -176,9 +175,9 @@ class _GroundedTextBarState extends State ), icon: Icon( switch (widget.editor.align) { - TextAlign.left => configs.icons.textEditor.alignLeft, - TextAlign.right => configs.icons.textEditor.alignRight, - TextAlign.center || _ => configs.icons.textEditor.alignCenter, + TextAlign.left => textEditorConfigs.icons.alignLeft, + TextAlign.right => textEditorConfigs.icons.alignRight, + TextAlign.center || _ => textEditorConfigs.icons.alignCenter, }, color: _foreGroundColor, ), @@ -195,7 +194,7 @@ class _GroundedTextBarState extends State ), ), icon: Icon( - configs.icons.textEditor.backgroundMode, + textEditorConfigs.icons.backgroundMode, color: _foreGroundColor, ), onPressed: () { @@ -212,7 +211,7 @@ class _GroundedTextBarState extends State width: 1, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: imageEditorTheme.paintingEditor.bottomBarInactiveItemColor, + color: paintEditorConfigs.style.bottomBarInactiveItemColor, ), ); } diff --git a/lib/designs/grounded/grounded_tune_bar.dart b/lib/designs/grounded/grounded_tune_bar.dart index e6252564..fef5dc94 100644 --- a/lib/designs/grounded/grounded_tune_bar.dart +++ b/lib/designs/grounded/grounded_tune_bar.dart @@ -85,7 +85,8 @@ class _GroundedTuneBarState extends State var bottomTextStyle = const TextStyle(fontSize: 10.0, color: Colors.white); double bottomIconSize = 22.0; return Container( - color: imageEditorTheme.bottomBarBackgroundColor, + color: mainEditorConfigs.style.bottomBarBackground, + width: double.infinity, child: FadeInUp( duration: GROUNDED_FADE_IN_DURATION, child: Column( @@ -143,7 +144,7 @@ class _GroundedTuneBarState extends State item.icon, size: bottomIconSize, color: tuneEditor.selectedIndex == index - ? imageEditorPrimaryColor + ? kImageEditorPrimaryColor : Colors.white, ), onPressed: () { diff --git a/lib/designs/whatsapp/whatsapp.dart b/lib/designs/whatsapp/whatsapp.dart index 88908443..7d572b39 100644 --- a/lib/designs/whatsapp/whatsapp.dart +++ b/lib/designs/whatsapp/whatsapp.dart @@ -4,9 +4,9 @@ export 'whatsapp_crop_rotate_toolbar.dart'; export 'whatsapp_filter_button.dart'; export 'whatsapp_filters.dart'; export 'whatsapp_open_filter_button.dart'; +export 'whatsapp_paint_appbar.dart'; +export 'whatsapp_paint_bottombar.dart'; export 'whatsapp_paint_colorpicker.dart'; -export 'whatsapp_painting_appbar.dart'; -export 'whatsapp_painting_bottombar.dart'; export 'whatsapp_sticker_editor.dart'; export 'whatsapp_text_appbar.dart'; export 'whatsapp_text_bottombar.dart'; diff --git a/lib/designs/whatsapp/whatsapp_appbar.dart b/lib/designs/whatsapp/whatsapp_appbar.dart index 735f1080..84cfa655 100644 --- a/lib/designs/whatsapp/whatsapp_appbar.dart +++ b/lib/designs/whatsapp/whatsapp_appbar.dart @@ -70,7 +70,7 @@ class _WhatsAppAppBarState extends State { IconButton( tooltip: widget.configs.i18n.cancel, onPressed: widget.onClose, - icon: Icon(widget.configs.icons.closeEditor), + icon: Icon(widget.configs.mainEditor.icons.closeEditor), style: whatsAppButtonStyle, ), const Spacer(), @@ -88,24 +88,25 @@ class _WhatsAppAppBarState extends State { ? IconButton( tooltip: widget.configs.i18n.undo, onPressed: widget.onTapUndo, - icon: Icon(widget.configs.icons.undoAction), + icon: Icon( + widget.configs.mainEditor.icons.undoAction), style: whatsAppButtonStyle, ) : const SizedBox.shrink(), ), - if (widget.configs.cropRotateEditorConfigs.enabled) ...[ + if (widget.configs.cropRotateEditor.enabled) ...[ gap, IconButton( tooltip: widget.configs.i18n.cropRotateEditor .bottomNavigationBarText, onPressed: widget.onTapCropRotateEditor, icon: Icon( - widget.configs.icons.cropRotateEditor.bottomNavBar), + widget.configs.cropRotateEditor.icons.bottomNavBar), style: whatsAppButtonStyle, ), ], - if (widget.configs.stickerEditorConfigs?.enabled == true || - widget.configs.emojiEditorConfigs.enabled) ...[ + if (widget.configs.stickerEditor.enabled || + widget.configs.emojiEditor.enabled) ...[ gap, IconButton( key: const ValueKey('whatsapp-open-sticker-editor-btn'), @@ -113,28 +114,27 @@ class _WhatsAppAppBarState extends State { .configs.i18n.stickerEditor.bottomNavigationBarText, onPressed: widget.onTapStickerEditor, icon: - Icon(widget.configs.icons.stickerEditor.bottomNavBar), + Icon(widget.configs.stickerEditor.icons.bottomNavBar), style: whatsAppButtonStyle, ), ], - if (widget.configs.textEditorConfigs.enabled) ...[ + if (widget.configs.textEditor.enabled) ...[ gap, IconButton( tooltip: widget .configs.i18n.textEditor.bottomNavigationBarText, onPressed: widget.onTapTextEditor, - icon: Icon(widget.configs.icons.textEditor.bottomNavBar), + icon: Icon(widget.configs.textEditor.icons.bottomNavBar), style: whatsAppButtonStyle, ), ], - if (widget.configs.paintEditorConfigs.enabled) ...[ + if (widget.configs.paintEditor.enabled) ...[ gap, IconButton( tooltip: widget .configs.i18n.paintEditor.bottomNavigationBarText, onPressed: widget.onTapPaintEditor, - icon: Icon( - widget.configs.icons.paintingEditor.bottomNavBar), + icon: Icon(widget.configs.paintEditor.icons.bottomNavBar), style: whatsAppButtonStyle, ), ], diff --git a/lib/designs/whatsapp/whatsapp_crop_rotate_toolbar.dart b/lib/designs/whatsapp/whatsapp_crop_rotate_toolbar.dart index 121da6fc..26f5117d 100644 --- a/lib/designs/whatsapp/whatsapp_crop_rotate_toolbar.dart +++ b/lib/designs/whatsapp/whatsapp_crop_rotate_toolbar.dart @@ -59,13 +59,11 @@ class _WhatsAppCropRotateToolbar extends State { Widget _buildMaterialToolbar() { var style = TextStyle( - color: widget - .configs.imageEditorTheme.cropRotateEditor.appBarForegroundColor, + color: widget.configs.cropRotateEditor.style.appBarColor, ); return BottomAppBar( - color: widget - .configs.imageEditorTheme.cropRotateEditor.appBarBackgroundColor, + color: widget.configs.cropRotateEditor.style.appBarBackground, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -80,9 +78,8 @@ class _WhatsAppCropRotateToolbar extends State { IconButton( onPressed: widget.onRotate, tooltip: widget.configs.i18n.cropRotateEditor.rotate, - icon: Icon(widget.configs.icons.cropRotateEditor.rotate), - color: widget.configs.imageEditorTheme.cropRotateEditor - .appBarForegroundColor, + icon: Icon(widget.configs.cropRotateEditor.icons.rotate), + color: widget.configs.cropRotateEditor.style.appBarColor, ), TextButton( onPressed: widget.onDone, @@ -99,8 +96,7 @@ class _WhatsAppCropRotateToolbar extends State { Widget _buildCupertinoToolbar() { var padding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16); var style = TextStyle( - color: widget - .configs.imageEditorTheme.cropRotateEditor.appBarForegroundColor, + color: widget.configs.cropRotateEditor.style.appBarColor, fontSize: 16, ); @@ -117,9 +113,8 @@ class _WhatsAppCropRotateToolbar extends State { IconButton( onPressed: widget.onRotate, tooltip: widget.configs.i18n.cropRotateEditor.rotate, - icon: Icon(widget.configs.icons.cropRotateEditor.rotate), - color: widget.configs.imageEditorTheme.cropRotateEditor - .appBarForegroundColor, + icon: Icon(widget.configs.cropRotateEditor.icons.rotate), + color: widget.configs.cropRotateEditor.style.appBarColor, ), CupertinoButton( onPressed: widget.onReset, @@ -132,9 +127,8 @@ class _WhatsAppCropRotateToolbar extends State { IconButton( onPressed: widget.openAspectRatios, tooltip: widget.configs.i18n.cropRotateEditor.ratio, - icon: Icon(widget.configs.icons.cropRotateEditor.aspectRatio), - color: widget.configs.imageEditorTheme.cropRotateEditor - .appBarForegroundColor, + icon: Icon(widget.configs.cropRotateEditor.icons.aspectRatio), + color: widget.configs.cropRotateEditor.style.appBarColor, ), ], ), diff --git a/lib/designs/whatsapp/whatsapp_painting_appbar.dart b/lib/designs/whatsapp/whatsapp_paint_appbar.dart similarity index 91% rename from lib/designs/whatsapp/whatsapp_painting_appbar.dart rename to lib/designs/whatsapp/whatsapp_paint_appbar.dart index 82e8c9bf..f3f749b7 100644 --- a/lib/designs/whatsapp/whatsapp_painting_appbar.dart +++ b/lib/designs/whatsapp/whatsapp_paint_appbar.dart @@ -73,14 +73,14 @@ class _WhatsAppPaintAppBarState extends State { ? IconButton( tooltip: widget.configs.i18n.undo, onPressed: widget.onTapUndo, - icon: Icon(widget.configs.icons.undoAction), + icon: Icon(widget.configs.paintEditor.icons.undoAction), style: whatsAppButtonStyle, ) : Opacity( opacity: 0, child: IconButton( onPressed: null, - icon: Icon(widget.configs.icons.undoAction), + icon: Icon(widget.configs.paintEditor.icons.undoAction), style: whatsAppButtonStyle, ), ), @@ -93,7 +93,7 @@ class _WhatsAppPaintAppBarState extends State { tooltip: widget.configs.i18n.paintEditor.bottomNavigationBarText, onPressed: () {}, - icon: Icon(widget.configs.icons.paintingEditor.bottomNavBar), + icon: Icon(widget.configs.paintEditor.icons.bottomNavBar), style: whatsAppButtonStyle.copyWith( backgroundColor: WidgetStateProperty.all(widget.activeColor), ), @@ -106,8 +106,7 @@ class _WhatsAppPaintAppBarState extends State { Widget _buildDoneBtn() { return WhatsAppDoneBtn( - foregroundColor: - widget.configs.imageEditorTheme.paintingEditor.appBarForegroundColor, + foregroundColor: widget.configs.paintEditor.style.appBarColor, configs: widget.configs, onPressed: widget.onDone, ); diff --git a/lib/designs/whatsapp/whatsapp_painting_bottombar.dart b/lib/designs/whatsapp/whatsapp_paint_bottombar.dart similarity index 94% rename from lib/designs/whatsapp/whatsapp_painting_bottombar.dart rename to lib/designs/whatsapp/whatsapp_paint_bottombar.dart index 7fccb081..17133b00 100644 --- a/lib/designs/whatsapp/whatsapp_painting_bottombar.dart +++ b/lib/designs/whatsapp/whatsapp_paint_bottombar.dart @@ -9,12 +9,12 @@ import 'package:pro_image_editor/utils/pro_image_editor_icons.dart'; /// Represents the bottom bar for the paint functionality in the WhatsApp theme. /// /// This widget provides controls for adjusting the stroke width and color -/// for painting operations, using a design inspired by WhatsApp. +/// for paint operations, using a design inspired by WhatsApp. class WhatsAppPaintBottomBar extends StatefulWidget { /// Creates a [WhatsAppPaintBottomBar] widget. /// /// This bottom bar allows users to select stroke widths and colors for - /// painting, integrating seamlessly with the WhatsApp theme. + /// paint, integrating seamlessly with the WhatsApp theme. /// /// Example: /// ``` @@ -48,9 +48,9 @@ class WhatsAppPaintBottomBar extends StatefulWidget { /// and appearance, ensuring it aligns with the application's overall theme. final ProImageEditorConfigs configs; - /// The current stroke width for painting. + /// The current stroke width for paint. /// - /// This value determines the thickness of the lines drawn in the painting + /// This value determines the thickness of the lines drawn in the paint /// editor, allowing users to customize the appearance of their artwork. final double strokeWidth; @@ -60,7 +60,7 @@ class WhatsAppPaintBottomBar extends StatefulWidget { /// width, allowing the application to update the line thickness. final Function(double value) onSetLineWidth; - /// The initial color for painting. + /// The initial color for paint. /// /// This color sets the initial paint color, providing a starting point /// for color customization. @@ -69,7 +69,7 @@ class WhatsAppPaintBottomBar extends StatefulWidget { /// Callback function for handling color changes. /// /// This function is called whenever the user selects a new color, allowing - /// the application to update the painting color. + /// the application to update the paint color. final ValueChanged onColorChanged; /// Icon representing thin stroke width. @@ -150,8 +150,8 @@ class _WhatsAppPaintBottomBarState extends State { Widget _buildLineWidths() { ButtonStyle buttonStyle = IconButton.styleFrom( backgroundColor: Colors.black38, - foregroundColor: widget - .configs.imageEditorTheme.paintingEditor.bottomBarInactiveItemColor, + foregroundColor: + widget.configs.paintEditor.style.bottomBarInactiveItemColor, padding: const EdgeInsets.all(10), iconSize: 22, minimumSize: const Size.fromRadius(10), diff --git a/lib/designs/whatsapp/whatsapp_paint_colorpicker.dart b/lib/designs/whatsapp/whatsapp_paint_colorpicker.dart index 53ae0bde..33889b68 100644 --- a/lib/designs/whatsapp/whatsapp_paint_colorpicker.dart +++ b/lib/designs/whatsapp/whatsapp_paint_colorpicker.dart @@ -7,15 +7,15 @@ import 'package:flutter/material.dart'; // Project imports: import 'package:pro_image_editor/pro_image_editor.dart'; -/// A stateless widget that provides a color picker for painting in the +/// A stateless widget that provides a color picker for paint in the /// WhatsApp theme. /// -/// This widget allows users to select colors for painting operations within -/// a painting editor, using a design inspired by WhatsApp. +/// This widget allows users to select colors for paint operations within +/// a paint editor, using a design inspired by WhatsApp. class WhatsappPaintColorpicker extends StatelessWidget { /// Creates a [WhatsappPaintColorpicker] widget. /// - /// This color picker lets users select colors for painting within a painting + /// This color picker lets users select colors for paint within a paint /// editor, integrating seamlessly with the WhatsApp theme. /// /// Example: @@ -29,11 +29,11 @@ class WhatsappPaintColorpicker extends StatelessWidget { required this.paintEditor, }); - /// The state of the painting editor associated with this color picker. + /// The state of the paint editor associated with this color picker. /// - /// This state allows the color picker to interact with the painting editor, - /// providing necessary controls to manage painting color selections. - final PaintingEditorState paintEditor; + /// This state allows the color picker to interact with the paint editor, + /// providing necessary controls to manage paint color selections. + final PaintEditorState paintEditor; @override Widget build(BuildContext context) { @@ -61,8 +61,7 @@ class WhatsappPaintColorpicker extends StatelessWidget { thumbColor: Colors.white, cornerRadius: 10, pickMode: PickMode.color, - initialColor: - paintEditor.configs.imageEditorTheme.paintingEditor.initialColor, + initialColor: paintEditor.configs.paintEditor.style.initialColor, colorListener: (int value) { paintEditor.colorChanged(Color(value)); }, diff --git a/lib/designs/whatsapp/whatsapp_sticker_editor.dart b/lib/designs/whatsapp/whatsapp_sticker_editor.dart index 7fd67722..864875d9 100644 --- a/lib/designs/whatsapp/whatsapp_sticker_editor.dart +++ b/lib/designs/whatsapp/whatsapp_sticker_editor.dart @@ -47,7 +47,7 @@ class _WhatsAppStickerPageState extends State { void initState() { _searchCtrl = TextEditingController(); _searchFocus = FocusNode(); - if (widget.configs.stickerEditorConfigs == null) { + if (!widget.configs.stickerEditor.enabled) { whatsAppTemporaryStickerMode = WhatsAppStickerMode.emoji; } super.initState(); @@ -86,7 +86,7 @@ class _WhatsAppStickerPageState extends State { configs: widget.configs, ), ), - if (widget.configs.stickerEditorConfigs != null) + if (widget.configs.stickerEditor.enabled) Offstage( offstage: whatsAppTemporaryStickerMode != WhatsAppStickerMode.sticker, @@ -132,7 +132,7 @@ class _WhatsAppStickerPageState extends State { } }, icon: Icon( - widget.configs.icons.backButton, + widget.configs.mainEditor.icons.backButton, color: Colors.white, ), ), @@ -142,7 +142,7 @@ class _WhatsAppStickerPageState extends State { ), onPressed: () {}, icon: Icon( - widget.configs.icons.stickerEditor.bottomNavBar, + widget.configs.stickerEditor.icons.bottomNavBar, color: Colors.white, ), ), @@ -171,7 +171,7 @@ class _WhatsAppStickerPageState extends State { color: Colors.white, ), ), - if (widget.configs.stickerEditorConfigs != null) + if (widget.configs.stickerEditor.enabled) Align( alignment: Alignment.center, child: SegmentedButton( @@ -235,13 +235,12 @@ class _WhatsAppStickerPageState extends State { ), AnimatedSwitcher( duration: const Duration(milliseconds: 180), - reverseDuration: widget.configs.stickerEditorConfigs != null - ? null - : const Duration(), + reverseDuration: + widget.configs.stickerEditor.enabled ? null : const Duration(), switchInCurve: Curves.easeInOut, transitionBuilder: (child, animation) => FadeTransition( opacity: animation, - child: widget.configs.stickerEditorConfigs != null + child: widget.configs.stickerEditor.enabled ? SizeTransition( sizeFactor: animation, axisAlignment: -1, @@ -259,15 +258,14 @@ class _WhatsAppStickerPageState extends State { padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: AnimatedSwitcher( duration: Duration( - milliseconds: - widget.configs.stickerEditorConfigs != null ? 160 : 0), + milliseconds: widget.configs.stickerEditor.enabled ? 160 : 0), switchInCurve: Curves.easeInOut, transitionBuilder: (child, animation) => FadeTransition( opacity: animation, child: child, ), child: _activeSearch - ? (widget.configs.stickerEditorConfigs != null + ? (widget.configs.stickerEditor.enabled ? Row( children: [ Expanded( @@ -290,12 +288,12 @@ class _WhatsAppStickerPageState extends State { icon: const Icon(Icons.search), color: Colors.white, ), - if (widget.configs.stickerEditorConfigs != null) + if (widget.configs.stickerEditor.enabled) _buildCupertinoSegments(), IconButton( onPressed: null, icon: Icon( - widget.configs.icons.stickerEditor.bottomNavBar, + widget.configs.stickerEditor.icons.bottomNavBar, color: Colors.white, ), ), @@ -323,14 +321,14 @@ class _WhatsAppStickerPageState extends State { WhatsAppStickerMode.emoji: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Icon( - widget.configs.icons.emojiEditor.bottomNavBar, + widget.configs.emojiEditor.icons.bottomNavBar, color: Colors.white, ), ), WhatsAppStickerMode.sticker: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Icon( - widget.configs.icons.stickerEditor.bottomNavBar, + widget.configs.stickerEditor.icons.bottomNavBar, color: Colors.white, ), ), diff --git a/lib/designs/whatsapp/whatsapp_text_appbar.dart b/lib/designs/whatsapp/whatsapp_text_appbar.dart index 3126ac35..be45abf6 100644 --- a/lib/designs/whatsapp/whatsapp_text_appbar.dart +++ b/lib/designs/whatsapp/whatsapp_text_appbar.dart @@ -61,17 +61,17 @@ class _WhatsAppTextAppBarState extends State { tooltip: widget.configs.i18n.textEditor.textAlign, onPressed: widget.onAlignChange, icon: Icon(widget.align == TextAlign.left - ? widget.configs.icons.textEditor.alignLeft + ? widget.configs.textEditor.icons.alignLeft : widget.align == TextAlign.right - ? widget.configs.icons.textEditor.alignRight - : widget.configs.icons.textEditor.alignCenter), + ? widget.configs.textEditor.icons.alignRight + : widget.configs.textEditor.icons.alignCenter), ), gap, IconButton( style: whatsAppButtonStyle, tooltip: widget.configs.i18n.textEditor.backgroundMode, onPressed: widget.onBackgroundModeChange, - icon: Icon(widget.configs.icons.textEditor.backgroundMode), + icon: Icon(widget.configs.textEditor.icons.backgroundMode), ), ], ), @@ -81,8 +81,7 @@ class _WhatsAppTextAppBarState extends State { ? Alignment.centerLeft : Alignment.centerRight, child: WhatsAppDoneBtn( - foregroundColor: widget.configs.imageEditorTheme.paintingEditor - .appBarForegroundColor, + foregroundColor: widget.configs.textEditor.style.appBarColor, configs: widget.configs, onPressed: widget.onDone, ), diff --git a/lib/designs/whatsapp/whatsapp_text_bottombar.dart b/lib/designs/whatsapp/whatsapp_text_bottombar.dart index c5c9a588..b1569346 100644 --- a/lib/designs/whatsapp/whatsapp_text_bottombar.dart +++ b/lib/designs/whatsapp/whatsapp_text_bottombar.dart @@ -107,8 +107,8 @@ class _WhatsAppTextBottomBarState extends State { ? const Icon(Icons.color_lens) : Text( 'Aa', - style: widget.configs.textEditorConfigs - .customTextStyles?.first, + style: + widget.configs.textEditor.customTextStyles?.first, ), style: IconButton.styleFrom(backgroundColor: Colors.black38), ), diff --git a/lib/mixins/converted_configs.dart b/lib/mixins/converted_configs.dart index feb32bfd..d8796df2 100644 --- a/lib/mixins/converted_configs.dart +++ b/lib/mixins/converted_configs.dart @@ -1,5 +1,4 @@ // Project imports: -import 'package:pro_image_editor/models/editor_configs/main_editor_configs.dart'; import 'package:pro_image_editor/pro_image_editor.dart'; /// A mixin providing access to converted configurations from @@ -9,61 +8,50 @@ mixin ImageEditorConvertedConfigs { ProImageEditorConfigs get configs; /// Returns the configuration options for the main editor. - MainEditorConfigs get mainEditorConfigs => configs.mainEditorConfigs; + MainEditorConfigs get mainEditorConfigs => configs.mainEditor; /// Returns the configuration options for the paint editor. - PaintEditorConfigs get paintEditorConfigs => configs.paintEditorConfigs; + PaintEditorConfigs get paintEditorConfigs => configs.paintEditor; /// Returns the configuration options for the text editor. - TextEditorConfigs get textEditorConfigs => configs.textEditorConfigs; + TextEditorConfigs get textEditorConfigs => configs.textEditor; /// Returns the configuration options for the crop and rotate editor. CropRotateEditorConfigs get cropRotateEditorConfigs => - configs.cropRotateEditorConfigs; + configs.cropRotateEditor; /// Returns the configuration options for the filter editor. - FilterEditorConfigs get filterEditorConfigs => configs.filterEditorConfigs; + FilterEditorConfigs get filterEditorConfigs => configs.filterEditor; /// Returns the configuration options for the tune editor. - TuneEditorConfigs get tuneEditorConfigs => configs.tuneEditorConfigs; + TuneEditorConfigs get tuneEditorConfigs => configs.tuneEditor; /// Returns the configuration options for the blur editor. - BlurEditorConfigs get blurEditorConfigs => configs.blurEditorConfigs; + BlurEditorConfigs get blurEditorConfigs => configs.blurEditor; /// Returns the configuration options for the emoji editor. - EmojiEditorConfigs get emojiEditorConfigs => configs.emojiEditorConfigs; + EmojiEditorConfigs get emojiEditorConfigs => configs.emojiEditor; /// Returns the configuration options for the sticker editor. - StickerEditorConfigs? get stickerEditorConfigs => - configs.stickerEditorConfigs; + StickerEditorConfigs get stickerEditorConfigs => configs.stickerEditor; /// Returns the design mode for the image editor. ImageEditorDesignModeE get designMode => configs.designMode; - /// Returns the theme settings for the image editor. - ImageEditorTheme get imageEditorTheme => configs.imageEditorTheme; - - /// Returns custom widget configurations for the image editor. - ImageEditorCustomWidgets get customWidgets => configs.customWidgets; - - /// Returns the icons used in the image editor. - ImageEditorIcons get icons => configs.icons; - /// Returns the internationalization settings for the image editor. I18n get i18n => configs.i18n; /// Returns helper lines configurations for the image editor. - HelperLines get helperLines => configs.helperLines; + HelperLineConfigs get helperLines => configs.helperLines; /// Returns layerInteraction configurations for the image editor. - LayerInteraction get layerInteraction => configs.layerInteraction; + LayerInteractionConfigs get layerInteraction => configs.layerInteraction; /// Gets the configurations related to state history management. - StateHistoryConfigs get stateHistoryConfigs => configs.stateHistoryConfigs; + StateHistoryConfigs get stateHistoryConfigs => configs.stateHistory; /// Gets the configurations related to image generation. - ImageGenerationConfigs get imageGenerationConfigs => - configs.imageGenerationConfigs; + ImageGenerationConfigs get imageGenerationConfigs => configs.imageGeneration; /// Returns the hero tag used in the image editor. String get heroTag => configs.heroTag; diff --git a/lib/mixins/main_editor/main_editor_global_keys.dart b/lib/mixins/main_editor/main_editor_global_keys.dart index 774790fc..b3c90500 100644 --- a/lib/mixins/main_editor/main_editor_global_keys.dart +++ b/lib/mixins/main_editor/main_editor_global_keys.dart @@ -12,9 +12,9 @@ import '../../modules/tune_editor/tune_editor.dart'; /// Mixin which contains all global keys for the main-editor mixin MainEditorGlobalKeys { - /// A GlobalKey for the Painting Editor, used to access and control the state - /// of the painting editor. - final paintingEditor = GlobalKey(); + /// A GlobalKey for the Paint Editor, used to access and control the state + /// of the paint editor. + final paintEditor = GlobalKey(); /// A GlobalKey for the Text Editor, used to access and control the state of /// the text editor. diff --git a/lib/models/custom_widgets/custom_widgets_blur_editor.dart b/lib/models/custom_widgets/blur_editor_widgets.dart similarity index 86% rename from lib/models/custom_widgets/custom_widgets_blur_editor.dart rename to lib/models/custom_widgets/blur_editor_widgets.dart index 448e04ce..77da907e 100644 --- a/lib/models/custom_widgets/custom_widgets_blur_editor.dart +++ b/lib/models/custom_widgets/blur_editor_widgets.dart @@ -7,9 +7,8 @@ import 'utils/custom_widgets_typedef.dart'; /// /// This widget extends the standalone editor for the blur editor state, /// providing a customizable interface for applying and adjusting blur effects. -class CustomWidgetsBlurEditor - extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsBlurEditor] widget. +class BlurEditorWidgets extends CustomWidgetsStandaloneEditor { + /// Creates a [BlurEditorWidgets] widget. /// /// This widget allows customization of the app bar, bottom bar, body items, /// and slider for the blur editor, enabling a flexible design tailored to @@ -17,14 +16,14 @@ class CustomWidgetsBlurEditor /// /// Example: /// ``` - /// CustomWidgetsBlurEditor( + /// BlurEditorWidgets( /// appBar: myAppBar, /// bottomBar: myBottomBar, /// bodyItems: myBodyItems, /// slider: mySlider, /// ) /// ``` - const CustomWidgetsBlurEditor({ + const BlurEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -41,7 +40,7 @@ class CustomWidgetsBlurEditor final CustomSlider? slider; @override - CustomWidgetsBlurEditor copyWith({ + BlurEditorWidgets copyWith({ ReactiveCustomAppbar? Function( BlurEditorState editorState, Stream rebuildStream)? appBar, @@ -52,7 +51,7 @@ class CustomWidgetsBlurEditor CustomBodyItems? bodyItemsRecorded, CustomSlider? slider, }) { - return CustomWidgetsBlurEditor( + return BlurEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItems: bodyItems ?? this.bodyItems, diff --git a/lib/models/custom_widgets/custom_widgets_crop_rotate_editor.dart b/lib/models/custom_widgets/crop_rotate_editor_widgets.dart similarity index 89% rename from lib/models/custom_widgets/custom_widgets_crop_rotate_editor.dart rename to lib/models/custom_widgets/crop_rotate_editor_widgets.dart index c0ab7147..14b78d23 100644 --- a/lib/models/custom_widgets/custom_widgets_crop_rotate_editor.dart +++ b/lib/models/custom_widgets/crop_rotate_editor_widgets.dart @@ -8,9 +8,9 @@ import 'utils/custom_widgets_typedef.dart'; /// This widget extends the standalone editor for the crop and rotate editor /// state, providing a customizable interface for applying and adjusting crop /// and rotate transformations. -class CustomWidgetsCropRotateEditor +class CropRotateEditorWidgets extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsCropRotateEditor] widget. + /// Creates a [CropRotateEditorWidgets] widget. /// /// This widget allows customization of the app bar, bottom bar, body items, /// and additional widgets specific to crop and rotate functionality, @@ -18,13 +18,13 @@ class CustomWidgetsCropRotateEditor /// /// Example: /// ``` - /// CustomWidgetsCropRotateEditor( + /// CropRotateEditorWidgets( /// appBar: myAppBar, /// bottomBar: myBottomBar, /// bodyItems: myBodyItems, /// ) /// ``` - const CustomWidgetsCropRotateEditor({ + const CropRotateEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -46,7 +46,7 @@ class CustomWidgetsCropRotateEditor final CropEditorAspectRatioOptions? aspectRatioOptions; @override - CustomWidgetsCropRotateEditor copyWith({ + CropRotateEditorWidgets copyWith({ ReactiveCustomAppbar? Function( CropRotateEditorState editorState, Stream rebuildStream)? appBar, @@ -56,7 +56,7 @@ class CustomWidgetsCropRotateEditor CustomBodyItems? bodyItems, CropEditorAspectRatioOptions? aspectRatioOptions, }) { - return CustomWidgetsCropRotateEditor( + return CropRotateEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItems: bodyItems ?? this.bodyItems, diff --git a/lib/models/custom_widgets/custom_widgets.dart b/lib/models/custom_widgets/custom_widgets.dart deleted file mode 100644 index 51d9a732..00000000 --- a/lib/models/custom_widgets/custom_widgets.dart +++ /dev/null @@ -1,160 +0,0 @@ -// Flutter imports: -import 'package:flutter/widgets.dart'; -import 'package:pro_image_editor/models/editor_configs/pro_image_editor_configs.dart'; - -import 'custom_widgets_layer_interaction.dart'; - -export 'custom_widgets_blur_editor.dart'; -export 'custom_widgets_crop_rotate_editor.dart'; -export 'custom_widgets_filter_editor.dart'; -export 'custom_widgets_main_editor.dart'; -export 'custom_widgets_paint_editor.dart'; -export 'custom_widgets_text_editor.dart'; -export 'custom_widgets_tune_editor.dart'; - -/// The `ImageEditorCustomWidgets` class encapsulates custom widget components -/// that can be used within various parts of the application's user interface. -/// It provides flexibility for customizing the appearance and behavior of -/// specific UI elements such as app bars, bottom navigation bars, and more. -class ImageEditorCustomWidgets { - /// Creates an instance of the `CustomWidgets` class with the specified - /// properties. - const ImageEditorCustomWidgets({ - this.loadingDialog, - this.circularProgressIndicator, - this.mainEditor = const CustomWidgetsMainEditor(), - this.paintEditor = const CustomWidgetsPaintEditor(), - this.textEditor = const CustomWidgetsTextEditor(), - this.cropRotateEditor = const CustomWidgetsCropRotateEditor(), - this.filterEditor = const CustomWidgetsFilterEditor(), - this.blurEditor = const CustomWidgetsBlurEditor(), - this.tuneEditor = const CustomWidgetsTuneEditor(), - this.layerInteraction = const CustomWidgetsLayerInteraction(), - }); - - /// The main editor instance. - final CustomWidgetsMainEditor mainEditor; - - /// The paint editor instance. - final CustomWidgetsPaintEditor paintEditor; - - /// The text editor instance. - final CustomWidgetsTextEditor textEditor; - - /// The crop and rotate editor instance. - final CustomWidgetsCropRotateEditor cropRotateEditor; - - /// The filter editor instance. - final CustomWidgetsFilterEditor filterEditor; - - /// The tune editor instance. - final CustomWidgetsTuneEditor tuneEditor; - - /// The blur editor instance. - final CustomWidgetsBlurEditor blurEditor; - - /// Defines the set of interactions (edit, remove, rotate/scale) for - /// custom widgets. - final CustomWidgetsLayerInteraction layerInteraction; - - /// Replace the existing loading dialog. - /// - /// **Example:** - /// ```dart - /// loadingDialog: (message, configs) => Stack( - /// children: [ - /// ModalBarrier( - /// onDismiss: kDebugMode ? LoadingDialog.instance.hide : null, - /// color: Colors.black54, - /// dismissible: kDebugMode, - /// ), - /// Center( - /// child: Theme( - /// data: Theme.of(context), - /// child: AlertDialog( - /// contentPadding: - /// const EdgeInsets.symmetric(vertical: 16, horizontal: 20), - /// content: ConstrainedBox( - /// constraints: const BoxConstraints(maxWidth: 500), - /// child: Padding( - /// padding: const EdgeInsets.only(top: 3.0), - /// child: Row( - /// crossAxisAlignment: CrossAxisAlignment.center, - /// mainAxisAlignment: MainAxisAlignment.start, - /// children: [ - /// Padding( - /// padding: const EdgeInsets.only(right: 20.0), - /// child: SizedBox( - /// height: 40, - /// width: 40, - /// child: FittedBox( - /// child: PlatformCircularProgressIndicator( - /// configs: configs, - /// ), - /// ), - /// ), - /// ), - /// Expanded( - /// child: Text( - /// message, - /// style: platformTextStyle( - /// context, - /// configs.designMode, - /// ).copyWith( - /// fontSize: 16, - /// color: configs.imageEditorTheme - /// .loadingDialogTheme.textColor, - /// ), - /// textAlign: TextAlign.start, - /// ), - /// ), - /// ], - /// ), - /// ), - /// ), - /// ), - /// ), - /// ), - /// ], - /// ), - /// ``` - final Widget Function(String message, ProImageEditorConfigs configs)? - loadingDialog; - - /// Replace the existing CircularProgressIndicator. - final Widget? circularProgressIndicator; - - /// Creates a copy of this `ImageEditorCustomWidgets` object with the given - /// fields replaced with new values. - /// - /// The [copyWith] method allows you to create a new instance of - /// [ImageEditorCustomWidgets] with some properties updated while keeping the - /// others unchanged. - ImageEditorCustomWidgets copyWith({ - CustomWidgetsMainEditor? mainEditor, - CustomWidgetsPaintEditor? paintEditor, - CustomWidgetsTextEditor? textEditor, - CustomWidgetsCropRotateEditor? cropRotateEditor, - CustomWidgetsFilterEditor? filterEditor, - CustomWidgetsTuneEditor? tuneEditor, - CustomWidgetsBlurEditor? blurEditor, - Widget Function(String message, ProImageEditorConfigs configs)? - loadingDialog, - Widget? circularProgressIndicator, - CustomWidgetsLayerInteraction? layerInteraction, - }) { - return ImageEditorCustomWidgets( - mainEditor: mainEditor ?? this.mainEditor, - paintEditor: paintEditor ?? this.paintEditor, - textEditor: textEditor ?? this.textEditor, - cropRotateEditor: cropRotateEditor ?? this.cropRotateEditor, - filterEditor: filterEditor ?? this.filterEditor, - tuneEditor: tuneEditor ?? this.tuneEditor, - blurEditor: blurEditor ?? this.blurEditor, - loadingDialog: loadingDialog ?? this.loadingDialog, - circularProgressIndicator: - circularProgressIndicator ?? this.circularProgressIndicator, - layerInteraction: layerInteraction ?? this.layerInteraction, - ); - } -} diff --git a/lib/models/custom_widgets/dialog_widgets.dart b/lib/models/custom_widgets/dialog_widgets.dart new file mode 100644 index 00000000..a2c88876 --- /dev/null +++ b/lib/models/custom_widgets/dialog_widgets.dart @@ -0,0 +1,83 @@ +import 'package:flutter/widgets.dart'; + +import '../editor_configs/pro_image_editor_configs.dart'; + +/// Defines customizable widgets for the dialog in the editor. +class DialogWidgets { + /// Creates a new instance of [DialogWidgets]. + const DialogWidgets({ + this.loadingDialog, + }); + + /// Replace the existing loading dialog. + /// + /// **Example:** + /// ```dart + /// loadingDialog: (message, configs) => Stack( + /// children: [ + /// ModalBarrier( + /// onDismiss: kDebugMode ? LoadingDialog.instance.hide : null, + /// color: Colors.black54, + /// dismissible: kDebugMode, + /// ), + /// Center( + /// child: Theme( + /// data: Theme.of(context), + /// child: AlertDialog( + /// contentPadding: + /// const EdgeInsets.symmetric(vertical: 16, horizontal: 20), + /// content: ConstrainedBox( + /// constraints: const BoxConstraints(maxWidth: 500), + /// child: Padding( + /// padding: const EdgeInsets.only(top: 3.0), + /// child: Row( + /// crossAxisAlignment: CrossAxisAlignment.center, + /// mainAxisAlignment: MainAxisAlignment.start, + /// children: [ + /// Padding( + /// padding: const EdgeInsets.only(right: 20.0), + /// child: SizedBox( + /// height: 40, + /// width: 40, + /// child: FittedBox( + /// child: PlatformCircularProgressIndicator( + /// configs: configs, + /// ), + /// ), + /// ), + /// ), + /// Expanded( + /// child: Text( + /// message, + /// style: platformTextStyle( + /// context, + /// configs.designMode, + /// ).copyWith( + /// fontSize: 16, + /// color: configs.imageEditorTheme + /// .loadingDialogTheme.textColor, + /// ), + /// textAlign: TextAlign.start, + /// ), + /// ), + /// ], + /// ), + /// ), + /// ), + /// ), + /// ), + /// ), + /// ], + /// ), + /// ``` + final Widget Function(String message, ProImageEditorConfigs configs)? + loadingDialog; + + /// Creates a copy of this widget configuration with specified overrides. + DialogWidgets copyWith({ + Widget Function(String message, ProImageEditorConfigs configs)? + loadingDialog, + }) { + return DialogWidgets(loadingDialog: loadingDialog ?? this.loadingDialog); + } +} diff --git a/lib/models/custom_widgets/custom_widgets_filter_editor.dart b/lib/models/custom_widgets/filter_editor_widgets.dart similarity index 93% rename from lib/models/custom_widgets/custom_widgets_filter_editor.dart rename to lib/models/custom_widgets/filter_editor_widgets.dart index 4152b6e9..731941c7 100644 --- a/lib/models/custom_widgets/custom_widgets_filter_editor.dart +++ b/lib/models/custom_widgets/filter_editor_widgets.dart @@ -11,14 +11,14 @@ import 'utils/custom_widgets_typedef.dart'; /// This widget extends the standalone editor for the filter editor state, /// providing a customizable interface for applying and adjusting image filters. -class CustomWidgetsFilterEditor +class FilterEditorWidgets extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsFilterEditor] widget. + /// Creates a [FilterEditorWidgets] widget. /// /// This widget allows customization of the app bar, bottom bar, body items, /// and additional widgets specific to filter functionality, enabling a /// flexible design tailored to specific needs. - const CustomWidgetsFilterEditor({ + const FilterEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -58,7 +58,7 @@ class CustomWidgetsFilterEditor )? filterButton; @override - CustomWidgetsFilterEditor copyWith({ + FilterEditorWidgets copyWith({ ReactiveCustomAppbar? Function( FilterEditorState editorState, Stream rebuildStream)? appBar, @@ -77,7 +77,7 @@ class CustomWidgetsFilterEditor Key filterKey, )? filterButton, }) { - return CustomWidgetsFilterEditor( + return FilterEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItems: bodyItems ?? this.bodyItems, diff --git a/lib/models/custom_widgets/custom_widgets_layer_interaction.dart b/lib/models/custom_widgets/layer_interaction_widgets.dart similarity index 87% rename from lib/models/custom_widgets/custom_widgets_layer_interaction.dart rename to lib/models/custom_widgets/layer_interaction_widgets.dart index 1b7d7939..4c11e493 100644 --- a/lib/models/custom_widgets/custom_widgets_layer_interaction.dart +++ b/lib/models/custom_widgets/layer_interaction_widgets.dart @@ -8,21 +8,21 @@ import 'utils/custom_widgets_typedef.dart'; /// /// Example usage: /// ```dart -/// CustomWidgetsLayerInteraction( +/// LayerInteractionWidgets( /// editIcon: LayerInteractionTapButton(...), /// removeIcon: LayerInteractionTapButton(...), /// rotateScaleIcon: LayerInteractionScaleRotateButton(...), /// ); /// ``` -class CustomWidgetsLayerInteraction { - /// Creates a [CustomWidgetsLayerInteraction] with optional interaction +class LayerInteractionWidgets { + /// Creates a [LayerInteractionWidgets] with optional interaction /// buttons. /// /// * [editIcon]: A button that triggers the edit action. /// * [removeIcon]: A button that triggers the remove action. /// * [rotateScaleIcon]: A button for rotate/scale actions. - const CustomWidgetsLayerInteraction({ + const LayerInteractionWidgets({ this.editIcon, this.removeIcon, this.rotateScaleIcon, @@ -47,12 +47,12 @@ class CustomWidgetsLayerInteraction { /// * [editIcon]: Updates the button for the edit action. /// * [removeIcon]: Updates the button for the remove action. /// * [rotateScaleIcon]: Updates the button for rotate/scale actions. - CustomWidgetsLayerInteraction copyWith({ + LayerInteractionWidgets copyWith({ LayerInteractionTapButton? editIcon, LayerInteractionTapButton? removeIcon, LayerInteractionScaleRotateButton? rotateScaleIcon, }) { - return CustomWidgetsLayerInteraction( + return LayerInteractionWidgets( editIcon: editIcon ?? this.editIcon, removeIcon: removeIcon ?? this.removeIcon, rotateScaleIcon: rotateScaleIcon ?? this.rotateScaleIcon, diff --git a/lib/models/custom_widgets/custom_widgets_main_editor.dart b/lib/models/custom_widgets/main_editor_widgets.dart similarity index 92% rename from lib/models/custom_widgets/custom_widgets_main_editor.dart rename to lib/models/custom_widgets/main_editor_widgets.dart index 85286abe..f395a5f0 100644 --- a/lib/models/custom_widgets/custom_widgets_main_editor.dart +++ b/lib/models/custom_widgets/main_editor_widgets.dart @@ -10,15 +10,15 @@ import 'utils/custom_widgets_typedef.dart'; /// This widget provides a customizable interface for the main editing area, /// allowing for configuration of the app bar, bottom bar, body items, and /// additional components specific to the main editor functionality. -class CustomWidgetsMainEditor { - /// Creates a [CustomWidgetsMainEditor] widget. +class MainEditorWidgets { + /// Creates a [MainEditorWidgets] widget. /// /// This widget allows customization of various components in the main editor, /// enabling a flexible design tailored to specific editing needs. /// /// Example: /// ``` - /// CustomWidgetsMainEditor( + /// MainEditorWidgets( /// appBar: myAppBar, /// bottomBar: myBottomBar, /// bodyItems: myBodyItems, @@ -27,7 +27,7 @@ class CustomWidgetsMainEditor { /// wrapBody: myWrapBody, /// ) /// ``` - const CustomWidgetsMainEditor({ + const MainEditorWidgets({ this.closeWarningDialog, this.removeLayerArea, this.wrapBody, @@ -124,13 +124,13 @@ class CustomWidgetsMainEditor { /// {@macro customBodyItemRecorded} final CustomBodyItems? bodyItemsRecorded; - /// Creates a copy of this `CustomWidgetsMainEditor` object with the given + /// Creates a copy of this `MainEditorWidgets` object with the given /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [CustomWidgetsMainEditor] with some properties updated while keeping the + /// [MainEditorWidgets] with some properties updated while keeping the /// others unchanged. - CustomWidgetsMainEditor copyWith({ + MainEditorWidgets copyWith({ Future Function(ProImageEditorState editor)? closeWarningDialog, RemoveLayerArea? removeLayerArea, Widget Function( @@ -150,7 +150,7 @@ class CustomWidgetsMainEditor { CustomBodyItems? bodyItems, CustomBodyItems? bodyItemsRecorded, }) { - return CustomWidgetsMainEditor( + return MainEditorWidgets( closeWarningDialog: closeWarningDialog ?? this.closeWarningDialog, removeLayerArea: removeLayerArea ?? this.removeLayerArea, wrapBody: wrapBody ?? this.wrapBody, diff --git a/lib/models/custom_widgets/custom_widgets_paint_editor.dart b/lib/models/custom_widgets/paint_editor_widgets.dart similarity index 66% rename from lib/models/custom_widgets/custom_widgets_paint_editor.dart rename to lib/models/custom_widgets/paint_editor_widgets.dart index 6a9c00bf..4d9f46b3 100644 --- a/lib/models/custom_widgets/custom_widgets_paint_editor.dart +++ b/lib/models/custom_widgets/paint_editor_widgets.dart @@ -6,19 +6,19 @@ import 'package:pro_image_editor/pro_image_editor.dart'; import 'utils/custom_widgets_standalone_editor.dart'; import 'utils/custom_widgets_typedef.dart'; -/// A custom widget for editing paint effects in an image editor. +/// A list of custom widgets for the paint editor. /// -/// This widget extends the standalone editor for the painting editor state, -/// providing a customizable interface for applying and adjusting painting +/// This widget extends the standalone editor for the paint editor state, +/// providing a customizable interface for applying and adjusting paint /// effects, such as line width, opacity, and color selection. -class CustomWidgetsPaintEditor - extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsPaintEditor] widget. +class PaintEditorWidgets + extends CustomWidgetsStandaloneEditor { + /// Creates a [PaintEditorWidgets] widget. /// /// This widget allows customization of the app bar, bottom bar, body items, - /// and additional components specific to painting functionality, enabling a + /// and additional components specific to paint functionality, enabling a /// flexible design tailored to specific needs. - const CustomWidgetsPaintEditor({ + const PaintEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -43,7 +43,7 @@ class CustomWidgetsPaintEditor /// }, /// ``` final Widget Function( - PaintingEditorState editorState, + PaintEditorState editorState, Function() tap, )? lineWidthCloseButton; @@ -60,44 +60,44 @@ class CustomWidgetsPaintEditor /// }, /// ``` final Widget Function( - PaintingEditorState editorState, + PaintEditorState editorState, Function() tap, )? changeOpacityCloseButton; /// A custom slider widget for the line width in the paint editor. /// /// {@macro customSliderWidget} - final CustomSlider? sliderLineWidth; + final CustomSlider? sliderLineWidth; /// A custom slider widget to change the line width in the paint editor. /// /// {@macro customSliderWidget} - final CustomSlider? sliderChangeOpacity; + final CustomSlider? sliderChangeOpacity; /// A custom color picker widget for the paint editor. /// /// {@macro colorPickerWidget} - final CustomColorPicker? colorPicker; + final CustomColorPicker? colorPicker; @override - CustomWidgetsPaintEditor copyWith({ + PaintEditorWidgets copyWith({ ReactiveCustomAppbar? Function( - PaintingEditorState editorState, Stream rebuildStream)? + PaintEditorState editorState, Stream rebuildStream)? appBar, ReactiveCustomWidget? Function( - PaintingEditorState editorState, Stream rebuildStream)? + PaintEditorState editorState, Stream rebuildStream)? bottomBar, - CustomBodyItems? bodyItems, - CustomBodyItems? bodyItemsRecorded, - Widget Function(PaintingEditorState editorState, Function() tap)? + CustomBodyItems? bodyItems, + CustomBodyItems? bodyItemsRecorded, + Widget Function(PaintEditorState editorState, Function() tap)? lineWidthCloseButton, - Widget Function(PaintingEditorState editorState, Function() tap)? + Widget Function(PaintEditorState editorState, Function() tap)? changeOpacityCloseButton, - CustomSlider? sliderLineWidth, - CustomSlider? sliderChangeOpacity, - CustomColorPicker? colorPicker, + CustomSlider? sliderLineWidth, + CustomSlider? sliderChangeOpacity, + CustomColorPicker? colorPicker, }) { - return CustomWidgetsPaintEditor( + return PaintEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItems: bodyItems ?? this.bodyItems, diff --git a/lib/models/custom_widgets/progress_indicator_widgets.dart b/lib/models/custom_widgets/progress_indicator_widgets.dart new file mode 100644 index 00000000..9711127c --- /dev/null +++ b/lib/models/custom_widgets/progress_indicator_widgets.dart @@ -0,0 +1,22 @@ +import 'package:flutter/widgets.dart'; + +/// Configuration class for customizing progress indicators. +class ProgressIndicatorWidgets { + /// Creates a new instance of [ProgressIndicatorWidgets]. + const ProgressIndicatorWidgets({ + this.circularProgressIndicator, + }); + + /// Custom widget to replace the default [CircularProgressIndicator]. + final Widget? circularProgressIndicator; + + /// Creates a copy of this configuration with the specified overrides. + ProgressIndicatorWidgets copyWith({ + Widget? circularProgressIndicator, + }) { + return ProgressIndicatorWidgets( + circularProgressIndicator: + circularProgressIndicator ?? this.circularProgressIndicator, + ); + } +} diff --git a/lib/models/custom_widgets/custom_widgets_text_editor.dart b/lib/models/custom_widgets/text_editor_widgets.dart similarity index 90% rename from lib/models/custom_widgets/custom_widgets_text_editor.dart rename to lib/models/custom_widgets/text_editor_widgets.dart index 06598f39..b0052515 100644 --- a/lib/models/custom_widgets/custom_widgets_text_editor.dart +++ b/lib/models/custom_widgets/text_editor_widgets.dart @@ -13,9 +13,8 @@ import 'utils/custom_widgets_typedef.dart'; /// This widget extends the standalone editor for the text editor state, /// providing a customizable interface for applying and adjusting text /// properties such as color and font size. -class CustomWidgetsTextEditor - extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsTextEditor] widget. +class TextEditorWidgets extends CustomWidgetsStandaloneEditor { + /// Creates a [TextEditorWidgets] widget. /// /// This widget allows customization of the app bar, bottom bar, body items, /// and additional components specific to text editing functionality, @@ -23,7 +22,7 @@ class CustomWidgetsTextEditor /// /// Example: /// ``` - /// CustomWidgetsTextEditor( + /// TextEditorWidgets( /// appBar: myAppBar, /// bottomBar: myBottomBar, /// bodyItems: myBodyItems, @@ -32,7 +31,7 @@ class CustomWidgetsTextEditor /// fontSizeCloseButton: myFontSizeCloseButton, /// ) /// ``` - const CustomWidgetsTextEditor({ + const TextEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -68,7 +67,7 @@ class CustomWidgetsTextEditor final CustomSlider? sliderFontSize; @override - CustomWidgetsTextEditor copyWith({ + TextEditorWidgets copyWith({ ReactiveCustomAppbar? Function( TextEditorState editorState, Stream rebuildStream)? appBar, @@ -81,7 +80,7 @@ class CustomWidgetsTextEditor Widget Function(TextEditorState editorState, Function() tap)? fontSizeCloseButton, }) { - return CustomWidgetsTextEditor( + return TextEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItems: bodyItems ?? this.bodyItems, diff --git a/lib/models/custom_widgets/custom_widgets_tune_editor.dart b/lib/models/custom_widgets/tune_editor_widgets.dart similarity index 87% rename from lib/models/custom_widgets/custom_widgets_tune_editor.dart rename to lib/models/custom_widgets/tune_editor_widgets.dart index cdc41009..2cff38f2 100644 --- a/lib/models/custom_widgets/custom_widgets_tune_editor.dart +++ b/lib/models/custom_widgets/tune_editor_widgets.dart @@ -9,15 +9,14 @@ import 'utils/custom_widgets_typedef.dart'; /// This widget provides an interface to adjust the tune settings /// of an image editor using various UI components like app bar, /// bottom bar, and body items. -class CustomWidgetsTuneEditor - extends CustomWidgetsStandaloneEditor { - /// Creates a [CustomWidgetsTuneEditor] with optional appBar, +class TuneEditorWidgets extends CustomWidgetsStandaloneEditor { + /// Creates a [TuneEditorWidgets] with optional appBar, /// bottomBar, bodyItems, and a custom slider widget. /// /// The [appBar], [bottomBar], and [bodyItems] are reactive widgets /// that rebuild based on the [TuneEditorState]. The [slider] allows /// the user to adjust tune parameters. - const CustomWidgetsTuneEditor({ + const TuneEditorWidgets({ super.appBar, super.bottomBar, super.bodyItems, @@ -33,7 +32,7 @@ class CustomWidgetsTuneEditor /// {@macro customSliderWidget} final CustomSlider? slider; - /// Copies the current [CustomWidgetsTuneEditor] with new values for + /// Copies the current [TuneEditorWidgets] with new values for /// [appBar], [bottomBar], [bodyItems], or [slider]. /// /// If any of these are not provided, the existing value will be used. @@ -46,7 +45,7 @@ class CustomWidgetsTuneEditor /// widgets based on the editor state and a rebuild stream. /// - [slider] is a custom slider for the tune editor. @override - CustomWidgetsTuneEditor copyWith({ + TuneEditorWidgets copyWith({ ReactiveCustomAppbar? Function( TuneEditorState editorState, Stream rebuildStream)? appBar, @@ -57,7 +56,7 @@ class CustomWidgetsTuneEditor CustomBodyItems? bodyItemsRecorded, CustomSlider? slider, }) { - return CustomWidgetsTuneEditor( + return TuneEditorWidgets( appBar: appBar ?? this.appBar, bottomBar: bottomBar ?? this.bottomBar, bodyItemsRecorded: bodyItemsRecorded ?? this.bodyItemsRecorded, diff --git a/lib/models/editor_configs/blur_editor_configs.dart b/lib/models/editor_configs/blur_editor_configs.dart index 1fab3229..79d3a68e 100644 --- a/lib/models/editor_configs/blur_editor_configs.dart +++ b/lib/models/editor_configs/blur_editor_configs.dart @@ -1,5 +1,12 @@ +import '../custom_widgets/blur_editor_widgets.dart'; +import '../icons/blur_editor_icons.dart'; +import '../styles/blur_editor_style.dart'; import 'utils/editor_safe_area.dart'; +export '../custom_widgets/blur_editor_widgets.dart'; +export '../icons/blur_editor_icons.dart'; +export '../styles/blur_editor_style.dart'; + /// Configuration options for a blur editor. /// /// `BlurEditorConfigs` allows you to define settings for a blur editor, @@ -21,6 +28,9 @@ class BlurEditorConfigs { this.showLayers = true, this.maxBlur = 5.0, this.safeArea = const EditorSafeArea(), + this.style = const BlurEditorStyle(), + this.icons = const BlurEditorIcons(), + this.widgets = const BlurEditorWidgets(), }) : assert(maxBlur > 0, 'maxBlur must be positive'); /// Indicates whether the blur editor is enabled. @@ -35,6 +45,15 @@ class BlurEditorConfigs { /// Defines the safe area configuration for the editor. final EditorSafeArea safeArea; + /// Style configuration for the blur editor. + final BlurEditorStyle style; + + /// Icons used in the blur editor. + final BlurEditorIcons icons; + + /// Widgets associated with the blur editor. + final BlurEditorWidgets widgets; + /// Creates a copy of this `BlurEditorConfigs` object with the given fields /// replaced with new values. /// @@ -46,12 +65,18 @@ class BlurEditorConfigs { bool? showLayers, double? maxBlur, EditorSafeArea? safeArea, + BlurEditorStyle? style, + BlurEditorIcons? icons, + BlurEditorWidgets? widgets, }) { return BlurEditorConfigs( safeArea: safeArea ?? this.safeArea, enabled: enabled ?? this.enabled, showLayers: showLayers ?? this.showLayers, maxBlur: maxBlur ?? this.maxBlur, + style: style ?? this.style, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/editor_configs/crop_rotate_editor_configs.dart b/lib/models/editor_configs/crop_rotate_editor_configs.dart index 020309d9..3c4d7971 100644 --- a/lib/models/editor_configs/crop_rotate_editor_configs.dart +++ b/lib/models/editor_configs/crop_rotate_editor_configs.dart @@ -4,9 +4,15 @@ import 'package:flutter/material.dart'; // Project imports: import '../crop_rotate_editor/aspect_ratio_item.dart'; import '../crop_rotate_editor/rotate_direction.dart'; +import '../custom_widgets/crop_rotate_editor_widgets.dart'; +import '../icons/crop_rotate_editor_icons.dart'; +import '../styles/crop_rotate_editor_style.dart'; import 'utils/editor_safe_area.dart'; export '../crop_rotate_editor/rotate_direction.dart'; +export '../custom_widgets/crop_rotate_editor_widgets.dart'; +export '../icons/crop_rotate_editor_icons.dart'; +export '../styles/crop_rotate_editor_style.dart'; /// Configuration options for a crop and rotate editor. /// @@ -67,6 +73,9 @@ class CropRotateEditorConfigs { AspectRatioItem(text: '9*16', value: 9.0 / 16.0) ], this.safeArea = const EditorSafeArea(), + this.style = const CropRotateEditorStyle(), + this.icons = const CropRotateEditorIcons(), + this.widgets = const CropRotateEditorWidgets(), }) : assert(maxScale >= 1, 'maxScale must be greater than or equal to 1'), assert(desktopCornerDragArea > 0, 'desktopCornerDragArea must be positive'), @@ -180,6 +189,15 @@ class CropRotateEditorConfigs { /// Defines the safe area configuration for the editor. final EditorSafeArea safeArea; + /// Style configuration for the crop and rotate editor. + final CropRotateEditorStyle style; + + /// Icons used in the crop and rotate editor. + final CropRotateEditorIcons icons; + + /// Widgets associated with the crop and rotate editor. + final CropRotateEditorWidgets widgets; + /// Creates a copy of this `CropRotateEditorConfigs` object with the given /// fields replaced with new values. /// @@ -215,6 +233,9 @@ class CropRotateEditorConfigs { double? desktopCornerDragArea, double? mobileCornerDragArea, EditorSafeArea? safeArea, + CropRotateEditorStyle? style, + CropRotateEditorIcons? icons, + CropRotateEditorWidgets? widgets, }) { return CropRotateEditorConfigs( safeArea: safeArea ?? this.safeArea, @@ -253,6 +274,9 @@ class CropRotateEditorConfigs { desktopCornerDragArea: desktopCornerDragArea ?? this.desktopCornerDragArea, mobileCornerDragArea: mobileCornerDragArea ?? this.mobileCornerDragArea, + style: style ?? this.style, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/editor_configs/dialog_configs.dart b/lib/models/editor_configs/dialog_configs.dart new file mode 100644 index 00000000..db379b04 --- /dev/null +++ b/lib/models/editor_configs/dialog_configs.dart @@ -0,0 +1,31 @@ +import '../custom_widgets/dialog_widgets.dart'; +import '../styles/dialog_style.dart'; + +export '../custom_widgets/dialog_widgets.dart'; +export '../styles/dialog_style.dart'; + +/// Configuration class for customizing the dialog in the editor. +class DialogConfigs { + /// Creates a new instance of [DialogConfigs]. + const DialogConfigs({ + this.widgets = const DialogWidgets(), + this.style = const DialogStyle(), + }); + + /// Widgets used for customizing the dialogs. + final DialogWidgets widgets; + + /// Style configuration for dialogs in the editor. + final DialogStyle style; + + /// Creates a copy of this configuration with the specified overrides. + DialogConfigs copyWith({ + DialogWidgets? widgets, + DialogStyle? style, + }) { + return DialogConfigs( + widgets: widgets ?? this.widgets, + style: style ?? this.style, + ); + } +} diff --git a/lib/models/editor_configs/emoji_editor_configs.dart b/lib/models/editor_configs/emoji_editor_configs.dart index 6a1e7257..7c8d3fee 100644 --- a/lib/models/editor_configs/emoji_editor_configs.dart +++ b/lib/models/editor_configs/emoji_editor_configs.dart @@ -1,8 +1,11 @@ // Project imports: -import '../../pro_image_editor.dart'; + +import 'emoji_editor_configs.dart'; export 'package:emoji_picker_flutter/emoji_picker_flutter.dart' show CategoryEmoji, defaultEmojiSet; +export '../icons/emoji_editor_icons.dart'; +export '../styles/emoji_editor_style.dart'; /// Configuration options for an emoji editor. /// @@ -32,6 +35,8 @@ class EmojiEditorConfigs { this.maxScale = double.infinity, this.checkPlatformCompatibility = true, this.emojiSet = defaultEmojiSet, + this.style = const EmojiEditorStyle(), + this.icons = const EmojiEditorIcons(), }) : assert(initScale > 0, 'initScale must be positive'), assert(maxScale >= minScale, 'maxScale must be greater than or equal to minScale'); @@ -54,6 +59,12 @@ class EmojiEditorConfigs { /// The maximum scale factor from the layer. final double maxScale; + /// Style configuration for the emoji editor. + final EmojiEditorStyle style; + + /// Icons used in the emoji editor. + final EmojiEditorIcons icons; + /// Creates a copy of this `EmojiEditorConfigs` object with the given fields /// replaced with new values. /// @@ -67,6 +78,8 @@ class EmojiEditorConfigs { List? emojiSet, double? minScale, double? maxScale, + EmojiEditorStyle? style, + EmojiEditorIcons? icons, }) { return EmojiEditorConfigs( enabled: enabled ?? this.enabled, @@ -76,6 +89,8 @@ class EmojiEditorConfigs { emojiSet: emojiSet ?? this.emojiSet, minScale: minScale ?? this.minScale, maxScale: maxScale ?? this.maxScale, + style: style ?? this.style, + icons: icons ?? this.icons, ); } } diff --git a/lib/models/editor_configs/filter_editor_configs.dart b/lib/models/editor_configs/filter_editor_configs.dart index e0b4690b..dbf045a8 100644 --- a/lib/models/editor_configs/filter_editor_configs.dart +++ b/lib/models/editor_configs/filter_editor_configs.dart @@ -1,8 +1,15 @@ // Project imports: import 'package:pro_image_editor/modules/filter_editor/utils/filter_generator/filter_model.dart'; +import '../custom_widgets/filter_editor_widgets.dart'; +import '../icons/filter_editor_icons.dart'; +import '../styles/filter_editor_style.dart'; import 'utils/editor_safe_area.dart'; +export '../custom_widgets/filter_editor_widgets.dart'; +export '../icons/filter_editor_icons.dart'; +export '../styles/filter_editor_style.dart'; + /// Configuration options for a filter editor. /// /// `FilterEditorConfigs` allows you to define settings for a filter editor, @@ -30,6 +37,9 @@ class FilterEditorConfigs { this.safeArea = const EditorSafeArea(), this.fadeInUpDuration = const Duration(milliseconds: 220), this.fadeInUpStaggerDelayDuration = const Duration(milliseconds: 25), + this.style = const FilterEditorStyle(), + this.icons = const FilterEditorIcons(), + this.widgets = const FilterEditorWidgets(), }); /// Indicates whether the filter editor is enabled. @@ -58,6 +68,15 @@ class FilterEditorConfigs { /// Defines the safe area configuration for the editor. final EditorSafeArea safeArea; + /// Style configuration for the filter editor. + final FilterEditorStyle style; + + /// Icons used in the filter editor. + final FilterEditorIcons icons; + + /// Widgets associated with the filter editor. + final FilterEditorWidgets widgets; + /// Creates a copy of this `FilterEditorConfigs` object with the given fields /// replaced with new values. /// @@ -71,6 +90,9 @@ class FilterEditorConfigs { Duration? fadeInUpDuration, Duration? fadeInUpStaggerDelayDuration, EditorSafeArea? safeArea, + FilterEditorStyle? style, + FilterEditorIcons? icons, + FilterEditorWidgets? widgets, }) { return FilterEditorConfigs( safeArea: safeArea ?? this.safeArea, @@ -78,8 +100,11 @@ class FilterEditorConfigs { showLayers: showLayers ?? this.showLayers, filterList: filterList ?? this.filterList, fadeInUpDuration: fadeInUpDuration ?? this.fadeInUpDuration, + style: style ?? this.style, fadeInUpStaggerDelayDuration: fadeInUpStaggerDelayDuration ?? this.fadeInUpStaggerDelayDuration, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/editor_configs/helper_lines_configs.dart b/lib/models/editor_configs/helper_lines_configs.dart index 1c45237a..e11e2478 100644 --- a/lib/models/editor_configs/helper_lines_configs.dart +++ b/lib/models/editor_configs/helper_lines_configs.dart @@ -1,11 +1,15 @@ -/// The `HelperLines` class defines the settings for displaying helper lines in -/// the image editor. +import '../styles/helper_line_style.dart'; + +export '../styles/helper_line_style.dart'; + +/// The `HelperLineConfigs` class defines the settings for displaying helper +/// lines in the image editor. /// Helper lines are used to guide users in positioning and rotating layers. /// /// Usage: /// /// ```dart -/// HelperLines helperLines = HelperLines( +/// HelperLineConfigs helperLines = HelperLineConfigs( /// showVerticalLine: true, /// showHorizontalLine: true, /// showRotateLine: true, @@ -24,7 +28,7 @@ /// Example Usage: /// /// ```dart -/// HelperLines helperLines = HelperLines( +/// HelperLineConfigs helperLines = HelperLineConfigs( /// showVerticalLine: true, /// showHorizontalLine: true, /// showRotateLine: true, @@ -34,14 +38,15 @@ /// bool showHorizontalLine = helperLines.showHorizontalLine; /// // Access other helper lines settings... /// ``` -class HelperLines { +class HelperLineConfigs { /// Creates an instance of the `HelperLines` class with the specified /// settings. - const HelperLines({ + const HelperLineConfigs({ this.showVerticalLine = true, this.showHorizontalLine = true, this.showRotateLine = true, this.hitVibration = true, + this.style = const HelperLineStyle(), }); /// Specifies whether to show the vertical helper line. @@ -67,23 +72,28 @@ class HelperLines { /// feedback. final bool hitVibration; - /// Creates a copy of this `HelperLines` object with the given fields + /// Style configuration for helper lines. + final HelperLineStyle style; + + /// Creates a copy of this `HelperLineConfigs` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [HelperLines] with some properties updated while keeping the + /// [HelperLineConfigs] with some properties updated while keeping the /// others unchanged. - HelperLines copyWith({ + HelperLineConfigs copyWith({ bool? showVerticalLine, bool? showHorizontalLine, bool? showRotateLine, bool? hitVibration, + HelperLineStyle? style, }) { - return HelperLines( + return HelperLineConfigs( showVerticalLine: showVerticalLine ?? this.showVerticalLine, showHorizontalLine: showHorizontalLine ?? this.showHorizontalLine, showRotateLine: showRotateLine ?? this.showRotateLine, hitVibration: hitVibration ?? this.hitVibration, + style: style ?? this.style, ); } } diff --git a/lib/models/editor_configs/image_generation_configs/image_generation_configs.dart b/lib/models/editor_configs/image_generation_configs/image_generation_configs.dart index 0290afaa..b4bc3db9 100644 --- a/lib/models/editor_configs/image_generation_configs/image_generation_configs.dart +++ b/lib/models/editor_configs/image_generation_configs/image_generation_configs.dart @@ -69,7 +69,7 @@ class ImageGenerationConfigs { final bool captureOnlyBackgroundImageArea; /// Determines whether to capture only the content within the boundaries of - /// the painting when editing is complete. + /// the drawings when editing is complete. /// /// If set to `true`, editing completion will result in cropping all content /// outside the image boundaries. diff --git a/lib/models/editor_configs/layer_interaction_configs.dart b/lib/models/editor_configs/layer_interaction_configs.dart index e52f9454..a2446b05 100644 --- a/lib/models/editor_configs/layer_interaction_configs.dart +++ b/lib/models/editor_configs/layer_interaction_configs.dart @@ -1,24 +1,34 @@ +import '../custom_widgets/layer_interaction_widgets.dart'; +import '../icons/layer_interaction_icons.dart'; +import '../styles/layer_interaction_style.dart'; + +export '../icons/layer_interaction_icons.dart'; +export '../styles/layer_interaction_style.dart'; + /// Represents the interaction behavior for a layer. /// /// This class provides configuration options for layer interactions, such as /// whether the layer is selectable and its initial selection state. -class LayerInteraction { - /// Creates a [LayerInteraction] instance. +class LayerInteractionConfigs { + /// Creates a [LayerInteractionConfigs] instance. /// /// This constructor allows configuration of layer interaction behavior, /// including the selectable state and the initial selection state. /// /// Example: /// ``` - /// LayerInteraction( + /// LayerInteractionConfigs( /// selectable: LayerInteractionSelectable.manual, /// initialSelected: true, /// ) /// ``` - const LayerInteraction({ + const LayerInteractionConfigs({ this.selectable = LayerInteractionSelectable.auto, this.initialSelected = false, this.hideToolbarOnInteraction = false, + this.icons = const LayerInteractionIcons(), + this.widgets = const LayerInteractionWidgets(), + this.style = const LayerInteractionStyle(), }); /// Specifies the selectability behavior for the layer. @@ -35,22 +45,37 @@ class LayerInteraction { /// with the editor. final bool hideToolbarOnInteraction; - /// Creates a copy of this `LayerInteraction` object with the given fields - /// replaced with new values. + /// Defines icons used in layer interactions. + final LayerInteractionIcons icons; + + /// Widgets associated with layer interactions. + final LayerInteractionWidgets widgets; + + /// Style configuration for layer interactions. + final LayerInteractionStyle style; + + /// Creates a copy of this `LayerInteractionConfigs` object with the given + /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [LayerInteraction] with some properties updated while keeping the + /// [LayerInteractionConfigs] with some properties updated while keeping the /// others unchanged. - LayerInteraction copyWith({ + LayerInteractionConfigs copyWith({ LayerInteractionSelectable? selectable, bool? initialSelected, bool? hideToolbarOnInteraction, + LayerInteractionIcons? icons, + LayerInteractionWidgets? widgets, + LayerInteractionStyle? style, }) { - return LayerInteraction( + return LayerInteractionConfigs( + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, selectable: selectable ?? this.selectable, initialSelected: initialSelected ?? this.initialSelected, hideToolbarOnInteraction: hideToolbarOnInteraction ?? this.hideToolbarOnInteraction, + style: style ?? this.style, ); } } diff --git a/lib/models/editor_configs/main_editor_configs.dart b/lib/models/editor_configs/main_editor_configs.dart index 5152c134..545f5001 100644 --- a/lib/models/editor_configs/main_editor_configs.dart +++ b/lib/models/editor_configs/main_editor_configs.dart @@ -1,18 +1,32 @@ import 'package:flutter/widgets.dart'; import 'package:pro_image_editor/models/crop_rotate_editor/transform_factors.dart'; -import 'package:pro_image_editor/utils/decode_image.dart'; +import '../../utils/decode_image.dart'; +import '../custom_widgets/main_editor_widgets.dart'; +import '../icons/main_editor_icons.dart'; +import '../styles/main_editor_style.dart'; + +export '../custom_widgets/main_editor_widgets.dart'; +export '../icons/main_editor_icons.dart'; +export '../styles/main_editor_style.dart'; /// Configuration options for a main editor. class MainEditorConfigs { /// Creates an instance of MainEditorConfigs with optional settings. const MainEditorConfigs({ this.enableZoom = false, + this.enableCloseButton = true, this.editorMinScale = 1.0, this.editorMaxScale = 5.0, this.transformSetup, this.boundaryMargin = EdgeInsets.zero, + this.style = const MainEditorStyle(), + this.icons = const MainEditorIcons(), + this.widgets = const MainEditorWidgets(), }); + /// Determines whether the close button is displayed on the widget. + final bool enableCloseButton; + /// {@template enableZoom} /// Indicates whether the editor supports zoom functionality. /// @@ -67,6 +81,15 @@ class MainEditorConfigs { /// such as cropping, based on the provided setup. final MainEditorTransformSetup? transformSetup; + /// Style configuration for the main editor. + final MainEditorStyle style; + + /// Icons used in the main editor. + final MainEditorIcons icons; + + /// Widgets associated with the main editor. + final MainEditorWidgets widgets; + /// Creates a copy of this `MainEditorConfigs` object with the given fields /// replaced with new values. /// @@ -74,18 +97,26 @@ class MainEditorConfigs { /// [MainEditorConfigs] with some properties updated while keeping the /// others unchanged. MainEditorConfigs copyWith({ + bool? enableCloseButton, bool? enableZoom, double? editorMinScale, double? editorMaxScale, MainEditorTransformSetup? transformSetup, EdgeInsets? boundaryMargin, + MainEditorStyle? style, + MainEditorIcons? icons, + MainEditorWidgets? widgets, }) { return MainEditorConfigs( + enableCloseButton: enableCloseButton ?? this.enableCloseButton, enableZoom: enableZoom ?? this.enableZoom, editorMinScale: editorMinScale ?? this.editorMinScale, editorMaxScale: editorMaxScale ?? this.editorMaxScale, transformSetup: transformSetup ?? this.transformSetup, boundaryMargin: boundaryMargin ?? this.boundaryMargin, + style: style ?? this.style, + widgets: widgets ?? this.widgets, + icons: icons ?? this.icons, ); } } diff --git a/lib/models/editor_configs/paint_editor_configs.dart b/lib/models/editor_configs/paint_editor_configs.dart index 2f5971d9..f116ee7a 100644 --- a/lib/models/editor_configs/paint_editor_configs.dart +++ b/lib/models/editor_configs/paint_editor_configs.dart @@ -2,8 +2,15 @@ import 'package:flutter/widgets.dart'; import '../../modules/paint_editor/utils/paint_editor_enum.dart'; +import '../custom_widgets/paint_editor_widgets.dart'; +import '../icons/paint_editor_icons.dart'; +import '../styles/paint_editor_style.dart'; import 'utils/editor_safe_area.dart'; +export '../custom_widgets/paint_editor_widgets.dart'; +export '../icons/paint_editor_icons.dart'; +export '../styles/paint_editor_style.dart'; + /// Configuration options for a paint editor. /// /// `PaintEditorConfigs` allows you to define settings for a paint editor, @@ -58,6 +65,9 @@ class PaintEditorConfigs { this.freeStyleHighPerformanceHero = false, this.initialPaintMode = PaintModeE.freeStyle, this.safeArea = const EditorSafeArea(), + this.style = const PaintEditorStyle(), + this.icons = const PaintEditorIcons(), + this.widgets = const PaintEditorWidgets(), }) : assert(maxScale >= minScale, 'maxScale must be greater than or equal to minScale'), assert(editorMaxScale > editorMinScale, @@ -185,6 +195,15 @@ class PaintEditorConfigs { /// Defines the safe area configuration for the editor. final EditorSafeArea safeArea; + /// Style configuration for the paint editor. + final PaintEditorStyle style; + + /// Icons used in the paint editor. + final PaintEditorIcons icons; + + /// Widgets associated with the paint editor. + final PaintEditorWidgets widgets; + /// Creates a copy of this `PaintEditorConfigs` object with the given fields /// replaced with new values. /// @@ -215,6 +234,9 @@ class PaintEditorConfigs { double? maxScale, EditorSafeArea? safeArea, EdgeInsets? boundaryMargin, + PaintEditorStyle? style, + PaintEditorIcons? icons, + PaintEditorWidgets? widgets, }) { return PaintEditorConfigs( safeArea: safeArea ?? this.safeArea, @@ -243,6 +265,9 @@ class PaintEditorConfigs { boundaryMargin: boundaryMargin ?? this.boundaryMargin, minScale: minScale ?? this.minScale, maxScale: maxScale ?? this.maxScale, + style: style ?? this.style, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/editor_configs/pro_image_editor_configs.dart b/lib/models/editor_configs/pro_image_editor_configs.dart index ddaa4036..dc72372c 100644 --- a/lib/models/editor_configs/pro_image_editor_configs.dart +++ b/lib/models/editor_configs/pro_image_editor_configs.dart @@ -1,14 +1,13 @@ // Flutter imports: import 'package:flutter/material.dart'; +import 'package:pro_image_editor/common/editor_various_constants.dart'; // Project imports: import '../../utils/design_mode.dart'; -import '../custom_widgets/custom_widgets.dart'; import '../i18n/i18n.dart'; -import '../icons/icons.dart'; -import '../theme/theme.dart'; import 'blur_editor_configs.dart'; import 'crop_rotate_editor_configs.dart'; +import 'dialog_configs.dart'; import 'emoji_editor_configs.dart'; import 'filter_editor_configs.dart'; import 'helper_lines_configs.dart'; @@ -16,6 +15,7 @@ import 'image_generation_configs/image_generation_configs.dart'; import 'layer_interaction_configs.dart'; import 'main_editor_configs.dart'; import 'paint_editor_configs.dart'; +import 'progress_indicator_configs.dart'; import 'state_history_configs.dart'; import 'sticker_editor_configs.dart'; import 'text_editor_configs.dart'; @@ -24,19 +24,19 @@ import 'tune_editor_configs.dart'; export '../../utils/design_mode.dart'; export '../../utils/pro_image_editor_mode.dart'; export '../crop_rotate_editor/aspect_ratio_item.dart'; -export '../custom_widgets/custom_widgets.dart'; export '../i18n/i18n.dart'; -export '../icons/icons.dart'; export '../layer/layer_background_mode.dart'; -export '../theme/theme.dart'; export 'blur_editor_configs.dart'; export 'crop_rotate_editor_configs.dart'; +export 'dialog_configs.dart'; export 'emoji_editor_configs.dart'; export 'filter_editor_configs.dart'; export 'helper_lines_configs.dart'; export 'image_generation_configs/image_generation_configs.dart'; export 'layer_interaction_configs.dart'; +export 'main_editor_configs.dart'; export 'paint_editor_configs.dart'; +export 'progress_indicator_configs.dart'; export 'state_history_configs.dart'; export 'sticker_editor_configs.dart'; export 'text_editor_configs.dart'; @@ -55,12 +55,6 @@ class ProImageEditorConfigs { /// default, it uses an empty `HelperLines` instance. /// - The `layerInteraction` specifies options for the layer interaction /// behavior. - /// - The `customWidgets` specifies custom widgets to be used in the Image - /// Editor. By default, it uses an empty `CustomWidgets` instance. - /// - The `imageEditorTheme` sets the theme for the Image Editor. By - /// default, it uses an empty `ImageEditorTheme` instance. - /// - The `icons` specifies the icons to be used in the Image Editor. By - /// default, it uses an empty `ImageEditorIcons` instance. /// - The `mainEditorConfigs` configures the Main Editor. By default, it /// uses an empty `MainEditorConfigs` instance. /// - The `paintEditorConfigs` configures the Paint Editor. By default, it @@ -89,24 +83,23 @@ class ProImageEditorConfigs { /// to use when opening editors in modal bottom sheets. const ProImageEditorConfigs({ this.theme, - this.heroTag = 'Pro-Image-Editor-Hero', + this.heroTag = kImageEditorHeroTag, this.i18n = const I18n(), - this.helperLines = const HelperLines(), - this.layerInteraction = const LayerInteraction(), - this.customWidgets = const ImageEditorCustomWidgets(), - this.imageEditorTheme = const ImageEditorTheme(), - this.icons = const ImageEditorIcons(), - this.stateHistoryConfigs = const StateHistoryConfigs(), - this.imageGenerationConfigs = const ImageGenerationConfigs(), - this.mainEditorConfigs = const MainEditorConfigs(), - this.paintEditorConfigs = const PaintEditorConfigs(), - this.textEditorConfigs = const TextEditorConfigs(), - this.cropRotateEditorConfigs = const CropRotateEditorConfigs(), - this.filterEditorConfigs = const FilterEditorConfigs(), - this.tuneEditorConfigs = const TuneEditorConfigs(), - this.blurEditorConfigs = const BlurEditorConfigs(), - this.emojiEditorConfigs = const EmojiEditorConfigs(), - this.stickerEditorConfigs, + this.mainEditor = const MainEditorConfigs(), + this.paintEditor = const PaintEditorConfigs(), + this.textEditor = const TextEditorConfigs(), + this.cropRotateEditor = const CropRotateEditorConfigs(), + this.filterEditor = const FilterEditorConfigs(), + this.tuneEditor = const TuneEditorConfigs(), + this.blurEditor = const BlurEditorConfigs(), + this.emojiEditor = const EmojiEditorConfigs(), + this.stickerEditor = const StickerEditorConfigs(), + this.stateHistory = const StateHistoryConfigs(), + this.imageGeneration = const ImageGenerationConfigs(), + this.helperLines = const HelperLineConfigs(), + this.layerInteraction = const LayerInteractionConfigs(), + this.dialogConfigs = const DialogConfigs(), + this.progressIndicatorConfigs = const ProgressIndicatorConfigs(), this.designMode = ImageEditorDesignModeE.material, }); @@ -120,55 +113,52 @@ class ProImageEditorConfigs { final I18n i18n; /// Configuration options for helper lines in the Image Editor. - final HelperLines helperLines; + final HelperLineConfigs helperLines; /// Configuration options for the layer interaction behavior. - final LayerInteraction layerInteraction; - - /// Custom widgets to be used in the Image Editor. - final ImageEditorCustomWidgets customWidgets; - - /// Theme settings for the Image Editor. - final ImageEditorTheme imageEditorTheme; - - /// Icons to be used in the Image Editor. - final ImageEditorIcons icons; + final LayerInteractionConfigs layerInteraction; /// Configuration options for the main Editor. - final MainEditorConfigs mainEditorConfigs; + final MainEditorConfigs mainEditor; /// Configuration options for the Paint Editor. - final PaintEditorConfigs paintEditorConfigs; + final PaintEditorConfigs paintEditor; /// Configuration options for the Text Editor. - final TextEditorConfigs textEditorConfigs; + final TextEditorConfigs textEditor; /// Configuration options for the Crop and Rotate Editor. - final CropRotateEditorConfigs cropRotateEditorConfigs; + final CropRotateEditorConfigs cropRotateEditor; /// Configuration options for the Filter Editor. - final FilterEditorConfigs filterEditorConfigs; + final FilterEditorConfigs filterEditor; /// Configuration options for the tune Editor. - final TuneEditorConfigs tuneEditorConfigs; + final TuneEditorConfigs tuneEditor; /// Configuration options for the Blur Editor. - final BlurEditorConfigs blurEditorConfigs; + final BlurEditorConfigs blurEditor; /// Configuration options for the Emoji Editor. - final EmojiEditorConfigs emojiEditorConfigs; + final EmojiEditorConfigs emojiEditor; /// Configuration options for the Sticker Editor. - final StickerEditorConfigs? stickerEditorConfigs; + final StickerEditorConfigs stickerEditor; /// The design mode for the Image Editor. final ImageEditorDesignModeE designMode; /// Holds the configurations related to state history management. - final StateHistoryConfigs stateHistoryConfigs; + final StateHistoryConfigs stateHistory; /// Holds the configurations related to image generation. - final ImageGenerationConfigs imageGenerationConfigs; + final ImageGenerationConfigs imageGeneration; + + /// Configuration for the loading dialog used in the editor. + final DialogConfigs dialogConfigs; + + /// Configuration for customizing progress indicators. + final ProgressIndicatorConfigs progressIndicatorConfigs; /// Creates a copy of this `ProImageEditorConfigs` object with the given /// fields replaced with new values. @@ -176,23 +166,22 @@ class ProImageEditorConfigs { ThemeData? theme, String? heroTag, I18n? i18n, - HelperLines? helperLines, - LayerInteraction? layerInteraction, - ImageEditorCustomWidgets? customWidgets, - ImageEditorTheme? imageEditorTheme, - ImageEditorIcons? icons, - StateHistoryConfigs? stateHistoryConfigs, - ImageGenerationConfigs? imageGenerationConfigs, - MainEditorConfigs? mainEditorConfigs, - PaintEditorConfigs? paintEditorConfigs, - TextEditorConfigs? textEditorConfigs, - CropRotateEditorConfigs? cropRotateEditorConfigs, - FilterEditorConfigs? filterEditorConfigs, - TuneEditorConfigs? tuneEditorConfigs, - BlurEditorConfigs? blurEditorConfigs, - EmojiEditorConfigs? emojiEditorConfigs, - StickerEditorConfigs? stickerEditorConfigs, + HelperLineConfigs? helperLines, + LayerInteractionConfigs? layerInteraction, + StateHistoryConfigs? stateHistory, + ImageGenerationConfigs? imageGeneration, + MainEditorConfigs? mainEditor, + PaintEditorConfigs? paintEditor, + TextEditorConfigs? textEditor, + CropRotateEditorConfigs? cropRotateEditor, + FilterEditorConfigs? filterEditor, + TuneEditorConfigs? tuneEditor, + BlurEditorConfigs? blurEditor, + EmojiEditorConfigs? emojiEditor, + StickerEditorConfigs? stickerEditor, ImageEditorDesignModeE? designMode, + DialogConfigs? dialogConfigs, + ProgressIndicatorConfigs? progressIndicatorConfigs, }) { return ProImageEditorConfigs( theme: theme ?? this.theme, @@ -200,23 +189,21 @@ class ProImageEditorConfigs { i18n: i18n ?? this.i18n, helperLines: helperLines ?? this.helperLines, layerInteraction: layerInteraction ?? this.layerInteraction, - customWidgets: customWidgets ?? this.customWidgets, - imageEditorTheme: imageEditorTheme ?? this.imageEditorTheme, - icons: icons ?? this.icons, - stateHistoryConfigs: stateHistoryConfigs ?? this.stateHistoryConfigs, - imageGenerationConfigs: - imageGenerationConfigs ?? this.imageGenerationConfigs, - mainEditorConfigs: mainEditorConfigs ?? this.mainEditorConfigs, - paintEditorConfigs: paintEditorConfigs ?? this.paintEditorConfigs, - textEditorConfigs: textEditorConfigs ?? this.textEditorConfigs, - cropRotateEditorConfigs: - cropRotateEditorConfigs ?? this.cropRotateEditorConfigs, - filterEditorConfigs: filterEditorConfigs ?? this.filterEditorConfigs, - tuneEditorConfigs: tuneEditorConfigs ?? this.tuneEditorConfigs, - blurEditorConfigs: blurEditorConfigs ?? this.blurEditorConfigs, - emojiEditorConfigs: emojiEditorConfigs ?? this.emojiEditorConfigs, - stickerEditorConfigs: stickerEditorConfigs ?? this.stickerEditorConfigs, + stateHistory: stateHistory ?? this.stateHistory, + imageGeneration: imageGeneration ?? this.imageGeneration, + mainEditor: mainEditor ?? this.mainEditor, + paintEditor: paintEditor ?? this.paintEditor, + textEditor: textEditor ?? this.textEditor, + cropRotateEditor: cropRotateEditor ?? this.cropRotateEditor, + filterEditor: filterEditor ?? this.filterEditor, + tuneEditor: tuneEditor ?? this.tuneEditor, + blurEditor: blurEditor ?? this.blurEditor, + emojiEditor: emojiEditor ?? this.emojiEditor, + stickerEditor: stickerEditor ?? this.stickerEditor, designMode: designMode ?? this.designMode, + dialogConfigs: dialogConfigs ?? this.dialogConfigs, + progressIndicatorConfigs: + progressIndicatorConfigs ?? this.progressIndicatorConfigs, ); } } diff --git a/lib/models/editor_configs/progress_indicator_configs.dart b/lib/models/editor_configs/progress_indicator_configs.dart new file mode 100644 index 00000000..180e9d3c --- /dev/null +++ b/lib/models/editor_configs/progress_indicator_configs.dart @@ -0,0 +1,23 @@ +import '../custom_widgets/progress_indicator_widgets.dart'; + +export '../custom_widgets/progress_indicator_widgets.dart'; + +/// Configuration class for customizing progress indicators. +class ProgressIndicatorConfigs { + /// Creates a new instance of [ProgressIndicatorConfigs]. + const ProgressIndicatorConfigs({ + this.widgets = const ProgressIndicatorWidgets(), + }); + + /// Widgets used for customizing progress indicators. + final ProgressIndicatorWidgets widgets; + + /// Creates a copy of this configuration with the specified overrides. + ProgressIndicatorConfigs copyWith({ + ProgressIndicatorWidgets? widgets, + }) { + return ProgressIndicatorConfigs( + widgets: widgets ?? this.widgets, + ); + } +} diff --git a/lib/models/editor_configs/sticker_editor_configs.dart b/lib/models/editor_configs/sticker_editor_configs.dart index 1c7e4d0c..f091663b 100644 --- a/lib/models/editor_configs/sticker_editor_configs.dart +++ b/lib/models/editor_configs/sticker_editor_configs.dart @@ -1,6 +1,12 @@ // Flutter imports: import 'package:flutter/widgets.dart'; +import '../icons/sticker_editor_icons.dart'; +import '../styles/sticker_editor_style.dart'; + +export '../icons/sticker_editor_icons.dart'; +export '../styles/sticker_editor_style.dart'; + /// Configuration options for a sticker editor. /// /// `StickerEditorConfigs` allows you to define various settings for a sticker @@ -23,11 +29,13 @@ class StickerEditorConfigs { /// By default, the editor is disabled (if not specified), and other /// properties are set to reasonable defaults. const StickerEditorConfigs({ - required this.buildStickers, + this.buildStickers, this.initWidth = 100, this.minScale = double.negativeInfinity, this.maxScale = double.infinity, this.enabled = false, + this.style = const StickerEditorStyle(), + this.icons = const StickerEditorIcons(), }) : assert(initWidth > 0, 'initWidth must be positive'), assert(maxScale >= minScale, 'maxScale must be greater than or equal to minScale'); @@ -51,7 +59,7 @@ class StickerEditorConfigs { /// returns a Widget. The function parameter `setLayer` is used to set a /// layer in the editor. This callback allows for customizing the appearance /// and behavior of stickers in the editor. - final BuildStickers buildStickers; + final BuildStickers? buildStickers; /// The minimum scale factor from the layer. final double minScale; @@ -59,6 +67,12 @@ class StickerEditorConfigs { /// The maximum scale factor from the layer. final double maxScale; + /// Style configuration for the sticker editor. + final StickerEditorStyle style; + + /// Icons used in the sticker editor. + final StickerEditorIcons icons; + /// Creates a copy of this `StickerEditorConfigs` object with the given fields /// replaced with new values. /// @@ -71,6 +85,8 @@ class StickerEditorConfigs { BuildStickers? buildStickers, double? minScale, double? maxScale, + StickerEditorStyle? style, + StickerEditorIcons? icons, }) { return StickerEditorConfigs( enabled: enabled ?? this.enabled, @@ -78,6 +94,8 @@ class StickerEditorConfigs { buildStickers: buildStickers ?? this.buildStickers, minScale: minScale ?? this.minScale, maxScale: maxScale ?? this.maxScale, + style: style ?? this.style, + icons: icons ?? this.icons, ); } } diff --git a/lib/models/editor_configs/text_editor_configs.dart b/lib/models/editor_configs/text_editor_configs.dart index 116b5190..e1b67667 100644 --- a/lib/models/editor_configs/text_editor_configs.dart +++ b/lib/models/editor_configs/text_editor_configs.dart @@ -2,9 +2,16 @@ import 'package:flutter/widgets.dart'; // Project imports: +import '../custom_widgets/text_editor_widgets.dart'; +import '../icons/text_editor_icons.dart'; import '../layer/layer_background_mode.dart'; +import '../styles/text_editor_style.dart'; import 'utils/editor_safe_area.dart'; +export '../custom_widgets/text_editor_widgets.dart'; +export '../icons/text_editor_icons.dart'; +export '../styles/text_editor_style.dart'; + /// Configuration options for a text editor. /// /// `TextEditorConfigs` allows you to define settings for a text editor, @@ -43,6 +50,9 @@ class TextEditorConfigs { this.customTextStyles, this.initialBackgroundColorMode = LayerBackgroundMode.backgroundAndColor, this.safeArea = const EditorSafeArea(), + this.style = const TextEditorStyle(), + this.icons = const TextEditorIcons(), + this.widgets = const TextEditorWidgets(), }) : assert(initFontSize > 0, 'initFontSize must be positive'), assert(maxScale >= minScale, 'maxScale must be greater than or equal to minScale'); @@ -107,6 +117,15 @@ class TextEditorConfigs { /// Defines the safe area configuration for the editor. final EditorSafeArea safeArea; + /// Style configuration for the text editor. + final TextEditorStyle style; + + /// Icons used in the text editor. + final TextEditorIcons icons; + + /// Widgets associated with the text editor. + final TextEditorWidgets widgets; + /// Creates a copy of this `TextEditorConfigs` object with the given fields /// replaced with new values. /// @@ -131,6 +150,9 @@ class TextEditorConfigs { bool? enableSuggestions, bool? autocorrect, EditorSafeArea? safeArea, + TextEditorStyle? style, + TextEditorIcons? icons, + TextEditorWidgets? widgets, }) { return TextEditorConfigs( safeArea: safeArea ?? this.safeArea, @@ -153,6 +175,9 @@ class TextEditorConfigs { maxScale: maxScale ?? this.maxScale, enableSuggestions: enableSuggestions ?? this.enableSuggestions, autocorrect: autocorrect ?? this.autocorrect, + style: style ?? this.style, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/editor_configs/tune_editor_configs.dart b/lib/models/editor_configs/tune_editor_configs.dart index 136bda75..829cc1e7 100644 --- a/lib/models/editor_configs/tune_editor_configs.dart +++ b/lib/models/editor_configs/tune_editor_configs.dart @@ -1,6 +1,13 @@ +import '../custom_widgets/tune_editor_widgets.dart'; +import '../icons/tune_editor_icons.dart'; +import '../styles/tune_editor_style.dart'; import '../tune_editor/tune_adjustment_item.dart'; import 'utils/editor_safe_area.dart'; +export '../custom_widgets/tune_editor_widgets.dart'; +export '../icons/tune_editor_icons.dart'; +export '../styles/tune_editor_style.dart'; + /// A configuration class for the Tune Editor. /// /// This class defines various configurations such as enabling the editor, @@ -19,6 +26,9 @@ class TuneEditorConfigs { this.showLayers = true, this.tuneAdjustmentOptions, this.safeArea = const EditorSafeArea(), + this.style = const TuneEditorStyle(), + this.icons = const TuneEditorIcons(), + this.widgets = const TuneEditorWidgets(), }); /// Indicates whether the tune editor is enabled. @@ -42,6 +52,15 @@ class TuneEditorConfigs { /// or other tune adjustments. final List? tuneAdjustmentOptions; + /// Style configuration for the tune editor. + final TuneEditorStyle style; + + /// Icons used in the tune editor. + final TuneEditorIcons icons; + + /// Widgets associated with the tune editor. + final TuneEditorWidgets widgets; + /// Creates a copy of this [TuneEditorConfigs] object with the given fields /// replaced with new values. /// @@ -58,6 +77,9 @@ class TuneEditorConfigs { bool? showLayers, EditorSafeArea? safeArea, List? tuneAdjustmentOptions, + TuneEditorStyle? style, + TuneEditorIcons? icons, + TuneEditorWidgets? widgets, }) { return TuneEditorConfigs( enabled: enabled ?? this.enabled, @@ -65,6 +87,9 @@ class TuneEditorConfigs { showLayers: showLayers ?? this.showLayers, tuneAdjustmentOptions: tuneAdjustmentOptions ?? this.tuneAdjustmentOptions, + style: style ?? this.style, + icons: icons ?? this.icons, + widgets: widgets ?? this.widgets, ); } } diff --git a/lib/models/i18n/i18n.dart b/lib/models/i18n/i18n.dart index 5d2488a4..16876870 100644 --- a/lib/models/i18n/i18n.dart +++ b/lib/models/i18n/i18n.dart @@ -4,7 +4,7 @@ import 'i18n_crop_rotate_editor.dart'; import 'i18n_emoji_editor.dart'; import 'i18n_filter_editor.dart'; import 'i18n_layer_interaction.dart'; -import 'i18n_painting_editor.dart'; +import 'i18n_paint_editor.dart'; import 'i18n_sticker_editor.dart'; import 'i18n_text_editor.dart'; import 'i18n_tune_editor.dart'; @@ -15,7 +15,7 @@ export 'i18n_crop_rotate_editor.dart'; export 'i18n_emoji_editor.dart'; export 'i18n_filter_editor.dart'; export 'i18n_layer_interaction.dart'; -export 'i18n_painting_editor.dart'; +export 'i18n_paint_editor.dart'; export 'i18n_sticker_editor.dart'; export 'i18n_text_editor.dart'; export 'i18n_tune_editor.dart'; @@ -32,8 +32,8 @@ export 'i18n_various.dart'; /// various: I18nVarious( /// // Define various translations... /// ), -/// paintEditor: I18nPaintingEditor( -/// // Define painting editor translations... +/// paintEditor: I18nPaintEditor( +/// // Define paint editor translations... /// ), /// textEditor: I18nTextEditor( /// // Define text editor translations... @@ -62,7 +62,7 @@ export 'i18n_various.dart'; /// /// - `various`: Translations and messages for various parts of the editor. /// -/// - `paintEditor`: Translations and messages specific to the painting editor. +/// - `paintEditor`: Translations and messages specific to the paint editor. /// /// - `textEditor`: Translations and messages specific to the text editor. /// @@ -94,8 +94,8 @@ export 'i18n_various.dart'; /// various: I18nVarious( /// // Define various translations... /// ), -/// paintEditor: I18nPaintingEditor( -/// // Define painting editor translations... +/// paintEditor: I18nPaintEditor( +/// // Define paint editor translations... /// ), /// // Access other translations and messages... /// ); @@ -125,8 +125,8 @@ class I18n { /// various: I18nVarious( /// // Custom translations and settings for various components /// ), - /// paintEditor: I18nPaintingEditor( - /// // Custom translations and settings for the Painting Editor + /// paintEditor: I18nPaintEditor( + /// // Custom translations and settings for the Paint Editor /// ), /// textEditor: I18nTextEditor( /// // Custom translations and settings for the Text Editor @@ -142,7 +142,7 @@ class I18n { /// ``` const I18n({ this.layerInteraction = const I18nLayerInteraction(), - this.paintEditor = const I18nPaintingEditor(), + this.paintEditor = const I18nPaintEditor(), this.textEditor = const I18nTextEditor(), this.cropRotateEditor = const I18nCropRotateEditor(), this.tuneEditor = const I18nTuneEditor(), @@ -160,8 +160,8 @@ class I18n { this.doneLoadingMsg = 'Changes are being applied', }); - /// Translations and messages specific to the painting editor. - final I18nPaintingEditor paintEditor; + /// Translations and messages specific to the paint editor. + final I18nPaintEditor paintEditor; /// Translations and messages for various parts of the editor. final I18nVarious various; @@ -219,7 +219,7 @@ class I18n { /// [I18n] with some properties updated while keeping the /// others unchanged. I18n copyWith({ - I18nPaintingEditor? paintEditor, + I18nPaintEditor? paintEditor, I18nVarious? various, I18nLayerInteraction? layerInteraction, I18nTextEditor? textEditor, diff --git a/lib/models/i18n/i18n_painting_editor.dart b/lib/models/i18n/i18n_paint_editor.dart similarity index 81% rename from lib/models/i18n/i18n_painting_editor.dart rename to lib/models/i18n/i18n_paint_editor.dart index 442b339c..ddfe05af 100644 --- a/lib/models/i18n/i18n_painting_editor.dart +++ b/lib/models/i18n/i18n_paint_editor.dart @@ -1,17 +1,17 @@ -/// Internationalization (i18n) settings for the Painting Editor component. -class I18nPaintingEditor { - /// Creates an instance of [I18nPaintingEditor] with customizable +/// Internationalization (i18n) settings for the Paint Editor component. +class I18nPaintEditor { + /// Creates an instance of [I18nPaintEditor] with customizable /// internationalization settings. /// /// You can provide translations and messages for various components of the - /// Painting Editor in the Image Editor. Customize the text for painting + /// Paint Editor in the Image Editor. Customize the text for paint /// modes, buttons, and messages to suit your application's language and /// style. /// /// Example: /// /// ```dart - /// I18nPaintingEditor( + /// I18nPaintEditor( /// bottomNavigationBarText: 'Paint', /// freestyle: 'Freestyle', /// arrow: 'Arrow', @@ -29,7 +29,7 @@ class I18nPaintingEditor { /// back: 'Back', /// ) /// ``` - const I18nPaintingEditor({ + const I18nPaintEditor({ this.moveAndZoom = 'Zoom', this.bottomNavigationBarText = 'Paint', this.freestyle = 'Freestyle', @@ -49,7 +49,7 @@ class I18nPaintingEditor { this.smallScreenMoreTooltip = 'More', }); - /// Text for the bottom navigation bar item that opens the Painting Editor. + /// Text for the bottom navigation bar item that opens the Paint Editor. final String bottomNavigationBarText; /// The text used for moving and zooming within the editor. @@ -62,25 +62,25 @@ class I18nPaintingEditor { /// the text will be hidden. final String moveAndZoom; - /// Text for the "Freestyle" painting mode. + /// Text for the "Freestyle" paint mode. final String freestyle; - /// Text for the "Arrow" painting mode. + /// Text for the "Arrow" paint mode. final String arrow; - /// Text for the "Line" painting mode. + /// Text for the "Line" paint mode. final String line; - /// Text for the "Rectangle" painting mode. + /// Text for the "Rectangle" paint mode. final String rectangle; - /// Text for the "Circle" painting mode. + /// Text for the "Circle" paint mode. final String circle; - /// Text for the "Dash line" painting mode. + /// Text for the "Dash line" paint mode. final String dashLine; - /// Text for the "Eraser" painting mode. + /// Text for the "Eraser" paint mode. final String eraser; /// Text for the "Line width" tooltip. @@ -107,13 +107,13 @@ class I18nPaintingEditor { /// The tooltip text displayed for the "More" option on small screens. final String smallScreenMoreTooltip; - /// Creates a copy of this `I18nPaintingEditor` object with the given fields + /// Creates a copy of this `I18nPaintEditor` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [I18nPaintingEditor] with some properties updated while keeping the + /// [I18nPaintEditor] with some properties updated while keeping the /// others unchanged. - I18nPaintingEditor copyWith({ + I18nPaintEditor copyWith({ String? moveAndZoom, String? bottomNavigationBarText, String? freestyle, @@ -132,7 +132,7 @@ class I18nPaintingEditor { String? back, String? smallScreenMoreTooltip, }) { - return I18nPaintingEditor( + return I18nPaintEditor( moveAndZoom: moveAndZoom ?? this.moveAndZoom, bottomNavigationBarText: bottomNavigationBarText ?? this.bottomNavigationBarText, diff --git a/lib/models/icons/icons_blur_editor.dart b/lib/models/icons/blur_editor_icons.dart similarity index 53% rename from lib/models/icons/icons_blur_editor.dart rename to lib/models/icons/blur_editor_icons.dart index 03dfdaf9..0d9117cc 100644 --- a/lib/models/icons/icons_blur_editor.dart +++ b/lib/models/icons/blur_editor_icons.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; /// Customizable icons for the Blur Editor component. -class IconsBlurEditor { - /// Creates an instance of [IconsBlurEditor] with customizable icon settings. +class BlurEditorIcons { + /// Creates an instance of [BlurEditorIcons] with customizable icon settings. /// /// You can provide a custom icon for the bottom navigation bar in the Blur /// Editor component. @@ -13,28 +13,40 @@ class IconsBlurEditor { /// Example: /// /// ```dart - /// IconsBlurEditor( + /// BlurEditorIcons( /// bottomNavBar: Icons.blur_on, /// ) /// ``` - const IconsBlurEditor({ + const BlurEditorIcons({ this.bottomNavBar = Icons.blur_on, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, }); /// The icon to be displayed in the bottom navigation bar. final IconData bottomNavBar; - /// Creates a copy of this `IconsBlurEditor` object with the given fields + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// Creates a copy of this `BlurEditorIcons` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsBlurEditor] with some properties updated while keeping the + /// [BlurEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsBlurEditor copyWith({ + BlurEditorIcons copyWith({ IconData? bottomNavBar, + IconData? backButton, + IconData? applyChanges, }) { - return IconsBlurEditor( + return BlurEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, ); } } diff --git a/lib/models/icons/icons_crop_rotate_editor.dart b/lib/models/icons/crop_rotate_editor_icons.dart similarity index 61% rename from lib/models/icons/icons_crop_rotate_editor.dart rename to lib/models/icons/crop_rotate_editor_icons.dart index d54e7c8e..6f1b3687 100644 --- a/lib/models/icons/icons_crop_rotate_editor.dart +++ b/lib/models/icons/crop_rotate_editor_icons.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; /// Customizable icons for the Crop/Rotate Editor component. -class IconsCropRotateEditor { - /// Creates an instance of [IconsCropRotateEditor] with customizable icon +class CropRotateEditorIcons { + /// Creates an instance of [CropRotateEditorIcons] with customizable icon /// settings. /// /// You can provide custom icons for various actions in the Crop/Rotate Editor component. @@ -16,18 +16,22 @@ class IconsCropRotateEditor { /// Example: /// /// ```dart - /// IconsCropRotateEditor( + /// CropRotateEditorIcons( /// bottomNavBar: Icons.crop_rotate_rounded, /// rotate: Icons.rotate_90_degrees_ccw_outlined, /// aspectRatio: Icons.crop, /// ) /// ``` - const IconsCropRotateEditor({ + const CropRotateEditorIcons({ this.bottomNavBar = Icons.crop_rotate_rounded, this.rotate = Icons.rotate_90_degrees_ccw_outlined, this.aspectRatio = Icons.crop, this.flip = Icons.flip, this.reset = Icons.restore, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, + this.undoAction = Icons.undo, + this.redoAction = Icons.redo, }); /// The icon to be displayed in the bottom navigation bar. @@ -45,25 +49,45 @@ class IconsCropRotateEditor { /// The icon for the reset action. final IconData reset; - /// Creates a copy of this `IconsCropRotateEditor` object with the given + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// The icon for undoing the last action. + final IconData undoAction; + + /// The icon for redoing the last undone action. + final IconData redoAction; + + /// Creates a copy of this `CropRotateEditorIcons` object with the given /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsCropRotateEditor] with some properties updated while keeping the + /// [CropRotateEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsCropRotateEditor copyWith({ + CropRotateEditorIcons copyWith({ IconData? bottomNavBar, IconData? rotate, IconData? aspectRatio, IconData? flip, IconData? reset, + IconData? backButton, + IconData? applyChanges, + IconData? undoAction, + IconData? redoAction, }) { - return IconsCropRotateEditor( + return CropRotateEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, rotate: rotate ?? this.rotate, aspectRatio: aspectRatio ?? this.aspectRatio, flip: flip ?? this.flip, reset: reset ?? this.reset, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, + undoAction: undoAction ?? this.undoAction, + redoAction: redoAction ?? this.redoAction, ); } } diff --git a/lib/models/icons/icons_emoji_editor.dart b/lib/models/icons/emoji_editor_icons.dart similarity index 78% rename from lib/models/icons/icons_emoji_editor.dart rename to lib/models/icons/emoji_editor_icons.dart index 3b1a9905..117a850b 100644 --- a/lib/models/icons/icons_emoji_editor.dart +++ b/lib/models/icons/emoji_editor_icons.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; /// Customizable icons for the Emoji Editor component. -class IconsEmojiEditor { - /// Creates an instance of [IconsEmojiEditor] with customizable icon settings. +class EmojiEditorIcons { + /// Creates an instance of [EmojiEditorIcons] with customizable icon settings. /// /// You can provide a custom [bottomNavBar] icon to be displayed in the /// bottom navigation bar of the Emoji Editor component. If no custom icon @@ -12,11 +12,11 @@ class IconsEmojiEditor { /// Example: /// /// ```dart - /// IconsEmojiEditor( + /// EmojiEditorIcons( /// bottomNavBar: Icons.sentiment_satisfied_alt_rounded, /// ) /// ``` - const IconsEmojiEditor({ + const EmojiEditorIcons({ this.bottomNavBar = Icons.sentiment_satisfied_alt_rounded, }); @@ -27,12 +27,12 @@ class IconsEmojiEditor { /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsEmojiEditor] with some properties updated while keeping the + /// [EmojiEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsEmojiEditor copyWith({ + EmojiEditorIcons copyWith({ IconData? bottomNavBar, }) { - return IconsEmojiEditor( + return EmojiEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, ); } diff --git a/lib/models/icons/icons_filter_editor.dart b/lib/models/icons/filter_editor_icons.dart similarity index 53% rename from lib/models/icons/icons_filter_editor.dart rename to lib/models/icons/filter_editor_icons.dart index 549fddd6..088c7920 100644 --- a/lib/models/icons/icons_filter_editor.dart +++ b/lib/models/icons/filter_editor_icons.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; /// Customizable icons for the Filter Editor component. -class IconsFilterEditor { - /// Creates an instance of [IconsFilterEditor] with customizable icon +class FilterEditorIcons { + /// Creates an instance of [FilterEditorIcons] with customizable icon /// settings. /// /// You can provide a custom icon for the bottom navigation bar in the Filter @@ -14,28 +14,40 @@ class IconsFilterEditor { /// Example: /// /// ```dart - /// IconsFilterEditor( + /// FilterEditorIcons( /// bottomNavBar: Icons.filter, /// ) /// ``` - const IconsFilterEditor({ + const FilterEditorIcons({ this.bottomNavBar = Icons.filter, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, }); /// The icon to be displayed in the bottom navigation bar. final IconData bottomNavBar; - /// Creates a copy of this `IconsFilterEditor` object with the given fields + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// Creates a copy of this `FilterEditorIcons` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsFilterEditor] with some properties updated while keeping the + /// [FilterEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsFilterEditor copyWith({ + FilterEditorIcons copyWith({ IconData? bottomNavBar, + IconData? backButton, + IconData? applyChanges, }) { - return IconsFilterEditor( + return FilterEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, ); } } diff --git a/lib/models/icons/icons.dart b/lib/models/icons/icons.dart deleted file mode 100644 index 78561103..00000000 --- a/lib/models/icons/icons.dart +++ /dev/null @@ -1,204 +0,0 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - -// Project imports: -import 'icons_blur_editor.dart'; -import 'icons_crop_rotate_editor.dart'; -import 'icons_emoji_editor.dart'; -import 'icons_filter_editor.dart'; -import 'icons_layer_interaction.dart'; -import 'icons_painting_editor.dart'; -import 'icons_sticker_editor.dart'; -import 'icons_text_editor.dart'; -import 'icons_tune_editor.dart'; - -export 'icons_blur_editor.dart'; -export 'icons_crop_rotate_editor.dart'; -export 'icons_emoji_editor.dart'; -export 'icons_filter_editor.dart'; -export 'icons_layer_interaction.dart'; -export 'icons_painting_editor.dart'; -export 'icons_sticker_editor.dart'; -export 'icons_text_editor.dart'; -export 'icons_tune_editor.dart'; - -/// Customizable icons for the Image Editor component. -class ImageEditorIcons { - /// Creates an instance of [ImageEditorIcons] with customizable icon settings. - /// - /// You can provide custom icons for various actions in the Image Editor - /// component. - /// - /// - [closeEditor]: The icon for closing the editor. - /// - [doneIcon]: The icon for applying changes. - /// - [backButton]: The icon for the back button. - /// - [applyChanges]: The icon for applying changes in the editor. - /// - [undoAction]: The icon for undoing the last action. - /// - [redoAction]: The icon for redoing the last undone action. - /// - [removeElementZone]: The icon for removing an element or zone. - /// - [paintingEditor]: Customizable icons for the Painting Editor component. - /// - [textEditor]: Customizable icons for the Text Editor component. - /// - [cropRotateEditor]: Customizable icons for the Crop and Rotate Editor - /// component. - /// - [filterEditor]: Customizable icons for the Filter Editor component. - /// - [blurEditor]: Customizable icons for the Blur Editor component. - /// - [emojiEditor]: Customizable icons for the Emoji Editor component. - /// - [stickerEditor]: Customizable icons for the Sticker Editor component. - /// - [layerInteraction]: Icons for the layer interaction settings. - /// - /// If no custom icons are provided, default icons are used for each action. - /// - /// Example: - /// - /// ```dart - /// ImageEditorIcons( - /// paintingEditor: IconsPaintingEditor( - /// bottomNavBar: Icons.edit_rounded, - /// lineWeight: Icons.line_weight_rounded, - /// freeStyle: Icons.edit, - /// // ... (customize other painting editor icons) - /// ), - /// textEditor: IconsTextEditor( - /// bottomNavBar: Icons.text_fields, - /// alignLeft: Icons.align_horizontal_left_rounded, - /// alignCenter: Icons.align_horizontal_center_rounded, - /// // ... (customize other text editor icons) - /// ), - /// cropRotateEditor: IconsCropRotateEditor( - /// bottomNavBar: Icons.crop_rotate_rounded, - /// rotate: Icons.rotate_90_degrees_ccw_outlined, - /// aspectRatio: Icons.crop, - /// // ... (customize other crop and rotate editor icons) - /// ), - /// filterEditor: IconsFilterEditor( - /// bottomNavBar: Icons.filter, - /// // ... (customize other filter editor icons) - /// ), - /// blurEditor: IconsBlurEditor( - /// bottomNavBar: Icons.blur_on, - /// // ... (customize other blur editor icons) - /// ), - /// emojiEditor: IconsEmojiEditor( - /// bottomNavBar: Icons.sentiment_satisfied_alt_rounded, - /// // ... (customize other emoji editor icons) - /// ), - /// closeEditor: Icons.clear, - /// doneIcon: Icons.done, - /// backButton: Icons.arrow_back, - /// applyChanges: Icons.done, - /// undoAction: Icons.undo, - /// redoAction: Icons.redo, - /// removeElementZone: Icons.delete_outline_rounded, - /// ) - /// ``` - const ImageEditorIcons({ - this.paintingEditor = const IconsPaintingEditor(), - this.textEditor = const IconsTextEditor(), - this.cropRotateEditor = const IconsCropRotateEditor(), - this.filterEditor = const IconsFilterEditor(), - this.tuneEditor = const IconsTuneEditor(), - this.blurEditor = const IconsBlurEditor(), - this.emojiEditor = const IconsEmojiEditor(), - this.stickerEditor = const IconsStickerEditor(), - this.layerInteraction = const IconsLayerInteraction(), - this.closeEditor = Icons.clear, - this.doneIcon = Icons.done, - this.applyChanges = Icons.done, - this.backButton = Icons.arrow_back, - this.undoAction = Icons.undo, - this.redoAction = Icons.redo, - this.removeElementZone = Icons.delete_outline_rounded, - }); - - /// The icon for closing the editor without saving. - final IconData closeEditor; - - /// The icon for applying changes and closing the editor. - final IconData doneIcon; - - /// The icon for the back button. - final IconData backButton; - - /// The icon for applying changes in the editor. - final IconData applyChanges; - - /// The icon for undoing the last action. - final IconData undoAction; - - /// The icon for redoing the last undone action. - final IconData redoAction; - - /// The icon for removing an element/ layer like an emoji. - final IconData removeElementZone; - - /// Icons for the Painting Editor component. - final IconsPaintingEditor paintingEditor; - - /// Icons for the Text Editor component. - final IconsTextEditor textEditor; - - /// Icons for the Crop and Rotate Editor component. - final IconsCropRotateEditor cropRotateEditor; - - /// Icons for the Filter Editor component. - final IconsFilterEditor filterEditor; - - /// Icons for the tune Editor component. - final IconsTuneEditor tuneEditor; - - /// Icons for the Blur Editor component. - final IconsBlurEditor blurEditor; - - /// Icons for the Emoji Editor component. - final IconsEmojiEditor emojiEditor; - - /// Icons for the Sticker Editor component. - final IconsStickerEditor stickerEditor; - - /// Icons for the layer interaction settings. - final IconsLayerInteraction layerInteraction; - - /// Creates a copy of this `ImageEditorIcons` object with the given fields - /// replaced with new values. - /// - /// The [copyWith] method allows you to create a new instance of - /// [ImageEditorIcons] with some properties updated while keeping the - /// others unchanged. - ImageEditorIcons copyWith({ - IconData? closeEditor, - IconData? doneIcon, - IconData? backButton, - IconData? applyChanges, - IconData? undoAction, - IconData? redoAction, - IconData? removeElementZone, - IconsPaintingEditor? paintingEditor, - IconsTextEditor? textEditor, - IconsCropRotateEditor? cropRotateEditor, - IconsFilterEditor? filterEditor, - IconsTuneEditor? tuneEditor, - IconsBlurEditor? blurEditor, - IconsEmojiEditor? emojiEditor, - IconsStickerEditor? stickerEditor, - IconsLayerInteraction? layerInteraction, - }) { - return ImageEditorIcons( - closeEditor: closeEditor ?? this.closeEditor, - doneIcon: doneIcon ?? this.doneIcon, - backButton: backButton ?? this.backButton, - applyChanges: applyChanges ?? this.applyChanges, - undoAction: undoAction ?? this.undoAction, - redoAction: redoAction ?? this.redoAction, - removeElementZone: removeElementZone ?? this.removeElementZone, - paintingEditor: paintingEditor ?? this.paintingEditor, - textEditor: textEditor ?? this.textEditor, - cropRotateEditor: cropRotateEditor ?? this.cropRotateEditor, - filterEditor: filterEditor ?? this.filterEditor, - tuneEditor: tuneEditor ?? this.tuneEditor, - blurEditor: blurEditor ?? this.blurEditor, - emojiEditor: emojiEditor ?? this.emojiEditor, - stickerEditor: stickerEditor ?? this.stickerEditor, - layerInteraction: layerInteraction ?? this.layerInteraction, - ); - } -} diff --git a/lib/models/icons/icons_layer_interaction.dart b/lib/models/icons/layer_interaction_icons.dart similarity index 77% rename from lib/models/icons/icons_layer_interaction.dart rename to lib/models/icons/layer_interaction_icons.dart index 5a26c79e..53dbfde5 100644 --- a/lib/models/icons/icons_layer_interaction.dart +++ b/lib/models/icons/layer_interaction_icons.dart @@ -5,13 +5,13 @@ import 'package:flutter/material.dart'; /// /// This class defines the icons used for various layer interactions such as /// removing a layer and rotating/scaling a layer. -class IconsLayerInteraction { - /// Creates a new instance of [IconsLayerInteraction]. +class LayerInteractionIcons { + /// Creates a new instance of [LayerInteractionIcons]. /// /// The [edit] icon defaults to [Icons.edit]. /// The [remove] icon defaults to [Icons.clear]. /// The [rotateScale] icon defaults to [Icons.sync]. - const IconsLayerInteraction({ + const LayerInteractionIcons({ this.remove = Icons.clear, this.edit = Icons.edit_outlined, this.rotateScale = Icons.sync, @@ -26,18 +26,18 @@ class IconsLayerInteraction { /// The icon data for rotating or scaling a layer. final IconData rotateScale; - /// Creates a copy of this `IconsLayerInteraction` object with the given + /// Creates a copy of this `LayerInteractionIcons` object with the given /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsLayerInteraction] with some properties updated while keeping the + /// [LayerInteractionIcons] with some properties updated while keeping the /// others unchanged. - IconsLayerInteraction copyWith({ + LayerInteractionIcons copyWith({ IconData? remove, IconData? edit, IconData? rotateScale, }) { - return IconsLayerInteraction( + return LayerInteractionIcons( remove: remove ?? this.remove, edit: edit ?? this.edit, rotateScale: rotateScale ?? this.rotateScale, diff --git a/lib/models/icons/main_editor_icons.dart b/lib/models/icons/main_editor_icons.dart new file mode 100644 index 00000000..9007bda9 --- /dev/null +++ b/lib/models/icons/main_editor_icons.dart @@ -0,0 +1,63 @@ +// Flutter imports: +import 'package:flutter/material.dart'; + +/// Customizable icons for Main-Editor component. +class MainEditorIcons { + /// Creates an instance of [MainEditorIcons] with customizable icon settings. + const MainEditorIcons({ + this.closeEditor = Icons.clear, + this.doneIcon = Icons.done, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, + this.undoAction = Icons.undo, + this.redoAction = Icons.redo, + this.removeElementZone = Icons.delete_outline_rounded, + }); + + /// The icon for closing the editor without saving. + final IconData closeEditor; + + /// The icon for applying changes and closing the editor. + final IconData doneIcon; + + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// The icon for undoing the last action. + final IconData undoAction; + + /// The icon for redoing the last undone action. + final IconData redoAction; + + /// The icon for removing an element/ layer like an emoji. + final IconData removeElementZone; + + /// Creates a copy of this `MainEditorIcons` object with the given fields + /// replaced with new values. + /// + /// The [copyWith] method allows you to create a new instance of + /// [MainEditorIcons] with some properties updated while keeping the + /// others unchanged. + MainEditorIcons copyWith({ + IconData? doneIcon, + IconData? closeEditor, + IconData? backButton, + IconData? applyChanges, + IconData? undoAction, + IconData? redoAction, + IconData? removeElementZone, + }) { + return MainEditorIcons( + doneIcon: doneIcon ?? this.doneIcon, + closeEditor: closeEditor ?? this.closeEditor, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, + undoAction: undoAction ?? this.undoAction, + redoAction: redoAction ?? this.redoAction, + removeElementZone: removeElementZone ?? this.removeElementZone, + ); + } +} diff --git a/lib/models/icons/icons_painting_editor.dart b/lib/models/icons/paint_editor_icons.dart similarity index 78% rename from lib/models/icons/icons_painting_editor.dart rename to lib/models/icons/paint_editor_icons.dart index ed14d9e2..0e86458e 100644 --- a/lib/models/icons/icons_painting_editor.dart +++ b/lib/models/icons/paint_editor_icons.dart @@ -1,12 +1,12 @@ // Flutter imports: import 'package:flutter/material.dart'; -/// Customizable icons for the Painting Editor component. -class IconsPaintingEditor { - /// Creates an instance of [IconsPaintingEditor] with customizable icon +/// Customizable icons for the Paint Editor component. +class PaintEditorIcons { + /// Creates an instance of [PaintEditorIcons] with customizable icon /// settings. /// - /// You can provide custom icons for various actions in the Painting Editor + /// You can provide custom icons for various actions in the Paint Editor /// component. /// /// - [bottomNavBar]: The icon for the bottom navigation bar. @@ -25,7 +25,7 @@ class IconsPaintingEditor { /// Example: /// /// ```dart - /// IconsPaintingEditor( + /// PaintEditorIcons( /// bottomNavBar: Icons.edit_rounded, /// lineWeight: Icons.line_weight_rounded, /// fill: Icons.fill, // Add the fill icon here @@ -38,7 +38,7 @@ class IconsPaintingEditor { /// dashLine: Icons.power_input, /// ) /// ``` - const IconsPaintingEditor({ + const PaintEditorIcons({ this.moveAndZoom = Icons.pinch_outlined, this.changeOpacity = Icons.opacity_outlined, this.eraser = Icons.delete_forever_outlined, @@ -52,6 +52,10 @@ class IconsPaintingEditor { this.rectangle = Icons.crop_free, this.circle = Icons.lens_outlined, this.dashLine = Icons.power_input, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, + this.undoAction = Icons.undo, + this.redoAction = Icons.redo, }); /// The icon to be displayed in the bottom navigation bar. @@ -100,13 +104,25 @@ class IconsPaintingEditor { /// The icon for the eraser tool. final IconData eraser; - /// Creates a copy of this `IconsPaintingEditor` object with the given fields + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// The icon for undoing the last action. + final IconData undoAction; + + /// The icon for redoing the last undone action. + final IconData redoAction; + + /// Creates a copy of this `PaintEditorIcons` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsPaintingEditor] with some properties updated while keeping the + /// [PaintEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsPaintingEditor copyWith({ + PaintEditorIcons copyWith({ IconData? moveAndZoom, IconData? changeOpacity, IconData? eraser, @@ -120,8 +136,12 @@ class IconsPaintingEditor { IconData? rectangle, IconData? circle, IconData? dashLine, + IconData? backButton, + IconData? undoAction, + IconData? redoAction, + IconData? applyChanges, }) { - return IconsPaintingEditor( + return PaintEditorIcons( moveAndZoom: moveAndZoom ?? this.moveAndZoom, changeOpacity: changeOpacity ?? this.changeOpacity, eraser: eraser ?? this.eraser, @@ -135,6 +155,10 @@ class IconsPaintingEditor { rectangle: rectangle ?? this.rectangle, circle: circle ?? this.circle, dashLine: dashLine ?? this.dashLine, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, + undoAction: undoAction ?? this.undoAction, + redoAction: redoAction ?? this.redoAction, ); } } diff --git a/lib/models/icons/icons_sticker_editor.dart b/lib/models/icons/sticker_editor_icons.dart similarity index 80% rename from lib/models/icons/icons_sticker_editor.dart rename to lib/models/icons/sticker_editor_icons.dart index 732fa342..99f0f6f7 100644 --- a/lib/models/icons/icons_sticker_editor.dart +++ b/lib/models/icons/sticker_editor_icons.dart @@ -5,8 +5,8 @@ import 'package:flutter/material.dart'; import '../../utils/pro_image_editor_icons.dart'; /// Customizable icons for the Sticker Editor component. -class IconsStickerEditor { - /// Creates an instance of [IconsStickerEditor] with customizable icon +class StickerEditorIcons { + /// Creates an instance of [StickerEditorIcons] with customizable icon /// settings. /// /// You can provide a custom [bottomNavBar] icon to be displayed in the @@ -20,7 +20,7 @@ class IconsStickerEditor { /// bottomNavBar: Icons.layers_outlined, /// ) /// ``` - const IconsStickerEditor({ + const StickerEditorIcons({ this.bottomNavBar = ProImageEditorIcons.stickers, }); @@ -31,12 +31,12 @@ class IconsStickerEditor { /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsStickerEditor] with some properties updated while keeping the + /// [StickerEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsStickerEditor copyWith({ + StickerEditorIcons copyWith({ IconData? bottomNavBar, }) { - return IconsStickerEditor( + return StickerEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, ); } diff --git a/lib/models/icons/icons_text_editor.dart b/lib/models/icons/text_editor_icons.dart similarity index 78% rename from lib/models/icons/icons_text_editor.dart rename to lib/models/icons/text_editor_icons.dart index a48e207e..fa773011 100644 --- a/lib/models/icons/icons_text_editor.dart +++ b/lib/models/icons/text_editor_icons.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; /// Customizable icons for the Text Editor component. -class IconsTextEditor { - /// Creates an instance of [IconsTextEditor] with customizable icon settings. +class TextEditorIcons { + /// Creates an instance of [TextEditorIcons] with customizable icon settings. /// /// You can provide custom icons for various actions in the Text Editor /// component. @@ -19,7 +19,7 @@ class IconsTextEditor { /// Example: /// /// ```dart - /// IconsTextEditor( + /// TextEditorIcons( /// bottomNavBar: Icons.text_fields, /// alignLeft: Icons.align_horizontal_left_rounded, /// alignCenter: Icons.align_horizontal_center_rounded, @@ -27,7 +27,7 @@ class IconsTextEditor { /// backgroundMode: Icons.layers_rounded, /// ) /// ``` - const IconsTextEditor({ + const TextEditorIcons({ this.bottomNavBar = Icons.title_rounded, this.alignLeft = Icons.align_horizontal_left_rounded, this.alignCenter = Icons.align_horizontal_center_rounded, @@ -35,6 +35,8 @@ class IconsTextEditor { this.fontScale = Icons.format_size_rounded, this.resetFontScale = Icons.refresh_rounded, this.backgroundMode = Icons.layers_rounded, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, }); /// The icon to be displayed in the bottom navigation bar. @@ -58,13 +60,19 @@ class IconsTextEditor { /// The icon for resetting font scale to preset value. final IconData resetFontScale; - /// Creates a copy of this `IconsTextEditor` object with the given fields + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// Creates a copy of this `TextEditorIcons` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsTextEditor] with some properties updated while keeping the + /// [TextEditorIcons] with some properties updated while keeping the /// others unchanged. - IconsTextEditor copyWith({ + TextEditorIcons copyWith({ IconData? bottomNavBar, IconData? alignLeft, IconData? alignCenter, @@ -72,8 +80,10 @@ class IconsTextEditor { IconData? backgroundMode, IconData? fontScale, IconData? resetFontScale, + IconData? backButton, + IconData? applyChanges, }) { - return IconsTextEditor( + return TextEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, alignLeft: alignLeft ?? this.alignLeft, alignCenter: alignCenter ?? this.alignCenter, @@ -81,6 +91,8 @@ class IconsTextEditor { backgroundMode: backgroundMode ?? this.backgroundMode, fontScale: fontScale ?? this.fontScale, resetFontScale: resetFontScale ?? this.resetFontScale, + backButton: backButton ?? this.backButton, + applyChanges: applyChanges ?? this.applyChanges, ); } } diff --git a/lib/models/icons/icons_tune_editor.dart b/lib/models/icons/tune_editor_icons.dart similarity index 72% rename from lib/models/icons/icons_tune_editor.dart rename to lib/models/icons/tune_editor_icons.dart index 168f9292..871ae786 100644 --- a/lib/models/icons/icons_tune_editor.dart +++ b/lib/models/icons/tune_editor_icons.dart @@ -5,13 +5,13 @@ import 'package:flutter/material.dart'; /// /// This class holds the [IconData] for various tune adjustment options, /// including brightness, contrast, saturation, exposure, and more. -class IconsTuneEditor { - /// Creates an [IconsTuneEditor] instance with customizable icons for each +class TuneEditorIcons { + /// Creates an [TuneEditorIcons] instance with customizable icons for each /// tune adjustment option. /// /// Each parameter represents the icon used for a specific control in the /// Tune Editor interface. - const IconsTuneEditor({ + const TuneEditorIcons({ this.bottomNavBar = Icons.tune_rounded, this.brightness = Icons.brightness_4_outlined, this.contrast = Icons.contrast, @@ -22,6 +22,10 @@ class IconsTuneEditor { this.sharpness = Icons.shutter_speed, this.fade = Icons.blur_off_outlined, this.luminance = Icons.light_mode_outlined, + this.applyChanges = Icons.done, + this.backButton = Icons.arrow_back, + this.undoAction = Icons.undo, + this.redoAction = Icons.redo, }); /// Icon for the bottom navigation bar item that opens the Tune Editor. @@ -54,11 +58,23 @@ class IconsTuneEditor { /// Icon for the "Luminance" adjustment control. final IconData luminance; - /// Creates a copy of this [IconsTuneEditor] object with the given fields + /// The icon for the back button. + final IconData backButton; + + /// The icon for applying changes in the editor. + final IconData applyChanges; + + /// The icon for undoing the last action. + final IconData undoAction; + + /// The icon for redoing the last undone action. + final IconData redoAction; + + /// Creates a copy of this [TuneEditorIcons] object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [IconsTuneEditor] with some properties updated while keeping the + /// [TuneEditorIcons] with some properties updated while keeping the /// others unchanged. /// /// - [bottomNavBar] updates the icon for the bottom navigation bar item. @@ -66,7 +82,7 @@ class IconsTuneEditor { /// [temperature], [sharpness], /// [fade], and [luminance] update the icons for the respective tune /// adjustment controls. - IconsTuneEditor copyWith({ + TuneEditorIcons copyWith({ IconData? bottomNavBar, IconData? brightness, IconData? contrast, @@ -77,8 +93,12 @@ class IconsTuneEditor { IconData? sharpness, IconData? fade, IconData? luminance, + IconData? backButton, + IconData? undoAction, + IconData? redoAction, + IconData? applyChanges, }) { - return IconsTuneEditor( + return TuneEditorIcons( bottomNavBar: bottomNavBar ?? this.bottomNavBar, brightness: brightness ?? this.brightness, contrast: contrast ?? this.contrast, @@ -89,6 +109,10 @@ class IconsTuneEditor { sharpness: sharpness ?? this.sharpness, fade: fade ?? this.fade, luminance: luminance ?? this.luminance, + backButton: backButton ?? this.backButton, + undoAction: undoAction ?? this.undoAction, + redoAction: redoAction ?? this.redoAction, + applyChanges: applyChanges ?? this.applyChanges, ); } } diff --git a/lib/models/import_export/export_state_history.dart b/lib/models/import_export/export_state_history.dart index 9fbdf5bd..117374a0 100644 --- a/lib/models/import_export/export_state_history.dart +++ b/lib/models/import_export/export_state_history.dart @@ -195,7 +195,7 @@ class ExportStateHistory { required ImageInfos imageInfos, }) async { for (var layer in element.layers) { - if ((_configs.exportPainting && layer.runtimeType == PaintingLayerData) || + if ((_configs.exportPaint && layer.runtimeType == PaintLayerData) || (_configs.exportText && layer.runtimeType == TextLayerData) || (_configs.exportEmoji && layer.runtimeType == EmojiLayerData)) { layers.add(layer.toMap()); @@ -203,9 +203,7 @@ class ExportStateHistory { layer.runtimeType == StickerLayerData) { layers.add((layer as StickerLayerData).toStickerMap(stickers.length)); - double imageWidth = - (editorConfigs.stickerEditorConfigs?.initWidth ?? 100) * - layer.scale; + double imageWidth = editorConfigs.stickerEditor.initWidth * layer.scale; Size targetSize = Size( imageWidth, MediaQuery.of(context).size.height / diff --git a/lib/models/import_export/export_state_history_configs.dart b/lib/models/import_export/export_state_history_configs.dart index fc3d6fd2..348cbd20 100644 --- a/lib/models/import_export/export_state_history_configs.dart +++ b/lib/models/import_export/export_state_history_configs.dart @@ -4,12 +4,12 @@ import 'utils/export_import_enum.dart'; /// Configuration options for exporting editor contents. /// /// This class defines various options for exporting editor contents such as -/// paintings, text, crop/rotate actions, filters, emojis, and stickers. +/// paint, text, crop/rotate actions, filters, emojis, and stickers. class ExportEditorConfigs { /// Creates an instance of the [ExportEditorConfigs] const ExportEditorConfigs({ this.historySpan = ExportHistorySpan.all, - this.exportPainting = true, + this.exportPaint = true, this.exportText = true, this.exportCropRotate = true, this.exportFilter = true, @@ -23,10 +23,10 @@ class ExportEditorConfigs { /// By default, it includes the entire export history. final ExportHistorySpan historySpan; - /// Whether to export the painting content. + /// Whether to export the layers from the paint editor. /// /// Defaults to `true`. - final bool exportPainting; + final bool exportPaint; /// Whether to export the text content. /// diff --git a/lib/models/init_configs/crop_rotate_editor_init_configs.dart b/lib/models/init_configs/crop_rotate_editor_init_configs.dart index bd82b469..7b433b36 100644 --- a/lib/models/init_configs/crop_rotate_editor_init_configs.dart +++ b/lib/models/init_configs/crop_rotate_editor_init_configs.dart @@ -61,11 +61,17 @@ class CropRotateEditorInitConfigs extends EditorInitConfigs { super.onImageEditingComplete, super.onImageEditingStarted, super.convertToUint8List, + super.enableCloseButton, required super.theme, this.onDone, + this.enablePopWhenDone = true, this.enableFakeHero = false, }); + /// Indicates whether the widget should automatically pop from the navigation + /// stack when done. + final bool enablePopWhenDone; + /// A callback function called when editing is completed. final CropRotateEditorDone? onDone; diff --git a/lib/models/init_configs/editor_init_configs.dart b/lib/models/init_configs/editor_init_configs.dart index d52981f0..8f4fb505 100644 --- a/lib/models/init_configs/editor_init_configs.dart +++ b/lib/models/init_configs/editor_init_configs.dart @@ -43,8 +43,12 @@ abstract class EditorInitConfigs { this.onImageEditingComplete, this.onImageEditingStarted, this.convertToUint8List = false, + this.enableCloseButton = true, }); + /// Determines whether the close button is displayed on the widget. + final bool enableCloseButton; + /// The configuration options for the image editor. final ProImageEditorConfigs configs; diff --git a/lib/models/init_configs/paint_editor_init_configs.dart b/lib/models/init_configs/paint_editor_init_configs.dart index 3ce10697..71fedf3f 100644 --- a/lib/models/init_configs/paint_editor_init_configs.dart +++ b/lib/models/init_configs/paint_editor_init_configs.dart @@ -4,7 +4,7 @@ import 'editor_init_configs.dart'; /// Configuration class for initializing the paint editor. /// /// This class extends [EditorInitConfigs] and adds specific parameters related -/// to painting functionality. +/// to paint functionality. class PaintEditorInitConfigs extends EditorInitConfigs { /// Creates a new instance of [PaintEditorInitConfigs]. /// diff --git a/lib/models/layer/layer.dart b/lib/models/layer/layer.dart index 24829486..cef79f77 100644 --- a/lib/models/layer/layer.dart +++ b/lib/models/layer/layer.dart @@ -66,25 +66,21 @@ class Layer { /// LayerData subclass. switch (map['type']) { case 'text': - - /// Returns a TextLayerData instance when type is 'text'. + // Returns a TextLayerData instance when type is 'text'. return TextLayerData.fromMap(layer, map); case 'emoji': - - /// Returns an EmojiLayerData instance when type is 'emoji'. + // Returns an EmojiLayerData instance when type is 'emoji'. return EmojiLayerData.fromMap(layer, map); + case 'paint': case 'painting': - - /// Returns a PaintingLayerData instance when type is 'painting'. - return PaintingLayerData.fromMap(layer, map); + // Returns a PaintLayerData instance when type is 'paint'. + return PaintLayerData.fromMap(layer, map); case 'sticker': - - /// Returns a StickerLayerData instance when type is 'sticker', - /// utilizing the stickers list. + // Returns a StickerLayerData instance when type is 'sticker', + // utilizing the stickers list. return StickerLayerData.fromMap(layer, map, stickers); default: - - /// Returns the base Layer instance when type is unrecognized. + // Returns the base Layer instance when type is unrecognized. return layer; } } @@ -372,16 +368,16 @@ class EmojiLayerData extends Layer { } } -/// A class representing a layer with custom painting content. +/// A class representing a layer with custom paint content. /// -/// PaintingLayerData is a subclass of [Layer] that allows you to display +/// PaintLayerData is a subclass of [Layer] that allows you to display /// custom-painted content on a canvas. You can specify the painted item and /// its raw size, along with optional properties like offset, rotation, /// scale, and more. /// /// Example usage: /// ```dart -/// PaintingLayerData( +/// PaintLayerData( /// item: CustomPaintedItem(), /// rawSize: Size(200.0, 150.0), /// offset: Offset(50.0, 50.0), @@ -389,12 +385,12 @@ class EmojiLayerData extends Layer { /// scale: 1.5, /// ); /// ``` -class PaintingLayerData extends Layer { - /// Creates an instance of PaintingLayerData. +class PaintLayerData extends Layer { + /// Creates an instance of PaintLayerData. /// /// The [item] and [rawSize] parameters are required, and other properties /// are optional. - PaintingLayerData({ + PaintLayerData({ required this.item, required this.rawSize, required this.opacity, @@ -407,12 +403,12 @@ class PaintingLayerData extends Layer { super.enableInteraction, }); - /// Factory constructor for creating a PaintingLayerData instance from a + /// Factory constructor for creating a PaintLayerData instance from a /// Layer and a map. - factory PaintingLayerData.fromMap(Layer layer, Map map) { - /// Constructs and returns a PaintingLayerData instance with properties + factory PaintLayerData.fromMap(Layer layer, Map map) { + /// Constructs and returns a PaintLayerData instance with properties /// derived from the layer and map. - return PaintingLayerData( + return PaintLayerData( flipX: layer.flipX, flipY: layer.flipY, enableInteraction: layer.enableInteraction, @@ -450,7 +446,7 @@ class PaintingLayerData extends Layer { 'h': rawSize.height, }, 'opacity': opacity, - 'type': 'painting', + 'type': 'paint', }; } } diff --git a/lib/models/paint_editor/paint_bottom_bar_item.dart b/lib/models/paint_editor/paint_bottom_bar_item.dart index ceb8f176..737c0699 100644 --- a/lib/models/paint_editor/paint_bottom_bar_item.dart +++ b/lib/models/paint_editor/paint_bottom_bar_item.dart @@ -4,26 +4,26 @@ import 'package:flutter/widgets.dart'; // Project imports: import '../../modules/paint_editor/utils/paint_editor_enum.dart'; -/// Represents a model for a painting mode, including an icon, a mode +/// Represents a model for a paint-mode item, including an icon, a mode /// identifier, and a label. class PaintModeBottomBarItem { - /// Creates a [PaintModeBottomBarItem] instance to define a painting mode. + /// Creates a [PaintModeBottomBarItem] instance to define a paint mode. /// - /// - [icon]: An optional icon to visually represent the painting mode. - /// - [mode]: The identifier for the painting mode (enum value). - /// - [label]: A descriptive label for the painting mode. + /// - [icon]: An optional icon to visually represent the paint mode. + /// - [mode]: The identifier for the paint mode (enum value). + /// - [label]: A descriptive label for the paint mode. const PaintModeBottomBarItem({ required this.icon, required this.mode, required this.label, }); - /// The icon representing the painting mode. + /// The icon representing the paint mode. final IconData icon; - /// The identifier for the painting mode. + /// The identifier for the paint mode. final PaintModeE mode; - /// A descriptive label for the painting mode. + /// A descriptive label for the paint mode. final String label; } diff --git a/lib/models/paint_editor/painted_model.dart b/lib/models/paint_editor/painted_model.dart index 4f3e9691..3b619ef3 100644 --- a/lib/models/paint_editor/painted_model.dart +++ b/lib/models/paint_editor/painted_model.dart @@ -10,11 +10,11 @@ import 'package:pro_image_editor/utils/parser/double_parser.dart'; import '../../modules/paint_editor/utils/paint_editor_enum.dart'; import '../../utils/unique_id_generator.dart'; -/// Represents a unit of shape or drawing information used in painting. +/// Represents a unit of shape or drawing information used in paint. class PaintedModel { /// Factory constructor for creating a PaintedModel instance from a map. factory PaintedModel.fromMap(Map map) { - /// List to hold offset points for the painting. + /// List to hold offset points for the paint. List offsets = []; /// Iterate over the offsets in the map and add them to the list. diff --git a/lib/models/theme/theme_adaptive_dialog.dart b/lib/models/styles/adaptive_dialog_style.dart similarity index 71% rename from lib/models/theme/theme_adaptive_dialog.dart rename to lib/models/styles/adaptive_dialog_style.dart index 3c77a610..7fc20aca 100644 --- a/lib/models/theme/theme_adaptive_dialog.dart +++ b/lib/models/styles/adaptive_dialog_style.dart @@ -1,10 +1,10 @@ // Flutter imports: import 'package:flutter/widgets.dart'; -/// A theme configuration for adaptive dialogs. -class AdaptiveDialogTheme { - /// Constructs an [AdaptiveDialogTheme] object with the given parameters. - const AdaptiveDialogTheme({ +/// A style configuration for adaptive dialogs. +class AdaptiveDialogStyle { + /// Constructs an [AdaptiveDialogStyle] object with the given parameters. + const AdaptiveDialogStyle({ this.cupertinoPrimaryColorLight = const Color(0xFF000000), this.cupertinoPrimaryColorDark = const Color(0xFFFFFFFF), }); @@ -15,17 +15,17 @@ class AdaptiveDialogTheme { /// Primary color in the Cupertino design with brightness `dark`. final Color cupertinoPrimaryColorDark; - /// Creates a copy of this `AdaptiveDialogTheme` object with the given fields + /// Creates a copy of this `AdaptiveDialogStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [AdaptiveDialogTheme] with some properties updated while keeping the + /// [AdaptiveDialogStyle] with some properties updated while keeping the /// others unchanged. - AdaptiveDialogTheme copyWith({ + AdaptiveDialogStyle copyWith({ Color? cupertinoPrimaryColorLight, Color? cupertinoPrimaryColorDark, }) { - return AdaptiveDialogTheme( + return AdaptiveDialogStyle( cupertinoPrimaryColorLight: cupertinoPrimaryColorLight ?? this.cupertinoPrimaryColorLight, cupertinoPrimaryColorDark: diff --git a/lib/models/theme/theme_blur_editor.dart b/lib/models/styles/blur_editor_style.dart similarity index 58% rename from lib/models/theme/theme_blur_editor.dart rename to lib/models/styles/blur_editor_style.dart index 46a53828..df1372eb 100644 --- a/lib/models/theme/theme_blur_editor.dart +++ b/lib/models/styles/blur_editor_style.dart @@ -1,17 +1,16 @@ // Flutter imports: -import 'package:flutter/widgets.dart'; +import 'package:flutter/services.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// The `BlurEditorTheme` class defines the theme for the blur editor in the +/// The `BlurEditorStyle` class defines the style for the blur editor in the /// image editor. /// It includes properties such as colors for the app bar and background. /// /// Usage: /// /// ```dart -/// BlurEditorTheme BlurEditorTheme = BlurEditorTheme( +/// BlurEditorStyle BlurEditorStyle = BlurEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, @@ -30,23 +29,23 @@ import 'theme_shared_values.dart'; /// Example Usage: /// /// ```dart -/// BlurEditorTheme BlurEditorTheme = BlurEditorTheme( +/// BlurEditorStyle BlurEditorStyle = BlurEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, /// ); /// -/// Color appBarBackgroundColor = BlurEditorTheme.appBarBackgroundColor; -/// Color background = BlurEditorTheme.background; -/// // Access other theme properties... +/// Color appBarBackgroundColor = BlurEditorStyle.appBarBackgroundColor; +/// Color background = BlurEditorStyle.background; /// ``` -class BlurEditorTheme { - /// Creates an instance of the `BlurEditorTheme` class with the specified - /// theme properties. - const BlurEditorTheme({ - this.appBarBackgroundColor = imageEditorAppBarColor, +class BlurEditorStyle { + /// Creates an instance of the `BlurEditorStyle` class with the specified + /// style properties. + const BlurEditorStyle({ + this.appBarBackgroundColor = kImageEditorAppBarBackground, this.appBarForegroundColor = const Color(0xFFE1E1E1), - this.background = imageEditorBackgroundColor, + this.background = kImageEditorBackground, + this.uiOverlayStyle = kImageEditorUiOverlayStyle, }); /// Background color of the app bar in the blur editor. @@ -58,23 +57,28 @@ class BlurEditorTheme { /// Background color of the blur editor. final Color background; - /// Creates a copy of this `BlurEditorTheme` object with the given fields + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// Creates a copy of this `BlurEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [BlurEditorTheme] with some properties updated while keeping the + /// [BlurEditorStyle] with some properties updated while keeping the /// others unchanged. - BlurEditorTheme copyWith({ + BlurEditorStyle copyWith({ Color? appBarBackgroundColor, Color? appBarForegroundColor, Color? background, + SystemUiOverlayStyle? uiOverlayStyle, }) { - return BlurEditorTheme( + return BlurEditorStyle( appBarBackgroundColor: appBarBackgroundColor ?? this.appBarBackgroundColor, appBarForegroundColor: appBarForegroundColor ?? this.appBarForegroundColor, background: background ?? this.background, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, ); } } diff --git a/lib/models/theme/theme_crop_rotate_editor.dart b/lib/models/styles/crop_rotate_editor_style.dart similarity index 65% rename from lib/models/theme/theme_crop_rotate_editor.dart rename to lib/models/styles/crop_rotate_editor_style.dart index 5ec1ac00..ee14d8df 100644 --- a/lib/models/theme/theme_crop_rotate_editor.dart +++ b/lib/models/styles/crop_rotate_editor_style.dart @@ -1,10 +1,9 @@ // Flutter imports: -import 'package:flutter/widgets.dart'; +import 'package:flutter/services.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// The `CropRotateEditorTheme` class defines the theme for the crop and rotate +/// The `CropRotateEditorStyle` class defines the styles for the crop and rotate /// editor in the image editor. /// It includes properties such as colors for the app bar, background, crop /// corners, and more. @@ -12,7 +11,7 @@ import 'theme_shared_values.dart'; /// Usage: /// /// ```dart -/// CropRotateEditorTheme cropRotateEditorTheme = CropRotateEditorTheme( +/// CropRotateEditorStyle cropRotateEditorStyle = CropRotateEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, @@ -38,7 +37,7 @@ import 'theme_shared_values.dart'; /// Example Usage: /// /// ```dart -/// CropRotateEditorTheme cropRotateEditorTheme = CropRotateEditorTheme( +/// CropRotateEditorStyle cropRotateEditorStyle = CropRotateEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, @@ -46,39 +45,40 @@ import 'theme_shared_values.dart'; /// cropRectType: InitCropRectType.circle, /// ); /// -/// Color appBarBackgroundColor = cropRotateEditorTheme.appBarBackgroundColor; -/// Color background = cropRotateEditorTheme.background; -/// // Access other theme properties... +/// Color appBarBackgroundColor = cropRotateEditorStyle.appBarBackgroundColor; +/// Color background = cropRotateEditorStyle.background; +/// // Access other style properties... /// ``` -class CropRotateEditorTheme { - /// Creates an instance of the `CropRotateEditorTheme` class with the - /// specified theme properties. - const CropRotateEditorTheme({ - this.appBarBackgroundColor = imageEditorAppBarColor, - this.appBarForegroundColor = const Color(0xFFE1E1E1), +class CropRotateEditorStyle { + /// Creates an instance of the `CropRotateEditorStyle` class with the + /// specified style properties. + const CropRotateEditorStyle({ + this.appBarBackground = kImageEditorAppBarBackground, + this.appBarColor = kImageEditorAppBarColor, this.helperLineColor = const Color(0xFF000000), - this.background = imageEditorBackgroundColor, - this.cropCornerColor = imageEditorPrimaryColor, + this.background = kImageEditorBackground, + this.cropCornerColor = kImageEditorPrimaryColor, this.cropOverlayColor = const Color(0xFF000000), - this.bottomBarBackgroundColor = imageEditorAppBarColor, - this.bottomBarForegroundColor = const Color(0xFFE1E1E1), + this.bottomBarBackground = kImageEditorAppBarBackground, + this.bottomBarColor = kImageEditorAppBarColor, this.aspectRatioSheetBackgroundColor = const Color(0xFF303030), this.aspectRatioSheetForegroundColor = const Color(0xFFFAFAFA), this.cropCornerLength = 36, this.cropCornerThickness = 6, + this.uiOverlayStyle = kImageEditorUiOverlayStyle, }); /// Background color of the app bar in the crop and rotate editor. - final Color appBarBackgroundColor; + final Color appBarBackground; /// Foreground color (text and icons) of the app bar. - final Color appBarForegroundColor; + final Color appBarColor; /// Background color of the bottom app bar. - final Color bottomBarBackgroundColor; + final Color bottomBarBackground; /// Foreground color (text and icons) of the bottom app bar. - final Color bottomBarForegroundColor; + final Color bottomBarColor; /// Background color of the bottomSheet for aspect ratios. final Color aspectRatioSheetBackgroundColor; @@ -108,17 +108,20 @@ class CropRotateEditorTheme { /// The thickness of the crop corner. final double cropCornerThickness; - /// Creates a copy of this `CropRotateEditorTheme` object with the given + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// Creates a copy of this `CropRotateEditorStyle` object with the given /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [CropRotateEditorTheme] with some properties updated while keeping the + /// [CropRotateEditorStyle] with some properties updated while keeping the /// others unchanged. - CropRotateEditorTheme copyWith({ - Color? appBarBackgroundColor, - Color? appBarForegroundColor, - Color? bottomBarBackgroundColor, - Color? bottomBarForegroundColor, + CropRotateEditorStyle copyWith({ + Color? appBarBackground, + Color? appBarColor, + Color? bottomBarBackground, + Color? bottomBarColor, Color? aspectRatioSheetBackgroundColor, Color? aspectRatioSheetForegroundColor, Color? background, @@ -127,16 +130,13 @@ class CropRotateEditorTheme { Color? cropOverlayColor, double? cropCornerLength, double? cropCornerThickness, + SystemUiOverlayStyle? uiOverlayStyle, }) { - return CropRotateEditorTheme( - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, - bottomBarBackgroundColor: - bottomBarBackgroundColor ?? this.bottomBarBackgroundColor, - bottomBarForegroundColor: - bottomBarForegroundColor ?? this.bottomBarForegroundColor, + return CropRotateEditorStyle( + appBarBackground: appBarBackground ?? this.appBarBackground, + appBarColor: appBarColor ?? this.appBarColor, + bottomBarBackground: bottomBarBackground ?? this.bottomBarBackground, + bottomBarColor: bottomBarColor ?? this.bottomBarColor, aspectRatioSheetBackgroundColor: aspectRatioSheetBackgroundColor ?? this.aspectRatioSheetBackgroundColor, aspectRatioSheetForegroundColor: aspectRatioSheetForegroundColor ?? @@ -147,6 +147,7 @@ class CropRotateEditorTheme { cropOverlayColor: cropOverlayColor ?? this.cropOverlayColor, cropCornerLength: cropCornerLength ?? this.cropCornerLength, cropCornerThickness: cropCornerThickness ?? this.cropCornerThickness, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, ); } } diff --git a/lib/models/styles/dialog_style.dart b/lib/models/styles/dialog_style.dart new file mode 100644 index 00000000..2ea1b389 --- /dev/null +++ b/lib/models/styles/dialog_style.dart @@ -0,0 +1,31 @@ +import 'adaptive_dialog_style.dart'; +import 'loading_dialog_style.dart'; + +export 'adaptive_dialog_style.dart'; +export 'loading_dialog_style.dart'; + +/// Style configuration class for dialogs used in the editor. +class DialogStyle { + /// Creates a new instance of [DialogStyle]. + const DialogStyle({ + this.loadingDialog = const LoadingDialogStyle(), + this.adaptiveDialog = const AdaptiveDialogStyle(), + }); + + /// Style configuration for the loading dialog. + final LoadingDialogStyle loadingDialog; + + /// Style configuration for adaptive dialogs. + final AdaptiveDialogStyle adaptiveDialog; + + /// Creates a copy of this style configuration with the specified overrides. + DialogStyle copyWith({ + LoadingDialogStyle? loadingDialog, + AdaptiveDialogStyle? adaptiveDialog, + }) { + return DialogStyle( + loadingDialog: loadingDialog ?? this.loadingDialog, + adaptiveDialog: adaptiveDialog ?? this.adaptiveDialog, + ); + } +} diff --git a/lib/models/theme/theme_draggable_sheet.dart b/lib/models/styles/draggable_sheet_style.dart similarity index 88% rename from lib/models/theme/theme_draggable_sheet.dart rename to lib/models/styles/draggable_sheet_style.dart index 467e6cb7..69a43ca6 100644 --- a/lib/models/theme/theme_draggable_sheet.dart +++ b/lib/models/styles/draggable_sheet_style.dart @@ -1,11 +1,11 @@ /// Configuration settings for a draggable bottom sheet component. -class ThemeDraggableSheet { - /// Creates an instance of [ThemeDraggableSheet] with customizable settings. +class DraggableSheetStyle { + /// Creates an instance of [DraggableSheetStyle] with customizable settings. /// /// Example: /// /// ```dart - /// ThemeDraggableSheet( + /// DraggableSheetStyle( /// initialChildSize: 0.5, /// minChildSize: 0.25, /// maxChildSize: 1.0, @@ -16,7 +16,7 @@ class ThemeDraggableSheet { /// shouldCloseOnMinExtent: true, /// ) /// ``` - const ThemeDraggableSheet({ + const DraggableSheetStyle({ this.initialChildSize = 0.5, this.minChildSize = 0.25, this.maxChildSize = 1.0, @@ -67,13 +67,13 @@ class ThemeDraggableSheet { /// Defaults to `true`. final bool shouldCloseOnMinExtent; - /// Creates a copy of this `ThemeDraggableSheet` object with the given fields + /// Creates a copy of this `DraggableSheetStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [ThemeDraggableSheet] with some properties updated while keeping the + /// [DraggableSheetStyle] with some properties updated while keeping the /// others unchanged. - ThemeDraggableSheet copyWith({ + DraggableSheetStyle copyWith({ double? initialChildSize, double? minChildSize, double? maxChildSize, @@ -83,7 +83,7 @@ class ThemeDraggableSheet { Duration? snapAnimationDuration, bool? shouldCloseOnMinExtent, }) { - return ThemeDraggableSheet( + return DraggableSheetStyle( initialChildSize: initialChildSize ?? this.initialChildSize, minChildSize: minChildSize ?? this.minChildSize, maxChildSize: maxChildSize ?? this.maxChildSize, diff --git a/lib/models/theme/theme_emoji_editor.dart b/lib/models/styles/emoji_editor_style.dart similarity index 87% rename from lib/models/theme/theme_emoji_editor.dart rename to lib/models/styles/emoji_editor_style.dart index ecb45536..91284747 100644 --- a/lib/models/theme/theme_emoji_editor.dart +++ b/lib/models/styles/emoji_editor_style.dart @@ -13,9 +13,9 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart' import 'package:flutter/widgets.dart'; // Project imports: -import '../theme/theme_shared_values.dart'; -import 'theme_draggable_sheet.dart'; -import 'types/theme_types.dart'; +import '../../common/editor_style_constants.dart'; +import 'draggable_sheet_style.dart'; +import 'types/style_types.dart'; export 'package:emoji_picker_flutter/emoji_picker_flutter.dart' show @@ -27,39 +27,39 @@ export 'package:emoji_picker_flutter/emoji_picker_flutter.dart' SearchViewConfig, SkinToneConfig; -/// The `EmojiEditorTheme` class defines the theme for the emoji editor in the +/// The `EmojiEditorStyle` class defines the styles for the emoji editor in the /// image editor. /// /// Usage: /// /// ```dart -/// EmojiEditorTheme emojiEditorTheme = EmojiEditorTheme(); +/// EmojiEditorStyle emojiEditorStyle = EmojiEditorStyle(); /// ``` -class EmojiEditorTheme { - /// Creates an instance of the `EmojiEditorTheme` class with the specified - /// theme properties. +class EmojiEditorStyle { + /// Creates an instance of the `EmojiEditorStyle` class with the specified + /// style properties. /// /// Example: /// /// ```dart - /// EmojiEditorTheme( + /// EmojiEditorStyle( /// bottomActionBarConfig: BottomActionBarConfig(...), /// skinToneConfig: SkinToneConfig(...), /// ... /// ) /// ``` - const EmojiEditorTheme({ + const EmojiEditorStyle({ this.editorBoxConstraintsBuilder, this.backgroundColor = const Color(0xFF121B22), this.scrollToDuration = Duration.zero, - this.themeDraggableSheet = const ThemeDraggableSheet( + this.themeDraggableSheet = const DraggableSheetStyle( minChildSize: 0.4, maxChildSize: 0.4, initialChildSize: 0.4, ), this.showDragHandle = true, this.bottomActionBarConfig = const BottomActionBarConfig( - buttonIconColor: imageEditorTextColor, + buttonIconColor: kImageEditorTextColor, backgroundColor: Color(0xFF121B22), buttonColor: Color(0xFF121B22), showBackspaceButton: false, @@ -126,7 +126,7 @@ class EmojiEditorTheme { final bool showDragHandle; /// Configuration settings for the draggable bottom sheet component. - final ThemeDraggableSheet themeDraggableSheet; + final DraggableSheetStyle themeDraggableSheet; /// Padding for the category title. final EdgeInsets categoryTitlePadding; @@ -147,13 +147,13 @@ class EmojiEditorTheme { /// [ProImageEditorConfigs.editorBoxConstraintsBuilder]. final EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder; - /// Creates a copy of this `EmojiEditorTheme` object with the given fields + /// Creates a copy of this `EmojiEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [EmojiEditorTheme] with some properties updated while keeping the + /// [EmojiEditorStyle] with some properties updated while keeping the /// others unchanged. - EmojiEditorTheme copyWith({ + EmojiEditorStyle copyWith({ SkinToneConfig? skinToneConfig, BottomActionBarConfig? bottomActionBarConfig, SearchViewConfig? searchViewConfig, @@ -162,14 +162,14 @@ class EmojiEditorTheme { TextStyle? textStyle, ViewOrderConfig? viewOrderConfig, bool? showDragHandle, - ThemeDraggableSheet? themeDraggableSheet, + DraggableSheetStyle? themeDraggableSheet, EdgeInsets? categoryTitlePadding, TextStyle? categoryTitleStyle, Color? backgroundColor, Duration? scrollToDuration, EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder, }) { - return EmojiEditorTheme( + return EmojiEditorStyle( skinToneConfig: skinToneConfig ?? this.skinToneConfig, bottomActionBarConfig: bottomActionBarConfig ?? this.bottomActionBarConfig, diff --git a/lib/models/theme/theme_filter_editor.dart b/lib/models/styles/filter_editor_style.dart similarity index 60% rename from lib/models/theme/theme_filter_editor.dart rename to lib/models/styles/filter_editor_style.dart index 6cd02b89..42874a1e 100644 --- a/lib/models/theme/theme_filter_editor.dart +++ b/lib/models/styles/filter_editor_style.dart @@ -1,25 +1,14 @@ // Flutter imports: +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// The `FilterEditorTheme` class defines the theme for the filter editor in +/// The `FilterEditorStyle` class defines the style for the filter editor in /// the image editor. /// It includes properties such as colors for the app bar, background, and /// preview text. /// -/// Usage: -/// -/// ```dart -/// FilterEditorTheme filterEditorTheme = FilterEditorTheme( -/// appBarBackgroundColor: Colors.black, -/// appBarForegroundColor: Colors.white, -/// background: Colors.grey, -/// previewTextColor: Colors.blue, -/// ); -/// ``` -/// /// Properties: /// /// - `appBarBackgroundColor`: Background color of the app bar in the filter @@ -34,35 +23,36 @@ import 'theme_shared_values.dart'; /// Example Usage: /// /// ```dart -/// FilterEditorTheme filterEditorTheme = FilterEditorTheme( +/// FilterEditorStyle filterEditorStyle = FilterEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, /// previewTextColor: Colors.blue, /// ); /// -/// Color appBarBackgroundColor = filterEditorTheme.appBarBackgroundColor; -/// Color background = filterEditorTheme.background; -/// // Access other theme properties... +/// Color appBarBackgroundColor = FilterEditorStyle.appBarBackgroundColor; +/// Color background = FilterEditorStyle.background; +/// // Access other style properties... /// ``` -class FilterEditorTheme { - /// Creates an instance of the `FilterEditorTheme` class with the specified - /// theme properties. - const FilterEditorTheme({ - this.appBarBackgroundColor = imageEditorAppBarColor, - this.appBarForegroundColor = const Color(0xFFE1E1E1), +class FilterEditorStyle { + /// Creates an instance of the `FilterEditorStyle` class with the specified + /// style properties. + const FilterEditorStyle({ + this.appBarBackground = kImageEditorAppBarBackground, + this.appBarColor = kImageEditorAppBarColor, this.previewTextColor = const Color(0xFFE1E1E1), this.previewSelectedTextColor = const Color.fromARGB(255, 34, 148, 242), - this.background = imageEditorBackgroundColor, + this.background = kImageEditorBackground, this.filterListSpacing = 15, this.filterListMargin = const EdgeInsets.fromLTRB(8, 4, 8, 10), + this.uiOverlayStyle = kImageEditorUiOverlayStyle, }); /// Background color of the app bar in the filter editor. - final Color appBarBackgroundColor; + final Color appBarBackground; /// Foreground color (text and icons) of the app bar. - final Color appBarForegroundColor; + final Color appBarColor; /// Background color of the filter editor. final Color background; @@ -79,32 +69,35 @@ class FilterEditorTheme { /// The margin around the filter list. final EdgeInsets filterListMargin; - /// Creates a copy of this `FilterEditorTheme` object with the given fields + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// Creates a copy of this `FilterEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [FilterEditorTheme] with some properties updated while keeping the + /// [FilterEditorStyle] with some properties updated while keeping the /// others unchanged. - FilterEditorTheme copyWith({ - Color? appBarBackgroundColor, - Color? appBarForegroundColor, + FilterEditorStyle copyWith({ + Color? appBarBackground, + Color? appBarColor, Color? background, Color? previewTextColor, Color? previewSelectedTextColor, double? filterListSpacing, EdgeInsets? filterListMargin, + SystemUiOverlayStyle? uiOverlayStyle, }) { - return FilterEditorTheme( - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, + return FilterEditorStyle( + appBarBackground: appBarBackground ?? this.appBarBackground, + appBarColor: appBarColor ?? this.appBarColor, background: background ?? this.background, previewTextColor: previewTextColor ?? this.previewTextColor, previewSelectedTextColor: previewSelectedTextColor ?? this.previewSelectedTextColor, filterListSpacing: filterListSpacing ?? this.filterListSpacing, filterListMargin: filterListMargin ?? this.filterListMargin, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, ); } } diff --git a/lib/models/theme/theme_helper_lines.dart b/lib/models/styles/helper_line_style.dart similarity index 69% rename from lib/models/theme/theme_helper_lines.dart rename to lib/models/styles/helper_line_style.dart index ab71763c..cfaec125 100644 --- a/lib/models/theme/theme_helper_lines.dart +++ b/lib/models/styles/helper_line_style.dart @@ -1,7 +1,7 @@ // Flutter imports: import 'package:flutter/widgets.dart'; -/// The `HelperLineTheme` class defines the theme for helper lines in the image +/// The `HelperLineStyle` class defines the style for helper lines in the image /// editor. /// Helper lines are used to assist with alignment and positioning of elements /// in the editor. @@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart'; /// Usage: /// /// ```dart -/// HelperLineTheme helperLineTheme = HelperLineTheme( +/// HelperLineStyle HelperLineStyle = HelperLineStyle( /// horizontalColor: Colors.blue, /// verticalColor: Colors.red, /// rotateColor: Colors.pink, @@ -27,20 +27,20 @@ import 'package:flutter/widgets.dart'; /// Example Usage: /// /// ```dart -/// HelperLineTheme helperLineTheme = HelperLineTheme( +/// HelperLineStyle HelperLineStyle = HelperLineStyle( /// horizontalColor: Colors.blue, /// verticalColor: Colors.red, /// rotateColor: Colors.pink, /// ); /// -/// Color horizontalColor = helperLineTheme.horizontalColor; -/// Color verticalColor = helperLineTheme.verticalColor; -/// // Access other theme properties... +/// Color horizontalColor = HelperLineStyle.horizontalColor; +/// Color verticalColor = HelperLineStyle.verticalColor; +/// // Access other style properties... /// ``` -class HelperLineTheme { - /// Creates an instance of the `HelperLineTheme` class with the specified - /// theme properties. - const HelperLineTheme({ +class HelperLineStyle { + /// Creates an instance of the `HelperLineStyle` class with the specified + /// style properties. + const HelperLineStyle({ this.horizontalColor = const Color(0xFF1565C0), this.verticalColor = const Color(0xFF1565C0), this.rotateColor = const Color(0xFFE91E63), @@ -55,18 +55,18 @@ class HelperLineTheme { /// Color of rotation helper lines. final Color rotateColor; - /// Creates a copy of this `HelperLineTheme` object with the given fields + /// Creates a copy of this `HelperLineStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [HelperLineTheme] with some properties updated while keeping the + /// [HelperLineStyle] with some properties updated while keeping the /// others unchanged. - HelperLineTheme copyWith({ + HelperLineStyle copyWith({ Color? horizontalColor, Color? verticalColor, Color? rotateColor, }) { - return HelperLineTheme( + return HelperLineStyle( horizontalColor: horizontalColor ?? this.horizontalColor, verticalColor: verticalColor ?? this.verticalColor, rotateColor: rotateColor ?? this.rotateColor, diff --git a/lib/models/theme/theme_layer_interaction.dart b/lib/models/styles/layer_interaction_style.dart similarity index 94% rename from lib/models/theme/theme_layer_interaction.dart rename to lib/models/styles/layer_interaction_style.dart index 38d0e1dd..53057d66 100644 --- a/lib/models/theme/theme_layer_interaction.dart +++ b/lib/models/styles/layer_interaction_style.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -/// Represents the interaction settings for layers in the theme. +/// Represents the interaction settings for layers in the style. /// /// This class defines the visual interaction properties such as button radius, /// stroke width, dash width, dash space, dash color, and cursor styles for -/// interacting with layers in the theme. -class ThemeLayerInteraction { - /// Creates a new instance of [ThemeLayerInteraction]. +/// interacting with layers in the style. +class LayerInteractionStyle { + /// Creates a new instance of [LayerInteractionStyle]. /// /// - The [buttonRadius] defaults to `10.0`. /// - The [strokeWidth] defaults to `1.2`. @@ -20,7 +20,7 @@ class ThemeLayerInteraction { /// - The [hoverCursor] defaults to [SystemMouseCursors.move]. /// - The [borderStyle] defaults to [LayerInteractionBorderStyle.solid]. /// - The [showTooltips] defaults to `false`. - const ThemeLayerInteraction({ + const LayerInteractionStyle({ this.removeAreaBackgroundActive = const Color(0xFFF44336), this.removeAreaBackgroundInactive = const Color(0xFF424242), this.buttonRadius = 10, @@ -123,13 +123,13 @@ class ThemeLayerInteraction { /// rotate layers, influencing its visual appearance. final Color buttonScaleRotateBackground; - /// Creates a copy of this `ThemeLayerInteraction` object with the given + /// Creates a copy of this `LayerInteractionStyle` object with the given /// fields replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [ThemeLayerInteraction] with some properties updated while keeping the + /// [LayerInteractionStyle] with some properties updated while keeping the /// others unchanged. - ThemeLayerInteraction copyWith({ + LayerInteractionStyle copyWith({ double? buttonRadius, double? strokeWidth, double? borderElementWidth, @@ -150,7 +150,7 @@ class ThemeLayerInteraction { Color? buttonScaleRotateColor, Color? buttonScaleRotateBackground, }) { - return ThemeLayerInteraction( + return LayerInteractionStyle( buttonRadius: buttonRadius ?? this.buttonRadius, strokeWidth: strokeWidth ?? this.strokeWidth, borderElementWidth: borderElementWidth ?? this.borderElementWidth, diff --git a/lib/models/theme/theme_loading_dialog.dart b/lib/models/styles/loading_dialog_style.dart similarity index 68% rename from lib/models/theme/theme_loading_dialog.dart rename to lib/models/styles/loading_dialog_style.dart index 96685a01..53933e38 100644 --- a/lib/models/theme/theme_loading_dialog.dart +++ b/lib/models/styles/loading_dialog_style.dart @@ -1,15 +1,14 @@ // Flutter imports: import 'package:flutter/widgets.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// A theme configuration for loading dialogs. -class LoadingDialogTheme { - /// Creates an instance of the `LoadingDialogTheme` class with the specified - /// theme properties. - const LoadingDialogTheme({ - this.textColor = imageEditorTextColor, +/// A style configuration for loading dialogs. +class LoadingDialogStyle { + /// Creates an instance of the `LoadingDialogStyle` class with the specified + /// style properties. + const LoadingDialogStyle({ + this.textColor = kImageEditorTextColor, this.cupertinoPrimaryColorLight = const Color(0xFF000000), this.cupertinoPrimaryColorDark = const Color(0xFFFFFFFF), }); @@ -23,18 +22,18 @@ class LoadingDialogTheme { /// Primary color in the Cupertino design with brightness `dark`. final Color cupertinoPrimaryColorDark; - /// Creates a copy of this `LoadingDialogTheme` object with the given fields + /// Creates a copy of this `LoadingDialogStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [LoadingDialogTheme] with some properties updated while keeping the + /// [LoadingDialogStyle] with some properties updated while keeping the /// others unchanged. - LoadingDialogTheme copyWith({ + LoadingDialogStyle copyWith({ Color? textColor, Color? cupertinoPrimaryColorLight, Color? cupertinoPrimaryColorDark, }) { - return LoadingDialogTheme( + return LoadingDialogStyle( textColor: textColor ?? this.textColor, cupertinoPrimaryColorLight: cupertinoPrimaryColorLight ?? this.cupertinoPrimaryColorLight, diff --git a/lib/models/styles/main_editor_style.dart b/lib/models/styles/main_editor_style.dart new file mode 100644 index 00000000..7893380f --- /dev/null +++ b/lib/models/styles/main_editor_style.dart @@ -0,0 +1,75 @@ +// Flutter imports: +import 'package:flutter/services.dart'; +import 'package:pro_image_editor/common/editor_style_constants.dart'; + +import 'sub_editor_page_style.dart'; + +/// Represents the styling configuration for the main editor interface. +class MainEditorStyle { + /// Creates a new instance of [MainEditorStyle]. + const MainEditorStyle({ + this.background = kImageEditorBackground, + this.bottomBarColor = kImageEditorBottomBarColor, + this.bottomBarBackground = kImageEditorBottomBarBackground, + this.appBarColor = kImageEditorAppBarColor, + this.appBarBackground = kImageEditorAppBarBackground, + this.uiOverlayStyle = kImageEditorUiOverlayStyle, + this.outsideCaptureAreaLayerOpacity = 0.5, + this.subEditorPage = const SubEditorPageStyle(), + }); + + /// Background color for the image editor in the overview. + final Color background; + + /// Color of the bottom bar. + final Color bottomBarColor; + + /// Background color of the bottom bar. + final Color bottomBarBackground; + + /// Color of the app bar. + final Color appBarColor; + + /// Background color of the app bar. + final Color appBarBackground; + + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// The theme configuration for the sub-editor page. + final SubEditorPageStyle subEditorPage; + + /// If this opacity is greater than 0, it will paint a transparent overlay + /// over all layers that are drawn outside the background image area. The + /// overlay will have the specified opacity level. + /// + /// Note: This opacity only takes effect if the + /// `captureOnlyBackgroundImageArea` flag in the generation configuration is + /// set to `true`. + final double outsideCaptureAreaLayerOpacity; + + /// Creates a copy of this style with the specified overrides. + /// + /// Returns a new [MainEditorStyle] instance with the overridden properties. + MainEditorStyle copyWith({ + Color? background, + Color? bottomBarColor, + Color? bottomBarBackground, + Color? appBarColor, + Color? appBarBackground, + SystemUiOverlayStyle? uiOverlayStyle, + double? outsideCaptureAreaLayerOpacity, + SubEditorPageStyle? subEditorPage, + }) { + return MainEditorStyle( + background: background ?? this.background, + bottomBarColor: bottomBarColor ?? this.bottomBarColor, + bottomBarBackground: bottomBarBackground ?? this.bottomBarBackground, + appBarColor: appBarColor ?? this.appBarColor, + appBarBackground: appBarBackground ?? this.appBarBackground, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, + subEditorPage: subEditorPage ?? this.subEditorPage, + outsideCaptureAreaLayerOpacity: outsideCaptureAreaLayerOpacity ?? + this.outsideCaptureAreaLayerOpacity); + } +} diff --git a/lib/models/theme/theme_painting_editor.dart b/lib/models/styles/paint_editor_style.dart similarity index 58% rename from lib/models/theme/theme_painting_editor.dart rename to lib/models/styles/paint_editor_style.dart index 2b4efd2c..993f971f 100644 --- a/lib/models/theme/theme_painting_editor.dart +++ b/lib/models/styles/paint_editor_style.dart @@ -1,12 +1,12 @@ // Flutter imports: +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// Flutter PaintingEditorTheme Class Documentation +/// Flutter PaintEditorStyle Class Documentation /// -/// The `PaintingEditorTheme` class defines the theme for the painting editor +/// The `PaintEditorStyle` class defines the styles for the paint editor /// in the image editor. /// It includes properties such as colors for the app bar, background, bottom /// bar, and more. @@ -14,7 +14,7 @@ import 'theme_shared_values.dart'; /// Usage: /// /// ```dart -/// PaintingEditorTheme paintingEditorTheme = PaintingEditorTheme( +/// PaintEditorStyle PaintEditorStyle = PaintEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, @@ -25,12 +25,12 @@ import 'theme_shared_values.dart'; /// /// Properties: /// -/// - `appBarBackgroundColor`: Background color of the app bar in the painting +/// - `appBarBackgroundColor`: Background color of the app bar in the paint /// editor. /// /// - `appBarForegroundColor`: Foreground color (text and icons) of the app bar. /// -/// - `background`: Background color of the painting editor. +/// - `background`: Background color of the paint editor. /// /// - `bottomBarColor`: Background color of the bottom navigation bar. /// @@ -46,7 +46,7 @@ import 'theme_shared_values.dart'; /// Example Usage: /// /// ```dart -/// PaintingEditorTheme paintingEditorTheme = PaintingEditorTheme( +/// PaintEditorStyle paintEditorStyle = PaintEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey, @@ -54,42 +54,43 @@ import 'theme_shared_values.dart'; /// bottomBarActiveItemColor: Colors.blue, /// ); /// -/// Color appBarBackgroundColor = paintingEditorTheme.appBarBackgroundColor; -/// Color background = paintingEditorTheme.background; -/// // Access other theme properties... +/// Color appBarBackgroundColor = PaintEditorStyle.appBarBackgroundColor; +/// Color background = PaintEditorStyle.background; +/// // Access other style properties... /// ``` -class PaintingEditorTheme { - /// Creates an instance of the `PaintingEditorTheme` class with the specified - /// theme properties. - const PaintingEditorTheme({ +class PaintEditorStyle { + /// Creates an instance of the `PaintEditorStyle` class with the specified + /// style properties. + const PaintEditorStyle({ this.lineWidthBottomSheetTitle, this.opacityBottomSheetTitle, - this.appBarBackgroundColor = imageEditorAppBarColor, - this.lineWidthBottomSheetColor = const Color(0xFF252728), - this.opacityBottomSheetColor = const Color(0xFF252728), - this.appBarForegroundColor = const Color(0xFFE1E1E1), - this.background = imageEditorBackgroundColor, - this.bottomBarColor = imageEditorAppBarColor, - this.bottomBarActiveItemColor = imageEditorPrimaryColor, + this.appBarBackground = kImageEditorAppBarBackground, + this.appBarColor = kImageEditorAppBarColor, + this.lineWidthBottomSheetBackground = const Color(0xFF252728), + this.opacityBottomSheetBackground = const Color(0xFF252728), + this.background = kImageEditorBackground, + this.bottomBarBackground = kImageEditorBottomBarBackground, + this.bottomBarActiveItemColor = kImageEditorPrimaryColor, this.bottomBarInactiveItemColor = const Color(0xFFEEEEEE), this.initialStrokeWidth = 10.0, this.initialOpacity = 1.0, + this.uiOverlayStyle = kImageEditorUiOverlayStyle, this.initialColor = const Color(0xffff0000), }) : assert(initialStrokeWidth > 0, 'initialStrokeWidth must be positive'), assert(initialOpacity >= 0 && initialOpacity <= 1, 'initialOpacity must be between 0 and 1'); - /// Background color of the app bar in the painting editor. - final Color appBarBackgroundColor; + /// Background color of the paint editor. + final Color background; - /// Foreground color (text and icons) of the app bar. - final Color appBarForegroundColor; + /// Background color of the bottom bar. + final Color bottomBarBackground; - /// Background color of the painting editor. - final Color background; + /// Color of the app bar. + final Color appBarColor; - /// Background color of the bottom navigation bar. - final Color bottomBarColor; + /// Background color of the app bar. + final Color appBarBackground; /// Color of active items in the bottom navigation bar. final Color bottomBarActiveItemColor; @@ -98,10 +99,10 @@ class PaintingEditorTheme { final Color bottomBarInactiveItemColor; /// Color of the bottom sheet used to select line width. - final Color lineWidthBottomSheetColor; + final Color lineWidthBottomSheetBackground; /// Color of the bottom sheet used to change the opacity. - final Color opacityBottomSheetColor; + final Color opacityBottomSheetBackground; /// Title of the bottom sheet used to select line width. final TextStyle? lineWidthBottomSheetTitle; @@ -118,42 +119,44 @@ class PaintingEditorTheme { /// Indicates the initial drawing color. final Color initialColor; - /// Creates a copy of this `PaintingEditorTheme` object with the given fields + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// Creates a copy of this `PaintEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [PaintingEditorTheme] with some properties updated while keeping the + /// [PaintEditorStyle] with some properties updated while keeping the /// others unchanged. - PaintingEditorTheme copyWith({ - Color? appBarBackgroundColor, - Color? appBarForegroundColor, + PaintEditorStyle copyWith({ + Color? bottomBarBackground, + Color? appBarColor, + Color? appBarBackground, Color? background, - Color? bottomBarColor, Color? bottomBarActiveItemColor, Color? bottomBarInactiveItemColor, - Color? lineWidthBottomSheetColor, - Color? opacityBottomSheetColor, + Color? lineWidthBottomSheetBackground, + Color? opacityBottomSheetBackground, TextStyle? lineWidthBottomSheetTitle, TextStyle? opacityBottomSheetTitle, double? initialStrokeWidth, double? initialOpacity, Color? initialColor, + SystemUiOverlayStyle? uiOverlayStyle, }) { - return PaintingEditorTheme( - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, + return PaintEditorStyle( background: background ?? this.background, - bottomBarColor: bottomBarColor ?? this.bottomBarColor, + bottomBarBackground: bottomBarBackground ?? this.bottomBarBackground, + appBarColor: appBarColor ?? this.appBarColor, + appBarBackground: appBarBackground ?? this.appBarBackground, bottomBarActiveItemColor: bottomBarActiveItemColor ?? this.bottomBarActiveItemColor, bottomBarInactiveItemColor: bottomBarInactiveItemColor ?? this.bottomBarInactiveItemColor, - lineWidthBottomSheetColor: - lineWidthBottomSheetColor ?? this.lineWidthBottomSheetColor, - opacityBottomSheetColor: - opacityBottomSheetColor ?? this.opacityBottomSheetColor, + lineWidthBottomSheetBackground: + lineWidthBottomSheetBackground ?? this.lineWidthBottomSheetBackground, + opacityBottomSheetBackground: + opacityBottomSheetBackground ?? this.opacityBottomSheetBackground, lineWidthBottomSheetTitle: lineWidthBottomSheetTitle ?? this.lineWidthBottomSheetTitle, opacityBottomSheetTitle: @@ -161,6 +164,7 @@ class PaintingEditorTheme { initialStrokeWidth: initialStrokeWidth ?? this.initialStrokeWidth, initialOpacity: initialOpacity ?? this.initialOpacity, initialColor: initialColor ?? this.initialColor, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, ); } } diff --git a/lib/models/theme/theme_sticker_editor.dart b/lib/models/styles/sticker_editor_style.dart similarity index 66% rename from lib/models/theme/theme_sticker_editor.dart rename to lib/models/styles/sticker_editor_style.dart index f0d85d95..c12368c0 100644 --- a/lib/models/theme/theme_sticker_editor.dart +++ b/lib/models/styles/sticker_editor_style.dart @@ -2,10 +2,10 @@ import 'dart:ui'; // Project imports: -import 'theme_draggable_sheet.dart'; -import 'types/theme_types.dart'; +import 'draggable_sheet_style.dart'; +import 'types/style_types.dart'; -/// The `StickerEditorTheme` class defines the theme for the sticker editor in +/// The `StickerEditorStyle` class defines the style for the sticker editor in /// the image editor. /// It includes properties such as colors for the background, category /// indicator, category icons, and more. @@ -13,7 +13,7 @@ import 'types/theme_types.dart'; /// Usage: /// /// ```dart -/// StickerEditorTheme stickerEditorTheme = StickerEditorTheme( +/// StickerEditorStyle StickerEditorStyle = StickerEditorStyle( /// ); /// ``` /// @@ -22,16 +22,16 @@ import 'types/theme_types.dart'; /// Example Usage: /// /// ```dart -/// StickerEditorTheme stickerEditorTheme = StickerEditorTheme( +/// StickerEditorStyle StickerEditorStyle = StickerEditorStyle( /// ); /// /// ``` -class StickerEditorTheme { - /// Creates an instance of the `StickerEditorTheme` class with the specified - /// theme properties. - const StickerEditorTheme({ +class StickerEditorStyle { + /// Creates an instance of the `StickerEditorStyle` class with the specified + /// style properties. + const StickerEditorStyle({ this.showDragHandle = true, - this.themeDraggableSheet = const ThemeDraggableSheet(), + this.draggableSheetStyle = const DraggableSheetStyle(), this.bottomSheetBackgroundColor = const Color(0xFFFFFFFF), this.editorBoxConstraintsBuilder, }); @@ -43,7 +43,7 @@ class StickerEditorTheme { final Color bottomSheetBackgroundColor; /// Configuration settings for a draggable bottom sheet component. - final ThemeDraggableSheet themeDraggableSheet; + final DraggableSheetStyle draggableSheetStyle; /// Use this to build custom [BoxConstraints] that will be applied to /// the modal bottom sheet displaying the [StickerEditor]. @@ -52,23 +52,23 @@ class StickerEditorTheme { /// [ProImageEditorConfigs.editorBoxConstraintsBuilder]. final EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder; - /// Creates a copy of this `StickerEditorTheme` object with the given fields + /// Creates a copy of this `StickerEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [StickerEditorTheme] with some properties updated while keeping the + /// [StickerEditorStyle] with some properties updated while keeping the /// others unchanged. - StickerEditorTheme copyWith({ + StickerEditorStyle copyWith({ bool? showDragHandle, Color? bottomSheetBackgroundColor, - ThemeDraggableSheet? themeDraggableSheet, + DraggableSheetStyle? draggableSheetStyle, EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder, }) { - return StickerEditorTheme( + return StickerEditorStyle( showDragHandle: showDragHandle ?? this.showDragHandle, bottomSheetBackgroundColor: bottomSheetBackgroundColor ?? this.bottomSheetBackgroundColor, - themeDraggableSheet: themeDraggableSheet ?? this.themeDraggableSheet, + draggableSheetStyle: draggableSheetStyle ?? this.draggableSheetStyle, editorBoxConstraintsBuilder: editorBoxConstraintsBuilder ?? this.editorBoxConstraintsBuilder, ); diff --git a/lib/models/theme/theme_sub_editor_page.dart b/lib/models/styles/sub_editor_page_style.dart similarity index 89% rename from lib/models/theme/theme_sub_editor_page.dart rename to lib/models/styles/sub_editor_page_style.dart index 6a7ade54..e4a920cf 100644 --- a/lib/models/theme/theme_sub_editor_page.dart +++ b/lib/models/styles/sub_editor_page_style.dart @@ -1,13 +1,13 @@ // Flutter imports: import 'package:flutter/widgets.dart'; -/// A class representing the theme configuration for a sub-editor page. -class SubEditorPageTheme { - /// Creates a [SubEditorPageTheme]. +/// A class representing the style configuration for a sub-editor page. +class SubEditorPageStyle { + /// Creates a [SubEditorPageStyle]. /// /// The [enforceSizeFromMainEditor] defaults to `false`. /// The [barrierDismissible] defaults to `false`. - const SubEditorPageTheme({ + const SubEditorPageStyle({ this.enforceSizeFromMainEditor = false, this.barrierDismissible = false, this.borderRadius, @@ -63,13 +63,13 @@ class SubEditorPageTheme { enforceSizeFromMainEditor; } - /// Creates a copy of this `SubEditorPageTheme` object with the given fields + /// Creates a copy of this `SubEditorPageStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [SubEditorPageTheme] with some properties updated while keeping the + /// [SubEditorPageStyle] with some properties updated while keeping the /// others unchanged. - SubEditorPageTheme copyWith({ + SubEditorPageStyle copyWith({ bool? enforceSizeFromMainEditor, bool? barrierDismissible, BorderRadiusGeometry? borderRadius, @@ -81,7 +81,7 @@ class SubEditorPageTheme { Widget Function(BuildContext, Animation, Animation, Widget)? transitionsBuilder, }) { - return SubEditorPageTheme( + return SubEditorPageStyle( enforceSizeFromMainEditor: enforceSizeFromMainEditor ?? this.enforceSizeFromMainEditor, barrierDismissible: barrierDismissible ?? this.barrierDismissible, diff --git a/lib/models/theme/theme_text_editor.dart b/lib/models/styles/text_editor_style.dart similarity index 64% rename from lib/models/theme/theme_text_editor.dart rename to lib/models/styles/text_editor_style.dart index 927cbce8..1dd2a863 100644 --- a/lib/models/theme/theme_text_editor.dart +++ b/lib/models/styles/text_editor_style.dart @@ -1,10 +1,9 @@ // Flutter imports: import 'package:flutter/material.dart'; -// Project imports: -import 'theme_shared_values.dart'; +import '../../common/editor_style_constants.dart'; -/// The `TextEditorTheme` class defines the theme for the text editor in the +/// The `TextEditorStyle` class defines the style for the text editor in the /// image editor. /// It includes properties such as colors for the app bar, background, text /// input, and more. @@ -12,7 +11,7 @@ import 'theme_shared_values.dart'; /// Usage: /// /// ```dart -/// TextEditorTheme textEditorTheme = TextEditorTheme( +/// TextEditorStyle TextEditorStyle = TextEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey.withOpacity(0.6), @@ -37,7 +36,7 @@ import 'theme_shared_values.dart'; /// Example Usage: /// /// ```dart -/// TextEditorTheme textEditorTheme = TextEditorTheme( +/// TextEditorStyle TextEditorStyle = TextEditorStyle( /// appBarBackgroundColor: Colors.black, /// appBarForegroundColor: Colors.white, /// background: Colors.grey.withOpacity(0.6), @@ -45,34 +44,35 @@ import 'theme_shared_values.dart'; /// inputCursorColor: Colors.blue, /// ); /// -/// Color appBarBackgroundColor = textEditorTheme.appBarBackgroundColor; -/// Color background = textEditorTheme.background; -/// // Access other theme properties... +/// Color appBarBackgroundColor = TextEditorStyle.appBarBackgroundColor; +/// Color background = TextEditorStyle.background; +/// // Access other style properties... /// ``` -class TextEditorTheme { - /// Creates an instance of the `TextEditorTheme` class with the specified - /// theme properties. - const TextEditorTheme({ +class TextEditorStyle { + /// Creates an instance of the `TextEditorStyle` class with the specified + /// style properties. + const TextEditorStyle({ this.fontSizeBottomSheetTitle, this.textFieldMargin = const EdgeInsets.only(bottom: kBottomNavigationBarHeight), - this.appBarBackgroundColor = imageEditorAppBarColor, - this.appBarForegroundColor = const Color(0xFFE1E1E1), + this.appBarBackground = kImageEditorAppBarBackground, + this.appBarColor = kImageEditorAppBarColor, + this.bottomBarBackground = kImageEditorBottomBarBackground, this.background = const Color(0x9B000000), - this.bottomBarBackgroundColor = const Color(0xFF000000), this.bottomBarMainAxisAlignment = MainAxisAlignment.spaceEvenly, this.inputHintColor = const Color(0xFFBDBDBD), - this.inputCursorColor = imageEditorPrimaryColor, + this.inputCursorColor = kImageEditorPrimaryColor, + this.fontScaleBottomSheetBackground = const Color(0xFF252728), }); /// Background color of the app bar in the text editor. - final Color appBarBackgroundColor; + final Color appBarBackground; /// Background color of the bottom bar in the text editor. - final Color bottomBarBackgroundColor; + final Color bottomBarBackground; /// Foreground color (text and icons) of the app bar. - final Color appBarForegroundColor; + final Color appBarColor; /// Background color of the text editor. final Color background; @@ -92,30 +92,33 @@ class TextEditorTheme { /// Title of the bottom sheet used to select the font-size. final TextStyle? fontSizeBottomSheetTitle; - /// Creates a copy of this `TextEditorTheme` object with the given fields + /// Background color for the font scale bottom sheet. + final Color fontScaleBottomSheetBackground; + + /// Creates a copy of this `TextEditorStyle` object with the given fields /// replaced with new values. /// /// The [copyWith] method allows you to create a new instance of - /// [TextEditorTheme] with some properties updated while keeping the + /// [TextEditorStyle] with some properties updated while keeping the /// others unchanged. - TextEditorTheme copyWith({ - Color? appBarBackgroundColor, - Color? bottomBarBackgroundColor, - Color? appBarForegroundColor, + TextEditorStyle copyWith({ + Color? appBarBackground, + Color? appBarColor, + Color? bottomBarBackground, Color? background, Color? inputHintColor, Color? inputCursorColor, + Color? fontScaleBottomSheetBackground, MainAxisAlignment? bottomBarMainAxisAlignment, EdgeInsets? textFieldMargin, TextStyle? fontSizeBottomSheetTitle, }) { - return TextEditorTheme( - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - bottomBarBackgroundColor: - bottomBarBackgroundColor ?? this.bottomBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, + return TextEditorStyle( + fontScaleBottomSheetBackground: + fontScaleBottomSheetBackground ?? this.fontScaleBottomSheetBackground, + appBarBackground: appBarBackground ?? this.appBarBackground, + appBarColor: appBarColor ?? this.appBarColor, + bottomBarBackground: bottomBarBackground ?? this.bottomBarBackground, background: background ?? this.background, inputHintColor: inputHintColor ?? this.inputHintColor, inputCursorColor: inputCursorColor ?? this.inputCursorColor, diff --git a/lib/models/styles/tune_editor_style.dart b/lib/models/styles/tune_editor_style.dart new file mode 100644 index 00000000..2c5c1c04 --- /dev/null +++ b/lib/models/styles/tune_editor_style.dart @@ -0,0 +1,79 @@ +// Flutter imports: +import 'package:flutter/services.dart'; + +import '../../common/editor_style_constants.dart'; + +/// A style class for the Tune Editor that allows customization of colors +/// used in the app bar and background. +class TuneEditorStyle { + /// Creates an instance of [TuneEditorStyle] with customizable color options. + /// + /// - [appBarBackground] defines the background color of the app bar in + /// the tune editor. + /// - [appBarColor] specifies the color used for text and icons in + /// the app bar. + /// - [background] defines the background color of the entire tune editor. + const TuneEditorStyle({ + this.appBarBackground = kImageEditorAppBarBackground, + this.appBarColor = kImageEditorAppBarColor, + this.bottomBarBackground = kImageEditorBottomBarBackground, + this.bottomBarActiveItemColor = kImageEditorPrimaryColor, + this.bottomBarInactiveItemColor = kImageEditorBottomBarColor, + this.background = kImageEditorBackground, + this.uiOverlayStyle = kImageEditorUiOverlayStyle, + }); + + /// Background color of the app bar in the tune editor. + final Color appBarBackground; + + /// Foreground color (text and icons) of the app bar. + final Color appBarColor; + + /// Background color of the tune editor. + final Color background; + + /// Background color of the bottom navigation bar. + final Color bottomBarBackground; + + /// Color of active items in the bottom navigation bar. + final Color bottomBarActiveItemColor; + + /// Color of inactive items in the bottom navigation bar. + final Color bottomBarInactiveItemColor; + + /// UI overlay style, defining the appearance of system status bars. + final SystemUiOverlayStyle uiOverlayStyle; + + /// Creates a copy of this [TuneEditorStyle] object with the given fields + /// replaced with new values. + /// + /// The [copyWith] method allows you to create a new instance of + /// [TuneEditorStyle] with some properties updated while keeping the + /// others unchanged. + /// + /// - [appBarBackground] updates the background color of the app bar. + /// - [appBarColor] updates the color of the text and icons in the + /// app bar. + /// - [background] updates the background color of the tune editor. + TuneEditorStyle copyWith({ + Color? appBarBackground, + Color? appBarColor, + Color? background, + Color? bottomBarBackground, + Color? bottomBarActiveItemColor, + Color? bottomBarInactiveItemColor, + SystemUiOverlayStyle? uiOverlayStyle, + }) { + return TuneEditorStyle( + appBarBackground: appBarBackground ?? this.appBarBackground, + appBarColor: appBarColor ?? this.appBarColor, + background: background ?? this.background, + bottomBarBackground: bottomBarBackground ?? this.bottomBarBackground, + bottomBarActiveItemColor: + bottomBarActiveItemColor ?? this.bottomBarActiveItemColor, + bottomBarInactiveItemColor: + bottomBarInactiveItemColor ?? this.bottomBarInactiveItemColor, + uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, + ); + } +} diff --git a/lib/models/theme/types/theme_types.dart b/lib/models/styles/types/style_types.dart similarity index 100% rename from lib/models/theme/types/theme_types.dart rename to lib/models/styles/types/style_types.dart diff --git a/lib/models/theme/theme.dart b/lib/models/theme/theme.dart deleted file mode 100644 index 28a9d66c..00000000 --- a/lib/models/theme/theme.dart +++ /dev/null @@ -1,253 +0,0 @@ -// Flutter imports: -import 'package:flutter/services.dart'; - -import 'theme_adaptive_dialog.dart'; -import 'theme_blur_editor.dart'; -import 'theme_crop_rotate_editor.dart'; -import 'theme_emoji_editor.dart'; -import 'theme_filter_editor.dart'; -import 'theme_helper_lines.dart'; -import 'theme_layer_interaction.dart'; -import 'theme_loading_dialog.dart'; -import 'theme_painting_editor.dart'; -import 'theme_shared_values.dart'; -import 'theme_sticker_editor.dart'; -import 'theme_sub_editor_page.dart'; -import 'theme_text_editor.dart'; -import 'theme_tune_editor.dart'; -import 'types/theme_types.dart'; - -export 'theme_adaptive_dialog.dart'; -export 'theme_blur_editor.dart'; -export 'theme_crop_rotate_editor.dart'; -export 'theme_emoji_editor.dart'; -export 'theme_filter_editor.dart'; -export 'theme_helper_lines.dart'; -export 'theme_layer_interaction.dart'; -export 'theme_loading_dialog.dart'; -export 'theme_painting_editor.dart'; -export 'theme_shared_values.dart'; -export 'theme_sticker_editor.dart'; -export 'theme_sub_editor_page.dart'; -export 'theme_text_editor.dart'; -export 'theme_tune_editor.dart'; - -/// The `ImageEditorTheme` class defines the overall theme for the image editor -/// in your Flutter application. It includes themes for various editor -/// components such as helper lines, painting editor, text editor, crop & -/// rotate editor, filter editor, emoji editor, and more. -/// -/// Usage: -/// -/// ```dart -/// ImageEditorTheme editorTheme = ImageEditorTheme( -/// helperLine: HelperLineTheme(), -/// paintingEditor: PaintingEditorTheme(), -/// textEditor: TextEditorTheme(), -/// cropRotateEditor: CropRotateEditorTheme(), -/// filterEditor: FilterEditorTheme(), -/// blurEditor: BlurEditorTheme(), -/// emojiEditor: EmojiEditorTheme(), -/// stickerEditor: StickerEditorTheme(), -/// ); -/// ``` -/// -/// Properties: -/// -/// - `helperLine`: Theme for helper lines in the image editor. -/// -/// - `paintingEditor`: Theme for the painting editor. -/// -/// - `textEditor`: Theme for the text editor. -/// -/// - `cropRotateEditor`: Theme for the crop & rotate editor. -/// -/// - `filterEditor`: Theme for the filter editor. -/// -/// - `blurEditor`: Theme for the blur editor. -/// -/// - `emojiEditor`: Theme for the emoji editor. -/// -/// - `stickerEditor`: Theme for the sticker editor. -/// -/// - `background`: Background color for the image editor. -/// -/// - `loadingDialogTextColor`: Text color for loading dialogs. -/// -/// - `uiOverlayStyle`: Defines the system UI overlay style for the image -/// editor. -/// -/// - `loadingDialogTheme`: Theme for the loading dialog. -/// -/// - `adaptiveDialogTheme`: Theme for the adaptive dialog. -/// -/// Example Usage: -/// -/// ```dart -/// ImageEditorTheme editorTheme = ImageEditorTheme( -/// background: Colors.black, -/// loadingDialogTextColor: Colors.white, -/// ); -/// -/// HelperLineTheme helperLineTheme = editorTheme.helperLine; -/// PaintingEditorTheme paintingEditorTheme = editorTheme.paintingEditor; -/// // Access other theme properties... -/// ``` -/// -/// Please refer to the documentation of individual theme classes for more -/// details. -class ImageEditorTheme { - /// Creates an instance of the `ImageEditorTheme` class with the specified - /// theme properties. - const ImageEditorTheme({ - this.editorBoxConstraintsBuilder, - this.outsideCaptureAreaLayerOpacity = 0.5, - this.layerInteraction = const ThemeLayerInteraction(), - this.helperLine = const HelperLineTheme(), - this.paintingEditor = const PaintingEditorTheme(), - this.textEditor = const TextEditorTheme(), - this.cropRotateEditor = const CropRotateEditorTheme(), - this.filterEditor = const FilterEditorTheme(), - this.tuneEditor = const TuneEditorTheme(), - this.blurEditor = const BlurEditorTheme(), - this.emojiEditor = const EmojiEditorTheme(), - this.stickerEditor = const StickerEditorTheme(), - this.loadingDialogTheme = const LoadingDialogTheme(), - this.adaptiveDialogTheme = const AdaptiveDialogTheme(), - this.subEditorPage = const SubEditorPageTheme(), - this.background = imageEditorBackgroundColor, - this.bottomBarBackgroundColor = const Color(0xFF000000), - this.appBarForegroundColor = const Color(0xFFFFFFFF), - this.appBarBackgroundColor = const Color(0xFF000000), - this.uiOverlayStyle = const SystemUiOverlayStyle( - statusBarColor: Color(0x42000000), - statusBarIconBrightness: Brightness.light, - systemNavigationBarIconBrightness: Brightness.light, - statusBarBrightness: Brightness.dark, - systemNavigationBarColor: Color(0xFF000000), - ), - }); - - /// Theme for helper lines in the image editor. - final HelperLineTheme helperLine; - - /// Theme for the painting editor. - final PaintingEditorTheme paintingEditor; - - /// Theme for the text editor. - final TextEditorTheme textEditor; - - /// Theme for the crop & rotate editor. - final CropRotateEditorTheme cropRotateEditor; - - /// Theme for the filter editor. - final FilterEditorTheme filterEditor; - - /// Theme for the tune editor. - final TuneEditorTheme tuneEditor; - - /// Theme for the blur editor. - final BlurEditorTheme blurEditor; - - /// Theme for the emoji editor. - final EmojiEditorTheme emojiEditor; - - /// Theme for the sticker editor. - final StickerEditorTheme stickerEditor; - - /// If this opacity is greater than 0, it will paint a transparent overlay - /// over all layers that are drawn outside the background image area. The - /// overlay will have the specified opacity level. - /// - /// Note: This opacity only takes effect if the - /// `captureOnlyBackgroundImageArea` flag in the generation configuration is - /// set to `true`. - final double outsideCaptureAreaLayerOpacity; - - /// The theme configuration for the sub-editor page. - final SubEditorPageTheme subEditorPage; - - /// Background color for the image editor in the overview. - final Color background; - - /// Background color for the BottomBar in the overview. - final Color bottomBarBackgroundColor; - - /// Background color for the AppBar in the overview. - final Color appBarBackgroundColor; - - /// Background color for the AppBar in the overview. - final Color appBarForegroundColor; - - /// Theme for the loading dialog. - final LoadingDialogTheme loadingDialogTheme; - - /// Theme for the adaptive dialog. - final AdaptiveDialogTheme adaptiveDialogTheme; - - /// Defines the system UI overlay style for the image editor. - final SystemUiOverlayStyle uiOverlayStyle; - - /// Theme for the layer interaction settings. - final ThemeLayerInteraction layerInteraction; - - /// Use this to build custom [BoxConstraints] that will be applied - /// globally to the modal bottom sheet when opening various editors - /// from this library. - final EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder; - - /// Creates a copy of this `ImageEditorTheme` object with the given fields - /// replaced with new values. - /// - /// The [copyWith] method allows you to create a new instance of - /// [ImageEditorTheme] with some properties updated while keeping the - /// others unchanged. - ImageEditorTheme copyWith({ - HelperLineTheme? helperLine, - PaintingEditorTheme? paintingEditor, - TextEditorTheme? textEditor, - CropRotateEditorTheme? cropRotateEditor, - FilterEditorTheme? filterEditor, - BlurEditorTheme? blurEditor, - EmojiEditorTheme? emojiEditor, - StickerEditorTheme? stickerEditor, - double? outsideCaptureAreaLayerOpacity, - SubEditorPageTheme? subEditorPage, - Color? background, - Color? bottomBarBackgroundColor, - Color? appBarBackgroundColor, - Color? appBarForegroundColor, - LoadingDialogTheme? loadingDialogTheme, - AdaptiveDialogTheme? adaptiveDialogTheme, - SystemUiOverlayStyle? uiOverlayStyle, - ThemeLayerInteraction? layerInteraction, - EditorBoxConstraintsBuilder? editorBoxConstraintsBuilder, - }) { - return ImageEditorTheme( - helperLine: helperLine ?? this.helperLine, - paintingEditor: paintingEditor ?? this.paintingEditor, - textEditor: textEditor ?? this.textEditor, - cropRotateEditor: cropRotateEditor ?? this.cropRotateEditor, - filterEditor: filterEditor ?? this.filterEditor, - blurEditor: blurEditor ?? this.blurEditor, - emojiEditor: emojiEditor ?? this.emojiEditor, - stickerEditor: stickerEditor ?? this.stickerEditor, - outsideCaptureAreaLayerOpacity: - outsideCaptureAreaLayerOpacity ?? this.outsideCaptureAreaLayerOpacity, - subEditorPage: subEditorPage ?? this.subEditorPage, - background: background ?? this.background, - bottomBarBackgroundColor: - bottomBarBackgroundColor ?? this.bottomBarBackgroundColor, - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, - loadingDialogTheme: loadingDialogTheme ?? this.loadingDialogTheme, - adaptiveDialogTheme: adaptiveDialogTheme ?? this.adaptiveDialogTheme, - uiOverlayStyle: uiOverlayStyle ?? this.uiOverlayStyle, - layerInteraction: layerInteraction ?? this.layerInteraction, - editorBoxConstraintsBuilder: - editorBoxConstraintsBuilder ?? this.editorBoxConstraintsBuilder, - ); - } -} diff --git a/lib/models/theme/theme_shared_values.dart b/lib/models/theme/theme_shared_values.dart deleted file mode 100644 index c8044c06..00000000 --- a/lib/models/theme/theme_shared_values.dart +++ /dev/null @@ -1,14 +0,0 @@ -// Flutter imports: -import 'package:flutter/widgets.dart'; - -/// Primary color used in the image editor interface. -const imageEditorPrimaryColor = Color(0xFF004C9E); - -/// Color for the app bar in the image editor. -const imageEditorAppBarColor = Color(0xFF000000); - -/// Background color for the image editor. -const imageEditorBackgroundColor = Color(0xFF161616); - -/// Text color used in the image editor interface. -const imageEditorTextColor = Color(0xFFE1E1E1); diff --git a/lib/models/theme/theme_tune_editor.dart b/lib/models/theme/theme_tune_editor.dart deleted file mode 100644 index 252fabed..00000000 --- a/lib/models/theme/theme_tune_editor.dart +++ /dev/null @@ -1,76 +0,0 @@ -// Flutter imports: -import 'package:flutter/widgets.dart'; - -// Project imports: -import 'theme_shared_values.dart'; - -/// A theme class for the Tune Editor that allows customization of colors -/// used in the app bar and background. -class TuneEditorTheme { - /// Creates an instance of [TuneEditorTheme] with customizable color options. - /// - /// - [appBarBackgroundColor] defines the background color of the app bar in - /// the tune editor. - /// - [appBarForegroundColor] specifies the color used for text and icons in - /// the app bar. - /// - [background] defines the background color of the entire tune editor. - const TuneEditorTheme({ - this.appBarBackgroundColor = imageEditorAppBarColor, - this.appBarForegroundColor = const Color(0xFFE1E1E1), - this.bottomBarColor = imageEditorAppBarColor, - this.bottomBarActiveItemColor = imageEditorPrimaryColor, - this.bottomBarInactiveItemColor = const Color(0xFFEEEEEE), - this.background = imageEditorBackgroundColor, - }); - - /// Background color of the app bar in the tune editor. - final Color appBarBackgroundColor; - - /// Foreground color (text and icons) of the app bar. - final Color appBarForegroundColor; - - /// Background color of the tune editor. - final Color background; - - /// Background color of the bottom navigation bar. - final Color bottomBarColor; - - /// Color of active items in the bottom navigation bar. - final Color bottomBarActiveItemColor; - - /// Color of inactive items in the bottom navigation bar. - final Color bottomBarInactiveItemColor; - - /// Creates a copy of this [TuneEditorTheme] object with the given fields - /// replaced with new values. - /// - /// The [copyWith] method allows you to create a new instance of - /// [TuneEditorTheme] with some properties updated while keeping the - /// others unchanged. - /// - /// - [appBarBackgroundColor] updates the background color of the app bar. - /// - [appBarForegroundColor] updates the color of the text and icons in the - /// app bar. - /// - [background] updates the background color of the tune editor. - TuneEditorTheme copyWith({ - Color? appBarBackgroundColor, - Color? appBarForegroundColor, - Color? background, - Color? bottomBarColor, - Color? bottomBarActiveItemColor, - Color? bottomBarInactiveItemColor, - }) { - return TuneEditorTheme( - appBarBackgroundColor: - appBarBackgroundColor ?? this.appBarBackgroundColor, - appBarForegroundColor: - appBarForegroundColor ?? this.appBarForegroundColor, - background: background ?? this.background, - bottomBarColor: bottomBarColor ?? this.bottomBarColor, - bottomBarActiveItemColor: - bottomBarActiveItemColor ?? this.bottomBarActiveItemColor, - bottomBarInactiveItemColor: - bottomBarInactiveItemColor ?? this.bottomBarInactiveItemColor, - ); - } -} diff --git a/lib/modules/blur_editor/blur_editor.dart b/lib/modules/blur_editor/blur_editor.dart index d1257494..990c1522 100644 --- a/lib/modules/blur_editor/blur_editor.dart +++ b/lib/modules/blur_editor/blur_editor.dart @@ -221,7 +221,7 @@ class BlurEditorState extends State data: theme.copyWith( tooltipTheme: theme.tooltipTheme.copyWith(preferBelow: true)), child: AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: blurEditorConfigs.style.uiOverlayStyle, child: SafeArea( top: blurEditorConfigs.safeArea.top, bottom: blurEditorConfigs.safeArea.bottom, @@ -230,7 +230,7 @@ class BlurEditorState extends State child: RecordInvisibleWidget( controller: screenshotCtrl, child: Scaffold( - backgroundColor: imageEditorTheme.blurEditor.background, + backgroundColor: blurEditorConfigs.style.background, appBar: _buildAppBar(), body: _buildBody(), bottomNavigationBar: _buildBottomNavBar(), @@ -243,27 +243,27 @@ class BlurEditorState extends State /// Builds the app bar for the blur editor. PreferredSizeWidget? _buildAppBar() { - if (customWidgets.blurEditor.appBar != null) { - return customWidgets.blurEditor.appBar! + if (blurEditorConfigs.widgets.appBar != null) { + return blurEditorConfigs.widgets.appBar! .call(this, rebuildController.stream); } return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.blurEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.blurEditor.appBarForegroundColor, + backgroundColor: blurEditorConfigs.style.appBarBackgroundColor, + foregroundColor: blurEditorConfigs.style.appBarForegroundColor, actions: [ IconButton( tooltip: i18n.blurEditor.back, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), + icon: Icon(blurEditorConfigs.icons.backButton), onPressed: close, ), const Spacer(), IconButton( tooltip: i18n.blurEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(blurEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ), @@ -325,14 +325,14 @@ class BlurEditorState extends State layers: layers!, clipBehavior: Clip.none, ), - if (customWidgets.blurEditor.bodyItemsRecorded != null) - ...customWidgets.blurEditor.bodyItemsRecorded!( + if (blurEditorConfigs.widgets.bodyItemsRecorded != null) + ...blurEditorConfigs.widgets.bodyItemsRecorded!( this, rebuildController.stream), ], ), ), - if (customWidgets.blurEditor.bodyItems != null) - ...customWidgets.blurEditor.bodyItems!( + if (blurEditorConfigs.widgets.bodyItems != null) + ...blurEditorConfigs.widgets.bodyItems!( this, rebuildController.stream), ], ); @@ -341,14 +341,14 @@ class BlurEditorState extends State /// Builds the bottom navigation bar with blur slider. Widget? _buildBottomNavBar() { - if (customWidgets.blurEditor.bottomBar != null) { - return customWidgets.blurEditor.bottomBar! + if (blurEditorConfigs.widgets.bottomBar != null) { + return blurEditorConfigs.widgets.bottomBar! .call(this, rebuildController.stream); } return SafeArea( child: Container( - color: imageEditorTheme.blurEditor.background, + color: blurEditorConfigs.style.background, height: 100, child: Align( alignment: Alignment.center, @@ -358,7 +358,7 @@ class BlurEditorState extends State child: StreamBuilder( stream: _uiBlurStream.stream, builder: (context, snapshot) { - return customWidgets.blurEditor.slider?.call( + return blurEditorConfigs.widgets.slider?.call( this, rebuildController.stream, blurFactor, diff --git a/lib/modules/crop_rotate_editor/crop_rotate_editor.dart b/lib/modules/crop_rotate_editor/crop_rotate_editor.dart index 55025a0c..31b61374 100644 --- a/lib/modules/crop_rotate_editor/crop_rotate_editor.dart +++ b/lib/modules/crop_rotate_editor/crop_rotate_editor.dart @@ -348,10 +348,7 @@ class CropRotateEditorState extends State editorBodySize.height, ), fadeInOpacity: _painterOpacity, - cornerThickness: - imageEditorTheme.cropRotateEditor.cropCornerThickness, - cornerLength: imageEditorTheme.cropRotateEditor.cropCornerLength, - imageEditorTheme: imageEditorTheme, + style: cropRotateEditorConfigs.style, drawCircle: cropRotateEditorConfigs.roundCropper, ) : null; @@ -707,7 +704,9 @@ class CropRotateEditorState extends State await initConfigs.onDone ?.call(transformC, _transformHelperScale, imageInfos); - if (mounted) Navigator.pop(context, transformC); + if (mounted && initConfigs.enablePopWhenDone) { + Navigator.pop(context, transformC); + } } else { LoadingDialog.instance.show( context, @@ -971,10 +970,10 @@ class CropRotateEditorState extends State showModalBottomSheet( context: context, backgroundColor: - imageEditorTheme.cropRotateEditor.aspectRatioSheetBackgroundColor, + cropRotateEditorConfigs.style.aspectRatioSheetBackgroundColor, isScrollControlled: true, builder: (BuildContext context) { - return customWidgets.cropRotateEditor.aspectRatioOptions?.call( + return cropRotateEditorConfigs.widgets.aspectRatioOptions?.call( this, rebuildController.stream, aspectRatio, @@ -1298,7 +1297,7 @@ class CropRotateEditorState extends State double outsidePadding = _screenPadding * 2; double cornerGap = - imageEditorTheme.cropRotateEditor.cropCornerLength * 2.25; + cropRotateEditorConfigs.style.cropCornerLength * 2.25; double minCornerDistance = outsidePadding + cornerGap; double halfViewRectW = _viewRect.width / 2; @@ -1943,14 +1942,14 @@ class CropRotateEditorState extends State }, child: LayoutBuilder(builder: (context, constraints) { return AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: cropRotateEditorConfigs.style.uiOverlayStyle, child: Theme( data: theme.copyWith( tooltipTheme: theme.tooltipTheme.copyWith(preferBelow: true)), child: Scaffold( resizeToAvoidBottomInset: false, - backgroundColor: imageEditorTheme.cropRotateEditor.background, + backgroundColor: cropRotateEditorConfigs.style.background, appBar: _buildAppBar(constraints), body: _buildBody(), bottomNavigationBar: _buildBottomAppBar(), @@ -1966,8 +1965,8 @@ class CropRotateEditorState extends State /// Builds the app bar for the editor, including buttons for actions such as /// back, rotate, aspect ratio, and done. PreferredSizeWidget? _buildAppBar(BoxConstraints constraints) { - if (customWidgets.cropRotateEditor.appBar != null) { - var customToolbar = customWidgets.cropRotateEditor.appBar! + if (cropRotateEditorConfigs.widgets.appBar != null) { + var customToolbar = cropRotateEditorConfigs.widgets.appBar! .call(this, rebuildController.stream); _hasToolbar = customToolbar != null; return customToolbar; @@ -1975,21 +1974,22 @@ class CropRotateEditorState extends State _hasToolbar = true; return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.cropRotateEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.cropRotateEditor.appBarForegroundColor, + backgroundColor: cropRotateEditorConfigs.style.appBarBackground, + foregroundColor: cropRotateEditorConfigs.style.appBarColor, actions: [ - IconButton( - tooltip: i18n.cropRotateEditor.back, - padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), - onPressed: close, - ), + if (initConfigs.enableCloseButton) + IconButton( + tooltip: i18n.cropRotateEditor.back, + padding: const EdgeInsets.symmetric(horizontal: 8), + icon: Icon(cropRotateEditorConfigs.icons.backButton), + onPressed: close, + ), const Spacer(), IconButton( tooltip: i18n.cropRotateEditor.undo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.undoAction, + cropRotateEditorConfigs.icons.undoAction, color: canUndo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: undoAction, @@ -1998,7 +1998,7 @@ class CropRotateEditorState extends State tooltip: i18n.cropRotateEditor.redo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.redoAction, + cropRotateEditorConfigs.icons.redoAction, color: canRedo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: redoAction, @@ -2009,8 +2009,8 @@ class CropRotateEditorState extends State } Widget? _buildBottomAppBar() { - if (customWidgets.cropRotateEditor.bottomBar != null) { - return customWidgets.cropRotateEditor.bottomBar! + if (cropRotateEditorConfigs.widgets.bottomBar != null) { + return cropRotateEditorConfigs.widgets.bottomBar! .call(this, rebuildController.stream); } @@ -2026,8 +2026,7 @@ class CropRotateEditorState extends State thickness: isDesktop ? null : 0, child: BottomAppBar( height: kToolbarHeight, - color: - imageEditorTheme.cropRotateEditor.bottomBarBackgroundColor, + color: cropRotateEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Center( child: SingleChildScrollView( @@ -2039,8 +2038,8 @@ class CropRotateEditorState extends State maxWidth: 500, ), child: Builder(builder: (context) { - Color foregroundColor = imageEditorTheme - .cropRotateEditor.appBarForegroundColor; + Color foregroundColor = + cropRotateEditorConfigs.style.appBarColor; return Wrap( direction: Axis.horizontal, alignment: WrapAlignment.spaceAround, @@ -2054,7 +2053,7 @@ class CropRotateEditorState extends State style: TextStyle( fontSize: 10.0, color: foregroundColor), ), - icon: Icon(icons.cropRotateEditor.rotate, + icon: Icon(cropRotateEditorConfigs.icons.rotate, color: foregroundColor), onPressed: rotate, ), @@ -2067,7 +2066,7 @@ class CropRotateEditorState extends State style: TextStyle( fontSize: 10.0, color: foregroundColor), ), - icon: Icon(icons.cropRotateEditor.flip, + icon: Icon(cropRotateEditorConfigs.icons.flip, color: foregroundColor), onPressed: flip, ), @@ -2080,7 +2079,8 @@ class CropRotateEditorState extends State style: TextStyle( fontSize: 10.0, color: foregroundColor), ), - icon: Icon(icons.cropRotateEditor.aspectRatio, + icon: Icon( + cropRotateEditorConfigs.icons.aspectRatio, color: foregroundColor), onPressed: openAspectRatioOptions, ), @@ -2093,7 +2093,7 @@ class CropRotateEditorState extends State style: TextStyle( fontSize: 10.0, color: foregroundColor), ), - icon: Icon(icons.cropRotateEditor.reset, + icon: Icon(cropRotateEditorConfigs.icons.reset, color: foregroundColor), onPressed: reset, ), @@ -2180,8 +2180,8 @@ class CropRotateEditorState extends State ), ), ), - if (customWidgets.cropRotateEditor.bodyItems != null) - ...customWidgets.cropRotateEditor.bodyItems!( + if (cropRotateEditorConfigs.widgets.bodyItems != null) + ...cropRotateEditorConfigs.widgets.bodyItems!( this, rebuildController.stream), ], ), @@ -2408,7 +2408,7 @@ class CropRotateEditorState extends State return IconButton( tooltip: i18n.cropRotateEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(cropRotateEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ); diff --git a/lib/modules/crop_rotate_editor/utils/crop_area_history.dart b/lib/modules/crop_rotate_editor/utils/crop_area_history.dart index f2f06219..fb982015 100644 --- a/lib/modules/crop_rotate_editor/utils/crop_area_history.dart +++ b/lib/modules/crop_rotate_editor/utils/crop_area_history.dart @@ -295,7 +295,7 @@ mixin CropAreaHistory screenshotHistoryPosition = history.length - 1; } - /// Undoes the last action performed in the painting editor. + /// Undoes the last action performed in the crop-rotate editor. void undoAction() { if (canUndo) { setState(() { @@ -310,7 +310,7 @@ mixin CropAreaHistory } } - /// Redoes the previously undone action in the painting editor. + /// Redoes the previously undone action in the crop-rotate editor. void redoAction() { if (canRedo) { setState(() { diff --git a/lib/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options.dart b/lib/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options.dart index 3fc7ff29..4216f4dc 100644 --- a/lib/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options.dart +++ b/lib/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options.dart @@ -69,7 +69,7 @@ class _CropAspectRatioOptionsState extends State { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 24, - color: widget.configs.imageEditorTheme.cropRotateEditor + color: widget.configs.cropRotateEditor.style .aspectRatioSheetForegroundColor, ), ), @@ -81,11 +81,10 @@ class _CropAspectRatioOptionsState extends State { primary: false, shrinkWrap: true, controller: _scrollCtrl, - itemCount: - widget.configs.cropRotateEditorConfigs.aspectRatios.length, + itemCount: widget.configs.cropRotateEditor.aspectRatios.length, itemBuilder: (context, index) { - var item = widget - .configs.cropRotateEditorConfigs.aspectRatios[index]; + var item = + widget.configs.cropRotateEditor.aspectRatios[index]; return ListTile( leading: SizedBox( height: 38, @@ -103,7 +102,7 @@ class _CropAspectRatioOptionsState extends State { style: TextStyle( fontWeight: FontWeight.w500, fontSize: 16, - color: widget.configs.imageEditorTheme.cropRotateEditor + color: widget.configs.cropRotateEditor.style .aspectRatioSheetForegroundColor, ), ), diff --git a/lib/modules/crop_rotate_editor/widgets/crop_corner_painter.dart b/lib/modules/crop_rotate_editor/widgets/crop_corner_painter.dart index ff18b7b2..01f70821 100644 --- a/lib/modules/crop_rotate_editor/widgets/crop_corner_painter.dart +++ b/lib/modules/crop_rotate_editor/widgets/crop_corner_painter.dart @@ -5,7 +5,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; // Project imports: -import '../../../models/theme/theme.dart'; +import '../../../models/styles/crop_rotate_editor_style.dart'; /// A custom painter for drawing crop corners and interaction elements. /// @@ -46,9 +46,7 @@ class CropCornerPainter extends CustomPainter { required this.viewRect, required this.screenSize, required this.scaleFactor, - required this.imageEditorTheme, - required this.cornerLength, - required this.cornerThickness, + required this.style, required this.rotationScaleFactor, }); @@ -72,9 +70,9 @@ class CropCornerPainter extends CustomPainter { /// The theme settings for the image editor. /// - /// This [ImageEditorTheme] object provides style configurations for the + /// This [CropRotateEditorStyle] object provides style configurations for the /// elements drawn by this painter, such as colors and line thicknesses. - final ImageEditorTheme imageEditorTheme; + final CropRotateEditorStyle style; /// Whether to draw circles at the crop corners. /// @@ -100,18 +98,6 @@ class CropCornerPainter extends CustomPainter { /// such as highlighting or accentuating elements during user actions. final double interactionOpacity; - /// The length of the crop corner lines. - /// - /// This double value determines how long the lines at the corners of the - /// crop rectangle are drawn, affecting their visual appearance. - final double cornerLength; - - /// The thickness of the crop corner lines. - /// - /// This double value determines the thickness of the lines at the corners - /// of the crop rectangle, influencing their visual prominence. - final double cornerThickness; - /// The width of the helper lines. /// /// This double value specifies the thickness of auxiliary lines drawn to @@ -199,8 +185,8 @@ class CropCornerPainter extends CustomPainter { } Color interpolatedColor = Color.lerp( - imageEditorTheme.cropRotateEditor.background, - imageEditorTheme.cropRotateEditor.cropOverlayColor, + style.background, + style.cropOverlayColor, fadeInOpacity, )!; @@ -224,9 +210,9 @@ class CropCornerPainter extends CustomPainter { }) { Path path = Path(); - double width = cornerThickness / rotationScaleFactor; + double width = style.cropCornerThickness / rotationScaleFactor; if (!drawCircle) { - double length = cornerLength / rotationScaleFactor; + double length = style.cropCornerLength / rotationScaleFactor; /// Top-Left path @@ -254,8 +240,7 @@ class CropCornerPainter extends CustomPainter { canvas.drawPath( path, Paint() - ..color = imageEditorTheme.cropRotateEditor.cropCornerColor - .withValues(alpha: fadeInOpacity) + ..color = style.cropCornerColor.withValues(alpha: fadeInOpacity) ..style = PaintingStyle.fill, ); } else { @@ -315,8 +300,7 @@ class CropCornerPainter extends CustomPainter { canvas.drawPath( path, Paint() - ..color = imageEditorTheme.cropRotateEditor.cropCornerColor - .withValues(alpha: fadeInOpacity) + ..color = style.cropCornerColor.withValues(alpha: fadeInOpacity) ..strokeWidth = width ..strokeCap = StrokeCap.round ..style = PaintingStyle.stroke, @@ -368,7 +352,7 @@ class CropCornerPainter extends CustomPainter { } final cornerPaint = Paint() - ..color = imageEditorTheme.cropRotateEditor.helperLineColor + ..color = style.helperLineColor .withValues(alpha: fadeInOpacity * interactionOpacity) ..style = PaintingStyle.fill; canvas.drawPath(path, cornerPaint); @@ -385,8 +369,7 @@ class CropCornerPainter extends CustomPainter { oldDelegate.viewRect != viewRect || oldDelegate.screenSize != screenSize || oldDelegate.scaleFactor != scaleFactor || - oldDelegate.imageEditorTheme != imageEditorTheme || - oldDelegate.cornerLength != cornerLength || + oldDelegate.style != style || oldDelegate.rotationScaleFactor != rotationScaleFactor; } @@ -401,9 +384,7 @@ class CropCornerPainter extends CustomPainter { viewRect: viewRect, screenSize: screenSize, scaleFactor: scaleFactor, - imageEditorTheme: imageEditorTheme, - cornerLength: cornerLength, - cornerThickness: cornerThickness, + style: style, rotationScaleFactor: rotationScaleFactor, ); } diff --git a/lib/modules/emoji_editor/emoji_editor.dart b/lib/modules/emoji_editor/emoji_editor.dart index 555d1b6c..3512c050 100644 --- a/lib/modules/emoji_editor/emoji_editor.dart +++ b/lib/modules/emoji_editor/emoji_editor.dart @@ -57,7 +57,7 @@ class EmojiEditorState extends State @override void initState() { - _textStyle = imageEditorTheme.emojiEditor.textStyle; + _textStyle = emojiEditorConfigs.style.textStyle; _controller = EmojiTextEditingController(emojiTextStyle: _textStyle); @@ -97,13 +97,13 @@ class EmojiEditorState extends State emojiSet: emojiEditorConfigs.emojiSet, checkPlatformCompatibility: emojiEditorConfigs.checkPlatformCompatibility, emojiTextStyle: _textStyle, - emojiViewConfig: imageEditorTheme.emojiEditor.emojiViewConfig ?? + emojiViewConfig: emojiEditorConfigs.style.emojiViewConfig ?? EmojiViewConfig( gridPadding: EdgeInsets.zero, horizontalSpacing: 0, verticalSpacing: 0, recentsLimit: 28, - backgroundColor: imageEditorBackgroundColor, + backgroundColor: kImageEditorBackground, buttonMode: designMode == ImageEditorDesignModeE.cupertino ? ButtonMode.CUPERTINO : ButtonMode.MATERIAL, @@ -112,13 +112,13 @@ class EmojiEditorState extends State emojiSizeMax: 32, replaceEmojiOnLimitExceed: false, ), - viewOrderConfig: imageEditorTheme.emojiEditor.viewOrderConfig, - skinToneConfig: imageEditorTheme.emojiEditor.skinToneConfig, - categoryViewConfig: imageEditorTheme.emojiEditor.categoryViewConfig ?? + viewOrderConfig: emojiEditorConfigs.style.viewOrderConfig, + skinToneConfig: emojiEditorConfigs.style.skinToneConfig, + categoryViewConfig: emojiEditorConfigs.style.categoryViewConfig ?? CategoryViewConfig( initCategory: Category.RECENT, - backgroundColor: imageEditorTheme.emojiEditor.backgroundColor, - indicatorColor: imageEditorPrimaryColor, + backgroundColor: emojiEditorConfigs.style.backgroundColor, + indicatorColor: kImageEditorPrimaryColor, iconColorSelected: Colors.white, iconColor: const Color(0xFF9E9E9E), tabIndicatorAnimDuration: kTabScrollDuration, @@ -148,11 +148,11 @@ class EmojiEditorState extends State flagIcon: Icons.flag_outlined, ), ), - bottomActionBarConfig: imageEditorTheme.emojiEditor.bottomActionBarConfig, - searchViewConfig: imageEditorTheme.emojiEditor.searchViewConfig ?? + bottomActionBarConfig: emojiEditorConfigs.style.bottomActionBarConfig, + searchViewConfig: emojiEditorConfigs.style.searchViewConfig ?? SearchViewConfig( - backgroundColor: imageEditorTheme.emojiEditor.backgroundColor, - buttonIconColor: imageEditorTextColor, + backgroundColor: emojiEditorConfigs.style.backgroundColor, + buttonIconColor: kImageEditorTextColor, customSearchView: ( config, state, @@ -220,7 +220,7 @@ class EmojiEditorState extends State showSearchBar: showSearchBar, scrollController: widget.scrollController, i18nEmojiEditor: widget.configs.i18n.emojiEditor, - themeEmojiEditor: widget.configs.imageEditorTheme.emojiEditor, + emojiEditorStyle: widget.configs.emojiEditor.style, ); }, ), diff --git a/lib/modules/emoji_editor/widgets/emoji_editor_full_screen_search.dart b/lib/modules/emoji_editor/widgets/emoji_editor_full_screen_search.dart index 540a320f..94519a1b 100644 --- a/lib/modules/emoji_editor/widgets/emoji_editor_full_screen_search.dart +++ b/lib/modules/emoji_editor/widgets/emoji_editor_full_screen_search.dart @@ -109,7 +109,7 @@ class EmojiEditorFullScreenSearchViewState emojiBoxPosition, emoji, emojiSize, - null, // Todo: check if we can provide the category + null, widget.config, _onSkinTonedEmojiSelected, links[emoji.emoji]!, diff --git a/lib/modules/emoji_editor/widgets/emoji_editor_header_search.dart b/lib/modules/emoji_editor/widgets/emoji_editor_header_search.dart index 6069b871..1feb29a0 100644 --- a/lib/modules/emoji_editor/widgets/emoji_editor_header_search.dart +++ b/lib/modules/emoji_editor/widgets/emoji_editor_header_search.dart @@ -1,7 +1,8 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:flutter/material.dart'; import 'package:pro_image_editor/models/i18n/i18n.dart'; -import 'package:pro_image_editor/models/theme/theme_shared_values.dart'; + +import '../../../common/editor_style_constants.dart'; /// Search view header for the emoji editor, allowing search input and emoji /// display. @@ -76,13 +77,13 @@ class HeaderSearchViewState extends SearchViewState { onChanged: onTextInputChanged, focusNode: focusNode, style: const TextStyle( - color: imageEditorTextColor, + color: kImageEditorTextColor, ), decoration: InputDecoration( border: InputBorder.none, hintText: i18n.emojiEditor.search, hintStyle: const TextStyle( - color: imageEditorTextColor, + color: kImageEditorTextColor, fontWeight: FontWeight.normal, ), contentPadding: EdgeInsets.zero, diff --git a/lib/modules/emoji_editor/widgets/emoji_picker_view.dart b/lib/modules/emoji_editor/widgets/emoji_picker_view.dart index 1527ed5d..fa0fbf61 100644 --- a/lib/modules/emoji_editor/widgets/emoji_picker_view.dart +++ b/lib/modules/emoji_editor/widgets/emoji_picker_view.dart @@ -3,9 +3,9 @@ import 'dart:math'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:flutter/material.dart'; import 'package:pro_image_editor/models/i18n/i18n_emoji_editor.dart'; -import 'package:pro_image_editor/models/theme/theme.dart'; import 'package:pro_image_editor/modules/emoji_editor/utils/emoji_state_manager.dart'; +import '../../../models/styles/emoji_editor_style.dart'; import '../../../utils/pro_image_editor_mode.dart'; import 'emoji_cell_extended.dart'; @@ -38,7 +38,7 @@ class ProEmojiPickerView extends EmojiPickerView { required VoidCallback showSearchBar, required this.scrollController, required this.i18nEmojiEditor, - required this.themeEmojiEditor, + required this.emojiEditorStyle, super.key, }) : super(config, state, showSearchBar); @@ -56,10 +56,10 @@ class ProEmojiPickerView extends EmojiPickerView { /// Theme settings for the emoji editor. /// - /// This [EmojiEditorTheme] object contains styling options for the emoji + /// This [EmojiEditorStyle] object contains styling options for the emoji /// picker, enabling customization of colors, fonts, and other visual /// aspects. - final EmojiEditorTheme themeEmojiEditor; + final EmojiEditorStyle emojiEditorStyle; @override State createState() => _DefaultEmojiPickerViewState(); @@ -134,19 +134,19 @@ class _DefaultEmojiPickerViewState extends State _activeTabChange = true; - if (widget.themeEmojiEditor.scrollToDuration.inMilliseconds == 0) { + if (widget.emojiEditorStyle.scrollToDuration.inMilliseconds == 0) { _scrollController.jumpTo(offset); _tabController.animateTo(index); } else { _scrollController.animateTo( offset, - duration: widget.themeEmojiEditor.scrollToDuration, + duration: widget.emojiEditorStyle.scrollToDuration, curve: Curves.easeInOut, ); _tabController.animateTo( index, - duration: widget.themeEmojiEditor.scrollToDuration, + duration: widget.emojiEditorStyle.scrollToDuration, curve: Curves.easeInOut, ); } @@ -154,7 +154,7 @@ class _DefaultEmojiPickerViewState extends State Future.delayed( Duration( milliseconds: - max(widget.themeEmojiEditor.scrollToDuration.inMilliseconds, 200), + max(widget.emojiEditorStyle.scrollToDuration.inMilliseconds, 200), ), () { _activeTabChange = false; }); @@ -278,7 +278,7 @@ class _DefaultEmojiPickerViewState extends State _setEmojiTextStyle(); return EmojiContainer( - color: widget.themeEmojiEditor.backgroundColor, + color: widget.emojiEditorStyle.backgroundColor, buttonMode: widget.config.emojiViewConfig.buttonMode, child: Column( children: [ @@ -314,12 +314,12 @@ class _DefaultEmojiPickerViewState extends State if (page.emoji.isNotEmpty) { pages.addAll([ SliverPadding( - padding: widget.themeEmojiEditor.categoryTitlePadding, + padding: widget.emojiEditorStyle.categoryTitlePadding, sliver: SliverToBoxAdapter( child: Text( _i18nCategoryName(page.category), key: _itemKeys[i], - style: widget.themeEmojiEditor.categoryTitleStyle, + style: widget.emojiEditorStyle.categoryTitleStyle, ), ), ), diff --git a/lib/modules/filter_editor/filter_editor.dart b/lib/modules/filter_editor/filter_editor.dart index ff501ab4..ed67a4c2 100644 --- a/lib/modules/filter_editor/filter_editor.dart +++ b/lib/modules/filter_editor/filter_editor.dart @@ -242,7 +242,7 @@ class FilterEditorState extends State tooltipTheme: theme.tooltipTheme.copyWith(preferBelow: true)), child: ExtendedPopScope( child: AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: filterEditorConfigs.style.uiOverlayStyle, child: SafeArea( top: filterEditorConfigs.safeArea.top, bottom: filterEditorConfigs.safeArea.bottom, @@ -251,7 +251,7 @@ class FilterEditorState extends State child: RecordInvisibleWidget( controller: screenshotCtrl, child: Scaffold( - backgroundColor: imageEditorTheme.filterEditor.background, + backgroundColor: filterEditorConfigs.style.background, appBar: _buildAppBar(), body: _buildBody(), bottomNavigationBar: _buildBottomNavBar(), @@ -265,26 +265,26 @@ class FilterEditorState extends State /// Builds the app bar for the filter editor. PreferredSizeWidget? _buildAppBar() { - if (customWidgets.filterEditor.appBar != null) { - return customWidgets.filterEditor.appBar! + if (filterEditorConfigs.widgets.appBar != null) { + return filterEditorConfigs.widgets.appBar! .call(this, rebuildController.stream); } return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.filterEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.filterEditor.appBarForegroundColor, + backgroundColor: filterEditorConfigs.style.appBarBackground, + foregroundColor: filterEditorConfigs.style.appBarColor, actions: [ IconButton( tooltip: i18n.filterEditor.back, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), + icon: Icon(filterEditorConfigs.icons.backButton), onPressed: close, ), const Spacer(), IconButton( tooltip: i18n.filterEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(filterEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ), @@ -346,14 +346,14 @@ class FilterEditorState extends State layers: layers!, clipBehavior: Clip.none, ), - if (customWidgets.filterEditor.bodyItemsRecorded != null) - ...customWidgets.filterEditor.bodyItemsRecorded!( + if (filterEditorConfigs.widgets.bodyItemsRecorded != null) + ...filterEditorConfigs.widgets.bodyItemsRecorded!( this, rebuildController.stream), ], ), ), - if (customWidgets.filterEditor.bodyItems != null) - ...customWidgets.filterEditor.bodyItems!( + if (filterEditorConfigs.widgets.bodyItems != null) + ...filterEditorConfigs.widgets.bodyItems!( this, rebuildController.stream), ], ); @@ -362,14 +362,14 @@ class FilterEditorState extends State /// Builds the bottom navigation bar with filter options. Widget? _buildBottomNavBar() { - if (customWidgets.filterEditor.bottomBar != null) { - return customWidgets.filterEditor.bottomBar! + if (filterEditorConfigs.widgets.bottomBar != null) { + return filterEditorConfigs.widgets.bottomBar! .call(this, rebuildController.stream); } return SafeArea( child: Container( - color: imageEditorTheme.filterEditor.background, + color: filterEditorConfigs.style.background, child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -383,7 +383,7 @@ class FilterEditorState extends State height: 40, child: selectedFilter == PresetFilters.none ? null - : customWidgets.filterEditor.slider?.call( + : filterEditorConfigs.widgets.slider?.call( this, rebuildController.stream, filterOpacity, diff --git a/lib/modules/filter_editor/widgets/filter_editor_item_list.dart b/lib/modules/filter_editor/widgets/filter_editor_item_list.dart index 8a6b18ff..e5866d75 100644 --- a/lib/modules/filter_editor/widgets/filter_editor_item_list.dart +++ b/lib/modules/filter_editor/widgets/filter_editor_item_list.dart @@ -98,7 +98,7 @@ class _FilterEditorItemListState extends State { /// A list of `ColorFilterGenerator` objects that define the image filters /// available in the editor. List get _filters => - widget.configs.filterEditorConfigs.filterList ?? presetFiltersList; + widget.configs.filterEditor.filterList ?? presetFiltersList; @override void initState() { @@ -133,13 +133,11 @@ class _FilterEditorItemListState extends State { constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width), child: Padding( - padding: - widget.configs.imageEditorTheme.filterEditor.filterListMargin, + padding: widget.configs.filterEditor.style.filterListMargin, child: Wrap( crossAxisAlignment: WrapCrossAlignment.end, alignment: WrapAlignment.spaceAround, - spacing: widget - .configs.imageEditorTheme.filterEditor.filterListSpacing, + spacing: widget.configs.filterEditor.style.filterListSpacing, children: [ for (int i = 0; i < _filters.length; i++) buildFilterButton( @@ -166,8 +164,8 @@ class _FilterEditorItemListState extends State { widget.selectedFilter.hashCode == filter.filters.hashCode || (widget.selectedFilter.isEmpty && filter.filters.isEmpty); - if (widget.configs.customWidgets.filterEditor.filterButton != null) { - return widget.configs.customWidgets.filterEditor.filterButton!.call( + if (widget.configs.filterEditor.widgets.filterButton != null) { + return widget.configs.filterEditor.widgets.filterButton!.call( FilterModel( name: widget.configs.i18n.filterEditor.filters .getFilterI18n(filter.name), @@ -185,9 +183,8 @@ class _FilterEditorItemListState extends State { } return FadeInUp( - duration: widget.configs.filterEditorConfigs.fadeInUpDuration, - delay: widget.configs.filterEditorConfigs.fadeInUpStaggerDelayDuration * - index, + duration: widget.configs.filterEditor.fadeInUpDuration, + delay: widget.configs.filterEditor.fadeInUpStaggerDelayDuration * index, child: GestureDetector( key: ValueKey('Filter-${filter.name}-$index'), onTap: () { @@ -220,10 +217,9 @@ class _FilterEditorItemListState extends State { style: TextStyle( fontSize: 11, color: isSelected - ? widget.configs.imageEditorTheme.filterEditor - .previewSelectedTextColor - : widget.configs.imageEditorTheme.filterEditor - .previewTextColor, + ? widget + .configs.filterEditor.style.previewSelectedTextColor + : widget.configs.filterEditor.style.previewTextColor, ), ), ), diff --git a/lib/modules/main_editor/main_editor.dart b/lib/modules/main_editor/main_editor.dart index 26872688..37cb4ebd 100644 --- a/lib/modules/main_editor/main_editor.dart +++ b/lib/modules/main_editor/main_editor.dart @@ -21,7 +21,7 @@ import '../../models/crop_rotate_editor/transform_factors.dart'; import '../../models/history/last_layer_interaction_position.dart'; import '../../models/import_export/export_state_history.dart'; import '../../models/import_export/utils/export_import_version.dart'; -import '../../models/theme/theme_draggable_sheet.dart'; +import '../../models/styles/draggable_sheet_style.dart'; import '../../models/tune_editor/tune_adjustment_matrix.dart'; import '../../plugins/defer_pointer/defer_pointer.dart'; import '../../pro_image_editor.dart'; @@ -475,7 +475,7 @@ class ProImageEditorState extends State onEscape: () { if (!_openDialog && !_openContextMenu) { if (isSubEditorOpen) { - if (!imageEditorTheme.subEditorPage.barrierDismissible) { + if (!mainEditorConfigs.style.subEditorPage.barrierDismissible) { if (cropRotateEditor.currentState != null) { // Important to close the crop-editor like that cuz we need to // set the fake hero first @@ -567,7 +567,7 @@ class ProImageEditorState extends State } stateManager.position++; - stateManager.setHistoryLimit(configs.stateHistoryConfigs.stateHistoryLimit); + stateManager.setHistoryLimit(configs.stateHistory.stateHistoryLimit); } /// Replaces a layer at the specified index with a new layer. @@ -914,7 +914,7 @@ class ProImageEditorState extends State details: details, editorSize: sizesManager.bodySize, appBarHeight: sizesManager.appBarHeight, - layerTheme: imageEditorTheme.layerInteraction, + layerTheme: layerInteraction.style, editorScaleFactor: _interactiveViewer.currentState?.scaleFactor ?? 1.0, editorScaleOffset: @@ -1074,7 +1074,7 @@ class ProImageEditorState extends State SubEditor editorName = SubEditor.unknown; - if (T is PaintingEditor) { + if (T is PaintEditor) { editorName = SubEditor.paint; } else if (T is TextEditor) { editorName = SubEditor.text; @@ -1094,17 +1094,19 @@ class ProImageEditorState extends State context, PageRouteBuilder( opaque: false, - barrierColor: imageEditorTheme.subEditorPage.barrierColor, - barrierDismissible: imageEditorTheme.subEditorPage.barrierDismissible, + barrierColor: mainEditorConfigs.style.subEditorPage.barrierColor, + barrierDismissible: + mainEditorConfigs.style.subEditorPage.barrierDismissible, transitionDuration: duration, reverseTransitionDuration: duration, - transitionsBuilder: imageEditorTheme.subEditorPage.transitionsBuilder ?? - (context, animation, secondaryAnimation, child) { - return FadeTransition( - opacity: animation, - child: child, - ); - }, + transitionsBuilder: + mainEditorConfigs.style.subEditorPage.transitionsBuilder ?? + (context, animation, secondaryAnimation, child) { + return FadeTransition( + opacity: animation, + child: child, + ); + }, pageBuilder: (context, animation, secondaryAnimation) { void animationStatusListener(AnimationStatus status) { switch (status) { @@ -1142,30 +1144,31 @@ class ProImageEditorState extends State } animation.addStatusListener(animationStatusListener); - if (imageEditorTheme.subEditorPage.requireReposition) { + if (mainEditorConfigs.style.subEditorPage.requireReposition) { return SafeArea( child: Stack( fit: StackFit.expand, children: [ Positioned( - top: imageEditorTheme.subEditorPage.positionTop, - left: imageEditorTheme.subEditorPage.positionLeft, - right: imageEditorTheme.subEditorPage.positionRight, - bottom: imageEditorTheme.subEditorPage.positionBottom, + top: mainEditorConfigs.style.subEditorPage.positionTop, + left: mainEditorConfigs.style.subEditorPage.positionLeft, + right: mainEditorConfigs.style.subEditorPage.positionRight, + bottom: + mainEditorConfigs.style.subEditorPage.positionBottom, child: Center( child: Container( - width: imageEditorTheme - .subEditorPage.enforceSizeFromMainEditor + width: mainEditorConfigs + .style.subEditorPage.enforceSizeFromMainEditor ? sizesManager.editorSize.width : null, - height: imageEditorTheme - .subEditorPage.enforceSizeFromMainEditor + height: mainEditorConfigs + .style.subEditorPage.enforceSizeFromMainEditor ? sizesManager.editorSize.height : null, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - borderRadius: - imageEditorTheme.subEditorPage.borderRadius, + borderRadius: mainEditorConfigs + .style.subEditorPage.borderRadius, ), child: page, ), @@ -1182,17 +1185,17 @@ class ProImageEditorState extends State ); } - /// Opens the painting editor. + /// Opens the paint editor. /// - /// This method opens the painting editor and allows the user to draw on the + /// This method opens the paint editor and allows the user to draw on the /// current image. - /// After closing the painting editor, any changes made are applied to the + /// After closing the paint editor, any changes made are applied to the /// image's layers. - void openPaintingEditor() async { - List? paintingLayers = - await openPage>( - PaintingEditor.autoSource( - key: paintingEditor, + void openPaintEditor() async { + List? paintItemLayers = + await openPage>( + PaintEditor.autoSource( + key: paintEditor, file: editorImage.file, byteArray: editorImage.byteArray, assetPath: editorImage.assetPath, @@ -1212,16 +1215,16 @@ class ProImageEditorState extends State ), duration: const Duration(milliseconds: 150), ); - if (paintingLayers != null && paintingLayers.isNotEmpty) { - for (var i = 0; i < paintingLayers.length; i++) { + if (paintItemLayers != null && paintItemLayers.isNotEmpty) { + for (var i = 0; i < paintItemLayers.length; i++) { addLayer( - paintingLayers[i], + paintItemLayers[i], blockSelectLayer: true, - blockCaptureScreenshot: i != paintingLayers.length - 1, + blockCaptureScreenshot: i != paintItemLayers.length - 1, ); } - _selectLayerAfterHeroIsDone(paintingLayers.last.id); + _selectLayerAfterHeroIsDone(paintItemLayers.last.id); setState(() {}); mainEditorCallbacks?.handleUpdateUI(); @@ -1466,19 +1469,18 @@ class ProImageEditorState extends State setState(() => layerInteractionManager.selectedLayerId = ''); _checkInteractiveViewer(); ServicesBinding.instance.keyboard.removeHandler(_onKeyEvent); - final effectiveBoxConstraints = imageEditorTheme - .emojiEditor.editorBoxConstraintsBuilder - ?.call(context, configs) ?? - imageEditorTheme.editorBoxConstraintsBuilder?.call(context, configs); + final effectiveBoxConstraints = emojiEditorConfigs + .style.editorBoxConstraintsBuilder + ?.call(context, configs); - ThemeDraggableSheet sheetTheme = - imageEditorTheme.emojiEditor.themeDraggableSheet; + DraggableSheetStyle sheetTheme = + emojiEditorConfigs.style.themeDraggableSheet; bool useDraggableSheet = sheetTheme.maxChildSize != sheetTheme.minChildSize; EmojiLayerData? layer = await showModalBottomSheet( context: context, - backgroundColor: imageEditorTheme.emojiEditor.backgroundColor, + backgroundColor: emojiEditorConfigs.style.backgroundColor, constraints: effectiveBoxConstraints, - showDragHandle: imageEditorTheme.emojiEditor.showDragHandle, + showDragHandle: emojiEditorConfigs.style.showDragHandle, isScrollControlled: true, useSafeArea: true, builder: (BuildContext context) { @@ -1523,17 +1525,15 @@ class ProImageEditorState extends State setState(() => layerInteractionManager.selectedLayerId = ''); _checkInteractiveViewer(); ServicesBinding.instance.keyboard.removeHandler(_onKeyEvent); - final effectiveBoxConstraints = imageEditorTheme - .stickerEditor.editorBoxConstraintsBuilder - ?.call(context, configs) ?? - imageEditorTheme.editorBoxConstraintsBuilder?.call(context, configs); - var sheetTheme = imageEditorTheme.stickerEditor.themeDraggableSheet; + final effectiveBoxConstraints = stickerEditorConfigs + .style.editorBoxConstraintsBuilder + ?.call(context, configs); + var sheetTheme = stickerEditorConfigs.style.draggableSheetStyle; StickerLayerData? layer = await showModalBottomSheet( context: context, - backgroundColor: - imageEditorTheme.stickerEditor.bottomSheetBackgroundColor, + backgroundColor: stickerEditorConfigs.style.bottomSheetBackgroundColor, constraints: effectiveBoxConstraints, - showDragHandle: imageEditorTheme.stickerEditor.showDragHandle, + showDragHandle: stickerEditorConfigs.style.showDragHandle, isScrollControlled: true, useSafeArea: true, builder: (_) { @@ -1787,8 +1787,8 @@ class ProImageEditorState extends State if (!mounted) return; - if (customWidgets.mainEditor.closeWarningDialog != null) { - close = await customWidgets.mainEditor.closeWarningDialog!(this); + if (mainEditorConfigs.widgets.closeWarningDialog != null) { + close = await mainEditorConfigs.widgets.closeWarningDialog!(this); } else { await showAdaptiveDialog( context: context, @@ -1797,7 +1797,7 @@ class ProImageEditorState extends State child: AdaptiveDialog( designMode: designMode, brightness: _theme.brightness, - imageEditorTheme: imageEditorTheme, + style: configs.dialogConfigs.style.adaptiveDialog, title: Text(i18n.various.closeEditorWarningTitle), content: Text(i18n.various.closeEditorWarningMessage), actions: [ @@ -2017,14 +2017,14 @@ class ProImageEditorState extends State await decodeImage(); }, child: AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: mainEditorConfigs.style.uiOverlayStyle, child: Theme( data: _theme, child: SafeArea( child: LayoutBuilder(builder: (context, constraints) { sizesManager.editorSize = constraints.biggest; return Scaffold( - backgroundColor: imageEditorTheme.background, + backgroundColor: mainEditorConfigs.style.background, resizeToAvoidBottomInset: false, appBar: _buildAppBar(), body: _buildBody(), @@ -2040,31 +2040,35 @@ class ProImageEditorState extends State } PreferredSizeWidget? _buildAppBar() { - if (customWidgets.mainEditor.appBar != null) { - return customWidgets.mainEditor.appBar! + if (mainEditorConfigs.widgets.appBar != null) { + return mainEditorConfigs.widgets.appBar! .call(this, _rebuildController.stream); } + var foregroundColor = mainEditorConfigs.style.appBarColor; + return selectedLayerIndex >= 0 && configs.layerInteraction.hideToolbarOnInteraction ? null : AppBar( - foregroundColor: imageEditorTheme.appBarForegroundColor, - backgroundColor: imageEditorTheme.appBarBackgroundColor, - leading: IconButton( - tooltip: i18n.cancel, - icon: Icon(icons.closeEditor), - onPressed: closeEditor, - ), + foregroundColor: foregroundColor, + backgroundColor: mainEditorConfigs.style.appBarBackground, + leading: mainEditorConfigs.enableCloseButton + ? IconButton( + tooltip: i18n.cancel, + icon: Icon(mainEditorConfigs.icons.closeEditor), + onPressed: closeEditor, + ) + : null, actions: [ IconButton( key: const ValueKey('MainEditorUndoButton'), tooltip: i18n.undo, icon: Icon( - icons.undoAction, + mainEditorConfigs.icons.undoAction, color: stateManager.position > 0 - ? imageEditorTheme.appBarForegroundColor - : imageEditorTheme.appBarForegroundColor.withAlpha(80), + ? foregroundColor + : foregroundColor.withAlpha(80), ), onPressed: undoAction, ), @@ -2072,10 +2076,10 @@ class ProImageEditorState extends State key: const ValueKey('MainEditorRedoButton'), tooltip: i18n.redo, icon: Icon( - icons.redoAction, + mainEditorConfigs.icons.redoAction, color: stateManager.position < stateHistory.length - 1 - ? imageEditorTheme.appBarForegroundColor - : imageEditorTheme.appBarForegroundColor.withAlpha(80), + ? foregroundColor + : foregroundColor.withAlpha(80), ), onPressed: redoAction, ), @@ -2091,7 +2095,7 @@ class ProImageEditorState extends State : IconButton( key: const ValueKey('MainEditorDoneButton'), tooltip: i18n.done, - icon: Icon(icons.doneIcon), + icon: Icon(mainEditorConfigs.icons.doneIcon), iconSize: 28, onPressed: doneEditing, ), @@ -2129,7 +2133,7 @@ class ProImageEditorState extends State onScaleStart: _onScaleStart, onScaleUpdate: _onScaleUpdate, onScaleEnd: _onScaleEnd, - child: customWidgets.mainEditor.wrapBody?.call( + child: mainEditorConfigs.widgets.wrapBody?.call( this, _rebuildController.stream, _buildInteractiveContent(), @@ -2192,8 +2196,8 @@ class ProImageEditorState extends State /// Build layer stack _buildLayers(), - if (customWidgets.mainEditor.bodyItemsRecorded != null) - ...customWidgets.mainEditor.bodyItemsRecorded!( + if (mainEditorConfigs.widgets.bodyItemsRecorded != null) + ...mainEditorConfigs.widgets.bodyItemsRecorded!( this, _rebuildController.stream), ], ), @@ -2207,9 +2211,9 @@ class ProImageEditorState extends State foregroundPainter: imageGenerationConfigs .captureOnlyBackgroundImageArea ? CropLayerPainter( - opacity: - imageEditorTheme.outsideCaptureAreaLayerOpacity, - backgroundColor: imageEditorTheme.background, + opacity: mainEditorConfigs + .style.outsideCaptureAreaLayerOpacity, + backgroundColor: mainEditorConfigs.style.background, imgRatio: stateManager.transformConfigs.isNotEmpty ? stateManager .transformConfigs.cropRect.size.aspectRatio @@ -2228,8 +2232,8 @@ class ProImageEditorState extends State _buildHelperLines(), if (selectedLayerIndex >= 0) _buildRemoveIcon(), ], - if (customWidgets.mainEditor.bodyItems != null) - ...customWidgets.mainEditor.bodyItems!( + if (mainEditorConfigs.widgets.bodyItems != null) + ...mainEditorConfigs.widgets.bodyItems!( this, _rebuildController.stream), ], ), @@ -2237,11 +2241,12 @@ class ProImageEditorState extends State } Widget? _buildBottomNavBar() { - var bottomTextStyle = const TextStyle(fontSize: 10.0, color: Colors.white); + Color foregroundColor = mainEditorConfigs.style.bottomBarColor; + var bottomTextStyle = TextStyle(fontSize: 10.0, color: foregroundColor); double bottomIconSize = 22.0; - if (customWidgets.mainEditor.bottomBar != null) { - return customWidgets.mainEditor.bottomBar! + if (mainEditorConfigs.widgets.bottomBar != null) { + return mainEditorConfigs.widgets.bottomBar! .call(this, _rebuildController.stream, _bottomBarKey); } @@ -2259,7 +2264,7 @@ class ProImageEditorState extends State thickness: isDesktop ? null : 0, child: BottomAppBar( height: kBottomNavigationBarHeight, - color: imageEditorTheme.bottomBarBackgroundColor, + color: mainEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Center( child: SingleChildScrollView( @@ -2283,18 +2288,18 @@ class ProImageEditorState extends State children: [ if (paintEditorConfigs.enabled) FlatIconTextButton( - key: const ValueKey( - 'open-painting-editor-btn'), + key: + const ValueKey('open-paint-editor-btn'), label: Text( i18n.paintEditor .bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.paintingEditor.bottomNavBar, + paintEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), - onPressed: openPaintingEditor, + onPressed: openPaintEditor, ), if (textEditorConfigs.enabled) FlatIconTextButton( @@ -2303,9 +2308,9 @@ class ProImageEditorState extends State i18n.textEditor.bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.textEditor.bottomNavBar, + textEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openTextEditor, ), @@ -2318,9 +2323,10 @@ class ProImageEditorState extends State .bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.cropRotateEditor.bottomNavBar, + cropRotateEditorConfigs + .icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openCropRotateEditor, ), @@ -2331,9 +2337,9 @@ class ProImageEditorState extends State i18n.tuneEditor.bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.tuneEditor.bottomNavBar, + tuneEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openTuneEditor, ), @@ -2346,9 +2352,9 @@ class ProImageEditorState extends State .bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.filterEditor.bottomNavBar, + filterEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openFilterEditor, ), @@ -2359,9 +2365,9 @@ class ProImageEditorState extends State i18n.blurEditor.bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.blurEditor.bottomNavBar, + blurEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openBlurEditor, ), @@ -2374,13 +2380,13 @@ class ProImageEditorState extends State .bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.emojiEditor.bottomNavBar, + emojiEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openEmojiEditor, ), - if (stickerEditorConfigs?.enabled == true) + if (stickerEditorConfigs.enabled == true) FlatIconTextButton( key: const ValueKey( 'open-sticker-editor-btn'), @@ -2389,9 +2395,9 @@ class ProImageEditorState extends State .bottomNavigationBarText, style: bottomTextStyle), icon: Icon( - icons.stickerEditor.bottomNavBar, + stickerEditorConfigs.icons.bottomNavBar, size: bottomIconSize, - color: Colors.white, + color: foregroundColor, ), onPressed: openStickerEditor, ), @@ -2422,14 +2428,14 @@ class ProImageEditorState extends State onHover: isDesktop ? (event) { bool hasHit = activeLayers.indexWhere((element) => - element is PaintingLayerData && + element is PaintLayerData && element.item.hit) >= 0; MouseCursor activeCursor = _mouseCursorsKey.currentState!.currentCursor; MouseCursor moveCursor = - imageEditorTheme.layerInteraction.hoverCursor; + layerInteraction.style.hoverCursor; if (hasHit && activeCursor != moveCursor) { _mouseCursorsKey.currentState!.setCursor(moveCursor); @@ -2577,7 +2583,7 @@ class ProImageEditorState extends State ? lineH : 0, height: screenH, - color: imageEditorTheme.helperLine.verticalColor, + color: helperLines.style.verticalColor, ), ), if (helperLines.showHorizontalLine) @@ -2595,7 +2601,7 @@ class ProImageEditorState extends State height: layerInteractionManager.showHorizontalHelperLine ? lineH : 0, - color: imageEditorTheme.helperLine.horizontalColor, + color: helperLines.style.horizontalColor, ), ), if (helperLines.showRotateLine) @@ -2612,7 +2618,7 @@ class ProImageEditorState extends State ? lineH : 0, height: screenH * 2, - color: imageEditorTheme.helperLine.rotateColor, + color: helperLines.style.rotateColor, ), ), ), @@ -2624,7 +2630,7 @@ class ProImageEditorState extends State } Widget _buildRemoveIcon() { - return customWidgets.mainEditor.removeLayerArea?.call( + return mainEditorConfigs.widgets.removeLayerArea?.call( _removeAreaKey, this, _controllers.removeBtnCtrl.stream, @@ -2643,17 +2649,15 @@ class ProImageEditorState extends State width: kToolbarHeight, decoration: BoxDecoration( color: layerInteractionManager.hoverRemoveBtn - ? imageEditorTheme - .layerInteraction.removeAreaBackgroundActive - : imageEditorTheme - .layerInteraction.removeAreaBackgroundInactive, + ? layerInteraction.style.removeAreaBackgroundActive + : layerInteraction.style.removeAreaBackgroundInactive, borderRadius: const BorderRadius.only( bottomRight: Radius.circular(100)), ), padding: const EdgeInsets.only(right: 12, bottom: 7), child: Center( child: Icon( - icons.removeElementZone, + mainEditorConfigs.icons.removeElementZone, size: 28, ), ), diff --git a/lib/modules/main_editor/utils/desktop_interaction_manager.dart b/lib/modules/main_editor/utils/desktop_interaction_manager.dart index 9eb63e6a..da739680 100644 --- a/lib/modules/main_editor/utils/desktop_interaction_manager.dart +++ b/lib/modules/main_editor/utils/desktop_interaction_manager.dart @@ -156,11 +156,11 @@ class DesktopInteractionManager { required Layer? activeLayer, }) { if (activeLayer == null) return; - double factor = activeLayer is PaintingLayerData + double factor = activeLayer is PaintLayerData ? 0.1 : activeLayer is TextLayerData ? 0.15 - : configs.textEditorConfigs.initFontSize / 50; + : configs.textEditor.initFontSize / 50; if (zoomIn) { activeLayer ..scale -= factor @@ -191,11 +191,11 @@ class DesktopInteractionManager { activeLayer.rotation += 0.087266; } } else { - double factor = activeLayer is PaintingLayerData + double factor = activeLayer is PaintLayerData ? 0.1 : activeLayer is TextLayerData ? 0.15 - : configs.textEditorConfigs.initFontSize / 50; + : configs.textEditor.initFontSize / 50; if (event.scrollDelta.dy > 0) { activeLayer ..scale -= factor diff --git a/lib/modules/main_editor/utils/layer_copy_manager.dart b/lib/modules/main_editor/utils/layer_copy_manager.dart index 708cc353..d2ae9b0f 100644 --- a/lib/modules/main_editor/utils/layer_copy_manager.dart +++ b/lib/modules/main_editor/utils/layer_copy_manager.dart @@ -8,7 +8,7 @@ import 'package:pro_image_editor/models/layer/layer.dart'; /// /// The `LayerManager` provides methods for copying layers to create new /// instances of the same type. It supports various types of layers, including -/// text, emoji, painting, and sticker layers. +/// text, emoji, paint, and sticker layers. class LayerCopyManager { /// Copy a layer to create a new instance of the same type. /// @@ -21,8 +21,8 @@ class LayerCopyManager { return createCopyTextLayer(layer); } else if (layer is EmojiLayerData) { return createCopyEmojiLayer(layer); - } else if (layer is PaintingLayerData) { - return createCopyPaintingLayer(layer); + } else if (layer is PaintLayerData) { + return createCopyPaintLayer(layer); } else if (layer is StickerLayerData) { return createCopyStickerLayer(layer); } else { @@ -95,9 +95,9 @@ class LayerCopyManager { ); } - /// Create a copy of a PaintingLayerData instance. - PaintingLayerData createCopyPaintingLayer(PaintingLayerData layer) { - return PaintingLayerData( + /// Create a copy of a PaintLayerData instance. + PaintLayerData createCopyPaintLayer(PaintLayerData layer) { + return PaintLayerData( id: layer.id, offset: Offset(layer.offset.dx, layer.offset.dy), rotation: layer.rotation, diff --git a/lib/modules/main_editor/utils/layer_interaction_manager.dart b/lib/modules/main_editor/utils/layer_interaction_manager.dart index e4a9a7e6..7da95404 100644 --- a/lib/modules/main_editor/utils/layer_interaction_manager.dart +++ b/lib/modules/main_editor/utils/layer_interaction_manager.dart @@ -146,7 +146,7 @@ class LayerInteractionManager { required Size editorSize, required double appBarHeight, required bool configEnabledHitVibration, - required ThemeLayerInteraction layerTheme, + required LayerInteractionStyle layerTheme, }) { Offset layerOffset = Offset( activeLayer.offset.dx, @@ -521,26 +521,25 @@ class LayerInteractionManager { } void _setMinMaxScaleFactor(ProImageEditorConfigs configs, Layer layer) { - if (layer is PaintingLayerData) { + if (layer is PaintLayerData) { layer.scale = layer.scale.clamp( - configs.paintEditorConfigs.minScale, - configs.paintEditorConfigs.maxScale, + configs.paintEditor.minScale, + configs.paintEditor.maxScale, ); } else if (layer is TextLayerData) { layer.scale = layer.scale.clamp( - configs.textEditorConfigs.minScale, - configs.textEditorConfigs.maxScale, + configs.textEditor.minScale, + configs.textEditor.maxScale, ); } else if (layer is EmojiLayerData) { layer.scale = layer.scale.clamp( - configs.emojiEditorConfigs.minScale, - configs.emojiEditorConfigs.maxScale, + configs.emojiEditor.minScale, + configs.emojiEditor.maxScale, ); - } else if (layer is StickerLayerData && - configs.stickerEditorConfigs != null) { + } else if (layer is StickerLayerData) { layer.scale = layer.scale.clamp( - configs.stickerEditorConfigs!.minScale, - configs.stickerEditorConfigs!.maxScale, + configs.stickerEditor.minScale, + configs.stickerEditor.maxScale, ); } } diff --git a/lib/modules/paint_editor/paint_editor.dart b/lib/modules/paint_editor/paint_editor.dart index fe9afc0e..86f06712 100644 --- a/lib/modules/paint_editor/paint_editor.dart +++ b/lib/modules/paint_editor/paint_editor.dart @@ -29,108 +29,108 @@ import '../../utils/transparent_image_bytes.dart'; import '../filter_editor/widgets/filtered_image.dart'; import 'utils/paint_controller.dart'; import 'utils/paint_desktop_interaction_manager.dart'; -import 'widgets/painting_canvas.dart'; +import 'widgets/paint_canvas.dart'; export '/models/paint_editor/paint_bottom_bar_item.dart'; export './utils/paint_editor_enum.dart'; -export './widgets/draw_painting.dart'; +export 'widgets/draw_paint_item.dart'; -/// The `PaintingEditor` widget allows users to editing images with painting +/// The `PaintEditor` widget allows users to editing images with paint /// tools. /// -/// You can create a `PaintingEditor` using one of the factory methods provided: -/// - `PaintingEditor.file`: Loads an image from a file. -/// - `PaintingEditor.asset`: Loads an image from an asset. -/// - `PaintingEditor.network`: Loads an image from a network URL. -/// - `PaintingEditor.memory`: Loads an image from memory as a `Uint8List`. -/// - `PaintingEditor.autoSource`: Automatically selects the source based on +/// You can create a `PaintEditor` using one of the factory methods provided: +/// - `PaintEditor.file`: Loads an image from a file. +/// - `PaintEditor.asset`: Loads an image from an asset. +/// - `PaintEditor.network`: Loads an image from a network URL. +/// - `PaintEditor.memory`: Loads an image from memory as a `Uint8List`. +/// - `PaintEditor.autoSource`: Automatically selects the source based on /// provided parameters. -class PaintingEditor extends StatefulWidget +class PaintEditor extends StatefulWidget with StandaloneEditor { - /// Constructs a `PaintingEditor` widget. + /// Constructs a `PaintEditor` widget. /// /// The [key] parameter is used to provide a key for the widget. /// The [editorImage] parameter specifies the image to be edited. /// The [initConfigs] parameter specifies the initialization configurations /// for the editor. - const PaintingEditor._({ + const PaintEditor._({ super.key, required this.editorImage, required this.initConfigs, - this.paintingOnly = false, + this.paintOnly = false, }); - /// Constructs a `PaintingEditor` widget with image data loaded from memory. - factory PaintingEditor.memory( + /// Constructs a `PaintEditor` widget with image data loaded from memory. + factory PaintEditor.memory( Uint8List byteArray, { Key? key, required PaintEditorInitConfigs initConfigs, }) { - return PaintingEditor._( + return PaintEditor._( key: key, editorImage: EditorImage(byteArray: byteArray), initConfigs: initConfigs, ); } - /// Constructs a `PaintingEditor` widget with an image loaded from a file. - factory PaintingEditor.file( + /// Constructs a `PaintEditor` widget with an image loaded from a file. + factory PaintEditor.file( File file, { Key? key, required PaintEditorInitConfigs initConfigs, }) { - return PaintingEditor._( + return PaintEditor._( key: key, editorImage: EditorImage(file: file), initConfigs: initConfigs, ); } - /// Constructs a `PaintingEditor` widget with an image loaded from an asset. - factory PaintingEditor.asset( + /// Constructs a `PaintEditor` widget with an image loaded from an asset. + factory PaintEditor.asset( String assetPath, { Key? key, required PaintEditorInitConfigs initConfigs, }) { - return PaintingEditor._( + return PaintEditor._( key: key, editorImage: EditorImage(assetPath: assetPath), initConfigs: initConfigs, ); } - /// Constructs a `PaintingEditor` widget with an image loaded from a network + /// Constructs a `PaintEditor` widget with an image loaded from a network /// URL. - factory PaintingEditor.network( + factory PaintEditor.network( String networkUrl, { Key? key, required PaintEditorInitConfigs initConfigs, }) { - return PaintingEditor._( + return PaintEditor._( key: key, editorImage: EditorImage(networkUrl: networkUrl), initConfigs: initConfigs, ); } - /// Constructs a `PaintingEditor` widget optimized for drawing purposes. - factory PaintingEditor.drawing({ + /// Constructs a `PaintEditor` widget optimized for drawing purposes. + factory PaintEditor.drawing({ Key? key, required PaintEditorInitConfigs initConfigs, }) { - return PaintingEditor._( + return PaintEditor._( key: key, editorImage: EditorImage(byteArray: transparentBytes), initConfigs: initConfigs, - paintingOnly: true, + paintOnly: true, ); } - /// Constructs a `PaintingEditor` widget with an image loaded automatically + /// Constructs a `PaintEditor` widget with an image loaded automatically /// based on the provided source. /// /// Either [byteArray], [file], [networkUrl], or [assetPath] must be provided. - factory PaintingEditor.autoSource({ + factory PaintEditor.autoSource({ Key? key, Uint8List? byteArray, File? file, @@ -139,25 +139,25 @@ class PaintingEditor extends StatefulWidget required PaintEditorInitConfigs initConfigs, }) { if (byteArray != null) { - return PaintingEditor.memory( + return PaintEditor.memory( byteArray, key: key, initConfigs: initConfigs, ); } else if (file != null) { - return PaintingEditor.file( + return PaintEditor.file( file, key: key, initConfigs: initConfigs, ); } else if (networkUrl != null) { - return PaintingEditor.network( + return PaintEditor.network( networkUrl, key: key, initConfigs: initConfigs, ); } else if (assetPath != null) { - return PaintingEditor.asset( + return PaintEditor.asset( assetPath, key: key, initConfigs: initConfigs, @@ -173,25 +173,25 @@ class PaintingEditor extends StatefulWidget @override final EditorImage editorImage; - /// A flag indicating whether only painting operations are allowed. - final bool paintingOnly; + /// A flag indicating whether only paint operations are allowed. + final bool paintOnly; @override - State createState() => PaintingEditorState(); + State createState() => PaintEditorState(); } -/// State class for managing the painting editor, handling user interactions -/// and painting operations. -class PaintingEditorState extends State +/// State class for managing the paint editor, handling user interactions +/// and paint operations. +class PaintEditorState extends State with ImageEditorConvertedConfigs, ImageEditorConvertedCallbacks, - StandaloneEditorState { - final _paintingCanvas = GlobalKey(); + StandaloneEditorState { + final _paintCanvas = GlobalKey(); final _interactiveViewer = GlobalKey(); - /// Controller for managing painting operations within the widget's context. - late final PaintingController paintCtrl; + /// Controller for managing paint operations within the widget's context. + late final PaintController paintCtrl; /// Update the color picker. late final StreamController uiPickerStream; @@ -218,8 +218,8 @@ class PaintingEditorState extends State /// Determines whether redo actions can be performed on the current state. bool get canRedo => paintCtrl.canRedo; - /// Determines whether the user painting. - bool get activePainting => paintCtrl.busy; + /// Determines whether the user draw something. + bool get isActive => paintCtrl.busy; /// Manager class for handling desktop interactions. late final PaintDesktopInteractionManager _desktopInteractionManager; @@ -234,50 +234,50 @@ class PaintingEditorState extends State Color get activeColor => paintCtrl.color; /// A list of [PaintModeBottomBarItem] representing the available drawing - /// modes in the painting editor. + /// modes in the paint editor. /// The list is dynamically generated based on the configuration settings in /// the [PaintEditorConfigs] object. List get paintModes => [ if (paintEditorConfigs.hasOptionFreeStyle) PaintModeBottomBarItem( mode: PaintModeE.freeStyle, - icon: icons.paintingEditor.freeStyle, + icon: paintEditorConfigs.icons.freeStyle, label: i18n.paintEditor.freestyle, ), if (paintEditorConfigs.hasOptionArrow) PaintModeBottomBarItem( mode: PaintModeE.arrow, - icon: icons.paintingEditor.arrow, + icon: paintEditorConfigs.icons.arrow, label: i18n.paintEditor.arrow, ), if (paintEditorConfigs.hasOptionLine) PaintModeBottomBarItem( mode: PaintModeE.line, - icon: icons.paintingEditor.line, + icon: paintEditorConfigs.icons.line, label: i18n.paintEditor.line, ), if (paintEditorConfigs.hasOptionRect) PaintModeBottomBarItem( mode: PaintModeE.rect, - icon: icons.paintingEditor.rectangle, + icon: paintEditorConfigs.icons.rectangle, label: i18n.paintEditor.rectangle, ), if (paintEditorConfigs.hasOptionCircle) PaintModeBottomBarItem( mode: PaintModeE.circle, - icon: icons.paintingEditor.circle, + icon: paintEditorConfigs.icons.circle, label: i18n.paintEditor.circle, ), if (paintEditorConfigs.hasOptionDashLine) PaintModeBottomBarItem( mode: PaintModeE.dashLine, - icon: icons.paintingEditor.dashLine, + icon: paintEditorConfigs.icons.dashLine, label: i18n.paintEditor.dashLine, ), if (paintEditorConfigs.hasOptionEraser) PaintModeBottomBarItem( mode: PaintModeE.eraser, - icon: icons.paintingEditor.eraser, + icon: paintEditorConfigs.icons.eraser, label: i18n.paintEditor.eraser, ), ]; @@ -292,12 +292,12 @@ class PaintingEditorState extends State @override void initState() { super.initState(); - paintCtrl = PaintingController( + paintCtrl = PaintController( fill: paintEditorConfigs.initialFill, mode: paintEditorConfigs.initialPaintMode, - strokeWidth: imageEditorTheme.paintingEditor.initialStrokeWidth, - color: imageEditorTheme.paintingEditor.initialColor, - opacity: imageEditorTheme.paintingEditor.initialOpacity, + strokeWidth: paintEditorConfigs.style.initialStrokeWidth, + color: paintEditorConfigs.style.initialColor, + opacity: paintEditorConfigs.style.initialOpacity, strokeMultiplier: 1, ); @@ -363,8 +363,7 @@ class PaintingEditorState extends State void openLineWeightBottomSheet() { showModalBottomSheet( context: context, - backgroundColor: - imageEditorTheme.paintingEditor.lineWidthBottomSheetColor, + backgroundColor: paintEditorConfigs.style.lineWidthBottomSheetBackground, builder: (BuildContext context) { return StatefulBuilder(builder: (context, setState) { return Material( @@ -381,17 +380,18 @@ class PaintingEditorState extends State BottomSheetHeaderRow( title: i18n.paintEditor.lineWidth, theme: initConfigs.theme, - textStyle: imageEditorTheme - .paintingEditor.lineWidthBottomSheetTitle, + textStyle: + paintEditorConfigs.style.lineWidthBottomSheetTitle, closeButton: - customWidgets.paintEditor.lineWidthCloseButton != null - ? (fn) => customWidgets - .paintEditor.lineWidthCloseButton!(this, fn) + paintEditorConfigs.widgets.lineWidthCloseButton != + null + ? (fn) => paintEditorConfigs + .widgets.lineWidthCloseButton!(this, fn) : null, ), StatefulBuilder(builder: (context, setState) { - if (customWidgets.paintEditor.sliderLineWidth != null) { - return customWidgets.paintEditor.sliderLineWidth!( + if (paintEditorConfigs.widgets.sliderLineWidth != null) { + return paintEditorConfigs.widgets.sliderLineWidth!( this, rebuildController.stream, paintCtrl.strokeWidth, @@ -428,7 +428,7 @@ class PaintingEditorState extends State void openOpacityBottomSheet() { showModalBottomSheet( context: context, - backgroundColor: imageEditorTheme.paintingEditor.opacityBottomSheetColor, + backgroundColor: paintEditorConfigs.style.opacityBottomSheetBackground, builder: (BuildContext context) { return StatefulBuilder(builder: (context, setState) { return Material( @@ -445,19 +445,19 @@ class PaintingEditorState extends State BottomSheetHeaderRow( title: i18n.paintEditor.changeOpacity, theme: initConfigs.theme, - textStyle: imageEditorTheme - .paintingEditor.opacityBottomSheetTitle, + textStyle: + paintEditorConfigs.style.opacityBottomSheetTitle, closeButton: - customWidgets.paintEditor.changeOpacityCloseButton != + paintEditorConfigs.widgets.changeOpacityCloseButton != null - ? (fn) => customWidgets.paintEditor - .changeOpacityCloseButton!(this, fn) + ? (fn) => paintEditorConfigs + .widgets.changeOpacityCloseButton!(this, fn) : null, ), StatefulBuilder(builder: (context, setState) { - if (customWidgets.paintEditor.sliderChangeOpacity != + if (paintEditorConfigs.widgets.sliderChangeOpacity != null) { - return customWidgets.paintEditor.sliderChangeOpacity!( + return paintEditorConfigs.widgets.sliderChangeOpacity!( this, rebuildController.stream, paintCtrl.opacity, @@ -523,10 +523,10 @@ class PaintingEditorState extends State _interactiveViewer.currentState?.setEnableInteraction( mode == PaintModeE.moveAndZoom, ); - _paintingCanvas.currentState?.setState(() {}); + _paintCanvas.currentState?.setState(() {}); } - /// Undoes the last action performed in the painting editor. + /// Undoes the last action performed in the paint editor. void undoAction() { if (canUndo) screenshotHistoryPosition--; paintCtrl.undo(); @@ -535,7 +535,7 @@ class PaintingEditorState extends State paintEditorCallbacks?.handleUndo(); } - /// Redoes the previously undone action in the painting editor. + /// Redoes the previously undone action in the paint editor. void redoAction() { if (canRedo) screenshotHistoryPosition++; paintCtrl.redo(); @@ -544,7 +544,7 @@ class PaintingEditorState extends State paintEditorCallbacks?.handleRedo(); } - /// Finishes editing in the painting editor and returns the painted items as + /// Finishes editing in the paint editor and returns the painted items as /// a result. /// If no changes have been made, it closes the editor without returning any /// changes. @@ -567,16 +567,16 @@ class PaintingEditorState extends State paintEditorCallbacks?.handleDone(); } - /// Exports the painted items as a list of [PaintingLayerData]. + /// Exports the painted items as a list of [PaintLayerData]. /// - /// This method converts the painting history into a list of - /// [PaintingLayerData] representing the painted items. + /// This method converts the paint history into a list of + /// [PaintLayerData] representing the painted items. /// /// Example: /// ```dart - /// List layers = exportPaintedItems(); + /// List layers = exportPaintedItems(); /// ``` - List _exportPaintedItems(Size editorSize) { + List _exportPaintedItems(Size editorSize) { Rect findRenderedLayerRect(List points) { if (points.isEmpty) return Rect.zero; @@ -609,7 +609,7 @@ class PaintingEditorState extends State } // Convert to free positions - return paintCtrl.activePaintings.map((e) { + return paintCtrl.activePaintItemList.map((e) { PaintedModel layer = PaintedModel( mode: e.mode, offsets: [...e.offsets], @@ -619,7 +619,7 @@ class PaintingEditorState extends State opacity: e.opacity, ); - // Find extreme points of the painting layer + // Find extreme points of the paint layer Rect? layerRect = findRenderedLayerRect(e.offsets); Size size = layerRect.size; @@ -631,7 +631,7 @@ class PaintingEditorState extends State ((e.mode == PaintModeE.rect || e.mode == PaintModeE.circle) && !e.fill); - // Scale and offset the offsets of the painting layer + // Scale and offset the offsets of the paint layer double strokeHelperWidth = onlyStrokeMode ? e.strokeWidth : 0; for (int i = 0; i < layer.offsets.length; i++) { @@ -644,7 +644,7 @@ class PaintingEditorState extends State } } - // Calculate the final offset of the painting layer + // Calculate the final offset of the paint layer Offset finalOffset = Offset( layerRect.center.dx - editorSize.width / 2, layerRect.center.dy - editorSize.height / 2, @@ -657,8 +657,8 @@ class PaintingEditorState extends State ); } - // Create and return a PaintingLayerData instance for the exported layer - return PaintingLayerData( + // Create and return a PaintLayerData instance for the exported layer + return PaintLayerData( item: layer.copy(), rawSize: Size( max(size.width, layer.strokeWidth), @@ -688,7 +688,7 @@ class PaintingEditorState extends State @override Widget build(BuildContext context) { return AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: paintEditorConfigs.style.uiOverlayStyle, child: ExtendedPopScope( child: Theme( data: theme.copyWith( @@ -703,7 +703,7 @@ class PaintingEditorState extends State child: LayoutBuilder(builder: (context, constraints) { return Scaffold( resizeToAvoidBottomInset: false, - backgroundColor: imageEditorTheme.paintingEditor.background, + backgroundColor: paintEditorConfigs.style.background, appBar: _buildAppBar(constraints), body: _buildBody(), bottomNavigationBar: _buildBottomBar(), @@ -716,18 +716,18 @@ class PaintingEditorState extends State ); } - /// Builds the app bar for the painting editor. + /// Builds the app bar for the paint editor. /// Returns a [PreferredSizeWidget] representing the app bar. PreferredSizeWidget? _buildAppBar(BoxConstraints constraints) { - if (customWidgets.paintEditor.appBar != null) { - return customWidgets.paintEditor.appBar! + if (paintEditorConfigs.widgets.appBar != null) { + return paintEditorConfigs.widgets.appBar! .call(this, rebuildController.stream); } return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.paintingEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.paintingEditor.appBarForegroundColor, + backgroundColor: paintEditorConfigs.style.appBarBackground, + foregroundColor: paintEditorConfigs.style.appBarColor, actions: _buildAction(constraints), ); } @@ -747,7 +747,7 @@ class PaintingEditorState extends State IconButton( tooltip: i18n.paintEditor.back, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), + icon: Icon(paintEditorConfigs.icons.backButton), onPressed: close, ), const Spacer(), @@ -791,7 +791,7 @@ class PaintingEditorState extends State PopupMenuOption( label: i18n.paintEditor.lineWidth, icon: Icon( - icons.paintingEditor.lineWeight, + paintEditorConfigs.icons.lineWeight, ), onTap: openLineWeightBottomSheet, ), @@ -800,8 +800,8 @@ class PaintingEditorState extends State label: i18n.paintEditor.toggleFill, icon: Icon( !_fill - ? icons.paintingEditor.noFill - : icons.paintingEditor.fill, + ? paintEditorConfigs.icons.noFill + : paintEditorConfigs.icons.fill, ), onTap: () { _fill = !_fill; @@ -815,7 +815,7 @@ class PaintingEditorState extends State PopupMenuOption( label: i18n.paintEditor.changeOpacity, icon: Icon( - icons.paintingEditor.changeOpacity, + paintEditorConfigs.icons.changeOpacity, ), onTap: openOpacityBottomSheet, ), @@ -824,7 +824,7 @@ class PaintingEditorState extends State PopupMenuOption( label: i18n.paintEditor.undo, icon: Icon( - icons.undoAction, + paintEditorConfigs.icons.undoAction, ), onTap: undoAction, ), @@ -832,7 +832,7 @@ class PaintingEditorState extends State PopupMenuOption( label: i18n.paintEditor.redo, icon: Icon( - icons.redoAction, + paintEditorConfigs.icons.redoAction, ), onTap: redoAction, ), @@ -853,7 +853,7 @@ class PaintingEditorState extends State tooltip: i18n.paintEditor.lineWidth, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.paintingEditor.lineWeight, + paintEditorConfigs.icons.lineWeight, color: Colors.white, ), onPressed: openLineWeightBottomSheet, @@ -868,8 +868,8 @@ class PaintingEditorState extends State padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( !_fill - ? icons.paintingEditor.noFill - : icons.paintingEditor.fill, + ? paintEditorConfigs.icons.noFill + : paintEditorConfigs.icons.fill, color: Colors.white, ), onPressed: toggleFill, @@ -883,7 +883,7 @@ class PaintingEditorState extends State tooltip: i18n.paintEditor.changeOpacity, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.paintingEditor.changeOpacity, + paintEditorConfigs.icons.changeOpacity, color: Colors.white, ), onPressed: openOpacityBottomSheet, @@ -900,7 +900,7 @@ class PaintingEditorState extends State tooltip: i18n.paintEditor.undo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.undoAction, + paintEditorConfigs.icons.undoAction, color: canUndo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: undoAction, @@ -913,7 +913,7 @@ class PaintingEditorState extends State tooltip: i18n.paintEditor.redo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.redoAction, + paintEditorConfigs.icons.redoAction, color: canRedo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: redoAction, @@ -927,13 +927,13 @@ class PaintingEditorState extends State return IconButton( tooltip: i18n.paintEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(paintEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ); } - /// Builds the main body of the painting editor. + /// Builds the main body of the paint editor. /// Returns a [Widget] representing the editor's body. Widget _buildBody() { return SafeArea( @@ -943,7 +943,7 @@ class PaintingEditorState extends State data: theme, child: Material( color: initConfigs.convertToUint8List - ? imageEditorTheme.background + ? paintEditorConfigs.style.background : Colors.transparent, textStyle: platformTextStyle(context, designMode), child: Stack( @@ -994,7 +994,7 @@ class PaintingEditorState extends State alignment: Alignment.center, fit: StackFit.expand, children: [ - if (!widget.paintingOnly) + if (!widget.paintOnly) TransformedContentGenerator( configs: configs, transformConfigs: initialTransformConfigs ?? @@ -1015,10 +1015,10 @@ class PaintingEditorState extends State ) else SizedBox( - width: configs.imageGenerationConfigs - .maxOutputSize.width, - height: configs.imageGenerationConfigs - .maxOutputSize.height, + width: configs + .imageGeneration.maxOutputSize.width, + height: configs + .imageGeneration.maxOutputSize.height, ), if (layers != null) LayerStack( @@ -1034,17 +1034,19 @@ class PaintingEditorState extends State ), ), _buildPainter(), - if (customWidgets.paintEditor.bodyItemsRecorded != + if (paintEditorConfigs + .widgets.bodyItemsRecorded != null) - ...customWidgets.paintEditor.bodyItemsRecorded!( + ...paintEditorConfigs + .widgets.bodyItemsRecorded!( this, rebuildController.stream), ], ), ), ), _buildColorPicker(), - if (customWidgets.paintEditor.bodyItems != null) - ...customWidgets.paintEditor.bodyItems!( + if (paintEditorConfigs.widgets.bodyItems != null) + ...paintEditorConfigs.widgets.bodyItems!( this, rebuildController.stream), ], ), @@ -1054,11 +1056,11 @@ class PaintingEditorState extends State ); } - /// Builds the bottom navigation bar of the painting editor. + /// Builds the bottom navigation bar of the paint editor. /// Returns a [Widget] representing the bottom navigation bar. Widget? _buildBottomBar() { - if (customWidgets.paintEditor.bottomBar != null) { - return customWidgets.paintEditor.bottomBar! + if (paintEditorConfigs.widgets.bottomBar != null) { + return paintEditorConfigs.widgets.bottomBar! .call(this, rebuildController.stream); } @@ -1075,7 +1077,7 @@ class PaintingEditorState extends State thickness: isDesktop ? null : 0, child: BottomAppBar( height: kToolbarHeight, - color: imageEditorTheme.paintingEditor.bottomBarColor, + color: paintEditorConfigs.style.bottomBarBackground, padding: EdgeInsets.zero, child: Center( child: SingleChildScrollView( @@ -1091,10 +1093,8 @@ class PaintingEditorState extends State child: StatefulBuilder(builder: (context, setStateBottomBar) { Color getColor(PaintModeE mode) { return paintMode == mode - ? imageEditorTheme - .paintingEditor.bottomBarActiveItemColor - : imageEditorTheme - .paintingEditor.bottomBarInactiveItemColor; + ? paintEditorConfigs.style.bottomBarActiveItemColor + : paintEditorConfigs.style.bottomBarInactiveItemColor; } return Wrap( @@ -1113,7 +1113,7 @@ class PaintingEditorState extends State ), ), icon: Icon( - icons.paintingEditor.moveAndZoom, + paintEditorConfigs.icons.moveAndZoom, color: getColor(PaintModeE.moveAndZoom), ), onPressed: () { @@ -1127,8 +1127,8 @@ class PaintingEditorState extends State width: 1, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), - color: imageEditorTheme - .paintingEditor.bottomBarInactiveItemColor, + color: paintEditorConfigs + .style.bottomBarInactiveItemColor, ), ) ], @@ -1161,11 +1161,11 @@ class PaintingEditorState extends State ); } - /// Builds the painting canvas for the editor. - /// Returns a [Widget] representing the painting canvas. + /// Builds the paint canvas for the editor. + /// Returns a [Widget] representing the paint canvas. Widget _buildPainter() { - return PaintingCanvas( - key: _paintingCanvas, + return PaintCanvas( + key: _paintCanvas, paintCtrl: paintCtrl, drawAreaSize: mainBodySize ?? editorBodySize, freeStyleHighPerformance: _freeStyleHighPerformance, @@ -1176,10 +1176,10 @@ class PaintingEditorState extends State takeScreenshot(); }); }, - onStartPainting: () { + onStart: () { rebuildController.add(null); }, - onCreatedPainting: () { + onCreated: () { _uiAppbarIconsStream.add(null); uiPickerStream.add(null); paintEditorCallbacks?.handleDrawingDone(); @@ -1190,11 +1190,11 @@ class PaintingEditorState extends State ); } - /// Builds the color picker widget for selecting colors while painting. + /// Builds the color picker widget for selecting colors while paint. /// Returns a [Widget] representing the color picker. Widget _buildColorPicker() { - if (customWidgets.paintEditor.colorPicker != null) { - return customWidgets.paintEditor.colorPicker!.call( + if (paintEditorConfigs.widgets.colorPicker != null) { + return paintEditorConfigs.widgets.colorPicker!.call( this, rebuildController.stream, paintCtrl.color, @@ -1224,7 +1224,7 @@ class PaintingEditorState extends State thumbColor: Colors.white, cornerRadius: 10, pickMode: PickMode.color, - initialColor: imageEditorTheme.paintingEditor.initialColor, + initialColor: paintEditorConfigs.style.initialColor, colorListener: (int value) { colorChanged(Color(value)); }, diff --git a/lib/modules/paint_editor/utils/paint_controller.dart b/lib/modules/paint_editor/utils/paint_controller.dart index 446e9175..035ac681 100644 --- a/lib/modules/paint_editor/utils/paint_controller.dart +++ b/lib/modules/paint_editor/utils/paint_controller.dart @@ -5,18 +5,18 @@ import 'package:flutter/material.dart'; import '../../../models/paint_editor/painted_model.dart'; import 'paint_editor_enum.dart'; -/// The `PaintingController` class is responsible for managing and controlling -/// the painting state. -class PaintingController extends ChangeNotifier { - /// Creates an instance of the `PaintingController` with initial settings. +/// The `PaintController` class is responsible for managing and controlling +/// the paint state. +class PaintController extends ChangeNotifier { + /// Creates an instance of the `PaintController` with initial settings. /// /// - `strokeWidth`: The initial stroke width. /// - `color`: The initial color. - /// - `mode`: The initial painting mode (e.g., line, circle, rectangle). + /// - `mode`: The initial paint mode (e.g., line, circle, rectangle). /// - `fill`: Whether the initial mode should fill the shape /// (e.g., circle or rectangle). /// - `strokeMultiplier`: The multiplier for the stroke width. - PaintingController({ + PaintController({ required double strokeWidth, required Color color, required PaintModeE mode, @@ -31,46 +31,46 @@ class PaintingController extends ChangeNotifier { _strokeMultiplier = strokeMultiplier; } - /// The width of the stroke for painting operations. + /// The width of the stroke for paint operations. late double _strokeWidth; - /// The color used for painting operations. + /// The color used for paint operations. late Color _color; - /// The mode of painting, specifying the type of painting operation. + /// The mode of paint, specifying the type of paint operation. late PaintModeE _mode; - /// A flag indicating whether painting operations should fill shapes. + /// A flag indicating whether paint operations should fill shapes. late bool _fill; /// The opacity for the drawing late double opacity; - /// List of offsets representing points on the canvas during painting. + /// List of offsets representing points on the canvas during paint. final List _offsets = []; - /// History of painted models representing previous painting operations. + /// History of painted models representing previous paint operations. final List> paintHistory = []; - /// The current position in the painting history. + /// The current position in the paint history. int historyPosition = 0; - /// The starting point of the current painting operation. + /// The starting point of the current paint operation. Offset? _start; - /// The ending point of the current painting operation. + /// The ending point of the current paint operation. Offset? _end; /// Multiplier for stroke width, used in scaling the stroke. int _strokeMultiplier = 1; - /// Flag indicating whether a painting operation is in progress. + /// Flag indicating whether a paint operation is in progress. bool _paintInProgress = false; /// Getter for the current state of the painted model. /// /// Returns a [PaintedModel] instance representing the current state of the - /// painting. + /// paint. PaintedModel get paintedModel => PaintedModel( mode: mode, offsets: mode == PaintModeE.freeStyle ? offsets : [start, end], @@ -80,7 +80,7 @@ class PaintingController extends ChangeNotifier { opacity: opacity, ); - /// Returns the current painting mode (e.g., line, circle, rectangle). + /// Returns the current paint mode (e.g., line, circle, rectangle). PaintModeE get mode => _mode; /// Returns the current stroke width. @@ -89,29 +89,29 @@ class PaintingController extends ChangeNotifier { /// Returns the scaled stroke width based on the stroke multiplier. double get scaledStrokeWidth => _strokeWidth * _strokeMultiplier; - /// Indicates whether there is an ongoing painting action. + /// Indicates whether there is an ongoing paint action. bool get busy => _paintInProgress; /// Indicates whether the current mode requires filling /// (e.g., circle or rectangle). bool get fill => _fill; - /// Returns the current color used for painting. + /// Returns the current color used for paint. Color get color => _color; - /// Returns the list of painted models representing the painting history. - List get activePaintings => + /// Returns the list of painted models representing the paint history. + List get activePaintItemList => historyPosition <= 0 || paintHistory.length < historyPosition ? [] : paintHistory[historyPosition - 1]; - /// Returns the list of recorded painting offsets. + /// Returns the list of recorded paint offsets. List get offsets => _offsets; - /// Returns the starting point of a painting action. + /// Returns the starting point of a paint action. Offset? get start => _start; - /// Returns the ending point of a painting action. + /// Returns the ending point of a paint action. Offset? get end => _end; /// Determines whether undo actions can be performed on the current state. @@ -120,21 +120,21 @@ class PaintingController extends ChangeNotifier { /// Determines whether redo actions can be performed on the current state. bool get canRedo => historyPosition < paintHistory.length; - /// Adds a painted model to the painting history and notifies listeners of + /// Adds a painted model to the paint history and notifies listeners of /// the change. void addPaintInfo(PaintedModel paintInfo) { _cleanForwardChanges(); - paintHistory.add([...activePaintings, paintInfo]); + paintHistory.add([...activePaintItemList, paintInfo]); historyPosition++; } - /// Adds a painted model to the painting history and notifies listeners of + /// Adds a painted model to the paint history and notifies listeners of /// the change. void removeLayers(List idList) { _cleanForwardChanges(); - paintHistory.add([...activePaintings]); + paintHistory.add([...activePaintItemList]); historyPosition++; - activePaintings.removeWhere((el) => idList.contains(el.id)); + activePaintItemList.removeWhere((el) => idList.contains(el.id)); } /// Clean forward changes in the history. @@ -153,7 +153,7 @@ class PaintingController extends ChangeNotifier { historyPosition = paintHistory.length; } - /// Undoes the last painting action by moving it from the history to the + /// Undoes the last paint action by moving it from the history to the /// redo history and notifies listeners. void undo() { if (historyPosition > 0) { @@ -161,7 +161,7 @@ class PaintingController extends ChangeNotifier { } } - /// Redoes the last undone painting action by moving it from the redo history + /// Redoes the last undone paint action by moving it from the redo history /// to the history and notifies listeners. void redo() { if (historyPosition < paintHistory.length) { @@ -175,13 +175,13 @@ class PaintingController extends ChangeNotifier { notifyListeners(); } - /// Sets the painting color to the specified color and notifies listeners. + /// Sets the paint color to the specified color and notifies listeners. void setColor(Color color) { _color = color; notifyListeners(); } - /// Sets the painting mode to the specified mode and notifies listeners. + /// Sets the paint mode to the specified mode and notifies listeners. void setMode(PaintModeE mode) { _mode = mode; notifyListeners(); @@ -193,13 +193,13 @@ class PaintingController extends ChangeNotifier { notifyListeners(); } - /// Sets the starting point of a painting action and notifies listeners. + /// Sets the starting point of a paint action and notifies listeners. void setStart(Offset offset) { _start = offset; notifyListeners(); } - /// Sets the ending point of a painting action and notifies listeners. + /// Sets the ending point of a paint action and notifies listeners. void setEnd(Offset offset) { _end = offset; notifyListeners(); @@ -233,9 +233,9 @@ class PaintingController extends ChangeNotifier { notifyListeners(); } - /// Sets the painting progress state and notifies listeners. + /// Sets the paint progress state and notifies listeners. /// - /// - [val]: The boolean value indicating the painting progress state. + /// - [val]: The boolean value indicating the paint progress state. void setInProgress(bool val) { _paintInProgress = val; notifyListeners(); diff --git a/lib/modules/paint_editor/utils/paint_desktop_interaction_manager.dart b/lib/modules/paint_editor/utils/paint_desktop_interaction_manager.dart index 180ab94e..45dd02e2 100644 --- a/lib/modules/paint_editor/utils/paint_desktop_interaction_manager.dart +++ b/lib/modules/paint_editor/utils/paint_desktop_interaction_manager.dart @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; /// to keyboard /// and mouse events on desktop platforms. class PaintDesktopInteractionManager { - /// Manages desktop interactions for painting functionality. + /// Manages desktop interactions for paint functionality. /// Creates an instance of [PaintDesktopInteractionManager]. /// /// [context] is the build context used for interactions. diff --git a/lib/modules/paint_editor/utils/paint_editor_enum.dart b/lib/modules/paint_editor/utils/paint_editor_enum.dart index 6321de08..75202d4e 100644 --- a/lib/modules/paint_editor/utils/paint_editor_enum.dart +++ b/lib/modules/paint_editor/utils/paint_editor_enum.dart @@ -1,4 +1,4 @@ -/// The `PaintModeE` enum represents different painting modes for a drawing +/// The `PaintModeE` enum represents different paint-item modes for a drawing /// application in Flutter. enum PaintModeE { /// Allows to move and zoom the editor @@ -22,6 +22,6 @@ enum PaintModeE { /// Draws a dashed line between two points. dashLine, - /// Remove paintings when hit. + /// Remove paint-items when hit. eraser, } diff --git a/lib/modules/paint_editor/utils/paint_element.dart b/lib/modules/paint_editor/utils/paint_element.dart index 353cdf23..ed3f8f98 100644 --- a/lib/modules/paint_editor/utils/paint_element.dart +++ b/lib/modules/paint_editor/utils/paint_element.dart @@ -5,7 +5,7 @@ import 'dart:ui'; import '../../../models/paint_editor/painted_model.dart'; import 'paint_editor_enum.dart'; -/// Represents an element within the painting editor. +/// Represents an element within the paint-editor. class PaintElement { /// Draws an element on a canvas based on the specified mode and parameters. /// @@ -21,7 +21,7 @@ class PaintElement { /// - `freeStyleHighPerformance`: Controls high-performance for free-style /// drawing. /// - `item` Represents a unit of shape or drawing information used in - /// painting. + /// paint-items. void drawElement({ required Canvas canvas, required Size size, diff --git a/lib/modules/paint_editor/widgets/draw_painting.dart b/lib/modules/paint_editor/widgets/draw_paint_item.dart similarity index 98% rename from lib/modules/paint_editor/widgets/draw_painting.dart rename to lib/modules/paint_editor/widgets/draw_paint_item.dart index 72f89e74..9fc5afe2 100644 --- a/lib/modules/paint_editor/widgets/draw_painting.dart +++ b/lib/modules/paint_editor/widgets/draw_paint_item.dart @@ -9,10 +9,10 @@ import 'package:pro_image_editor/pro_image_editor.dart'; import '../../../models/paint_editor/painted_model.dart'; import '../utils/paint_element.dart'; -/// Handles the painting ongoing on the canvas. -class DrawPainting extends CustomPainter { +/// Handles the paint ongoing on the canvas. +class DrawPaintItem extends CustomPainter { /// Constructor for the canvas. - DrawPainting({ + DrawPaintItem({ this.selected = false, required this.item, this.scale = 1, @@ -50,7 +50,7 @@ class DrawPainting extends CustomPainter { } @override - bool shouldRepaint(DrawPainting oldDelegate) { + bool shouldRepaint(DrawPaintItem oldDelegate) { return oldDelegate.item != item || oldDelegate.freeStyleHighPerformance != freeStyleHighPerformance; } diff --git a/lib/modules/paint_editor/widgets/painting_canvas.dart b/lib/modules/paint_editor/widgets/paint_canvas.dart similarity index 72% rename from lib/modules/paint_editor/widgets/painting_canvas.dart rename to lib/modules/paint_editor/widgets/paint_canvas.dart index eb5bb01f..37d158a8 100644 --- a/lib/modules/paint_editor/widgets/painting_canvas.dart +++ b/lib/modules/paint_editor/widgets/paint_canvas.dart @@ -9,71 +9,71 @@ import 'package:pro_image_editor/pro_image_editor.dart'; import '../../../models/paint_editor/painted_model.dart'; import '../utils/paint_controller.dart'; -/// A widget for creating a canvas for painting on images. +/// A widget for creating a canvas for paint on images. /// -/// This widget allows you to create a canvas for painting on images loaded +/// This widget allows you to create a canvas for paint on images loaded /// from various sources, including network URLs, asset paths, files, or memory /// (Uint8List). /// It provides customization options for appearance and behavior. -class PaintingCanvas extends StatefulWidget { - /// Constructs a `PaintingCanvas` widget. - const PaintingCanvas({ +class PaintCanvas extends StatefulWidget { + /// Constructs a `PaintCanvas` widget. + const PaintCanvas({ super.key, - this.onStartPainting, - this.onCreatedPainting, + this.onStart, + this.onCreated, this.onRemoveLayer, this.freeStyleHighPerformance = false, required this.drawAreaSize, required this.paintCtrl, }); - /// Callback function when the active painting is done. - final VoidCallback? onCreatedPainting; + /// Callback function when the active paint is done. + final VoidCallback? onCreated; /// Callback invoked when layers are removed. /// /// Receives a list of layer identifiers that have been removed. final ValueChanged>? onRemoveLayer; - /// Callback invoked when painting starts. - final VoidCallback? onStartPainting; + /// Callback invoked when paint starts. + final VoidCallback? onStart; /// Size of the image. final Size drawAreaSize; - /// The `PaintingController` class is responsible for managing and controlling - /// the painting state. - final PaintingController paintCtrl; + /// The `PaintController` class is responsible for managing and controlling + /// the paint state. + final PaintController paintCtrl; /// Controls high-performance for free-style drawing. final bool freeStyleHighPerformance; @override - PaintingCanvasState createState() => PaintingCanvasState(); + PaintCanvasState createState() => PaintCanvasState(); } -/// State class for managing the painting canvas. -class PaintingCanvasState extends State { - /// Getter for accessing the [PaintingController] instance provided by the +/// State class for managing the paint canvas. +class PaintCanvasState extends State { + /// Getter for accessing the [PaintController] instance provided by the /// parent widget. - PaintingController get _paintCtrl => widget.paintCtrl; + PaintController get _paintCtrl => widget.paintCtrl; - /// Stream controller for updating painting events. - late final StreamController _activePaintingStreamCtrl; + /// Stream controller for updating paint events. + late final StreamController _activePaintStreamCtrl; @override void initState() { - _activePaintingStreamCtrl = StreamController.broadcast(); + _activePaintStreamCtrl = StreamController.broadcast(); super.initState(); } @override void dispose() { - _activePaintingStreamCtrl.close(); + _activePaintStreamCtrl.close(); super.dispose(); } - /// This method is called when a scaling gesture for painting begins. It + /// This method is called when a scaling gesture for paint begins. It /// captures the starting point of the gesture. /// /// It is not meant to be called directly but is an event handler for scaling @@ -90,14 +90,14 @@ class PaintingCanvasState extends State { _paintCtrl ..setStart(offset) ..addOffsets(offset); - _activePaintingStreamCtrl.add(null); + _activePaintStreamCtrl.add(null); } - /// Fires while the user is interacting with the screen to record painting. + /// Fires while the user is interacting with the screen to record paint. /// /// This method is called during an ongoing scaling gesture to record - /// painting actions. It captures the current position and updates the - /// painting controller accordingly. + /// paint actions. It captures the current position and updates the + /// paint controller accordingly. /// /// It is not meant to be called directly but is an event handler for scaling /// gestures. @@ -106,14 +106,14 @@ class PaintingCanvasState extends State { return; } else if (widget.paintCtrl.mode == PaintModeE.eraser) { List removeIds = []; - for (var item in _paintCtrl.activePaintings) { + for (var item in _paintCtrl.activePaintItemList) { if (item.hit) removeIds.add(item.id); } if (removeIds.isNotEmpty) widget.onRemoveLayer?.call(removeIds); } else { final offset = details.localFocalPoint; if (!_paintCtrl.busy) { - widget.onStartPainting?.call(); + widget.onStart?.call(); _paintCtrl.setInProgress(true); } @@ -127,14 +127,14 @@ class PaintingCanvasState extends State { _paintCtrl.setEnd(offset); - _activePaintingStreamCtrl.add(null); + _activePaintStreamCtrl.add(null); } } /// Fires when the user stops interacting with the screen. /// - /// This method is called when a scaling gesture for painting ends. It - /// finalizes and records the painting action. + /// This method is called when a scaling gesture for paint ends. It + /// finalizes and records the paint action. /// /// It is not meant to be called directly but is an event handler for scaling /// gestures. @@ -166,7 +166,7 @@ class PaintingCanvasState extends State { opacity: _paintCtrl.opacity, ), ); - widget.onCreatedPainting?.call(); + widget.onCreated?.call(); } _paintCtrl.reset(); @@ -180,13 +180,13 @@ class PaintingCanvasState extends State { child: Stack( fit: StackFit.expand, children: [ - for (final item in _paintCtrl.activePaintings) + for (final item in _paintCtrl.activePaintItemList) Opacity( opacity: item.opacity, child: CustomPaint( willChange: false, isComplex: item.mode == PaintModeE.freeStyle, - painter: DrawPainting( + painter: DrawPaintItem( item: item, freeStyleHighPerformance: widget.freeStyleHighPerformance, enabledHitDetection: _paintCtrl.mode == PaintModeE.eraser, @@ -194,7 +194,7 @@ class PaintingCanvasState extends State { ), ), StreamBuilder( - stream: _activePaintingStreamCtrl.stream, + stream: _activePaintStreamCtrl.stream, builder: (context, snapshot) { return GestureDetector( behavior: HitTestBehavior.translucent, @@ -208,7 +208,7 @@ class PaintingCanvasState extends State { size: widget.drawAreaSize, willChange: true, isComplex: true, - painter: DrawPainting(item: _paintCtrl.paintedModel), + painter: DrawPaintItem(item: _paintCtrl.paintedModel), ), ) : const SizedBox.expand(), diff --git a/lib/modules/sticker_editor/sticker_editor.dart b/lib/modules/sticker_editor/sticker_editor.dart index deb4bd94..8eb79caa 100644 --- a/lib/modules/sticker_editor/sticker_editor.dart +++ b/lib/modules/sticker_editor/sticker_editor.dart @@ -52,9 +52,14 @@ class StickerEditorState extends State @override Widget build(BuildContext context) { + assert( + widget.configs.stickerEditor.buildStickers != null, + '`buildStickers` is required', + ); + return ExtendedPopScope( - child: widget.configs.stickerEditorConfigs! - .buildStickers(setLayer, widget.scrollController), + child: widget.configs.stickerEditor.buildStickers!( + setLayer, widget.scrollController), ); } diff --git a/lib/modules/text_editor/text_editor.dart b/lib/modules/text_editor/text_editor.dart index 5d3abab0..37651944 100644 --- a/lib/modules/text_editor/text_editor.dart +++ b/lib/modules/text_editor/text_editor.dart @@ -255,16 +255,15 @@ class TextEditorState extends State textEditorCallbacks?.handleFontScaleChanged(value); } - /// Displays a range slider for adjusting the line width of the painting tool. + /// Displays a range slider for adjusting the line width of the paint tool. /// /// This method shows a range slider in a modal bottom sheet for adjusting the - /// line width of the painting tool. + /// line width of the paint tool. void openFontScaleBottomSheet() { final presetFontScale = _fontScale; showModalBottomSheet( context: context, - backgroundColor: - imageEditorTheme.paintingEditor.lineWidthBottomSheetColor, + backgroundColor: textEditorConfigs.style.fontScaleBottomSheetBackground, builder: (BuildContext context) { return Material( color: Colors.transparent, @@ -287,14 +286,14 @@ class TextEditorState extends State title: '${i18n.textEditor.fontScale} ${_fontScale}x', theme: widget.theme, textStyle: - imageEditorTheme.textEditor.fontSizeBottomSheetTitle, + textEditorConfigs.style.fontSizeBottomSheetTitle, closeButton: - customWidgets.textEditor.fontSizeCloseButton != null - ? (fn) => customWidgets - .textEditor.fontSizeCloseButton!(this, fn) + textEditorConfigs.widgets.fontSizeCloseButton != null + ? (fn) => textEditorConfigs + .widgets.fontSizeCloseButton!(this, fn) : null, ), - customWidgets.textEditor.sliderFontSize?.call( + textEditorConfigs.widgets.sliderFontSize?.call( this, _rebuildController.stream, _fontScale, @@ -324,15 +323,15 @@ class TextEditorState extends State onPressed: () { updateFontScaleScale(presetFontScale); }, - icon: Icon( - icons.textEditor.resetFontScale), + icon: Icon(textEditorConfigs + .icons.resetFontScale), ) : IconButton( key: UniqueKey(), color: Colors.transparent, onPressed: null, - icon: Icon( - icons.textEditor.resetFontScale), + icon: Icon(textEditorConfigs + .icons.resetFontScale), ), ), ), @@ -401,7 +400,7 @@ class TextEditorState extends State left: textEditorConfigs.safeArea.left, right: textEditorConfigs.safeArea.right, child: Scaffold( - backgroundColor: imageEditorTheme.textEditor.background, + backgroundColor: textEditorConfigs.style.background, appBar: _buildAppBar(constraints), body: _buildBody(), bottomNavigationBar: _buildBottomBar(), @@ -415,8 +414,8 @@ class TextEditorState extends State /// Builds the app bar for the text editor. PreferredSizeWidget? _buildAppBar(BoxConstraints constraints) { - if (customWidgets.textEditor.appBar != null) { - return customWidgets.textEditor.appBar! + if (textEditorConfigs.widgets.appBar != null) { + return textEditorConfigs.widgets.appBar! .call(this, _rebuildController.stream); } @@ -428,13 +427,13 @@ class TextEditorState extends State return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.textEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.textEditor.appBarForegroundColor, + backgroundColor: textEditorConfigs.style.appBarBackground, + foregroundColor: textEditorConfigs.style.appBarColor, actions: [ IconButton( tooltip: i18n.textEditor.back, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), + icon: Icon(textEditorConfigs.icons.backButton), onPressed: close, ), const Spacer(), @@ -452,10 +451,10 @@ class TextEditorState extends State PopupMenuOption( label: i18n.textEditor.textAlign, icon: Icon(align == TextAlign.left - ? icons.textEditor.alignLeft + ? textEditorConfigs.icons.alignLeft : align == TextAlign.right - ? icons.textEditor.alignRight - : icons.textEditor.alignCenter), + ? textEditorConfigs.icons.alignRight + : textEditorConfigs.icons.alignCenter), onTap: () { toggleTextAlign(); if (designMode == ImageEditorDesignModeE.cupertino) { @@ -466,7 +465,7 @@ class TextEditorState extends State if (textEditorConfigs.canChangeFontScale) PopupMenuOption( label: i18n.textEditor.fontScale, - icon: Icon(icons.textEditor.fontScale), + icon: Icon(textEditorConfigs.icons.fontScale), onTap: () { openFontScaleBottomSheet(); if (designMode == ImageEditorDesignModeE.cupertino) { @@ -477,7 +476,7 @@ class TextEditorState extends State if (textEditorConfigs.canToggleBackgroundMode) PopupMenuOption( label: i18n.textEditor.backgroundMode, - icon: Icon(icons.textEditor.backgroundMode), + icon: Icon(textEditorConfigs.icons.backgroundMode), onTap: () { toggleBackgroundMode(); if (designMode == ImageEditorDesignModeE.cupertino) { @@ -492,17 +491,16 @@ class TextEditorState extends State ); } - /// Builds the bottom navigation bar of the painting editor. + /// Builds the bottom navigation bar of the paint editor. /// Returns a [Widget] representing the bottom navigation bar. Widget? _buildBottomBar() { - if (customWidgets.textEditor.bottomBar != null) { - return customWidgets.textEditor.bottomBar! + if (textEditorConfigs.widgets.bottomBar != null) { + return textEditorConfigs.widgets.bottomBar! .call(this, _rebuildController.stream); } if (isDesktop && - widget.configs.textEditorConfigs.customTextStyles?.isNotEmpty == - false) { + widget.configs.textEditor.customTextStyles?.isNotEmpty == false) { return const SizedBox(height: kBottomNavigationBarHeight); } @@ -519,8 +517,8 @@ class TextEditorState extends State onTap: done, child: Stack( children: [ - if (customWidgets.textEditor.bodyItems != null) - ...customWidgets.textEditor.bodyItems!( + if (textEditorConfigs.widgets.bodyItems != null) + ...textEditorConfigs.widgets.bodyItems!( this, _rebuildController.stream, ), @@ -551,24 +549,24 @@ class TextEditorState extends State tooltip: i18n.textEditor.textAlign, onPressed: toggleTextAlign, icon: Icon(align == TextAlign.left - ? icons.textEditor.alignLeft + ? textEditorConfigs.icons.alignLeft : align == TextAlign.right - ? icons.textEditor.alignRight - : icons.textEditor.alignCenter), + ? textEditorConfigs.icons.alignRight + : textEditorConfigs.icons.alignCenter), ), if (textEditorConfigs.canChangeFontScale) IconButton( key: const ValueKey('BackgroundModeFontScaleButton'), tooltip: i18n.textEditor.fontScale, onPressed: openFontScaleBottomSheet, - icon: Icon(icons.textEditor.fontScale), + icon: Icon(textEditorConfigs.icons.fontScale), ), if (textEditorConfigs.canToggleBackgroundMode) IconButton( key: const ValueKey('BackgroundModeColorIconButton'), tooltip: i18n.textEditor.backgroundMode, onPressed: toggleBackgroundMode, - icon: Icon(icons.textEditor.backgroundMode), + icon: Icon(textEditorConfigs.icons.backgroundMode), ), ]; @@ -578,15 +576,15 @@ class TextEditorState extends State key: const ValueKey('TextEditorDoneButton'), tooltip: i18n.textEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(textEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ); } Widget _buildColorPicker() { - if (customWidgets.textEditor.colorPicker != null) { - return customWidgets.textEditor.colorPicker!.call( + if (textEditorConfigs.widgets.colorPicker != null) { + return textEditorConfigs.widgets.colorPicker!.call( this, _rebuildController.stream, selectedTextStyle.color ?? primaryColor, @@ -636,7 +634,7 @@ class TextEditorState extends State /// `RoundedBackgroundTextField` code child: IntrinsicWidth( child: Padding( - padding: imageEditorTheme.textEditor.textFieldMargin, + padding: textEditorConfigs.style.textFieldMargin, child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -683,14 +681,14 @@ class TextEditorState extends State textCapitalization: TextCapitalization.sentences, textAlign: textCtrl.text.isEmpty ? TextAlign.center : align, maxLines: null, - cursorColor: imageEditorTheme.textEditor.inputCursorColor, + cursorColor: textEditorConfigs.style.inputCursorColor, cursorHeight: _textFontSize * 1.2, scrollPhysics: const NeverScrollableScrollPhysics(), hint: textCtrl.text.isEmpty ? i18n.textEditor.inputHintText : '', hintStyle: selectedTextStyle.copyWith( - color: imageEditorTheme.textEditor.inputHintColor, + color: textEditorConfigs.style.inputHintColor, fontSize: _textFontSize, height: 1.35, shadows: [], diff --git a/lib/modules/text_editor/widgets/text_editor_bottom_bar.dart b/lib/modules/text_editor/widgets/text_editor_bottom_bar.dart index 55949c34..9624b6fd 100644 --- a/lib/modules/text_editor/widgets/text_editor_bottom_bar.dart +++ b/lib/modules/text_editor/widgets/text_editor_bottom_bar.dart @@ -36,13 +36,12 @@ class _TextEditorBottomBarState extends State { @override Widget build(BuildContext context) { - if (widget.configs.textEditorConfigs.customTextStyles == null) { + if (widget.configs.textEditor.customTextStyles == null) { return const SizedBox.shrink(); } return Container( - color: - widget.configs.imageEditorTheme.textEditor.bottomBarBackgroundColor, + color: widget.configs.textEditor.style.bottomBarBackground, child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 14), scrollDirection: Axis.horizontal, @@ -50,8 +49,8 @@ class _TextEditorBottomBarState extends State { constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width), child: Row( - mainAxisAlignment: widget - .configs.imageEditorTheme.textEditor.bottomBarMainAxisAlignment, + mainAxisAlignment: + widget.configs.textEditor.style.bottomBarMainAxisAlignment, children: _buildIconButtons(), ), ), @@ -60,7 +59,7 @@ class _TextEditorBottomBarState extends State { } List _buildIconButtons() { - var items = widget.configs.textEditorConfigs.customTextStyles!; + var items = widget.configs.textEditor.customTextStyles!; return List.generate( items.length, (index) { diff --git a/lib/modules/tune_editor/tune_editor.dart b/lib/modules/tune_editor/tune_editor.dart index abcae109..c2b9e59b 100644 --- a/lib/modules/tune_editor/tune_editor.dart +++ b/lib/modules/tune_editor/tune_editor.dart @@ -211,7 +211,7 @@ class TuneEditorState extends State var items = tuneEditorConfigs.tuneAdjustmentOptions ?? tunePresets( - icons: icons.tuneEditor, + icons: tuneEditorConfigs.icons, i18n: i18n.tuneEditor, ); tuneAdjustmentList = items.map((item) { @@ -370,7 +370,7 @@ class TuneEditorState extends State tooltipTheme: theme.tooltipTheme.copyWith(preferBelow: true)), child: ExtendedPopScope( child: AnnotatedRegion( - value: imageEditorTheme.uiOverlayStyle, + value: tuneEditorConfigs.style.uiOverlayStyle, child: SafeArea( top: tuneEditorConfigs.safeArea.top, bottom: tuneEditorConfigs.safeArea.bottom, @@ -379,7 +379,7 @@ class TuneEditorState extends State child: RecordInvisibleWidget( controller: screenshotCtrl, child: Scaffold( - backgroundColor: imageEditorTheme.tuneEditor.background, + backgroundColor: tuneEditorConfigs.style.background, appBar: _buildAppBar(), body: _buildBody(), bottomNavigationBar: _buildBottomNavBar(), @@ -393,19 +393,19 @@ class TuneEditorState extends State /// Builds the app bar for the tune editor. PreferredSizeWidget? _buildAppBar() { - if (customWidgets.tuneEditor.appBar != null) { - return customWidgets.tuneEditor.appBar! + if (tuneEditorConfigs.widgets.appBar != null) { + return tuneEditorConfigs.widgets.appBar! .call(this, rebuildController.stream); } return AppBar( automaticallyImplyLeading: false, - backgroundColor: imageEditorTheme.tuneEditor.appBarBackgroundColor, - foregroundColor: imageEditorTheme.tuneEditor.appBarForegroundColor, + backgroundColor: tuneEditorConfigs.style.appBarBackground, + foregroundColor: tuneEditorConfigs.style.appBarColor, actions: [ IconButton( tooltip: i18n.tuneEditor.back, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.backButton), + icon: Icon(tuneEditorConfigs.icons.backButton), onPressed: close, ), const Spacer(), @@ -413,7 +413,7 @@ class TuneEditorState extends State tooltip: i18n.tuneEditor.undo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.undoAction, + tuneEditorConfigs.icons.undoAction, color: canUndo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: canUndo ? undo : null, @@ -422,7 +422,7 @@ class TuneEditorState extends State tooltip: i18n.tuneEditor.redo, padding: const EdgeInsets.symmetric(horizontal: 8), icon: Icon( - icons.redoAction, + tuneEditorConfigs.icons.redoAction, color: canRedo ? Colors.white : Colors.white.withAlpha(80), ), onPressed: canRedo ? redo : null, @@ -430,7 +430,7 @@ class TuneEditorState extends State IconButton( tooltip: i18n.tuneEditor.done, padding: const EdgeInsets.symmetric(horizontal: 8), - icon: Icon(icons.applyChanges), + icon: Icon(tuneEditorConfigs.icons.applyChanges), iconSize: 28, onPressed: done, ), @@ -492,14 +492,14 @@ class TuneEditorState extends State layers: layers!, clipBehavior: Clip.none, ), - if (customWidgets.tuneEditor.bodyItemsRecorded != null) - ...customWidgets.tuneEditor.bodyItemsRecorded!( + if (tuneEditorConfigs.widgets.bodyItemsRecorded != null) + ...tuneEditorConfigs.widgets.bodyItemsRecorded!( this, rebuildController.stream), ], ), ), - if (customWidgets.tuneEditor.bodyItems != null) - ...customWidgets.tuneEditor.bodyItems!( + if (tuneEditorConfigs.widgets.bodyItems != null) + ...tuneEditorConfigs.widgets.bodyItems!( this, rebuildController.stream), ], ); @@ -508,8 +508,8 @@ class TuneEditorState extends State /// Builds the bottom navigation bar with tune options. Widget? _buildBottomNavBar() { - if (customWidgets.tuneEditor.bottomBar != null) { - return customWidgets.tuneEditor.bottomBar! + if (tuneEditorConfigs.widgets.bottomBar != null) { + return tuneEditorConfigs.widgets.bottomBar! .call(this, rebuildController.stream); } var bottomTextStyle = const TextStyle(fontSize: 10.0); @@ -517,7 +517,7 @@ class TuneEditorState extends State return SafeArea( child: Container( - color: imageEditorTheme.tuneEditor.bottomBarColor, + color: tuneEditorConfigs.style.bottomBarBackground, padding: const EdgeInsets.only(top: 5), child: Column( mainAxisSize: MainAxisSize.min, @@ -533,7 +533,7 @@ class TuneEditorState extends State var activeMatrix = tuneAdjustmentMatrix[selectedIndex]; return SizedBox( height: 40, - child: customWidgets.tuneEditor.slider?.call( + child: tuneEditorConfigs.widgets.slider?.call( this, rebuildController.stream, activeMatrix.value, @@ -580,20 +580,20 @@ class TuneEditorState extends State item.label, style: bottomTextStyle.copyWith( color: selectedIndex == index - ? imageEditorTheme - .tuneEditor.bottomBarActiveItemColor - : imageEditorTheme - .tuneEditor.bottomBarInactiveItemColor, + ? tuneEditorConfigs + .style.bottomBarActiveItemColor + : tuneEditorConfigs + .style.bottomBarInactiveItemColor, ), ), icon: Icon( item.icon, size: bottomIconSize, color: selectedIndex == index - ? imageEditorTheme - .tuneEditor.bottomBarActiveItemColor - : imageEditorTheme - .tuneEditor.bottomBarInactiveItemColor, + ? tuneEditorConfigs + .style.bottomBarActiveItemColor + : tuneEditorConfigs + .style.bottomBarInactiveItemColor, ), onPressed: () { setState(() { diff --git a/lib/modules/tune_editor/utils/tune_presets.dart b/lib/modules/tune_editor/utils/tune_presets.dart index 7d16a40f..3f97aeb4 100644 --- a/lib/modules/tune_editor/utils/tune_presets.dart +++ b/lib/modules/tune_editor/utils/tune_presets.dart @@ -1,12 +1,12 @@ import 'package:pro_image_editor/models/i18n/i18n_tune_editor.dart'; -import 'package:pro_image_editor/models/icons/icons_tune_editor.dart'; +import 'package:pro_image_editor/models/icons/tune_editor_icons.dart'; import '../../../models/tune_editor/tune_adjustment_item.dart'; import '../../filter_editor/utils/filter_generator/filter_addons.dart'; /// Preset list from tune adjustment List tunePresets({ - required IconsTuneEditor icons, + required TuneEditorIcons icons, required I18nTuneEditor i18n, }) => [ diff --git a/lib/pro_image_editor.dart b/lib/pro_image_editor.dart index 4602201e..96492617 100644 --- a/lib/pro_image_editor.dart +++ b/lib/pro_image_editor.dart @@ -48,6 +48,7 @@ export 'widgets/color_picker/bar_color_picker.dart'; export 'widgets/custom_widgets/reactive_custom_appbar.dart'; export 'widgets/custom_widgets/reactive_custom_widget.dart'; export 'widgets/extended/extended_pop_scope.dart'; +export 'common/editor_style_constants.dart'; /// Widgets export 'widgets/animated/fade_in_up.dart'; diff --git a/lib/utils/content_recorder.dart/content_recorder_controller.dart b/lib/utils/content_recorder.dart/content_recorder_controller.dart index 99c4da24..9ca12aa2 100644 --- a/lib/utils/content_recorder.dart/content_recorder_controller.dart +++ b/lib/utils/content_recorder.dart/content_recorder_controller.dart @@ -107,7 +107,7 @@ class ContentRecorderController { return null; } - outputFormat ??= _configs.imageGenerationConfigs.outputFormat; + outputFormat ??= _configs.imageGeneration.outputFormat; image ??= await _getRenderedImage(imageInfos: imageInfos); id ??= generateUniqueId(); onImageCaptured?.call(image); @@ -133,9 +133,9 @@ class ContentRecorderController { required String id, OutputFormat? format, }) async { - format ??= _configs.imageGenerationConfigs.outputFormat; + format ??= _configs.imageGeneration.outputFormat; - if (_configs.imageGenerationConfigs.generateInsideSeparateThread) { + if (_configs.imageGeneration.generateInsideSeparateThread) { try { if (!kIsWeb) { // Run in dart native the thread isolated. @@ -211,7 +211,7 @@ class ContentRecorderController { Future _captureWithMainThread({ required ui.Image image, }) async { - if (_configs.imageGenerationConfigs.captureOnlyDrawingBounds) { + if (_configs.imageGeneration.captureOnlyDrawingBounds) { image = await dartUiRemoveTransparentImgAreas(image) ?? image; } @@ -262,7 +262,7 @@ class ContentRecorderController { BuildContext? context = widgetKey.currentContext; double outputRatio = imageInfos.pixelRatio; - if (!_configs.imageGenerationConfigs.captureOnlyDrawingBounds && + if (!_configs.imageGeneration.captureOnlyDrawingBounds && context != null && context.mounted) { outputRatio = @@ -283,11 +283,11 @@ class ContentRecorderController { } double pixelRatio = - _configs.imageGenerationConfigs.customPixelRatio ?? outputRatio; + _configs.imageGeneration.customPixelRatio ?? outputRatio; ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); - if (_configs.imageGenerationConfigs.captureOnlyBackgroundImageArea) { + if (_configs.imageGeneration.captureOnlyBackgroundImageArea) { double cropRectRatio = !imageInfos.isRotated ? imageInfos.cropRectSize.aspectRatio : 1 / imageInfos.cropRectSize.aspectRatio; @@ -351,8 +351,8 @@ class ContentRecorderController { /// Retrieves the maximum output dimension for image generation from the /// configuration. Size _maxOutputDimension(bool useThumbnailSize) => !useThumbnailSize - ? _configs.imageGenerationConfigs.maxOutputSize - : _configs.imageGenerationConfigs.maxThumbnailSize; + ? _configs.imageGeneration.maxOutputSize + : _configs.imageGeneration.maxThumbnailSize; /// Checks if the output size exceeds the maximum allowable dimensions. bool _isOutputSizeTooLarge( @@ -426,8 +426,8 @@ class ContentRecorderController { Size? targetSize, Widget? widget, }) async { - if (!_configs.imageGenerationConfigs.generateImageInBackground || - !_configs.imageGenerationConfigs.generateInsideSeparateThread) { + if (!_configs.imageGeneration.generateImageInBackground || + !_configs.imageGeneration.generateInsideSeparateThread) { return; } @@ -529,13 +529,12 @@ class ContentRecorderController { lookupMimeType('', headerBytes: bytes) ?? 'Unknown'; List sp = contentType.split('/'); bool formatIsCorrect = sp.length > 1 && - (_configs.imageGenerationConfigs.outputFormat.name == sp[1] || + (_configs.imageGeneration.outputFormat.name == sp[1] || (sp[1] == 'jpeg' && - _configs.imageGenerationConfigs.outputFormat == - OutputFormat.jpg)); + _configs.imageGeneration.outputFormat == OutputFormat.jpg)); double outputRatio = imageInfos.pixelRatio; - if (!_configs.imageGenerationConfigs.captureOnlyDrawingBounds && + if (!_configs.imageGeneration.captureOnlyDrawingBounds && context != null && context.mounted) { outputRatio = max( @@ -548,7 +547,7 @@ class ContentRecorderController { ); if (!formatIsCorrect || isOutputSizeTooLarge) { final ui.Image image = await decodeImageFromList(originalImageBytes); - if (_configs.imageGenerationConfigs.generateInsideSeparateThread) { + if (_configs.imageGeneration.generateInsideSeparateThread) { if (kIsWeb || isOutputSizeTooLarge) { /// currently in the web flutter decode the image wrong so we need /// to recapture it. @@ -629,12 +628,12 @@ class ContentRecorderController { Future _encodeImage(ui.Image image) async { return await encodeImage( image: await _convertFlutterUiToImage(image), - outputFormat: _configs.imageGenerationConfigs.outputFormat, - singleFrame: _configs.imageGenerationConfigs.singleFrame, - jpegQuality: _configs.imageGenerationConfigs.jpegQuality, - jpegChroma: _configs.imageGenerationConfigs.jpegChroma, - pngFilter: _configs.imageGenerationConfigs.pngFilter, - pngLevel: _configs.imageGenerationConfigs.pngLevel, + outputFormat: _configs.imageGeneration.outputFormat, + singleFrame: _configs.imageGeneration.singleFrame, + jpegQuality: _configs.imageGeneration.jpegQuality, + jpegChroma: _configs.imageGeneration.jpegChroma, + pngFilter: _configs.imageGeneration.pngFilter, + pngLevel: _configs.imageGeneration.pngLevel, ); } @@ -657,13 +656,13 @@ class ContentRecorderController { return ImageConvertThreadRequest( id: id, generateOnlyImageBounds: - _configs.imageGenerationConfigs.captureOnlyDrawingBounds, + _configs.imageGeneration.captureOnlyDrawingBounds, outputFormat: format, - jpegChroma: _configs.imageGenerationConfigs.jpegChroma, - jpegQuality: _configs.imageGenerationConfigs.jpegQuality, - pngFilter: _configs.imageGenerationConfigs.pngFilter, - pngLevel: _configs.imageGenerationConfigs.pngLevel, - singleFrame: _configs.imageGenerationConfigs.singleFrame, + jpegChroma: _configs.imageGeneration.jpegChroma, + jpegQuality: _configs.imageGeneration.jpegQuality, + pngFilter: _configs.imageGeneration.pngFilter, + pngLevel: _configs.imageGeneration.pngLevel, + singleFrame: _configs.imageGeneration.singleFrame, image: await _convertFlutterUiToImage(image), ); } @@ -686,12 +685,12 @@ class ContentRecorderController { return ThreadRequest( id: id, image: await _convertFlutterUiToImage(image), - outputFormat: _configs.imageGenerationConfigs.outputFormat, - singleFrame: _configs.imageGenerationConfigs.singleFrame, - jpegQuality: _configs.imageGenerationConfigs.jpegQuality, - jpegChroma: _configs.imageGenerationConfigs.jpegChroma, - pngFilter: _configs.imageGenerationConfigs.pngFilter, - pngLevel: _configs.imageGenerationConfigs.pngLevel, + outputFormat: _configs.imageGeneration.outputFormat, + singleFrame: _configs.imageGeneration.singleFrame, + jpegQuality: _configs.imageGeneration.jpegQuality, + jpegChroma: _configs.imageGeneration.jpegChroma, + pngFilter: _configs.imageGeneration.pngFilter, + pngLevel: _configs.imageGeneration.pngLevel, ); } } diff --git a/lib/utils/content_recorder.dart/threads_managers/isolate/isolate_manager.dart b/lib/utils/content_recorder.dart/threads_managers/isolate/isolate_manager.dart index 73aeb84e..8c996e3a 100644 --- a/lib/utils/content_recorder.dart/threads_managers/isolate/isolate_manager.dart +++ b/lib/utils/content_recorder.dart/threads_managers/isolate/isolate_manager.dart @@ -19,10 +19,10 @@ class IsolateManager extends ThreadManager { @override void init(ProImageEditorConfigs configs) async { - processorConfigs = configs.imageGenerationConfigs.processorConfigs; + processorConfigs = configs.imageGeneration.processorConfigs; int processors = getNumberOfProcessors( - configs: configs.imageGenerationConfigs.processorConfigs, + configs: configs.imageGeneration.processorConfigs, deviceNumberOfProcessors: Platform.numberOfProcessors, ); for (var i = 0; i < processors && !isDestroyed; i++) { diff --git a/lib/utils/content_recorder.dart/threads_managers/web_worker/web_worker_manager.dart b/lib/utils/content_recorder.dart/threads_managers/web_worker/web_worker_manager.dart index 007f0555..c074e2a5 100644 --- a/lib/utils/content_recorder.dart/threads_managers/web_worker/web_worker_manager.dart +++ b/lib/utils/content_recorder.dart/threads_managers/web_worker/web_worker_manager.dart @@ -24,10 +24,10 @@ class WebWorkerManager extends ThreadManager { @override void init(ProImageEditorConfigs configs) { - processorConfigs = configs.imageGenerationConfigs.processorConfigs; + processorConfigs = configs.imageGeneration.processorConfigs; int processors = getNumberOfProcessors( - configs: configs.imageGenerationConfigs.processorConfigs, + configs: configs.imageGeneration.processorConfigs, deviceNumberOfProcessors: _deviceNumberOfProcessors(), ); diff --git a/lib/utils/content_recorder.dart/utils/generate_high_quality_image.dart b/lib/utils/content_recorder.dart/utils/generate_high_quality_image.dart index 63b697be..8260af83 100644 --- a/lib/utils/content_recorder.dart/utils/generate_high_quality_image.dart +++ b/lib/utils/content_recorder.dart/utils/generate_high_quality_image.dart @@ -37,7 +37,7 @@ Future generateHighQualityImage( }) async { var recorder = ContentRecorderController( configs: ProImageEditorConfigs( - imageGenerationConfigs: configs.copyWith( + imageGeneration: configs.copyWith( processorConfigs: configs.processorConfigs.copyWith( processorMode: ProcessorMode.minimum, ), diff --git a/lib/widgets/adaptive_dialog.dart b/lib/widgets/adaptive_dialog.dart index 25302074..f182ae47 100644 --- a/lib/widgets/adaptive_dialog.dart +++ b/lib/widgets/adaptive_dialog.dart @@ -4,7 +4,8 @@ import 'package:flutter/material.dart'; // Project imports: import 'package:pro_image_editor/utils/design_mode.dart'; -import '../models/theme/theme.dart'; + +import '../models/styles/adaptive_dialog_style.dart'; /// A dialog that adapts its appearance based on the design mode. class AdaptiveDialog extends StatefulWidget { @@ -15,7 +16,7 @@ class AdaptiveDialog extends StatefulWidget { /// The [actions] is a list of [AdaptiveDialogAction] widgets to include as /// buttons. /// The [brightness] controls the brightness of the dialog. - /// The [imageEditorTheme] is the theme specific to the image editor. + /// The [style] is the theme specific to the image editor. const AdaptiveDialog({ super.key, required this.designMode, @@ -23,7 +24,7 @@ class AdaptiveDialog extends StatefulWidget { required this.content, required this.actions, required this.brightness, - required this.imageEditorTheme, + required this.style, }); /// The design mode to determine the appearance of the dialog. @@ -42,7 +43,7 @@ class AdaptiveDialog extends StatefulWidget { final Brightness brightness; /// Theme from the image editor. - final ImageEditorTheme imageEditorTheme; + final AdaptiveDialogStyle style; @override State createState() => _AdaptiveDialogState(); @@ -58,17 +59,13 @@ class _AdaptiveDialogState extends State { data: CupertinoTheme.of(context).copyWith( brightness: widget.brightness, primaryColor: widget.brightness == Brightness.dark - ? widget.imageEditorTheme.adaptiveDialogTheme - .cupertinoPrimaryColorDark - : widget.imageEditorTheme.adaptiveDialogTheme - .cupertinoPrimaryColorLight, + ? widget.style.cupertinoPrimaryColorDark + : widget.style.cupertinoPrimaryColorLight, textTheme: CupertinoTextThemeData( textStyle: TextStyle( color: widget.brightness == Brightness.dark - ? widget.imageEditorTheme.adaptiveDialogTheme - .cupertinoPrimaryColorDark - : widget.imageEditorTheme.adaptiveDialogTheme - .cupertinoPrimaryColorLight, + ? widget.style.cupertinoPrimaryColorDark + : widget.style.cupertinoPrimaryColorLight, ), ), ), diff --git a/lib/widgets/extended/extended_custom_paint.dart b/lib/widgets/extended/extended_custom_paint.dart index 01bf9341..292be5fb 100644 --- a/lib/widgets/extended/extended_custom_paint.dart +++ b/lib/widgets/extended/extended_custom_paint.dart @@ -2,12 +2,12 @@ import 'package:flutter/widgets.dart'; /// [ExtendedCustomPaint] is a stateful widget that allows you to use -/// custom painting within a widget. It extends the functionality of -/// [CustomPaint] by providing methods to update the painting properties +/// custom paint within a widget. It extends the functionality of +/// [CustomPaint] by providing methods to update the paint properties /// without rebuilding the child widget. /// /// This is useful for scenarios where you need to dynamically update -/// painting properties such as the [painter], [foregroundPainter], +/// paint properties such as the [painter], [foregroundPainter], /// [isComplex], and [willChange] flags without affecting the child widget. /// /// The [initIsComplex] and [initWillChange] parameters set the initial values @@ -26,10 +26,10 @@ class ExtendedCustomPaint extends StatefulWidget { required this.child, }); - /// Initial value for whether the painting is complex. + /// Initial value for whether the paint-item is complex. final bool initIsComplex; - /// Initial value for whether the painting will change. + /// Initial value for whether the paint-item will change. final bool initWillChange; /// Initial custom painter for the foreground. @@ -45,13 +45,13 @@ class ExtendedCustomPaint extends StatefulWidget { State createState() => ExtendedCustomPaintState(); } -/// The state for [ExtendedCustomPaint], managing the painting logic and +/// The state for [ExtendedCustomPaint], managing the paint logic and /// properties. class ExtendedCustomPaintState extends State { - /// Indicates whether the painting is complex. + /// Indicates whether the paint-item is complex. late bool isComplex; - /// Determines if the painting will change. + /// Determines if the paint-item will change. late bool willChange; /// The painter used for drawing on the foreground. @@ -81,10 +81,10 @@ class ExtendedCustomPaintState extends State { } /// Updates the properties of the [CustomPaint] widget and triggers a - /// rebuild of the painting without affecting the child widget. + /// rebuild of the paint without affecting the child widget. /// - /// [isComplex] - Optional new value for whether the painting is complex. - /// [willChange] - Optional new value for whether the painting will change. + /// [isComplex] - Optional new value for whether the paint is complex. + /// [willChange] - Optional new value for whether the paint will change. /// [foregroundPainter] - Optional new foreground painter. /// [painter] - Optional new painter. void update({ diff --git a/lib/widgets/layer_interaction_helper/layer_interaction_border_painter.dart b/lib/widgets/layer_interaction_helper/layer_interaction_border_painter.dart index e4c61cad..65ab0ad6 100644 --- a/lib/widgets/layer_interaction_helper/layer_interaction_border_painter.dart +++ b/lib/widgets/layer_interaction_helper/layer_interaction_border_painter.dart @@ -5,7 +5,7 @@ import 'dart:math'; import 'package:flutter/widgets.dart'; // Project imports: -import 'package:pro_image_editor/models/theme/theme_layer_interaction.dart'; +import 'package:pro_image_editor/models/styles/layer_interaction_style.dart'; /// A custom painter for rendering the border of a layer interaction area. /// @@ -34,7 +34,7 @@ class LayerInteractionBorderPainter extends CustomPainter { /// /// This theme provides color, opacity, and other styling options for the /// layer border, ensuring it matches the overall design of the application. - final ThemeLayerInteraction theme; + final LayerInteractionStyle theme; /// The style of the layer interaction border. /// diff --git a/lib/widgets/layer_interaction_helper/layer_interaction_helper_widget.dart b/lib/widgets/layer_interaction_helper/layer_interaction_helper_widget.dart index 271cc53f..97e75054 100644 --- a/lib/widgets/layer_interaction_helper/layer_interaction_helper_widget.dart +++ b/lib/widgets/layer_interaction_helper/layer_interaction_helper_widget.dart @@ -165,20 +165,19 @@ class _LayerInteractionHelperWidgetState return DeferPointer(child: widget.child); } return TooltipVisibility( - visible: - _tooltipVisible && imageEditorTheme.layerInteraction.showTooltips, + visible: _tooltipVisible && layerInteraction.style.showTooltips, child: DeferPointer( child: Stack( children: [ Container( margin: EdgeInsets.all( - imageEditorTheme.layerInteraction.buttonRadius + - imageEditorTheme.layerInteraction.strokeWidth * 2, + layerInteraction.style.buttonRadius + + layerInteraction.style.strokeWidth * 2, ), child: CustomPaint( foregroundPainter: LayerInteractionBorderPainter( - theme: imageEditorTheme.layerInteraction, - borderStyle: imageEditorTheme.layerInteraction.borderStyle, + theme: layerInteraction.style, + borderStyle: layerInteraction.style.borderStyle, ), child: widget.child, ), @@ -197,7 +196,7 @@ class _LayerInteractionHelperWidgetState } Widget _buildRotateScaleIcon() { - return customWidgets.layerInteraction.rotateScaleIcon?.call( + return layerInteraction.widgets.rotateScaleIcon?.call( _rebuildStream.stream, (value) => widget.onScaleRotateDown?.call(value), (value) => widget.onScaleRotateUp?.call(value), @@ -212,19 +211,18 @@ class _LayerInteractionHelperWidgetState rotation: -widget.layerData.rotation, onScaleRotateDown: widget.onScaleRotateDown, onScaleRotateUp: widget.onScaleRotateUp, - buttonRadius: imageEditorTheme.layerInteraction.buttonRadius, - cursor: imageEditorTheme.layerInteraction.rotateScaleCursor, - icon: icons.layerInteraction.rotateScale, + buttonRadius: layerInteraction.style.buttonRadius, + cursor: layerInteraction.style.rotateScaleCursor, + icon: layerInteraction.icons.rotateScale, tooltip: i18n.layerInteraction.rotateScale, - color: imageEditorTheme.layerInteraction.buttonScaleRotateColor, - background: - imageEditorTheme.layerInteraction.buttonScaleRotateBackground, + color: layerInteraction.style.buttonScaleRotateColor, + background: layerInteraction.style.buttonScaleRotateBackground, ), ); } Widget _buildEditIcon() { - return customWidgets.layerInteraction.editIcon?.call( + return layerInteraction.widgets.editIcon?.call( _rebuildStream.stream, () => widget.onEditLayer?.call(), toggleTooltipVisibility, @@ -237,19 +235,18 @@ class _LayerInteractionHelperWidgetState toggleTooltipVisibility: toggleTooltipVisibility, rotation: -widget.layerData.rotation, onTap: widget.onEditLayer, - buttonRadius: imageEditorTheme.layerInteraction.buttonRadius, - cursor: imageEditorTheme.layerInteraction.editCursor, - icon: icons.layerInteraction.edit, + buttonRadius: layerInteraction.style.buttonRadius, + cursor: layerInteraction.style.editCursor, + icon: layerInteraction.icons.edit, tooltip: i18n.layerInteraction.edit, - color: imageEditorTheme.layerInteraction.buttonEditTextColor, - background: - imageEditorTheme.layerInteraction.buttonEditTextBackground, + color: layerInteraction.style.buttonEditTextColor, + background: layerInteraction.style.buttonEditTextBackground, ), ); } Widget _buildRemoveIcon() { - return customWidgets.layerInteraction.removeIcon?.call( + return layerInteraction.widgets.removeIcon?.call( _rebuildStream.stream, () => widget.onRemoveLayer?.call(), toggleTooltipVisibility, @@ -262,13 +259,12 @@ class _LayerInteractionHelperWidgetState toggleTooltipVisibility: toggleTooltipVisibility, rotation: -widget.layerData.rotation, onTap: widget.onRemoveLayer, - buttonRadius: imageEditorTheme.layerInteraction.buttonRadius, - cursor: imageEditorTheme.layerInteraction.removeCursor, - icon: icons.layerInteraction.remove, + buttonRadius: layerInteraction.style.buttonRadius, + cursor: layerInteraction.style.removeCursor, + icon: layerInteraction.icons.remove, tooltip: i18n.layerInteraction.remove, - color: imageEditorTheme.layerInteraction.buttonRemoveColor, - background: - imageEditorTheme.layerInteraction.buttonRemoveBackground, + color: layerInteraction.style.buttonRemoveColor, + background: layerInteraction.style.buttonRemoveBackground, ), ); } diff --git a/lib/widgets/layer_stack.dart b/lib/widgets/layer_stack.dart index 3ee3251b..bc28528c 100644 --- a/lib/widgets/layer_stack.dart +++ b/lib/widgets/layer_stack.dart @@ -100,7 +100,7 @@ class _LayerStackState extends State { // Determine whether to cut content outside the image area based on widget // settings. _cutOutsideImageArea = widget.cutOutsideImageArea ?? - widget.configs.imageGenerationConfigs.captureOnlyBackgroundImageArea; + widget.configs.imageGeneration.captureOnlyBackgroundImageArea; super.initState(); } @@ -135,22 +135,21 @@ class _LayerStackState extends State { }).toList()), ), ), - if (widget - .configs.imageGenerationConfigs.captureOnlyBackgroundImageArea) + if (widget.configs.imageGeneration.captureOnlyBackgroundImageArea) RepaintBoundary( child: Hero( tag: 'crop_layer_painter_hero', child: CustomPaint( foregroundPainter: _cutOutsideImageArea ? CropLayerPainter( - opacity: widget.configs.imageEditorTheme + opacity: widget.configs.mainEditor.style .outsideCaptureAreaLayerOpacity, backgroundColor: - widget.configs.imageEditorTheme.background, + widget.configs.cropRotateEditor.style.background, imgRatio: transformConfigs?.cropRect.size.aspectRatio ?? widget.transformHelper.mainImageSize.aspectRatio, isRoundCropper: - widget.configs.cropRotateEditorConfigs.roundCropper, + widget.configs.cropRotateEditor.roundCropper, is90DegRotated: transformConfigs?.is90DegRotated ?? false, ) diff --git a/lib/widgets/layer_widget.dart b/lib/widgets/layer_widget.dart index 77036241..126ea642 100644 --- a/lib/widgets/layer_widget.dart +++ b/lib/widgets/layer_widget.dart @@ -145,7 +145,7 @@ class _LayerWidgetState extends State case const (StickerLayerData): _layerType = _LayerType.sticker; break; - case const (PaintingLayerData): + case const (PaintLayerData): _layerType = _LayerType.canvas; break; default: @@ -214,7 +214,7 @@ class _LayerWidgetState extends State /// Checks if the hit is outside the canvas for certain types of layers. bool _checkHitIsOutsideInCanvas() { return _layerType == _LayerType.canvas && - !(_layer as PaintingLayerData).item.hit; + !(_layer as PaintLayerData).item.hit; } /// Calculates the transformation matrix for the layer's position and @@ -279,7 +279,7 @@ class _LayerWidgetState extends State child: MouseRegion( hitTestBehavior: HitTestBehavior.translucent, cursor: _showMoveCursor - ? imageEditorTheme.layerInteraction.hoverCursor + ? layerInteraction.style.hoverCursor : MouseCursor.defer, onEnter: (event) { if (_layerType != _LayerType.canvas) { @@ -290,7 +290,7 @@ class _LayerWidgetState extends State }, onExit: (event) { if (_layerType == _LayerType.canvas) { - (widget.layerData as PaintingLayerData).item.hit = false; + (widget.layerData as PaintLayerData).item.hit = false; } else { setState(() { _showMoveCursor = false; @@ -394,7 +394,7 @@ class _LayerWidgetState extends State child: Text( layer.emoji.toString(), textAlign: TextAlign.center, - style: imageEditorTheme.emojiEditor.textStyle.copyWith( + style: emojiEditorConfigs.style.textStyle.copyWith( fontSize: textEditorConfigs.initFontSize * _layer.scale, ), ), @@ -405,7 +405,7 @@ class _LayerWidgetState extends State Widget _buildSticker() { var layer = _layer as StickerLayerData; return SizedBox( - width: (stickerEditorConfigs?.initWidth ?? 100) * layer.scale, + width: stickerEditorConfigs.initWidth * layer.scale, child: FittedBox( fit: BoxFit.contain, child: layer.sticker, @@ -415,7 +415,7 @@ class _LayerWidgetState extends State /// Build the canvas widget Widget _buildCanvas() { - var layer = _layer as PaintingLayerData; + var layer = _layer as PaintLayerData; return Padding( // Better hit detection for mobile devices padding: EdgeInsets.all(isDesktop ? 0 : 15), @@ -426,7 +426,7 @@ class _LayerWidgetState extends State size: layer.size, willChange: false, isComplex: layer.item.mode == PaintModeE.freeStyle, - painter: DrawPainting( + painter: DrawPaintItem( item: layer.item, scale: widget.layerData.scale, selected: widget.selected, diff --git a/lib/widgets/overlays/loading_dialog/loading_dialog.dart b/lib/widgets/overlays/loading_dialog/loading_dialog.dart index 62456ea6..01d5ae3e 100644 --- a/lib/widgets/overlays/loading_dialog/loading_dialog.dart +++ b/lib/widgets/overlays/loading_dialog/loading_dialog.dart @@ -65,8 +65,8 @@ class LoadingDialog extends ChangeNotifier { /// Remove the overlay after the animation is done. _removeOverlay(); }, - child: configs.customWidgets.loadingDialog != null - ? configs.customWidgets.loadingDialog!(message!, configs) + child: configs.dialogConfigs.widgets.loadingDialog != null + ? configs.dialogConfigs.widgets.loadingDialog!(message!, configs) : Stack( children: [ _buildBackdrop(context, isDismissible), @@ -182,15 +182,15 @@ class LoadingDialog extends ChangeNotifier { brightness: theme.brightness, primaryColor: theme.brightness == Brightness.dark ? configs - .imageEditorTheme.loadingDialogTheme.cupertinoPrimaryColorDark + .dialogConfigs.style.loadingDialog.cupertinoPrimaryColorDark : configs - .imageEditorTheme.loadingDialogTheme.cupertinoPrimaryColorLight, + .dialogConfigs.style.loadingDialog.cupertinoPrimaryColorLight, textTheme: CupertinoTextThemeData( textStyle: TextStyle( color: theme.brightness == Brightness.dark - ? configs.imageEditorTheme.loadingDialogTheme - .cupertinoPrimaryColorDark - : configs.imageEditorTheme.loadingDialogTheme + ? configs + .dialogConfigs.style.loadingDialog.cupertinoPrimaryColorDark + : configs.dialogConfigs.style.loadingDialog .cupertinoPrimaryColorLight, ), ), @@ -235,7 +235,7 @@ class LoadingDialog extends ChangeNotifier { configs.designMode, ).copyWith( fontSize: 16, - color: configs.imageEditorTheme.loadingDialogTheme.textColor, + color: configs.dialogConfigs.style.loadingDialog.textColor, ), textAlign: TextAlign.start, ), diff --git a/lib/widgets/platform_circular_progress_indicator.dart b/lib/widgets/platform_circular_progress_indicator.dart index 3a14867b..67ce59e9 100644 --- a/lib/widgets/platform_circular_progress_indicator.dart +++ b/lib/widgets/platform_circular_progress_indicator.dart @@ -27,7 +27,8 @@ class _PlatformCircularProgressIndicatorState @override Widget build(BuildContext context) { // Conditionally choose the progress indicator based on the platform. - return widget.configs.customWidgets.circularProgressIndicator ?? + return widget.configs.progressIndicatorConfigs.widgets + .circularProgressIndicator ?? (widget.configs.designMode == ImageEditorDesignModeE.material ? const CircularProgressIndicator() : const CupertinoActivityIndicator()); diff --git a/lib/widgets/transform/transformed_content_generator.dart b/lib/widgets/transform/transformed_content_generator.dart index 16b8ddf7..4fe44676 100644 --- a/lib/widgets/transform/transformed_content_generator.dart +++ b/lib/widgets/transform/transformed_content_generator.dart @@ -138,7 +138,7 @@ class _TransformedContentGeneratorState Widget _buildCropPainter({required Widget child}) { CutOutsideArea clipper = CutOutsideArea(configs: widget.transformConfigs); - if (widget.configs.cropRotateEditorConfigs.roundCropper) { + if (widget.configs.cropRotateEditor.roundCropper) { return ClipOval(clipper: clipper, child: child); } else { return ClipRect(clipper: clipper, child: child); diff --git a/pubspec.yaml b/pubspec.yaml index 1444f8e8..b95e6f75 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pro_image_editor description: "A Flutter image editor: Seamlessly enhance your images with user-friendly editing features." -version: 6.2.3 +version: 7.0.0 homepage: https://github.com/hm21/pro_image_editor/ repository: https://github.com/hm21/pro_image_editor/ issue_tracker: https://github.com/hm21/pro_image_editor/issues/ diff --git a/test/modules/crop_rotate_editor/crop_rotate_editor_test.dart b/test/modules/crop_rotate_editor/crop_rotate_editor_test.dart index 8e7a9916..8ca9a991 100644 --- a/test/modules/crop_rotate_editor/crop_rotate_editor_test.dart +++ b/test/modules/crop_rotate_editor/crop_rotate_editor_test.dart @@ -17,13 +17,13 @@ void main() { theme: ThemeData.light(), enableFakeHero: false, configs: const ProImageEditorConfigs( - cropRotateEditorConfigs: CropRotateEditorConfigs( + cropRotateEditor: CropRotateEditorConfigs( animationDuration: Duration.zero, cropDragAnimationDuration: Duration.zero, fadeInOutsideCropAreaAnimationDuration: Duration.zero, opacityOutsideCropAreaDuration: Duration.zero, ), - imageGenerationConfigs: ImageGenerationConfigs( + imageGeneration: ImageGenerationConfigs( generateImageInBackground: false, generateInsideSeparateThread: false, ), diff --git a/test/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options_test.dart b/test/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options_test.dart index c24b0dc6..94927845 100644 --- a/test/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options_test.dart +++ b/test/modules/crop_rotate_editor/widgets/crop_aspect_ratio_options_test.dart @@ -25,8 +25,7 @@ void main() { aspectRatio: 1.0, originalAspectRatio: 1.0, configs: ProImageEditorConfigs( - cropRotateEditorConfigs: - CropRotateEditorConfigs(aspectRatios: [ + cropRotateEditor: CropRotateEditorConfigs(aspectRatios: [ AspectRatioItem(text: ratioText, value: 1), ])), ), diff --git a/test/modules/crop_rotate_editor/widgets/crop_corner_painter_test.dart b/test/modules/crop_rotate_editor/widgets/crop_corner_painter_test.dart index f355b317..0c81f1eb 100644 --- a/test/modules/crop_rotate_editor/widgets/crop_corner_painter_test.dart +++ b/test/modules/crop_rotate_editor/widgets/crop_corner_painter_test.dart @@ -16,32 +16,30 @@ void main() { const Size screenSize = Size(400, 400); final painter1 = CropCornerPainter( - cropRect: cropRect, - viewRect: viewRect, - screenSize: screenSize, - imageEditorTheme: const ImageEditorTheme(), - drawCircle: false, - offset: Offset.zero, - interactionOpacity: 0, - fadeInOpacity: 0.5, - cornerLength: 20.0, - rotationScaleFactor: 1.0, - scaleFactor: 1.0, - cornerThickness: 6); + cropRect: cropRect, + viewRect: viewRect, + screenSize: screenSize, + style: const CropRotateEditorStyle(), + drawCircle: false, + offset: Offset.zero, + interactionOpacity: 0, + fadeInOpacity: 0.5, + rotationScaleFactor: 1.0, + scaleFactor: 1.0, + ); final painter2 = CropCornerPainter( - cropRect: cropRect.translate(10, 20), // Changed property - viewRect: viewRect, - screenSize: screenSize, - imageEditorTheme: const ImageEditorTheme(), - drawCircle: false, - offset: Offset.zero, - fadeInOpacity: 0.5, - interactionOpacity: 0, - cornerLength: 20.0, - rotationScaleFactor: 1.0, - scaleFactor: 1.0, - cornerThickness: 6); + cropRect: cropRect.translate(10, 20), // Changed property + viewRect: viewRect, + screenSize: screenSize, + style: const CropRotateEditorStyle(), + drawCircle: false, + offset: Offset.zero, + fadeInOpacity: 0.5, + interactionOpacity: 0, + rotationScaleFactor: 1.0, + scaleFactor: 1.0, + ); expect(painter1.shouldRepaint(painter2), isTrue); }); diff --git a/test/modules/paint_editor/paint_editor_test.dart b/test/modules/paint_editor/paint_editor_test.dart index 89635c9f..78e7001f 100644 --- a/test/modules/paint_editor/paint_editor_test.dart +++ b/test/modules/paint_editor/paint_editor_test.dart @@ -8,16 +8,16 @@ import 'package:network_image_mock/network_image_mock.dart'; // Project imports: import 'package:pro_image_editor/models/init_configs/paint_editor_init_configs.dart'; import 'package:pro_image_editor/modules/paint_editor/paint_editor.dart'; -import 'package:pro_image_editor/modules/paint_editor/widgets/painting_canvas.dart'; +import 'package:pro_image_editor/modules/paint_editor/widgets/paint_canvas.dart'; import 'package:pro_image_editor/widgets/color_picker/bar_color_picker.dart'; import '../../fake/fake_image.dart'; void main() { - group('PaintingEditor Tests', () { + group('PaintEditor Tests', () { testWidgets('Initializes with memory constructor', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, initConfigs: PaintEditorInitConfigs( theme: ThemeData(), @@ -25,13 +25,13 @@ void main() { ), )); - expect(find.byType(PaintingEditor), findsOneWidget); + expect(find.byType(PaintEditor), findsOneWidget); }); testWidgets('Initializes with network constructor', (WidgetTester tester) async { await mockNetworkImagesFor(() async { await tester.pumpWidget(MaterialApp( - home: PaintingEditor.network( + home: PaintEditor.network( fakeNetworkImage, initConfigs: PaintEditorInitConfigs( theme: ThemeData(), @@ -39,13 +39,13 @@ void main() { ), )); - expect(find.byType(PaintingEditor), findsOneWidget); + expect(find.byType(PaintEditor), findsOneWidget); }); }); testWidgets('should render BarColorPicker', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, initConfigs: PaintEditorInitConfigs( theme: ThemeData(), @@ -55,9 +55,9 @@ void main() { expect(find.byType(BarColorPicker), findsOneWidget); }); - testWidgets('should render PaintingCanvas', (WidgetTester tester) async { + testWidgets('should render Canvas', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, initConfigs: PaintEditorInitConfigs( theme: ThemeData(), @@ -65,12 +65,12 @@ void main() { ), )); - expect(find.byType(PaintingCanvas), findsOneWidget); + expect(find.byType(PaintCanvas), findsOneWidget); }); - testWidgets('should change painting-mode', (WidgetTester tester) async { - var key = GlobalKey(); + testWidgets('should change paint-mode', (WidgetTester tester) async { + var key = GlobalKey(); await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, key: key, initConfigs: PaintEditorInitConfigs( @@ -90,9 +90,9 @@ void main() { expect(key.currentState!.paintMode, PaintModeE.arrow); }); testWidgets('should change stroke width', (WidgetTester tester) async { - var key = GlobalKey(); + var key = GlobalKey(); await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, key: key, initConfigs: PaintEditorInitConfigs( @@ -108,9 +108,9 @@ void main() { } }); testWidgets('should toggle fill state', (WidgetTester tester) async { - var key = GlobalKey(); + var key = GlobalKey(); await tester.pumpWidget(MaterialApp( - home: PaintingEditor.memory( + home: PaintEditor.memory( fakeMemoryImage, key: key, initConfigs: PaintEditorInitConfigs( diff --git a/test/modules/paint_editor/painting_canvas_test.dart b/test/modules/paint_editor/painting_canvas_test.dart index df87121d..17a36106 100644 --- a/test/modules/paint_editor/painting_canvas_test.dart +++ b/test/modules/paint_editor/painting_canvas_test.dart @@ -7,15 +7,15 @@ import 'package:flutter_test/flutter_test.dart'; // Project imports: import 'package:pro_image_editor/modules/paint_editor/utils/paint_controller.dart'; import 'package:pro_image_editor/modules/paint_editor/utils/paint_editor_enum.dart'; -import 'package:pro_image_editor/modules/paint_editor/widgets/painting_canvas.dart'; +import 'package:pro_image_editor/modules/paint_editor/widgets/paint_canvas.dart'; void main() { - group('PaintingCanvas Tests', () { + group('PaintCanvas Tests', () { testWidgets( - 'Handles gestures and updates painting in paintings with start/stop offsets', + 'Handles gestures and updates paint-items with start/stop offsets', (WidgetTester tester) async { - final GlobalKey canvasKey = GlobalKey(); - PaintingController ctrl = PaintingController( + final GlobalKey canvasKey = GlobalKey(); + PaintController ctrl = PaintController( color: Colors.red, mode: PaintModeE.arrow, fill: false, @@ -26,7 +26,7 @@ void main() { await tester.pumpWidget( MaterialApp( home: Scaffold( - body: PaintingCanvas( + body: PaintCanvas( key: canvasKey, drawAreaSize: const Size(1000, 1000), paintCtrl: ctrl, @@ -60,10 +60,10 @@ void main() { expect(ctrl.canUndo, isTrue); }); - testWidgets('Handles gestures and updates painting in freestyle-paintings', + testWidgets('Handles gestures and updates paint-items in freestyle-mode', (WidgetTester tester) async { - final GlobalKey canvasKey = GlobalKey(); - PaintingController ctrl = PaintingController( + final GlobalKey canvasKey = GlobalKey(); + PaintController ctrl = PaintController( color: Colors.red, mode: PaintModeE.freeStyle, fill: false, @@ -74,7 +74,7 @@ void main() { await tester.pumpWidget( MaterialApp( home: Scaffold( - body: PaintingCanvas( + body: PaintCanvas( key: canvasKey, drawAreaSize: const Size(1000, 1000), paintCtrl: ctrl, @@ -107,7 +107,7 @@ void main() { }); testWidgets('Performs undo and redo actions', (WidgetTester tester) async { - PaintingController ctrl = PaintingController( + PaintController ctrl = PaintController( color: Colors.red, mode: PaintModeE.arrow, fill: false, @@ -119,7 +119,7 @@ void main() { await tester.pumpWidget( MaterialApp( home: Scaffold( - body: PaintingCanvas( + body: PaintCanvas( drawAreaSize: const Size(200, 200), paintCtrl: ctrl, ), diff --git a/test/modules/paint_editor/utils/draw/draw_canvas_test.dart b/test/modules/paint_editor/utils/draw/draw_canvas_test.dart index 00cd1a18..16ef5492 100644 --- a/test/modules/paint_editor/utils/draw/draw_canvas_test.dart +++ b/test/modules/paint_editor/utils/draw/draw_canvas_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; // Project imports: import 'package:pro_image_editor/models/paint_editor/painted_model.dart'; import 'package:pro_image_editor/modules/paint_editor/utils/paint_editor_enum.dart'; -import 'package:pro_image_editor/modules/paint_editor/widgets/draw_painting.dart'; +import 'package:pro_image_editor/modules/paint_editor/widgets/draw_paint_item.dart'; void main() { testWidgets('DrawCanvas should handle hit testing for different modes', @@ -38,7 +38,7 @@ void main() { MaterialApp( home: Scaffold( body: CustomPaint( - painter: DrawPainting( + painter: DrawPaintItem( item: paintedModel, scale: 1.0, enabledHitDetection: true, diff --git a/test/modules/paint_editor/utils/paint_controller_test.dart b/test/modules/paint_editor/utils/paint_controller_test.dart index 9a0d0b71..0c48a134 100644 --- a/test/modules/paint_editor/utils/paint_controller_test.dart +++ b/test/modules/paint_editor/utils/paint_controller_test.dart @@ -10,8 +10,8 @@ import 'package:pro_image_editor/modules/paint_editor/utils/paint_controller.dar import 'package:pro_image_editor/modules/paint_editor/utils/paint_editor_enum.dart'; void main() { - test('PaintingController initializes with correct values', () { - final controller = PaintingController( + test('PaintController initializes with correct values', () { + final controller = PaintController( strokeWidth: 2.0, color: Colors.red, mode: PaintModeE.line, @@ -26,8 +26,8 @@ void main() { expect(controller.fill, false); }); - test('Add and retrieve painted models in painting history', () { - final controller = PaintingController( + test('Add and retrieve painted models in paint history', () { + final controller = PaintController( strokeWidth: 2.0, color: Colors.red, mode: PaintModeE.line, @@ -46,11 +46,11 @@ void main() { controller.addPaintInfo(paintedModel); - expect(controller.activePaintings, [paintedModel]); + expect(controller.activePaintItemList, [paintedModel]); }); - test('Undo and redo painting actions', () { - final controller = PaintingController( + test('Undo and redo paint actions', () { + final controller = PaintController( strokeWidth: 2.0, color: Colors.red, mode: PaintModeE.line, @@ -79,11 +79,11 @@ void main() { ..addPaintInfo(paintedModel1) ..addPaintInfo(paintedModel2) ..undo(); - expect(controller.activePaintings, [paintedModel1]); + expect(controller.activePaintItemList, [paintedModel1]); expect(controller.historyPosition, 1); controller.redo(); - expect(controller.activePaintings, [paintedModel1, paintedModel2]); + expect(controller.activePaintItemList, [paintedModel1, paintedModel2]); expect(controller.historyPosition, 2); }); } diff --git a/test/modules/sticker_editor_test.dart b/test/modules/sticker_editor_test.dart index 0f2b16ea..1f07c6d6 100644 --- a/test/modules/sticker_editor_test.dart +++ b/test/modules/sticker_editor_test.dart @@ -14,7 +14,7 @@ void main() { home: StickerEditor( scrollController: ScrollController(), configs: ProImageEditorConfigs( - stickerEditorConfigs: StickerEditorConfigs( + stickerEditor: StickerEditorConfigs( enabled: true, buildStickers: (setLayer, scrollController) { return Container(); diff --git a/test/pro_image_editor_test.dart b/test/pro_image_editor_test.dart index affe63a9..0042eff3 100644 --- a/test/pro_image_editor_test.dart +++ b/test/pro_image_editor_test.dart @@ -14,10 +14,12 @@ import 'fake/fake_image.dart'; void main() { ProImageEditorConfigs configs = const ProImageEditorConfigs( - customWidgets: ImageEditorCustomWidgets( - circularProgressIndicator: SizedBox.shrink(), + progressIndicatorConfigs: ProgressIndicatorConfigs( + widgets: ProgressIndicatorWidgets( + circularProgressIndicator: SizedBox.shrink(), + ), ), - imageGenerationConfigs: ImageGenerationConfigs( + imageGeneration: ImageGenerationConfigs( generateInsideSeparateThread: false, generateImageInBackground: false, ), @@ -93,7 +95,7 @@ void main() { }); group('ProImageEditor open subeditors', () { - testWidgets('ProImageEditor opens PaintingEditor', + testWidgets('ProImageEditor opens PaintEditor', (WidgetTester tester) async { final key = GlobalKey(); await tester.pumpWidget( @@ -109,12 +111,12 @@ void main() { ), ); - final openBtn = find.byKey(const ValueKey('open-painting-editor-btn')); + final openBtn = find.byKey(const ValueKey('open-paint-editor-btn')); expect(openBtn, findsOneWidget); await tester.tap(openBtn); await tester.pumpAndSettle(); - expect(find.byType(PaintingEditor), findsOneWidget); + expect(find.byType(PaintEditor), findsOneWidget); }); testWidgets('ProImageEditor opens TextEditor', (WidgetTester tester) async { @@ -211,20 +213,17 @@ void main() { onImageEditingComplete: (Uint8List bytes) async {}, ), configs: ProImageEditorConfigs( - paintEditorConfigs: const PaintEditorConfigs(enabled: false), - textEditorConfigs: const TextEditorConfigs(enabled: false), - cropRotateEditorConfigs: - const CropRotateEditorConfigs(enabled: false), - emojiEditorConfigs: const EmojiEditorConfigs( + paintEditor: const PaintEditorConfigs(enabled: false), + textEditor: const TextEditorConfigs(enabled: false), + cropRotateEditor: const CropRotateEditorConfigs(enabled: false), + emojiEditor: const EmojiEditorConfigs( enabled: false, ), - stickerEditorConfigs: StickerEditorConfigs( + stickerEditor: StickerEditorConfigs( enabled: true, buildStickers: (setLayer, scrollController) => Container(key: widgetKey), - ), - imageEditorTheme: ImageEditorTheme( - stickerEditor: StickerEditorTheme( + style: StickerEditorStyle( editorBoxConstraintsBuilder: (context, configs) => expectedConstraints, ), @@ -248,53 +247,6 @@ void main() { ); }); - testWidgets('ProImageEditor opens StickerEditor with global constraints', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: ProImageEditor.memory( - fakeMemoryImage, - callbacks: ProImageEditorCallbacks( - onImageEditingComplete: (Uint8List bytes) async {}, - ), - configs: ProImageEditorConfigs( - paintEditorConfigs: const PaintEditorConfigs(enabled: false), - textEditorConfigs: const TextEditorConfigs(enabled: false), - cropRotateEditorConfigs: - const CropRotateEditorConfigs(enabled: false), - emojiEditorConfigs: const EmojiEditorConfigs( - enabled: false, - ), - stickerEditorConfigs: StickerEditorConfigs( - enabled: true, - buildStickers: (setLayer, scrollController) => Container( - key: widgetKey, - ), - ), - imageEditorTheme: ImageEditorTheme( - editorBoxConstraintsBuilder: (context, configs) => - expectedConstraints, - ), - ), - ), - ), - ); - - final openBtn = find.byKey(const ValueKey('open-sticker-editor-btn')); - expect(openBtn, findsOneWidget); - await tester.tap(openBtn); - - // Wait for the modal bottom sheet animation to complete - await tester.pump(); // Start the animation - await tester.pump(const Duration(seconds: 1)); // Wait for it to finish - - expect(find.byKey(widgetKey), findsOneWidget); - expect( - tester.getRect(find.byKey(widgetKey)).width, - expectedConstraints.maxWidth, - ); - }); - testWidgets('ProImageEditor opens EmojiEditor with constraints', (WidgetTester tester) async { await tester.pumpWidget( @@ -302,44 +254,11 @@ void main() { home: ProImageEditor.memory( fakeMemoryImage, configs: ProImageEditorConfigs( - imageEditorTheme: ImageEditorTheme( - emojiEditor: EmojiEditorTheme( - editorBoxConstraintsBuilder: (context, configs) => - expectedConstraints, - )), - ), - callbacks: ProImageEditorCallbacks( - onImageEditingComplete: (Uint8List bytes) async {}, - ), - ), - ), - ); - - final openBtn = find.byKey(const ValueKey('open-emoji-editor-btn')); - expect(openBtn, findsOneWidget); - await tester.tap(openBtn); - - // Wait for the modal bottom sheet animation to complete - await tester.pump(); // Start the animation - await tester.pump(const Duration(seconds: 1)); // Wait for it to finish - - expect(find.byType(EmojiEditor), findsOneWidget); - expect( - tester.getRect(find.byType(EmojiEditor)).width, - expectedConstraints.maxWidth, - ); - }); - - testWidgets('ProImageEditor opens EmojiEditor with global constraints', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: ProImageEditor.memory( - fakeMemoryImage, - configs: ProImageEditorConfigs( - imageEditorTheme: ImageEditorTheme( - editorBoxConstraintsBuilder: (context, configs) => - expectedConstraints, + emojiEditor: EmojiEditorConfigs( + style: EmojiEditorStyle( + editorBoxConstraintsBuilder: (context, configs) => + expectedConstraints, + ), ), ), callbacks: ProImageEditorCallbacks(