]> git.sesse.net Git - vlc/blob - modules/gui/macosx/misc.m
* collection of various fixes and edits
[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     return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] ||
51            [(VLCControls *)[[VLCMain sharedInstance] getControls] keyEvent:o_event];
52 }
53
54 @end
55
56
57
58 /*****************************************************************************
59  * VLCControllerView
60  *****************************************************************************/
61
62 @implementation VLCControllerView
63
64 - (void)dealloc
65 {
66     [self unregisterDraggedTypes];
67     [super dealloc];
68 }
69
70 #if GC_ENABLED
71 - (void)finalize
72 {
73     /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */
74     [self unregisterDraggedTypes];
75     [super finalize];
76 }
77 #endif
78
79 - (void)awakeFromNib
80 {
81     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, 
82         NSFilenamesPboardType, nil]];
83 }
84
85 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
86 {
87     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) 
88                 == NSDragOperationGeneric)
89     {
90         return NSDragOperationGeneric;
91     }
92     else
93     {
94         return NSDragOperationNone;
95     }
96 }
97
98 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
99 {
100     return YES;
101 }
102
103 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
104 {
105     NSPasteboard *o_paste = [sender draggingPasteboard];
106     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
107     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
108     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
109
110     if( o_carried_data )
111     {
112         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
113         {
114             int i;
115             NSArray *o_array = [NSArray array];
116             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
117                         sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
118
119             for( i = 0; i < (int)[o_values count]; i++)
120             {
121                 NSDictionary *o_dic;
122                 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
123                 o_array = [o_array arrayByAddingObject: o_dic];
124             }
125             [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO];
126             return YES;
127         }
128     }
129     [self setNeedsDisplay:YES];
130     return YES;
131 }
132
133 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
134 {
135     [self setNeedsDisplay:YES];
136 }
137
138 @end
139
140 /*****************************************************************************
141  * VLBrushedMetalImageView
142  *****************************************************************************/
143
144 @implementation VLBrushedMetalImageView
145
146 - (BOOL)mouseDownCanMoveWindow
147 {
148     return YES;
149 }
150
151 - (void)dealloc
152 {
153     [self unregisterDraggedTypes];
154     [super dealloc];
155 }
156
157 #if GC_ENABLED
158 - (void)finalize
159 {
160     /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */
161     [self unregisterDraggedTypes];
162     [super finalize];
163 }
164 #endif
165
166 - (void)awakeFromNib
167 {
168     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, 
169         NSFilenamesPboardType, nil]];
170 }
171
172 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
173 {
174     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) 
175                 == NSDragOperationGeneric)
176     {
177         return NSDragOperationGeneric;
178     }
179     else
180     {
181         return NSDragOperationNone;
182     }
183 }
184
185 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
186 {
187     return YES;
188 }
189
190 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
191 {
192     NSPasteboard *o_paste = [sender draggingPasteboard];
193     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
194     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
195     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
196     BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
197
198     if( o_carried_data )
199     {
200         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
201         {
202             int i;
203             NSArray *o_array = [NSArray array];
204             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
205                         sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
206
207             for( i = 0; i < (int)[o_values count]; i++)
208             {
209                 NSDictionary *o_dic;
210                 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
211                 o_array = [o_array arrayByAddingObject: o_dic];
212             }
213             if( b_autoplay )
214                 [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO];
215             else
216                 [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:YES];
217             return YES;
218         }
219     }
220     [self setNeedsDisplay:YES];
221     return YES;
222 }
223
224 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
225 {
226     [self setNeedsDisplay:YES];
227 }
228
229 @end
230
231
232 /*****************************************************************************
233  * MPSlider
234  *****************************************************************************/
235 @implementation MPSlider
236
237 void _drawKnobInRect(NSRect knobRect)
238 {
239     // Center knob in given rect
240     knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0);
241     knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0);
242     
243     // Draw diamond
244     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver);
245     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver);
246     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver);
247     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver);
248     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver);
249     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver);
250     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver);
251 }
252
253 void _drawFrameInRect(NSRect frameRect)
254 {
255     // Draw frame
256     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver);
257     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver);
258     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
259     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
260 }
261
262 - (void)drawRect:(NSRect)rect
263 {
264     // Draw default to make sure the slider behaves correctly
265     [[NSGraphicsContext currentContext] saveGraphicsState];
266     NSRectClip(NSZeroRect);
267     [super drawRect:rect];
268     [[NSGraphicsContext currentContext] restoreGraphicsState];
269     
270     // Full size
271     rect = [self bounds];
272     int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1;
273     rect.origin.x += diff-1;
274     rect.origin.y += diff;
275     rect.size.width -= 2*diff-2;
276     rect.size.height -= 2*diff;
277     
278     // Draw dark
279     NSRect knobRect = [[self cell] knobRectFlipped:NO];
280     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
281     _drawFrameInRect(rect);
282     _drawKnobInRect(knobRect);
283     
284     // Draw shadow
285     [[[NSColor blackColor] colorWithAlphaComponent:0.1] set];
286     rect.origin.x++;
287     rect.origin.y++;
288     knobRect.origin.x++;
289     knobRect.origin.y++;
290     _drawFrameInRect(rect);
291     _drawKnobInRect(knobRect);
292 }
293
294 @end
295
296
297 /*****************************************************************************
298  * ITSlider
299  *****************************************************************************/
300
301 @implementation ITSlider
302
303 - (void)awakeFromNib
304 {
305     if ([[self cell] class] != [ITSliderCell class]) {
306         // replace cell
307         NSSliderCell *oldCell = [self cell];
308         NSSliderCell *newCell = [[[ITSliderCell alloc] init] autorelease];
309         [newCell setTag:[oldCell tag]];
310         [newCell setTarget:[oldCell target]];
311         [newCell setAction:[oldCell action]];
312         [newCell setControlSize:[oldCell controlSize]];
313         [newCell setType:[oldCell type]];
314         [newCell setState:[oldCell state]]; 
315         [newCell setAllowsTickMarkValuesOnly:[oldCell allowsTickMarkValuesOnly]];
316         [newCell setAltIncrementValue:[oldCell altIncrementValue]];
317         [newCell setControlTint:[oldCell controlTint]];
318         [newCell setKnobThickness:[oldCell knobThickness]];
319         [newCell setMaxValue:[oldCell maxValue]];
320         [newCell setMinValue:[oldCell minValue]];
321         [newCell setDoubleValue:[oldCell doubleValue]];
322         [newCell setNumberOfTickMarks:[oldCell numberOfTickMarks]];
323         [newCell setEditable:[oldCell isEditable]];
324         [newCell setEnabled:[oldCell isEnabled]];
325         [newCell setEntryType:[oldCell entryType]];
326         [newCell setHighlighted:[oldCell isHighlighted]];
327         [newCell setTickMarkPosition:[oldCell tickMarkPosition]];
328         [self setCell:newCell];
329     }
330 }
331
332 @end
333
334 /*****************************************************************************
335  * ITSliderCell
336  *****************************************************************************/
337 @implementation ITSliderCell
338
339 - (id)init
340 {
341     self = [super init];
342     _knobOff = [[NSImage imageNamed:@"volumeslider_normal"] retain];
343     _knobOn = [[NSImage imageNamed:@"volumeslider_blue"] retain];
344     b_mouse_down = FALSE;
345     return self;
346 }
347
348 - (void)dealloc
349 {
350     [_knobOff release];
351     [_knobOn release];
352     [super dealloc];
353 }
354
355 - (void)drawKnob:(NSRect)knob_rect
356 {
357     NSImage *knob;
358
359     if( b_mouse_down )
360         knob = _knobOn;
361     else
362         knob = _knobOff;
363
364     [[self controlView] lockFocus];
365     [knob compositeToPoint:NSMakePoint( knob_rect.origin.x + 1,
366         knob_rect.origin.y + knob_rect.size.height -2 )  
367         operation:NSCompositeSourceOver];
368     [[self controlView] unlockFocus];
369 }
370
371 - (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView: 
372         (NSView *)controlView mouseIsUp:(BOOL)flag
373 {
374     b_mouse_down = NO;
375     [self drawKnob];
376     [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
377 }
378
379 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
380 {
381     b_mouse_down = YES;
382     [self drawKnob];
383     return [super startTrackingAt:startPoint inView:controlView];
384 }
385
386 @end
387