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 @@
+
+
+
@@ -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