source: trunk/Cocoa/Pester/Source/PSVolumeController.m@ 584

Last change on this file since 584 was 584, checked in by Nicholas Riley, 15 years ago

Better solution for volume popup in 10.6: use a menu.

File size: 3.7 KB
Line 
1//
2// PSVolumeController.m
3// Pester
4//
5// Created by Nicholas Riley on Tue Apr 08 2003.
6// Copyright (c) 2003 Nicholas Riley. All rights reserved.
7//
8
9#import "PSVolumeController.h"
10#import "NJRSoundManager.h"
11#import "NJRNonCenteringWindow.h"
12
13@interface NSMenu (SnowLeopardAdditions)
14- (BOOL)popUpMenuPositioningItem:(NSMenuItem *)item atLocation:(NSPoint)location inView:(NSView *)view;
15- (void)setAllowsContextMenuPlugIns:(BOOL)allows;
16- (void)cancelTracking;
17@end
18
19@interface NSMenuItem (SnowLeopardAdditions)
20- (void)setView:(NSView *)view;
21@end
22
23@implementation PSVolumeController
24
25+ (PSVolumeController *)controllerWithVolume:(float)volume delegate:(id)aDelegate;
26{
27 return [[self alloc] initWithVolume: volume delegate: aDelegate];
28}
29
30- (id)initWithVolume:(float)volume delegate:(id)aDelegate;
31{
32 if ( (self = [self initWithWindowNibName: @"Volume"]) != nil) {
33 [self window]; // connect outlets
34
35 if ([NJRSoundManager volumeIsNotMutedOrInvalid: volume])
36 [volumeSlider setFloatValue: volume];
37
38 delegate = [aDelegate retain];
39
40 NSView *view = [aDelegate volumeControllerLaunchingView: self];
41
42 // In 10.6, we can no longer force the modal session to work by "seeding" the slider with a mouse-down event.
43 // Instead, use a menu. (This should mostly work on 10.5 too, but is currently untested.)
44 if ([NSMenu instancesRespondToSelector: @selector(popUpMenuPositioningItem:atLocation:inView:)]) {
45 menu = [[NSMenu alloc] initWithTitle: @""];
46 NSMenuItem *menuItem = [[NSMenuItem alloc] init];
47 [menuItem setView: contentView];
48 [menu addItem: menuItem];
49 [menuItem release];
50 NSPoint point;
51 if (view != nil) {
52 NSSize size = [view bounds].size;
53 point = [view isFlipped] ? NSMakePoint(0, size.height) : NSZeroPoint;
54 } else {
55 point = [NSEvent mouseLocation];
56 }
57 [menu setAllowsContextMenuPlugIns: NO];
58 [menu popUpMenuPositioningItem: nil atLocation: point inView: view];
59 [menu release];
60 } else {
61 NSWindow *window = [[NJRNonCenteringWindow alloc] initWithContentRect: [contentView bounds] styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO];
62 [window setContentView: contentView];
63 [window setOpaque: NO];
64 [window setBackgroundColor: [NSColor colorWithCalibratedWhite: 0.81f alpha: 0.9f]];
65 [window setHasShadow: YES];
66 [window setOneShot: YES];
67 [window setDelegate: self];
68
69 if (view != nil) {
70 NSRect rect = [view convertRect: [view bounds] toView: nil];
71 NSWindow *parentWindow = [view window];
72 rect.origin = [parentWindow convertBaseToScreen: rect.origin];
73 rect.origin.x -= [window frame].size.width - rect.size.width + 1;
74 [window setFrameTopLeftPoint: rect.origin];
75 NSRect visibleFrame = [[parentWindow screen] visibleFrame];
76 if (!NSContainsRect(visibleFrame, [window frame])) {
77 NSPoint viewTopLeft = { rect.origin.x, rect.origin.y + rect.size.height };
78 [window setFrameOrigin: viewTopLeft];
79 }
80 }
81 // -[NSApplication beginModalSessionForWindow:] shows and centers the window; we use NJRNonCenteringWindow to prevent the repositioning from succeeding
82 NSModalSession session = [NSApp beginModalSessionForWindow: window];
83 [volumeSlider mouseDown: [NSApp currentEvent]];
84 [NSApp runModalSession: session];
85 [NSApp endModalSession: session];
86 [window close];
87 }
88
89 [self autorelease];
90 }
91 return self;
92}
93
94- (void)dealloc;
95{
96 [delegate release];
97 [super dealloc];
98}
99
100- (IBAction)volumeSet:(NSSlider *)sender;
101{
102 [delegate volumeController: self didSetVolume: [sender floatValue]];
103 if (NSEventMaskFromType([[NSApp currentEvent] type]) & (NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask))
104 [menu cancelTracking];
105}
106
107@end
Note: See TracBrowser for help on using the repository browser.