Skip to content

Commit ec47663

Browse files
authored
merge: pull request #607 from hm21/beta
release: promote v11.0.0 from beta to stable
2 parents f18275d + 573872a commit ec47663

File tree

123 files changed

+5380
-3805
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+5380
-3805
lines changed

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
# Changelog
22

3+
## 11.0.0
4+
- **FEAT**(multi-select): Layers can now be selected simultaneously using Ctrl, Shift, or long-press gestures.
5+
- **FEAT**(grouping): Layers can be grouped for unified selection and movement.
6+
- **FEAT**(main-editor): Added `selectAllLayers` and `unselectAllLayers` methods for bulk selection control.
7+
- **FEAT**(main-editor): Introduced `enableMultiSelectMode` to allow instant multi-selection without modifier keys.
8+
- **FEAT**(drag-selection): Added support for selecting multiple layers by dragging a rectangle around them.
9+
- **FEAT**(mouse-actions): Added support for different mouse button actions such as pan, multi-select, and drag-select.
10+
- **FEAT**(layer-configs): Added `enableKeyboardMultiSelection` and `enableLongPressMultiSelection` to `LayerInteractionConfigs` for dynamically enabling or disabling multi-selection via keyboard or long press.
11+
- **FEAT**(remove-area): Applied `AnimatedSwitcher` to the remove area for smooth fade-in/out transitions.
12+
- **FEAT**(crop-rotate-editor): Add `enableFlipAnimation` to `CropRotateEditorConfigs`, which enables flip animation by default.
13+
14+
<br/>
15+
16+
- **PERF**(GPU): Improved GPU performance by optimizing transformation and color filter matrices, especially beneficial when multiple filters or tune adjustments are applied.
17+
- **PERF**(CPU): Replace the `rounded_background_text` package-code with a custom solution that significantly improves the CPU usage required for drawing calculations.
18+
- **PERF**(RAM): Use cached sizes in the filter editor to display filter previews which reduce RAM usage.
19+
20+
<br/>
21+
22+
- **FIX**(rounded_background_text): Resolved issue where two text lines with nearly identical widths would not render with correct rounding; now ensures both lines are treated as equally long.
23+
- **FIX**(crop-rotate-editor): Resolve broken undo/redo functionality in the `CropRotateEditor`.
24+
25+
<br/>
26+
27+
#### Breaking Changes
28+
- Removed `layerIndex` from `onTapEditSticker` in `StickerEditorCallbacks`.
29+
- Removed `selectedLayerIndex` from `MainEditor`.
30+
- Remove `ColorFilterAddons.opacity`.
31+
- The way the editor handles multiple filters and tune adjustments has changed, so combinations might now appear slightly differently.
32+
- Removed `enableFreeStyleHighPerformanceScaling`, `enableFreeStyleHighPerformanceMoving` and `enableFreeStyleHighPerformanceHero` from `PaintEditorConfigs`.
33+
334
## 10.5.4
435
- **FEAT**(text-layers): Delete the edited 'TextLayers' if the new text is empty.
536

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ The ProImageEditor is a Flutter widget designed for image editing within your ap
163163
- 🖌️ **Hit Detection**: Paint layers support interactive selection.
164164
- 🔍 **Zoom Support**: Zoom in/out in both paint and main editor views.
165165
- 🖱️ **Enhanced Desktop UX**: Fine-tuned movement and scaling on desktop platforms.
166+
- 🧲 **Multiselect Support**: Select multiple elements at once.
166167

167168
### 🎨 Themes
168169

@@ -332,7 +333,6 @@ A big thanks to the authors of these amazing packages.
332333
- [emoji_picker_flutter](https://pub.dev/packages/emoji_picker_flutter)
333334
- [image](https://pub.dev/packages/image)
334335
- [mime](https://pub.dev/packages/mime)
335-
- [rounded_background_text](https://pub.dev/packages/rounded_background_text)
336336

337337
## Contributors
338338
<a href="https://github.com/hm21/pro_image_editor/graphs/contributors">

example/lib/core/constants/example_list_constant.dart

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import 'package:example/features/ai/ai_group.dart';
2-
import 'package:example/features/layer_select_design_example.dart';
1+
import 'package:example/features/layer/layer_group_page.dart';
32
import 'package:flutter/material.dart';
43

4+
import '/features/ai/ai_group_page.dart';
55
import '/features/crop_to_main_editor.dart';
66
import '/features/custom_widgets_example.dart';
77
import '/features/default_example.dart';
@@ -17,7 +17,6 @@ import '/features/movable_background_image.dart';
1717
import '/features/pick_image_example.dart';
1818
import '/features/reorder_layer_example.dart';
1919
import '/features/round_cropper_example.dart';
20-
import '/features/selectable_layer_example.dart';
2120
import '/features/signature_drawing_example.dart';
2221
import '/features/standalone_example.dart';
2322
import '/features/stickers_example.dart';
@@ -48,7 +47,6 @@ List<Example> kImageEditorExamples = const [
4847
name: 'AI-Integration',
4948
icon: Icons.hub_outlined,
5049
page: AiGroupPage(),
51-
disabledMessage: 'That function is not supported on the web.',
5250
),
5351
Example(
5452
path: '/designs',
@@ -105,16 +103,10 @@ List<Example> kImageEditorExamples = const [
105103
page: RoundCropperExample(),
106104
),
107105
Example(
108-
path: '/selectable-layers',
109-
name: 'Selectable-Layers',
110-
icon: Icons.select_all_rounded,
111-
page: SelectableLayerExample(),
112-
),
113-
Example(
114-
path: '/layer-selection-design',
115-
name: 'Selected Layer Design',
116-
icon: Icons.design_services_outlined,
117-
page: LayerSelectDesignExample(),
106+
path: '/layer',
107+
name: 'Layers',
108+
icon: Icons.layers_outlined,
109+
page: LayerGroupPage(),
118110
),
119111
Example(
120112
path: '/generation-configs',
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/// A map representing the demo data for file import history.
2+
Map<String, dynamic> kImportHistoryDemoData = {
3+
'v': '6.3.0',
4+
'm': true,
5+
'p': 7,
6+
'h': [
7+
{
8+
'l': [
9+
{'id': 'A'}
10+
],
11+
'b': 0.0
12+
},
13+
{
14+
'l': [
15+
{
16+
'id': 'A',
17+
'x': -84.25000000000004,
18+
'y': -106.37150837988824,
19+
'r': -0.523596,
20+
's': 3.010189295690343
21+
}
22+
]
23+
},
24+
{
25+
'l': [
26+
{'id': 'A'},
27+
{'id': 'B'}
28+
]
29+
},
30+
{
31+
'l': [
32+
{'id': 'A'},
33+
{
34+
'id': 'B',
35+
'x': 68.24720670391063,
36+
'y': -203.80027932960894,
37+
'r': 0.43633,
38+
's': 1.0001745810055866
39+
}
40+
]
41+
},
42+
{
43+
'l': [
44+
{'id': 'A'},
45+
{'id': 'B'},
46+
{'id': 'C'}
47+
]
48+
},
49+
{
50+
'l': [
51+
{'id': 'A'},
52+
{'id': 'B'},
53+
{'id': 'C'}
54+
],
55+
'f': [
56+
[
57+
1.0,
58+
0.0,
59+
0.0,
60+
0.0,
61+
13.5,
62+
0.0,
63+
1.0,
64+
0.0,
65+
0.0,
66+
0.0,
67+
0.0,
68+
0.0,
69+
1.0,
70+
0.0,
71+
0.0,
72+
0.0,
73+
0.0,
74+
0.0,
75+
1.0,
76+
0.0
77+
],
78+
[
79+
0.9867,
80+
0.0,
81+
0.0,
82+
0.0,
83+
-3.3915,
84+
0.0,
85+
0.9867,
86+
0.0,
87+
0.0,
88+
-3.3915,
89+
0.0,
90+
0.0,
91+
0.9867,
92+
0.0,
93+
0.0,
94+
0.0,
95+
0.0,
96+
0.0,
97+
1.0,
98+
0.0
99+
]
100+
]
101+
},
102+
{
103+
'l': [
104+
{'id': 'A'},
105+
{'id': 'B'},
106+
{'id': 'C'}
107+
],
108+
'a': [
109+
{
110+
'id': 'contrast',
111+
'value': 0.07999999999999996,
112+
'matrix': [
113+
1.1723386420787927,
114+
0.0,
115+
0.0,
116+
0.0,
117+
-22.059346186085463,
118+
0.0,
119+
1.1723386420787927,
120+
0.0,
121+
0.0,
122+
-22.059346186085463,
123+
0.0,
124+
0.0,
125+
1.1723386420787927,
126+
0.0,
127+
-22.059346186085463,
128+
0.0,
129+
0.0,
130+
0.0,
131+
1.0,
132+
0.0
133+
]
134+
},
135+
{
136+
'id': 'temperature',
137+
'value': 0.050000000000000044,
138+
'matrix': [
139+
1.05,
140+
0.0,
141+
0.0,
142+
0.0,
143+
0.0,
144+
0.0,
145+
1.025,
146+
0.0,
147+
0.0,
148+
0.0,
149+
0.0,
150+
0.0,
151+
1.0,
152+
0.0,
153+
0.0,
154+
0.0,
155+
0.0,
156+
0.0,
157+
1.0,
158+
0.0
159+
]
160+
}
161+
]
162+
},
163+
{
164+
'l': [
165+
{'id': 'A'},
166+
{'id': 'B'},
167+
{'id': 'C'},
168+
{'id': 'D'},
169+
{'id': 'E'}
170+
]
171+
}
172+
],
173+
'r': {
174+
'A': {
175+
'x': 0.0,
176+
'y': 0.0,
177+
'r': 0.0,
178+
's': 1.880580357142857,
179+
'fx': false,
180+
'fy': false,
181+
'in': {'m': true, 's': true, 'r': true, 't': true, 'e': true},
182+
't': 'emoji',
183+
'e': '😛'
184+
},
185+
'B': {
186+
'x': 0.0,
187+
'y': 0.0,
188+
'r': 0.0,
189+
's': 1.1766759776536313,
190+
'fx': false,
191+
'fy': false,
192+
'in': {'m': true, 's': true, 'r': true, 't': true, 'e': true},
193+
't': 'text',
194+
'te': 'Hello World',
195+
'cm': 'backgroundAndColor',
196+
'c': 4281073408,
197+
'b': 4278190080,
198+
'cp': 0.4788571428571428,
199+
'a': 'center',
200+
'f': 1.0
201+
},
202+
'C': {
203+
'x': 10.707751396648074,
204+
'y': 89.66270949720676,
205+
'r': 0.0,
206+
's': 1.1766759776536313,
207+
'fx': false,
208+
'fy': false,
209+
'in': {'m': true, 's': true, 'r': true, 't': true, 'e': true},
210+
't': 'paint',
211+
'i': {
212+
'm': 'arrow',
213+
'o': [
214+
{'x': 5.0, 'y': 68.59999999999997},
215+
{'x': 70.60000000000002, 'y': 5.0}
216+
],
217+
'c': 4294901760,
218+
's': 10.0,
219+
't': 1.0,
220+
'f': false
221+
},
222+
'rs': {'w': 75.60000000000002, 'h': 73.59999999999997},
223+
'o': 1.0
224+
},
225+
'D': {
226+
'x': -119.07960893854742,
227+
'y': -264.98743016759767,
228+
'r': -0.261798,
229+
's': 0.7060055865921787,
230+
'fx': false,
231+
'fy': false,
232+
'in': {'m': true, 's': true, 'r': true, 't': true, 'e': true},
233+
't': 'widget',
234+
'ec': {'id': 'my-special-container'}
235+
},
236+
'E': {
237+
'x': 119.07960893854742,
238+
'y': 264.98743016759767,
239+
'r': 0.261798,
240+
's': 0.7060055865921787,
241+
'fx': false,
242+
'fy': false,
243+
'in': {'m': true, 's': true, 'r': true, 't': true, 'e': true},
244+
't': 'widget',
245+
'ec': {'networkUrl': 'https://picsum.photos/id/17/400'}
246+
}
247+
},
248+
'i': {'w': 1024.0, 'h': 1792.0},
249+
'l': {'w': 385.14285714285717, 'h': 674.0}
250+
};

example/lib/features/ai/ai_group.dart renamed to example/lib/features/ai/ai_group_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import 'package:example/features/ai/ai_replace_background/ai_replace_background_page_example.dart';
21
import 'package:flutter/foundation.dart';
32
import 'package:flutter/material.dart';
43

4+
import 'ai_replace_background/ai_replace_background_page_example.dart';
55
import 'ai_text_commands/ai_text_commands_page_example.dart';
66
import 'background_remover/background_remover_stub_example.dart'
77
if (dart.library.io) 'background_remover/background_remover_example.dart';

example/lib/features/ai/ai_replace_background/ai_replace_background_page_example.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class _AiReplaceBackgroundExampleState extends State<AiReplaceBackgroundExample>
153153
builder: (_) {
154154
return AnimatedSwitcher(
155155
duration: const Duration(milliseconds: 220),
156-
child: editor.selectedLayerIndex >= 0 || editor.isSubEditorOpen
156+
child: editor.isLayerBeingTransformed || editor.isSubEditorOpen
157157
? SizedBox.shrink(key: UniqueKey())
158158
: _buildCommandLine(),
159159
);

example/lib/features/ai/ai_text_commands/ai_text_commands_page_example.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class _AiTextCommandsExampleState extends State<AiTextCommandsExample>
123123
builder: (_) {
124124
return AnimatedSwitcher(
125125
duration: const Duration(milliseconds: 220),
126-
child: editor.selectedLayerIndex >= 0 || editor.isSubEditorOpen
126+
child: editor.isLayerBeingTransformed || editor.isSubEditorOpen
127127
? SizedBox.shrink(key: UniqueKey())
128128
: _buildCommandLine(),
129129
);

example/lib/features/ai/background_remover/background_remover_example.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class _BackgroundRemoverExampleState extends State<BackgroundRemoverExample>
129129
ReactiveWidget(
130130
stream: rebuildStream,
131131
builder: (_) =>
132-
editor.selectedLayerIndex >= 0 || editor.isSubEditorOpen
132+
editor.isLayerBeingTransformed || editor.isSubEditorOpen
133133
? const SizedBox.shrink()
134134
: Positioned(
135135
bottom: 20,
@@ -157,7 +157,7 @@ class _BackgroundRemoverExampleState extends State<BackgroundRemoverExample>
157157
ReactiveWidget(
158158
stream: rebuildStream,
159159
builder: (_) =>
160-
editor.selectedLayerIndex >= 0 || editor.isSubEditorOpen
160+
editor.isLayerBeingTransformed || editor.isSubEditorOpen
161161
? const SizedBox.shrink()
162162
: Positioned(
163163
bottom: 20,

0 commit comments

Comments
 (0)