Update volume slider to use NSPopover.

CQTexperiment
Dzmitry Neviadomski 2021-01-07 06:48:40 +03:00
parent 42690a8077
commit 76bdebd058
4 changed files with 95 additions and 54 deletions

View File

@ -1739,19 +1739,19 @@ Gw
</items> </items>
</menu> </menu>
<customView id="1611" userLabel="Volume View"> <customView id="1611" userLabel="Volume View">
<rect key="frame" x="0.0" y="0.0" width="26" height="168"/> <rect key="frame" x="0.0" y="0.0" width="32" height="168"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<slider horizontalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1612" customClass="VolumeSlider"> <slider horizontalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1612" customClass="VolumeSlider">
<rect key="frame" x="6" y="19" width="15" height="129"/> <rect key="frame" x="6" y="2" width="20" height="164"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<sliderCell key="cell" controlSize="small" continuous="YES" alignment="left" maxValue="100" doubleValue="50" tickMarkPosition="left" sliderType="linear" id="1613"/> <sliderCell key="cell" controlSize="small" continuous="YES" alignment="left" minValue="10" maxValue="100" doubleValue="55" tickMarkPosition="left" sliderType="linear" id="1613"/>
<connections> <connections>
<action selector="changeVolume:" target="705" id="1614"/> <action selector="changeVolume:" target="705" id="1614"/>
</connections> </connections>
</slider> </slider>
</subviews> </subviews>
<point key="canvasLocation" x="-137" y="118"/> <point key="canvasLocation" x="615" y="-25"/>
</customView> </customView>
<customObject id="1675" customClass="SpotlightWindowController"> <customObject id="1675" customClass="SpotlightWindowController">
<connections> <connections>

View File

@ -20,7 +20,7 @@
[[(VolumeSlider *)_popView target] changeVolume:_popView]; [[(VolumeSlider *)_popView target] changeVolume:_popView];
[(VolumeSlider *)_popView showToolTipForDuration:1.0]; [(VolumeSlider *)_popView showToolTipForView:self closeAfter:1.0];
} }
- (void)mouseDown:(NSEvent *)theEvent - (void)mouseDown:(NSEvent *)theEvent

View File

@ -10,11 +10,13 @@
#import "ToolTipWindow.h" #import "ToolTipWindow.h"
@interface VolumeSlider : NSSlider { @interface VolumeSlider : NSSlider {
ToolTipWindow *toolTip; NSPopover *popover;
NSText *textView;
} }
- (void)showToolTip; - (void)showToolTip;
- (void)showToolTipForDuration:(NSTimeInterval)duration; - (void)showToolTipForDuration:(NSTimeInterval)duration;
- (void)showToolTipForView:(NSView *)view closeAfter:(NSTimeInterval)duration;
- (void)hideToolTip; - (void)hideToolTip;
@end @end

View File

@ -10,28 +10,38 @@
#import "PlaybackController.h" #import "PlaybackController.h"
#import "CogAudio/Helper.h" #import "CogAudio/Helper.h"
@implementation VolumeSlider @implementation VolumeSlider {
NSTimer *currentTimer;
}
- (id)initWithFrame:(NSRect)frame - (id)initWithFrame:(NSRect)frame
{ {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self)
{
toolTip = [[ToolTipWindow alloc] init];
}
return self; return self;
} }
- (id)initWithCoder:(NSCoder *)coder - (id)initWithCoder:(NSCoder *)coder
{ {
self = [super initWithCoder:coder]; self = [super initWithCoder:coder];
if (self) return self;
{
toolTip = [[ToolTipWindow alloc] init];
} }
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 - (void)updateToolTip
@ -39,42 +49,71 @@
double value = [self doubleValue]; double value = [self doubleValue];
double volume = linearToLogarithmic(value); double volume = linearToLogarithmic(value);
NSString *text = [[NSString alloc] initWithFormat:@"%0.lf%%", volume]; NSString *text = [NSString stringWithFormat:@"%0.lf%%", volume];
NSSize size = [toolTip suggestedSizeForTooltip:text]; [textView setString:text];
NSPoint mouseLocation = [NSEvent mouseLocation];
[toolTip setToolTip:text];
[toolTip setFrame:NSMakeRect(mouseLocation.x, mouseLocation.y, size.width, size.height) display:YES];
} }
- (void)showToolTip - (void)showToolTip
{ {
[self updateToolTip]; [self updateToolTip];
[toolTip orderFront]; 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 - (void)showToolTipForDuration:(NSTimeInterval)duration
{ {
[self updateToolTip]; [self showToolTip];
[toolTip orderFrontForDuration:duration];
[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 - (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 - (BOOL)sendAction:(SEL)theAction to:(id)theTarget
{ {
double oneLog = logarithmicToLinear(100.0); // Snap to 100% if value is close
double distance = [self frame].size.height*([self doubleValue] - oneLog)/100.0; double snapTarget = logarithmicToLinear(100.0);
if (fabs(distance) < 2.0) double snapProgress = ([self doubleValue] - snapTarget) / (self.maxValue - self.minValue);
if (fabs(snapProgress) < 0.005)
{ {
[self setDoubleValue:oneLog]; [self setDoubleValue:snapTarget];
} }
[self showToolTip]; [self showToolTip];