From 65316f1b72deaf0282addb1edbd0ff9a11c712d6 Mon Sep 17 00:00:00 2001 From: Eric Petit Date: Wed, 8 Feb 2006 17:44:07 +0000 Subject: [PATCH] Updated badging --- macosx/Badger.h | 18 +- macosx/Badger.m | 293 +++++++++--------- macosx/Controller.m | 4 +- macosx/Images/Badge.png | Bin 1227 -> 1681 bytes macosx/Images/DownloadBadge.png | Bin 0 -> 739 bytes macosx/Images/UploadBadge.png | Bin 0 -> 768 bytes macosx/StringAdditions.h | 1 + macosx/StringAdditions.m | 12 +- macosx/Transmission.xcodeproj/project.pbxproj | 8 + 9 files changed, 175 insertions(+), 161 deletions(-) create mode 100644 macosx/Images/DownloadBadge.png create mode 100644 macosx/Images/UploadBadge.png diff --git a/macosx/Badger.h b/macosx/Badger.h index d06d9b2f1..3b61cc83d 100644 --- a/macosx/Badger.h +++ b/macosx/Badger.h @@ -12,18 +12,18 @@ @interface Badger : NSObject { - NSImage * fBadge, * fDockIcon, * fBadgedDockIcon; - - NSDictionary * fBadgeAttributes, * fStringAttributes; - - NSColor * fUploadingColor, * fDownloadingColor; - - int fCompleted; + NSImage * fDockIcon, * fBadgedDockIcon, + * fBadge, * fUploadBadge, * fDownloadBadge; + + NSDictionary * fAttributes; + + int fCompleted; + BOOL fSpeedShown; } - (void) updateBadgeWithCompleted: (int) completed - uploadRate: (NSString *) uploadRate - downloadRate: (NSString *) downloadRate; + uploadRate: (NSString *) uploadRate + downloadRate: (NSString *) downloadRate; - (void) clearBadge; @end diff --git a/macosx/Badger.m b/macosx/Badger.m index 14926def3..88f01b5a8 100644 --- a/macosx/Badger.m +++ b/macosx/Badger.m @@ -9,7 +9,7 @@ @interface Badger (Private) -- (NSImage *) badgeWithNum: (int) num; +- (void) badgeString: (NSString *) string forRect: (NSRect) rect; @end @@ -17,174 +17,173 @@ - (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; + if ((self = [super init])) + { + fBadge = [NSImage imageNamed: @"Badge"]; + fDockIcon = [[NSApp applicationIconImage] copy]; + fBadgedDockIcon = [fDockIcon copy]; + fUploadBadge = [NSImage imageNamed: @"UploadBadge"]; + fDownloadBadge = [NSImage imageNamed: @"DownloadBadge"]; + + NSShadow * stringShadow = [[NSShadow alloc] init]; + [stringShadow setShadowOffset: NSMakeSize(2, -2)]; + [stringShadow setShadowBlurRadius: 4]; + + fAttributes = [[NSDictionary dictionaryWithObjectsAndKeys: + [NSColor whiteColor], NSForegroundColorAttributeName, + [NSFont fontWithName: @"Helvetica-Bold" size: 28], NSFontAttributeName, + stringShadow, NSShadowAttributeName, + nil] retain]; + [stringShadow release]; + + fCompleted = 0; + fSpeedShown = NO; + } + + return self; } - (void) dealloc { - [fDockIcon release]; - [fBadgedDockIcon release]; + [fDockIcon release]; + [fBadgedDockIcon release]; - [fBadgeAttributes release]; - [fStringAttributes release]; - - [fUploadingColor release]; - [fDownloadingColor release]; + [fAttributes release]; - [super dealloc]; + [super dealloc]; } - (void) updateBadgeWithCompleted: (int) completed - uploadRate: (NSString *) uploadRate - downloadRate: (NSString *) downloadRate + 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]; - } + NSImage * dockIcon = nil; + NSSize iconSize = [fDockIcon size]; - [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]; + //set seeding and downloading badges if there was a change + if (completed != fCompleted) + { + fCompleted = completed; + + dockIcon = [fDockIcon copy]; + + //set completed badge to top right + if (completed > 0) + { + NSRect badgeRect; + badgeRect.size = [fBadge size]; + badgeRect.origin.x = iconSize.width - badgeRect.size.width; + badgeRect.origin.y = iconSize.height - badgeRect.size.height; + + [dockIcon lockFocus]; + + //place badge + [fBadge compositeToPoint: badgeRect.origin + operation: NSCompositeSourceOver]; + + //ignore shadow of badge when placing string + float badgeBottomExtra = 5.0; + badgeRect.size.height -= badgeBottomExtra; + badgeRect.origin.y += badgeBottomExtra; + + //place badge text + [self badgeString: [NSString stringWithFormat: @"%d", completed] + forRect: badgeRect]; + + [dockIcon unlockFocus]; + } + + [fBadgedDockIcon release]; + fBadgedDockIcon = [dockIcon copy]; + } + + //display upload and download rates + BOOL speedShown = NO; + if (uploadRate || downloadRate) + { + speedShown = YES; + + NSRect badgeRect, stringRect; + badgeRect.size = [fUploadBadge size]; + badgeRect.origin = NSZeroPoint; + + //ignore shadow of badge when placing string + float badgeBottomExtra = 2.0; + stringRect = badgeRect; + stringRect.size.height -= badgeBottomExtra; + stringRect.origin.y += badgeBottomExtra; + + if (!dockIcon) + dockIcon = [fBadgedDockIcon copy]; + + [dockIcon lockFocus]; + + if (uploadRate) + { + //place badge + [fUploadBadge compositeToPoint: badgeRect.origin + operation: NSCompositeSourceOver]; + + //place badge text + [self badgeString: uploadRate forRect: stringRect]; + } + + if (downloadRate) + { + //download rate above upload rate + if (uploadRate) + { + float spaceBetween = badgeRect.size.height + 2.0; + badgeRect.origin.y += spaceBetween; + stringRect.origin.y += spaceBetween; + } + + //place badge + [fDownloadBadge compositeToPoint: badgeRect.origin + operation: NSCompositeSourceOver]; + + //place badge text + [self badgeString: downloadRate forRect: stringRect]; + } + + [dockIcon unlockFocus]; + } + + if (dockIcon || fSpeedShown) + { + if (!dockIcon) + dockIcon = [fBadgedDockIcon copy]; + + [NSApp setApplicationIconImage: dockIcon]; + + [dockIcon release]; + } + + fSpeedShown = speedShown; } - (void) clearBadge { - [fBadgedDockIcon release]; - fBadgedDockIcon = [fDockIcon copy]; + [fBadgedDockIcon release]; + fBadgedDockIcon = [fDockIcon copy]; - [NSApp setApplicationIconImage: fDockIcon]; + [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; +//dock icon must have locked focus +- (void) badgeString: (NSString *) string forRect: (NSRect) rect +{ + NSSize stringSize = [string sizeWithAttributes: fAttributes]; + + //string is in center of image + rect.origin.x += (rect.size.width - stringSize.width) * 0.5; + rect.origin.y += (rect.size.height - stringSize.height) * 0.5; + + [string drawAtPoint: rect.origin withAttributes: fAttributes]; } @end diff --git a/macosx/Controller.m b/macosx/Controller.m index 9e9dea256..d4eba8dae 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -612,8 +612,8 @@ static void sleepCallBack( void * controller, io_service_t y, //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]; + uploadRate: ul >= 0.1 && [defaults boolForKey: @"BadgeUploadRate"] ? [NSString stringForSpeedAbbrev: ul] : nil + downloadRate: dl >= 0.1 && [defaults boolForKey: @"BadgeDownloadRate"] ? [NSString stringForSpeedAbbrev: dl] : nil]; } - (int) numberOfRowsInTableView: (NSTableView *) t diff --git a/macosx/Images/Badge.png b/macosx/Images/Badge.png index 03ead6e84cde66141864614c16fa4b8107e65588..ad592d83a16fd16911b4baa959687d9487cf0c1b 100644 GIT binary patch delta 1664 zcmV-`27md>36TwuB!2{FK}|sb0M^*lPgpVl000?uMObuGZ)S9NVRB^vL1b@YWgtmy zVP|DhWnpA_ami&o000IfNkl6xm;Cgj9yNN4kM&*lKNTg zWQX-9((lRsM%5Ud*F*HYpLCuyZd5LDZo_|GJ}wZd#6xWSQ_>0fdSPQj$t^7@c{&=& zq>{gPuQ((I2Y(fprYW9KNNKosO>u`p)~3H9oh3{=b@LEC6OmtUAs#oOMcBB_aqGm|K#Xv;!u9X4x1D4Wf`O#hn@mX0Eksu8g& z+Lj~%+f~h>d_Mny+wK0!d;ydfkA{ZKT&blXw=UhiYk%gOnVW^eb&tpM^|=Y9)9EWM zEiJ!^ga;Xrs)v9KNQuI6cz8JA^ZC{)CX`GjgKceXAfwfrObJrSgM)(sP1Ck3A*AZM zzDD;hgTz4~PjfqJUd(S0#J?s1F)E#GhqWpJ5qKbr)DylTVAjCJ$+}#3^gYSLQnPk z(T#l9*x2~KHT0|=a>Zh?9*{9RQhp;&5`hUAfz|3ItB2fF8l%n4&67^_j@3&viui)M zlrSRF&O>13Cg$&&xf6{#cFrTPF;=(iCD}vj=6~kqE4{tFznBHTz5PNf+i7K7OC-$S zTU%SN_4W0wid>RCo~!D#_1w3GUmr&CljLb z?s?H1j5?s-IZXsc#_X{Y!m)vFz93xcbP*UCbA#X_ih`GZKSRIo<6@#pizc;}cAm=- z{(tA_@DS6sq8xgHSFdbyNPU6{sa8TyjaWwtkC&Ppzd~A!(PcY0rBU{t=!u;!0;9le zN64VT-k&D>lZ$`O^AKZX%!aLp_V)J7#SpA$I$Z=tf!Rt34E5#ZUTTg+976_Jgm)O@v40eD z|CMfO_W|U5q}`+gtE;Quisk=er>dpp+S9+2MW>Xs88DjF%U>)^%|>EYz$!qxfp^@_F~D^=KnO(DPnOpL9Au@=upZFcbB zwHDGY(tgr678e&k7mezPL|t+UHegE#FaQf<>SBy1r$07?T)gOTiIWavjKS&Y>B($1 zo2vJgBy7SqFff*G#^zD%b|6aZv5EqLr15h_85$cKo1j7wtJkJ6Y{4dMGk*p@V`@-J zY^VI+rm@PMEn+pu4dN{gudJ-xuJyJ)Y`_-V9AFF`jH&cY`;=X9nUtShjyQg2baeFk z*4EY?>&FF1VuZ}2krCtJ;NS@YxQ2W9A35QLpiQ(58*D4YwofNh1|gZ0#_`+FmF6wH zK^R|KTU$z{Qu~#D7lUWf27eP7=C-f0t!}n`IvJ(>Ph(VGDr(}M8J%w{SDGeHPS z?in8+f3>Hlr@ytewbSSGJ#W`oI-UL-Bx14H9}5c$zec0c822Z6?ps7ZgHAIo^*4I8 z2+3=AUWu4Y$}5QR3s9{K7*Yo=M)|wFudfQ>CTZQVk2xy5xzfd@K5|00RJ(A=%;|7#KMK0000< KMNUMnLSTZ&vnL<` delta 1207 zcmV;o1W5al4a*6TB!3BTNLh0L01FcU01FcV0GgZ_000DiNklLN zv`kVoiUtXiC~rgNj5&?k%i42}yE&eto@20ey?nFxUf=%KS%3e%F5mx~DwUURsq2nP zE>>O1m;WD<_TCB0NCv{A+zfZI1Qs$qU+)Q?gB47M7x^5%{)DrjIZ+`$xB#6%d+AQ%_V@8Q)Gu`6>3Rh6LA4Q}LISi??O#WEPh z1o(lUUY`7Nd#GfSS92-U(m-i?b! z=)nLO%!T>N?djP?q|+f~iWqNZ9~nfbGlsU&3iJ38 zmhmvTN`IcN7nPFq7mx%gOrL)p}O}hi(qMvd#ECV2z7P}Pk#pcGK-g>j=q#XhDt@G(ES8~j>vY4 zc^u{i$B{XNIZ&=ya_vkd&nF@`K-@bF%E*u7zG~%`_o7rg=x!TmH&9NS~4d4v6fhR0?$A* zpFum@LuEf1L@1y2X^n9kOy(h|4`g;m)6fu3J6S}EJx^qJtlK+c`N8NlXRxKKACzf? z66p>rBhSxeGtA&_csjCR!fmHxs*vYPMSrR$#`+lFW-UC=8*oKrGr6OtqfE#gLS1p& z$-TsR{a`g8Ku?B2O*nOEoC+i!KA4(Z44InLb#t5xwTH8lEOu+IbJ>%!GuzB*S22`M zG#xN27}ZU|F~7zP7#j8J=jeI|#y%=}ae`Rl&h**qFVW=>3U+BnoZwAjE)0)uUw`f> zs!&42X@XE%THzbskLz04!ZomhP2{rPDxQL6d`FJ&Oa4#c(_m*Nb1lqfX&BN0S4UVK z;w$(z$BdS89-KXdO8V6)NfJ}v7~5eO!(k%#!JMcYGo$0E3g^ua&SEwXz{=3u%EowK zQeTpt=y7e9&meRRsf)2^jIGdz^Dy(3_VH`{nRNHbpFPU%2u_seN@}%5n7Z_pgn=L=n?r*hpzYX-s^F1r%y}s zvDo%{+*w_Wr{ghl#77Bv>rB+Cd_#;h0N~f;(@)-)-#ou=f7Ty6e#`T@%MsDe=8Sc` zo0@f!RybVaEwDXkfUL1(sk6wvurnyk{%3{b0g}*FMA7(*$5EFHgcb zUTA<)IN`&X&+XDvU<<}7a~Qyt>--L8`#j;(S6~aqU@e)uFaUP=2R%x z>>IPpG(fO1fWH#C9cD;j-Gl*xumJu?=GK@Yh4noQfcOw0M8Ly<{sLpLmX{S60NF7@ zf+V+=U`NQe(1LBj3QOJFLaVI)}xlYfqc83KPG61EZE<4~yPWBxdy&|xOvSa?Li zW41p@EL=6g$b%twFFZm_gO(R!0rdYm7@~@ghDBR-n(%1Ypj_g^p;6G-heLk^7yur_ VG;oKEao7L=002ovPDHLkV1o0rQH%fp literal 0 HcmV?d00001 diff --git a/macosx/Images/UploadBadge.png b/macosx/Images/UploadBadge.png new file mode 100644 index 0000000000000000000000000000000000000000..9bba85b01182da7a429c19d60c7c34275928a2ef GIT binary patch literal 768 zcmV+b1ONPqP)2V_25Oet-av5RV{_CLV>1kcmj} z*yj=F5#w?0_6Ng703dsoM?2-#li1`jEJX1u0pJUd@E8)~RLV*{?>z1%qc_p#!>6M+ z%5CPMKCdn-TpG@8&2RDh3|}sPoI1kr;Ghr{&cy$iP}{VznkH&KvXz?SM4bGnK;OZYJ7 zD-oFAkw11eeic6GCh|QDa0d>-B{&t_Zpcl%EP#ki{`}>_E2U5kfJ=u6BF++khkN+J zr~M14hSH`UqK&I42bE&jjFONR0H%d@G<-GNwYN0wtJ@Qtv>lg-#t=)y4wQg^Sm&qE z?GyQG_XOY=Tno+v5J1RY=<{{{^7V>EX;K?l&Vy?)3_$?c-euV2q4el63rJiCP0;`{ z?C?=~G-(DuxNb7jYeL%I)dv#Sg(js#ZQlLk~z?Cm;aZ zEP!)lN{t?nxZZ~VU>{;I5l|UWAK(~Vi(woBfOm|+K@uts8k8cn0gi=R2#C>PkY->1 zSBF6WjDrj>;2@z?sR?i^S;U6rWgr?s7zY{bLxU9q*_1A|08WK9j0vvo=3n*%ezJs- zD@Yykr>Z8)*@rK%IsJ}Ip^DdhH&ZCt!WAVR-Tq%};j#!^FNSO-wkX>ffChhqP5OUb y43R-s!@P}6_Q$JXP6QZT4)p?leL3`9fB^t8|3==U%|&|v0000