| 1 |
/* $Id$ */ |
|---|
| 2 |
|
|---|
| 3 |
/* |
|---|
| 4 |
* Copyright (c) 2007 Axel Andersson |
|---|
| 5 |
* All rights reserved. |
|---|
| 6 |
* |
|---|
| 7 |
* Redistribution and use in source and binary forms, with or without |
|---|
| 8 |
* modification, are permitted provided that the following conditions |
|---|
| 9 |
* are met: |
|---|
| 10 |
* 1. Redistributions of source code must retain the above copyright |
|---|
| 11 |
* notice, this list of conditions and the following disclaimer. |
|---|
| 12 |
* 2. Redistributions in binary form must reproduce the above copyright |
|---|
| 13 |
* notice, this list of conditions and the following disclaimer in the |
|---|
| 14 |
* documentation and/or other materials provided with the distribution. |
|---|
| 15 |
* |
|---|
| 16 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|---|
| 17 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|---|
| 18 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|---|
| 19 |
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
|---|
| 20 |
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|---|
| 21 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|---|
| 22 |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|---|
| 23 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|---|
| 24 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|---|
| 25 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|---|
| 26 |
* POSSIBILITY OF SUCH DAMAGE. |
|---|
| 27 |
*/ |
|---|
| 28 |
|
|---|
| 29 |
#import "FHApplicationController.h" |
|---|
| 30 |
#import "FHBrowserController.h" |
|---|
| 31 |
#import "FHFile.h" |
|---|
| 32 |
#import "FHImage.h" |
|---|
| 33 |
#import "FHInspectorController.h" |
|---|
| 34 |
|
|---|
| 35 |
@interface FHInspectorController(Private) |
|---|
| 36 |
|
|---|
| 37 |
- (void)_updateFromFile:(FHFile *)file; |
|---|
| 38 |
- (void)_updateValuesFromFile:(FHFile *)file; |
|---|
| 39 |
- (void)_setValue:(NSString *)value forKey:(NSString *)key; |
|---|
| 40 |
- (void)_relayoutFields; |
|---|
| 41 |
- (NSTextField *)_textFieldLikeTextField:(NSTextField *)archetypeTextField withStringValue:(NSString *)string; |
|---|
| 42 |
|
|---|
| 43 |
@end |
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
@implementation FHInspectorController(Private) |
|---|
| 47 |
|
|---|
| 48 |
- (void)_updateFromFile:(FHFile *)file { |
|---|
| 49 |
[_sortedKeys removeAllObjects]; |
|---|
| 50 |
[_allValues removeAllObjects]; |
|---|
| 51 |
|
|---|
| 52 |
[self _updateValuesFromFile:file]; |
|---|
| 53 |
[self _relayoutFields]; |
|---|
| 54 |
} |
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
- (void)_updateValuesFromFile:(FHFile *)file { |
|---|
| 59 |
NSEnumerator *enumerator, *dictionaryEnumerator; |
|---|
| 60 |
NSDictionary *properties, *dictionary; |
|---|
| 61 |
FHImage *image; |
|---|
| 62 |
NSString *key, *dictionaryKey, *dictionaryValue; |
|---|
| 63 |
|
|---|
| 64 |
image = [file image]; |
|---|
| 65 |
properties = [image properties]; |
|---|
| 66 |
|
|---|
| 67 |
[self _setValue:[file name] forKey:NSLS(@"File Name", @"Inspector label")]; |
|---|
| 68 |
|
|---|
| 69 |
if(image) { |
|---|
| 70 |
[self _setValue:[NSSWF:NSLS(@"%.0fx%.0f", @"'640x480'"), [image size].width, [image size].height] |
|---|
| 71 |
forKey:NSLS(@"Image Size", @"Inspector label")]; |
|---|
| 72 |
} |
|---|
| 73 |
|
|---|
| 74 |
if(properties) { |
|---|
| 75 |
if([properties floatForKey:(id) kCGImagePropertyDPIHeight] > 0.0) { |
|---|
| 76 |
[self _setValue:[NSSWF:@"%.2f", [properties floatForKey:(id) kCGImagePropertyDPIHeight]] |
|---|
| 77 |
forKey:NSLS(@"Image DPI", @"Inspector label")]; |
|---|
| 78 |
} |
|---|
| 79 |
|
|---|
| 80 |
[self _setValue:[NSString humanReadableStringForSizeInBytes:[image dataLength]] |
|---|
| 81 |
forKey:NSLS(@"File Size", @"Inspector label")]; |
|---|
| 82 |
[self _setValue:[properties objectForKey:(id) kCGImagePropertyColorModel] |
|---|
| 83 |
forKey:NSLS(@"Color Model", @"Inspector label")]; |
|---|
| 84 |
[self _setValue:[properties objectForKey:(id) kCGImagePropertyProfileName] |
|---|
| 85 |
forKey:NSLS(@"Profile Name", @"Inspector label")]; |
|---|
| 86 |
|
|---|
| 87 |
enumerator = [[NSArray arrayWithObjects: |
|---|
| 88 |
(id) kCGImagePropertyTIFFDictionary, |
|---|
| 89 |
(id) kCGImagePropertyGIFDictionary, |
|---|
| 90 |
(id) kCGImagePropertyJFIFDictionary, |
|---|
| 91 |
(id) kCGImagePropertyExifDictionary, |
|---|
| 92 |
(id) kCGImagePropertyPNGDictionary, |
|---|
| 93 |
(id) kCGImagePropertyIPTCDictionary, |
|---|
| 94 |
(id) kCGImagePropertyGPSDictionary, |
|---|
| 95 |
(id) kCGImagePropertyRawDictionary, |
|---|
| 96 |
(id) kCGImagePropertyCIFFDictionary, |
|---|
| 97 |
(id) kCGImageProperty8BIMDictionary, |
|---|
| 98 |
NULL] objectEnumerator]; |
|---|
| 99 |
|
|---|
| 100 |
while((key = [enumerator nextObject])) { |
|---|
| 101 |
dictionary = [properties objectForKey:key]; |
|---|
| 102 |
|
|---|
| 103 |
if([dictionary count] > 0) { |
|---|
| 104 |
[self _setValue:@"-" forKey:@"-"]; |
|---|
| 105 |
dictionaryEnumerator = [dictionary keyEnumerator]; |
|---|
| 106 |
|
|---|
| 107 |
while((dictionaryKey = [dictionaryEnumerator nextObject])) { |
|---|
| 108 |
dictionaryValue = [dictionary objectForKey:dictionaryKey]; |
|---|
| 109 |
|
|---|
| 110 |
[self _setValue:dictionaryValue forKey:dictionaryKey]; |
|---|
| 111 |
} |
|---|
| 112 |
} |
|---|
| 113 |
} |
|---|
| 114 |
} |
|---|
| 115 |
} |
|---|
| 116 |
|
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 |
- (void)_setValue:(NSString *)value forKey:(NSString *)key { |
|---|
| 120 |
if(key && value) { |
|---|
| 121 |
[_sortedKeys addObject:key]; |
|---|
| 122 |
[_allValues setObject:value forKey:key]; |
|---|
| 123 |
} |
|---|
| 124 |
} |
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 |
|
|---|
| 128 |
- (void)_relayoutFields { |
|---|
| 129 |
NSTextField *nameTextField, *valueTextField; |
|---|
| 130 |
NSView *contentView; |
|---|
| 131 |
NSEnumerator *enumerator; |
|---|
| 132 |
NSString *key, *value; |
|---|
| 133 |
NSRect windowFrame; |
|---|
| 134 |
NSSize nameSize, valueSize; |
|---|
| 135 |
CGFloat verticalOffset, height; |
|---|
| 136 |
|
|---|
| 137 |
verticalOffset = 20.0; |
|---|
| 138 |
contentView = [[self window] contentView]; |
|---|
| 139 |
enumerator = [_sortedKeys reverseObjectEnumerator]; |
|---|
| 140 |
|
|---|
| 141 |
[[contentView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; |
|---|
| 142 |
|
|---|
| 143 |
while((key = [enumerator nextObject])) { |
|---|
| 144 |
if([key isEqualToString:@"-"]) { |
|---|
| 145 |
verticalOffset += 16.0; |
|---|
| 146 |
|
|---|
| 147 |
continue; |
|---|
| 148 |
} |
|---|
| 149 |
|
|---|
| 150 |
value = [_allValues objectForKey:key]; |
|---|
| 151 |
|
|---|
| 152 |
nameTextField = [self _textFieldLikeTextField:_nameTextField withStringValue:[key stringByAppendingString:@":"]]; |
|---|
| 153 |
valueTextField = [self _textFieldLikeTextField:_valueTextField withStringValue:value]; |
|---|
| 154 |
|
|---|
| 155 |
nameSize = [[nameTextField cell] cellSizeForBounds:NSMakeRect(0.0, 0.0, [nameTextField frame].size.width, 10000.0)]; |
|---|
| 156 |
valueSize = [[valueTextField cell] cellSizeForBounds:NSMakeRect(0.0, 0.0, [valueTextField frame].size.width, 10000.0)]; |
|---|
| 157 |
height = MAX(nameSize.height, valueSize.height); |
|---|
| 158 |
|
|---|
| 159 |
[nameTextField setFrame:NSMakeRect([nameTextField frame].origin.x, verticalOffset, |
|---|
| 160 |
[nameTextField frame].size.width, height)]; |
|---|
| 161 |
[valueTextField setFrame:NSMakeRect([valueTextField frame].origin.x, verticalOffset, |
|---|
| 162 |
[valueTextField frame].size.width, height)]; |
|---|
| 163 |
|
|---|
| 164 |
[contentView addSubview:nameTextField]; |
|---|
| 165 |
[contentView addSubview:valueTextField]; |
|---|
| 166 |
|
|---|
| 167 |
verticalOffset += height + 2.0; |
|---|
| 168 |
} |
|---|
| 169 |
|
|---|
| 170 |
windowFrame = [[self window] frame]; |
|---|
| 171 |
height = windowFrame.size.height; |
|---|
| 172 |
windowFrame.size.height = verticalOffset + 26.0; |
|---|
| 173 |
windowFrame.origin.y -= windowFrame.size.height - height; |
|---|
| 174 |
[[self window] setFrame:windowFrame display:YES animate:NO]; |
|---|
| 175 |
} |
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
|
|---|
| 179 |
- (NSTextField *)_textFieldLikeTextField:(NSTextField *)archetypeTextField withStringValue:(NSString *)string { |
|---|
| 180 |
NSTextField *textField; |
|---|
| 181 |
|
|---|
| 182 |
textField = [[NSTextField alloc] initWithFrame:[archetypeTextField frame]]; |
|---|
| 183 |
[textField setEditable:[archetypeTextField isEditable]]; |
|---|
| 184 |
[textField setSelectable:[archetypeTextField isSelectable]]; |
|---|
| 185 |
[textField setBordered:[archetypeTextField isBordered]]; |
|---|
| 186 |
[textField setBezelStyle:[archetypeTextField bezelStyle]]; |
|---|
| 187 |
[textField setFont:[archetypeTextField font]]; |
|---|
| 188 |
[textField setAlignment:[archetypeTextField alignment]]; |
|---|
| 189 |
[textField setTextColor:[archetypeTextField textColor]]; |
|---|
| 190 |
[textField setDrawsBackground:[archetypeTextField drawsBackground]]; |
|---|
| 191 |
[textField setBackgroundColor:[archetypeTextField backgroundColor]]; |
|---|
| 192 |
[textField setStringValue:string]; |
|---|
| 193 |
|
|---|
| 194 |
return [textField autorelease]; |
|---|
| 195 |
} |
|---|
| 196 |
|
|---|
| 197 |
@end |
|---|
| 198 |
|
|---|
| 199 |
|
|---|
| 200 |
|
|---|
| 201 |
@implementation FHInspectorController |
|---|
| 202 |
|
|---|
| 203 |
+ (FHInspectorController *)inspectorController { |
|---|
| 204 |
static FHInspectorController *inspectorController; |
|---|
| 205 |
|
|---|
| 206 |
if(!inspectorController) |
|---|
| 207 |
inspectorController = [[[self class] alloc] init]; |
|---|
| 208 |
|
|---|
| 209 |
return inspectorController; |
|---|
| 210 |
} |
|---|
| 211 |
|
|---|
| 212 |
|
|---|
| 213 |
|
|---|
| 214 |
- (id)init { |
|---|
| 215 |
self = [super initWithWindowNibName:@"Inspector"]; |
|---|
| 216 |
|
|---|
| 217 |
_sortedKeys = [[NSMutableArray alloc] init]; |
|---|
| 218 |
_allValues = [[NSMutableDictionary alloc] init]; |
|---|
| 219 |
|
|---|
| 220 |
[[NSNotificationCenter defaultCenter] |
|---|
| 221 |
addObserver:self |
|---|
| 222 |
selector:@selector(browserControllerDidShowFile:) |
|---|
| 223 |
name:FHBrowserControllerDidShowFile]; |
|---|
| 224 |
|
|---|
| 225 |
[(NSPanel *) [self window] setBecomesKeyOnlyIfNeeded:YES]; |
|---|
| 226 |
|
|---|
| 227 |
return self; |
|---|
| 228 |
} |
|---|
| 229 |
|
|---|
| 230 |
|
|---|
| 231 |
|
|---|
| 232 |
- (void)dealloc { |
|---|
| 233 |
[_nameTextField release]; |
|---|
| 234 |
[_valueTextField release]; |
|---|
| 235 |
|
|---|
| 236 |
[_sortedKeys release]; |
|---|
| 237 |
[_allValues release]; |
|---|
| 238 |
|
|---|
| 239 |
[super dealloc]; |
|---|
| 240 |
} |
|---|
| 241 |
|
|---|
| 242 |
|
|---|
| 243 |
|
|---|
| 244 |
#pragma mark - |
|---|
| 245 |
|
|---|
| 246 |
- (void)windowDidLoad { |
|---|
| 247 |
[[self window] setTitle:NSLS(@"Inspector", @"Inspector")]; |
|---|
| 248 |
|
|---|
| 249 |
[[_nameTextField retain] removeFromSuperview]; |
|---|
| 250 |
[[_valueTextField retain] removeFromSuperview]; |
|---|
| 251 |
} |
|---|
| 252 |
|
|---|
| 253 |
|
|---|
| 254 |
|
|---|
| 255 |
#pragma mark - |
|---|
| 256 |
|
|---|
| 257 |
- (void)browserControllerDidShowFile:(NSNotification *)notification { |
|---|
| 258 |
if([[self window] isVisible]) |
|---|
| 259 |
[self _updateFromFile:[notification object]]; |
|---|
| 260 |
} |
|---|
| 261 |
|
|---|
| 262 |
|
|---|
| 263 |
|
|---|
| 264 |
#pragma mark - |
|---|
| 265 |
|
|---|
| 266 |
- (void)showWindow:(id)sender { |
|---|
| 267 |
[self _updateFromFile:[[[NSApp delegate] browserController] selectedFile]]; |
|---|
| 268 |
|
|---|
| 269 |
[super showWindow:sender]; |
|---|
| 270 |
} |
|---|
| 271 |
|
|---|
| 272 |
@end |
|---|