diff options
author | dynaflash <[email protected]> | 2012-09-15 17:08:16 +0000 |
---|---|---|
committer | dynaflash <[email protected]> | 2012-09-15 17:08:16 +0000 |
commit | 1faac76d071993d03fb93ad8e58b3ef41e9b4c2a (patch) | |
tree | 3ab4505ea6e1eb42c9650dad578b65cff0eac700 | |
parent | 8329bf01460521587889fd4133f76b32ccf13217 (diff) |
MacGui: New dock icon progess behavior with percent & ETA "badges".
- Patch by Jerome Lacube Thanks !!
- Details can be found here https://reviews.handbrake.fr/r/344/
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4964 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | macosx/Controller.h | 7 | ||||
-rw-r--r-- | macosx/Controller.m | 130 | ||||
-rw-r--r-- | macosx/DockTextField.h | 17 | ||||
-rw-r--r-- | macosx/DockTextField.m | 74 | ||||
-rw-r--r-- | macosx/HandBrake.xcodeproj/project.pbxproj | 12 |
5 files changed, 162 insertions, 78 deletions
diff --git a/macosx/Controller.h b/macosx/Controller.h index 62aad34dd..c8eb322bb 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -25,6 +25,7 @@ extern NSString *HBTitleChangedNotification; extern NSString *keyTitleTag; @class HBOutputPanelController; +@class DockTextField; /* We subclass NSView so that our drags show both the icon as well as PresetName columns */ @interface HBPresetsOutlineView : NSOutlineView @@ -256,7 +257,11 @@ BOOL fIsDragging; NSString * currentSource; NSString * browsedSourceDisplayName; + /* Dock progress variables */ double dockIconProgress; + NSDockTile *dockTile; + DockTextField *percentField; + DockTextField *timeField; } - (int) getPidnum; - (IBAction) showAboutPanel:(id)sender; @@ -441,5 +446,7 @@ BOOL fIsDragging; + (unsigned int) maximumNumberOfAllowedAudioTracks; - (IBAction) addAllAudioTracks: (id) sender; +- (void) updateDockIcon:(double)progress withETA:(NSString*)etaStr; + @end diff --git a/macosx/Controller.m b/macosx/Controller.m index cf6fdd6c4..e147484c0 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -11,6 +11,7 @@ #import "HBDVDDetector.h" #import "HBPresets.h" #import "HBPreviewController.h" +#import "DockTextField.h" unsigned int maximumNumberOfAllowedAudioTracks = 24; NSString *HBContainerChangedNotification = @"HBContainerChangedNotification"; @@ -20,6 +21,10 @@ NSString *keyTitleTag = @"keyTitleTag"; #define DragDropSimplePboardType @"MyCustomOutlineViewPboardType" +NSString *dockTilePercentFormat = @"%2.1f%%"; +// DockTile update freqency in total percent increment +#define dockTileUpdateFrequency 0.5f + /* We setup the toolbar values here ShowPreviewIdentifier */ static NSString * ToggleDrawerIdentifier = @"Toggle Drawer Item Identifier"; static NSString * StartEncodingIdentifier = @"Start Encoding Item Identifier"; @@ -93,6 +98,24 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]]; [self writeToActivityLog: "%s", [versionStringFull UTF8String]]; + /* Load the dockTile and instiante initial text fields */ + self->dockTile = [[NSApplication sharedApplication] dockTile]; + NSImageView *iv = [[NSImageView alloc] init]; + [iv setImage:[[NSApplication sharedApplication] applicationIconImage]]; + [self->dockTile setContentView:iv]; + + /* We can move the specific values out from here by subclassing NSDockTile and package everything in here */ + /* If colors are to be chosen once and for all, we can also remove the instantiation with numerical values */ + percentField = [[DockTextField alloc] initWithFrame:NSMakeRect(0.0f, 32.0f, self->dockTile.size.width, 30.0f)]; + [percentField changeGradientColors:[NSColor colorWithSRGBRed:0.4f green:0.6f blue:0.4f alpha:1.0f] withEndColor:[NSColor colorWithSRGBRed:0.2f green:0.4f blue:0.2f alpha:1.0f]]; + [iv addSubview:percentField]; + + timeField = [[DockTextField alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, self->dockTile.size.width, 30.0f)]; + [timeField changeGradientColors:[NSColor colorWithSRGBRed:0.6f green:0.4f blue:0.4f alpha:1.0f] withEndColor:[NSColor colorWithSRGBRed:0.4f green:0.2f blue:0.2f alpha:1.0f]]; + [iv addSubview:timeField]; + + [self updateDockIcon:-1.0 withETA:@""]; + return self; } @@ -635,83 +658,26 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /*********************************************************************** - * UpdateDockIcon + * updateDockIcon *********************************************************************** - * Shows a progression bar on the dock icon, filled according to - * 'progress' (0.0 <= progress <= 1.0). - * Called with progress < 0.0 or progress > 1.0, restores the original - * icon. + * Updates two DockTextFields on the dockTile, + * one with total percentage, the other one with the ETA. + * The ETA string is formated by the callers **********************************************************************/ -- (void) UpdateDockIcon: (float) progress +- (void) updateDockIcon: (double) progress withETA:(NSString*)etaStr { - NSData * tiff; - NSBitmapImageRep * bmp; - uint32_t * pen; - uint32_t black = htonl( 0x000000FF ); - uint32_t red = htonl( 0xFF0000FF ); - uint32_t white = htonl( 0xFFFFFFFF ); - int row_start, row_end; - int i, j; - - if( progress < 0.0 || progress > 1.0 ) + if (progress < 0.0 || progress > 1.0) { - [NSApp setApplicationIconImage: fApplicationIcon]; - return; + [percentField setHidden:YES]; + [timeField setHidden:YES]; + } else { + [percentField setTextToDisplay:[NSString stringWithFormat:dockTilePercentFormat,progress * 100]]; + [percentField setHidden:NO]; + [timeField setTextToDisplay:etaStr]; + [timeField setHidden:NO]; } - - /* Get it in a raw bitmap form */ - tiff = [fApplicationIcon TIFFRepresentationUsingCompression: - NSTIFFCompressionNone factor: 1.0]; - bmp = [NSBitmapImageRep imageRepWithData: tiff]; - /* Draw the progression bar */ - /* It's pretty simple (ugly?) now, but I'm no designer */ - - row_start = 3 * (int) [bmp size].height / 4; - row_end = 7 * (int) [bmp size].height / 8; - - for( i = row_start; i < row_start + 2; i++ ) - { - pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] ); - for( j = 0; j < (int) [bmp size].width; j++ ) - { - pen[j] = black; - } - } - for( i = row_start + 2; i < row_end - 2; i++ ) - { - pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] ); - pen[0] = black; - pen[1] = black; - for( j = 2; j < (int) [bmp size].width - 2; j++ ) - { - if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) ) - { - pen[j] = red; - } - else - { - pen[j] = white; - } - } - pen[j] = black; - pen[j+1] = black; - } - for( i = row_end - 2; i < row_end; i++ ) - { - pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] ); - for( j = 0; j < (int) [bmp size].width; j++ ) - { - pen[j] = black; - } - } - - /* Now update the dock icon */ - tiff = [bmp TIFFRepresentationUsingCompression: - NSTIFFCompressionNone factor: 1.0]; - NSImage* icon = [[NSImage alloc] initWithData: tiff]; - [NSApp setApplicationIconImage: icon]; - [icon release]; + [self->dockTile display]; } - (void) updateUI: (NSTimer *) timer @@ -954,8 +920,22 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Update dock icon */ if( dockIconProgress < 100.0 * progress_total ) { - [self UpdateDockIcon: progress_total]; - dockIconProgress += 5; + // ETA format is [XX]X:XX:XX when ETA is greater than one hour + // [X]X:XX when ETA is greater than 0 (minutes or seconds) + // When these conditions doesn't applied (eg. when ETA is undefined) + // we show just a tilde (~) + + NSString *etaStr = @""; + if (p.hours > 0) + etaStr = [NSString stringWithFormat:@"%d:%02d:%02d", p.hours, p.minutes, p.seconds]; + else if (p.minutes > 0 || p.seconds > 0) + etaStr = [NSString stringWithFormat:@"%d:%02d", p.minutes, p.seconds]; + else + etaStr = @"~"; + + [self updateDockIcon:progress_total withETA:etaStr]; + + dockIconProgress += dockTileUpdateFrequency; } break; @@ -974,7 +954,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fRipIndicator startAnimation: nil]; /* Update dock icon */ - [self UpdateDockIcon: 1.0]; + [self updateDockIcon:1.0 withETA:@""]; break; } @@ -1002,7 +982,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [[fWindow toolbar] validateVisibleItems]; /* Restore dock icon */ - [self UpdateDockIcon: -1.0]; + [self updateDockIcon:-1.0 withETA:@""]; dockIconProgress = 0; if( fRipIndicatorShown ) diff --git a/macosx/DockTextField.h b/macosx/DockTextField.h new file mode 100644 index 000000000..a269211c7 --- /dev/null +++ b/macosx/DockTextField.h @@ -0,0 +1,17 @@ +/* DockTextField.h $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr/>. + It may be used under the terms of the GNU General Public License. */ + +#import <Cocoa/Cocoa.h> + +@interface DockTextField : NSTextField + +@property (nonatomic,retain) NSString *textToDisplay; +@property (nonatomic,retain) NSColor *startColor; +@property (nonatomic,retain) NSColor *endColor; + +- (void)changeGradientColors:(NSColor*)startColor withEndColor:(NSColor*)endColor; + +@end diff --git a/macosx/DockTextField.m b/macosx/DockTextField.m new file mode 100644 index 000000000..0b71d632f --- /dev/null +++ b/macosx/DockTextField.m @@ -0,0 +1,74 @@ +/* DockTextField.m $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr/>. + It may be used under the terms of the GNU General Public License. */ + +#import "DockTextField.h" + +#define DOCK_TEXTFIELD_ALPHA 0.8 +#define DOCK_TEXTFIELD_FONTSIZE 28.0 + +@implementation DockTextField + +@synthesize textToDisplay = _textToDisplay; +@synthesize startColor = _startColor; +@synthesize endColor = _endColor; + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [[self cell] setBezelStyle: NSTextFieldRoundedBezel]; + _textToDisplay = @""; + + [self changeGradientColors:[NSColor grayColor] withEndColor:[NSColor blackColor]]; + } + + return self; +} + +- (void)changeGradientColors:(NSColor*)startColor withEndColor:(NSColor*)endColor +{ + NSColor *startRGBColor = [startColor colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; + NSColor *endRGBColor = [endColor colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; + + self.startColor = [NSColor colorWithSRGBRed:startRGBColor.redComponent green:startRGBColor.greenComponent blue:startRGBColor.blueComponent alpha:DOCK_TEXTFIELD_ALPHA]; + self.endColor = [NSColor colorWithSRGBRed:endRGBColor.redComponent green:endRGBColor.greenComponent blue:endRGBColor.blueComponent alpha:DOCK_TEXTFIELD_ALPHA]; +} + +- (void)drawRect:(NSRect)dirtyRect +{ + if (self.isHidden) + return; + + NSRect blackOutlineFrame = NSMakeRect(0.0, 0.0, [self bounds].size.width, [self bounds].size.height-1.0); + double radius = self.bounds.size.height / 2; + + NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:self.startColor endingColor:self.endColor]; + [gradient drawInBezierPath:[NSBezierPath bezierPathWithRoundedRect:blackOutlineFrame xRadius:radius yRadius:radius] angle:90]; + + NSMutableDictionary *drawStringAttributes = [[NSMutableDictionary alloc] init]; + [drawStringAttributes setValue:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + [drawStringAttributes setValue:[NSFont boldSystemFontOfSize:DOCK_TEXTFIELD_FONTSIZE] forKey:NSFontAttributeName]; + NSShadow *stringShadow = [[NSShadow alloc] init]; + [stringShadow setShadowColor:[NSColor blackColor]]; + NSSize shadowSize; + shadowSize.width = 2; + shadowSize.height = -2; + [stringShadow setShadowOffset:shadowSize]; + [stringShadow setShadowBlurRadius:6]; + [drawStringAttributes setValue:stringShadow forKey:NSShadowAttributeName]; + [stringShadow release]; + + NSString *MRString = _textToDisplay; + NSString *budgetString = [NSString stringWithFormat:@"%@", MRString]; + NSSize stringSize = [budgetString sizeWithAttributes:drawStringAttributes]; + NSPoint centerPoint; + centerPoint.x = (dirtyRect.size.width / 2) - (stringSize.width / 2); + centerPoint.y = dirtyRect.size.height / 2 - (stringSize.height / 2) - 2; + [budgetString drawAtPoint:centerPoint withAttributes:drawStringAttributes]; + [drawStringAttributes release]; +} + +@end diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index 5c22284c7..870fec3f3 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 226268E01572CC7300477B4E /* libavresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226268DF1572CC7300477B4E /* libavresample.a */; }; + 226268E11572CC7300477B4E /* libavresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226268DF1572CC7300477B4E /* libavresample.a */; }; 273F202314ADB8650021BE6D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 273F202214ADB8650021BE6D /* IOKit.framework */; }; 273F202614ADB8A40021BE6D /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 273F202514ADB8A40021BE6D /* libz.dylib */; }; 273F202814ADB8BE0021BE6D /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 273F202714ADB8BE0021BE6D /* libbz2.dylib */; }; @@ -96,8 +98,6 @@ 27D6C74614B102DA00B785E4 /* libavcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72914B102DA00B785E4 /* libavcodec.a */; }; 27D6C74714B102DA00B785E4 /* libavformat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72A14B102DA00B785E4 /* libavformat.a */; }; 27D6C74814B102DA00B785E4 /* libavformat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72A14B102DA00B785E4 /* libavformat.a */; }; - 226268E01572CC7300477B4E /* libavresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226268DF1572CC7300477B4E /* libavresample.a */; }; - 226268E11572CC7300477B4E /* libavresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226268DF1572CC7300477B4E /* libavresample.a */; }; 27D6C74914B102DA00B785E4 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72B14B102DA00B785E4 /* libavutil.a */; }; 27D6C74A14B102DA00B785E4 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72B14B102DA00B785E4 /* libavutil.a */; }; 27D6C74B14B102DA00B785E4 /* libbluray.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C72C14B102DA00B785E4 /* libbluray.a */; }; @@ -138,6 +138,7 @@ 27D6C77114B102DA00B785E4 /* libx264.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C73F14B102DA00B785E4 /* libx264.a */; }; 27D6C77214B102DA00B785E4 /* libxml2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C74014B102DA00B785E4 /* libxml2.a */; }; 27D6C77314B102DA00B785E4 /* libxml2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D6C74014B102DA00B785E4 /* libxml2.a */; }; + 46AB433515F98A2B009C0961 /* DockTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 46AB433415F98A2B009C0961 /* DockTextField.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -181,6 +182,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 226268DF1572CC7300477B4E /* libavresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavresample.a; path = external/contrib/lib/libavresample.a; sourceTree = BUILT_PRODUCTS_DIR; }; 271BA4C014B119F800BC1D2C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = external/macosx/Info.plist; sourceTree = BUILT_PRODUCTS_DIR; }; 273F1FFF14ADAE950021BE6D /* HandBrakeCLI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = HandBrakeCLI; sourceTree = BUILT_PRODUCTS_DIR; }; 273F202214ADB8650021BE6D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; @@ -288,7 +290,6 @@ 27D6C72814B102DA00B785E4 /* libass.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libass.a; path = external/contrib/lib/libass.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C72914B102DA00B785E4 /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavcodec.a; path = external/contrib/lib/libavcodec.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C72A14B102DA00B785E4 /* libavformat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavformat.a; path = external/contrib/lib/libavformat.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 226268DF1572CC7300477B4E /* libavresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavresample.a; path = external/contrib/lib/libavresample.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C72B14B102DA00B785E4 /* libavutil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavutil.a; path = external/contrib/lib/libavutil.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C72C14B102DA00B785E4 /* libbluray.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbluray.a; path = external/contrib/lib/libbluray.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C72E14B102DA00B785E4 /* libdvdnav.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdvdnav.a; path = external/contrib/lib/libdvdnav.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -310,6 +311,8 @@ 27D6C73F14B102DA00B785E4 /* libx264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libx264.a; path = external/contrib/lib/libx264.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27D6C74014B102DA00B785E4 /* libxml2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxml2.a; path = external/contrib/lib/libxml2.a; sourceTree = BUILT_PRODUCTS_DIR; }; 34FF2FC014EEC363004C2400 /* HBAdvancedController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBAdvancedController.h; sourceTree = "<group>"; }; + 46AB433315F98A2B009C0961 /* DockTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DockTextField.h; sourceTree = "<group>"; }; + 46AB433415F98A2B009C0961 /* DockTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DockTextField.m; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -507,6 +510,8 @@ 273F208D14ADBE670021BE6D /* ChapterTitles.m */, 273F208E14ADBE670021BE6D /* Controller.h */, 273F208F14ADBE670021BE6D /* Controller.m */, + 46AB433315F98A2B009C0961 /* DockTextField.h */, + 46AB433415F98A2B009C0961 /* DockTextField.m */, 34FF2FC014EEC363004C2400 /* HBAdvancedController.h */, 273F209014ADBE670021BE6D /* HBAdvancedController.m */, 273F209114ADBE670021BE6D /* HBAudio.h */, @@ -822,6 +827,7 @@ 273F20B914ADBE670021BE6D /* HBSubtitles.m in Sources */, 273F20BA14ADBE670021BE6D /* PictureController.m in Sources */, 273F20BE14ADC09F0021BE6D /* main.mm in Sources */, + 46AB433515F98A2B009C0961 /* DockTextField.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; |