-
Notifications
You must be signed in to change notification settings - Fork 4
/
LHPhotoStream.m
146 lines (115 loc) · 4.2 KB
/
LHPhotoStream.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// LHPhotoStream.m
// LastHistory
//
// Created by Frederik Seiffert on 10.12.09.
// Copyright 2009 Frederik Seiffert. All rights reserved.
//
#import "LHPhotoStream.h"
#import "LHHistoryView.h"
#import "LHDocument.h"
#import "LHHistoryEntry.h"
#import "LHiPhotoLibrary.h"
#import "NSImage-Extras.h"
#define PHOTOS_HEIGHT_MIN 10.0
#define PHOTOS_HEIGHT_MAX 50.0
@implementation LHPhotoStream
+ (Class)nodeClass
{
return [LHiPhotoRoll class];
}
- (void)setupLayer
{
self.anchorPoint = CGPointMake(0, 0);
self.bounds = CGRectMake(0, 0, self.superlayer.bounds.size.width, PHOTOS_HEIGHT_MAX);
}
- (void)generateNodes
{
[self removeAllSublayers];
// load iPhoto library
LHiPhotoLibrary *library = [LHiPhotoLibrary defaultLibrary];
NSArray *rolls = library.rolls;
NSLog(@"Generating photo nodes...");
NSDate *startDate = self.view.document.firstHistoryEntry.timestamp;
NSDate *endDate = self.view.document.lastHistoryEntry.timestamp;
CGFloat photoPosY = self.bounds.size.height / 2.0;
NSUInteger processedCount = 0;
for (LHiPhotoRoll *roll in rolls)
{
if ([roll.eventEnd compare:startDate] == NSOrderedDescending
&& [roll.eventStart compare:endDate] == NSOrderedAscending)
{
CALayer *layer = [CALayer layer];
[layer setValue:roll forKey:LAYER_DATA_KEY];
NSUInteger historyEntryCount = [self.view.document numberOfHistoryEntriesForEvent:roll];
float weightFactor = MAX(1.0, MIN(PHOTOS_HEIGHT_MAX/PHOTOS_HEIGHT_MIN, (float)historyEntryCount / 10.0));
NSImage *image = roll.keyPhoto.thumb;
float aspectRatio = image.size.width / image.size.height;
layer.contentsGravity = kCAGravityResizeAspect;
layer.contents = (id)[image cgImage];
layer.anchorPoint = CGPointMake(1.0, 0.5);
layer.bounds = CGRectMake(0, 0, PHOTOS_HEIGHT_MIN * weightFactor * aspectRatio, PHOTOS_HEIGHT_MIN * weightFactor);
layer.position = CGPointMake([self.view xPositionForDate:roll.eventStart] + layer.bounds.size.width, photoPosY);
[self addSublayer:layer];
processedCount++;
}
}
NSLog(@"Generated %u photo nodes", processedCount);
}
- (void)layoutSublayers
{
if (self.superlayer.isHidden)
return;
CGFloat photoPosY = self.bounds.size.height / 2.0;
// reposition nodes
for (CALayer *layer in self.sublayers)
{
LHiPhotoRoll *roll = [layer valueForKey:LAYER_DATA_KEY];
layer.position = CGPointMake([self.view xPositionForDate:roll.eventStart] + layer.bounds.size.width, photoPosY);
}
}
- (void)setHighlightedNode:(CALayer *)newLayer
{
if (_highlightedNode != newLayer)
{
// restore key photo
LHiPhotoRoll *highlightedRoll = [_highlightedNode valueForKey:LAYER_DATA_KEY];
_highlightedNode.contents = (id)[highlightedRoll.keyPhoto.thumb cgImage];
// reset cache
[_highlightedNode setValue:nil forKey:@"currentPhoto"];
// set zPosition
_highlightedNode.zPosition = kDefaultZ;
newLayer.zPosition = kHighlightZ;
// scale to highlight
[_highlightedNode setValue:[NSNumber numberWithFloat:1.0] forKeyPath:@"transform.scale"];
float weightFactor = PHOTOS_HEIGHT_MAX / newLayer.bounds.size.height;
[newLayer setValue:[NSNumber numberWithFloat:3.0 * weightFactor] forKeyPath:@"transform.scale"];
_highlightedNode = newLayer;
}
}
- (void)mouseMoved:(NSEvent *)theEvent onLayer:(CALayer *)hitLayer
{
// set highlighted node
[super mouseMoved:theEvent onLayer:hitLayer];
// show roll photos on mouse-over
if (self.highlightedNode)
{
CALayer *rollLayer = self.highlightedNode;
LHiPhotoRoll *roll = [rollLayer valueForKey:LAYER_DATA_KEY];
// convert mouse coordianates
NSPoint mousePointInView = [self.view convertPoint:theEvent.locationInWindow fromView:nil];
CGPoint mousePointInRoll = [self.view.layer convertPoint:NSPointToCGPoint(mousePointInView) toLayer:rollLayer];
// find photo to display
float partOfRoll = mousePointInRoll.x / rollLayer.bounds.size.width; // between 0 and 1
NSUInteger photoIndex = roll.photos.count * partOfRoll;
if (photoIndex >= 0 && photoIndex < roll.photos.count)
{
LHiPhotoPhoto *photo = [roll.photos objectAtIndex:photoIndex];
if (![photo isEqual:[rollLayer valueForKey:@"currentPhoto"]]) {
rollLayer.contents = (id)[photo.thumb cgImage];
[rollLayer setValue:photo forKey:@"currentPhoto"];
}
}
}
}
@end