mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
Implement layout constraint conversion to internal solver constraints
This commit is contained in:
parent
fccf8771e6
commit
2e98bd5366
9 changed files with 1124 additions and 146 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -310,6 +310,11 @@ operator: (GSCSConstraintOperator) operator
|
|||
strength: [GSCSStrength strengthStrong]]);
|
||||
}
|
||||
|
||||
- (void) setStrength: (GSCSStrength *)strength
|
||||
{
|
||||
ASSIGN(_strength, strength);
|
||||
}
|
||||
|
||||
- (BOOL) isRequired
|
||||
{
|
||||
return [_strength isRequired];
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
- (void) removeConstraints: (NSArray*)constraints;
|
||||
|
||||
- (void) suggestEditVariable: (GSCSVariable*)variable equals: (CGFloat)value;
|
||||
|
||||
- (GSCSSolution*) solve;
|
||||
|
||||
@end
|
||||
|
|
|
@ -50,4 +50,9 @@
|
|||
return [[GSCSSolution alloc] init];
|
||||
}
|
||||
|
||||
- (void) suggestEditVariable: (GSCSVariable*)variable equals: (CGFloat)value
|
||||
{
|
||||
// FIXME Suggest edit variable
|
||||
}
|
||||
|
||||
@end
|
|
@ -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
|
||||
|
|
169
Source/NSView.m
169
Source/NSView.m
|
@ -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__)
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue