1 /*****************************************************************************
2 * VLCUIWidgets.m: Widgets for VLC's extensions dialogs for Mac OS X
3 *****************************************************************************
4 * Copyright (C) 2009-2014 the VideoLAN team and authors
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan dot>,
8 * Brendon Justin <brendonjustin@gmail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #import "CompatibilityFixes.h"
26 #import "VLCUIWidgets.h"
30 @implementation VLCDialogButton
35 @implementation VLCDialogPopUpButton
40 @implementation VLCDialogTextField
45 @implementation VLCDialogWindow
51 @implementation VLCDialogList
53 @synthesize contentArray;
55 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
57 return [contentArray count];
60 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
62 return [[contentArray objectAtIndex:rowIndex] objectForKey:@"text"];
67 @implementation VLCDialogGridView
69 - (NSUInteger)numViews
71 return [_griddedViews count];
76 if ((self = [super init])) {
79 _griddedViews = [[NSMutableArray alloc] init];
86 [_griddedViews release];
90 - (void)recomputeCount
94 for (NSDictionary *obj in _griddedViews) {
95 NSUInteger row = [[obj objectForKey:@"row"] intValue];
96 NSUInteger col = [[obj objectForKey:@"col"] intValue];
97 if (col + 1 > _colCount)
99 if (row + 1 > _rowCount)
104 - (void)recomputeWindowSize
106 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(recomputeWindowSize) object:nil];
108 NSWindow *window = [self window];
109 NSRect frame = [window frame];
110 NSRect contentRect = [window contentRectForFrameRect:frame];
111 contentRect.size = [self flexSize:frame.size];
112 NSRect newFrame = [window frameRectForContentRect:contentRect];
113 newFrame.origin.y -= newFrame.size.height - frame.size.height;
114 newFrame.origin.x -= (newFrame.size.width - frame.size.width) / 2;
115 [window setFrame:newFrame display:YES animate:YES];
118 - (NSSize)objectSizeToFit:(NSView *)view
120 if ([view isKindOfClass:[NSControl class]]) {
121 NSControl *control = (NSControl *)view;
122 return [[control cell] cellSize];
124 return [view frame].size;
136 - (CGFloat)constrainedHeightOfRow:(NSUInteger)targetRow
139 for(NSDictionary *obj in _griddedViews) {
140 NSUInteger row = [[obj objectForKey:@"row"] intValue];
141 if (row != targetRow)
143 NSUInteger rowSpan = [[obj objectForKey:@"rowSpan"] intValue];
146 NSView *view = [obj objectForKey:@"view"];
147 if ([view autoresizingMask] & NSViewHeightSizable)
149 NSSize sizeToFit = [self objectSizeToFit:view];
150 if (height < sizeToFit.height)
151 height = sizeToFit.height;
156 - (CGFloat)remainingRowsHeight
158 NSUInteger height = [self marginY];
161 NSUInteger autosizedRows = 0;
162 for (NSUInteger i = 0; i < _rowCount; i++) {
163 CGFloat constrainedHeight = [self constrainedHeightOfRow:i];
164 if (!constrainedHeight)
166 height += constrainedHeight + [self marginY];
168 CGFloat remaining = 0;
169 if (height < self.bounds.size.height && autosizedRows)
170 remaining = (self.bounds.size.height - height) / autosizedRows;
177 - (CGFloat)heightOfRow:(NSUInteger)targetRow
179 NSAssert(targetRow < _rowCount, @"accessing a non existing row");
180 CGFloat height = [self constrainedHeightOfRow:targetRow];
182 height = [self remainingRowsHeight];
187 - (CGFloat)topOfRow:(NSUInteger)targetRow
189 CGFloat top = [self marginY];
190 for (NSUInteger i = 1; i < _rowCount - targetRow; i++)
191 top += [self heightOfRow:_rowCount - i] + [self marginY];
196 - (CGFloat)constrainedWidthOfColumn:(NSUInteger)targetColumn
199 for(NSDictionary *obj in _griddedViews) {
200 NSUInteger col = [[obj objectForKey:@"col"] intValue];
201 if (col != targetColumn)
203 NSUInteger colSpan = [[obj objectForKey:@"colSpan"] intValue];
206 NSView *view = [obj objectForKey:@"view"];
207 if ([view autoresizingMask] & NSViewWidthSizable)
209 NSSize sizeToFit = [self objectSizeToFit:view];
210 if (width < sizeToFit.width)
211 width = sizeToFit.width;
216 - (CGFloat)remainingColumnWidth
218 NSUInteger width = [self marginX];
221 NSUInteger autosizedCol = 0;
222 for (NSUInteger i = 0; i < _colCount; i++) {
223 CGFloat constrainedWidth = [self constrainedWidthOfColumn:i];
224 if (!constrainedWidth)
226 width += constrainedWidth + [self marginX];
228 CGFloat remaining = 0;
229 if (width < self.bounds.size.width && autosizedCol)
230 remaining = (self.bounds.size.width - width) / autosizedCol;
236 - (CGFloat)widthOfColumn:(NSUInteger)targetColumn
238 CGFloat width = [self constrainedWidthOfColumn:targetColumn];
240 width = [self remainingColumnWidth];
245 - (CGFloat)leftOfColumn:(NSUInteger)targetColumn
247 CGFloat left = [self marginX];
248 for (NSUInteger i = 0; i < targetColumn; i++) {
249 left += [self widthOfColumn:i] + [self marginX];
256 for(NSDictionary *obj in _griddedViews) {
257 NSUInteger row = [[obj objectForKey:@"row"] intValue];
258 NSUInteger col = [[obj objectForKey:@"col"] intValue];
259 NSUInteger rowSpan = [[obj objectForKey:@"rowSpan"] intValue];
260 NSUInteger colSpan = [[obj objectForKey:@"colSpan"] intValue];
261 NSView *view = [obj objectForKey:@"view"];
265 if ([view autoresizingMask] & NSViewHeightSizable || rowSpan > 1) {
267 for (NSUInteger r = 0; r < rowSpan; r++) {
268 if (row + r >= _rowCount)
270 height += [self heightOfRow:row + r] + [self marginY];
272 rect.size.height = height - [self marginY];
275 rect.size.height = [self objectSizeToFit:view].height;
278 if ([view autoresizingMask] & NSViewWidthSizable) {
280 for (NSUInteger c = 0; c < colSpan; c++)
281 width += [self widthOfColumn:col + c] + [self marginX];
282 rect.size.width = width - [self marginX];
285 rect.size.width = [self objectSizeToFit:view].width;
288 rect.origin.y = [self topOfRow:row] + ([self heightOfRow:row] - rect.size.height) / 2;
289 rect.origin.x = [self leftOfColumn:col];
291 [view setFrame:rect];
292 [view setNeedsDisplay:YES];
296 - (NSMutableDictionary *)objectForView:(NSView *)view
298 for (NSMutableDictionary *dict in _griddedViews)
300 if ([dict objectForKey:@"view"] == view)
306 - (void)addSubview:(NSView *)view atRow:(NSUInteger)row column:(NSUInteger)column
307 rowSpan:(NSUInteger)rowSpan
308 colSpan:(NSUInteger)colSpan
310 if (row + 1 > _rowCount)
312 if (column + 1 > _colCount)
313 _colCount = column + 1;
315 NSMutableDictionary *dict = [self objectForView:view];
317 dict = [NSMutableDictionary dictionary];
318 [dict setObject:view forKey:@"view"];
319 [_griddedViews addObject:dict];
321 [dict setObject:[NSNumber numberWithInt:rowSpan] forKey:@"rowSpan"];
322 [dict setObject:[NSNumber numberWithInt:colSpan] forKey:@"colSpan"];
323 [dict setObject:[NSNumber numberWithInt:row] forKey:@"row"];
324 [dict setObject:[NSNumber numberWithInt:column] forKey:@"col"];
326 [self addSubview:view];
329 // Recompute the size of the window after making sure we won't see anymore update
330 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(recomputeWindowSize) object:nil];
331 [self performSelector:@selector(recomputeWindowSize) withObject:nil afterDelay:0.1];
334 - (void)removeSubview:(NSView *)view
336 NSDictionary *dict = [self objectForView:view];
338 [_griddedViews removeObject:dict];
339 [view removeFromSuperview];
341 [self recomputeCount];
342 [self recomputeWindowSize];
345 [self setNeedsDisplay:YES];
348 - (void)setFrame:(NSRect)frameRect
350 [super setFrame:frameRect];
354 - (NSSize)flexSize:(NSSize)size
356 if (!_rowCount || !_colCount)
359 CGFloat minHeight = [self marginY];
360 BOOL canFlexHeight = NO;
361 for (NSUInteger i = 0; i < _rowCount; i++) {
362 CGFloat constrained = [self constrainedHeightOfRow:i];
367 minHeight += constrained + [self marginY];
370 CGFloat minWidth = [self marginX];
371 BOOL canFlexWidth = NO;
372 for (NSUInteger i = 0; i < _colCount; i++) {
373 CGFloat constrained = [self constrainedWidthOfColumn:i];
378 minWidth += constrained + [self marginX];
380 if (size.width < minWidth)
381 size.width = minWidth;
382 if (size.height < minHeight)
383 size.height = minHeight;
385 size.height = minHeight;
387 size.width = minWidth;