source: trunk/macosx/InfoWindowController.m @ 13114

Last change on this file since 13114 was 13114, checked in by livings124, 10 years ago

#4683 Info window swapped view heights not constrained to screen size

  • Property svn:keywords set to Date Rev Author Id
File size: 18.5 KB
Line 
1/******************************************************************************
2 * $Id: InfoWindowController.m 13114 2011-12-25 22:05:18Z livings124 $
3 *
4 * Copyright (c) 2006-2011 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "InfoWindowController.h"
26#import "InfoViewController.h"
27#import "InfoGeneralViewController.h"
28#import "InfoActivityViewController.h"
29#import "InfoTrackersViewController.h"
30#import "InfoPeersViewController.h"
31#import "InfoFileViewController.h"
32#import "InfoOptionsViewController.h"
33#import "InfoTabButtonCell.h"
34#import "NSStringAdditions.h"
35#import "Torrent.h"
36
37#define TAB_INFO_IDENT @"Info"
38#define TAB_ACTIVITY_IDENT @"Activity"
39#define TAB_TRACKER_IDENT @"Tracker"
40#define TAB_PEERS_IDENT @"Peers"
41#define TAB_FILES_IDENT @"Files"
42#define TAB_OPTIONS_IDENT @"Options"
43
44#define TAB_MIN_HEIGHT 250
45
46#define INVALID -99
47
48typedef enum
49{
50    TAB_GENERAL_TAG = 0,
51    TAB_ACTIVITY_TAG = 1,
52    TAB_TRACKERS_TAG = 2,
53    TAB_PEERS_TAG = 3,
54    TAB_FILE_TAG = 4,
55    TAB_OPTIONS_TAG = 5
56} tabTag;
57
58@interface InfoWindowController (Private)
59
60- (void) resetInfo;
61- (void) resetInfoForTorrent: (NSNotification *) notification;
62
63@end
64
65@implementation InfoWindowController
66
67- (id) init
68{
69    self = [super initWithWindowNibName: @"InfoWindow"];
70    return self;
71}
72
73- (void) awakeFromNib
74{
75    [fNoneSelectedField setStringValue: NSLocalizedString(@"No Torrents Selected", "Inspector -> selected torrents")];
76   
77    //window location and size
78    NSPanel * window = (NSPanel *)[self window];
79   
80    [window setFloatingPanel: NO];
81   
82    const CGFloat windowHeight = NSHeight([window frame]);
83   
84    [window setFrameAutosaveName: @"InspectorWindow"];
85    [window setFrameUsingName: @"InspectorWindow"];
86   
87    NSRect windowRect = [window frame];
88    windowRect.origin.y -= windowHeight - NSHeight(windowRect);
89    windowRect.size.height = windowHeight;
90    [window setFrame: windowRect display: NO];
91   
92    [window setBecomesKeyOnlyIfNeeded: YES];
93   
94    //set tab tooltips
95    [fTabMatrix setToolTip: NSLocalizedString(@"General Info", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_GENERAL_TAG]];
96    [fTabMatrix setToolTip: NSLocalizedString(@"Activity", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_ACTIVITY_TAG]];
97    [fTabMatrix setToolTip: NSLocalizedString(@"Trackers", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_TRACKERS_TAG]];
98    [fTabMatrix setToolTip: NSLocalizedString(@"Peers", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_PEERS_TAG]];
99    [fTabMatrix setToolTip: NSLocalizedString(@"Files", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_FILE_TAG]];
100    [fTabMatrix setToolTip: NSLocalizedString(@"Options", "Inspector -> tab") forCell: [fTabMatrix cellWithTag: TAB_OPTIONS_TAG]];
101   
102    //set selected tab
103    fCurrentTabTag = INVALID;
104    NSString * identifier = [[NSUserDefaults standardUserDefaults] stringForKey: @"InspectorSelected"];
105    NSInteger tag;
106    if ([identifier isEqualToString: TAB_INFO_IDENT])
107        tag = TAB_GENERAL_TAG;
108    else if ([identifier isEqualToString: TAB_ACTIVITY_IDENT])
109        tag = TAB_ACTIVITY_TAG;
110    else if ([identifier isEqualToString: TAB_TRACKER_IDENT])
111        tag = TAB_TRACKERS_TAG;
112    else if ([identifier isEqualToString: TAB_PEERS_IDENT])
113        tag = TAB_PEERS_TAG;
114    else if ([identifier isEqualToString: TAB_FILES_IDENT])
115        tag = TAB_FILE_TAG;
116    else if ([identifier isEqualToString: TAB_OPTIONS_IDENT])
117        tag = TAB_OPTIONS_TAG;
118    else //safety
119    {
120        [[NSUserDefaults standardUserDefaults] setObject: TAB_INFO_IDENT forKey: @"InspectorSelected"];
121        tag = TAB_GENERAL_TAG;
122    }
123    [fTabMatrix selectCellWithTag: tag];
124    [self setTab: nil];
125   
126    //set blank inspector
127    [self setInfoForTorrents: [NSArray array]];
128   
129    //allow for update notifications
130    NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
131    [nc addObserver: self selector: @selector(resetInfoForTorrent:) name: @"ResetInspector" object: nil];
132    [nc addObserver: self selector: @selector(updateInfoStats) name: @"UpdateStats" object: nil];
133    [nc addObserver: self selector: @selector(updateOptions) name: @"UpdateOptions" object: nil];
134}
135
136- (void) dealloc
137{
138    [[NSNotificationCenter defaultCenter] removeObserver: self];
139   
140    if ([fViewController respondsToSelector: @selector(saveViewSize)])
141        [fViewController saveViewSize];
142   
143    [fGeneralViewController dealloc];
144    [fActivityViewController dealloc];
145    [fTrackersViewController dealloc];
146    [fPeersViewController dealloc];
147    [fFileViewController dealloc];
148    [fOptionsViewController dealloc];
149   
150    [fTorrents release];
151   
152    [super dealloc];
153}
154
155- (void) setInfoForTorrents: (NSArray *) torrents
156{
157    if (fTorrents && [fTorrents isEqualToArray: torrents])
158        return;
159   
160    [fTorrents release];
161    fTorrents = [torrents retain];
162   
163    [self resetInfo];
164}
165
166- (NSRect) windowWillUseStandardFrame: (NSWindow *) window defaultFrame: (NSRect) defaultFrame
167{
168    NSRect windowRect = [window frame];
169    windowRect.size.width = [window minSize].width;
170    return windowRect;
171}
172
173- (NSSize) windowWillResize: (NSWindow *) window toSize: (NSSize) proposedFrameSize
174{
175    //this is an edge-case - just stop the animation
176    [fPeersViewController stopWebSeedAnimation];
177   
178    return proposedFrameSize;
179}
180
181- (void) windowWillClose: (NSNotification *) notification
182{
183    if (fCurrentTabTag == TAB_FILE_TAG && ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]))
184        [[QLPreviewPanel sharedPreviewPanel] reloadData];
185}
186
187- (void) setTab: (id) sender
188{
189    const NSInteger oldTabTag = fCurrentTabTag;
190    fCurrentTabTag = [fTabMatrix selectedTag];
191    if (fCurrentTabTag == oldTabTag)
192        return;
193   
194    //take care of old view
195    CGFloat oldHeight = 0;
196    if (oldTabTag != INVALID)
197    {
198        //deselect old tab item
199        [(InfoTabButtonCell *)[fTabMatrix cellWithTag: oldTabTag] setSelectedTab: NO];
200       
201        if ([fViewController respondsToSelector: @selector(saveViewSize)])
202            [fViewController saveViewSize];
203       
204        if ([fViewController respondsToSelector: @selector(clearView)])
205            [fViewController clearView];
206       
207        NSView * oldView = [fViewController view];
208        oldHeight = NSHeight([oldView frame]);
209       
210        //remove old view
211        [oldView removeFromSuperview];
212    }
213   
214    //set new tab item
215    NSString * identifier;
216    switch (fCurrentTabTag)
217    {
218        case TAB_GENERAL_TAG:
219            if (!fGeneralViewController)
220            {
221                fGeneralViewController = [[InfoGeneralViewController alloc] init];
222                [fGeneralViewController setInfoForTorrents: fTorrents];
223            }
224           
225            fViewController = fGeneralViewController;
226            identifier = TAB_INFO_IDENT;
227            break;
228        case TAB_ACTIVITY_TAG:
229            if (!fActivityViewController)
230            {
231                fActivityViewController = [[InfoActivityViewController alloc] init];
232                [fActivityViewController setInfoForTorrents: fTorrents];
233            }
234           
235            fViewController = fActivityViewController;
236            identifier = TAB_ACTIVITY_IDENT;
237            break;
238        case TAB_TRACKERS_TAG:
239            if (!fTrackersViewController)
240            {
241                fTrackersViewController = [[InfoTrackersViewController alloc] init];
242                [fTrackersViewController setInfoForTorrents: fTorrents];
243            }
244           
245            fViewController = fTrackersViewController;
246            identifier = TAB_TRACKER_IDENT;
247            break;
248        case TAB_PEERS_TAG:
249            if (!fPeersViewController)
250            {
251                fPeersViewController = [[InfoPeersViewController alloc] init];
252                [fPeersViewController setInfoForTorrents: fTorrents];
253            }
254           
255            fViewController = fPeersViewController;
256            identifier = TAB_PEERS_IDENT;
257            break;
258        case TAB_FILE_TAG:
259            if (!fFileViewController)
260            {
261                fFileViewController = [[InfoFileViewController alloc] init];
262                [fFileViewController setInfoForTorrents: fTorrents];
263            }
264           
265            fViewController = fFileViewController;
266            identifier = TAB_FILES_IDENT;
267            break;
268        case TAB_OPTIONS_TAG:
269            if (!fOptionsViewController)
270            {
271                fOptionsViewController = [[InfoOptionsViewController alloc] init];
272                [fOptionsViewController setInfoForTorrents: fTorrents];
273            }
274           
275            fViewController = fOptionsViewController;
276            identifier = TAB_OPTIONS_IDENT;
277            break;
278        default:
279            NSAssert1(NO, @"Unknown info tab selected: %d", fCurrentTabTag);
280            return;
281    }
282   
283    [[NSUserDefaults standardUserDefaults] setObject: identifier forKey: @"InspectorSelected"];
284   
285    NSWindow * window = [self window];
286   
287    [window setTitle: [NSString stringWithFormat: @"%@ - %@", [fViewController title],
288                        NSLocalizedString(@"Torrent Inspector", "Inspector -> title")]];
289   
290    //selected tab item
291    [(InfoTabButtonCell *)[fTabMatrix selectedCell] setSelectedTab: YES];
292   
293    NSView * view = [fViewController view];
294   
295    [fViewController updateInfo];
296   
297    NSRect windowRect = [window frame], viewRect = [view frame];
298   
299    const CGFloat difference = (NSHeight(viewRect) - oldHeight) * [window userSpaceScaleFactor];
300    windowRect.origin.y -= difference;
301    windowRect.size.height += difference;
302   
303    if ([fViewController respondsToSelector: @selector(saveViewSize)]) //a little bit hacky, but avoids requiring an extra method
304    {
305        const CGFloat screenHeight = NSHeight([[window screen] visibleFrame]);
306        if (NSHeight(windowRect) > screenHeight)
307        {
308            const CGFloat difference = (screenHeight - NSHeight(windowRect)) * [window userSpaceScaleFactor];
309            windowRect.origin.y -= difference;
310            windowRect.size.height += difference;
311           
312            viewRect.size.height += difference;
313        }
314       
315        [window setMinSize: NSMakeSize([window minSize].width, NSHeight(windowRect) - NSHeight(viewRect) + TAB_MIN_HEIGHT)];
316        [window setMaxSize: NSMakeSize(FLT_MAX, FLT_MAX)];
317    }
318    else
319    {
320        [window setMinSize: NSMakeSize([window minSize].width, NSHeight(windowRect))];
321        [window setMaxSize: NSMakeSize(FLT_MAX, NSHeight(windowRect))];
322    }
323   
324    viewRect.size.width = NSWidth(windowRect);
325    [view setFrame: viewRect];
326   
327    [window setFrame: windowRect display: YES animate: oldTabTag != INVALID];
328    [[window contentView] addSubview: view];
329   
330    if ((fCurrentTabTag == TAB_FILE_TAG || oldTabTag == TAB_FILE_TAG)
331        && ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]))
332        [[QLPreviewPanel sharedPreviewPanel] reloadData];
333}
334
335- (void) setNextTab
336{
337    NSInteger tag = [fTabMatrix selectedTag]+1;
338    if (tag >= [fTabMatrix numberOfColumns])
339        tag = 0;
340   
341    [fTabMatrix selectCellWithTag: tag];
342    [self setTab: nil];
343}
344
345- (void) setPreviousTab
346{
347    NSInteger tag = [fTabMatrix selectedTag]-1;
348    if (tag < 0)
349        tag = [fTabMatrix numberOfColumns]-1;
350   
351    [fTabMatrix selectCellWithTag: tag];
352    [self setTab: nil];
353}
354
355- (void) swipeWithEvent: (NSEvent *) event
356{
357    if ([event deltaX] < 0.0)
358        [self setNextTab];
359    else if ([event deltaX] > 0.0)
360        [self setPreviousTab];
361}
362
363- (void) updateInfoStats
364{
365    [fViewController updateInfo];
366}
367
368- (void) updateOptions
369{
370    [fOptionsViewController updateOptions];
371}
372
373- (NSArray *) quickLookURLs
374{
375    return [fFileViewController quickLookURLs];
376}
377
378- (BOOL) canQuickLook
379{
380    if (fCurrentTabTag != TAB_FILE_TAG || ![[self window] isVisible])
381        return NO;
382   
383    return [fFileViewController canQuickLook];
384}
385
386- (NSRect) quickLookSourceFrameForPreviewItem: (id <QLPreviewItem>) item
387{
388    return [fFileViewController quickLookSourceFrameForPreviewItem: item];
389}
390
391@end
392
393@implementation InfoWindowController (Private)
394
395- (void) resetInfo
396{
397    const NSUInteger numberSelected = [fTorrents count];
398    if (numberSelected != 1)
399    {
400        if (numberSelected > 0)
401        {
402            [fImageView setImage: [NSImage imageNamed: NSImageNameMultipleDocuments]];
403           
404            [fNameField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%@ Torrents Selected",
405                                            "Inspector -> selected torrents"),
406                                            [NSString formattedUInteger: numberSelected]]];
407            [fNameField setHidden: NO];
408       
409            uint64_t size = 0;
410            NSUInteger fileCount = 0, magnetCount = 0;
411            for (Torrent * torrent in fTorrents)
412            {
413                size += [torrent size];
414                fileCount += [torrent fileCount];
415                if ([torrent isMagnet])
416                    ++magnetCount;
417            }
418           
419            NSMutableArray * fileStrings = [NSMutableArray arrayWithCapacity: 2];
420            if (fileCount > 0)
421            {
422                NSString * fileString;
423                if (fileCount == 1)
424                    fileString = NSLocalizedString(@"1 file", "Inspector -> selected torrents");
425                else
426                    fileString = [NSString stringWithFormat: NSLocalizedString(@"%@ files", "Inspector -> selected torrents"),
427                                    [NSString formattedUInteger: fileCount]];
428                [fileStrings addObject: fileString];
429            }
430            if (magnetCount > 0)
431            {
432                NSString * magnetString;
433                if (magnetCount == 1)
434                    magnetString = NSLocalizedString(@"1 magnetized transfer", "Inspector -> selected torrents");
435                else
436                    magnetString = [NSString stringWithFormat: NSLocalizedString(@"%@ magnetized transfers",
437                                    "Inspector -> selected torrents"), [NSString formattedUInteger: magnetCount]];
438                [fileStrings addObject: magnetString];
439            }
440           
441            NSString * fileString = [fileStrings componentsJoinedByString: @" + "];
442           
443            if (magnetCount < numberSelected)
444            {
445                [fBasicInfoField setStringValue: [NSString stringWithFormat: @"%@, %@", fileString,
446                    [NSString stringWithFormat: NSLocalizedString(@"%@ total", "Inspector -> selected torrents"),
447                        [NSString stringForFileSize: size]]]];
448                [fBasicInfoField setToolTip: [NSString stringWithFormat: NSLocalizedString(@"%@ bytes",
449                                                "Inspector -> selected torrents"), [NSString formattedUInteger: size]]];
450            }
451            else
452            {
453                [fBasicInfoField setStringValue: fileString];
454                [fBasicInfoField setToolTip: nil];
455            }
456            [fBasicInfoField setHidden: NO];
457           
458            [fNoneSelectedField setHidden: YES];
459        }
460        else
461        {
462            [fImageView setImage: [NSImage imageNamed: NSImageNameApplicationIcon]];
463            [fNoneSelectedField setHidden: NO];
464           
465            [fNameField setHidden: YES];
466            [fBasicInfoField setHidden: YES];
467        }
468       
469        [fNameField setToolTip: nil];
470    }
471    else
472    {
473        Torrent * torrent = [fTorrents objectAtIndex: 0];
474       
475        [fImageView setImage: [torrent icon]];
476       
477        NSString * name = [torrent name];
478        [fNameField setStringValue: name];
479        [fNameField setToolTip: name];
480        [fNameField setHidden: NO];
481       
482        if (![torrent isMagnet])
483        {
484            NSString * basicString = [NSString stringForFileSize: [torrent size]];
485            if ([torrent isFolder])
486            {
487                NSString * fileString;
488                const NSUInteger fileCount = [torrent fileCount];
489                if (fileCount == 1)
490                    fileString = NSLocalizedString(@"1 file", "Inspector -> selected torrents");
491                else
492                    fileString= [NSString stringWithFormat: NSLocalizedString(@"%@ files", "Inspector -> selected torrents"),
493                                    [NSString formattedUInteger: fileCount]];
494                basicString = [NSString stringWithFormat: @"%@, %@", fileString, basicString];
495            }
496            [fBasicInfoField setStringValue: basicString];
497            [fBasicInfoField setToolTip: [NSString stringWithFormat: NSLocalizedString(@"%@ bytes", "Inspector -> selected torrents"),
498                                            [NSString formattedUInteger: [torrent size]]]];
499        }
500        else
501        {
502            [fBasicInfoField setStringValue: NSLocalizedString(@"Magnetized transfer", "Inspector -> selected torrents")];
503            [fBasicInfoField setToolTip: nil];
504        }
505        [fBasicInfoField setHidden: NO];
506       
507        [fNoneSelectedField setHidden: YES];
508    }
509   
510    [fGeneralViewController setInfoForTorrents: fTorrents];
511    [fActivityViewController setInfoForTorrents: fTorrents];
512    [fTrackersViewController setInfoForTorrents: fTorrents];
513    [fPeersViewController setInfoForTorrents: fTorrents];
514    [fFileViewController setInfoForTorrents: fTorrents];
515    [fOptionsViewController setInfoForTorrents: fTorrents];
516   
517    [fViewController updateInfo];
518}
519
520- (void) resetInfoForTorrent: (NSNotification *) notification
521{
522    if (fTorrents && [fTorrents containsObject: [notification object]])
523        [self resetInfo];
524}
525
526@end
Note: See TracBrowser for help on using the repository browser.