source: trunk/SapphireBrowser.m @ 42

Revision 42, 11.2 KB checked in by gbooker, 7 years ago (diff)

Use tab alignments, makes a much nicer meta-data display.

Line 
1//
2//  SapphireBrowser.m
3//  Sapphire
4//
5//  Created by pnmerrill on 6/20/07.
6//  Copyright 2007 __MyCompanyName__. All rights reserved.
7//
8
9#import "SapphireBrowser.h"
10#import <BackRow/BackRow.h>
11#import "SapphireMetaData.h"
12#import "SapphireMarkMenu.h"
13#import "SapphireMedia.h"
14#import "SapphireVideoPlayer.h"
15#import "SapphireMediaPreview.h"
16
17@interface SapphireBrowser (private)
18- (void)reloadDirectoryContents;
19- (void)processFiles:(NSArray *)files;
20- (void)filesProcessed:(NSDictionary *)files;
21- (NSMutableDictionary *)metaDataForPath:(NSString *)path;
22@end
23
24@interface BRTVShowsSortControl (bypassAccess)
25- (BRTVShowsSortSelectorStateLayer *)gimmieDate;
26- (BRTVShowsSortSelectorStateLayer *)gimmieShow;
27- (int)gimmieState;
28@end
29
30@interface BRTVShowsSortSelectorStateLayer (bypassAccess)
31- (BRTextLayer *)gimmieDate;
32- (BRTextLayer *)gimmieShow;
33@end
34
35
36@implementation BRTVShowsSortControl (bypassAccess)
37- (BRTVShowsSortSelectorStateLayer *)gimmieDate
38{
39        return _sortedByDateWidget;
40}
41
42- (BRTVShowsSortSelectorStateLayer *)gimmieShow
43{
44        return _sortedByShowWidget;
45}
46
47- (int)gimmieState
48{
49        return _state;
50}
51
52@end
53
54@implementation BRTVShowsSortSelectorStateLayer (bypassAccess)
55- (BRTextLayer *)gimmieDate
56{
57        return _dateLayer;
58}
59
60- (BRTextLayer *)gimmieShow
61{
62        return _showLayer;
63}
64
65@end
66
67@implementation SapphireBrowser
68
69- (void)replaceControlText:(BRTextLayer *)control withString:(NSString *)str
70{
71        NSMutableAttributedString  *dateString = [[control attributedString] mutableCopy];
72        [dateString replaceCharactersInRange:NSMakeRange(0, [dateString length]) withString:str];
73        [control setAttributedString:dateString];
74        [dateString release];
75}
76
77- (id) initWithScene: (BRRenderScene *) scene metaData: (SapphireDirectoryMetaData *)meta
78{
79        return [self initWithScene:scene metaData:meta predicate:NULL];
80}
81
82- (id) initWithScene: (BRRenderScene *) scene metaData: (SapphireDirectoryMetaData *)meta predicate:(SapphirePredicate *)newPredicate;
83{
84        if ( [super initWithScene: scene] == nil ) return ( nil );
85               
86        _names = [NSMutableArray new];
87        metaData = [meta retain];
88        [metaData setDelegate:self];
89        predicate = [newPredicate retain];
90        sort = [[BRTVShowsSortControl alloc] initWithScene:scene state:1];
91
92        NSRect frame = [self masterLayerFrame];
93        NSRect sortRect;
94        sortRect.size = [sort preferredSizeForScreenHeight:frame.size.height];
95        sortRect.origin.y = frame.origin.y;
96        NSRect listFrame = [self listFrameForBounds:frame.size];
97        sortRect.origin.x = (listFrame.size.width - sortRect.size.width)/2 + listFrame.origin.x;
98        [self replaceControlText:[[sort gimmieDate] gimmieDate] withString:@"Select"];
99        [self replaceControlText:[[sort gimmieDate] gimmieShow] withString:@"Mark"];
100        [self replaceControlText:[[sort gimmieShow] gimmieDate] withString:@"Select"];
101        [self replaceControlText:[[sort gimmieShow] gimmieShow] withString:@"Mark"];
102        [sort setFrame:sortRect];
103        [self addControl:sort];
104       
105        // set the datasource *after* you've setup your array
106        [[self list] setDatasource: self] ;
107               
108        return ( self );
109}
110
111- (void)reloadDirectoryContents
112{
113        int divider = 0;
114        [metaData reloadDirectoryContents];
115        [_names removeAllObjects];
116        if(predicate == NULL)
117        {
118                [_names addObjectsFromArray:[metaData directories]];
119                divider = [_names count];
120                [_names addObjectsFromArray:[metaData files]];
121        }
122        else
123        {
124                [_names addObjectsFromArray:[metaData predicatedDirectories:predicate]];
125                divider = [_names count];
126                [_names addObjectsFromArray:[metaData predicatedFiles:predicate]];
127        }
128
129        BRListControl *list = [self list];
130        [list reload];
131        if(divider && divider != [_names count])
132                [list addDividerAtIndex:divider];
133        [[self scene] renderScene];
134}
135
136- (void) dealloc
137{
138    // always remember to deallocate your resources
139        [_names release];
140        [metaData release];
141        [predicate release];
142        [sort release];
143    [super dealloc];
144}
145
146- (void) willBePushed
147{
148    // We're about to be placed on screen, but we're not yet there
149   
150    // always call super
151    [super willBePushed];
152        [self reloadDirectoryContents];
153}
154
155- (void) wasPushed
156{
157    // We've just been put on screen, the user can see this controller's content now
158   
159    // always call super
160    [super wasPushed];
161        [metaData resumeImport];
162}
163
164- (void) willBePopped
165{
166    // The user pressed Menu, but we've not been removed from the screen yet
167   
168    // always call super
169    [super willBePopped];
170        [metaData cancelImport];
171        [metaData setDelegate:nil];
172}
173
174- (void) wasPopped
175{
176    // The user pressed Menu, removing us from the screen
177   
178    // always call super
179    [super wasPopped];
180}
181
182- (void) willBeBuried
183{
184    // The user just chose an option, and we will be taken off the screen
185   
186    // always call super
187        [metaData cancelImport];
188    [super willBeBuried];
189}
190
191- (void) wasBuriedByPushingController: (BRLayerController *) controller
192{
193    // The user chose an option and this controller os no longer on screen
194   
195    // always call super
196    [super wasBuriedByPushingController: controller];
197}
198
199- (void) willBeExhumed
200{
201    // the user pressed Menu, but we've not been revealed yet
202   
203        id controller = [[self stack] peekController];
204        if([controller isKindOfClass:[BRVideoPlayerController class]])
205        {
206                BRVideoPlayer *player = [(BRVideoPlayerController *)controller player];
207                float elapsed = [player elapsedPlaybackTime];
208                float duration = [player trackDuration];
209                if(elapsed / duration > 0.9f)
210                {
211                        [currentPlayFile setWatched:YES];
212                        [[self list] reload];
213                        [[self scene] renderScene];
214                }
215                if(elapsed < duration - 2)
216                        [currentPlayFile setResumeTime:[player elapsedPlaybackTime]];
217                else
218                        [currentPlayFile setResumeTime:0];
219                [currentPlayFile writeMetaData];
220        }
221        [currentPlayFile release];
222        currentPlayFile = nil;
223        [self reloadDirectoryContents];
224    // always call super
225    [super willBeExhumed];
226}
227
228- (void) wasExhumedByPoppingController: (BRLayerController *) controller
229{
230    // handle being revealed when the user presses Menu
231   
232    // always call super
233    [super wasExhumedByPoppingController: controller];
234        if([_names count] == 0)
235                [[self stack] popController];
236        [metaData resumeImport];
237}
238
239- (long) itemCount
240{
241    // return the number of items in your menu list here
242        if([_names count])
243                return ( [ _names count]);
244        // Put up an empty item
245        return 1;
246}
247
248- (id<BRMenuItemLayer>) itemForRow: (long) row
249{
250/*
251    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
252    // return that object, it will be used to display the list item.
253    return ( nil );
254*/
255        if( [_names count] == 0)
256        {
257                BRAdornedMenuItemLayer *result = [BRAdornedMenuItemLayer adornedMenuItemWithScene:[self scene]];
258                [[result textItem] setTitle:@"< EMPTY >"];
259                return result;
260        }
261        if( row >= [_names count] ) return ( nil ) ;
262       
263        BRAdornedMenuItemLayer * result = nil ;
264        NSString *name = [_names objectAtIndex:row];
265        BOOL watched = NO;
266        if([[metaData directories] containsObject:name])
267        {
268                result = [BRAdornedMenuItemLayer adornedFolderMenuItemWithScene: [self scene]] ;
269                SapphireDirectoryMetaData *meta = [metaData metaDataForDirectory:name];
270                watched = [meta watched];
271        }
272        else
273        {
274                result = [BRAdornedMenuItemLayer adornedMenuItemWithScene: [self scene]] ;
275                SapphireFileMetaData *meta = [metaData metaDataForFile:name];
276                if(meta != nil)
277                {
278                        [[result textItem] setRightJustifiedText:[meta sizeString]];
279                        watched = [meta watched];
280                }
281        }
282        if(!watched)
283                [result setLeftIcon:[[BRThemeInfo sharedTheme] unplayedPodcastImageForScene:[self scene]]];
284                       
285        // add text
286
287        [[result textItem] setTitle: name] ;
288                               
289        return ( result ) ;
290}
291
292- (NSString *) titleForRow: (long) row
293{
294
295        if ( row >= [ _names count] ) return ( nil );
296       
297        NSString *result = [ _names objectAtIndex: row] ;
298        return ( result ) ;
299}
300
301- (long) rowForTitle: (NSString *) title
302{
303    long result = -1;
304    long i, count = [self itemCount];
305    for ( i = 0; i < count; i++ )
306    {
307        if ( [title isEqualToString: [self titleForRow: i]] )
308        {
309            result = i;
310            break;
311        }
312    }
313   
314    return ( result );
315}
316
317- (void) itemSelected: (long) row
318{
319    // This is called when the user presses play/pause on a list item
320       
321        if([_names count] == 0)
322        {
323                [[self stack] popController];
324                return;
325        }
326       
327        NSString *name = [_names objectAtIndex:row];
328        NSString *dir = [metaData path];
329       
330        if([sort gimmieState] == 2)
331        {
332                id meta = nil;
333                if([[metaData directories] containsObject:name])
334                        meta = [metaData metaDataForDirectory:name];
335                else
336                        meta = [metaData metaDataForFile:name];
337                id controller = [[SapphireMarkMenu alloc] initWithScene:[self scene] metaData:meta];
338                [[self stack] pushController:controller];
339                [controller release];
340                return;
341        }
342       
343        if([[metaData directories] containsObject:name])
344        {
345                id controller = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:[metaData metaDataForDirectory:name] predicate:predicate];
346                [controller setListTitle:name];
347                [controller setListIcon:[self listIcon]];
348                [[self stack] pushController:controller];
349                [controller release];
350        }
351        else
352        {
353                BRVideoPlayerController *controller = [[BRVideoPlayerController alloc] initWithScene:[self scene]];
354               
355                currentPlayFile = [[metaData metaDataForFile:name] retain];
356                [controller setAllowsResume:YES];
357               
358                NSString *path = [dir stringByAppendingPathComponent:name];
359                NSURL *url = [NSURL fileURLWithPath:path];
360                SapphireMedia *asset  =[[SapphireMedia alloc] initWithMediaURL:url];
361                [asset setResumeTime:[currentPlayFile resumeTime]];
362
363                SapphireVideoPlayer *player = [[SapphireVideoPlayer alloc] init];
364                [player setMetaData:currentPlayFile];
365                NSError *error = nil;
366                [player setMedia:asset error:&error];
367               
368                [controller setVideoPlayer:player];
369                [[self stack] pushController:controller];
370
371                [asset release];
372                [player release];
373                [controller release];
374        }
375}
376
377- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
378{
379    // If subclassing BRMediaMenuController, this function is called when the selection cursor
380    // passes over an item.
381        NSString *name = [_names objectAtIndex:item];
382        if([[metaData files] containsObject:name])
383        {
384                SapphireFileMetaData *fileMeta = [metaData metaDataForFile:name];
385               
386                SapphireMediaPreview *preview = [[SapphireMediaPreview alloc] initWithScene:[self scene]];
387               
388                NSURL *url = [NSURL fileURLWithPath:@"/System/Library/PrivateFrameworks/BackRow.framework/Resources/Movies.png"];
389                CGImageSourceRef sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
390                CGImageRef imageRef = nil;
391                if(sourceRef)
392                {
393                        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
394                        CFRelease(sourceRef);
395                }
396                if(imageRef)
397                {
398                        [preview setImage:imageRef];
399                        CFRelease(imageRef);
400                }
401               
402                NSMutableDictionary *attrs = [[[BRThemeInfo sharedTheme] metadataSummaryFieldAttributes] mutableCopy];
403                NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
404                float tabLoc = [[self masterLayer] frame].size.width * 0.4f;
405                NSTextTab *myTab = [[NSTextTab alloc] initWithType:NSRightTabStopType location:tabLoc];
406                NSArray *tabs = [NSArray arrayWithObject:myTab];
407                [myTab release];
408                [style setTabStops:tabs];
409                [attrs removeObjectForKey:@"CTTextAlignment"];
410                [attrs setObject:style forKey:NSParagraphStyleAttributeName];
411                [preview setText:[[[NSAttributedString alloc] initWithString:[fileMeta metaDataDescription] attributes:attrs] autorelease]];
412                [attrs release];
413               
414                return [preview autorelease];
415        }
416    return ( nil );
417}
418
419- (void)updateComplete
420{
421        BRListControl *list = [self list];
422        [list reload];
423        [[self scene] renderScene];
424}
425
426@end
Note: See TracBrowser for help on using the repository browser.