1 /*****************************************************************************
2 * VLCUIWidgets.m: Widgets for VLC's Minimal Dialog Provider for Mac OS X
3 *****************************************************************************
4 * Copyright (C) 2009-2010 the VideoLAN team
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan dot>
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.
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.
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 *****************************************************************************/
24 #import "VLCUIWidgets.h"
26 @implementation VLCDialogButton
31 @implementation VLCDialogPopUpButton
36 @implementation VLCDialogTextField
41 @implementation VLCDialogWindow
46 @implementation VLCDialogList
48 @synthesize contentArray;
50 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
52 return [contentArray count];
55 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
57 return [[contentArray objectAtIndex:rowIndex] objectForKey:@"text"];
62 @implementation VLCDialogGridView
66 [_gridedViews release];
70 - (void)recomputeCount
74 for (NSDictionary *obj in _gridedViews)
76 NSUInteger row = [[obj objectForKey:@"row"] intValue];
77 NSUInteger col = [[obj objectForKey:@"col"] intValue];
78 if (col + 1 > _colCount)
80 if (row + 1 > _rowCount)
85 - (void)recomputeWindowSize
87 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(recomputeWindowSize) object:nil];
89 NSWindow *window = [self window];
90 NSRect frame = [window frame];
91 NSRect contentRect = [window contentRectForFrameRect:frame];
92 contentRect.size = [self flexSize:frame.size];
93 NSRect newFrame = [window frameRectForContentRect:contentRect];
94 newFrame.origin.y -= newFrame.size.height - frame.size.height;
95 newFrame.origin.x -= (newFrame.size.width - frame.size.width) / 2;
96 [window setFrame:newFrame display:YES animate:YES];
99 - (NSSize)objectSizeToFit:(NSView *)view
101 if ([view isKindOfClass:[NSControl class]]) {
102 NSControl *control = (NSControl *)view;
103 return [[control cell] cellSize];
105 return [view frame].size;
117 - (CGFloat)constrainedHeightOfRow:(NSUInteger)targetRow
120 for(NSDictionary *obj in _gridedViews) {
121 NSUInteger row = [[obj objectForKey:@"row"] intValue];
122 if (row != targetRow)
124 NSUInteger rowSpan = [[obj objectForKey:@"rowSpan"] intValue];
127 NSView *view = [obj objectForKey:@"view"];
128 if ([view autoresizingMask] & NSViewHeightSizable)
130 NSSize sizeToFit = [self objectSizeToFit:view];
131 if (height < sizeToFit.height)
132 height = sizeToFit.height;
137 - (CGFloat)remainingRowsHeight
139 NSUInteger height = [self marginY];
142 NSUInteger autosizedRows = 0;
143 for (NSUInteger i = 0; i < _rowCount; i++) {
144 CGFloat constrainedHeight = [self constrainedHeightOfRow:i];
145 if (!constrainedHeight)
147 height += constrainedHeight + [self marginY];
149 CGFloat remaining = 0;
150 if (height < self.bounds.size.height && autosizedRows)
151 remaining = (self.bounds.size.height - height) / autosizedRows;
158 - (CGFloat)heightOfRow:(NSUInteger)targetRow
160 NSAssert(targetRow < _rowCount, @"accessing a non existing row");
161 CGFloat height = [self constrainedHeightOfRow:targetRow];
163 height = [self remainingRowsHeight];
168 - (CGFloat)topOfRow:(NSUInteger)targetRow
170 CGFloat top = [self marginY];
171 for (NSUInteger i = 1; i < _rowCount - targetRow; i++)
173 top += [self heightOfRow:_rowCount - i] + [self marginY];
178 - (CGFloat)constrainedWidthOfColumn:(NSUInteger)targetColumn
181 for(NSDictionary *obj in _gridedViews) {
182 NSUInteger col = [[obj objectForKey:@"col"] intValue];
183 if (col != targetColumn)
185 NSUInteger colSpan = [[obj objectForKey:@"colSpan"] intValue];
188 NSView *view = [obj objectForKey:@"view"];
189 if ([view autoresizingMask] & NSViewWidthSizable)
191 NSSize sizeToFit = [self objectSizeToFit:view];
192 if (width < sizeToFit.width)
193 width = sizeToFit.width;
198 - (CGFloat)remainingColumnWidth
200 NSUInteger width = [self marginX];
203 NSUInteger autosizedCol = 0;
204 for (NSUInteger i = 0; i < _colCount; i++) {
205 CGFloat constrainedWidth = [self constrainedWidthOfColumn:i];
206 if (!constrainedWidth)
208 width += constrainedWidth + [self marginX];
211 CGFloat remaining = 0;
212 if (width < self.bounds.size.width && autosizedCol)
213 remaining = (self.bounds.size.width - width) / autosizedCol;
219 - (CGFloat)widthOfColumn:(NSUInteger)targetColumn
221 CGFloat width = [self constrainedWidthOfColumn:targetColumn];
223 width = [self remainingColumnWidth];
228 - (CGFloat)leftOfColumn:(NSUInteger)targetColumn
230 CGFloat left = [self marginX];
231 for (NSUInteger i = 0; i < targetColumn; i++)
233 left += [self widthOfColumn:i] + [self marginX];
241 for(NSDictionary *obj in _gridedViews) {
242 NSUInteger row = [[obj objectForKey:@"row"] intValue];
243 NSUInteger col = [[obj objectForKey:@"col"] intValue];
244 NSUInteger rowSpan = [[obj objectForKey:@"rowSpan"] intValue];
245 NSUInteger colSpan = [[obj objectForKey:@"colSpan"] intValue];
246 NSView *view = [obj objectForKey:@"view"];
250 if ([view autoresizingMask] & NSViewHeightSizable || rowSpan > 1) {
252 for (NSUInteger r = 0; r < rowSpan; r++) {
253 if (row + r >= _rowCount)
255 height += [self heightOfRow:row + r] + [self marginY];
257 rect.size.height = height - [self marginY];
260 rect.size.height = [self objectSizeToFit:view].height;
263 if ([view autoresizingMask] & NSViewWidthSizable) {
265 for (NSUInteger c = 0; c < colSpan; c++)
266 width += [self widthOfColumn:col + c] + [self marginX];
267 rect.size.width = width - [self marginX];
270 rect.size.width = [self objectSizeToFit:view].width;
273 rect.origin.y = [self topOfRow:row] + ([self heightOfRow:row] - rect.size.height) / 2;
274 rect.origin.x = [self leftOfColumn:col];
276 [view setFrame:rect];
277 [view setNeedsDisplay:YES];
281 - (NSMutableDictionary *)objectForView:(NSView *)view
283 for (NSMutableDictionary *dict in _gridedViews)
285 if ([dict objectForKey:@"view"] == view)
291 - (void)addSubview:(NSView *)view atRow:(NSUInteger)row column:(NSUInteger)column rowSpan:(NSUInteger)rowSpan colSpan:(NSUInteger)colSpan
293 if (row + 1 > _rowCount)
295 if (column + 1 > _colCount)
296 _colCount = column + 1;
299 _gridedViews = [[NSMutableArray alloc] init];
301 NSMutableDictionary *dict = [self objectForView:view];
303 dict = [NSMutableDictionary dictionary];
304 [dict setObject:view forKey:@"view"];
305 [_gridedViews addObject:dict];
307 [dict setObject:[NSNumber numberWithInt:rowSpan] forKey:@"rowSpan"];
308 [dict setObject:[NSNumber numberWithInt:colSpan] forKey:@"colSpan"];
309 [dict setObject:[NSNumber numberWithInt:row] forKey:@"row"];
310 [dict setObject:[NSNumber numberWithInt:column] forKey:@"col"];
313 [self addSubview:view];
316 // Recompute the size of the window after making sure we won't see anymore update
317 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(recomputeWindowSize) object:nil];
318 [self performSelector:@selector(recomputeWindowSize) withObject:nil afterDelay:0.1];
321 - (void)removeSubview:(NSView *)view
323 NSDictionary *dict = [self objectForView:view];
325 [_gridedViews removeObject:dict];
326 [view removeFromSuperview];
328 [self recomputeCount];
329 [self recomputeWindowSize];
332 [self setNeedsDisplay:YES];
335 - (void)setFrame:(NSRect)frameRect
337 [super setFrame:frameRect];
341 - (NSSize)flexSize:(NSSize)size
343 if (!_rowCount || !_colCount)
346 CGFloat minHeight = [self marginY];
347 BOOL canFlexHeight = NO;
348 for (NSUInteger i = 0; i < _rowCount; i++) {
349 CGFloat constrained = [self constrainedHeightOfRow:i];
354 minHeight += constrained + [self marginY];
357 CGFloat minWidth = [self marginX];
358 BOOL canFlexWidth = NO;
359 for (NSUInteger i = 0; i < _colCount; i++) {
360 CGFloat constrained = [self constrainedWidthOfColumn:i];
365 minWidth += constrained + [self marginX];
367 if (size.width < minWidth)
368 size.width = minWidth;
369 if (size.height < minHeight)
370 size.height = minHeight;
372 size.height = minHeight;
374 size.width = minWidth;