Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce IVisualDiagnosticsOverlay #3351

Merged
merged 106 commits into from
Dec 1, 2021

Conversation

drasticactions
Copy link
Contributor

2021-11-10_8.54.04.mov
android.mp4
winui.mp4

To improve the development of UI Tooling for MAUI, we need to introduce some new concepts into the platform. This PR adds IVisualDiagnosticsLayer, IAdornerBorder, and some new extension methods to allow, firstly, for drawing Adorners on top of any IView, but also built to be extended upon in the future.

IVisualDiagnosticsLayer is a new view that is applied to IWindow. It consists of a Maui.Graphics layer and is added as the first layer to the IWindow when it's created. Beyond just accepting IAdornerBorder items to draw on the screen, it also has an event handler for taps, OnTouch. Whenever a touch is applied on the top layer, it gets captured and sent to the event handler. It is then passed down to the underlying view, so it should not affect any functionality.

IAdornerBorder is an IDrawable for drawing Adorners around any IView. These can have their own colors and shapes for drawing adorners. I've created two, RectangleAdornerBorder and RectangleGridAdornerBorder.

Once passed to the Visual Diagnostics Layer, the adorner will be drawn. You can have as many adorners as you want. When one is added, we request the current view to see if there are any IScrollView on it, and if so, we attach to the native element to check when a user scrolls. If they move, we invalidate and redraw. Likewise, when the adorner is added, if the view is not on screen, we can use the same scroll view and scroll to make it visible.

To support this, I also introduced some new extension methods for IVisualTreeElement and IView. These help for scanning the Visual Tree for getting elements back as a list, and help support hit testing elements. You can pass in a point, a series of points, or a rectangle and get whatever elements are contained within those points, based on the native view bounds or the Frame of the element.

@drasticactions drasticactions added the partner/ui-tools .NET UI Tools label Nov 11, 2021
@drasticactions drasticactions marked this pull request as ready for review November 12, 2021 14:05
src/Core/src/Core/IVisualDiagnosticsLayer.cs Outdated Show resolved Hide resolved
src/Core/src/Core/IVisualDiagnosticsLayer.cs Outdated Show resolved Hide resolved
src/Core/src/Core/IVisualDiagnosticsLayer.cs Outdated Show resolved Hide resolved
src/Core/src/Core/IVisualDiagnosticsLayer.cs Outdated Show resolved Hide resolved
src/Core/src/Core/IVisualDiagnosticsLayer.cs Outdated Show resolved Hide resolved

if (_nativeActivity.Window != null)
{
_nativeActivity.Window.DecorView.LayoutChange += DecorView_LayoutChange;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we unsubscribe? Also there is inconsistency with method name casing, e.g. DecorView_LayoutChange vs scroll_ScrollChange.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ScrollViews should unsubscribe when we navigate pages. I also just added IDisposable to the root view so it should handle removing the other native properties should that be called. MAUI does not have an event for when a Window is disposed of. I'm looking at the native implementations, but considering IWindow isn't disposed we could wait until a proper solution is added so our Dispose would be called.

// When it is, we will clear existing adorners.
if (nativeWindow != null && nativeWindow is Frame frame)
{
frame.Navigating += Frame_Navigating;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we unsubscribe? There are other event handlers like this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See answer above. Added IDisposeable and unhooked the events, but I still don't know the best way to dispose these handlers yet.

src/Core/src/Core/Extensions/IViewExtensions.cs Outdated Show resolved Hide resolved
src/Core/src/VisualDiagnostics/AdornerBorder.Impl.cs Outdated Show resolved Hide resolved
src/Core/src/WindowOverlay/WindowOverlay.Android.cs Outdated Show resolved Hide resolved
src/Core/src/WindowOverlay/WindowOverlay.Android.cs Outdated Show resolved Hide resolved
src/Core/src/WindowOverlay/WindowOverlay.Android.cs Outdated Show resolved Hide resolved
src/Core/src/WindowOverlay/WindowOverlay.Android.cs Outdated Show resolved Hide resolved
internal static Matrix4x4 GetViewTransform(this IView view) => new Matrix4x4();
internal static Graphics.Matrix4x4 GetViewTransform(this IView view) => new Matrix4x4();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this in System.Numerics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rmarinho
Copy link
Member

@drasticactions needs rebase again, sorry merged the screenshot api pr

# Conflicts:
#	src/Core/src/Platform/Android/ViewExtensions.cs
#	src/Core/src/Platform/Standard/ViewExtensions.cs
#	src/Core/src/Platform/Windows/ViewExtensions.cs
#	src/Core/src/Platform/iOS/ViewExtensions.cs
@rmarinho rmarinho self-requested a review November 30, 2021 22:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
fixed-in-6.0.101-preview.11.3 Look for this fix in 6.0.101-preview.11.3! partner/ui-tools .NET UI Tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants