]> git.sesse.net Git - vlc/blob - projects/macosx/vlc_app/Sources/VLCAppAdditions.m
vlc_app: New media layer view. Enabled by default. Set bindings from resources. ...
[vlc] / projects / macosx / vlc_app / Sources / VLCAppAdditions.m
1 /*****************************************************************************
2  * VLCAppAdditions.m: Helpful additions to NS* classes
3  *****************************************************************************
4  * Copyright (C) 2007 Pierre d'Herbemont
5  * Copyright (C) 2007 the VideoLAN team
6  * $Id$
7  *
8  * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
9  *          Felix Kühne <fkuehne at videolan dot org>
10  *          Jérôme Decoodt <djc at videolan dot org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #import "VLCAppAdditions.h"
28 #import <QuartzCore/QuartzCore.h>
29
30 @implementation NSIndexPath (VLCAppAddition)
31 - (NSIndexPath *)indexPathByRemovingFirstIndex
32 {
33     if( [self length] <= 1 )
34         return [[[NSIndexPath alloc] init] autorelease];
35
36     NSIndexPath * ret;
37     NSUInteger * ints = malloc(sizeof(NSUInteger)*[self length]);
38     if( !ints ) return nil;
39     [self getIndexes:ints];
40
41     ret = [NSIndexPath indexPathWithIndexes:ints+1 length:[self length]-1];
42
43     free(ints);
44     return ret;
45 }
46 - (NSUInteger)lastIndex
47 {
48     if(![self length])
49         return 0;
50     return [self indexAtPosition:[self length]-1];
51 }
52 @end
53
54 @implementation NSArray (VLCAppAddition)
55 - (id)objectAtIndexPath:(NSIndexPath *)path withNodeKeyPath:(NSString *)nodeKeyPath
56 {
57     if( ![path length] || !nodeKeyPath )
58         return self;
59
60     id object = [self objectAtIndex:[path indexAtPosition:0]];
61     id subarray = [object valueForKeyPath:nodeKeyPath];
62     if([path length] == 1)
63         return subarray ? subarray : object;
64
65     if(!subarray)
66         return object;
67     return [subarray objectAtIndexPath:[path indexPathByRemovingFirstIndex] withNodeKeyPath:nodeKeyPath];
68 }
69 @end
70
71 @implementation NSView (VLCAppAdditions)
72 - (void)moveSubviewsToVisible
73 {
74     for(NSView * view in [self subviews])
75     {
76         if( ([view autoresizingMask] & NSViewHeightSizable) &&
77             !NSContainsRect([view frame], [self bounds]) )
78         {
79             NSRect newFrame = NSIntersectionRect( [self bounds], [view frame] );
80             if( !NSIsEmptyRect(newFrame) )
81                 [view setFrame:NSIntersectionRect( [self bounds], [view frame] )];
82         }
83     }
84 }
85 @end
86
87 /* Split view that supports slider animation */
88 @implementation VLCOneSplitView
89 - (CGFloat)dividerThickness
90 {
91     return 1.;
92 }
93 - (void)drawDividerInRect:(NSRect)aRect
94 {
95     [self lockFocus];
96     [[NSColor blackColor] set];
97     NSRectFill(aRect);
98     [self unlockFocus];
99 }
100 - (float)sliderPosition
101 {
102     NSSize size = [[[self subviews] objectAtIndex:0] frame].size;
103     return [self isVertical] ? size.width : size.height;
104 }
105 - (void)setSliderPosition:(float)newPosition
106 {
107     [self setPosition:newPosition ofDividerAtIndex:0];
108 }
109 + (id)defaultAnimationForKey:(NSString *)key
110 {
111     if([key isEqualToString:@"sliderPosition"])
112     {
113         return [CABasicAnimation animation];
114     }
115     return [super defaultAnimationForKey: key];
116 }
117 @end
118
119 /*****************************************************************************
120  * NSScreen (VLCAdditions)
121  *
122  *  Missing extension to NSScreen
123  *****************************************************************************/
124
125 @implementation NSScreen (VLCAdditions)
126
127 static NSMutableArray *blackoutWindows = NULL;
128
129 + (void)load
130 {
131     /* init our fake object attribute */
132     blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1];
133 }
134
135 + (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID
136 {
137     int i;
138  
139     for( i = 0; i < [[NSScreen screens] count]; i++ )
140     {
141         NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
142         if([screen displayID] == displayID)
143             return screen;
144     }
145     return nil;
146 }
147
148 - (BOOL)isMainScreen
149 {
150     return ([self displayID] == [[[NSScreen screens] objectAtIndex:0] displayID]);
151 }
152
153 - (BOOL)isScreen: (NSScreen*)screen
154 {
155     return ([self displayID] == [screen displayID]);
156 }
157
158 - (CGDirectDisplayID)displayID
159 {
160     return (CGDirectDisplayID)_screenNumber;
161 }
162
163 - (void)blackoutOtherScreens
164 {
165     unsigned int i;
166
167     /* Free our previous blackout window (follow blackoutWindow alloc strategy) */
168     [blackoutWindows makeObjectsPerformSelector:@selector(close)];
169     [blackoutWindows removeAllObjects];
170
171  
172     for(i = 0; i < [[NSScreen screens] count]; i++)
173     {
174         NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
175         VLCWindow *blackoutWindow;
176         NSRect screen_rect;
177  
178         if([self isScreen: screen])
179             continue;
180
181         screen_rect = [screen frame];
182         screen_rect.origin.x = screen_rect.origin.y = 0.0f;
183
184         /* blackoutWindow alloc strategy
185             - The NSMutableArray blackoutWindows has the blackoutWindow references
186             - blackoutOtherDisplays is responsible for alloc/releasing its Windows
187         */
188         blackoutWindow = [[VLCWindow alloc] initWithContentRect: screen_rect styleMask: NSBorderlessWindowMask
189                 backing: NSBackingStoreBuffered defer: NO screen: screen];
190         [blackoutWindow setBackgroundColor:[NSColor blackColor]];
191         [blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */
192  
193         [blackoutWindow orderFront: self];
194
195         [blackoutWindows addObject: blackoutWindow];
196         [blackoutWindow release];
197     }
198 }
199
200 + (void)unblackoutScreens
201 {
202     unsigned int i;
203
204     for(i = 0; i < [blackoutWindows count]; i++)
205     {
206         VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex: i];
207         [blackoutWindow close];
208     }
209 }
210
211 @end
212
213 /*****************************************************************************
214  * VLCWindow
215  *
216  *  Missing extension to NSWindow
217  *****************************************************************************/
218
219 @implementation VLCWindow
220 - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask
221     backing:(NSBackingStoreType)backingType defer:(BOOL)flag
222 {
223     self = [super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag];
224     if( self )
225         isset_canBecomeKeyWindow = NO;
226     return self;
227 }
228 - (void)setCanBecomeKeyWindow: (BOOL)canBecomeKey
229 {
230     isset_canBecomeKeyWindow = YES;
231     canBecomeKeyWindow = canBecomeKey;
232 }
233
234 - (BOOL)canBecomeKeyWindow
235 {
236     if(isset_canBecomeKeyWindow)
237         return canBecomeKeyWindow;
238
239     return [super canBecomeKeyWindow];
240 }
241 @end
242
243 /*****************************************************************************
244  * VLCImageCustomizedSlider
245  *
246  *  Slider personalized by backgroundImage and knobImage
247  *****************************************************************************/
248 @implementation VLCImageCustomizedSlider
249 @synthesize backgroundImage;
250 @synthesize knobImage;
251
252 - (id)initWithFrame:(NSRect)frame
253 {
254     if(self = [super initWithFrame:frame])
255     {
256         knobImage = nil;
257         backgroundImage = nil;
258     }
259     return self;
260 }
261
262 - (void)dealloc
263 {
264     [knobImage release];
265     [knobImage release];
266     [super dealloc];
267 }
268
269 - (void)drawKnobInRect:(NSRect) knobRect
270 {
271     NSRect imageRect;
272     imageRect.size = [self.knobImage size];
273     imageRect.origin.x = 0;
274     imageRect.origin.y = 0;
275     knobRect.origin.x += (knobRect.size.width - imageRect.size.width) / 2;
276     knobRect.origin.y += (knobRect.size.width - imageRect.size.width) / 2;
277     knobRect.size.width = imageRect.size.width;
278     knobRect.size.height = imageRect.size.height;
279     [self.knobImage drawInRect:knobRect fromRect:imageRect operation:NSCompositeSourceOver fraction:1];
280 }
281
282 - (void)drawBackgroundInRect:(NSRect) drawRect
283 {
284     NSRect imageRect = drawRect;
285     imageRect.origin.y += ([self.backgroundImage size].height - [self bounds].size.height ) / 2;
286     [self.backgroundImage drawInRect:drawRect fromRect:imageRect operation:NSCompositeSourceOver fraction:1];
287 }
288
289 - (void)drawRect:(NSRect)rect
290 {
291     /* Draw default to make sure the slider behaves correctly */
292     [[NSGraphicsContext currentContext] saveGraphicsState];
293     NSRectClip(NSZeroRect);
294     [super drawRect:rect];
295     [[NSGraphicsContext currentContext] restoreGraphicsState];
296     if( self.backgroundImage ) 
297         [self drawBackgroundInRect: rect];
298     if( self.knobImage ) 
299     {
300         NSRect knobRect = [[self cell] knobRectFlipped:NO];
301         [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
302         [self drawKnobInRect: knobRect];
303     }
304 }
305
306 @end
307
308 /*****************************************************************************
309  * NSImageView (VLCAppAdditions)
310  *
311  *  Make the image view  move the window by mouse down by default
312  *****************************************************************************/
313
314 @implementation NSImageView (VLCAppAdditions)
315 - (BOOL)mouseDownCanMoveWindow
316 {
317     return YES;
318 }
319 @end
320
321 /*****************************************************************************
322  * NSImage (VLCAppAdditions)
323  *
324  *  Make the image view move the window by mouse down by default
325  *****************************************************************************/
326
327 @implementation NSImage (VLCAppAdditions)
328 - (CGImageRef)CGImage
329 {
330     return [[NSBitmapImageRep imageRepWithData:[NSBitmapImageRep TIFFRepresentationOfImageRepsInArray: [self representations]]] CGImage];
331 }
332 @end
333
334