mirror of
https://github.com/transmission/transmission
synced 2024-12-24 08:43:27 +00:00
This adds badging
This commit is contained in:
parent
16a8e74cdc
commit
80b7627b5c
6 changed files with 256 additions and 4 deletions
31
macosx/Badger.h
Normal file
31
macosx/Badger.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Badger.h
|
||||
// Transmission
|
||||
//
|
||||
// Created by Mitchell Livingston on 12/21/05.
|
||||
//
|
||||
|
||||
#ifndef BADGER_H
|
||||
#define BADGER_H
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface Badger : NSObject {
|
||||
|
||||
NSImage * fBadge, * fDockIcon, * fBadgedDockIcon;
|
||||
|
||||
NSDictionary * fBadgeAttributes, * fStringAttributes;
|
||||
|
||||
NSColor * fUploadingColor, * fDownloadingColor;
|
||||
|
||||
int fCompleted;
|
||||
}
|
||||
|
||||
- (void) updateBadgeWithCompleted: (int) completed
|
||||
uploadRate: (NSString *) uploadRate
|
||||
downloadRate: (NSString *) downloadRate;
|
||||
- (void) clearBadge;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
190
macosx/Badger.m
Normal file
190
macosx/Badger.m
Normal file
|
@ -0,0 +1,190 @@
|
|||
//
|
||||
// Badger.m
|
||||
// Transmission
|
||||
//
|
||||
// Created by Mitchell Livingston on 12/21/05.
|
||||
//
|
||||
|
||||
#import "Badger.h"
|
||||
|
||||
@interface Badger (Private)
|
||||
|
||||
- (NSImage *) badgeWithNum: (int) num;
|
||||
|
||||
@end
|
||||
|
||||
@implementation Badger
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fBadge = [NSImage imageNamed: @"Badge"];
|
||||
fDockIcon = [[NSApp applicationIconImage] copy];
|
||||
fBadgedDockIcon = [fDockIcon copy];
|
||||
|
||||
fBadgeAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSColor whiteColor], NSForegroundColorAttributeName,
|
||||
[NSFont fontWithName: @"Helvetica-Bold" size: 24], NSFontAttributeName,
|
||||
nil] retain];
|
||||
|
||||
fStringAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSColor whiteColor], NSForegroundColorAttributeName,
|
||||
[NSFont fontWithName: @"Helvetica-Bold" size: 20], NSFontAttributeName,
|
||||
nil] retain];
|
||||
|
||||
fUploadingColor = [[[NSColor greenColor] colorWithAlphaComponent: 0.65] retain];
|
||||
fDownloadingColor = [[[NSColor blueColor] colorWithAlphaComponent: 0.65] retain];
|
||||
|
||||
fCompleted = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[fDockIcon release];
|
||||
[fBadgedDockIcon release];
|
||||
|
||||
[fBadgeAttributes release];
|
||||
[fStringAttributes release];
|
||||
|
||||
[fUploadingColor release];
|
||||
[fDownloadingColor release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) updateBadgeWithCompleted: (int) completed
|
||||
uploadRate: (NSString *) uploadRate
|
||||
downloadRate: (NSString *) downloadRate
|
||||
{
|
||||
NSImage * dockIcon;
|
||||
NSSize iconSize = [fDockIcon size];
|
||||
|
||||
//set seeding and downloading badges if there was a change
|
||||
if (completed != fCompleted)
|
||||
{
|
||||
fCompleted = completed;
|
||||
|
||||
dockIcon = [fDockIcon copy];
|
||||
[dockIcon lockFocus];
|
||||
|
||||
//set completed badge to top right
|
||||
if (completed > 0)
|
||||
{
|
||||
NSSize badgeSize = [fBadge size];
|
||||
[[self badgeWithNum: completed]
|
||||
compositeToPoint: NSMakePoint(iconSize.width - badgeSize.width,
|
||||
iconSize.height - badgeSize.height)
|
||||
operation: NSCompositeSourceOver];
|
||||
}
|
||||
|
||||
[dockIcon unlockFocus];
|
||||
|
||||
[fBadgedDockIcon release];
|
||||
fBadgedDockIcon = [dockIcon copy];
|
||||
}
|
||||
else
|
||||
dockIcon = [fBadgedDockIcon copy];
|
||||
|
||||
if (uploadRate || downloadRate)
|
||||
{
|
||||
//upload rate at bottom
|
||||
float mainY = 5,
|
||||
mainHeight = 25;
|
||||
NSRect shapeRect = NSMakeRect(12.5, mainY, iconSize.width - 25, mainHeight);
|
||||
|
||||
NSRect leftRect, rightRect;
|
||||
leftRect.origin.x = 0;
|
||||
leftRect.origin.y = mainY;
|
||||
leftRect.size.width = shapeRect.origin.x * 2.0;
|
||||
leftRect.size.height = mainHeight;
|
||||
|
||||
rightRect = leftRect;
|
||||
rightRect.origin.x = iconSize.width - rightRect.size.width;
|
||||
|
||||
NSRect textRect;
|
||||
textRect.origin.y = mainY;
|
||||
textRect.size.height = mainHeight;
|
||||
|
||||
[dockIcon lockFocus];
|
||||
|
||||
if (uploadRate)
|
||||
{
|
||||
float width = [uploadRate sizeWithAttributes: fStringAttributes].width;
|
||||
textRect.origin.x = (iconSize.width - width) * 0.5;
|
||||
textRect.size.width = width;
|
||||
|
||||
NSBezierPath * uploadOval = [NSBezierPath bezierPathWithRect: shapeRect];
|
||||
[uploadOval appendBezierPathWithOvalInRect: leftRect];
|
||||
[uploadOval appendBezierPathWithOvalInRect: rightRect];
|
||||
|
||||
[fUploadingColor set];
|
||||
[uploadOval fill];
|
||||
[uploadRate drawInRect: textRect withAttributes: fStringAttributes];
|
||||
|
||||
//shift up for download rate if there is an upload rate
|
||||
float heightDiff = 27;
|
||||
shapeRect.origin.y += heightDiff;
|
||||
leftRect.origin.y += heightDiff;
|
||||
rightRect.origin.y += heightDiff;
|
||||
textRect.origin.y += heightDiff;
|
||||
}
|
||||
|
||||
//download rate above upload rate
|
||||
if (downloadRate)
|
||||
{
|
||||
float width = [downloadRate sizeWithAttributes: fStringAttributes].width;
|
||||
textRect.origin.x = (iconSize.width - width) * 0.5;
|
||||
textRect.size.width = width;
|
||||
|
||||
NSBezierPath * downloadOval = [NSBezierPath bezierPathWithRect: shapeRect];
|
||||
[downloadOval appendBezierPathWithOvalInRect: leftRect];
|
||||
[downloadOval appendBezierPathWithOvalInRect: rightRect];
|
||||
|
||||
[fDownloadingColor set];
|
||||
[downloadOval fill];
|
||||
[downloadRate drawInRect: textRect withAttributes: fStringAttributes];
|
||||
}
|
||||
|
||||
[dockIcon unlockFocus];
|
||||
}
|
||||
|
||||
[NSApp setApplicationIconImage: dockIcon];
|
||||
[dockIcon release];
|
||||
}
|
||||
|
||||
- (void) clearBadge
|
||||
{
|
||||
[fBadgedDockIcon release];
|
||||
fBadgedDockIcon = [fDockIcon copy];
|
||||
|
||||
[NSApp setApplicationIconImage: fDockIcon];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation Badger (Private)
|
||||
|
||||
- (NSImage *) badgeWithNum: (int) num
|
||||
{
|
||||
NSImage * badge = [[fBadge copy] autorelease];
|
||||
NSString * numString = [NSString stringWithFormat: @"%d", num];
|
||||
|
||||
//number is in center of image
|
||||
NSRect badgeRect;
|
||||
NSSize numSize = [numString sizeWithAttributes: fBadgeAttributes];
|
||||
badgeRect.size = [badge size];
|
||||
badgeRect.origin.x = (badgeRect.size.width - numSize.width) * 0.5;
|
||||
badgeRect.origin.y = badgeRect.size.height * 0.5 - numSize.height * 1.2;
|
||||
|
||||
[badge lockFocus];
|
||||
[numString drawInRect: badgeRect withAttributes: fBadgeAttributes];
|
||||
[badge unlockFocus];
|
||||
|
||||
return badge;
|
||||
}
|
||||
|
||||
@end
|
|
@ -26,13 +26,14 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <transmission.h>
|
||||
#import "PrefsController.h"
|
||||
#import "Badger.h"
|
||||
|
||||
@class TorrentTableView;
|
||||
|
||||
@interface Controller : NSObject
|
||||
{
|
||||
tr_handle_t * fHandle;
|
||||
int fCount;
|
||||
int fCount, fCompleted;
|
||||
tr_stat_t * fStat;
|
||||
int fResumeOnWake[TR_MAX_TORRENT_COUNT];
|
||||
|
||||
|
@ -74,6 +75,7 @@
|
|||
NSUserDefaults * fDefaults;
|
||||
|
||||
BOOL fHasGrowl;
|
||||
Badger * fBadger;
|
||||
}
|
||||
|
||||
- (void) advancedChanged: (id) sender;
|
||||
|
|
|
@ -133,6 +133,10 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
|| [manager fileExistsAtPath: [[NSString stringWithFormat: @"~%@",
|
||||
GROWL_PATH] stringByExpandingTildeInPath]];
|
||||
[self growlRegister: self];
|
||||
|
||||
//initialize badging
|
||||
fBadger = [[Badger alloc] init];
|
||||
fCompleted = 0;
|
||||
|
||||
//update the interface every 500 ms
|
||||
fCount = 0;
|
||||
|
@ -143,6 +147,12 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
forMode: NSEventTrackingRunLoopMode];
|
||||
}
|
||||
|
||||
- (void) windowDidBecomeKey: (NSNotification *) n
|
||||
{
|
||||
/* Reset the number of recently completed downloads */
|
||||
fCompleted = 0;
|
||||
}
|
||||
|
||||
- (void) windowDidResize: (NSNotification *) n
|
||||
{
|
||||
[fTableView sizeToFit];
|
||||
|
@ -557,8 +567,10 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
|
||||
//Update the global DL/UL rates
|
||||
tr_torrentRates( fHandle, &dl, &ul );
|
||||
[fTotalDLField setStringValue: [NSString stringForSpeed: dl]];
|
||||
[fTotalULField setStringValue: [NSString stringForSpeed: ul]];
|
||||
NSString * downloadRate = [NSString stringForSpeed: dl];
|
||||
NSString * uploadRate = [NSString stringForSpeed: ul];
|
||||
[fTotalDLField setStringValue: downloadRate];
|
||||
[fTotalULField setStringValue: uploadRate];
|
||||
|
||||
//Update DL/UL totals in the Info panel
|
||||
row = [fTableView selectedRow];
|
||||
|
@ -575,11 +587,18 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
{
|
||||
if( !tr_getFinished( fHandle, i ) )
|
||||
continue;
|
||||
|
||||
|
||||
fCompleted++;
|
||||
[self notifyGrowl: [NSString stringWithUTF8String:
|
||||
fStat[i].info.name]];
|
||||
tr_setFinished( fHandle, i, 0 );
|
||||
}
|
||||
|
||||
//badge dock
|
||||
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
|
||||
[fBadger updateBadgeWithCompleted: [defaults boolForKey: @"BadgeCompleted"] ? fCompleted : 0
|
||||
uploadRate: ul >= 0.1 && [defaults boolForKey: @"BadgeUploadRate"] ? uploadRate : nil
|
||||
downloadRate: dl >= 0.1 && [defaults boolForKey: @"BadgeDownloadRate"] ? downloadRate : nil];
|
||||
}
|
||||
|
||||
- (int) numberOfRowsInTableView: (NSTableView *) t
|
||||
|
|
BIN
macosx/Images/Badge.png
Normal file
BIN
macosx/Images/Badge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -24,6 +24,8 @@
|
|||
4DA6FDC5091141AD00450CB1 /* ResumeOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDC3091141AD00450CB1 /* ResumeOff.png */; };
|
||||
4DA6FDC6091141AD00450CB1 /* ResumeOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDC4091141AD00450CB1 /* ResumeOn.png */; };
|
||||
4DE5CC9D0980656F00BE280E /* StringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* StringAdditions.m */; };
|
||||
4DE5CCA70980735700BE280E /* Badger.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CCA60980735700BE280E /* Badger.m */; };
|
||||
4DE5CCA90980739100BE280E /* Badge.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DE5CCA80980739100BE280E /* Badge.png */; };
|
||||
4DF0C5AB0899190500DD8943 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DF0C5A90899190500DD8943 /* Controller.m */; };
|
||||
4DF0C5AE08991C1600DD8943 /* libtransmission.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DF0C5AD08991C1600DD8943 /* libtransmission.a */; };
|
||||
4DF7500C08A103AD007B0D70 /* Open.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DF7500708A103AD007B0D70 /* Open.png */; };
|
||||
|
@ -93,6 +95,9 @@
|
|||
4DA6FDC4091141AD00450CB1 /* ResumeOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeOn.png; path = Images/ResumeOn.png; sourceTree = "<group>"; };
|
||||
4DE5CC9B0980656F00BE280E /* StringAdditions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StringAdditions.h; sourceTree = "<group>"; };
|
||||
4DE5CC9C0980656F00BE280E /* StringAdditions.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = StringAdditions.m; sourceTree = "<group>"; };
|
||||
4DE5CCA50980735700BE280E /* Badger.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Badger.h; sourceTree = "<group>"; };
|
||||
4DE5CCA60980735700BE280E /* Badger.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Badger.m; sourceTree = "<group>"; };
|
||||
4DE5CCA80980739100BE280E /* Badge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Badge.png; path = Images/Badge.png; sourceTree = "<group>"; };
|
||||
4DF0C5A90899190500DD8943 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
|
||||
4DF0C5AA0899190500DD8943 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
|
||||
4DF0C5AD08991C1600DD8943 /* libtransmission.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtransmission.a; path = ../libtransmission/libtransmission.a; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -132,6 +137,8 @@
|
|||
4D364D9F091FBB2C00377D12 /* TorrentTableView.m */,
|
||||
4DE5CC9B0980656F00BE280E /* StringAdditions.h */,
|
||||
4DE5CC9C0980656F00BE280E /* StringAdditions.m */,
|
||||
4DE5CCA50980735700BE280E /* Badger.h */,
|
||||
4DE5CCA60980735700BE280E /* Badger.m */,
|
||||
);
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
|
@ -202,6 +209,7 @@
|
|||
4DA6FDC4091141AD00450CB1 /* ResumeOn.png */,
|
||||
4D752E920913C949008EAAD4 /* Preferences.png */,
|
||||
4D8CEF90095870E00063BAEA /* Network.png */,
|
||||
4DE5CCA80980739100BE280E /* Badge.png */,
|
||||
8D1107310486CEB800E47090 /* Info.plist */,
|
||||
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
|
||||
29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
|
||||
|
@ -292,6 +300,7 @@
|
|||
4DA6FDC6091141AD00450CB1 /* ResumeOn.png in Resources */,
|
||||
4D752E930913C949008EAAD4 /* Preferences.png in Resources */,
|
||||
4D8CEF91095870E00063BAEA /* Network.png in Resources */,
|
||||
4DE5CCA90980739100BE280E /* Badge.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -309,6 +318,7 @@
|
|||
4D118E1A08CB46B20033958F /* PrefsController.m in Sources */,
|
||||
4D364DA0091FBB2C00377D12 /* TorrentTableView.m in Sources */,
|
||||
4DE5CC9D0980656F00BE280E /* StringAdditions.m in Sources */,
|
||||
4DE5CCA70980735700BE280E /* Badger.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue