Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
DiscInfoController.m
/* |
File: DiscInfoController.m |
Contains: Settings panel controller that provides control over volume |
properties of the burn hierarchy root. |
Version: Technology: Mac OS X |
Release: Mac OS X |
Copyright: (c) 2002 by Apple Computer, Inc., all rights reserved |
Bugs?: For bug reports, consult the following page on |
the World Wide Web: |
http://developer.apple.com/bugreporter/ |
*/ |
/* |
IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in |
consideration of your agreement to the following terms, and your use, installation, |
modification or redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject to these |
terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in |
this original Apple software (the "Apple Software"), to use, reproduce, modify and |
redistribute the Apple Software, with or without modifications, in source and/or binary |
forms; provided that if you redistribute the Apple Software in its entirety and without |
modifications, you must retain this notice and the following text and disclaimers in all |
such redistributions of the Apple Software. Neither the name, trademarks, service marks |
or logos of Apple Computer, Inc. may be used to endorse or promote products derived from |
the Apple Software without specific prior written permission from Apple. Except as expressly |
stated in this notice, no other rights or licenses, express or implied, are granted by Apple |
herein, including but not limited to any patent rights that may be infringed by your |
derivative works or by other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, |
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS |
USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, |
REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND |
WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR |
OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#import "DiscInfoController.h" |
#import "AppController.h" |
#import "FSTreeNode.h" |
static NSArray* propertyTagMappings = nil; |
static NSArray* filesystemNameTagMappings = nil; |
@implementation DiscInfoController |
+ (void) initialize |
{ |
// Through clever arrangement of the tags of objects in the info panel, |
// we use these tags to index into an array of the filesystem properties. |
// When one of out UI items changes and sends it's action, we look up that |
// objects tag in this array, which gives us back the proper property to |
// use as the dictionary key for the object value of the UI object. |
propertyTagMappings = [[NSArray alloc] initWithObjects: DRISOMacExtensions, |
DRISORockRidgeExtensions, // 1 |
DRISOLevel, // 2 |
DRVolumeSet, // 3 |
DRPublisher, // 4 |
DRDataPreparer, // 5 |
DRApplicationIdentifier, // 6 |
DRSystemIdentifier, // 7 |
DRVolumeExpirationDate, // 8 |
DRVolumeEffectiveDate, // 9 |
DRCopyrightFile, // 10 |
DRBibliographicFile, // 11 |
DRAbstractFile, // 12 |
DRDefaultDate, // 13 |
DRVolumeCreationDate, // 14 |
DRVolumeModificationDate, // 15 |
DRVolumeCheckedDate, // 16 |
nil]; |
// In a similar arrangement to above, we do the same object tag -> index mappings |
// for the filesystem names. |
filesystemNameTagMappings = [[NSArray alloc] initWithObjects: DRAllFilesystems, |
DRISO9660, |
DRISO9660LevelOne, |
DRISO9660LevelTwo, |
DRJoliet, |
DRHFSPlus, |
nil]; |
} |
- (id) init |
{ |
if (self = [super init]) |
{ |
fsProperties = [[NSMutableDictionary alloc] initWithCapacity:1]; |
} |
return self; |
} |
- (void) dealloc |
{ |
[fsProperties release]; |
fsProperties = nil; |
[super dealloc]; |
} |
- (IBAction) ok:(id)sender |
{ |
[NSApp stopModalWithCode:NSOKButton]; |
} |
- (IBAction) cancel:(id)sender |
{ |
[NSApp stopModalWithCode:NSCancelButton]; |
} |
- (IBAction)setVolumeProperty:(id)sender |
{ |
if ([DRISOLevel isEqualTo:[propertyTagMappings objectAtIndex:[sender tag]]]) |
{ |
// The ISO level needs special handling since the objectValue of a popup menu is the index of the |
// menu item, which starts at zero. We need it to start at 1. |
[fsProperties setObject:[NSNumber numberWithInt:[sender indexOfSelectedItem] + 1] forKey:DRISOLevel]; |
} |
else |
{ |
// But in every other case, we can just ask for the object value. Since everything is a date |
// or plain string, this can be handled by asking for the object value and |
// passing that along. |
[fsProperties setObject:[sender objectValue] forKey:[propertyTagMappings objectAtIndex:[sender tag]]]; |
} |
} |
- (IBAction)selectRootDirFile:(id)sender |
{ |
int returnCode; |
// Get the current list of root files from the mail app controller. This will be the |
// list of files that you can choose from. For any of the special ISO root files |
// (copyright, bibliographic, abstract), these file MUST exist in the root directory |
// of the ISO volume. This is in the spec, it's not negotiable. |
rootFiles = [appController rootFiles]; |
// setup and run the modal dialog. |
[okButton setEnabled:NO]; |
[fileList selectRow:-1 byExtendingSelection:NO]; |
returnCode = [NSApp runModalForWindow:fileChooser]; |
[fileChooser orderOut:self]; |
// User clicked OK, so we need to update display of the filename |
// as well as update the property we're setting. |
if (returnCode == NSOKButton) |
{ |
// We know which text field to simulate an action from by looking at the tag of the |
// button that was pressed and subtracting off 100. Then we look up the text field |
// in the info window using viewWithTag:. We use this to set the text shown in the |
// field to let the user know what file they selected. |
NSTextField* propertyView = [[infoWindow contentView] viewWithTag:[sender tag] - 100]; |
[propertyView setObjectValue:[[selectedItem nodeData] valueForKey:@"name"]]; |
[fsProperties setObject:[(FSNodeData*)[selectedItem nodeData] fsObject] forKey:[propertyTagMappings objectAtIndex:[propertyView tag]]]; |
} |
// we don't need to hold onto this anymore. We'll grab it again next time. |
rootFiles = nil; |
} |
- (IBAction)setFilesystemMask:(id)sender |
{ |
NSEnumerator* iter; |
NSControl* cntl; |
BOOL included = [sender state]; |
unsigned long includedFilesystems = [filesystemRoot explicitFilesystemMask]; |
// The correct filesystem is encoded in the tag of the object. |
// The filesystem mask is just a bit set in the includedFilesystems |
// variable. So we'll shift the bit by the tag of the object sending the |
// message to set the correct bit mask. |
if (included) |
includedFilesystems |= (1<<[sender tag]); |
else |
includedFilesystems &= ~(1<<[sender tag]); |
// Set the explicit filesystem mask. This mask tells the framework |
// which filesystems to generate for the disc when it's applied to the |
// root folder. |
[filesystemRoot setExplicitFilesystemMask:includedFilesystems]; |
// Now we'll enable/disable the contents of the specfic tab we're futzing with |
// to indicate to the user that they can't set any values. |
// First get the correct contents to use. We'll get an iterator to the |
// subviews. |
if (sender == iso) |
{ |
iter = [[[isoOptions contentView] subviews] objectEnumerator]; |
} |
else if (sender == hfs) |
{ |
iter = [[[hfsOptions contentView] subviews] objectEnumerator]; |
} |
else if (sender == joliet) |
{ |
iter = [[[jolietOptions contentView] subviews] objectEnumerator]; |
} |
// Now iterate over all of the subviews. If they respond to the |
// -setEnabled: method, call it to enable/disable the item. |
while ((cntl = [iter nextObject]) != NULL) |
{ |
if ([cntl respondsToSelector:@selector(setEnabled:)]) |
[cntl setEnabled:included]; |
} |
} |
- (IBAction)setVolumeName:(id)sender |
{ |
// The correct filesystem is encoded in the tag of the object. |
NSString* filesystem; |
NSString* volumeName; |
int index = [sender tag]; |
// If it's index 1 (that's ISO), we need to look at the ISO level popup. |
// For the filesystem names, we need to get specific since while we're |
// creating an ISO filesystem, we can only get/set item/volume names |
// based on DRISO9660LevelOne or DRISO9660LevelTwo naming. The reason for |
// this is that ISO has two different methods of handling filenames on the volume |
// Each one has different characters that are valid and lengths of the strings |
// used. Other volume formats don't have this quirk, so we only need to do it |
// for ISO. |
if (index == 1) |
{ |
int isoLevel = [[fsProperties objectForKey:DRISOLevel] intValue]; |
index = index + (isoLevel ? isoLevel : 1); |
} |
// Get the correct filesystem based on the index we got from the object tag. |
filesystem = [filesystemNameTagMappings objectAtIndex:index]; |
[filesystemRoot setSpecificName:[sender stringValue] forFilesystem:filesystem]; |
volumeName = [filesystemRoot specificNameForFilesystem:filesystem]; |
// Now, on the other end, we need to do some work if we're changing the Joliet |
// volume name. Normally Joliet has a length limit of 64 UTF-16 characters. But for |
// the volume name, there's not enough space, in fact there's only 32 bytes of space |
// so we can have at most 16 characters in the name. This unfortunately can't be handled |
// in the framework since there's no way to distinguish a file/folder that simply hasn't |
// been added to a hierarchy and the root of the filesystem (which doesn't have a parent) |
if (index == 4) |
{ |
if ([volumeName length] > 16) |
{ |
NSRange jolietVolumeRange = NSMakeRange(0, 16); |
volumeName = [volumeName substringWithRange:jolietVolumeRange]; |
[filesystemRoot setSpecificName:volumeName forFilesystem:filesystem]; |
} |
} |
// reset what the user typed in since they might have used illegal characters. |
[sender setStringValue:volumeName]; |
} |
- (IBAction)userSelectedISOLevel:(id)sender |
{ |
[self setVolumeProperty:sender]; |
// When the user selects the ISO level popup menu, we'll switch the volume name shown. |
[isoName setStringValue:[filesystemRoot specificNameForFilesystem:[filesystemNameTagMappings objectAtIndex:[sender indexOfSelectedItem] + 2]]]; |
} |
- (IBAction)openInfoPanel:(id)sender |
{ |
if ([infoWindow isVisible] == NO) |
{ |
if ([infoWindow setFrameUsingName:[infoWindow frameAutosaveName] force:YES] == NO) |
{ |
NSRect frame = [[appController window] frame]; |
NSPoint newOrigin = NSMakePoint(frame.origin.x + frame.size.width + 20, frame.origin.y + frame.size.height); |
[infoWindow cascadeTopLeftFromPoint:newOrigin]; |
} |
} |
[infoWindow orderFront:self]; |
} |
- (void) setRoot:(DRFolder*)root |
{ |
NSString* volumeName; |
filesystemRoot = root; |
// when we update the filesystem root, make sure that the text fields for the |
// different filesystem names are all in sync. |
[hfsName setStringValue:[filesystemRoot specificNameForFilesystem:DRHFSPlus]]; |
if ([[fsProperties objectForKey:DRISOLevel] intValue] == 1) |
{ |
[isoName setStringValue:[filesystemRoot specificNameForFilesystem:DRISO9660LevelOne]]; |
} |
else |
{ |
[isoName setStringValue:[filesystemRoot specificNameForFilesystem:DRISO9660LevelTwo]]; |
} |
volumeName = [filesystemRoot specificNameForFilesystem:DRJoliet]; |
if ([volumeName length] > 16) |
{ |
NSRange jolietVolumeRange = NSMakeRange(0, 16); |
volumeName = [volumeName substringWithRange:jolietVolumeRange]; |
[filesystemRoot setSpecificName:volumeName forFilesystem:DRJoliet]; |
} |
[jolietName setStringValue:volumeName]; |
} |
- (NSDictionary*)volumeProperties |
{ |
return [[fsProperties retain] autorelease]; |
} |
#pragma mark - |
#pragma mark ¥¥ÊData source methods |
- (int)numberOfRowsInTableView:(NSTableView *)aTableView |
{ |
return [rootFiles count]; |
} |
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex |
{ |
return [[[rootFiles objectAtIndex:rowIndex] nodeData] valueForKey:[tableColumn identifier]]; |
} |
#pragma mark - |
#pragma mark ¥¥ÊTable delegate methods |
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification |
{ |
NSTableView* tv = [aNotification object]; |
if ([tv selectedRow] != -1) |
{ |
selectedItem = [rootFiles objectAtIndex:[tv selectedRow]]; |
[okButton setEnabled:YES]; |
} |
else |
{ |
[okButton setEnabled:NO]; |
} |
} |
@end |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14