From 5f24a91d44e9f92e65bfa815716ef7e2c19c8ee0 Mon Sep 17 00:00:00 2001 From: Allan Odgaard Date: Fri, 14 Sep 2012 14:09:46 +0200 Subject: [PATCH] Auto-layout: Update OakDocumentView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gutter will invalidate its intrinsic size when its width changes which will cause the Cocoa layout engine to update the layout, so no more explicit code to deal with adjusting the gutter’s width. Likewise, the height of the gutter (not the gutter scroll view) has been setup to match the height of the text view (again, not the containing scroll view). This avoids observing the text view frame and manually updating gutter height to match it. --- Frameworks/OakTextView/src/GutterView.h | 1 - Frameworks/OakTextView/src/GutterView.mm | 13 +- Frameworks/OakTextView/src/OakDocumentView.h | 2 - Frameworks/OakTextView/src/OakDocumentView.mm | 162 ++++++------------ Frameworks/OakTextView/src/OakTextView.mm | 1 - 5 files changed, 65 insertions(+), 114 deletions(-) diff --git a/Frameworks/OakTextView/src/GutterView.h b/Frameworks/OakTextView/src/GutterView.h index ed5c4439..5b8d3785 100644 --- a/Frameworks/OakTextView/src/GutterView.h +++ b/Frameworks/OakTextView/src/GutterView.h @@ -72,5 +72,4 @@ struct GVLineRecord - (void)insertColumnWithIdentifier:(NSString*)columnIdentifier atPosition:(NSUInteger)index dataSource:(id )columnDataSource delegate:(id )columnDelegate; - (void)setVisibility:(BOOL)visible forColumnWithIdentifier:(NSString*)columnIdentifier; - (BOOL)visibilityForColumnWithIdentifier:(NSString*)identifier; -- (void)sizeToFit; @end diff --git a/Frameworks/OakTextView/src/GutterView.mm b/Frameworks/OakTextView/src/GutterView.mm index c3e5d4ae..fdb3a63e 100644 --- a/Frameworks/OakTextView/src/GutterView.mm +++ b/Frameworks/OakTextView/src/GutterView.mm @@ -385,7 +385,7 @@ static void DrawText (std::string const& text, CGRect const& rect, CGFloat basel } } -- (void)sizeToFit +- (CGFloat)updateWidth { static const CGFloat columnPadding = 1; @@ -404,13 +404,21 @@ static void DrawText (std::string const& text, CGRect const& rect, CGFloat basel it->width = 0; } } - [self setFrameSize:NSMakeSize(totalWidth, NSHeight([self frame]))]; + + return totalWidth; +} + +- (NSSize)intrinsicContentSize +{ + return NSMakeSize([self updateWidth], NSViewNoInstrinsicMetric); } - (void)reloadData:(id)sender { D(DBF_GutterView, bug("\n");); [self setNeedsDisplay:YES]; + if([self updateWidth] != NSWidth(self.frame)) + [self invalidateIntrinsicContentSize]; } - (NSRect)columnRectForPoint:(NSPoint)aPoint @@ -489,6 +497,7 @@ static void DrawText (std::string const& text, CGRect const& rect, CGFloat basel if(visible) [hiddenColumns removeObject:columnIdentifier]; else [hiddenColumns addObject:columnIdentifier]; + [self invalidateIntrinsicContentSize]; } // ================== diff --git a/Frameworks/OakTextView/src/OakDocumentView.h b/Frameworks/OakTextView/src/OakDocumentView.h index 72cf87cc..e840d1eb 100644 --- a/Frameworks/OakTextView/src/OakDocumentView.h +++ b/Frameworks/OakTextView/src/OakDocumentView.h @@ -27,8 +27,6 @@ PUBLIC @interface OakDocumentView : NSView =100)]|" options:NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom metrics:nil views:views]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[statusBar]|" options:0 metrics:nil views:views]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[gutterView(==textView)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(gutterView, textView)]]; + + NSMutableArray* stackedViews = [NSMutableArray array]; + [stackedViews addObjectsFromArray:topAuxiliaryViews]; + [stackedViews addObject:gutterScrollView]; + [stackedViews addObjectsFromArray:bottomAuxiliaryViews]; + [stackedViews addObject:statusBar]; + + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topView]" options:0 metrics:nil views:@{ @"topView" : stackedViews[0] }]]; + for(size_t i = 0; i < [stackedViews count]-1; ++i) + [self addConstraint:[NSLayoutConstraint constraintWithItem:stackedViews[i] attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:stackedViews[i+1] attribute:NSLayoutAttributeTop multiplier:1 constant:0]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomView]|" options:0 metrics:nil views:@{ @"bottomView" : stackedViews.lastObject }]]; + + for(NSArray* views : { topAuxiliaryViews, bottomAuxiliaryViews }) + { + for(NSView* view in views) + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]]; + } +} + - (NSImage*)gutterImage:(NSString*)aName { if(NSImage* res = [[[NSImage imageNamed:aName inSameBundleAsClass:[self class]] copy] autorelease]) @@ -221,7 +199,7 @@ private: kFoldingsColumnIdentifier : @[ [NSNull null], [self gutterImage:@"Folding Top Hover"], [self gutterImage:@"Folding Collapsed Hover"], [self gutterImage:@"Folding Bottom Hover"] ], }; - [self updateGutterHeight]; + [gutterView reloadData:self]; } - (IBAction)makeTextLarger:(id)sender { [self setFont:[NSFont fontWithName:[textView.font fontName] size:[textView.font pointSize] + 1]]; } @@ -319,7 +297,7 @@ private: } [textView setDocument:document]; - [self updateGutterHeight]; + [gutterView reloadData:self]; [self updateStyle]; if(oldDocument) @@ -382,9 +360,6 @@ private: D(DBF_OakDocumentView, bug("show line numbers %s\n", BSTR([gutterView visibilityForColumnWithIdentifier:GVLineNumbersColumnIdentifier]));); BOOL isVisibleFlag = ![gutterView visibilityForColumnWithIdentifier:GVLineNumbersColumnIdentifier]; [gutterView setVisibility:isVisibleFlag forColumnWithIdentifier:GVLineNumbersColumnIdentifier]; - [gutterView sizeToFit]; - [self updateGutterWidth]; - if(isVisibleFlag) [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"DocumentView Disable Line Numbers"]; else [[NSUserDefaults standardUserDefaults] setObject:YES_obj forKey:@"DocumentView Disable Line Numbers"]; @@ -405,46 +380,17 @@ private: // = Auxiliary Views = // =================== -- (void)layoutAuxiliaryViews -{ - CGFloat topHeight = 0, bottomHeight = 0; - for(NSView* view in topAuxiliaryViews) - topHeight += NSHeight(view.frame); - for(NSView* view in bottomAuxiliaryViews) - bottomHeight += NSHeight(view.frame); - - CGFloat totalHeight = NSHeight(self.frame); - CGFloat docHeight = totalHeight - NSHeight(statusBar.frame) - topHeight - bottomHeight; - CGFloat gutterWidth = NSWidth(gutterScrollView.frame) + 1; - - CGFloat y = NSHeight(statusBar.frame); - for(NSView* view in bottomAuxiliaryViews) - { - [view setFrame:NSMakeRect(0, y, NSWidth(self.frame), NSHeight(view.frame))]; - y += NSHeight(view.frame); - } - - [gutterScrollView setFrame:NSMakeRect(0, y, gutterWidth - 1, docHeight)]; - [gutterDividerView setFrame:NSMakeRect(gutterWidth - 1, y, 1, docHeight)]; - [textScrollView setFrame:NSMakeRect(gutterWidth, y, NSWidth(textScrollView.frame), docHeight)]; - - y += docHeight; - for(NSView* view in topAuxiliaryViews) - { - [view setFrame:NSMakeRect(0, y, NSWidth(self.frame), NSHeight(view.frame))]; - y += NSHeight(view.frame); - } -} - - (void)addAuxiliaryView:(NSView*)aView atEdge:(NSRectEdge)anEdge { + [aView setTranslatesAutoresizingMaskIntoConstraints:NO]; + topAuxiliaryViews = topAuxiliaryViews ?: [NSMutableArray new]; bottomAuxiliaryViews = bottomAuxiliaryViews ?: [NSMutableArray new]; if(anEdge == NSMinYEdge) [bottomAuxiliaryViews addObject:aView]; else [topAuxiliaryViews addObject:aView]; [self addSubview:aView]; - [self layoutAuxiliaryViews]; + [self setNeedsUpdateConstraints:YES]; } - (void)removeAuxiliaryView:(NSView*)aView @@ -456,7 +402,7 @@ private: else return; [aView removeFromSuperview]; - [self layoutAuxiliaryViews]; + [self setNeedsUpdateConstraints:YES]; } - (void)drawRect:(NSRect)aRect diff --git a/Frameworks/OakTextView/src/OakTextView.mm b/Frameworks/OakTextView/src/OakTextView.mm index 7f965f42..dc208a1f 100644 --- a/Frameworks/OakTextView/src/OakTextView.mm +++ b/Frameworks/OakTextView/src/OakTextView.mm @@ -1448,7 +1448,6 @@ static void update_menu_key_equivalents (NSMenu* menu, action_to_key_t const& ac if(!liveSearchViewController) { self.liveSearchViewController = [[NSViewController alloc] initWithNibName:@"SearchField" bundle:[NSBundle bundleForClass:[self class]]]; - [liveSearchViewController.view setAutoresizingMask:NSViewWidthSizable|NSViewMaxYMargin]; [documentView addAuxiliaryView:liveSearchViewController.view atEdge:NSMinYEdge]; }