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

Layoutable and SizeCalculable protocols #148

Merged
merged 11 commits into from
Jun 15, 2018

Conversation

antoinelamy
Copy link
Contributor

Refactoring to avoid having to deal directly with view types making it easier to extend layouting to other APIs (ie: CALayer).

I avoided moving/adding files for now to avoid potential conflicts but I feel like some things should be renamed/moved. For exemple, getRect / setRect / isLTR() functions should probably be moved where protocol conformance is declared.

@@ -16,7 +16,7 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

/*
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Temporarily commented out, should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should probably copy/paste comments before deleting the file 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Keep the file for now, we could do that in another PR

@@ -23,7 +23,7 @@ import Foundation
import UIKit

extension UIView {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should probably be moved in the extension where protocol conformance is declared

Copy link
Member

Choose a reason for hiding this comment

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

I agree, this should be moved in UIView+PinLayout.swift and NSView+PinLayout.swift

private func computeLegacyFitSize(size: Size) -> Size {
guard let sizeCalculableView = view as? SizeCalculable else {
Copy link
Member

Choose a reason for hiding this comment

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

It would be better to check if the View implement SizeCalculable in the method setAdjustSizeType() for types .fitTypeWidth, .fitTypeHeight, .fitTypeWidthFlexible, .fitTypeHeightFlexible and .fitSizeLegacy. And here we should simply asserts in the guard, since it should never occurs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

private func computeSizeToFit(adjustSizeType: AdjustSizeType, size: Size) -> Size {
guard let sizeCalculableView = view as? SizeCalculable else {
Copy link
Member

Choose a reason for hiding this comment

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

Same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

let layoutSuperviewRect = layoutSuperview.getRect(keepTransform: keepTransform)
return CGPoint(x: point.x - layoutSuperviewRect.origin.x,
y: point.y - layoutSuperviewRect.origin.y)
// TOOD: Handle all cases. computeCoordinates should compute coordinates using only untransformed
// coordinates, but UIView.convert(...) below use transformed coordinates!
// Currently we only support 1 and 2 levels.
} else {
return referenceSuperview.convert(point, to: layoutSuperview)
return referenceSuperview.convert(point, toView: layoutSuperview as! View.View)
Copy link
Member

Choose a reason for hiding this comment

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

It could be layoutSuperview as? View.View.
Also, View.View is a little bit weird 🙂, in my branch I was using TLayoutable instead of View for the generic type name. What do you think?

@@ -152,7 +152,8 @@ extension PinLayoutImpl {
#endif
}

displayText += ", Tag: \(view.tag))\n"
// Removed, layoutable tag should probably not be exposed
//displayText += ", Tag: \(view.tag))\n"
Copy link
Member

Choose a reason for hiding this comment

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

Maybe the Layoutable should expose a property warningContext, that would expose a String returning this block content:

var hierarchy: [String] = []
....
displayText += ", Tag: \(view.tag))\n"

The idea here is to give as much info as possible of the View being layouted

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would probably feel weird to have it directly in Layoutable as it have nothing to do with layout. If the goal is to print as much info as possible, why not use the built-in CustomDebugStringConvertible protocol that already serve that purpose and print the tag if any and many more properties. We could add it as a requirement to Layoutable, what do you think?

protocol Layoutable: AnyObject, Equatable, CustomDebugStringConvertible

Copy link
Member

Choose a reason for hiding this comment

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

I didn't know this one, excellent idea.


import Foundation

extension Layoutable {
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, really nice to add this as an extension of the Layoutable protocol 👍

@@ -45,4 +35,9 @@ public extension NSView {
}
}

@available(OSX 10.10, *)
extension NSControl: SizeCalculable {
Copy link
Member

Choose a reason for hiding this comment

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

👍


import Foundation

@available(OSX 10.10, *)
Copy link
Member

Choose a reason for hiding this comment

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

The @available is not really required in the protocol declaration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

extension UIView: Layoutable, SizeCalculable {
public typealias View = UIView

public func convert(_ point: CGPoint, toView view: UIView) -> CGPoint {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure to understand why does this method is required? Why not simply use directly the method convert(:CGPoint, to: UIView?) 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I initially thought it was a collision with the function taking UISpaceCoordinates as a parameter but after investigation, it was because the view parameter is optional. Fixed.

@@ -12,7 +12,7 @@ import Foundation
import UIKit

extension UIView {
func getRect(keepTransform: Bool) -> CGRect {
public func getRect(keepTransform: Bool) -> CGRect {
Copy link
Member

Choose a reason for hiding this comment

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

To be cleaner, I would move immediately getRect and setRect in UIView+PinLayout.swift

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -57,7 +57,7 @@ extension UIView {
import AppKit

extension NSView {
func getRect(keepTransform: Bool) -> CGRect {
public func getRect(keepTransform: Bool) -> CGRect {
Copy link
Member

Choose a reason for hiding this comment

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

Same here, I would move immediately getRect and setRect in NSView+PinLayout.swift

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -152,7 +152,7 @@ extension PinLayoutImpl {
#endif
}

displayText += ", Tag: \(view.tag))\n"
displayText += ", Debug description: \(view.debugDescription))\n"
Copy link
Member

Choose a reason for hiding this comment

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

In fact @antoinelamy, I would have put everything in the debugDescription property, anyway we will need to do that for other Layoutable.

I would include all this:

    var hierarchy: [String] = []
    ...
     if hierarchy.count > 0 {	  
             
     }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lucdion not sure about that one, debugDescription is already implemented on NSView/UIView and it's already pretty verbose. Furthermore, we cannot override an existing function from an extension so I would leave the responsibility to the caller with special debugging needs to override debugDescription in their subclasses. What do you think @lucdion ?

@lucdion lucdion merged commit 230e533 into layoutBox:master Jun 15, 2018
@lucdion
Copy link
Member

lucdion commented Jun 15, 2018

Thanks @antoinelamy for this amazing PR 👍 😄

@antoinelamy antoinelamy deleted the refactor/layoutable branch June 27, 2018 13:08
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