5 // Created by Pierre d'Herbemont on 1/14/08.
6 // Copyright 2008 __MyCompanyName__. All rights reserved.
9 #import "VLCMediaListLayer.h"
11 /*****************************************************************************
12 * @implementation VLCMediaListLayer
15 @interface VLCMediaListLayer (Private)
16 - (VLCMediaLayer *)selectedLayer;
17 - (VLCMediaLayer *)previousLayer;
18 - (VLCMediaLayer *)nextLayer;
19 - (void)changeSelectedLayerToNextIndex;
20 - (void)changeSelectedLayerToPreviousIndex;
24 - (void)setSelectedLayer:(VLCMediaLayer *)layer;
25 - (void)setPreviousLayer:(VLCMediaLayer *)layer;
26 - (void)setNextLayer:(VLCMediaLayer *)layer;
29 /*****************************************************************************
30 * @implementation VLCMediaListLayer
33 @implementation VLCMediaListLayer
34 @synthesize selectedIndex;
36 @synthesize controller;
40 VLCMediaListLayer * me = [super layer];
42 me.layoutManager = [CAConstraintLayoutManager layoutManager];
44 [CATransaction commit];
46 me->selectedIndex = NSNotFound;
50 + (id)layerWithMediaArrayController:(VLCMediaArrayController *)aController
52 VLCMediaListLayer * me = [VLCMediaListLayer layer];
53 me.controller = aController;
55 /* The following will trigger -observeValueForKeyPath: ofObject: change: context: */
56 [me.controller addObserver:me forKeyPath:@"arrangedObjects" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
57 [me.controller addObserver:me forKeyPath:@"selectionIndex" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
58 [me.controller addObserver:me forKeyPath:@"contentMediaList" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
65 /* Previously registered in +layerWithMediaArrayController: */
66 [self.controller removeObserver:self forKeyPath:@"arrangedObjects"];
67 [self.controller removeObserver:self forKeyPath:@"contentMediaList"];
68 [self.controller removeObserver:self forKeyPath:@"selectionIndex"];
73 /*****************************************************************************
74 * @implementation VLCMediaListLayer (Private)
77 @implementation VLCMediaListLayer (Private)
78 + (NSSet *)keyPathsForValuesAffectingSelectedLayer
80 return [NSSet setWithObjects:@"selectedLayer", @"content", nil];
83 - (VLCMediaLayer *)selectedLayer
85 VLCMedia * media = (self.selectedIndex != NSNotFound) ? [self.content objectAtIndex:self.selectedIndex ] : nil;
88 CATextLayer * layer = [CATextLayer layer];
89 CALayer * container = [CALayer layer];
90 container.layoutManager = [CAConstraintLayoutManager layoutManager];
91 if([self.controller.contentMediaList isReadOnly])
92 layer.string = @"Empty";
93 else if ([self.content count])
94 layer.string = @"Empty search.";
96 layer.string = @"Drag and Drop a movie or a music here.";
97 layer.alignmentMode = kCAAlignmentCenter;
99 [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
100 [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX relativeTo:@"superlayer" attribute:kCAConstraintMidX]];
101 [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintWidth relativeTo:@"superlayer" attribute:kCAConstraintWidth]];
102 [container addSublayer:layer];
103 return (VLCMediaLayer *)container;
106 if( [selectedLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[selectedLayer media]] == NSOrderedSame )
107 return [[selectedLayer retain] autorelease];
109 return [VLCMediaLayer layerWithMedia:[self.content objectAtIndex:self.selectedIndex]];
112 - (VLCMediaLayer *)previousLayer
114 if( self.selectedIndex == NSNotFound )
116 VLCMedia * media = self.selectedIndex > 0 ? [self.content objectAtIndex:self.selectedIndex - 1] : nil;
120 if( [previousLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[previousLayer media]] == NSOrderedSame )
121 return [[previousLayer retain] autorelease];
123 return [VLCMediaLayer layerWithMedia: media ];
126 - (VLCMediaLayer *)nextLayer
128 if( self.selectedIndex == NSNotFound )
130 VLCMedia * media = self.selectedIndex + 1 < [content count] ? [self.content objectAtIndex:self.selectedIndex + 1] : nil;
134 if( [nextLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[nextLayer media]] == NSOrderedSame )
135 return [[nextLayer retain] autorelease];
137 return [VLCMediaLayer layerWithMedia: media ];
140 - (void)changeSelectedLayerToNextIndex
144 /* Can't do anything */
149 /* Remove offscreen layer. Without actions */
152 [CATransaction begin];
153 [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
154 [previousLayer removeFromSuperlayer];
155 [CATransaction commit];
158 [CATransaction begin];
159 if ( [[NSApp currentEvent] modifierFlags] & NSShiftKeyMask )
160 [CATransaction setValue:[NSNumber numberWithFloat:1.5] forKey:kCATransactionAnimationDuration];
162 [self setPreviousLayer: selectedLayer];
163 [self setSelectedLayer: nextLayer];
164 [self setNextLayer: [self nextLayer]];
165 [CATransaction commit];
167 /* Move the new nextLayer layer on screen. Without Actions */
168 [CATransaction begin];
169 [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
170 [self addSublayer: nextLayer];
171 [CATransaction commit];
174 - (void)changeSelectedLayerToPreviousIndex
178 /* Can't do anything */
183 /* Remove offscreen layer. Without actions */
186 [CATransaction begin];
187 [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
188 [nextLayer removeFromSuperlayer];
189 [CATransaction commit];
192 [CATransaction begin];
193 if ( [[NSApp currentEvent] modifierFlags] & NSShiftKeyMask )
194 [CATransaction setValue:[NSNumber numberWithFloat:1.5] forKey:kCATransactionAnimationDuration];
196 [self setNextLayer: selectedLayer];
197 [self setSelectedLayer: previousLayer];
198 [self setPreviousLayer: [self previousLayer]];
199 [CATransaction commit];
201 /* Move the new previous layer on screen. Without Actions */
202 [CATransaction begin];
203 [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
204 [self addSublayer:previousLayer];
205 [CATransaction commit];
208 - (void)gotoIndex:(NSUInteger)index;
210 if( selectedIndex == index )
213 if( selectedIndex > index )
215 /* It is ok to scroll five layers */
216 if( selectedIndex - index < 5 )
218 [self changeSelectedLayerToPreviousIndex];
221 [self changeSelectedLayerToPreviousIndex];
222 [self changeSelectedLayerToPreviousIndex];
223 selectedIndex = index;
228 if( index - selectedIndex < 5 )
230 [self changeSelectedLayerToNextIndex];
233 [self changeSelectedLayerToNextIndex];
234 [self changeSelectedLayerToNextIndex];
235 selectedIndex = index;
242 VLCMediaLayer * layer;
243 [CATransaction begin];
244 layer = [self previousLayer];
245 if( previousLayer != layer )
247 if( previousLayer ) [self replaceSublayer:previousLayer with:layer];
248 else [self addSublayer:layer];
249 [self setPreviousLayer:layer];
251 layer = [self selectedLayer];
252 if( selectedLayer != layer )
254 if( selectedLayer ) [self replaceSublayer:selectedLayer with:layer];
255 else [self addSublayer:layer];
256 [self setSelectedLayer:layer];
258 layer = [self nextLayer];
259 if( nextLayer != layer )
261 if( nextLayer ) [self replaceSublayer:nextLayer with:layer];
262 else [self addSublayer:layer];
263 [self setNextLayer:layer];
265 [CATransaction commit];
269 - (void)setSelectedLayer:(VLCMediaLayer *)layer
271 [selectedLayer autorelease];
277 selectedLayer = [layer retain];
278 selectedLayer.frame = [self bounds];
279 [selectedLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
282 - (void)setPreviousLayer:(VLCMediaLayer *)layer
284 [previousLayer autorelease];
290 previousLayer = [layer retain];
291 CGRect frame = [self bounds];
292 frame.origin.x -= frame.size.width;
293 previousLayer.frame = frame;
294 [previousLayer setAutoresizingMask:kCALayerMaxXMargin|kCALayerHeightSizable];
297 - (void)setNextLayer:(VLCMediaLayer *)layer
299 [nextLayer autorelease];
305 nextLayer = [layer retain];
306 CGRect frame = [self bounds];
307 frame.origin.x += frame.size.width;
308 nextLayer.frame = frame;
309 [nextLayer setAutoresizingMask:kCALayerMinXMargin|kCALayerHeightSizable];
312 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
314 if([keyPath isEqualToString:@"selectionIndex"])
316 if ( selectedIndex == NSNotFound || [object selectionIndex] == NSNotFound )
318 selectedIndex = [object selectionIndex];
319 if(selectedIndex == NSNotFound && [content count])
327 [self gotoIndex: [object selectionIndex]];
330 if([keyPath isEqualToString:@"arrangedObjects"] || [keyPath isEqualToString:@"contentMediaList"])
332 selectedIndex = [object selectionIndex];
333 if(selectedIndex == NSNotFound && [[object arrangedObjects] count])
338 content = [[object arrangedObjects] retain];
342 [self observeValueForKeyPath:keyPath ofObject:object change:change context:context];