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

Create borders on demand #1

Closed
wants to merge 20 commits into from
Closed

Create borders on demand #1

wants to merge 20 commits into from

Conversation

rozele
Copy link
Owner

@rozele rozele commented Jul 17, 2017

Creating this pull request to start a dialog.

border = new Border { BorderBrush = s_defaultBorderBrush, Tag = 123 };
view.Children.Insert(0, border);

border.SetBinding(FrameworkElement.WidthProperty, new Binding
Copy link
Owner Author

@rozele rozele Jul 17, 2017

Choose a reason for hiding this comment

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

Not sure what would be more of a hack, but the ViewManager class has the SetDimensions method that you can override to intercept the width/height settings of the view. #Closed

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

return GetBorder(view) != null;
}

private Border GetBorder(TCanvas view)
Copy link
Owner Author

@rozele rozele Jul 17, 2017

Choose a reason for hiding this comment

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

GetBorder [](start = 23, length = 9)

I can see this being problematic if the actual first child is a border for some custom native component. #Closed

Copy link
Owner Author

Choose a reason for hiding this comment

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

One approach might be to subclass Canvas and maintain the state about whether the first child is a built-in Border there.


In reply to: 127780765 [](ancestors = 127780765)

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

view.Background = new SolidColorBrush(ColorHelpers.Parse(color));
if (!HasBorder(view) && ColorHelpers.IsTransparent(color))
return;

Copy link
Owner Author

@rozele rozele Jul 17, 2017

Choose a reason for hiding this comment

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

I think at some point we relied on transparent borders because without them the views weren't picked up as click targets. However, we've since done a bunch of work with the TouchHandler, so it may no longer be a problem, can you confirm if you have buttons with transparent backgrounds that they can still be targeted with and w/o a border #Closed

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

Need to check that... #Closed

@rozele
Copy link
Owner Author

rozele commented Jul 17, 2017

Would be good to clean up styles to follow the rest of the code base, I haven't got around to enabling any kind of linter, but just off the top of my head I saw some protected / private methods that needed to be ordered in the class and use { } on all blocks (even one liners) #Closed

@rozele
Copy link
Owner Author

rozele commented Jul 17, 2017

view.BorderBrush = color.HasValue
? new SolidColorBrush(ColorHelpers.Parse(color.Value))
: s_defaultBorderBrush;
if (HasBorder(view) || color.HasValue && !ColorHelpers.IsTransparent(color.Value))
Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

This optimization needs to be done more carefully. If we first set border color to 0 (a fully transparent black color), this if will ignore the request because the border wouldn't be visible. However if later we set border width to 2, the border will be created with the default border brush, which is an opaque black color, while it should be transparent. #Closed

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fair enough, why not just eliminate the optimization?


In reply to: 127868591 [](ancestors = 127868591)

{
border.Width = dimensions.Width;
border.Height = dimensions.Height;
}
Copy link
Owner Author

@rozele rozele Jul 18, 2017

Choose a reason for hiding this comment

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

Just curious, do you think this is a better approach? XAML binding also worked, I wasn't sure what felt like more of a hack. Do you think there's any performance benefits to either? #Closed

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

SetDimensions looks simpler. IMO, difference in performance would be hard to measure. #Closed


return (TFrameworkElement)parent.Child;
var pointerEvents = EnumHelpers.ParseNullable<PointerEvents>(pointerEventsValue) ?? PointerEvents.Auto;
view.SetPointerEvents(pointerEvents);
}
Copy link
Owner Author

@rozele rozele Jul 18, 2017

Choose a reason for hiding this comment

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

I'm not sure why these props are here and not on either:
a) ReactViewManager
b) BaseViewManager

I'll have to do some digging. #Closed

Copy link
Owner Author

@rozele rozele Jul 18, 2017

Choose a reason for hiding this comment

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

Ah, yeah these two props, accessible and pointerEvents should be on ReactViewManager (they currently are in the master branch of react-native-windows).


In reply to: 127970487 [](ancestors = 127970487)

Copy link
Owner Author

Choose a reason for hiding this comment

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

collapsible should also be moved, I added a PR - microsoft#1208


In reply to: 127974737 [](ancestors = 127974737,127970487)

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

I've also moved collapsable to ReactViewManager #Closed


