Revision: 15030 http://sourceforge.net/p/skim-app/code/15030 Author: hofman Date: 2025-03-27 16:53:35 +0000 (Thu, 27 Mar 2025) Log Message: ----------- Animate color swatch width for autolayout. Always update colors and itemViews before animating for insert/remove/move.
Modified Paths: -------------- trunk/SKColorSwatch.h trunk/SKColorSwatch.m Modified: trunk/SKColorSwatch.h =================================================================== --- trunk/SKColorSwatch.h 2025-03-27 10:23:44 UTC (rev 15029) +++ trunk/SKColorSwatch.h 2025-03-27 16:53:35 UTC (rev 15030) @@ -49,6 +49,7 @@ NSMutableArray<SKColorSwatchItemView *> *itemViews; NSControl *backgroundView; CGFloat bezelHeight; + CGFloat bezelWidth; NSInteger clickedIndex; NSInteger selectedIndex; Modified: trunk/SKColorSwatch.m =================================================================== --- trunk/SKColorSwatch.m 2025-03-27 10:23:44 UTC (rev 15029) +++ trunk/SKColorSwatch.m 2025-03-27 16:53:35 UTC (rev 15030) @@ -108,15 +108,25 @@ @interface SKColorSwatch () @property (nonatomic) NSInteger selectedColorIndex; -- (NSRect)frameForItemViewAtIndex:(NSInteger)anIndex collapsedIndex:(NSInteger)collapsedIndex; +@property (nonatomic) CGFloat bezelWidth; +- (NSRect)frameForItemViewAtIndex:(NSInteger)anIndex; - (void)setColor:(NSColor *)color atIndex:(NSInteger)i fromPanel:(BOOL)fromPanel; @end @implementation SKColorSwatch -@synthesize colors, autoResizes, selects, alternate, clickedColorIndex=clickedIndex, selectedColorIndex=selectedIndex; +@synthesize colors, autoResizes, selects, alternate, clickedColorIndex=clickedIndex, selectedColorIndex=selectedIndex, bezelWidth; @dynamic color; ++ (id)defaultAnimationForKey:(NSAnimatablePropertyKey)key { + if ([key isEqualToString:@"bezelWidth"]) { + CABasicAnimation *anim = [CABasicAnimation animation]; + [anim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]]; + return anim; + } else + return [super defaultAnimationForKey:key]; +} + - (Class)valueClassForBinding:(NSString *)binding { if ([binding isEqualToString:COLORS_KEY]) return [NSArray class]; @@ -130,6 +140,8 @@ selectedIndex = -1; draggedIndex = -1; + bezelWidth = 0.0; + [self registerForDraggedTypes:[NSColor readableTypesForPasteboard:[NSPasteboard pasteboardWithName:NSPasteboardNameDrag]]]; } @@ -154,7 +166,7 @@ [constraints setValue:@YES forKey:@"shouldBeArchived"]; [NSLayoutConstraint activateConstraints:constraints]; - SKColorSwatchItemView *itemView = [[SKColorSwatchItemView alloc] initWithFrame:[self frameForItemViewAtIndex:0 collapsedIndex:-1]]; + SKColorSwatchItemView *itemView = [[SKColorSwatchItemView alloc] initWithFrame:[self frameForItemViewAtIndex:0]]; [itemView setColor:[NSColor whiteColor]]; [self addSubview:itemView]; itemViews = [[NSMutableArray alloc] initWithObjects:itemView, nil]; @@ -214,16 +226,14 @@ return rect; } -- (NSRect)frameForItemViewAtIndex:(NSInteger)anIndex collapsedIndex:(NSInteger)collapsedIndex { - NSInteger i = anIndex; - if (collapsedIndex != -1 && anIndex > collapsedIndex) - i--; - NSRect rect = NSInsetRect([self frameForColorAtIndex:i], -COLOR_INSET, -COLOR_INSET); - if (collapsedIndex == anIndex) - rect.size.width -= DISTANCE_BETWEEN_COLORS; - return rect; +- (NSRect)frameForItemViewAtIndex:(NSInteger)anIndex { + return NSInsetRect([self frameForColorAtIndex:anIndex], -COLOR_INSET, -COLOR_INSET); } +- (NSRect)frameForCollapsedItemViewAtIndex:(NSInteger)anIndex { + return SKShrinkRect([self frameForItemViewAtIndex:anIndex], DISTANCE_BETWEEN_COLORS, NSMaxXEdge); +} + - (NSInteger)colorIndexAtPoint:(NSPoint)point { NSRect rect = [self frameForColorAtIndex:0]; NSInteger i, count = [colors count]; @@ -249,17 +259,21 @@ return count; } -- (NSSize)sizeForNumberOfColors:(NSUInteger)count { - NSEdgeInsets insets = [self alignmentRectInsets]; - return NSMakeSize(COLOR_INSET + count * DISTANCE_BETWEEN_COLORS + insets.left + insets.right, bezelHeight + insets.bottom + insets.top); +- (CGFloat)contentWidth { + return COLOR_INSET + [colors count] * DISTANCE_BETWEEN_COLORS; } - (NSSize)intrinsicContentSize { - return NSMakeSize(COLOR_INSET + [colors count] * DISTANCE_BETWEEN_COLORS, bezelHeight); + return NSMakeSize(bezelWidth ?: [self contentWidth], bezelHeight); } +- (NSSize)intrinsicFrameSize { + NSEdgeInsets insets = [self alignmentRectInsets]; + return NSMakeSize([self contentWidth] + insets.left + insets.right, bezelHeight + insets.bottom + insets.top); +} + - (void)sizeToFit { - [self setFrameSize:[self sizeForNumberOfColors:[colors count]]]; + [self setFrameSize:[self intrinsicFrameSize]]; } - (NSEdgeInsets)alignmentRectInsets { @@ -269,7 +283,7 @@ - (void)updateItemViewFrames { NSUInteger i, iMax = [itemViews count]; for (i = 0; i < iMax; i++) - [[itemViews objectAtIndex:i] setFrame:[self frameForItemViewAtIndex:i collapsedIndex:-1]]; + [[itemViews objectAtIndex:i] setFrame:[self frameForItemViewAtIndex:i]]; } - (void)updateBezelHeight { @@ -492,6 +506,11 @@ [super setEnabled:enabled]; } +- (void)setBezelWidth:(CGFloat)width { + bezelWidth = width; + [self invalidateIntrinsicContentSize]; +} + #pragma mark Modification - (void)selectColorAtIndex:(NSInteger)idx { @@ -585,9 +604,9 @@ [self setColor:color atIndex:i fromPanel:NO]; } -- (void)animateItemViewsCollapsing:(NSInteger)collapsedIndex { +- (void)animateItemViewFrames { [itemViews enumerateObjectsUsingBlock:^(SKColorSwatchItemView *itemView, NSUInteger i, BOOL *stop){ - NSRect frame = [self frameForItemViewAtIndex:i collapsedIndex:collapsedIndex]; + NSRect frame = [self frameForItemViewAtIndex:i]; if (NSEqualRects(frame, [itemView frame]) == NO) [[itemView animator] setFrame:frame]; }]; @@ -597,9 +616,9 @@ if (color && i >= 0 && i <= (NSInteger)[colors count]) { [self deactivate]; [self willChangeColors]; + bezelWidth = [self contentWidth]; [colors insertObject:color atIndex:i]; - [self invalidateIntrinsicContentSize]; - SKColorSwatchItemView *itemView = [[SKColorSwatchItemView alloc] initWithFrame:[self frameForItemViewAtIndex:i collapsedIndex:i]]; + SKColorSwatchItemView *itemView = [[SKColorSwatchItemView alloc] initWithFrame:[self frameForCollapsedItemViewAtIndex:i]]; [itemView setColor:color]; if (i < (NSInteger)[itemViews count]) [self addSubview:itemView positioned:NSWindowBelow relativeTo:[itemViews objectAtIndex:i]]; @@ -606,19 +625,20 @@ else [self addSubview:itemView positioned:NSWindowAbove relativeTo:nil]; [itemViews insertObject:itemView atIndex:i]; - NSSize size = [self sizeForNumberOfColors:[colors count]]; + [self didChangeColors]; [self noteFocusRingMaskChanged]; [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ - [self animateItemViewsCollapsing:-1]; + [self animateItemViewFrames]; + [[self animator] setBezelWidth:[self contentWidth]]; if (autoResizes) - [[self animator] setFrameSize:size]; + [[self animator] setFrameSize:[self intrinsicFrameSize]]; } completionHandler:^{ + [self setBezelWidth:0.0]; if (autoResizes) [self sizeToFit]; [self noteFocusRingMaskChanged]; }]; - [self didChangeColors]; } } @@ -625,22 +645,25 @@ - (void)removeColorAtIndex:(NSInteger)i { if (i >= 0 && i < (NSInteger)[colors count] && [colors count] > 1) { [self deactivate]; - NSSize size = [self sizeForNumberOfColors:[colors count] - 1]; + [self willChangeColors]; + bezelWidth = [self contentWidth]; + [colors removeObjectAtIndex:i]; + SKColorSwatchItemView *itemView = [itemViews objectAtIndex:i]; + [itemViews removeObjectAtIndex:i]; + [self didChangeColors]; [self noteFocusRingMaskChanged]; [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ - [self animateItemViewsCollapsing:i]; + [[itemView animator] setFrame:[self frameForCollapsedItemViewAtIndex:i]]; + [self animateItemViewFrames]; + [[self animator] setBezelWidth:[self contentWidth]]; if (autoResizes) - [[self animator] setFrameSize:size]; + [[self animator] setFrameSize:[self intrinsicFrameSize]]; } completionHandler:^{ - [self willChangeColors]; - [colors removeObjectAtIndex:i]; - [[itemViews objectAtIndex:i] removeFromSuperview]; - [itemViews removeObjectAtIndex:i]; - [self didChangeColors]; + [itemView removeFromSuperview]; + [self setBezelWidth:0.0]; if (autoResizes) [self sizeToFit]; - [self invalidateIntrinsicContentSize]; [self noteFocusRingMaskChanged]; }]; } @@ -658,9 +681,10 @@ [itemViews insertObject:itemView atIndex:to]; if (to > from) [self addSubview:itemView positioned:NSWindowAbove relativeTo:[itemViews objectAtIndex:to - 1]]; + [self didChangeColors]; [self noteFocusRingMaskChanged]; [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ - [self animateItemViewsCollapsing:-1]; + [self animateItemViewFrames]; } completionHandler:^{ if (to < from) @@ -667,7 +691,6 @@ [self addSubview:itemView positioned:NSWindowBelow relativeTo:[itemViews objectAtIndex:to + 1]]; [self noteFocusRingMaskChanged]; }]; - [self didChangeColors]; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Skim-app-commit mailing list Skim-app-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/skim-app-commit