Implement layout constraint conversion to internal solver constraints

This commit is contained in:
Benjamin Johnson 2023-05-27 10:58:27 +10:00
parent fccf8771e6
commit 2e98bd5366
9 changed files with 1124 additions and 146 deletions

View file

@ -29,10 +29,15 @@
#import <Foundation/NSGeometry.h>
#import <Foundation/NSKeyedArchiver.h>
#import <AppKit/NSLayoutAnchor.h>
#import <AppKit/NSView.h>
#import <AppKit/NSWindow.h>
@class NSControl, NSAnimation, NSArray, NSMutableArray, NSDictionary;
@class NSControl, NSAnimation, NSArray, NSMutableArray, NSDictionary, NSView;
typedef float NSLayoutPriority;
typedef struct GSIntrinsicContentSizePriority {
NSLayoutPriority horizontal;
NSLayoutPriority vertical;
} GSIntrinsicContentSizePriority;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST)
@ -41,7 +46,6 @@ extern "C" {
#endif
// Priority
typedef float NSLayoutPriority;
static const NSLayoutPriority NSLayoutPriorityRequired = 1000.0;
static const NSLayoutPriority NSLayoutPriorityDefaultHigh = 750.0;
static const NSLayoutPriority NSLayoutPriorityDragThatCanResizeWindow = 510.0;
@ -168,22 +172,6 @@ APPKIT_EXPORT_CLASS
@end
@interface NSView (NSConstraintBasedLayoutCoreMethods)
- (void) updateConstraints;
- (void) updateConstraintsForSubtreeIfNeeded;
@end
@interface NSView (NSConstraintBasedLayoutInstallingConstraints)
- (void) addConstraint: (NSLayoutConstraint *)constraint;
- (void) addConstraints: (NSArray*)constraints;
@end
@interface NSWindow (NSConstraintBasedLayoutCoreMethods)
- (void) _bootstrapAutoLayout;

View file

@ -37,6 +37,7 @@
#import <AppKit/NSGraphicsContext.h>
#import <AppKit/NSResponder.h>
#import <AppKit/NSUserInterfaceLayout.h>
#import <AppKit/NSLayoutConstraint.h>
@class NSArray;
@class NSAttributedString;
@ -123,6 +124,9 @@ typedef enum _NSFocusRingType {
NSFocusRingTypeExterior = 2
} NSFocusRingType;
extern const CGFloat NSViewNoInstrinsicMetric;
extern const CGFloat NSViewNoIntrinsicMetric;
APPKIT_EXPORT_CLASS
@interface NSView : NSResponder
{
@ -182,6 +186,9 @@ PACKAGE_SCOPE
BOOL _needsLayout;
BOOL _needsUpdateConstraints;
BOOL _translatesAutoresizingMaskIntoConstraints;
float _contentCompressionResistancePriority;
GSIntrinsicContentSizePriority _huggingPriorities;
GSIntrinsicContentSizePriority _compressionPriorities;
NSUInteger _autoresizingMask;
NSFocusRingType _focusRingType;
@ -672,10 +679,61 @@ PACKAGE_SCOPE
- (BOOL) translatesAutoresizingMaskIntoConstraints;
- (void) setTranslatesAutoresizingMaskIntoConstraints: (BOOL)translatesAutoresizingMaskIntoConstraints;
#endif
#if GS_HAS_DECLARED_PROPERTIES
@property float contentCompressionResistancePriority;
#else
- (BOOL) contentCompressionResistancePriority;
- (void) setContentCompressionResistancePriority: (float)priority;
#endif
#if GS_HAS_DECLARED_PROPERTIES
@property (readonly) NSSize intrinsicContentSize;
#else
- (BOOL) intrinsicContentSize;
#endif
#if GS_HAS_DECLARED_PROPERTIES
@property (readonly) CGFloat baselineOffsetFromBottom;
#else
- (CGFloat) baselineOffsetFromBottom;
#endif
#if GS_HAS_DECLARED_PROPERTIES
@property (readonly) CGFloat firstBaselineOffsetFromTop;
#else
- (CGFloat) firstBaselineOffsetFromTop;
#endif
#endif
@end
#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
@interface NSView (NSConstraintBasedLayoutCoreMethods)
- (void) updateConstraints;
- (void) updateConstraintsForSubtreeIfNeeded;
- (NSLayoutPriority)contentHuggingPriorityForOrientation:(NSLayoutConstraintOrientation)orientation;
- (void)setContentHuggingPriority:(NSLayoutPriority)priority forOrientation:(NSLayoutConstraintOrientation)orientation;
- (NSLayoutPriority)contentCompressionResistancePriorityForOrientation:(NSLayoutConstraintOrientation)orientation;
- (void)setContentCompressionResistancePriority:(NSLayoutPriority)priority forOrientation:(NSLayoutConstraintOrientation)orientation;
@end
@interface NSView (NSConstraintBasedLayoutInstallingConstraints)
- (void) addConstraint: (NSLayoutConstraint *)constraint;
- (void) addConstraints: (NSArray*)constraints;
@end
#endif
@class NSAffineTransform;

View file

@ -26,6 +26,38 @@
#import "GSFastEnumeration.h"
#import "NSViewPrivate.h"
enum
{
GSLayoutAttributeNotAnAttribute = 0,
GSLayoutAttributeLeft = 1,
GSLayoutAttributeRight,
GSLayoutAttributeTop,
GSLayoutAttributeBottom,
GSLayoutAttributeLeading,
GSLayoutAttributeTrailing,
GSLayoutAttributeWidth,
GSLayoutAttributeHeight,
GSLayoutAttributeCenterX,
GSLayoutAttributeCenterY,
GSLayoutAttributeLastBaseline,
GSLayoutAttributeBaseline = GSLayoutAttributeLastBaseline,
GSLayoutAttributeFirstBaseline,
GSLayoutAttributeMinX = 32,
GSLayoutAttributeMinY = 33,
GSLayoutAttributeMaxX = 36,
GSLayoutAttributeMaxY = 37
};
typedef NSInteger GSLayoutAttribute;
enum
{
GSLayoutViewAttributeBaselineOffsetFromBottom = 1,
GSLayoutViewAttributeFirstBaselineOffsetFromTop,
GSLayoutViewAttributeIntrinsicWidth,
GSLayoutViewAttributeInstrinctHeight,
} GSLayoutViewAttribue;
typedef NSInteger GSLayoutViewAttribute;
@interface GSAutoLayoutEngine (PrivateMethods)
- (GSCSConstraint *) solverConstraintForConstraint:
@ -79,6 +111,121 @@
- (BOOL) updateViewAligmentRect: (GSCSSolution *)solution view: (NSView *)view;
- (BOOL) hasAddedWidthAndHeightConstraintsToView: (NSView *)view;
- (GSCSVariable *) variableForView: (NSView *)view
andAttribute: (GSLayoutAttribute)attribute;
- (GSCSVariable *) variableForView: (NSView *)view
andViewAttribute: (GSLayoutViewAttribute)attribute;
- (void) resolveVariableForView: (NSView *)view
attribute: (GSLayoutViewAttribute)attribute;
- (GSCSVariable *) createVariableWithName: (NSString *)name;
- (GSCSVariable *) getExistingVariableForView: (NSView *)view
withAttribute: (GSLayoutAttribute)attribute;
- (GSCSVariable *) getExistingVariableForView: (NSView *)view
withViewAttribute:
(GSLayoutViewAttribute)attribute;
- (GSCSVariable *) variableWithName: (NSString *)variableName;
- (NSString *) getVariableIdentifierForView: (NSView *)view
withAttribute: (GSLayoutAttribute)attribute;
- (NSString *) getAttributeName: (GSLayoutAttribute)attribute;
- (NSString *) getLayoutViewAttributeName: (GSLayoutViewAttribute)attribute;
- (NSString *) getDynamicVariableIdentifierForView: (NSView *)view
withViewAttribute:
(GSLayoutViewAttribute)attribute;
- (NSString *) getIdentifierForView: (NSView *)view;
- (NSInteger) registerView: (NSView *)view;
- (void) addInternalWidthConstraintForView: (NSView *)view;
- (void) addInternalHeightConstraintForView: (NSView *)view;
- (void) addInternalLeadingConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalTrailingConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalLeftConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalRightConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalBottomConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalTopConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalCenterXConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalCenterYConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalFirstBaselineConstraintsForView: (NSView *)view
constraint:
(GSCSConstraint *)constraint;
- (void) addInternalBaselineConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint;
- (void) addInternalSolverConstraint: (GSCSConstraint *)constraint
forView: (NSView *)view;
- (void) addIntrinsicContentSizeConstraintsToView: (NSView *)view;
- (void) addSupportingInstrictSizeConstraintsToView: (NSView *)view
orientation:
(NSLayoutConstraintOrientation)
orientation
instrinctSizeAttribute:
(GSLayoutViewAttribute)instrinctSizeAttribute
dimensionAttribute:
(GSLayoutAttribute)dimensionAttribute;
- (void) addSupportingConstraintForLayoutViewAttribute:
(GSLayoutViewAttribute)attribute
view: (NSView *)view
constraint:
(GSCSConstraint *)constraint;
- (GSCSConstraint *) solverConstraintForRelationalConstraint:
(NSLayoutConstraint *)constraint;
- (GSCSConstraint *) solverConstraintForNonRelationalConstraint:
(NSLayoutConstraint *)constraint;
- (void) addObserverToConstraint: (NSLayoutConstraint *)constranit;
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context;
- (void) updateConstraint: (NSLayoutConstraint *)constraint;
- (void) addSupportingSolverConstraint: (GSCSConstraint *)supportingConstraint
forSolverConstraint: (GSCSConstraint *)constraint;
- (CGFloat) valueForView: (NSView *)view
attribute: (GSLayoutViewAttribute)attribute;
- (int) getConstantMultiplierForLayoutAttribute: (NSLayoutAttribute)attribute;
@end
@implementation GSAutoLayoutEngine
@ -199,8 +346,280 @@
- (GSCSConstraint *) solverConstraintForConstraint:
(NSLayoutConstraint *)constraint
{
// FIXME Map NSLayoutConstraint to GSCSConstraint
return AUTORELEASE([[GSCSConstraint alloc] init]);
if ([constraint secondItem] == nil)
{
return [self solverConstraintForNonRelationalConstraint: constraint];
}
else
{
return [self solverConstraintForRelationalConstraint: constraint];
}
}
- (GSCSConstraint *) solverConstraintForNonRelationalConstraint:
(NSLayoutConstraint *)constraint
{
GSCSVariable *firstItemConstraintVariable =
[self variableForView: [constraint firstItem]
andAttribute: (GSLayoutAttribute)[constraint firstAttribute]];
GSCSConstraint *newConstraint;
switch ([constraint relation])
{
case NSLayoutRelationLessThanOrEqual:
newConstraint = [GSCSConstraint constraintWithLeftVariable: firstItemConstraintVariable operator: GSCSConstraintOperatorLessThanOrEqual rightConstant: [constraint constant]];
break;
case NSLayoutRelationEqual:
newConstraint = [GSCSConstraint constraintWithLeftVariable: firstItemConstraintVariable operator: GSCSConstraintOperatorEqual rightConstant: [constraint constant]];
break;
case NSLayoutRelationGreaterThanOrEqual:
newConstraint = [GSCSConstraint constraintWithLeftVariable: firstItemConstraintVariable operator: GSCSConstraintOperationGreaterThanOrEqual rightConstant: [constraint constant]];
break;
}
GSCSStrength *strength =
[[GSCSStrength alloc] initWithName: nil strength: [constraint priority]];
[newConstraint setStrength: strength];
RELEASE(strength);
return newConstraint;
}
- (GSCSConstraint *) solverConstraintForRelationalConstraint:
(NSLayoutConstraint *)constraint
{
GSCSVariable *firstItemConstraintVariable =
[self variableForView: [constraint firstItem]
andAttribute: (GSLayoutAttribute)[constraint firstAttribute]];
GSCSVariable *secondItemConstraintVariable =
[self variableForView: [constraint secondItem]
andAttribute: (GSLayoutAttribute)[constraint secondAttribute]];
CGFloat multiplier = [constraint multiplier];
GSCSConstraintOperator op = GSCSConstraintOperatorEqual;
switch ([constraint relation])
{
case NSLayoutRelationEqual:
op = GSCSConstraintOperatorEqual;
break;
case NSLayoutRelationLessThanOrEqual:
op = GSCSConstraintOperatorLessThanOrEqual;
break;
case NSLayoutRelationGreaterThanOrEqual:
op = GSCSConstraintOperationGreaterThanOrEqual;
break;
}
double constant =
[self getConstantMultiplierForLayoutAttribute: [constraint secondAttribute]] * [constraint constant];
GSCSLinearExpression *rightExpression = [[GSCSLinearExpression alloc]
initWithVariable: secondItemConstraintVariable
coefficient: multiplier
constant: constant];
GSCSConstraint *newConstraint = [GSCSConstraint constraintWithLeftVariable: firstItemConstraintVariable operator: op rightExpression: rightExpression];
RELEASE(rightExpression);
GSCSStrength *strength =
[[GSCSStrength alloc] initWithName: nil strength: [constraint priority]];
[newConstraint setStrength: strength];
RELEASE(strength);
return newConstraint;
}
- (int) getConstantMultiplierForLayoutAttribute: (NSLayoutAttribute)attribute
{
switch (attribute)
{
case NSLayoutAttributeTop:
return -1;
case NSLayoutAttributeBottom:
return 1;
case NSLayoutAttributeLeading:
return 1;
case NSLayoutAttributeTrailing:
return -1;
case NSLayoutAttributeLeft:
return 1;
case NSLayoutAttributeRight:
return -1;
default:
return 1;
}
}
- (GSCSVariable *) variableForView: (NSView *)view
andViewAttribute: (GSLayoutViewAttribute)attribute
{
NSString *variableName = [self getDynamicVariableIdentifierForView: view
withViewAttribute: attribute];
GSCSVariable *existingVariable = [self variableWithName: variableName];
if (existingVariable != nil)
{
return existingVariable;
}
else
{
return [self createVariableWithName: variableName];
}
}
- (GSCSVariable *) variableForView: (NSView *)view
andAttribute: (GSLayoutAttribute)attribute
{
NSString *variableName =
[self getVariableIdentifierForView: view withAttribute: attribute];
GSCSVariable *existingVariable = [self variableWithName: variableName];
if (existingVariable != nil)
{
return existingVariable;
}
else
{
return [self createVariableWithName: variableName];
}
}
- (GSCSVariable *) getExistingVariableForView: (NSView *)view
withAttribute: (GSLayoutAttribute)attribute
{
NSString *variableIdentifier =
[self getVariableIdentifierForView: view
withAttribute: (GSLayoutAttribute)attribute];
return [self variableWithName: variableIdentifier];
}
- (GSCSVariable *) createVariableWithName: (NSString *)name
{
GSCSVariable *variable = [GSCSVariable variableWithValue: 0 name: name];
[_variablesByKey setObject: variable forKey: name];
return variable;
}
- (GSCSVariable *) getExistingVariableForView: (NSView *)view
withViewAttribute: (GSLayoutViewAttribute)attribute
{
NSString *variableIdentifier =
[self getDynamicVariableIdentifierForView: view
withViewAttribute: attribute];
return [self variableWithName: variableIdentifier];
}
- (GSCSVariable *) variableWithName: (NSString *)variableName
{
return [_variablesByKey objectForKey: variableName];
}
- (NSString *) getVariableIdentifierForView: (NSView *)view
withAttribute: (GSLayoutAttribute)attribute
{
NSString *viewIdentifier = [self getIdentifierForView: view];
return [NSString stringWithFormat: @"%@.%@", viewIdentifier,
[self getAttributeName: attribute]];
}
- (NSString *) getAttributeName: (GSLayoutAttribute)attribute
{
switch (attribute)
{
case GSLayoutAttributeTop:
return @"top";
case GSLayoutAttributeBottom:
return @"bottom";
case GSLayoutAttributeLeading:
return @"leading";
case GSLayoutAttributeLeft:
return @"left";
case GSLayoutAttributeRight:
return @"right";
case GSLayoutAttributeTrailing:
return @"trailing";
case GSLayoutAttributeHeight:
return @"height";
case GSLayoutAttributeWidth:
return @"width";
case GSLayoutAttributeCenterX:
return @"centerX";
case GSLayoutAttributeCenterY:
return @"centerY";
case GSLayoutAttributeBaseline:
return @"baseline";
case GSLayoutAttributeFirstBaseline:
return @"firstBaseline";
case GSLayoutAttributeMinX:
return @"minX";
case GSLayoutAttributeMinY:
return @"minY";
case GSLayoutAttributeMaxX:
return @"maxX";
case GSLayoutAttributeMaxY:
return @"maxY";
default:
[[NSException exceptionWithName: @"Not handled"
reason: @"GSLayoutAttribute not handled"
userInfo: nil] raise];
return nil;
}
}
- (NSString *) getLayoutViewAttributeName: (GSLayoutViewAttribute)attribute
{
switch (attribute)
{
case GSLayoutViewAttributeBaselineOffsetFromBottom:
return @"baselineOffsetFromBottom";
case GSLayoutViewAttributeFirstBaselineOffsetFromTop:
return @"firstBaselineOffsetFromTop";
case GSLayoutViewAttributeIntrinsicWidth:
return @"intrinsicContentSize.width";
case GSLayoutViewAttributeInstrinctHeight:
return @"intrinsicContentSize.height";
default:
[[NSException
exceptionWithName: @"GSLayoutViewAttribute Not handled"
reason: @"The provided GSLayoutViewAttribute does "
@"not have a name"
userInfo: nil] raise];
return nil;
}
}
- (NSString *) getDynamicVariableIdentifierForView: (NSView *)view
withViewAttribute:
(GSLayoutViewAttribute)attribute
{
NSString *viewIdentifier = [self getIdentifierForView: view];
return
[NSString stringWithFormat: @"%@.%@", viewIdentifier,
[self getLayoutViewAttributeName: attribute]];
}
- (NSString *) getIdentifierForView: (NSView *)view
{
NSUInteger viewIndex;
NSNumber *existingViewIndex = [self indexForView: view];
if (existingViewIndex)
{
viewIndex = [existingViewIndex unsignedIntegerValue];
}
else
{
viewIndex = [self registerView: view];
}
return [NSString stringWithFormat: @"view%ld", (long)viewIndex];
}
- (NSInteger) registerView: (NSView *)view
{
NSUInteger viewIndex = [_trackedViews count];
[_trackedViews addObject: view];
[_viewIndexByViewHash
setObject: [NSNumber numberWithUnsignedInteger: viewIndex]
forKey: [NSNumber numberWithUnsignedInteger: [view hash]]];
return viewIndex;
}
- (void) mapLayoutConstraint: (NSLayoutConstraint *)layoutConstraint
@ -209,14 +628,397 @@
[_constraintsByAutoLayoutConstaintHash setObject: solverConstraint
forKey: layoutConstraint];
[_layoutConstraintsBySolverConstraint setObject: layoutConstraint
forKey: solverConstraint];
forKey: solverConstraint];
}
- (void) addSupportingInternalConstraintsToView: (NSView *)view
forAttribute: (NSLayoutAttribute)attribute
constraint: (GSCSConstraint *)constraint
{
// FIXME addSupportingInternalConstraintsToView
if (![self hasAddedWidthAndHeightConstraintsToView: view])
{
[self addInternalWidthConstraintForView: view];
[self addInternalHeightConstraintForView: view];
[self addIntrinsicContentSizeConstraintsToView: view];
}
switch (attribute)
{
case NSLayoutAttributeTrailing:
[self addInternalTrailingConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeLeading:
[self addInternalLeadingConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeLeft:
[self addInternalLeftConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeRight:
[self addInternalRightConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeTop:
[self addInternalTopConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeBottom:
[self addInternalBottomConstraintForView: view
constraint: constraint];
break;
case NSLayoutAttributeCenterX:
[self addInternalCenterXConstraintsForView: view
constraint: constraint];
break;
case NSLayoutAttributeCenterY:
[self addInternalCenterYConstraintsForView: view
constraint: constraint];
break;
case NSLayoutAttributeBaseline:
[self addInternalBaselineConstraintsForView: view
constraint: constraint];
break;
case NSLayoutAttributeFirstBaseline:
[self addInternalFirstBaselineConstraintsForView: view
constraint: constraint];
default:
break;
}
}
- (BOOL) hasAddedWidthAndHeightConstraintsToView: (NSView *)view
{
NSArray *added = [_internalConstraintsByViewIndex objectForKey: view];
return added != nil;
}
- (void) addInternalWidthConstraintForView: (NSView *)view
{
GSCSVariable *widthConstraintVariable =
[self variableForView: view andAttribute: GSLayoutAttributeWidth];
GSCSVariable *minX = [self variableForView: view
andAttribute: GSLayoutAttributeMinX];
GSCSVariable *maxX = [self variableForView: view
andAttribute: GSLayoutAttributeMaxX];
GSCSLinearExpression *maxXMinusMinX =
[[GSCSLinearExpression alloc] initWithVariable: maxX];
[maxXMinusMinX addVariable: minX coefficient: -1];
GSCSConstraint *widthRelationshipToMaxXAndMinXConstraint = [GSCSConstraint constraintWithLeftVariable: widthConstraintVariable operator: GSCSConstraintOperatorEqual rightExpression: maxXMinusMinX];
[self addInternalSolverConstraint: widthRelationshipToMaxXAndMinXConstraint
forView: view];
RELEASE(maxXMinusMinX);
}
- (void) addInternalHeightConstraintForView: (NSView *)view
{
GSCSVariable *heightConstraintVariable =
[self variableForView: view andAttribute: GSLayoutAttributeHeight];
GSCSVariable *minY = [self variableForView: view
andAttribute: GSLayoutAttributeMinY];
GSCSVariable *maxY = [self variableForView: view
andAttribute: GSLayoutAttributeMaxY];
GSCSLinearExpression *maxYMinusMinY =
[[GSCSLinearExpression alloc] initWithVariable: maxY];
[maxYMinusMinY addVariable: minY coefficient: -1];
GSCSConstraint *heightConstraint = [GSCSConstraint constraintWithLeftVariable: heightConstraintVariable operator: GSCSConstraintOperatorEqual rightExpression: maxYMinusMinY];
[self addInternalSolverConstraint: heightConstraint forView: view];
RELEASE(maxYMinusMinY);
}
- (void) addInternalLeadingConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *minX = [self variableForView: view
andAttribute: GSLayoutAttributeMinX];
GSCSVariable *leadingVariable =
[self variableForView: view andAttribute: GSLayoutAttributeLeading];
GSCSConstraint *minXLeadingRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: minX operator: GSCSConstraintOperatorEqual rightVariable: leadingVariable];
[self addSupportingSolverConstraint: minXLeadingRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalTrailingConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *trailingVariable =
[self variableForView: view andAttribute: GSLayoutAttributeTrailing];
GSCSVariable *maxX = [self variableForView: view
andAttribute: GSLayoutAttributeMaxX];
GSCSConstraint *maxXTrailingRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: maxX operator: GSCSConstraintOperatorEqual rightVariable: trailingVariable];
[self addSupportingSolverConstraint: maxXTrailingRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalLeftConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *minX = [self variableForView: view
andAttribute: GSLayoutAttributeMinX];
GSCSVariable *leftVariable = [self variableForView: view
andAttribute: GSLayoutAttributeLeft];
GSCSConstraint *minXLeadingRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: minX operator: GSCSConstraintOperatorEqual rightVariable: leftVariable];
[self addSupportingSolverConstraint: minXLeadingRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalRightConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *maxX = [self variableForView: view
andAttribute: GSLayoutAttributeMaxX];
GSCSVariable *rightVariable =
[self variableForView: view andAttribute: GSLayoutAttributeRight];
GSCSConstraint *maxXRightRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: maxX operator: GSCSConstraintOperatorEqual rightVariable: rightVariable];
[self addSupportingSolverConstraint: maxXRightRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalBottomConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *minY = [self variableForView: view
andAttribute: GSLayoutAttributeMinY];
GSCSVariable *bottomVariable =
[self variableForView: view andAttribute: GSLayoutAttributeBottom];
GSCSConstraint *minYBottomRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: minY operator: GSCSConstraintOperatorEqual rightVariable: bottomVariable];
[self addSupportingSolverConstraint: minYBottomRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalTopConstraintForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *maxY = [self variableForView: view
andAttribute: GSLayoutAttributeMaxY];
GSCSVariable *topVariable = [self variableForView: view
andAttribute: GSLayoutAttributeTop];
GSCSConstraint *maxYTopRelationshipConstraint = [GSCSConstraint constraintWithLeftVariable: maxY operator: GSCSConstraintOperatorEqual rightVariable: topVariable];
[self addSupportingSolverConstraint: maxYTopRelationshipConstraint
forSolverConstraint: constraint];
}
- (void) addInternalCenterXConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *centerXVariable =
[self variableForView: view andAttribute: GSLayoutAttributeCenterX];
GSCSVariable *width = [self variableForView: view
andAttribute: GSLayoutAttributeWidth];
GSCSVariable *minX = [self variableForView: view
andAttribute: GSLayoutAttributeMinX];
GSCSLinearExpression *exp =
[[GSCSLinearExpression alloc] initWithVariable: minX];
[exp addVariable: width coefficient: 0.5];
GSCSConstraint *centerXConstraint = [GSCSConstraint constraintWithLeftVariable: centerXVariable operator: GSCSConstraintOperatorEqual rightExpression: exp];
[self addSupportingSolverConstraint: centerXConstraint
forSolverConstraint: constraint];
RELEASE(exp);
}
- (void) addInternalCenterYConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *centerYVariable =
[self variableForView: view andAttribute: GSLayoutAttributeCenterY];
GSCSVariable *height = [self variableForView: view
andAttribute: GSLayoutAttributeHeight];
GSCSVariable *minY = [self variableForView: view
andAttribute: GSLayoutAttributeMinY];
GSCSLinearExpression *exp =
[[GSCSLinearExpression alloc] initWithVariable: minY];
[exp addVariable: height coefficient: 0.5];
GSCSConstraint *centerYConstraint = [GSCSConstraint constraintWithLeftVariable: centerYVariable operator: GSCSConstraintOperatorEqual rightExpression: exp];
RELEASE(exp);
[self addSupportingSolverConstraint: centerYConstraint
forSolverConstraint: constraint];
}
- (void) addInternalFirstBaselineConstraintsForView: (NSView *)view
constraint:
(GSCSConstraint *)constraint
{
GSCSVariable *firstBaselineVariable =
[self variableForView: view
andAttribute: GSLayoutAttributeFirstBaseline];
GSCSVariable *maxY = [self variableForView: view
andAttribute: GSLayoutAttributeMaxY];
GSCSVariable *firstBaselineOffsetVariable =
[self variableForView: view
andViewAttribute: GSLayoutViewAttributeFirstBaselineOffsetFromTop];
GSCSLinearExpression *exp =
[[GSCSLinearExpression alloc] initWithVariable: maxY];
[exp addVariable: firstBaselineOffsetVariable coefficient:-1];
GSCSConstraint *firstBaselineConstraint = [GSCSConstraint constraintWithLeftVariable: firstBaselineVariable operator: GSCSConstraintOperatorEqual rightExpression: exp];
RELEASE(exp);
[self addSupportingConstraintForLayoutViewAttribute:
GSLayoutViewAttributeFirstBaselineOffsetFromTop
view: view
constraint: constraint];
[self addSupportingSolverConstraint: firstBaselineConstraint
forSolverConstraint: constraint];
}
- (void) addInternalBaselineConstraintsForView: (NSView *)view
constraint: (GSCSConstraint *)constraint
{
GSCSVariable *baselineVariable =
[self variableForView: view andAttribute: GSLayoutAttributeBaseline];
GSCSVariable *minY = [self variableForView: view
andAttribute: GSLayoutAttributeMinY];
GSCSVariable *baselineOffsetVariable =
[self variableForView: view
andViewAttribute: GSLayoutViewAttributeBaselineOffsetFromBottom];
[self addSupportingConstraintForLayoutViewAttribute:
GSLayoutViewAttributeBaselineOffsetFromBottom
view: view
constraint: constraint];
GSCSLinearExpression *exp =
[[GSCSLinearExpression alloc] initWithVariable: minY];
[exp addVariable: baselineOffsetVariable];
GSCSConstraint *baselineConstraint = [GSCSConstraint constraintWithLeftVariable: baselineVariable operator: GSCSConstraintOperatorEqual rightExpression: exp];
RELEASE(exp);
[self addSupportingSolverConstraint: baselineConstraint
forSolverConstraint: constraint];
}
- (void) addInternalSolverConstraint: (GSCSConstraint *)constraint
forView: (NSView *)view
{
[self addSolverConstraint: constraint];
NSArray *internalViewConstraints =
[_internalConstraintsByViewIndex objectForKey: view];
if (internalViewConstraints == nil)
{
[_internalConstraintsByViewIndex setObject: [NSMutableArray array]
forKey: view];
}
[[_internalConstraintsByViewIndex objectForKey: view]
addObject: constraint];
}
- (void) addIntrinsicContentSizeConstraintsToView: (NSView *)view
{
NSSize intrinsicContentSize = [view intrinsicContentSize];
if (intrinsicContentSize.width != NSViewNoIntrinsicMetric)
{
[self
addSupportingInstrictSizeConstraintsToView: view
orientation: NSLayoutConstraintOrientationHorizontal
instrinctSizeAttribute: GSLayoutViewAttributeIntrinsicWidth
dimensionAttribute: GSLayoutAttributeWidth];
}
if (intrinsicContentSize.height != NSViewNoIntrinsicMetric)
{
[self
addSupportingInstrictSizeConstraintsToView: view
orientation: NSLayoutConstraintOrientationVertical
instrinctSizeAttribute: GSLayoutViewAttributeInstrinctHeight
dimensionAttribute: GSLayoutAttributeHeight];
}
}
- (void) addSupportingInstrictSizeConstraintsToView: (NSView *)view
orientation: (NSLayoutConstraintOrientation)orientation
instrinctSizeAttribute: (GSLayoutViewAttribute)instrinctSizeAttribute
dimensionAttribute: (GSLayoutAttribute)dimensionAttribute
{
GSCSVariable *instrinctContentDimension =
[self variableForView: view andViewAttribute: instrinctSizeAttribute];
GSCSVariable *dimensionVariable =
[self variableForView: view andAttribute: dimensionAttribute];
GSCSVariable *instrinctSizeVariable =
[self getExistingVariableForView: view
withViewAttribute: instrinctSizeAttribute];
GSCSConstraint *instrinctSizeConstraint =
[GSCSConstraint editConstraintWithVariable: instrinctSizeVariable];
[self addInternalSolverConstraint: instrinctSizeConstraint forView: view];
[self resolveVariableForView: view attribute: instrinctSizeAttribute];
double huggingPriority =
[view contentHuggingPriorityForOrientation: orientation];
GSCSConstraint *huggingConstraint = [GSCSConstraint constraintWithLeftVariable: dimensionVariable operator: GSCSConstraintOperatorLessThanOrEqual rightVariable: instrinctContentDimension];
GSCSStrength *huggingConstraintStrength =
[[GSCSStrength alloc] initWithName: nil strength: huggingPriority];
[huggingConstraint setStrength: huggingConstraintStrength];
RELEASE(huggingConstraintStrength);
[self addInternalSolverConstraint: huggingConstraint forView: view];
double compressionPriority =
[view contentCompressionResistancePriorityForOrientation: orientation];
GSCSConstraint *compressionConstraint = [GSCSConstraint constraintWithLeftVariable: dimensionVariable operator: GSCSConstraintOperationGreaterThanOrEqual rightVariable: instrinctContentDimension];
GSCSStrength *compressionConstraintStrength =
[[GSCSStrength alloc] initWithName: nil strength: compressionPriority];
[compressionConstraint setStrength: compressionConstraintStrength];
RELEASE(compressionConstraintStrength);
[self addInternalSolverConstraint: compressionConstraint forView: view];
}
- (void) addSupportingConstraintForLayoutViewAttribute:
(GSLayoutViewAttribute)attribute
view: (NSView *)view
constraint:
(GSCSConstraint *)constraint
{
GSCSVariable *variable = [self getExistingVariableForView: view
withViewAttribute: attribute];
GSCSConstraint *editConstraint =
[GSCSConstraint editConstraintWithVariable: variable];
[self addSupportingSolverConstraint: editConstraint
forSolverConstraint: constraint];
[self resolveVariableForView: view attribute: attribute];
}
- (void) addObserverToConstraint: (NSLayoutConstraint *)constranit
{
[constranit addObserver: self
forKeyPath: @"constant"
options: NSKeyValueObservingOptionNew
context: nil];
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
if ([object isKindOfClass: [NSLayoutConstraint class]])
{
NSLayoutConstraint *constraint = (NSLayoutConstraint *)object;
[self updateConstraint: constraint];
}
}
- (void) updateConstraint: (NSLayoutConstraint *)constraint
{
GSCSConstraint *kConstraint =
[self getExistingConstraintForAutolayoutConstraint: constraint];
[self removeSolverConstraint: kConstraint];
GSCSConstraint *newKConstraint =
[self solverConstraintForConstraint: constraint];
[self mapLayoutConstraint: constraint toSolverConstraint: newKConstraint];
[self addSolverConstraint: newKConstraint];
[self updateAlignmentRectsForTrackedViews];
}
- (void) removeInternalConstraintsForView: (NSView *)view
@ -259,7 +1061,7 @@
if ([constraint secondItem] != nil)
{
NSNumber *secondItemViewIndex =
[self indexForView: [constraint secondItem]];
[self indexForView: [constraint secondItem]];
if ([_constraintsByViewIndex objectForKey: secondItemViewIndex])
{
[_constraintsByViewIndex setObject: [NSMutableArray array]
@ -356,7 +1158,7 @@
- (NSRect) currentAlignmentRectForViewAtIndex: (NSNumber *)viewIndex
{
NSValue *existingRectValue =
[_viewAlignmentRectByViewIndex objectForKey: viewIndex];
[_viewAlignmentRectByViewIndex objectForKey: viewIndex];
if (existingRectValue == nil)
{
return NSZeroRect;
@ -386,6 +1188,21 @@
return NSZeroRect;
}
- (void) addSupportingSolverConstraint: (GSCSConstraint *)supportingConstraint
forSolverConstraint: (GSCSConstraint *)constraint
{
[self addSolverConstraint: supportingConstraint];
if ([_supportingConstraintsByConstraint objectForKey: constraint] == nil)
{
[_supportingConstraintsByConstraint
setObject: [NSMutableArray array]
forKey: constraint];
}
[[_supportingConstraintsByConstraint objectForKey: constraint]
addObject: supportingConstraint];
}
- (void) addSolverConstraint: (GSCSConstraint *)constraint
{
[_solverConstraints addObject: constraint];
@ -424,21 +1241,53 @@
return constraintsForView;
}
- (void) dealloc
{
RELEASE (_trackedViews);
RELEASE (_viewAlignmentRectByViewIndex);
RELEASE (_viewIndexByViewHash);
RELEASE (_constraintsByViewIndex);
RELEASE (_constraintsByViewIndex);
RELEASE (_supportingConstraintsByConstraint);
RELEASE (_constraintsByAutoLayoutConstaintHash);
RELEASE (_internalConstraintsByViewIndex);
RELEASE (_solverConstraints);
RELEASE (_variablesByKey);
RELEASE (_solver);
- (void) resolveVariableForView: (NSView *)view
attribute: (GSLayoutViewAttribute)attribute
{
GSCSVariable *editVariable = [self getExistingVariableForView: view
withViewAttribute: attribute];
CGFloat value = [self valueForView: view attribute: attribute];
[super dealloc];
}
[_solver suggestEditVariable: editVariable equals: value];
[self updateAlignmentRectsForTrackedViews];
}
- (CGFloat) valueForView: (NSView *)view
attribute: (GSLayoutViewAttribute)attribute
{
switch (attribute)
{
case GSLayoutViewAttributeBaselineOffsetFromBottom:
return [view baselineOffsetFromBottom];
case GSLayoutViewAttributeFirstBaselineOffsetFromTop:
return [view firstBaselineOffsetFromTop];
case GSLayoutViewAttributeIntrinsicWidth:
return [view intrinsicContentSize].width;
case GSLayoutViewAttributeInstrinctHeight:
return [view intrinsicContentSize].height;
default:
[[NSException exceptionWithName: @"Not handled"
reason: @"GSLayoutAttribute not handled"
userInfo: nil] raise];
return 0;
}
}
- (void) dealloc
{
RELEASE(_trackedViews);
RELEASE(_viewAlignmentRectByViewIndex);
RELEASE(_viewIndexByViewHash);
RELEASE(_constraintsByViewIndex);
RELEASE(_constraintsByViewIndex);
RELEASE(_supportingConstraintsByConstraint);
RELEASE(_constraintsByAutoLayoutConstaintHash);
RELEASE(_internalConstraintsByViewIndex);
RELEASE(_solverConstraints);
RELEASE(_variablesByKey);
RELEASE(_solver);
[super dealloc];
}
@end

View file

@ -46,6 +46,13 @@ typedef enum GSCSConstraintType GSCSConstraintType;
GSCSVariable *_variable;
}
#if GS_HAS_DECLARED_PROPERTIES
@property (nonatomic, assign) GSCSStrength *strength;
#else
- (GSCSStrength *) strength;
- (void) setStrength: (GSCSStrength *)strength;
#endif
- (instancetype) initWithType: (GSCSConstraintType)type
strength: (GSCSStrength *)strength
expression: (GSCSLinearExpression *)expression
@ -63,7 +70,7 @@ typedef enum GSCSConstraintType GSCSConstraintType;
variable: (GSCSVariable *)variable;
- (instancetype) initEditConstraintWithVariable: (GSCSVariable *)variable
stength: (GSCSStrength *)strength;
strength: (GSCSStrength *)strength;
- (instancetype) initStayConstraintWithVariable: (GSCSVariable *)variable
strength: (GSCSStrength *)strength;
@ -116,8 +123,6 @@ operator: (GSCSConstraintOperator) operator
- (GSCSConstraintType) type;
- (GSCSStrength *) strength;
- (GSCSVariable *) variable;
@end

View file

@ -310,6 +310,11 @@ operator: (GSCSConstraintOperator) operator
strength: [GSCSStrength strengthStrong]]);
}
- (void) setStrength: (GSCSStrength *)strength
{
ASSIGN(_strength, strength);
}
- (BOOL) isRequired
{
return [_strength isRequired];

View file

@ -37,6 +37,8 @@
- (void) removeConstraints: (NSArray*)constraints;
- (void) suggestEditVariable: (GSCSVariable*)variable equals: (CGFloat)value;
- (GSCSSolution*) solve;
@end

View file

@ -50,4 +50,9 @@
return [[GSCSSolution alloc] init];
}
- (void) suggestEditVariable: (GSCSVariable*)variable equals: (CGFloat)value
{
// FIXME Suggest edit variable
}
@end

View file

@ -618,109 +618,6 @@ static NSMutableArray *activeConstraints = nil;
@end
@implementation NSView (NSConstraintBasedLayoutCoreMethods)
- (void) updateConstraintsForSubtreeIfNeeded
{
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
[subview updateConstraintsForSubtreeIfNeeded];
END_FOR_IN (subviews);
if ([self needsUpdateConstraints])
{
[self updateConstraints];
}
}
- (void) updateConstraints
{
if ([self translatesAutoresizingMaskIntoConstraints] &&
[self superview] != nil)
{
NSArray *autoresizingConstraints = [NSAutoresizingMaskLayoutConstraint
constraintsWithAutoresizingMask: [self autoresizingMask]
subitem: self
frame: [self frame]
superitem: [self superview]
bounds: [[self superview] bounds]];
[self addConstraints: autoresizingConstraints];
}
[self _setNeedsUpdateConstraints: NO];
}
@end
@implementation NSView (NSConstraintBasedLayoutInstallingConstraints)
- (GSAutoLayoutEngine*) _getOrCreateLayoutEngine
{
if (![self window])
{
return nil;
}
if (![[self window] _layoutEngine])
{
[[self window] _bootstrapAutoLayout];
}
return [[self window] _layoutEngine];
}
- (void) addConstraint: (NSLayoutConstraint *)constraint
{
if (![self _getOrCreateLayoutEngine])
{
return;
}
[[self _layoutEngine] addConstraint: constraint];
}
- (void) addConstraints: (NSArray*)constraints
{
if (![self _getOrCreateLayoutEngine])
{
return;
}
[[self _layoutEngine] addConstraints: constraints];
}
- (void) removeConstraint: (NSLayoutConstraint *)constraint
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraint: constraint];
}
- (void) removeConstraints: (NSArray *)constraints
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraints: constraints];
}
- (NSArray*) constraints
{
GSAutoLayoutEngine *engine = [self _layoutEngine];
if (!engine)
{
return [NSArray array];
}
return [engine constraintsForView: self];
}
@end
@implementation NSWindow (NSConstraintBasedLayoutCoreMethods)
- (void) layoutIfNeeded

