141 lines
4.1 KiB
Dart
141 lines
4.1 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// TODO(mattkae): remove invalid_use_of_internal_member ignore comment when this API is stable.
|
|
// See: https://github.com/flutter/flutter/issues/177586
|
|
// TODO(mattkae): refactor this example for better widget position tracking
|
|
// This positioning logic is simpler than you might want in production. See https://github.com/flutter/flutter/issues/178829.
|
|
// ignore_for_file: invalid_use_of_internal_member
|
|
// ignore_for_file: implementation_imports
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/src/widgets/_window.dart';
|
|
import 'package:flutter/src/widgets/_window_positioner.dart';
|
|
|
|
void main() {
|
|
try {
|
|
runWidget(
|
|
RegularWindow(
|
|
controller: RegularWindowController(
|
|
preferredSize: const Size(800, 600),
|
|
preferredConstraints: const BoxConstraints(
|
|
minWidth: 640,
|
|
minHeight: 480,
|
|
),
|
|
title: 'Example Window',
|
|
),
|
|
child: const MaterialApp(home: MyApp()),
|
|
),
|
|
);
|
|
} on UnsupportedError catch (e) {
|
|
// TODO(mattkae): Remove this catch block when Windows tooltips are supported in tests.
|
|
// For now, we need to catch the error so that the API smoke tests pass.
|
|
runApp(
|
|
MaterialApp(
|
|
home: Scaffold(body: Center(child: Text(e.message ?? 'Unsupported'))),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyApp extends StatefulWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
State<MyApp> createState() {
|
|
return _MyAppState();
|
|
}
|
|
}
|
|
|
|
class _CallbackPopupDelegate extends PopupWindowControllerDelegate {
|
|
_CallbackPopupDelegate({required this.onDestroyCallback});
|
|
|
|
final VoidCallback onDestroyCallback;
|
|
|
|
@override
|
|
void onWindowDestroyed() {
|
|
onDestroyCallback();
|
|
}
|
|
}
|
|
|
|
class _MyAppState extends State<MyApp> {
|
|
final GlobalKey _key = GlobalKey();
|
|
PopupWindowController? _popupController;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final List<Widget> children = <Widget>[
|
|
ElevatedButton(
|
|
key: _key,
|
|
onPressed: () {
|
|
setState(() {
|
|
_popupController ??= PopupWindowController(
|
|
parent: WindowScope.of(context),
|
|
anchorRect: _getAnchorRect()!,
|
|
positioner: const WindowPositioner(
|
|
parentAnchor: WindowPositionerAnchor.right,
|
|
childAnchor: WindowPositionerAnchor.left,
|
|
),
|
|
delegate: _CallbackPopupDelegate(
|
|
onDestroyCallback: () {
|
|
setState(() {
|
|
_popupController = null;
|
|
});
|
|
},
|
|
),
|
|
);
|
|
});
|
|
},
|
|
child: const Text('Show Popup'),
|
|
),
|
|
];
|
|
|
|
if (_popupController != null) {
|
|
children.add(
|
|
PopupWindow(
|
|
controller: _popupController!,
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
color: Colors.black,
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
const Text(
|
|
'This is a popup',
|
|
style: TextStyle(color: Colors.white),
|
|
),
|
|
const SizedBox(height: 8),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
setState(() {
|
|
_popupController?.destroy();
|
|
});
|
|
},
|
|
child: const Text('Close'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return Scaffold(
|
|
body: Center(
|
|
child: Row(mainAxisSize: MainAxisSize.min, children: children),
|
|
),
|
|
);
|
|
}
|
|
|
|
Rect? _getAnchorRect() {
|
|
final RenderBox? renderBox =
|
|
_key.currentContext?.findRenderObject() as RenderBox?;
|
|
if (renderBox != null) {
|
|
final Offset position = renderBox.localToGlobal(Offset.zero);
|
|
final Size size = renderBox.size;
|
|
return position & size; // creates a Rect
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|