AVMovieEditor/AVMovieEditor/AAPLMovieTimeline.m
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
The `AAPLMovieTimeline` and `AAPLMovieTimelineDelegate` protocols provide the infrastructure for drawing video track images in a timeline like view and track cursor movements and selections. |
*/ |
#import "AAPLMovieTimeline.h" |
#import "AAPLTimeRangeView.h" |
#import <QuartzCore/QuartzCore.h> |
@interface AAPLMovieTimeline() |
@property NSUInteger imagesAdded; |
@property CALayer *markerLayer; |
@property NSTrackingArea *trackingArea; |
@property CALayer *startPointMarker; |
@property NSPoint startingPoint; |
@property NSPoint endingPoint; |
@property NSUInteger numberOfMarkers; |
@property AAPLTimeRangeView *timeRangeView; |
@property NSTextField *timeLabel; |
@end |
@implementation AAPLMovieTimeline |
#pragma mark - initializers |
- (instancetype)initWithCoder:(nonnull NSCoder *)coder { |
if (self = [super initWithCoder:coder]) { |
// Setup a layer with a black background color |
self.wantsLayer = YES; |
self.layer = [CALayer layer]; |
self.layer.backgroundColor = [NSColor blackColor].CGColor; |
self.timeLabel = [[NSTextField alloc] init]; |
[self setupMarkerLayer]; |
//Add a tracking area to track the cursor in this view |
self.trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(-1.0, 0.0, self.frame.size.width, self.frame.size.height) options:(NSTrackingMouseMoved | NSTrackingActiveAlways) owner:self userInfo:nil]; |
[self addTrackingArea:self.trackingArea]; |
} |
return self; |
} |
- (CGFloat)imageViewWidth { |
return (self.frame.size.height * 16) / 9; |
} |
#pragma mark - Subview/Layer Management |
- (void)layout { |
// Remove the tracking area and re-add it when we layout in case the frame has changed size. |
if (self.trackingArea != nil) { |
[self removeTrackingArea:self.trackingArea]; |
self.trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(-1.0, 0.0, self.frame.size.width, self.frame.size.height) options:(NSTrackingMouseMoved | NSTrackingActiveAlways) owner:self userInfo:nil]; |
[self addTrackingArea:self.trackingArea]; |
} |
[super layout]; |
} |
- (void)setupMarkerLayer { |
// Add the markerlayer and the timelabel for the timeline. |
self.markerLayer = [CALayer layer]; |
self.markerLayer.frame = CGRectMake(0.0f, 0.0f, 5.0, self.frame.size.height); |
self.markerLayer.backgroundColor = [NSColor redColor].CGColor; |
[self.layer addSublayer:self.markerLayer]; |
self.timeLabel.frame = NSMakeRect(self.frame.origin.x, self.frame.origin.y, 50.0f, 25.0f); |
self.timeLabel.backgroundColor = [NSColor clearColor]; |
self.timeLabel.textColor = [NSColor whiteColor]; |
self.timeLabel.drawsBackground = NO; |
self.timeLabel.editable = NO; |
self.timeLabel.bezeled = NO; |
[self addSubview:self.timeLabel]; |
} |
- (void)updateTimeLabel:(NSString *)newLabel { |
self.timeLabel.stringValue = newLabel; |
} |
- (void)addImageView:(NSImage *)image { |
CGFloat nextX = self.imagesAdded * self.imageViewWidth; |
NSImageView *nextView = [[NSImageView alloc] initWithFrame:NSMakeRect(nextX, 0.0, self.imageViewWidth, self.frame.size.height)]; |
nextView.image = image; |
[self addSubview:nextView]; |
[self setNeedsDisplayInRect:self.frame]; |
self.imagesAdded++; |
// Remove the marker layer and time label then re add them to draw above the images. |
[self.markerLayer removeFromSuperlayer]; |
[self.timeLabel removeFromSuperview]; |
[self addSubview:self.timeLabel]; |
[self.layer addSublayer:self.markerLayer]; |
} |
- (void)removeAllPositionalSubviews { |
[self.subviews enumerateObjectsUsingBlock:^(__kindof NSView * __nonnull subView, NSUInteger idx, BOOL * __nonnull stop) { |
[subView removeFromSuperview]; |
}]; |
self.imagesAdded = 0; |
} |
- (NSUInteger)countOfImagesRequiredToFillView { |
return floor(self.frame.size.width / self.imageViewWidth); |
} |
#pragma mark - Cursor Movement methods |
- (void)moveMarkerLayerAndtimeLabelWithMouse:(NSEvent *)theEvent { |
NSPoint windowLocation = theEvent.locationInWindow; |
NSPoint newPoint = [self convertPoint:windowLocation fromView:nil]; |
[CATransaction begin]; |
[CATransaction setDisableActions:YES]; |
self.markerLayer.frame = CGRectMake(newPoint.x, 0.0f, 5.0f, self.frame.size.height); |
self.timeLabel.frame = NSMakeRect(newPoint.x + 5.0f, 0.0f, 50.0f, 25.0f); |
[CATransaction commit]; |
[self.delegate movieTimeline:self didUpdateCursorToPoint:newPoint]; |
} |
- (void)mouseDown:(nonnull NSEvent *)theEvent { |
[self.timeRangeView removeFromSuperview]; |
self.startingPoint = [self convertPoint:theEvent.locationInWindow toView:nil]; |
} |
- (void)mouseMoved:(nonnull NSEvent *)theEvent { |
[self moveMarkerLayerAndtimeLabelWithMouse:theEvent]; |
} |
- (void)mouseDragged:(nonnull NSEvent *)theEvent { |
[self moveMarkerLayerAndtimeLabelWithMouse:theEvent]; |
} |
- (void)mouseUp:(nonnull NSEvent *)theEvent { |
self.endingPoint = [self convertPoint:theEvent.locationInWindow fromView:nil]; |
if (self.startingPoint.x == self.endingPoint.x) { |
[self.timeRangeView removeFromSuperview]; |
self.startPointMarker.frame = CGRectMake(self.endingPoint.x, 0.0f, 5.0f, self.frame.size.height); |
self.startPointMarker.backgroundColor = [NSColor yellowColor].CGColor; |
[self.delegate didSelectTimelinePoint:self.endingPoint]; |
} else { |
[self.startPointMarker removeFromSuperlayer]; |
self.timeRangeView = [[AAPLTimeRangeView alloc] initWithFrame:NSMakeRect(self.startingPoint.x, 0.0, self.endingPoint.x - self.startingPoint.x, self.frame.size.height)]; |
[self addSubview:self.timeRangeView]; |
[self.delegate didSelectTimelineRangeFromPoint:self.startingPoint toPoint:self.endingPoint]; |
self.endingPoint = NSZeroPoint; |
} |
} |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-09-16