View file

@ -80,6 +80,7 @@
#import "GSFastEnumeration.h"
#import "GSGuiPrivate.h"
#import "GSAutoLayoutEngine.h"
#import "NSAutoresizingMaskLayoutConstraint.h"
#import "NSViewPrivate.h"
#import "NSWindowPrivate.h"
@ -103,6 +104,9 @@
*/
NSView *viewIsPrinting = nil;
const CGFloat NSViewNoInstrinsicMetric = -1;
const CGFloat NSViewNoIntrinsicMetric = -1;
/**
<unit>
<heading>NSView</heading>
@ -5202,8 +5206,35 @@ static NSView* findByTag(NSView *view, NSInteger aTag, NSUInteger *level)
return _translatesAutoresizingMaskIntoConstraints;
}
- (NSLayoutPriority) contentCompressionResistancePriority
{
return _contentCompressionResistancePriority;
}
- (void) setContentCompressionResistancePriority: (NSLayoutPriority)priority;
{
_contentCompressionResistancePriority = priority;
}
- (NSSize) intrinsicContentSize
{
return NSMakeSize(NSViewNoIntrinsicMetric, NSViewNoIntrinsicMetric);
}
- (CGFloat) baselineOffsetFromBottom
{
return 0;
}
- (CGFloat) firstBaselineOffsetFromTop
{
return 0;
}
@end
#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
@implementation NSView (NSConstraintBasedLayoutCorePrivateMethods)
// This private setter allows the updateConstraints method to toggle needsUpdateConstraints
- (void) _setNeedsUpdateConstraints: (BOOL)needsUpdateConstraints
@ -5240,8 +5271,146 @@ static NSView* findByTag(NSView *view, NSInteger aTag, NSUInteger *level)
[[self superview] setNeedsLayout: YES];
}
- (GSAutoLayoutEngine*) _getOrCreateLayoutEngine
{
if (![self window])
{
return nil;
}
if (![[self window] _layoutEngine])
{
[[self window] _bootstrapAutoLayout];
}
return [[self window] _layoutEngine];
}
@end
@implementation NSView (NSConstraintBasedLayoutCoreMethods)
- (void) updateConstraintsForSubtreeIfNeeded
{
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
[subview updateConstraintsForSubtreeIfNeeded];
END_FOR_IN (subviews);
if ([self needsUpdateConstraints])
{
[self updateConstraints];
}
}
- (void) updateConstraints
{
if ([self translatesAutoresizingMaskIntoConstraints] &&
[self superview] != nil)
{
NSArray *autoresizingConstraints = [NSAutoresizingMaskLayoutConstraint
constraintsWithAutoresizingMask: [self autoresizingMask]
subitem: self
frame: [self frame]
superitem: [self superview]
bounds: [[self superview] bounds]];
[self addConstraints: autoresizingConstraints];
}
[self _setNeedsUpdateConstraints: NO];
}
- (NSLayoutPriority) contentCompressionResistancePriorityForOrientation: (NSLayoutConstraintOrientation)orientation {
if (orientation == NSLayoutConstraintOrientationHorizontal) {
return _compressionPriorities.horizontal;
} else {
return _compressionPriorities.vertical;
}
}
- (void) setContentCompressionResistancePriority: (NSLayoutPriority)priority forOrientation: (NSLayoutConstraintOrientation)orientation {
if (orientation == NSLayoutConstraintOrientationHorizontal) {
_compressionPriorities.horizontal = priority;
} else {
_compressionPriorities.vertical = priority;
}
}
- (NSLayoutPriority) contentHuggingPriorityForOrientation: (NSLayoutConstraintOrientation)orientation {
if (orientation == NSLayoutConstraintOrientationHorizontal) {
return _huggingPriorities.horizontal;
} else {
return _huggingPriorities.vertical;
}
}
- (void) setContentHuggingPriority: (NSLayoutPriority)priority forOrientation: (NSLayoutConstraintOrientation)orientation
{
if (orientation == NSLayoutConstraintOrientationHorizontal) {
_huggingPriorities.horizontal = priority;
} else {
_huggingPriorities.vertical = priority;
}
}
@end
@implementation NSView (NSConstraintBasedLayoutInstallingConstraints)
- (void) addConstraint: (NSLayoutConstraint *)constraint
{
if (![self _getOrCreateLayoutEngine])
{
return;
}
[[self _layoutEngine] addConstraint: constraint];
}
- (void) addConstraints: (NSArray*)constraints
{
if (![self _getOrCreateLayoutEngine])
{
return;
}
[[self _layoutEngine] addConstraints: constraints];
}
- (void) removeConstraint: (NSLayoutConstraint *)constraint
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraint: constraint];
}
- (void) removeConstraints: (NSArray *)constraints
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraints: constraints];
}
- (NSArray*) constraints
{
GSAutoLayoutEngine *engine = [self _layoutEngine];
if (!engine)
{
return [NSArray array];
}
return [engine constraintsForView: self];
}
@end
#endif
@implementation NSView (__NSViewPrivateMethods__)
/*