summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordynaflash <[email protected]>2012-09-15 17:08:16 +0000
committerdynaflash <[email protected]>2012-09-15 17:08:16 +0000
commit1faac76d071993d03fb93ad8e58b3ef41e9b4c2a (patch)
tree3ab4505ea6e1eb42c9650dad578b65cff0eac700
parent8329bf01460521587889fd4133f76b32ccf13217 (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.h7
-rw-r--r--macosx/Controller.m130
-rw-r--r--macosx/DockTextField.h17
-rw-r--r--macosx/DockTextField.m74
-rw-r--r--macosx/HandBrake.xcodeproj/project.pbxproj12
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;
};