1/****************************************************************************** 2 * $Id: StatusBarController.m 13434 2012-08-13 00:52:04Z livings124 $ 3 * 4 * Copyright (c) 2011-2012 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 "StatusBarController.h" 26#import "NSStringAdditions.h" 27 28#import "transmission.h" 29 30#define STATUS_RATIO_TOTAL @"RatioTotal" 31#define STATUS_RATIO_SESSION @"RatioSession" 32#define STATUS_TRANSFER_TOTAL @"TransferTotal" 33#define STATUS_TRANSFER_SESSION @"TransferSession" 34 35typedef enum 36{ 37 STATUS_RATIO_TOTAL_TAG = 0, 38 STATUS_RATIO_SESSION_TAG = 1, 39 STATUS_TRANSFER_TOTAL_TAG = 2, 40 STATUS_TRANSFER_SESSION_TAG = 3 41} statusTag; 42 43@interface StatusBarController (Private) 44 45- (void) resizeStatusButton; 46 47@end 48 49@implementation StatusBarController 50 51- (id) initWithLib: (tr_session *) lib 52{ 53 if ((self = [super initWithNibName: @"StatusBar" bundle: nil])) 54 { 55 fLib = lib; 56 57 fPreviousDownloadRate = -1.0; 58 fPreviousUploadRate = -1.0; 59 } 60 61 return self; 62} 63 64- (void) awakeFromNib 65{ 66 //localize menu items 67 [[[fStatusButton menu] itemWithTag: STATUS_RATIO_TOTAL_TAG] setTitle: NSLocalizedString(@"Total Ratio", 68 "Status Bar -> status menu")]; 69 [[[fStatusButton menu] itemWithTag: STATUS_RATIO_SESSION_TAG] setTitle: NSLocalizedString(@"Session Ratio", 70 "Status Bar -> status menu")]; 71 [[[fStatusButton menu] itemWithTag: STATUS_TRANSFER_TOTAL_TAG] setTitle: NSLocalizedString(@"Total Transfer", 72 "Status Bar -> status menu")]; 73 [[[fStatusButton menu] itemWithTag: STATUS_TRANSFER_SESSION_TAG] setTitle: NSLocalizedString(@"Session Transfer", 74 "Status Bar -> status menu")]; 75 76 [[fStatusButton cell] setBackgroundStyle: NSBackgroundStyleRaised]; 77 [[fTotalDLField cell] setBackgroundStyle: NSBackgroundStyleRaised]; 78 [[fTotalULField cell] setBackgroundStyle: NSBackgroundStyleRaised]; 79 [[fTotalDLImageView cell] setBackgroundStyle: NSBackgroundStyleRaised]; 80 [[fTotalULImageView cell] setBackgroundStyle: NSBackgroundStyleRaised]; 81 82 [self updateSpeedFieldsToolTips]; 83 84 //update when speed limits are changed 85 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(updateSpeedFieldsToolTips) 86 name: @"SpeedLimitUpdate" object: nil]; 87 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(resizeStatusButton) 88 name: NSWindowDidResizeNotification object: [[self view] window]]; 89} 90 91- (void) dealloc 92{ 93 [[NSNotificationCenter defaultCenter] removeObserver: self]; 94 95 [super dealloc]; 96} 97 98- (void) updateWithDownload: (CGFloat) dlRate upload: (CGFloat) ulRate 99{ 100 //set rates 101 if (dlRate != fPreviousDownloadRate) 102 { 103 [fTotalDLField setStringValue: [NSString stringForSpeed: dlRate]]; 104 fPreviousDownloadRate = dlRate; 105 } 106 107 if (ulRate != fPreviousUploadRate) 108 { 109 [fTotalULField setStringValue: [NSString stringForSpeed: ulRate]]; 110 fPreviousUploadRate = ulRate; 111 } 112 113 //set status button text 114 NSString * statusLabel = [[NSUserDefaults standardUserDefaults] stringForKey: @"StatusLabel"], * statusString; 115 BOOL total; 116 if ((total = [statusLabel isEqualToString: STATUS_RATIO_TOTAL]) || [statusLabel isEqualToString: STATUS_RATIO_SESSION]) 117 { 118 tr_session_stats stats; 119 if (total) 120 tr_sessionGetCumulativeStats(fLib, &stats); 121 else 122 tr_sessionGetStats(fLib, &stats); 123 124 statusString = [NSLocalizedString(@"Ratio", "status bar -> status label") stringByAppendingFormat: @": %@", 125 [NSString stringForRatio: stats.ratio]]; 126 } 127 else //STATUS_TRANSFER_TOTAL or STATUS_TRANSFER_SESSION 128 { 129 total = [statusLabel isEqualToString: STATUS_TRANSFER_TOTAL]; 130 131 tr_session_stats stats; 132 if (total) 133 tr_sessionGetCumulativeStats(fLib, &stats); 134 else 135 tr_sessionGetStats(fLib, &stats); 136 137 statusString = [NSString stringWithFormat: @"%@: %@ %@: %@", 138 NSLocalizedString(@"DL", "status bar -> status label"), [NSString stringForFileSize: stats.downloadedBytes], 139 NSLocalizedString(@"UL", "status bar -> status label"), [NSString stringForFileSize: stats.uploadedBytes]]; 140 } 141 142 143 if (![[fStatusButton title] isEqualToString: statusString]) 144 { 145 [fStatusButton setTitle: statusString]; 146 [self resizeStatusButton]; 147 } 148} 149 150- (void) setStatusLabel: (id) sender 151{ 152 NSString * statusLabel; 153 switch ([sender tag]) 154 { 155 case STATUS_RATIO_TOTAL_TAG: 156 statusLabel = STATUS_RATIO_TOTAL; 157 break; 158 case STATUS_RATIO_SESSION_TAG: 159 statusLabel = STATUS_RATIO_SESSION; 160 break; 161 case STATUS_TRANSFER_TOTAL_TAG: 162 statusLabel = STATUS_TRANSFER_TOTAL; 163 break; 164 case STATUS_TRANSFER_SESSION_TAG: 165 statusLabel = STATUS_TRANSFER_SESSION; 166 break; 167 default: 168 NSAssert1(NO, @"Unknown status label tag received: %ld", [sender tag]); 169 return; 170 } 171 172 [[NSUserDefaults standardUserDefaults] setObject: statusLabel forKey: @"StatusLabel"]; 173 174 [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil]; 175} 176 177- (void) updateSpeedFieldsToolTips 178{ 179 NSString * uploadText, * downloadText; 180 181 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"SpeedLimit"]) 182 { 183 NSString * speedString = [NSString stringWithFormat: @"%@ (%@)", NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 184 NSLocalizedString(@"Speed Limit", "Status Bar -> speed tooltip")]; 185 186 uploadText = [NSString stringWithFormat: speedString, 187 [[NSUserDefaults standardUserDefaults] integerForKey: @"SpeedLimitUploadLimit"]]; 188 downloadText = [NSString stringWithFormat: speedString, 189 [[NSUserDefaults standardUserDefaults] integerForKey: @"SpeedLimitDownloadLimit"]]; 190 } 191 else 192 { 193 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"CheckUpload"]) 194 uploadText = [NSString stringWithFormat: NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 195 [[NSUserDefaults standardUserDefaults] integerForKey: @"UploadLimit"]]; 196 else 197 uploadText = NSLocalizedString(@"unlimited", "Status Bar -> speed tooltip"); 198 199 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"CheckDownload"]) 200 downloadText = [NSString stringWithFormat: NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 201 [[NSUserDefaults standardUserDefaults] integerForKey: @"DownloadLimit"]]; 202 else 203 downloadText = NSLocalizedString(@"unlimited", "Status Bar -> speed tooltip"); 204 } 205 206 uploadText = [NSLocalizedString(@"Global upload limit", "Status Bar -> speed tooltip") 207 stringByAppendingFormat: @": %@", uploadText]; 208 downloadText = [NSLocalizedString(@"Global download limit", "Status Bar -> speed tooltip") 209 stringByAppendingFormat: @": %@", downloadText]; 210 211 [fTotalULField setToolTip: uploadText]; 212 [fTotalDLField setToolTip: downloadText]; 213} 214 215- (BOOL) validateMenuItem: (NSMenuItem *) menuItem 216{ 217 const SEL action = [menuItem action]; 218 219 //enable sort options 220 if (action == @selector(setStatusLabel:)) 221 { 222 NSString * statusLabel; 223 switch ([menuItem tag]) 224 { 225 case STATUS_RATIO_TOTAL_TAG: 226 statusLabel = STATUS_RATIO_TOTAL; 227 break; 228 case STATUS_RATIO_SESSION_TAG: 229 statusLabel = STATUS_RATIO_SESSION; 230 break; 231 case STATUS_TRANSFER_TOTAL_TAG: 232 statusLabel = STATUS_TRANSFER_TOTAL; 233 break; 234 case STATUS_TRANSFER_SESSION_TAG: 235 statusLabel = STATUS_TRANSFER_SESSION; 236 break; 237 default: 238 NSAssert1(NO, @"Unknown status label tag received: %ld", [menuItem tag]); 239 } 240 241 [menuItem setState: [statusLabel isEqualToString: [[NSUserDefaults standardUserDefaults] stringForKey: @"StatusLabel"]] 242 ? NSOnState : NSOffState]; 243 return YES; 244 } 245 246 return YES; 247} 248 249@end 250 251@implementation StatusBarController (Private) 252 253- (void) resizeStatusButton 254{ 255 [fStatusButton sizeToFit]; 256 257 //width ends up being too long 258 NSRect statusFrame = [fStatusButton frame]; 259 statusFrame.size.width -= 25.0; 260 261 const CGFloat difference = NSMaxX(statusFrame) + 5.0 - NSMinX([fTotalDLImageView frame]); 262 if (difference > 0.0) 263 statusFrame.size.width -= difference; 264 265 [fStatusButton setFrame: statusFrame]; 266} 267 268@end 269