Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'galaxas/dev'

  • Loading branch information...
commit 991f78dc7ad83a918f702525bef0b9688241d5d8 2 parents 4b6633a + d8c0181
@jspahrsummers jspahrsummers authored
View
83 lib/UIKit/TUILayoutConstraint.h
@@ -1,6 +1,19 @@
@class TUIView;
typedef enum : NSUInteger {
+
+ /*
+ MaxY
+ -----------------
+ | | | Height
+ | | |
+ | MidY |
+ MinX |------MidX-----| MaxX
+ | | |
+ | | |
+ ----------------- Width
+ MinY
+ */
TUILayoutConstraintAttributeMinY = 1,
TUILayoutConstraintAttributeMaxY = 2,
TUILayoutConstraintAttributeMinX = 3,
@@ -10,6 +23,19 @@ typedef enum : NSUInteger {
TUILayoutConstraintAttributeMidY = 7,
TUILayoutConstraintAttributeMidX = 8,
+ /*
+ MaxXMinY MidXMaxY MaxXMaxY
+ -----------------
+ | |
+ | |
+ MinXMidY| |MaxXMidY
+ | |
+ | |
+ | |
+ -----------------
+ MinXMinY MidXMinY MaxXMinY
+ */
+
TUILayoutConstraintAttributeMinXMinY = 101,
TUILayoutConstraintAttributeMinXMidY = 102,
TUILayoutConstraintAttributeMinXMaxY = 103,
@@ -22,14 +48,71 @@ typedef enum : NSUInteger {
TUILayoutConstraintAttributeMaxXMidY = 108,
TUILayoutConstraintAttributeMaxXMaxY = 109,
+ /*
+ BoundsCenter is the center of the view bounds.
+ Frame is the frame of the view.
+ Bounds is the bounds of the view.
+ */
+
TUILayoutConstraintAttributeBoundsCenter = 110,
TUILayoutConstraintAttributeFrame = 1000,
TUILayoutConstraintAttributeBounds = 1001
} TUILayoutConstraintAttribute;
+/*
+ A block that contains a transformation to apply on
+ source CGFloat and returns a transformed value.
+ */
typedef CGFloat (^TUILayoutTransformer)(CGFloat);
+/*
+
+ Layout Constraint Solver System
+ Based on the CAConstraint and Cocoa Auto Layout systems.
+
+ Example Code:
+
+ ```
+ TUIButton *acceptButton = [TUIButton buttonWithType:TUIButtonTypeCustom];
+ [self setUpButton:acceptButton];
+ TUIButton *declineButton = [TUIButton buttonWithType:TUIButtonTypeCustom];
+ [self setUpButton:declineButton];
+ [acceptButton setLayoutName:@"accept"];
+ [declineButton setLayoutName:@"decline"];
+
+ TUILayoutConstraint *constrainLeft = [TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeMaxX
+ relativeTo:@"accept"
+ attribute:TUILayoutConstraintAttributeMinX
+ offset:-10];
+ [declineButton addConstraint:constrainLeft];
+ ```
+
+ Now whenever the window is resized or moved, and the acceptButton is subsequently
+ resized or moved, declineButton will be automatically moved to have its right edge
+ positioned 10 pixels to the left of acceptButton left edge.
+ This is only a simple example, a more complex example could use block transformers
+ and a fabs(sin()) to constrict a tranformation to a |sin(x)| curve. And more!
+
+ Along with simple scale and offset constraints, you can specify a block
+ value transformer to use more complex transformations. You can also bind
+ to point and rect values such as frame and bounds, and vertices.
+
+ CAUTION: It's very easy to set up circular dependancies with constraints.
+ While this leads to some very oddly cool things, here lie dragons. Beware.
+
+ NOTE: To constrain a view to its superview, use the source name @"superview".
+ This also means that you can't use views with a layout name @"superview".
+
+ NOTE: For now, constraints have no priority levels, so they are evaluated
+ in the order they are added.
+
+ NOTE: Transformations only apply to scalar attributes, and cannot be applied
+ to CGPoints, or CGRects. An attribute cannot be constrained to an attribute
+ of a different type, such as scalar-point, point-rect.
+
+ */
+
@interface TUILayoutConstraint : NSObject
@property (readonly) TUILayoutConstraintAttribute attribute;
View
55 lib/UIKit/TUILayoutConstraint.m
@@ -8,11 +8,18 @@ - (void)setValue:(NSRect)newValue forLayoutAttribute:(TUILayoutConstraintAttribu
@end
-
@interface TUILayoutConstraint ()
+@property (nonatomic, assign) CGFloat scale;
+@property (nonatomic, assign) CGFloat offset;
@property (nonatomic, copy) NSValueTransformer *valueTransformer;
+- (id)initWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ scale:(CGFloat)scale
+ offset:(CGFloat)offset;
+
- (CGFloat)transformValue:(CGFloat)original;
- (void)applyToTargetView:(TUIView *)target;
- (void)applyToTargetView:(TUIView *)target sourceView:(TUIView *)source;
@@ -33,6 +40,8 @@ @implementation TUILayoutConstraint
@synthesize attribute = _attribute;
@synthesize sourceAttribute = _sourceAttribute;
@synthesize sourceName = _sourceName;
+@synthesize scale = _scale;
+@synthesize offset = _offset;
@synthesize valueTransformer = _valueTransformer;
+ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
@@ -53,7 +62,7 @@ + (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
attribute:(TUILayoutConstraintAttribute)srcAttr
scale:(CGFloat)scale
offset:(CGFloat)offset {
- return [[self alloc] initWithAttribute:attr relativeTo:source attribute:srcAttr scale:scale offset:offset];
+ return [[TUILayoutConstraint alloc] initWithAttribute:attr relativeTo:source attribute:srcAttr scale:scale offset:offset];
}
+ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
@@ -74,26 +83,56 @@ + (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
- (id)initWithAttribute:(TUILayoutConstraintAttribute)attr
relativeTo:(NSString *)srcLayer
attribute:(TUILayoutConstraintAttribute)srcAttr
+ scale:(CGFloat)scale
+ offset:(CGFloat)offset {
+
+ double attributeRange = floor(log10(attr));
+ double sourceAttributeRange = floor(log10(srcAttr));
+
+ NSAssert(fabs(attributeRange - sourceAttributeRange) < 0.001, @"Invalid source and target attributes: %f, %f.", sourceAttributeRange, attributeRange);
+ NSAssert(scale > 0.0f && offset > 0.0f, @"Invalid scale and offset: %f, %f", scale, offset);
+
+ if((self = [super init])) {
+ _attribute = attr;
+ _sourceAttribute = srcAttr;
+ _sourceName = [srcLayer copy];
+
+ _scale = scale;
+ _offset = offset;
+ _valueTransformer = nil;
+ }
+ return self;
+}
+
+- (id)initWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr
valueTransformer:(NSValueTransformer *)transformer {
double attributeRange = floor(log10(attr));
double sourceAttributeRange = floor(log10(srcAttr));
- NSAssert(fabs(attributeRange - sourceAttributeRange) < 0.001, @"Invalid source and target attributes: %f, %f", sourceAttributeRange, attributeRange);
+ NSAssert(fabs(attributeRange - sourceAttributeRange) < 0.001, @"Invalid source and target attributes: %f, %f.", sourceAttributeRange, attributeRange);
+ NSAssert(transformer != nil, @"Cannot have a nil transformer.", sourceAttributeRange, attributeRange);
if((self = [super init])) {
_attribute = attr;
_sourceAttribute = srcAttr;
-
_sourceName = [srcLayer copy];
+
+ _scale = 0.0f;
+ _offset = 0.0f;
_valueTransformer = transformer;
}
return self;
}
-- (CGFloat)transformValue:(CGFloat)original {
- id transformed = [self.valueTransformer transformedValue:[NSNumber numberWithFloat:original]];
- return [transformed floatValue];
+- (CGFloat)transformValue:(CGFloat)source {
+ if(self.valueTransformer) {
+ id transformed = [self.valueTransformer transformedValue:[NSNumber numberWithFloat:source]];
+ return [transformed floatValue];
+ } else
+ return (source * self.scale) + self.offset;
}
- (void)applyToTargetView:(TUIView *)target {
@@ -106,7 +145,7 @@ - (void)applyToTargetView:(TUIView *)target sourceView:(TUIView *)source {
if(source == nil) return;
if([self sourceAttribute] == 0) return;
- NSRect sourceValue = [source valueForLayoutAttribute:[self sourceAttribute]];
+ NSRect sourceValue = [source valueForLayoutAttribute:self.sourceAttribute];
NSRect targetValue = sourceValue;
if(self.attribute >= TUILayoutConstraintAttributeMinY && self.attribute <= TUILayoutConstraintAttributeMidX)
View
46 lib/UIKit/TUILayoutManager.h
@@ -2,19 +2,65 @@
@class TUILayoutConstraint;
+/*
+
+ The layout manager is penultimate to solving constraints. It handles
+ views marked as needing processing, and recursively invokes the
+ constraint solver per view when required.
+
+ However, it also provides a bridge to the constraints and the views
+ by mediating the adding or removing of a constraint to and from a view.
+
+ Views are marked by an internal layout name, to which they are
+ then referred to from within constraints.
+
+ CAUTION:
+ This class has been marked as requiring refactorization
+ and should not be used directly. It will become private soon.
+
+ NOTE:
+ Layout names as identifiers might be removed in future updates.
+
+ */
+
@interface TUILayoutManager : NSObject
+/*
+
+ Requests the shared layout manager, the preferred usage method. This
+ shared manager then handles the constraint system for the global space.
+
+ You may also use -init to create a local layout manager, in cases where
+ you may want your constraint system to be factored and isolated, or
+ where you may be using TUIViews only in certain places, and not the whole
+ window or application.
+
+ */
+ (id)sharedLayoutManager;
+/*
+
+ Provides a bridge to add a constraint to a view, or remove a constraint
+ from a view. You can also remove ALL layout constraints on a view, and
+ retrieve an array of constraints currently attached to a view.
+
+ */
- (void)addLayoutConstraint:(TUILayoutConstraint *)constraint toView:(TUIView *)view;
- (void)removeLayoutConstraintsFromView:(TUIView *)view;
- (NSArray *)layoutConstraintsOnView:(TUIView *)view;
- (void)removeAllLayoutConstraints;
+/*
+ Provides a bridge for the TUIView layout name identifier.
+ */
- (NSString *)layoutNameForView:(TUIView *)view;
- (void)setLayoutName:(NSString *)name forView:(TUIView *)view;
+/*
+ Similar to -redraw on a TUIView, but for constraints. Forces a re-processing
+ of all constraints attached to a view.
+ */
- (void)beginProcessingView:(TUIView *)aView;
@end
View
1  lib/UIKit/TUILayoutManager.m
@@ -37,7 +37,6 @@ - (id)init {
@end
-
@interface TUILayoutManager ()
@property (nonatomic, assign, getter = isProcessingChanges) BOOL processingChanges;
View
11 lib/UIKit/TUIView+Layout.h
@@ -1,6 +1,17 @@
#import <Cocoa/Cocoa.h>
#import "TUILayoutConstraint.h"
+/*
+
+ The view-end of the layout system allows you to add constraints
+ to the view directly from the view, list all constraints currently
+ attached to the view, and remove all layout constraints at once.
+
+ It also allows you to set the layout name without interfacing
+ with the TUILayoutManager, as a shortcut.
+
+ */
+
@interface TUIView (Layout)
@property (nonatomic, copy) NSString *layoutName;
Please sign in to comment.
Something went wrong with that request. Please try again.