浏览代码

add a simple inspector framework

/zxw-devTools
guanghuispark 3 年前
当前提交
db8fdfe6
共有 17 个文件被更改,包括 1123 次插入190 次删除
  1. 7
      com.unity.uiwidgets.devtools/Editor/v2/dependencies/provider/inherited_provider.cs
  2. 15
      com.unity.uiwidgets.devtools/Editor/v2/main.cs
  3. 402
      com.unity.uiwidgets.devtools/Editor/v2/src/app.cs
  4. 3
      com.unity.uiwidgets/Runtime/widgets/focus_manager.cs
  5. 4
      com.unity.uiwidgets/Runtime/widgets/value_listenable_builder.cs
  6. 22
      com.unity.uiwidgets.devtools/Editor/v2/src/enum_utils.cs
  7. 69
      com.unity.uiwidgets.devtools/Editor/v2/src/notifications.cs
  8. 15
      com.unity.uiwidgets.devtools/Editor/v2/src/octicons.cs
  9. 72
      com.unity.uiwidgets.devtools/Editor/v2/src/split.cs
  10. 82
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/diagnostics_node.cs
  11. 7
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_controller.cs
  12. 87
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_screen.cs
  13. 41
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_screen_details_tab.cs
  14. 21
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_service.cs
  15. 281
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_tree.cs
  16. 185
      com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_tree_flutter.cs

7
com.unity.uiwidgets.devtools/Editor/v2/dependencies/provider/inherited_provider.cs


delegate void Dispose<T>(BuildContext context, T value);
delegate VoidCallback StartListening<T>(InheritedContext<T> element, T value);
// delegate VoidCallback StartListening<T>(InheritedContext<T> element, T value);
protected internal override Widget buildWithChild(BuildContext context, Widget child)
{
throw new System.NotImplementedException();
}
}
}

15
com.unity.uiwidgets.devtools/Editor/v2/main.cs


using Unity.UIWidgets.DevTools.config_specific.framework_initialize;
using Unity.UIWidgets.Editor;
using Unity.UIWidgets.widgets;
using UnityEditor;
public class Devetool : UIWidgetsEditorPanel
public class EditorWindowDevtools : UIWidgetsEditorPanel
[MenuItem("UIWidgets/DevTools")]
public static void CountDemo()
{
CreateWindow<EditorWindowDevtools>();
}
preferences.init();
FrameworkInitializeUtils.initializeFramework();
new DevToolsApp(defaultScreens, preferences)
new DevToolsApp(AppUtils.defaultScreens, preferences)
);
}
}

