/*****************************************************************************
* misc.m: code not specific to vlc
*****************************************************************************
- * Copyright (C) 2003-2013 VLC authors and VideoLAN
+ * Copyright (C) 2003-2014 VLC authors and VideoLAN
* $Id$
*
* Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
+#import "CompatibilityFixes.h"
#import "misc.h"
#import "intf.h" /* VLCApplication */
#import "MainWindow.h"
static NSMutableArray *blackoutWindows = NULL;
+static bool b_old_spaces_style = YES;
+
+ (void)load
{
/* init our fake object attribute */
blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1];
+
+ if (OSX_MAVERICKS || OSX_YOSEMITE) {
+ NSUserDefaults *userDefaults = [[NSUserDefaults alloc] init];
+ [userDefaults addSuiteNamed:@"com.apple.spaces"];
+ /* this is system settings -> mission control -> monitors using different spaces */
+ NSNumber *o_span_displays = [userDefaults objectForKey:@"spans-displays"];
+
+ b_old_spaces_style = [o_span_displays boolValue];
+ [userDefaults release];
+ }
}
+ (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID
NSUInteger count = [[NSScreen screens] count];
for ( NSUInteger i = 0; i < count; i++ ) {
- NSScreen *screen = [NSScreen screens][i];
+ NSScreen *screen = [[NSScreen screens] objectAtIndex:i];
if ([screen displayID] == displayID)
return screen;
}
- (BOOL)hasMenuBar
{
- return ([self displayID] == [[NSScreen screens][0] displayID]);
+ if (b_old_spaces_style)
+ return ([self displayID] == [[[NSScreen screens] objectAtIndex:0] displayID]);
+ else
+ return YES;
}
- (BOOL)hasDock
NSUInteger screenCount = [[NSScreen screens] count];
for (NSUInteger i = 0; i < screenCount; i++) {
- NSScreen *screen = [NSScreen screens][i];
+ NSScreen *screen = [[NSScreen screens] objectAtIndex:i];
VLCWindow *blackoutWindow;
NSRect screen_rect;
backing: NSBackingStoreBuffered defer: NO screen: screen];
[blackoutWindow setBackgroundColor:[NSColor blackColor]];
[blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */
+ [blackoutWindow setReleasedWhenClosed:NO]; // window is released when deleted from array above
[blackoutWindow displayIfNeeded];
[blackoutWindow orderFront: self animate: YES];
NSUInteger blackoutWindowCount = [blackoutWindows count];
for (NSUInteger i = 0; i < blackoutWindowCount; i++) {
- VLCWindow *blackoutWindow = blackoutWindows[i];
+ VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex:i];
[[blackoutWindow screen] setNonFullscreenPresentationOptions];
[blackoutWindow closeAndAnimate: YES];
}
@end
/*****************************************************************************
- * VLBrushedMetalImageView
+ * VLCDragDropView
+ *****************************************************************************/
+
+@implementation VLCDropDisabledImageView
+
+- (void)awakeFromNib
+{
+ [self unregisterDraggedTypes];
+}
+
+@end
+
+/*****************************************************************************
+ * VLCDragDropView
*****************************************************************************/
-@implementation VLBrushedMetalImageView
+@implementation VLCDragDropView
+
+@synthesize dropHandler=_dropHandler;
+@synthesize drawBorder;
+
+- (id)initWithFrame:(NSRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ // default value
+ [self setDrawBorder:YES];
+ }
+
+ return self;
+}
+
+- (void)enablePlaylistItems
+{
+ [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, @"VLCPlaylistItemPboardType", nil]];
+}
- (BOOL)mouseDownCanMoveWindow
{
- (void)awakeFromNib
{
- [self registerForDraggedTypes:@[NSFilenamesPboardType]];
- [self setImageScaling: NSScaleToFit];
- [self setImageFrameStyle: NSImageFrameNone];
- [self setImageAlignment: NSImageAlignCenter];
+ [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
- if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
- return NSDragOperationGeneric;
+ if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric) {
+ b_activeDragAndDrop = YES;
+ [self setNeedsDisplay:YES];
+
+ return NSDragOperationCopy;
+ }
return NSDragOperationNone;
}
+- (void)draggingEnded:(id < NSDraggingInfo >)sender
+{
+ b_activeDragAndDrop = NO;
+ [self setNeedsDisplay:YES];
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+ b_activeDragAndDrop = NO;
+ [self setNeedsDisplay:YES];
+}
+
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
return YES;
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
BOOL b_returned;
- b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
+
+ if (_dropHandler && [_dropHandler respondsToSelector:@selector(performDragOperation:)])
+ b_returned = [_dropHandler performDragOperation: sender];
+ else // default
+ b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
[self setNeedsDisplay:YES];
return b_returned;
[self setNeedsDisplay:YES];
}
+- (void)drawRect:(NSRect)dirtyRect
+{
+ if ([self drawBorder] && b_activeDragAndDrop) {
+ NSRect frameRect = [self bounds];
+
+ [[NSColor selectedControlColor] set];
+ NSFrameRectWithWidthUsingOperation(frameRect, 2., NSCompositeHighlight);
+ }
+
+ [super drawRect:dirtyRect];
+}
+
@end
- (void)scrollWheel:(NSEvent *)o_event
{
- intf_thread_t * p_intf = VLCIntf;
BOOL b_forward = NO;
CGFloat f_deltaY = [o_event deltaY];
CGFloat f_deltaX = [o_event deltaX];
- (void)awakeFromNib
{
if (config_GetInt( VLCIntf, "macosx-interfacestyle" )) {
- o_knob_img = [NSImage imageNamed:@"progression-knob_dark"];
+ o_knob_img = imageFromRes(@"progression-knob_dark");
b_dark = YES;
} else {
- o_knob_img = [NSImage imageNamed:@"progression-knob"];
+ o_knob_img = imageFromRes(@"progression-knob");
b_dark = NO;
}
img_rect.size = [o_knob_img size];
@implementation VLCVolumeSliderCommon : NSSlider
+@synthesize usesBrightArtwork = _usesBrightArtwork;
+
- (void)scrollWheel:(NSEvent *)o_event
{
- intf_thread_t * p_intf = VLCIntf;
BOOL b_up = NO;
CGFloat f_deltaY = [o_event deltaY];
CGFloat f_deltaX = [o_event deltaX];
// positive for left / down, negative otherwise
CGFloat f_delta = f_deltaX + f_deltaY;
CGFloat f_abs;
- int i_vlckey;
if (f_delta > 0.0f)
f_abs = f_delta;
}
}
+- (void)drawFullVolumeMarker
+{
+ CGFloat maxAudioVol = self.maxValue / AOUT_VOLUME_DEFAULT;
+ if (maxAudioVol < 1.)
+ return;
+
+ NSColor *drawingColor;
+ // for bright artwork, a black color is used and vice versa
+ if (_usesBrightArtwork)
+ drawingColor = [[NSColor blackColor] colorWithAlphaComponent:.4];
+ else
+ drawingColor = [[NSColor whiteColor] colorWithAlphaComponent:.4];
+
+ NSBezierPath* bezierPath = [NSBezierPath bezierPath];
+ [self drawFullVolBezierPath:bezierPath];
+ [bezierPath closePath];
+
+ bezierPath.lineWidth = 1.;
+ [drawingColor setStroke];
+ [bezierPath stroke];
+}
+
+- (CGFloat)fullVolumePos
+{
+ CGFloat maxAudioVol = self.maxValue / AOUT_VOLUME_DEFAULT;
+ CGFloat sliderRange = [self frame].size.width - [self knobThickness];
+ CGFloat sliderOrigin = [self knobThickness] / 2.;
+
+ return 1. / maxAudioVol * sliderRange + sliderOrigin;
+}
+
+- (void)drawFullVolBezierPath:(NSBezierPath*)bezierPath
+{
+ CGFloat fullVolPos = [self fullVolumePos];
+ [bezierPath moveToPoint:NSMakePoint(fullVolPos, [self frame].size.height - 3.)];
+ [bezierPath lineToPoint:NSMakePoint(fullVolPos, 2.)];
+}
+
+@end
+
+@implementation VolumeSliderCell
+
+- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
+{
+ VLCVolumeSliderCommon *o_slider = (VLCVolumeSliderCommon *)controlView;
+ CGFloat fullVolumePos = [o_slider fullVolumePos] + 2.;
+
+ CGPoint snapToPoint = currentPoint;
+ if (ABS(fullVolumePos - currentPoint.x) <= 4.)
+ snapToPoint.x = fullVolumePos;
+
+ return [super continueTracking:lastPoint at:snapToPoint inView:controlView];
+}
+
@end
/*****************************************************************************
{
BOOL b_dark = config_GetInt( VLCIntf, "macosx-interfacestyle" );
if (b_dark)
- img = [NSImage imageNamed:@"volume-slider-knob_dark"];
+ img = imageFromRes(@"volume-slider-knob_dark");
else
- img = [NSImage imageNamed:@"volume-slider-knob"];
+ img = imageFromRes(@"volume-slider-knob");
image_rect.size = [img size];
image_rect.origin.x = 0;
[super drawRect:rect];
[[NSGraphicsContext currentContext] restoreGraphicsState];
+ [self drawFullVolumeMarker];
+
NSRect knobRect = [[self cell] knobRectFlipped:NO];
knobRect.origin.y+=2;
[self drawKnobInRect: knobRect];
@"NO", @"DisplayTimeAsTimeRemaining",
@"YES", @"DisplayFullscreenTimeAsTimeRemaining",
nil];
-
+
[defaults registerDefaults:appDefaults];
}
textAlignment = NSCenterTextAlignment;
o_remaining_identifier = @"";
}
-
+
return self;
}
@end
-@implementation VLCThreePartDropView
-- (BOOL)mouseDownCanMoveWindow
+@implementation PositionFormatter
+
+- (id)init
{
- return YES;
+ self = [super init];
+ NSMutableCharacterSet *nonNumbers = [[[NSCharacterSet decimalDigitCharacterSet] invertedSet] mutableCopy];
+ [nonNumbers removeCharactersInString:@":"];
+ o_forbidden_characters = [nonNumbers copy];
+ [nonNumbers release];
+
+ return self;
}
- (void)dealloc
{
- [self unregisterDraggedTypes];
+ [o_forbidden_characters release];
[super dealloc];
}
-- (void)awakeFromNib
-{
- [self registerForDraggedTypes:@[NSFilenamesPboardType]];
-}
-
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+- (NSString*)stringForObjectValue:(id)obj
{
- if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
- return NSDragOperationGeneric;
+ if([obj isKindOfClass:[NSString class]])
+ return obj;
+ if([obj isKindOfClass:[NSNumber class]])
+ return [obj stringValue];
- return NSDragOperationNone;
+ return nil;
}
-- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
+- (BOOL)getObjectValue:(id*)obj forString:(NSString*)string errorDescription:(NSString**)error
{
+ *obj = [[string copy] autorelease];
return YES;
}
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+- (BOOL)isPartialStringValid:(NSString*)partialString newEditingString:(NSString**)newString errorDescription:(NSString**)error
{
- BOOL b_returned;
- b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
-
- [self setNeedsDisplay:YES];
- return YES;
+ if ([partialString rangeOfCharacterFromSet:o_forbidden_characters options:NSLiteralSearch].location != NSNotFound) {
+ return NO;
+ } else {
+ return YES;
+ }
}
-- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
+@end
+
+@implementation NSView (EnableSubviews)
+
+- (void)enableSubviews:(BOOL)b_enable
{
- [self setNeedsDisplay:YES];
+ for (NSView *o_view in [self subviews]) {
+ [o_view enableSubviews:b_enable];
+
+ // enable NSControl
+ if ([o_view respondsToSelector:@selector(setEnabled:)]) {
+ [(NSControl *)o_view setEnabled:b_enable];
+ }
+ // also "enable / disable" text views
+ if ([o_view respondsToSelector:@selector(setTextColor:)]) {
+ if (b_enable == NO) {
+ [(NSTextField *)o_view setTextColor:[NSColor disabledControlTextColor]];
+ } else {
+ [(NSTextField *)o_view setTextColor:[NSColor controlTextColor]];
+ }
+ }
+
+ }
}
@end
-@implementation PositionFormatter
+/*****************************************************************************
+ * VLCByteCountFormatter addition
+ *****************************************************************************/
-- (id)init
+@implementation VLCByteCountFormatter
+
++ (NSString *)stringFromByteCount:(long long)byteCount countStyle:(NSByteCountFormatterCountStyle)countStyle
{
- self = [super init];
- NSMutableCharacterSet *nonNumbers = [[[NSCharacterSet decimalDigitCharacterSet] invertedSet] mutableCopy];
- [nonNumbers removeCharactersInString:@":"];
- o_forbidden_characters = [nonNumbers copy];
+ // Use native implementation on >= mountain lion
+ Class byteFormatterClass = NSClassFromString(@"NSByteCountFormatter");
+ if (byteFormatterClass && [byteFormatterClass respondsToSelector:@selector(stringFromByteCount:countStyle:)]) {
+ return [byteFormatterClass stringFromByteCount:byteCount countStyle:NSByteCountFormatterCountStyleFile];
+ }
- return self;
-}
+ float devider = 0.;
+ float returnValue = 0.;
+ NSString *suffix;
-- (NSString*)stringForObjectValue:(id)obj
-{
- return obj;
-}
+ NSNumberFormatter *theFormatter = [[NSNumberFormatter alloc] init];
+ [theFormatter setLocale:[NSLocale currentLocale]];
+ [theFormatter setAllowsFloats:YES];
-- (BOOL)getObjectValue:(id*)obj forString:(NSString*)string errorDescription:(NSString**)error
-{
- *obj = [[string copy] autorelease];
- return YES;
-}
+ NSString *returnString = @"";
-- (bool)isPartialStringValid:(NSString*)partialString newEditingString:(NSString**)newString errorDescription:(NSString**)error
-{
- if ([partialString rangeOfCharacterFromSet:o_forbidden_characters options:NSLiteralSearch].location != NSNotFound) {
- return NO;
- } else {
- return YES;
+ if (countStyle != NSByteCountFormatterCountStyleDecimal)
+ devider = 1024.;
+ else
+ devider = 1000.;
+
+ if (byteCount < 1000) {
+ returnValue = byteCount;
+ suffix = _NS("B");
+ [theFormatter setMaximumFractionDigits:0];
+ goto end;
}
-}
+ if (byteCount < 1000000) {
+ returnValue = byteCount / devider;
+ suffix = _NS("KB");
+ [theFormatter setMaximumFractionDigits:0];
+ goto end;
+ }
+
+ if (byteCount < 1000000000) {
+ returnValue = byteCount / devider / devider;
+ suffix = _NS("MB");
+ [theFormatter setMaximumFractionDigits:1];
+ goto end;
+ }
+
+ [theFormatter setMaximumFractionDigits:2];
+ if (byteCount < 1000000000000) {
+ returnValue = byteCount / devider / devider / devider;
+ suffix = _NS("GB");
+ goto end;
+ }
+
+ returnValue = byteCount / devider / devider / devider / devider;
+ suffix = _NS("TB");
+
+end:
+ returnString = [NSString stringWithFormat:@"%@ %@", [theFormatter stringFromNumber:[NSNumber numberWithFloat:returnValue]], suffix];
+ [theFormatter release];
+
+ return returnString;
+}
@end