diff --git a/Application/PlaybackEventController.m b/Application/PlaybackEventController.m index 64f02741e..26819f3fd 100644 --- a/Application/PlaybackEventController.m +++ b/Application/PlaybackEventController.m @@ -108,8 +108,6 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response - (NSDictionary *)fillNotificationDictionary:(PlaylistEntry *)pe status:(TrackStatus)status { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - if (pe == nil) - return dict; [dict setObject:[[pe URL] absoluteString] forKey:TrackPath]; if ([pe title]) [dict setObject:[pe title] forKey:TrackTitle]; diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 0a13fd58b..fe746d058 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -1739,19 +1739,19 @@ Gw - - + + - + - + - + diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 7854b21fd..98a93de37 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -981,7 +981,7 @@ 8E9A30140BA792DC0091081B /* NSFileHandle+CreateFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileHandle+CreateFile.m"; sourceTree = ""; }; B09E94300D747F7B0064F138 /* FFMPEG.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FFMPEG.xcodeproj; path = Plugins/FFMPEG/FFMPEG.xcodeproj; sourceTree = ""; }; B09E96620D74A7BC0064F138 /* stop_current.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stop_current.png; path = Images/stop_current.png; sourceTree = ""; }; - EDAAA41E25A665C000731773 /* PositionSliderToolbarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PositionSliderToolbarItem.swift; path = Window/PositionSliderToolbarItem.swift; sourceTree = ""; }; + EDAAA41E25A665C000731773 /* PositionSliderToolbarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionSliderToolbarItem.swift; sourceTree = ""; }; F6F96718102C709000D2C9B4 /* NSString+FinderCompare.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+FinderCompare.m"; sourceTree = ""; }; F6F9671A102C70C800D2C9B4 /* NSString+FinderCompare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+FinderCompare.h"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1355,31 +1355,31 @@ children = ( 83BC5AB120E4C87100631CD4 /* DualWindow.h */, 83BC5AB020E4C87100631CD4 /* DualWindow.m */, - 17E0D5E10F520F02005B6FED /* MainWindow.h */, - 17E0D5E20F520F02005B6FED /* MainWindow.m */, 836D28A618086386005B7299 /* MiniModeMenuTitleTransformer.h */, 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */, - 17E0D5E30F520F02005B6FED /* MiniWindow.h */, - 17E0D5E40F520F02005B6FED /* MiniWindow.m */, - 838491201807F38A00E7332D /* NowPlayingBarController.h */, - 8384911F1807F38A00E7332D /* NowPlayingBarController.m */, - 838491241807F75D00E7332D /* NowPlayingBarView.h */, 8384911D1807F38A00E7332D /* NowPlayingBarView.m */, + 838491241807F75D00E7332D /* NowPlayingBarView.h */, + 8384911F1807F38A00E7332D /* NowPlayingBarController.m */, + 838491201807F38A00E7332D /* NowPlayingBarController.h */, 1752C36A0F59E00100F85F28 /* PlaybackButtons.h */, 1752C36B0F59E00100F85F28 /* PlaybackButtons.m */, - 17E0D5E50F520F02005B6FED /* PositionSlider.h */, - 17E0D5E60F520F02005B6FED /* PositionSlider.m */, - EDAAA41E25A665C000731773 /* PositionSliderToolbarItem.swift */, - 172A12310F5911D20078EF0C /* RepeatTransformers.h */, - 172A12320F5911D20078EF0C /* RepeatTransformers.m */, 172A123A0F5912AE0078EF0C /* ShuffleTransformers.h */, 172A123B0F5912AE0078EF0C /* ShuffleTransformers.m */, - 17E0D5E70F520F02005B6FED /* TimeField.h */, - 17E0D5E80F520F02005B6FED /* TimeField.m */, + 172A12310F5911D20078EF0C /* RepeatTransformers.h */, + 172A12320F5911D20078EF0C /* RepeatTransformers.m */, 17E0D6180F520F9F005B6FED /* VolumeButton.h */, 17E0D6190F520F9F005B6FED /* VolumeButton.m */, 17E0D61A0F520F9F005B6FED /* VolumeSlider.h */, 17E0D61B0F520F9F005B6FED /* VolumeSlider.m */, + 17E0D5E10F520F02005B6FED /* MainWindow.h */, + 17E0D5E20F520F02005B6FED /* MainWindow.m */, + 17E0D5E30F520F02005B6FED /* MiniWindow.h */, + 17E0D5E40F520F02005B6FED /* MiniWindow.m */, + 17E0D5E50F520F02005B6FED /* PositionSlider.h */, + 17E0D5E60F520F02005B6FED /* PositionSlider.m */, + 17E0D5E70F520F02005B6FED /* TimeField.h */, + 17E0D5E80F520F02005B6FED /* TimeField.m */, + EDAAA41E25A665C000731773 /* PositionSliderToolbarItem.swift */, ); name = Window; sourceTree = ""; diff --git a/Window/PositionSliderToolbarItem.swift b/PositionSliderToolbarItem.swift similarity index 100% rename from Window/PositionSliderToolbarItem.swift rename to PositionSliderToolbarItem.swift diff --git a/Window/VolumeButton.m b/Window/VolumeButton.m index b9dc907cc..79a0d15e5 100644 --- a/Window/VolumeButton.m +++ b/Window/VolumeButton.m @@ -20,7 +20,7 @@ [[(VolumeSlider *)_popView target] changeVolume:_popView]; - [(VolumeSlider *)_popView showToolTipForDuration:1.0]; + [(VolumeSlider *)_popView showToolTipForView:self closeAfter:1.0]; } - (void)mouseDown:(NSEvent *)theEvent diff --git a/Window/VolumeSlider.h b/Window/VolumeSlider.h index 7552fcfc1..483fb4845 100644 --- a/Window/VolumeSlider.h +++ b/Window/VolumeSlider.h @@ -10,11 +10,13 @@ #import "ToolTipWindow.h" @interface VolumeSlider : NSSlider { - ToolTipWindow *toolTip; + NSPopover *popover; + NSText *textView; } - (void)showToolTip; - (void)showToolTipForDuration:(NSTimeInterval)duration; +- (void)showToolTipForView:(NSView *)view closeAfter:(NSTimeInterval)duration; - (void)hideToolTip; @end diff --git a/Window/VolumeSlider.m b/Window/VolumeSlider.m index e3b6140a8..8523eed9b 100644 --- a/Window/VolumeSlider.m +++ b/Window/VolumeSlider.m @@ -10,87 +10,126 @@ #import "PlaybackController.h" #import "CogAudio/Helper.h" -@implementation VolumeSlider +@implementation VolumeSlider { + NSTimer *currentTimer; +} - (id)initWithFrame:(NSRect)frame { - self = [super initWithFrame:frame]; - if (self) - { - toolTip = [[ToolTipWindow alloc] init]; - } - - return self; + self = [super initWithFrame:frame]; + return self; } - (id)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - if (self) - { - toolTip = [[ToolTipWindow alloc] init]; - } - - return self; + self = [super initWithCoder:coder]; + return self; +} + +- (void) awakeFromNib { + textView = [[NSText alloc] init]; + [textView setFrame:NSMakeRect(0, 0, 50, 20)]; + textView.drawsBackground = NO; + textView.editable = NO; + textView.alignment = NSTextAlignmentCenter; + + NSViewController * viewController = [[NSViewController alloc] init]; + viewController.view = textView; + + popover = [[NSPopover alloc] init]; + popover.contentViewController = viewController; + // Don't hide the popover automatically. + popover.behavior = NSPopoverBehaviorApplicationDefined; + popover.animates = NO; + [popover setContentSize:textView.bounds.size]; } - (void)updateToolTip { - double value = [self doubleValue]; - double volume = linearToLogarithmic(value); - - NSString *text = [[NSString alloc] initWithFormat:@"%0.lf%%", volume]; - - NSSize size = [toolTip suggestedSizeForTooltip:text]; - NSPoint mouseLocation = [NSEvent mouseLocation]; - - [toolTip setToolTip:text]; - [toolTip setFrame:NSMakeRect(mouseLocation.x, mouseLocation.y, size.width, size.height) display:YES]; + double value = [self doubleValue]; + double volume = linearToLogarithmic(value); + + NSString *text = [NSString stringWithFormat:@"%0.lf%%", volume]; + + [textView setString:text]; } - (void)showToolTip { - [self updateToolTip]; - - [toolTip orderFront]; + [self updateToolTip]; + + double progress = (self.maxValue - [self doubleValue]) / (self.maxValue - self.minValue); + CGFloat width = self.knobThickness - 1; + // Show tooltip to the left of the Slider Knob + CGFloat height = self.knobThickness / 2.f + (self.bounds.size.height - self.knobThickness) * progress - 1; + + [popover showRelativeToRect:NSMakeRect(width, height, 2, 2) ofView:self preferredEdge:NSRectEdgeMaxX]; + [self.window.parentWindow makeKeyWindow]; } - (void)showToolTipForDuration:(NSTimeInterval)duration { - [self updateToolTip]; - [toolTip orderFrontForDuration:duration]; + [self showToolTip]; + + [self hideToolTipAfterDelay:duration]; } +- (void)showToolTipForView:(NSView *)view closeAfter:(NSTimeInterval)duration +{ + [self updateToolTip]; + + [popover showRelativeToRect:view.bounds ofView:view preferredEdge:NSRectEdgeMaxY]; + + [self hideToolTipAfterDelay:duration]; +} - (void)hideToolTip { - [toolTip close]; + [popover close]; } +- (void) hideToolTipAfterDelay:(NSTimeInterval)duration +{ + if (currentTimer) + { + [currentTimer invalidate]; + currentTimer = nil; + } + + if (duration > 0.0) { + currentTimer = [NSTimer scheduledTimerWithTimeInterval:duration + target:self + selector:@selector(hideToolTip) + userInfo:nil + repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:currentTimer forMode:NSRunLoopCommonModes]; + } +} - (BOOL)sendAction:(SEL)theAction to:(id)theTarget { - double oneLog = logarithmicToLinear(100.0); - double distance = [self frame].size.height*([self doubleValue] - oneLog)/100.0; - if (fabs(distance) < 2.0) - { - [self setDoubleValue:oneLog]; - } + // Snap to 100% if value is close + double snapTarget = logarithmicToLinear(100.0); + double snapProgress = ([self doubleValue] - snapTarget) / (self.maxValue - self.minValue); + if (fabs(snapProgress) < 0.005) + { + [self setDoubleValue:snapTarget]; + } - [self showToolTip]; - - return [super sendAction:theAction to:theTarget]; + [self showToolTip]; + + return [super sendAction:theAction to:theTarget]; } - (void)scrollWheel:(NSEvent *)theEvent { - double change = [theEvent deltaY]; - - [self setDoubleValue:[self doubleValue] + change]; - - [[self target] changeVolume:self]; - - [self showToolTipForDuration:1.0]; + double change = [theEvent deltaY]; + + [self setDoubleValue:[self doubleValue] + change]; + + [[self target] changeVolume:self]; + + [self showToolTipForDuration:1.0]; } @end