402
com.unity.uiwidgets.devtools/Editor/v2/src/app.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.DevTools.inspector;
using Unity.UIWidgets.ui;
using UnityEngine;
static class AppUtils
{
public static string homeRoute = "/";
public static string snapshotRoute = "/snapshot";
}
static class AppUtils
{
public static string homeRoute = "/";
public static string snapshotRoute = "/snapshot";
public static List<DevToolsScreen<object>> defaultScreens {
get
{
return new List<DevToolsScreen<object>>
{
new DevToolsScreen<object>(
new InspectorScreen(),
createController: null
)
};
}
}
}
class DevToolsApp : StatefulWidget {
public DevToolsApp(List<DevToolsScreen<object>> screens, PreferencesController preferences)
{
this.screens = screens;
this.preferences = preferences;
}
class DevToolsApp : StatefulWidget {
public DevToolsApp(List<DevToolsScreen<object>> screens, PreferencesController preferences)
{
this.screens = screens;
this.preferences = preferences;
}
public readonly List<DevToolsScreen<object>> screens;
public readonly PreferencesController preferences;
public readonly List<DevToolsScreen<object>> screens;
public readonly PreferencesController preferences;
public override State createState() => new DevToolsAppState();
public override State createState() => new DevToolsAppState();
public static DevToolsAppState of(BuildContext context) {
return context.findAncestorStateOfType<DevToolsAppState>();
}
}
class DevToolsAppState : State<DevToolsApp> {
List<Screen> _screens => widget.screens.Select(s => s.screen).ToList();
PreferencesController preferences => widget.preferences;
public override void initState() {
base.initState();
Globals.serviceManager.isolateManager.onSelectedIsolateChanged.listen((_) => {
setState(() => {
_clearCachedRoutes();
});
});
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
_clearCachedRoutes();
}
/// Generates routes, separating the path from URL query parameters.
Route _generateRoute(RouteSettings settings) {
var uri = settings.name;
var path = uri.isEmpty() ? AppUtils.homeRoute : uri;
var args = settings.arguments as SnapshotArguments;
// Provide the appropriate page route.
if (routes.ContainsKey(path)) {
WidgetBuilder builder = (context) => routes[path](
context,
uri.queryParameters,
args
);
D.assert(() => {
builder = (context) => new _AlternateCheckedModeBanner(
builder: (subContext) => routes[path](
subContext,
uri.queryParameters,
args
)
);
return true;
}());
return new MaterialPageRoute(settings: settings, builder: builder);
}
// Return a page not found.
return new MaterialPageRoute(
settings: settings,
builder: (BuildContext context) => {
return DevToolsScaffold.withChild(
child: new CenteredMessage("'$uri' not found.")
);
}
);
}
/// The routes that the app exposes.
Dictionary<string, UrlParametersBuilder> routes => {
_routes = _routes ?? new Dictionary<string, UrlParametersBuilder>(){
{AppUtils.homeRoute, (_, buildParam, __) => {
if (buildParam.getOrDefault("uri")?.isNotEmpty() ?? false) {
var embed = buildParam["embed"] == "true";
var page = buildParam["page"];
var tabs = embed && page != null
? _visibleScreens().Where((p) => p.screenId == page)
: _visibleScreens();
return new Initializer(
url: buildParam["uri"],
allowConnectionScreenOnDisconnect: !embed,
builder: (_) => _providedControllers(
child: new DevToolsScaffold(
embed: embed,
initialPage: page,
tabs: tabs,
actions: [
if (serviceManager.connectedApp.isFlutterAppNow) ...[
HotReloadButton(),
HotRestartButton(),
],
OpenSettingsAction(),
OpenAboutAction(),
],
),
),
);
} else {
return DevToolsScaffold.withChild(child: ConnectScreenBody());
public static DevToolsAppState of(BuildContext context) {
return context.findAncestorStateOfType<DevToolsAppState>();
},
snapshotRoute: (_, __, args) => {
return DevToolsScaffold.withChild(
child: _providedControllers(
offline: true,
child: SnapshotScreenBody(args, _screens),
),
);
},
}};
return _routes;
}
Dictionary<string, UrlParametersBuilder> _routes;
void _clearCachedRoutes() {
_routes = null;
}
List<Screen> _visibleScreens() {
var visibleScreens = new List<Screen>();
foreach (var screen in _screens) {
if (screen.conditionalLibrary != null) {
if (Globals.serviceManager.isServiceAvailable &&
Globals.serviceManager
.isolateManager.selectedIsolateAvailable.isCompleted &&
Globals.serviceManager.libraryUriAvailableNow(screen.conditionalLibrary)) {
visibleScreens.Add(screen);
}
} else {
visibleScreens.Add(screen);
}
}
return visibleScreens;
}
}
Widget _providedControllers(Widget child, bool offline = false)
{
var _providers = widget.screens
.Where((s) =>
s.createController != null && (offline ? s.supportsOffline : true))
.Select((s) => s.controllerProvider);
class DevToolsAppState : State<DevToolsApp> {
Route _generateRoute(RouteSettings settings)
{
return new MaterialPageRoute(
settings: settings,
builder: (BuildContext context2) => { return new Container(); });
}
public override Widget build(BuildContext context)
{
return new ValueListenableBuilder<bool>(
valueListenable: widget.preferences.darkModeTheme,
builder: (subContext, value, _) => {
return new MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeUtils.themeFor(isDarkTheme: true),
builder: (subsubContext, child) => new Notifications(child: child),
onGenerateRoute: _generateRoute
);
}
);
}
}
return new MultiProvider(
providers: _providers,
child: child
);
}
public override Widget build(BuildContext context) {
return new ValueListenableBuilder<bool>(
valueListenable: widget.preferences.darkModeTheme,
builder: (subContext, value, _) => {
return new MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeUtils.themeFor(isDarkTheme: value),
builder: (subsubContext, child) => new Notifications(child: child),
onGenerateRoute: _generateRoute
);
}
);
}
}
// class DevToolsAppState : State<DevToolsApp> {
// List<Screen> _screens => widget.screens.Select(s => s.screen).ToList();
//
// PreferencesController preferences => widget.preferences;
//
// public override void initState() {
// base.initState();
//
// Globals.serviceManager.isolateManager.onSelectedIsolateChanged.listen((_) => {
// setState(() => {
// _clearCachedRoutes();
// });
// });
// }
//
// public override void didUpdateWidget(StatefulWidget oldWidget) {
// base.didUpdateWidget(oldWidget);
// _clearCachedRoutes();
// }
//
// /// Generates routes, separating the path from URL query parameters.
// Route _generateRoute(RouteSettings settings) {
// var uri = settings.name;
// var path = uri.isEmpty() ? AppUtils.homeRoute : uri;
// var args = settings.arguments as SnapshotArguments;
//
// // Provide the appropriate page route.
// if (routes.ContainsKey(path)) {
// WidgetBuilder builder = (context) => routes[path](
// context,
// uri.queryParameters,
// args
// );
// D.assert(() => {
// builder = (context) => new _AlternateCheckedModeBanner(
// builder: (subContext) => routes[path](
// subContext,
// uri.queryParameters,
// args
// )
// );
// return true;
// }());
//
// return new MaterialPageRoute(settings: settings, builder: builder);
// }
//
// // Return a page not found.
// return new MaterialPageRoute(
// settings: settings,
// builder: (BuildContext context) => {
// return DevToolsScaffold.withChild(
// child: new CenteredMessage("'$uri' not found.")
// );
// }
// );
// }
//
// /// The routes that the app exposes.
// Dictionary<string, UrlParametersBuilder> routes => {
// _routes = _routes ?? new Dictionary<string, UrlParametersBuilder>(){
// {AppUtils.homeRoute, (_, buildParam, __) => {
// if (buildParam.getOrDefault("uri")?.isNotEmpty() ?? false) {
// var embed = buildParam["embed"] == "true";
// var page = buildParam["page"];
// var tabs = embed && page != null
// ? _visibleScreens().Where((p) => p.screenId == page)
// : _visibleScreens();
// return new Initializer(
// url: buildParam["uri"],
// allowConnectionScreenOnDisconnect: !embed,
// builder: (_) => _providedControllers(
// child: new DevToolsScaffold(
// embed: embed,
// initialPage: page,
// tabs: tabs,
// actions: [
// if (serviceManager.connectedApp.isFlutterAppNow) ...[
// HotReloadButton(),
// HotRestartButton(),
// ],
// OpenSettingsAction(),
// OpenAboutAction(),
// ],
// ),
// ),
// );
// } else {
// return DevToolsScaffold.withChild(child: ConnectScreenBody());
// }
// },
// snapshotRoute: (_, __, args) => {
// return DevToolsScaffold.withChild(
// child: _providedControllers(
// offline: true,
// child: SnapshotScreenBody(args, _screens),
// ),
// );
// },
// }};
//
// return _routes;
// }
//
// Dictionary<string, UrlParametersBuilder> _routes;
//
// void _clearCachedRoutes() {
// _routes = null;
// }
//
// List<Screen> _visibleScreens() {
// var visibleScreens = new List<Screen>();
// foreach (var screen in _screens) {
// if (screen.conditionalLibrary != null) {
// if (Globals.serviceManager.isServiceAvailable &&
// Globals.serviceManager
// .isolateManager.selectedIsolateAvailable.isCompleted &&
// Globals.serviceManager.libraryUriAvailableNow(screen.conditionalLibrary)) {
// visibleScreens.Add(screen);
// }
// } else {
// visibleScreens.Add(screen);
// }
// }
// return visibleScreens;
// }
//
// Widget _providedControllers(Widget child, bool offline = false)
// {
// var _providers = widget.screens
// .Where((s) =>
// s.createController != null && (offline ? s.supportsOffline : true))
// .Select((s) => s.controllerProvider);
//
// return new MultiProvider(
// providers: _providers,
// child: child
// );
// }
//
// public override Widget build(BuildContext context) {
// return new ValueListenableBuilder<bool>(
// valueListenable: widget.preferences.darkModeTheme,
// builder: (subContext, value, _) => {
// return new MaterialApp(
// debugShowCheckedModeBanner: false,
// theme: ThemeUtils.themeFor(isDarkTheme: value),
// builder: (subsubContext, child) => new Notifications(child: child),
// onGenerateRoute: _generateRoute
// );
// }
// );
// }
// }
//
class DevToolsScreen<C> {
public DevToolsScreen(
Screen screen,

public readonly bool supportsOffline;
internal Provider<C> controllerProvider => {
D.assert(createController != null);
return new Provider<C>(create: (_) => createController());
}
// internal Provider<C> controllerProvider => {
// D.assert(createController != null);
// return new Provider<C>(create: (_) => createController());
// }
public delegate Widget UrlParametersBuilder(
BuildContext buildContext,
Dictionary<string, string> route,
SnapshotArguments args
);
// public delegate Widget UrlParametersBuilder(
// BuildContext buildContext,
// Dictionary<string, string> route,
// SnapshotArguments args
// );
}

3
com.unity.uiwidgets/Runtime/widgets/focus_manager.cs


$"{(hasPrimaryFocus ? "[PRIMARY FOCUS]" : nullStr)}";
return $"{foundation_.describeIdentity(this)}" + $"{(extraData.isNotEmpty() ? extraData : nullStr)}";
}
}
}
}
public class FocusScopeNode : FocusNode {

4
com.unity.uiwidgets/Runtime/widgets/value_listenable_builder.cs


Key key = null,
Widget child = null
) : base(key: key) {
D.assert(valueListenable != null);
D.assert(builder != null);
// D.assert(valueListenable != null);
// D.assert(builder != null);
this.valueListenable = valueListenable;
this.builder = builder;
this.child = child;

22
com.unity.uiwidgets.devtools/Editor/v2/src/enum_utils.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.DevTools
{
public class EnumUtils<T> {
public EnumUtils(List<T> enumValues) {
foreach (var val in enumValues) {
var enumDescription = DiagnosticUtils.describeEnum(val);
_lookupTable[enumDescription] = val;
_reverseLookupTable[val] = enumDescription;
}
}
public readonly Dictionary<string, T> _lookupTable = new Dictionary<string, T>(){};
public readonly Dictionary<T, string> _reverseLookupTable = new Dictionary<T, string>(){};
public T enumEntry(string enumName) => _lookupTable[enumName];
string name(T enumEntry) => _reverseLookupTable[enumEntry];
}
}

69
com.unity.uiwidgets.devtools/Editor/v2/src/notifications.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.DevTools
{
public class Notifications : StatelessWidget
{
public Notifications(Widget child)
{
this.child = child;
}
public readonly Widget child;
public override Widget build(BuildContext context)
{
return new Overlay(initialEntries: new List<OverlayEntry>
{
new OverlayEntry(
builder: (context2) => new _NotificationsProvider(child: child),
maintainState: true,
opaque: true
)
}
);
}
}
class _NotificationsProvider : StatefulWidget {
public _NotificationsProvider(Key key = null, Widget child = null) : base(key: key)
{
this.child = child;
}
public readonly Widget child;
public override State createState()
{
return new NotificationsState();
}
}
class _InheritedNotifications : InheritedWidget {
public _InheritedNotifications(NotificationsState data = null, Widget child = null)
: base(child: child)
{
this.data = data;
}
public readonly NotificationsState data;
public override bool updateShouldNotify(InheritedWidget oldWidget)
{
return ((_InheritedNotifications)oldWidget).data != data;
}
}
class NotificationsState : State<_NotificationsProvider>
{
public override Widget build(BuildContext context)
{
return new _InheritedNotifications(data: this, child: widget.child);
}
}
}

15
com.unity.uiwidgets.devtools/Editor/v2/src/octicons.cs


using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.DevTools
{
public static class Octicons {
public static readonly IconData bug = new IconData(61714, fontFamily: "Octicons");
public static readonly IconData info = new IconData(61778, fontFamily: "Octicons");
public static readonly IconData deviceMobile = new IconData(61739, fontFamily: "Octicons");
public static readonly IconData clippy = new IconData(61724, fontFamily: "Octicons");
public static readonly IconData package = new IconData(61812, fontFamily: "Octicons");
public static readonly IconData dashboard = new IconData(61733, fontFamily: "Octicons");
public static readonly IconData pulse = new IconData(61823, fontFamily: "Octicons");
public static readonly IconData rss = new IconData(61492, fontFamily: "Octicons");
}
}

72
com.unity.uiwidgets.devtools/Editor/v2/src/split.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.DevTools
{
class Split : StatefulWidget
{
/// Builds a split oriented along [axis].
public Split(
Key key = null,
Axis? axis = null,
List<Widget> children = null,
List<float?> initialFractions = null,
List<float?> minSizes =null,
List<SizedBox> splitters = null
) : base(key: key)
{
D.assert(axis != null);
D.assert(children != null && children.Count >= 2);
D.assert(initialFractions != null && initialFractions.Count >= 2);
D.assert(children?.Count == initialFractions?.Count);
// _verifyFractionsSumTo1(initialFractions);
if (minSizes != null)
{
D.assert(minSizes.Count == children?.Count);
}
if (splitters != null)
{
D.assert(splitters.Count == children?.Count - 1);
}
this.axis = axis;
this.children = children;
this.initialFractions = initialFractions;
this.minSizes = minSizes;
this.splitters = splitters;
}
public static Axis axisFor(BuildContext context, float horizontalAspectRatio) {
var screenSize = MediaQuery.of(context).size;
var aspectRatio = screenSize.width / screenSize.height;
if (aspectRatio >= horizontalAspectRatio) return Axis.horizontal;
return Axis.vertical;
}
public readonly Axis? axis;
public readonly List<Widget> children;
public readonly List<float?> initialFractions;
public readonly List<float?> minSizes;
public readonly List<SizedBox> splitters;
public override State createState()
{
return new _SplitState();
}
class _SplitState : State<Split>
{
public override Widget build(BuildContext context)
{
throw new System.NotImplementedException();
}
}
}
}

82
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/diagnostics_node.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.DevTools.inspector
{
class RemoteDiagnosticsNode : DiagnosticableTree {
public RemoteDiagnosticsNode(
Dictionary<string, Object> json,
FutureOr inspectorService,
bool isProperty,
RemoteDiagnosticsNode parent
)
{
this.json = json;
this.inspectorService = inspectorService;
this.isProperty = isProperty;
}
RemoteDiagnosticsNode parent;
Future<string> propertyDocFuture;
List<RemoteDiagnosticsNode> cachedProperties;
public readonly FutureOr inspectorService; // FutureOr<ObjectGroup>
public readonly Dictionary<string, object> json;
// Future<Dictionary<string, InstanceRef>> _valueProperties;
public readonly bool isProperty;
public DiagnosticsTreeStyle? style {
get
{
return _style != null ?_style: getStyleMember("style", DiagnosticsTreeStyle.sparse);
}
set {
_style = value;
}
}
DiagnosticsTreeStyle? _style;
DiagnosticsTreeStyle getStyleMember(
string memberName, DiagnosticsTreeStyle defaultValue) {
if (!json.ContainsKey(memberName)) {
return defaultValue;
}
string value = json[memberName].ToString();
if (value == null) {
return defaultValue;
}
var style1 = treeStyleUtils.enumEntry(value);
D.assert(style1 != null);
return style ?? defaultValue;
}
private EnumUtils<DiagnosticsTreeStyle> _treeStyleUtils;
EnumUtils<DiagnosticsTreeStyle> treeStyleUtils
{
get
{
List<DiagnosticsTreeStyle> styles = new List<DiagnosticsTreeStyle>();
foreach (DiagnosticsTreeStyle style in Enum.GetValues(typeof(DiagnosticsTreeStyle)))
{
styles.Add(style);
}
return new EnumUtils<DiagnosticsTreeStyle>(styles);
}
}
}
}

7
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_controller.cs


namespace Unity.UIWidgets.DevTools.inspector
{
class InspectorController
{
}
}

87
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_screen.cs


using System.Collections.Generic;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.DevTools.inspector
{
class InspectorScreen : Screen {
public InspectorScreen() : base(
"inspector",
title: "Flutter Inspector",
icon: Octicons.deviceMobile
)
{
}
protected override Widget build(BuildContext context)
{
// var isFlutterApp = serviceManager.connectedApp.isFlutterAppNow;
// var isProfileBuild = serviceManager.connectedApp.isProfileBuildNow;
// if (!isFlutterApp || isProfileBuild) {
// return !isFlutterApp
// ? new DisabledForNonFlutterAppMessage()
// : new DisabledForProfileBuildMessage();
// }
return new InspectorScreenBody();
}
class InspectorScreenBody : StatefulWidget {
public InspectorScreenBody(){}
public override State createState()
{
return new _InspectorScreenBodyState();
}
}
class _InspectorScreenBodyState : State<InspectorScreenBody>
{
bool _layoutExplorerSupported = false;
InspectorController inspectorController;
InspectorTreeControllerFlutter summaryTreeController;
InspectorTreeControllerFlutter detailsTreeController;
public override Widget build(BuildContext context)
{
var summaryTree = new Container(
decoration: new BoxDecoration(
border: Border.all(color: Theme.of(context).focusColor)
),
child: new InspectorTree(
controller: summaryTreeController,
isSummaryTree: true
)
);
var detailsTree = new InspectorTree(
controller: detailsTreeController
);
var splitAxis = Split.axisFor(context, 0.85f);
return new Column(
children: new List<Widget>
{
new Expanded(
child: new Split(
axis: splitAxis,
initialFractions: new List<float?>{0.33f, 0.67f},
children: new List<Widget>
{
summaryTree,
new InspectorDetailsTabController(
detailsTree: detailsTree,
controller: inspectorController,
actionButtons: null,
layoutExplorerSupported: _layoutExplorerSupported
)
}
)
)
}
);
}
}
}
}

41
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_screen_details_tab.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.DevTools.inspector
{
class InspectorDetailsTabController : StatefulWidget
{
public InspectorDetailsTabController(
Widget detailsTree = null,
Widget actionButtons = null,
InspectorController controller = null,
bool? layoutExplorerSupported = null,
Key key = null
) : base(key: key)
{
this.detailsTree = detailsTree;
this.actionButtons = actionButtons;
this.controller = controller;
this.layoutExplorerSupported = layoutExplorerSupported;
}
public readonly Widget detailsTree;
public readonly Widget actionButtons;
public readonly InspectorController controller;
public readonly bool? layoutExplorerSupported;
public override State createState()
{
return new _InspectorDetailsTabControllerState();
}
}
class _InspectorDetailsTabControllerState : State<InspectorDetailsTabController>
{
public override Widget build(BuildContext context)
{
return new Container(child: new Text("this is a text!"));
}
}
}

21
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_service.cs


using System;
namespace Unity.UIWidgets.DevTools.inspector
{
// public class ObjectGroup
// {
// public ObjectGroup(
// string debugName,
// InspectorService inspectorService
// )
// {
// groupName = $"{debugName}_${InspectorService.nextGroupId}";
// InspectorService.nextGroupId++;
// }
//
// /// Object group all objects in this arena are allocated with.
// public readonly string groupName;
// public readonly InspectorService inspectorService;
// bool disposed = false;
// }
}

281
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_tree.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.DevTools.inspector
{
public static class InspectorTreeUtils{
public static readonly float iconPadding = 5.0f;
public static readonly float chartLineStrokeWidth = 1.0f;
public static readonly float columnWidth = 16.0f;
public static readonly float verticalPadding = 10.0f;
public static readonly float rowHeight = 24.0f;
}
abstract class InspectorTreeController
{
public float? lastContentWidth;
public int numRows
{
get
{
return root != null ? root.subtreeSize : 0;
}
}
public InspectorTreeNode root
{
get
{
return _root;
}
set {
_root = value;
}
}
InspectorTreeNode _root;
public InspectorTreeRow getCachedRow(int index) {
// _maybeClearCache();
// while (cachedRows.length <= index) {
// cachedRows.add(null);
// }
// cachedRows[index] ??= root.getRow(index);
// return cachedRows[index];
return null;
}
float horizontalPadding
{
get
{
return 10.0f;
}
}
public float getDepthIndent(int? depth) {
return (depth.Value + 1) * InspectorTreeUtils.columnWidth + horizontalPadding;
}
}
class InspectorTreeNode
{
bool showLinesToChildren {
get
{
return _children.Count > 1 && !_children.Last().isProperty;
}
}
InspectorTreeNode parent
{
get
{
return _parent;
}
set {
_parent = value;
if (_parent != null)
{
_parent.isDirty = true;
}
}
}
InspectorTreeNode _parent;
public bool isDirty
{
get
{
return _isDirty;
}
set {
if (value) {
_isDirty = true;
_shouldShow = null;
if (_childrenCount == null) {
// Already dirty.
return;
}
_childrenCount = null;
if (parent != null) {
parent.isDirty = true;
}
} else {
_isDirty = false;
}
}
}
bool _isDirty = true;
bool? _shouldShow;
public readonly List<InspectorTreeNode> _children;
public bool selected = false;
RemoteDiagnosticsNode _diagnostic;
bool isProperty
{
get
{
return diagnostic == null || diagnostic.isProperty;
}
}
List<InspectorTreeNode> children
{
get
{
return _children;
}
}
void updateShouldShow(bool value) {
if (value != _shouldShow) {
_shouldShow = value;
foreach (var child in children) {
child.updateShouldShow(value);
}
}
}
bool isExpanded
{
get
{
return _isExpanded;
}
set {
if (value != _isExpanded) {
_isExpanded = value;
isDirty = true;
if (_shouldShow ?? false) {
foreach (var child in children) {
child.updateShouldShow(value);
}
}
}
}
}
bool _isExpanded;
int? childrenCount {
get
{
if (!isExpanded) {
_childrenCount = 0;
}
if (_childrenCount != null) {
return _childrenCount;
}
int count = 0;
foreach (InspectorTreeNode child in _children) {
count += child.subtreeSize;
}
_childrenCount = count;
return _childrenCount;
}
}
int? _childrenCount;
public int subtreeSize => childrenCount.GetValueOrDefault(0) + 1;
RemoteDiagnosticsNode diagnostic
{
get
{
return _diagnostic;
}
}
public InspectorTreeRow getRow(int index) {
List<int> ticks = new List<int>();
InspectorTreeNode node = this;
if (subtreeSize <= index) {
return null;
}
int current = 0;
int depth = 0;
while (node != null) {
var style = node.diagnostic?.style;
bool indented = style != DiagnosticsTreeStyle.flat &&
style != DiagnosticsTreeStyle.error;
if (current == index) {
return new InspectorTreeRow(
node: node,
index: index,
ticks: ticks,
depth: depth,
lineToParent:
!node.isProperty && index != 0 && node.parent.showLinesToChildren
);
}
D.assert(index > current);
current++;
List<InspectorTreeNode> children = node._children;
int i;
for (i = 0; i < children.Count; ++i) {
var child = children[i];
var subtreeSize = child.subtreeSize;
if (current + subtreeSize > index) {
node = child;
if (children.Count > 1 &&
i + 1 != children.Count &&
!children.Last().isProperty) {
if (indented) {
ticks.Add(depth);
}
}
break;
}
current += subtreeSize;
}
D.assert(i < children.Count);
if (indented) {
depth++;
}
}
D.assert(false); // internal error.
return null;
}
}
class InspectorTreeRow {
public InspectorTreeRow(
InspectorTreeNode node = null,
int? index = null,
List<int> ticks = null,
int? depth = null,
bool? lineToParent = null
)
{
this.node = node;
this.index = index;
this.ticks = ticks;
this.depth = depth;
this.lineToParent = lineToParent;
}
public readonly InspectorTreeNode node;
public readonly List<int> ticks;
public readonly int? depth;
public readonly int? index;
public readonly bool? lineToParent;
bool isSelected
{
get
{
return node.selected;
}
}
}
}

185
com.unity.uiwidgets.devtools/Editor/v2/src/inspector/inspector_tree_flutter.cs


using System;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.service;
using Unity.UIWidgets.services;
using Unity.UIWidgets.widgets;
using UnityEngine;
namespace Unity.UIWidgets.DevTools.inspector
{
class _InspectorTreeRowWidget : StatefulWidget {
public _InspectorTreeRowWidget(
Key key = null,
InspectorTreeRow row = null,
_InspectorTreeState inspectorTreeState = null
) : base(key: key)
{
this.row = row;
this.inspectorTreeState = inspectorTreeState;
}
public readonly _InspectorTreeState inspectorTreeState;
InspectorTreeNode node
{
get
{
return row.node;
}
}
public readonly InspectorTreeRow row;
public override State createState()
{
return new _InspectorTreeRowState();
}
}
class _InspectorTreeRowState : State<_InspectorTreeRowWidget>
{
public override Widget build(BuildContext context)
{
// return new SizedBox(
// height: rowHeight,
// child: InspectorRowContent(
// row: widget.row,
// expandArrowAnimation: expandArrowAnimation,
// controller: widget.inspectorTreeState.controller,
// onToggle: () => {
// setExpanded(!isExpanded);
// }
// )
// );
return null;
}
}
class InspectorTreeControllerFlutter : InspectorTreeController
{
public readonly float rowWidth = 1200;
float _maxIndent;
public float maxRowIndent {
get
{
if (lastContentWidth == null) {
float maxIndent = 0;
for (int i = 0; i < numRows; i++) {
var row = getCachedRow(i);
if (row != null) {
maxIndent = Mathf.Max(maxIndent, getDepthIndent(row.depth));
}
}
lastContentWidth = maxIndent + maxIndent;
_maxIndent = maxIndent;
}
return _maxIndent;
}
}
}
class InspectorTree : StatefulWidget
{
public InspectorTree(
Key key = null,
InspectorTreeController controller = null,
bool isSummaryTree = false
) : base(key: key)
{
this.controller = controller;
this.isSummaryTree = isSummaryTree;
}
public readonly InspectorTreeController controller;
public bool isSummaryTree;
public override State createState()
{
return new _InspectorTreeState();
}
}
class _InspectorTreeState : State<InspectorTree>
{
ScrollController _scrollControllerY;
ScrollController _scrollControllerX;
FocusNode _focusNode;
InspectorTreeControllerFlutter controller
{
get
{
return (InspectorTreeControllerFlutter)widget.controller;
}
}
bool _handleKeyEvent(FocusNode _, RawKeyEvent event_) {
if (!(event_ is RawKeyDownEvent)) return false;
// if (event_.logicalKey == LogicalKeyboardKey.arrowDown) {
// controller.navigateDown();
// return true;
// } else if (event_.logicalKey == LogicalKeyboardKey.arrowUp) {
// controller.navigateUp();
// return true;
// } else if (event_.logicalKey == LogicalKeyboardKey.arrowLeft) {
// controller.navigateLeft();
// return true;
// } else if (event_.logicalKey == LogicalKeyboardKey.arrowRight) {
// controller.navigateRight();
// return true;
// }
return false;
}
public override Widget build(BuildContext context)
{
// base.build(context);
if (controller == null) {
// Indicate the tree is loading.
return new Center(child: new CircularProgressIndicator());
}
return new Scrollbar(
child: new SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: _scrollControllerX,
child: new SizedBox(
width: controller.rowWidth + controller.maxRowIndent,
child: new Scrollbar(
child: new GestureDetector(
onTap: null,//_focusNode.requestFocus,
child: new Focus(
onKey: _handleKeyEvent,
autofocus: widget.isSummaryTree,
focusNode: _focusNode,
child: ListView.custom(
itemExtent: InspectorTreeUtils.rowHeight,
childrenDelegate: new SliverChildBuilderDelegate(
(context2, index) =>{
InspectorTreeRow row = controller.root?.getRow(index);
return new _InspectorTreeRowWidget(
key: null,// new PageStorageKey(row?.node),
inspectorTreeState: this,
row: row
);
},
childCount: controller.numRows
),
controller: _scrollControllerY
)
)
)
)
)
)
);
}
}
}
正在加载...
取消
保存