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 while( index < selectedIndex )
219 [self changeSelectedLayerToPreviousIndex];
222 [self changeSelectedLayerToPreviousIndex];
223 [self changeSelectedLayerToPreviousIndex];
224 selectedIndex = index;
229 if( index - selectedIndex < 5 )
231 while( index > selectedIndex )
232 [self changeSelectedLayerToNextIndex];
235 [self changeSelectedLayerToNextIndex];
236 [self changeSelectedLayerToNextIndex];
237 selectedIndex = index;
244 VLCMediaLayer * layer;
245 [CATransaction begin];
246 layer = [self previousLayer];
247 if( previousLayer != layer )
249 if( previousLayer ) [self replaceSublayer:previousLayer with:layer];
250 else [self addSublayer:layer];
251 [self setPreviousLayer:layer];
253 layer = [self selectedLayer];
254 if( selectedLayer != layer )
256 if( selectedLayer ) [self replaceSublayer:selectedLayer with:layer];
257 else [self addSublayer:layer];
258 [self setSelectedLayer:layer];
260 layer = [self nextLayer];
261 if( nextLayer != layer )
263 if( nextLayer ) [self replaceSublayer:nextLayer with:layer];
264 else [self addSublayer:layer];
265 [self setNextLayer:layer];
267 [CATransaction commit];
271 - (void)setSelectedLayer:(VLCMediaLayer *)layer
273 [selectedLayer autorelease];
279 selectedLayer = [layer retain];
280 selectedLayer.frame = [self bounds];
281 [selectedLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
284 - (void)setPreviousLayer:(VLCMediaLayer *)layer
286 [previousLayer autorelease];
292 previousLayer = [layer retain];
293 CGRect frame = [self bounds];
294 frame.origin.x -= frame.size.width;
295 previousLayer.frame = frame;
296 [previousLayer setAutoresizingMask:kCALayerMaxXMargin|kCALayerHeightSizable];
299 - (void)setNextLayer:(VLCMediaLayer *)layer
301 [nextLayer autorelease];
307 nextLayer = [layer retain];
308 CGRect frame = [self bounds];
309 frame.origin.x += frame.size.width;
310 nextLayer.frame = frame;
311 [nextLayer setAutoresizingMask:kCALayerMinXMargin|kCALayerHeightSizable];
314 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
316 if([keyPath isEqualToString:@"selectionIndex"])
318 if ( selectedIndex == NSNotFound || [object selectionIndex] == NSNotFound )
320 selectedIndex = [object selectionIndex];
321 if(selectedIndex == NSNotFound && [content count])
329 [self gotoIndex: [object selectionIndex]];
332 if([keyPath isEqualToString:@"arrangedObjects"] || [keyPath isEqualToString:@"contentMediaList"])
334 selectedIndex = [object selectionIndex];
335 if(selectedIndex == NSNotFound && [[object arrangedObjects] count])
340 content = [[object arrangedObjects] retain];
344 [self observeValueForKeyPath:keyPath ofObject:object change:change context:context];