]> git.sesse.net Git - vlc/blob - modules/gui/macosx/misc.m
* fixed a bug which prevented the fspanel to show up in some circumstances. Patch...
[vlc] / modules / gui / macosx / misc.m
1 /*****************************************************************************
2  * misc.m: code not specific to vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include <Cocoa/Cocoa.h>
25
26 #include "intf.h"                                          /* VLCApplication */
27 #include "misc.h"
28 #include "playlist.h"
29 #include "controls.h"
30
31 /*****************************************************************************
32  * VLCControllerWindow
33  *****************************************************************************/
34
35 @implementation VLCControllerWindow
36
37 - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask
38     backing:(NSBackingStoreType)backingType defer:(BOOL)flag
39 {
40     self = [super initWithContentRect:contentRect styleMask:styleMask //& ~NSTitledWindowMask
41     backing:backingType defer:flag];
42
43     [[VLCMain sharedInstance] updateTogglePlaylistState];
44
45     return( self );
46 }
47
48 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
49 {
50     /* We indeed want to prioritize Cocoa key equivalent against libvlc,
51        so we perform the menu equivalent now. */
52     if([[NSApp mainMenu] performKeyEquivalent:o_event])
53         return TRUE;
54
55     return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] ||
56            [(VLCControls *)[[VLCMain sharedInstance] getControls] keyEvent:o_event];
57 }
58
59 @end
60
61
62
63 /*****************************************************************************
64  * VLCControllerView
65  *****************************************************************************/
66
67 @implementation VLCControllerView
68
69 - (void)dealloc
70 {
71     [self unregisterDraggedTypes];
72     [super dealloc];
73 }
74
75 #if GC_ENABLED
76 - (void)finalize
77 {
78     /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */
79     [self unregisterDraggedTypes];
80     [super finalize];
81 }
82 #endif
83
84 - (void)awakeFromNib
85 {
86     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, 
87         NSFilenamesPboardType, nil]];
88 }
89
90 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
91 {
92     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) 
93                 == NSDragOperationGeneric)
94     {
95         return NSDragOperationGeneric;
96     }
97     else
98     {
99         return NSDragOperationNone;
100     }
101 }
102
103 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
104 {
105     return YES;
106 }
107
108 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
109 {
110     NSPasteboard *o_paste = [sender draggingPasteboard];
111     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
112     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
113     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
114
115     if( o_carried_data )
116     {
117         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
118         {
119             int i;
120             NSArray *o_array = [NSArray array];
121             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
122                         sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
123
124             for( i = 0; i < (int)[o_values count]; i++)
125             {
126                 NSDictionary *o_dic;
127                 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
128                 o_array = [o_array arrayByAddingObject: o_dic];
129             }
130             [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO];
131             return YES;
132         }
133     }
134     [self setNeedsDisplay:YES];
135     return YES;
136 }
137
138 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
139 {
140     [self setNeedsDisplay:YES];
141 }
142
143 @end
144
145 /*****************************************************************************
146  * VLBrushedMetalImageView
147  *****************************************************************************/
148
149 @implementation VLBrushedMetalImageView
150
151 - (BOOL)mouseDownCanMoveWindow
152 {
153     return YES;
154 }
155
156 - (void)dealloc
157 {
158     [self unregisterDraggedTypes];
159     [super dealloc];
160 }
161
162 #if GC_ENABLED
163 - (void)finalize
164 {
165     /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */
166     [self unregisterDraggedTypes];
167     [super finalize];
168 }
169 #endif
170
171 - (void)awakeFromNib
172 {
173     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, 
174         NSFilenamesPboardType, nil]];
175 }
176
177 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
178 {
179     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) 
180                 == NSDragOperationGeneric)
181     {
182         return NSDragOperationGeneric;
183     }
184     else
185     {
186         return NSDragOperationNone;
187     }
188 }
189
190 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
191 {
192     return YES;
193 }
194
195 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
196 {
197     NSPasteboard *o_paste = [sender draggingPasteboard];
198     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
199     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
200     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
201     BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
202
203     if( o_carried_data )
204     {
205         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
206         {
207             int i;
208             NSArray *o_array = [NSArray array];
209             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
210                         sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
211
212             for( i = 0; i < (int)[o_values count]; i++)
213             {
214                 NSDictionary *o_dic;
215                 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
216                 o_array = [o_array arrayByAddingObject: o_dic];
217             }
218             if( b_autoplay )
219                 [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO];
220             else
221                 [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:YES];
222             return YES;
223         }
224     }
225     [self setNeedsDisplay:YES];
226     return YES;
227 }
228
229 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
230 {
231     [self setNeedsDisplay:YES];
232 }
233
234 @end
235
236
237 /*****************************************************************************
238  * MPSlider
239  *****************************************************************************/
240 @implementation MPSlider
241
242 void _drawKnobInRect(NSRect knobRect)
243 {
244     // Center knob in given rect
245     knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0);
246     knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0);
247     
248     // Draw diamond
249     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver);
250     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver);
251     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver);
252     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver);
253     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver);
254     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver);
255     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver);
256 }
257
258 void _drawFrameInRect(NSRect frameRect)
259 {
260     // Draw frame
261     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver);
262     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver);
263     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
264     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
265 }
266
267 - (void)drawRect:(NSRect)rect
268 {
269     // Draw default to make sure the slider behaves correctly
270     [[NSGraphicsContext currentContext] saveGraphicsState];
271     NSRectClip(NSZeroRect);
272     [super drawRect:rect];
273     [[NSGraphicsContext currentContext] restoreGraphicsState];
274     
275     // Full size
276     rect = [self bounds];
277     int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1;
278     rect.origin.x += diff-1;
279     rect.origin.y += diff;
280     rect.size.width -= 2*diff-2;
281     rect.size.height -= 2*diff;
282     
283     // Draw dark
284     NSRect knobRect = [[self cell] knobRectFlipped:NO];
285     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
286     _drawFrameInRect(rect);
287     _drawKnobInRect(knobRect);
288     
289     // Draw shadow
290     [[[NSColor blackColor] colorWithAlphaComponent:0.1] set];
291     rect.origin.x++;
292     rect.origin.y++;
293     knobRect.origin.x++;
294     knobRect.origin.y++;
295     _drawFrameInRect(rect);
296     _drawKnobInRect(knobRect);
297 }
298
299 @end
300
301
302 /*****************************************************************************
303  * ITSlider
304  *****************************************************************************/
305
306 @implementation ITSlider
307
308 - (void)awakeFromNib
309 {
310     if ([[self cell] class] != [ITSliderCell class]) {
311         // replace cell
312         NSSliderCell *oldCell = [self cell];
313         NSSliderCell *newCell = [[[ITSliderCell alloc] init] autorelease];
314         [newCell setTag:[oldCell tag]];
315         [newCell setTarget:[oldCell target]];
316         [newCell setAction:[oldCell action]];
317         [newCell setControlSize:[oldCell controlSize]];
318         [newCell setType:[oldCell type]];
319         [newCell setState:[oldCell state]]; 
320         [newCell setAllowsTickMarkValuesOnly:[oldCell allowsTickMarkValuesOnly]];
321         [newCell setAltIncrementValue:[oldCell altIncrementValue]];
322         [newCell setControlTint:[oldCell controlTint]];
323         [newCell setKnobThickness:[oldCell knobThickness]];
324         [newCell setMaxValue:[oldCell maxValue]];
325         [newCell setMinValue:[oldCell minValue]];
326         [newCell setDoubleValue:[oldCell doubleValue]];
327         [newCell setNumberOfTickMarks:[oldCell numberOfTickMarks]];
328         [newCell setEditable:[oldCell isEditable]];
329         [newCell setEnabled:[oldCell isEnabled]];
330         [newCell setEntryType:[oldCell entryType]];
331         [newCell setHighlighted:[oldCell isHighlighted]];
332         [newCell setTickMarkPosition:[oldCell tickMarkPosition]];
333         [self setCell:newCell];
334     }
335 }
336
337 @end
338
339 /*****************************************************************************
340  * ITSliderCell
341  *****************************************************************************/
342 @implementation ITSliderCell
343
344 - (id)init
345 {
346     self = [super init];
347     _knobOff = [[NSImage imageNamed:@"volumeslider_normal"] retain];
348     _knobOn = [[NSImage imageNamed:@"volumeslider_blue"] retain];
349     b_mouse_down = FALSE;
350     return self;
351 }
352
353 - (void)dealloc
354 {
355     [_knobOff release];
356     [_knobOn release];
357     [super dealloc];
358 }
359
360 - (void)drawKnob:(NSRect)knob_rect
361 {
362     NSImage *knob;
363
364     if( b_mouse_down )
365         knob = _knobOn;
366     else
367         knob = _knobOff;
368
369     [[self controlView] lockFocus];
370     [knob compositeToPoint:NSMakePoint( knob_rect.origin.x + 1,
371         knob_rect.origin.y + knob_rect.size.height -2 )  
372         operation:NSCompositeSourceOver];
373     [[self controlView] unlockFocus];
374 }
375
376 - (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView: 
377         (NSView *)controlView mouseIsUp:(BOOL)flag
378 {
379     b_mouse_down = NO;
380     [self drawKnob];
381     [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
382 }
383
384 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
385 {
386     b_mouse_down = YES;
387     [self drawKnob];
388     return [super startTrackingAt:startPoint inView:controlView];
389 }
390
391 @end
392