mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
## What's new? - Implemented `_TestTooltipWindowController` in the `TestWindowingOwner` - Fixed how child windows of the main window are rendered in the application - Introduced `WindowManager.getChildrenOf` to simplify filtering and rendering of the children of a parent window - Added a test for the tooltip window - Added a test for modal dialogs of the main window ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [X] All existing and new tests are passing.
152 lines
4.5 KiB
Dart
152 lines
4.5 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.
|
|
|
|
// ignore_for_file: invalid_use_of_internal_member
|
|
// ignore_for_file: implementation_imports
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter/src/widgets/_window.dart';
|
|
import 'package:flutter/src/widgets/_window_positioner.dart';
|
|
|
|
class KeyedWindow {
|
|
KeyedWindow({
|
|
this.isMainWindow = false,
|
|
required this.key,
|
|
required this.controller,
|
|
});
|
|
|
|
BaseWindowController? get parent {
|
|
switch (controller) {
|
|
case RegularWindowController():
|
|
return null;
|
|
case DialogWindowController dialogController:
|
|
return dialogController.parent;
|
|
case TooltipWindowController tooltipController:
|
|
return tooltipController.parent;
|
|
default:
|
|
throw Exception('Unknown controller type');
|
|
}
|
|
}
|
|
|
|
final bool isMainWindow;
|
|
final UniqueKey key;
|
|
final BaseWindowController controller;
|
|
}
|
|
|
|
/// Provides access to the windows created by the application.
|
|
///
|
|
/// The window manager manages a flat list of all of the [BaseWindowController]s
|
|
/// that have been created by the application as well as which controller is
|
|
/// currently selected by the UI.
|
|
class WindowManager extends ChangeNotifier {
|
|
WindowManager({required List<KeyedWindow> initialWindows})
|
|
: _windows = initialWindows;
|
|
|
|
final List<KeyedWindow> _windows;
|
|
List<KeyedWindow> get windows => _windows;
|
|
|
|
void add(KeyedWindow window) {
|
|
_windows.add(window);
|
|
notifyListeners();
|
|
}
|
|
|
|
void remove(UniqueKey key) {
|
|
_windows.removeWhere((KeyedWindow window) => window.key == key);
|
|
notifyListeners();
|
|
}
|
|
|
|
Iterable<KeyedWindow> getWindows({required BaseWindowController? parent}) {
|
|
return _windows.where((KeyedWindow window) => window.parent == parent);
|
|
}
|
|
}
|
|
|
|
/// Provides access to the [WindowManager] from the widget tree.
|
|
class WindowManagerAccessor extends InheritedNotifier<WindowManager> {
|
|
const WindowManagerAccessor({
|
|
super.key,
|
|
required super.child,
|
|
required WindowManager windowManager,
|
|
}) : super(notifier: windowManager);
|
|
|
|
static WindowManager of(BuildContext context) {
|
|
final WindowManagerAccessor? result = context
|
|
.dependOnInheritedWidgetOfExactType<WindowManagerAccessor>();
|
|
assert(result != null, 'No WindowManager found in context');
|
|
return result!.notifier!;
|
|
}
|
|
}
|
|
|
|
class TooltipSettings {}
|
|
|
|
/// Settings that control the behavior of newly created windows.
|
|
class WindowSettings {
|
|
WindowSettings({
|
|
this.regularSize = const Size(800, 600),
|
|
this.dialogSize = const Size(400, 400),
|
|
this.positioner = const WindowPositioner(
|
|
parentAnchor: WindowPositionerAnchor.right,
|
|
childAnchor: WindowPositionerAnchor.left,
|
|
),
|
|
});
|
|
|
|
/// The initial size for newly created regular windows.
|
|
Size regularSize;
|
|
|
|
/// The initial size of the dialog window.
|
|
Size dialogSize;
|
|
|
|
/// The positioner used to determine where new tooltips and popups are placed.
|
|
WindowPositioner positioner;
|
|
}
|
|
|
|
/// Provides access to the [WindowSettings] from the widget tree.
|
|
class WindowSettingsAccessor extends InheritedWidget {
|
|
const WindowSettingsAccessor({
|
|
super.key,
|
|
required super.child,
|
|
required this.windowSettings,
|
|
});
|
|
|
|
final WindowSettings windowSettings;
|
|
|
|
static WindowSettings of(BuildContext context) {
|
|
final WindowSettingsAccessor? result = context
|
|
.dependOnInheritedWidgetOfExactType<WindowSettingsAccessor>();
|
|
assert(result != null, 'No WindowSettings found in context');
|
|
return result!.windowSettings;
|
|
}
|
|
|
|
@override
|
|
bool updateShouldNotify(WindowSettingsAccessor oldWidget) {
|
|
return windowSettings != oldWidget.windowSettings;
|
|
}
|
|
}
|
|
|
|
class CallbackDialogWindowControllerDelegate
|
|
with DialogWindowControllerDelegate {
|
|
CallbackDialogWindowControllerDelegate({required this.onDestroyed});
|
|
|
|
@override
|
|
void onWindowDestroyed() {
|
|
onDestroyed();
|
|
super.onWindowDestroyed();
|
|
}
|
|
|
|
final VoidCallback onDestroyed;
|
|
}
|
|
|
|
String anchorToString(WindowPositionerAnchor anchor) {
|
|
return switch (anchor) {
|
|
WindowPositionerAnchor.center => 'Center',
|
|
WindowPositionerAnchor.top => 'Top',
|
|
WindowPositionerAnchor.bottom => 'Bottom',
|
|
WindowPositionerAnchor.left => 'Left',
|
|
WindowPositionerAnchor.right => 'Right',
|
|
WindowPositionerAnchor.topLeft => 'Top Left',
|
|
WindowPositionerAnchor.bottomLeft => 'Bottom Left',
|
|
WindowPositionerAnchor.topRight => 'Top Right',
|
|
WindowPositionerAnchor.bottomRight => 'Bottom Right',
|
|
};
|
|
}
|