if (borderParent != null)
{
x -= borderParent.GetLeftBorderWidth();
Copy link
Owner Author

@rozele rozele Jul 18, 2017

Choose a reason for hiding this comment

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

GetLeftBorderWidth [](start = 34, length = 18)

Can you also delete these helpers, which are now no longer needed? I.e., delete ReactShadowNodeExtensions.cs. #Closed

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

{
/// <summary>
/// Checks if the Canvas has a Border already.
/// </summary>
protected override bool HasBorder(TCanvas view)
Copy link
Owner Author

@rozele rozele Jul 18, 2017

Choose a reason for hiding this comment

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

HasBorder [](start = 32, length = 9)

Maybe we should just leave HasBorder and GetOrCreateBorder abstract, then you can implement them on ReactViewManager. If we're going to keep this base class, I'd rather not tie it to a specific Canvas subclass. #Closed

Copy link

@antonkh antonkh Jul 18, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

@@ -12,16 +13,37 @@ namespace ReactNative.UIManager
/// View parent manager for bordered canvases.
/// </summary>
public abstract class BorderedCanvasManager<TCanvas> : BorderedViewParentManager<TCanvas>
where TCanvas : Canvas
where TCanvas : BorderedCanvas
Copy link
Owner Author

@rozele rozele Jul 20, 2017

Choose a reason for hiding this comment

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

BorderedCanvas [](start = 24, length = 14)

This can be reverted to Canvas. #Closed

Copy link

Choose a reason for hiding this comment

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

Fixed. I had to move SetDimensions to ReactViewManager as it changes the border size.

/// Adds a Border to a Canvas if it hasn't been added yet.
/// </summary>
protected abstract Border GetOrCreateBorder(TFrameworkElement view);


Copy link
Owner Author

@rozele rozele Jul 20, 2017

Choose a reason for hiding this comment

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

Extra newline. #Closed

Copy link

@antonkh antonkh Jul 20, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

@@ -1,4 +1,5 @@
using ReactNative.UIManager.Annotations;
using ReactNative.Reflection;
using ReactNative.UIManager.Annotations;
Copy link
Owner Author

@rozele rozele Jul 20, 2017

Choose a reason for hiding this comment

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

Delete this? #Closed

{
return (color & ~Transparent) == 0;
}

Copy link
Owner Author

@rozele rozele Jul 20, 2017

Choose a reason for hiding this comment

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

Is this still being used or can it be deleted? #Closed

Copy link

@antonkh antonkh Jul 20, 2017

Choose a reason for hiding this comment

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

Yup, it can be deleted too. #Closed

for (var i = GetChildCount(parent) - 1; i >= 0; i--)
{
RemoveChildAt(parent, i);
}
Copy link
Owner Author

@rozele rozele Jul 20, 2017

Choose a reason for hiding this comment

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

Can you inject a HasBorder check and just clear children in case there is no border? That way there's no net performance impact on views without a border. #Closed

Copy link

@antonkh antonkh Jul 20, 2017

Choose a reason for hiding this comment

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

Fixed #Closed

Copy link
Owner Author

Choose a reason for hiding this comment

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

It turns out we use RemoveAllChildren quite frequently to tear down views via a depth-first recursive call to this method for the entire subtree being removed. Most views will not have a border, so it is a reasonable optimization.


In reply to: 128656455 [](ancestors = 128656455)

@rozele
Copy link
Owner Author

rozele commented Jul 21, 2017

    where TCanvas : Canvas

Can you use HasBorder and GetOrCreateBorder to get the border reference and set the dimensions from the base class? I.e.,

        public override void SetDimensions(BorderedCanvas view, Dimensions dimensions)
        {
            base.SetDimensions(view, dimensions);

            if (HasBorder(view))
            {
                var border = GetOrCreateBorder(view);           
                border.Width = dimensions.Width;
                border.Height = dimensions.Height;
            }
        }

For that matter, you could put it in the BorderedViewParentManager base class where the abstracts first show up.


Refers to: ReactWindows/ReactNative.Shared/UIManager/BorderedCanvasManager.cs:16 in e5f9f64. [](commit_id = e5f9f64, deletion_comment = False)

@rozele
Copy link
Owner Author

rozele commented Jul 27, 2017

    where TCanvas : Canvas

Is there something blocking you from putting this in the BorderedViewParentManager base class? Honestly the number of base classes here is quite useless at this point. I'm not even sure why all these base classes were introduced 😕


In reply to: 316868201 [](ancestors = 316868201)


Refers to: ReactWindows/ReactNative.Shared/UIManager/BorderedCanvasManager.cs:16 in e5f9f64. [](commit_id = e5f9f64, deletion_comment = False)

@rozele
Copy link
Owner Author

rozele commented Jul 29, 2017

@antonkh - It turns out SetDimensions won't work after all, because the LayoutAnimation bypasses the SetDimensions API. We'll need to use the XAML binding approach.

@rozele
Copy link
Owner Author

rozele commented Aug 8, 2017

Closed, thanks for your iterations on this @antonkh

@rozele rozele closed this Aug 8, 2017
acoates-ms pushed a commit that referenced this pull request Jun 4, 2024
* Integrate 5/14

* Change files

* Fix CI #1

* Re-add BoundedConsumableBuffer.h

* Integrate 5/18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants