Skip to content

Commit 5fa2cb1

Browse files
committed
Revert "Revert all API changes to the framework"
This reverts commit 1070b86.
1 parent 1070b86 commit 5fa2cb1

27 files changed

+2161
-2
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "4f182c3ce1f3a60a007b034cd5d9f2122ca2e5f1"
8+
channel: "[user-branch]"
9+
10+
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: 4f182c3ce1f3a60a007b034cd5d9f2122ca2e5f1
17+
base_revision: 4f182c3ce1f3a60a007b034cd5d9f2122ca2e5f1
18+
- platform: windows
19+
create_revision: 4f182c3ce1f3a60a007b034cd5d9f2122ca2e5f1
20+
base_revision: 4f182c3ce1f3a60a007b034cd5d9f2122ca2e5f1
21+
22+
# User provided section
23+
24+
# List of Local paths (relative to this file) that should be
25+
# ignored by the migrate tool.
26+
#
27+
# Files that are not part of the templates will be ignored by default.
28+
unmanaged_files:
29+
- 'lib/main.dart'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# multi_window_ref_app
2+
3+
A reference application demonstrating multi-window support for Flutter using a
4+
rich semantics windowing API. At the moment, only the Windows platform is
5+
supported.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This file configures the analyzer, which statically analyzes Dart code to
2+
# check for errors, warnings, and lints.
3+
#
4+
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+
# invoked from the command line by running `flutter analyze`.
7+
8+
# The following line activates a set of recommended lints for Flutter apps,
9+
# packages, and plugins designed to encourage good coding practices.
10+
include: package:flutter_lints/flutter.yaml
11+
12+
linter:
13+
# The lint rules applied to this project can be customized in the
14+
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
15+
# included above or to enable additional rules. A list of all available lints
16+
# and their documentation is published at https://dart.dev/lints.
17+
#
18+
# Instead of disabling a lint rule for the entire project in the
19+
# section below, it can also be suppressed for a single line of code
20+
# or a specific dart file by using the `// ignore: name_of_lint` and
21+
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
22+
# producing the lint.
23+
rules:
24+
# avoid_print: false # Uncomment to disable the `avoid_print` rule
25+
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26+
27+
# Additional information about this file can be found at
28+
# https://dart.dev/guides/language/analysis-options
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:multi_window_ref_app/app/window_controller_render.dart';
3+
4+
import 'window_settings.dart';
5+
import 'window_settings_dialog.dart';
6+
import 'window_manager_model.dart';
7+
import 'regular_window_edit_dialog.dart';
8+
9+
class MainWindow extends StatefulWidget {
10+
MainWindow({super.key, required WindowController mainController}) {
11+
_windowManagerModel.add(KeyedWindowController(
12+
isMainWindow: true, key: UniqueKey(), controller: mainController));
13+
}
14+
15+
final WindowManagerModel _windowManagerModel = WindowManagerModel();
16+
final WindowSettings _settings = WindowSettings();
17+
18+
@override
19+
State<MainWindow> createState() => _MainWindowState();
20+
}
21+
22+
class _MainWindowState extends State<MainWindow> {
23+
@override
24+
Widget build(BuildContext context) {
25+
final child = Scaffold(
26+
appBar: AppBar(
27+
title: const Text('Multi Window Reference App'),
28+
),
29+
body: Row(
30+
crossAxisAlignment: CrossAxisAlignment.start,
31+
children: [
32+
Expanded(
33+
flex: 60,
34+
child: SingleChildScrollView(
35+
scrollDirection: Axis.vertical,
36+
child: _ActiveWindowsTable(
37+
windowManagerModel: widget._windowManagerModel),
38+
),
39+
),
40+
Expanded(
41+
flex: 40,
42+
child: Column(
43+
crossAxisAlignment: CrossAxisAlignment.stretch,
44+
children: [
45+
ListenableBuilder(
46+
listenable: widget._windowManagerModel,
47+
builder: (BuildContext context, Widget? child) {
48+
return _WindowCreatorCard(
49+
selectedWindow: widget._windowManagerModel.selected,
50+
windowManagerModel: widget._windowManagerModel,
51+
windowSettings: widget._settings);
52+
})
53+
],
54+
),
55+
),
56+
],
57+
),
58+
);
59+
60+
return ViewAnchor(
61+
view: ListenableBuilder(
62+
listenable: widget._windowManagerModel,
63+
builder: (BuildContext context, Widget? _) {
64+
final List<Widget> childViews = <Widget>[];
65+
for (final KeyedWindowController controller
66+
in widget._windowManagerModel.windows) {
67+
if (controller.parent == null && !controller.isMainWindow) {
68+
childViews.add(WindowControllerRender(
69+
controller: controller.controller,
70+
key: controller.key,
71+
windowSettings: widget._settings,
72+
windowManagerModel: widget._windowManagerModel,
73+
onDestroyed: () =>
74+
widget._windowManagerModel.remove(controller.key),
75+
onError: () =>
76+
widget._windowManagerModel.remove(controller.key),
77+
));
78+
}
79+
}
80+
81+
return ViewCollection(views: childViews);
82+
}),
83+
child: child);
84+
}
85+
}
86+
87+
class _ActiveWindowsTable extends StatelessWidget {
88+
const _ActiveWindowsTable({required this.windowManagerModel});
89+
90+
final WindowManagerModel windowManagerModel;
91+
92+
@override
93+
Widget build(BuildContext context) {
94+
return ListenableBuilder(
95+
listenable: windowManagerModel,
96+
builder: (BuildContext context, Widget? widget) {
97+
return DataTable(
98+
showBottomBorder: true,
99+
onSelectAll: (selected) {
100+
windowManagerModel.select(null);
101+
},
102+
columns: const [
103+
DataColumn(
104+
label: SizedBox(
105+
width: 20,
106+
child: Text(
107+
'ID',
108+
style: TextStyle(
109+
fontSize: 16,
110+
),
111+
),
112+
),
113+
),
114+
DataColumn(
115+
label: SizedBox(
116+
width: 120,
117+
child: Text(
118+
'Type',
119+
style: TextStyle(
120+
fontSize: 16,
121+
),
122+
),
123+
),
124+
),
125+
DataColumn(
126+
label: SizedBox(
127+
width: 20,
128+
child: Text(''),
129+
),
130+
numeric: true),
131+
],
132+
rows: (windowManagerModel.windows)
133+
.map<DataRow>((KeyedWindowController controller) {
134+
return DataRow(
135+
key: controller.key,
136+
color: WidgetStateColor.resolveWith((states) {
137+
if (states.contains(WidgetState.selected)) {
138+
return Theme.of(context).colorScheme.primary.withAlpha(20);
139+
}
140+
return Colors.transparent;
141+
}),
142+
selected: controller.controller == windowManagerModel.selected,
143+
onSelectChanged: (selected) {
144+
if (selected != null) {
145+
windowManagerModel.select(selected
146+
? controller.controller.rootView.viewId
147+
: null);
148+
}
149+
},
150+
cells: [
151+
DataCell(
152+
ListenableBuilder(
153+
listenable: controller.controller,
154+
builder: (BuildContext context, Widget? _) => Text(
155+
controller.controller.isReady
156+
? '${controller.controller.rootView.viewId}'
157+
: 'Loading...')),
158+
),
159+
DataCell(
160+
ListenableBuilder(
161+
listenable: controller.controller,
162+
builder: (BuildContext context, Widget? _) => Text(
163+
controller.controller.type
164+
.toString()
165+
.replaceFirst('WindowArchetype.', ''))),
166+
),
167+
DataCell(
168+
ListenableBuilder(
169+
listenable: controller.controller,
170+
builder: (BuildContext context, Widget? _) =>
171+
Row(children: [
172+
IconButton(
173+
icon: const Icon(Icons.edit_outlined),
174+
onPressed: () {
175+
if (controller.controller.type ==
176+
WindowArchetype.regular) {
177+
showRegularWindowEditDialog(context,
178+
initialWidth:
179+
controller.controller.size.width,
180+
initialHeight:
181+
controller.controller.size.height,
182+
initialTitle: "",
183+
initialState: (controller.controller
184+
as RegularWindowController)
185+
.state,
186+
onSave: (double? width, double? height,
187+
String? title, WindowState? state) {
188+
(controller.controller
189+
as RegularWindowController)
190+
.modify(
191+
size: width != null &&
192+
height != null
193+
? Size(width, height)
194+
: null,
195+
title: title,
196+
state: state);
197+
});
198+
}
199+
},
200+
),
201+
IconButton(
202+
icon: const Icon(Icons.delete_outlined),
203+
onPressed: () async {
204+
await controller.controller.destroy();
205+
},
206+
)
207+
])),
208+
),
209+
],
210+
);
211+
}).toList(),
212+
);
213+
});
214+
}
215+
}
216+
217+
class _WindowCreatorCard extends StatelessWidget {
218+
const _WindowCreatorCard(
219+
{required this.selectedWindow,
220+
required this.windowManagerModel,
221+
required this.windowSettings});
222+
223+
final WindowController? selectedWindow;
224+
final WindowManagerModel windowManagerModel;
225+
final WindowSettings windowSettings;
226+
227+
@override
228+
Widget build(BuildContext context) {
229+
return Card.outlined(
230+
margin: const EdgeInsets.symmetric(horizontal: 25),
231+
child: Padding(
232+
padding: const EdgeInsets.fromLTRB(25, 0, 25, 5),
233+
child: Column(
234+
crossAxisAlignment: CrossAxisAlignment.center,
235+
children: [
236+
const Padding(
237+
padding: EdgeInsets.only(top: 10, bottom: 10),
238+
child: Text(
239+
'New Window',
240+
style: TextStyle(
241+
fontWeight: FontWeight.bold,
242+
fontSize: 16.0,
243+
),
244+
),
245+
),
246+
Column(
247+
crossAxisAlignment: CrossAxisAlignment.stretch,
248+
children: [
249+
OutlinedButton(
250+
onPressed: () async {
251+
final UniqueKey key = UniqueKey();
252+
windowManagerModel.add(KeyedWindowController(
253+
key: key,
254+
controller: RegularWindowController(
255+
onDestroyed: () => windowManagerModel.remove(key),
256+
onError: (String error) =>
257+
windowManagerModel.remove(key),
258+
title: "Regular",
259+
size: windowSettings.regularSize)));
260+
},
261+
child: const Text('Regular'),
262+
),
263+
const SizedBox(height: 8),
264+
Container(
265+
alignment: Alignment.bottomRight,
266+
child: TextButton(
267+
child: const Text('SETTINGS'),
268+
onPressed: () {
269+
windowSettingsDialog(context, windowSettings);
270+
},
271+
),
272+
),
273+
const SizedBox(width: 8),
274+
],
275+
),
276+
],
277+
),
278+
),
279+
);
280+
}
281+
}

0 commit comments

Comments
 (0)