Permalink
Browse files

Merge remote-tracking branch 'galaxas/dev' into dev

  • Loading branch information...
jspahrsummers committed Jul 19, 2012
2 parents 36e4a81 + 7f3f9e5 commit 1c7a8cda9f9a22e87f4eebe85211677a1d343feb
@@ -52,7 +52,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
tuiScrollViewContainer.rootView = scrollExample;
[self showTableViewExampleWindow:nil];
-
+
}
/**
View
@@ -1,4 +1,4 @@
-# TwUI 0.2.0
+# TwUI 0.2.0r1
TwUI is a hardware accelerated UI framework for Mac, inspired by UIKit. It enables:
@@ -11,6 +11,7 @@ It differs from UIKit in a few ways:
* Block-based layout and drawRect
* A consistent coordinate system (bottom left origin)
* Sub-pixel text rendering
+* Layout Constraints (ala Cocoa Auto-Layout)
# Setup
@@ -26,7 +27,7 @@ An included example project shows off the basic construction of a pure TwUI-base
# Status
-TwUI should be considered an alpha project. It is current shipping in Twitter for Mac, in use 24/7 by many, many users and has proven itself very stable. The code still has a few Twitter-for-Mac-isms that should be refactored and cleaned up.
+TwUI should be considered an alpha project. It is current shipping in Twitter for Mac and Github for Mac, in use 24/7 by many, many users and has proven itself very stable.
This project follows the [SemVer](http://semver.org/) standard. The API may change in backwards-incompatible ways before the 1.0 release.
@@ -40,8 +41,6 @@ There are many places where TwUI could be improved:
* Text editing. TUITextEditor is a simple text editor (built on TUITextRenderer). It provides basic editing support and handles a number of standard keybindings. Fleshing this out to be indistinguishable from NSTextView (read: spellchecking, autocorrect) would be useful. If the logic around this were self-contained it would even be great as a standalone project, useful for anyone looking to build a custom text editor for the Mac.
-* Reverse-hosting. Right now TUIViews may be hosted inside of an existing NSView hierarchy. It would be useful if the reverse were possible, adding NSViews inside of TUIViews. Doing so in a robust way so event routing, the responder chain, and CAAnimations all just work is a challenge.
-
# Documentation
You can generate documentation with [doxygen](http://www.doxygen.org). Install it, and then run:
@@ -9,6 +9,12 @@
/* Begin PBXBuildFile section */
30D399C9156D8ADD006ECDAE /* TUIProgressBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D399C7156D8ADD006ECDAE /* TUIProgressBar.m */; };
30D39A0D156D8F71006ECDAE /* TUIProgressBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 30D399C6156D8ADD006ECDAE /* TUIProgressBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 48A10E8115B7769A007F9EE3 /* TUILayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A10E7D15B7769A007F9EE3 /* TUILayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 48A10E8215B7769A007F9EE3 /* TUILayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A10E7E15B7769A007F9EE3 /* TUILayoutConstraint.m */; };
+ 48A10E8315B7769A007F9EE3 /* TUILayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A10E7F15B7769A007F9EE3 /* TUILayoutManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 48A10E8415B7769A007F9EE3 /* TUILayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A10E8015B7769A007F9EE3 /* TUILayoutManager.m */; };
+ 48A10E8915B778E8007F9EE3 /* TUIView+Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A10E8715B778E8007F9EE3 /* TUIView+Layout.m */; };
+ 48A10E8B15B77A46007F9EE3 /* TUIView+Layout.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A10E8A15B77A46007F9EE3 /* TUIView+Layout.h */; settings = {ATTRIBUTES = (Public, ); }; };
5E6ECEB313BE791600109598 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EE9839C13BE7650005F430D /* ApplicationServices.framework */; };
5E6ECEB413BE791600109598 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB5E31B613BE6F49004B7899 /* QuartzCore.framework */; };
5E6ECEB613BE791C00109598 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EE9839C13BE7650005F430D /* ApplicationServices.framework */; };
@@ -284,6 +290,12 @@
/* Begin PBXFileReference section */
30D399C6156D8ADD006ECDAE /* TUIProgressBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUIProgressBar.h; sourceTree = "<group>"; };
30D399C7156D8ADD006ECDAE /* TUIProgressBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUIProgressBar.m; sourceTree = "<group>"; };
+ 48A10E7D15B7769A007F9EE3 /* TUILayoutConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUILayoutConstraint.h; sourceTree = "<group>"; };
+ 48A10E7E15B7769A007F9EE3 /* TUILayoutConstraint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUILayoutConstraint.m; sourceTree = "<group>"; };
+ 48A10E7F15B7769A007F9EE3 /* TUILayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUILayoutManager.h; sourceTree = "<group>"; };
+ 48A10E8015B7769A007F9EE3 /* TUILayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUILayoutManager.m; sourceTree = "<group>"; };
+ 48A10E8715B778E8007F9EE3 /* TUIView+Layout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TUIView+Layout.m"; sourceTree = "<group>"; };
+ 48A10E8A15B77A46007F9EE3 /* TUIView+Layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TUIView+Layout.h"; sourceTree = "<group>"; };
5EE9839C13BE7650005F430D /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
5EE983B713BE7809005F430D /* libtwui.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtwui.a; sourceTree = BUILT_PRODUCTS_DIR; };
8819794213E26E0200AA39EB /* TUIView+Accessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TUIView+Accessibility.h"; sourceTree = "<group>"; };
@@ -604,6 +616,10 @@
CBB74C5913BE6E1900C85CB5 /* TUIImageView.m */,
CBB74C5C13BE6E1900C85CB5 /* TUILabel.h */,
CBB74C5D13BE6E1900C85CB5 /* TUILabel.m */,
+ 48A10E7D15B7769A007F9EE3 /* TUILayoutConstraint.h */,
+ 48A10E7E15B7769A007F9EE3 /* TUILayoutConstraint.m */,
+ 48A10E7F15B7769A007F9EE3 /* TUILayoutManager.h */,
+ 48A10E8015B7769A007F9EE3 /* TUILayoutManager.m */,
CBB74C5E13BE6E1900C85CB5 /* TUINSView+Hyperfocus.h */,
CBB74C5F13BE6E1900C85CB5 /* TUINSView+Hyperfocus.m */,
CBB74C6013BE6E1900C85CB5 /* TUINSView+NSTextInputClient.m */,
@@ -661,6 +677,8 @@
CBB74C8213BE6E1900C85CB5 /* TUIView+Animation.m */,
CBB74C8313BE6E1900C85CB5 /* TUIView+Event.h */,
CBB74C8413BE6E1900C85CB5 /* TUIView+Event.m */,
+ 48A10E8A15B77A46007F9EE3 /* TUIView+Layout.h */,
+ 48A10E8715B778E8007F9EE3 /* TUIView+Layout.m */,
CBB74C8513BE6E1900C85CB5 /* TUIView+NSTextInputClient.h */,
CBB74C8613BE6E1900C85CB5 /* TUIView+NSTextInputClient.m */,
CBB74C8713BE6E1900C85CB5 /* TUIView+PasteboardDragging.h */,
@@ -756,6 +774,9 @@
88EFFB5113F417E200CF91A9 /* TUITextViewEditor.h in Headers */,
88D25F5513F5D96500CFAAA9 /* TUITableView+Cell.h in Headers */,
88A4AFDE145A16CA0071CF22 /* TUITextRenderer+Accessibility.h in Headers */,
+ 48A10E8115B7769A007F9EE3 /* TUILayoutConstraint.h in Headers */,
+ 48A10E8315B7769A007F9EE3 /* TUILayoutManager.h in Headers */,
+ 48A10E8B15B77A46007F9EE3 /* TUIView+Layout.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1041,6 +1062,9 @@
884E8F5E1538809C000F7A8D /* CAAnimation+TUIExtensions.m in Sources */,
30D399C9156D8ADD006ECDAE /* TUIProgressBar.m in Sources */,
88D81D001577EF0D009D453B /* TUIStyledView.m in Sources */,
+ 48A10E8215B7769A007F9EE3 /* TUILayoutConstraint.m in Sources */,
+ 48A10E8415B7769A007F9EE3 /* TUILayoutManager.m in Sources */,
+ 48A10E8915B778E8007F9EE3 /* TUIView+Layout.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -0,0 +1,61 @@
+@class TUIView;
+
+typedef enum : NSUInteger {
+ TUILayoutConstraintAttributeMinY = 1,
+ TUILayoutConstraintAttributeMaxY = 2,
+ TUILayoutConstraintAttributeMinX = 3,
+ TUILayoutConstraintAttributeMaxX = 4,
+ TUILayoutConstraintAttributeWidth = 5,
+ TUILayoutConstraintAttributeHeight = 6,
+ TUILayoutConstraintAttributeMidY = 7,
+ TUILayoutConstraintAttributeMidX = 8,
+
+ TUILayoutConstraintAttributeMinXMinY = 101,
+ TUILayoutConstraintAttributeMinXMidY = 102,
+ TUILayoutConstraintAttributeMinXMaxY = 103,
+
+ TUILayoutConstraintAttributeMidXMinY = 104,
+ TUILayoutConstraintAttributeMidXMidY = 105,
+ TUILayoutConstraintAttributeMidXMaxY = 106,
+
+ TUILayoutConstraintAttributeMaxXMinY = 107,
+ TUILayoutConstraintAttributeMaxXMidY = 108,
+ TUILayoutConstraintAttributeMaxXMaxY = 109,
+
+ TUILayoutConstraintAttributeBoundsCenter = 110,
+
+ TUILayoutConstraintAttributeFrame = 1000,
+ TUILayoutConstraintAttributeBounds = 1001
+} TUILayoutConstraintAttribute;
+
+typedef CGFloat (^TUILayoutTransformer)(CGFloat);
+
+@interface TUILayoutConstraint : NSObject
+
+@property (readonly) TUILayoutConstraintAttribute attribute;
+@property (readonly) TUILayoutConstraintAttribute sourceAttribute;
+@property (readonly) NSString *sourceName;
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr;
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ offset:(CGFloat)offset;
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ scale:(CGFloat)scale
+ offset:(CGFloat)offset;
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ blockTransformer:(TUILayoutTransformer)transformer;
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ valueTransformer:(NSValueTransformer *)transformer;
+
+@end
@@ -0,0 +1,142 @@
+#import "TUILayoutConstraint.h"
+#import "TUILayoutManager.h"
+
+@interface TUIView (Layout_Private)
+
+- (NSRect)valueForLayoutAttribute:(TUILayoutConstraintAttribute)attribute;
+- (void)setValue:(NSRect)newValue forLayoutAttribute:(TUILayoutConstraintAttribute)attribute;
+
+@end
+
+
+@interface TUILayoutConstraint ()
+
+@property (nonatomic, copy) NSValueTransformer *valueTransformer;
+
+- (CGFloat)transformValue:(CGFloat)original;
+- (void)applyToTargetView:(TUIView *)target;
+- (void)applyToTargetView:(TUIView *)target sourceView:(TUIView *)source;
+
+@end
+
+@interface TUILayoutBlockValueTransformer : NSValueTransformer
+
+@property (nonatomic, copy) TUILayoutTransformer transformer;
+
++ (id)transformerWithBlock:(TUILayoutTransformer)block;
+- (id)initWithBlock:(TUILayoutTransformer)block;
+
+@end
+
+@implementation TUILayoutConstraint
+
+@synthesize attribute = _attribute;
+@synthesize sourceAttribute = _sourceAttribute;
+@synthesize sourceName = _sourceName;
+@synthesize valueTransformer = _valueTransformer;
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr {
+ return [self constraintWithAttribute:attr relativeTo:srcLayer attribute:srcAttr scale:1.0 offset:0.0];
+}
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ offset:(CGFloat)offset {
+ return [self constraintWithAttribute:attr relativeTo:srcLayer attribute:srcAttr scale:1.0 offset:offset];
+}
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)source
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ scale:(CGFloat)scale
+ offset:(CGFloat)offset {
+ return [[self alloc] initWithAttribute:attr relativeTo:source attribute:srcAttr scale:scale offset:offset];
+}
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ blockTransformer:(TUILayoutTransformer)transformer {
+ TUILayoutBlockValueTransformer *t = [TUILayoutBlockValueTransformer transformerWithBlock:transformer];
+ return [self constraintWithAttribute:attr relativeTo:srcLayer attribute:srcAttr valueTransformer:t];
+}
+
++ (id)constraintWithAttribute:(TUILayoutConstraintAttribute)attr
+ relativeTo:(NSString *)srcLayer
+ attribute:(TUILayoutConstraintAttribute)srcAttr
+ valueTransformer:(NSValueTransformer *)transformer {
+ return [[self alloc] initWithAttribute:attr relativeTo:srcLayer attribute:srcAttr valueTransformer:transformer];
+}
+
+- (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);
+
+ if((self = [super init])) {
+ _attribute = attr;
+ _sourceAttribute = srcAttr;
+
+ _sourceName = [srcLayer copy];
+ _valueTransformer = transformer;
+ }
+ return self;
+}
+
+- (CGFloat)transformValue:(CGFloat)original {
+ id transformed = [self.valueTransformer transformedValue:[NSNumber numberWithFloat:original]];
+ return [transformed floatValue];
+}
+
+- (void)applyToTargetView:(TUIView *)target {
+ TUIView *source = [target relativeViewForName:[self sourceName]];
+ [self applyToTargetView:target sourceView:source];
+}
+
+- (void)applyToTargetView:(TUIView *)target sourceView:(TUIView *)source {
+ if(source == target) return;
+ if(source == nil) return;
+ if([self sourceAttribute] == 0) return;
+
+ NSRect sourceValue = [source valueForLayoutAttribute:[self sourceAttribute]];
+ NSRect targetValue = sourceValue;
+
+ if(self.attribute >= TUILayoutConstraintAttributeMinY && self.attribute <= TUILayoutConstraintAttributeMidX)
+ targetValue.origin.x = [self transformValue:sourceValue.origin.x];
+
+ [target setValue:targetValue forLayoutAttribute:[self attribute]];
+}
+
+@end
+
+@implementation TUILayoutBlockValueTransformer
+
+@synthesize transformer = _transformer;
+
++ (id)transformerWithBlock:(TUILayoutTransformer)block {
+ return [[self alloc] initWithBlock:block];
+}
+
+- (id)initWithBlock:(TUILayoutTransformer)block {
+ if((self = [super init])) {
+ _transformer = [block copy];
+ }
+ return self;
+}
+
+- (id)transformedValue:(id)value {
+ if(!self.transformer) return nil;
+ CGFloat source = [value floatValue];
+ CGFloat transformed = self.transformer(source);
+ return [NSNumber numberWithFloat:transformed];
+}
+
+@end
@@ -0,0 +1,20 @@
+#import "TUIView.h"
+
+@class TUILayoutConstraint;
+
+@interface TUILayoutManager : NSObject
+
++ (id)sharedLayoutManager;
+
+- (void)addLayoutConstraint:(TUILayoutConstraint *)constraint toView:(TUIView *)view;
+- (void)removeLayoutConstraintsFromView:(TUIView *)view;
+
+- (NSArray *)layoutConstraintsOnView:(TUIView *)view;
+- (void)removeAllLayoutConstraints;
+
+- (NSString *)layoutNameForView:(TUIView *)view;
+- (void)setLayoutName:(NSString *)name forView:(TUIView *)view;
+
+- (void)beginProcessingView:(TUIView *)aView;
+
+@end
Oops, something went wrong.

0 comments on commit 1c7a8cd

Please sign in to comment.