William Bowling is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this again1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | /*
* Adium is the legal property of its developers, whose names are listed in the copyright file included
* with this source distribution.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Adium/AIAccountControllerProtocol.h>
#import "AIAccountProxySettings.h"
#import <Adium/AIContactControllerProtocol.h>
#import "AIEditAccountWindowController.h"
#import <AIUtilities/AIStringAdditions.h>
#import <AIUtilities/AITabViewAdditions.h>
#import <AIUtilities/AIViewAdditions.h>
#import <AIUtilities/AIImageAdditions.h>
#import <AIUtilities/AIImageViewWithImagePicker.h>
#import <Adium/AIAccount.h>
#import <Adium/AIAccountViewController.h>
#import <Adium/AIService.h>
#import <Adium/AIService.h>
#import <Adium/AIServiceIcons.h>
@interface AIEditAccountWindowController ()
- (id)initWithWindowNibName:(NSString *)windowNibName account:(AIAccount *)inAccount notifyingTarget:(id)inTarget;
- (void)_addCustomViewAndTabsForAccount:(AIAccount *)inAccount;
- (void)_addCustomView:(NSView *)customView toView:(NSView *)setupView tabViewItemIdentifier:(NSString *)identifier
runningHeight:(NSInteger *)height width:(NSInteger *)width;
- (void)_removeCustomViewAndTabs;
- (void)_localizeTabViewItemLabels;
- (void)saveConfiguration;
- (void)configureControlDimming;
@end
/*!
* @class AIEditAccountWindowController
* @brief Window controller for configuring an <tt>AIAccount</tt>
*/
@implementation AIEditAccountWindowController
/*!
* @brief Begin editing
*
* @param inAccount The account to edit
* @param parentWindow A window on which to show the edit account window as a sheet. If nil, account editing takes place in an independent window.
* @param inTarget Target to notify when editing is complete.
*/
+ (void)editAccount:(AIAccount *)inAccount onWindow:(id)parentWindow notifyingTarget:(id)inTarget
{
AIEditAccountWindowController *controller;
controller = [[self alloc] initWithWindowNibName:@"EditAccountSheet"
account:inAccount
notifyingTarget:inTarget];
if (parentWindow) {
[NSApp beginSheet:[controller window]
modalForWindow:parentWindow
modalDelegate:controller
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
} else {
[controller showWindow:nil];
}
}
/*!
* @brief Init the window controller
*/
- (id)initWithWindowNibName:(NSString *)windowNibName account:(AIAccount *)inAccount notifyingTarget:(id)inTarget
{
if ((self = [super initWithWindowNibName:windowNibName])) {
account = [inAccount retain];
notifyTarget = inTarget;
userIconData = nil;
didDeleteUserIcon = NO;
}
return self;
}
/*!
* @brief Deallocate
*/
- (void)dealloc
{
[account release];
[userIconData release]; userIconData = nil;
[super dealloc];
}
/*!
* @brief Setup the window before it is displayed
*/
- (void)windowDidLoad
{
//Center our window if we're not a sheet (or opening a sheet failed)
[[self window] center];
[[self window] setTitle:AILocalizedString(@"Edit Account", nil)];
//Account Overview
[textField_serviceName setStringValue:[account.service longDescription]];
[textField_accountDescription setStringValue:account.UID];
[button_chooseIcon setLocalizedString:[AILocalizedString(@"Choose Icon",nil) stringByAppendingEllipsis]];
[button_OK setLocalizedString:AILocalizedString(@"OK",nil)];
[button_cancel setLocalizedString:AILocalizedString(@"Cancel",nil)];
[checkbox_autoconnect setLocalizedString:AILocalizedString(@"Connect when Adium opens", "Account preferences checkbox for automatically conencting the account when Adium opens")];
[[matrix_userIcon cellWithTag:0] setTitle:AILocalizedString(@"Use global icon", "Radio button in the Personal tab of Account preferences. This -must- be a short string of 20 characters or less.")];
[[matrix_userIcon cellWithTag:1] setTitle:AILocalizedString(@"Use this icon:", "Radio button in the Personal tab of Account preferences; an image is shown beneath it to select the account's icon. This -must- be a short string of 20 characters or less.")];
//User icon
if ([[account preferenceForKey:KEY_USE_USER_ICON group:GROUP_ACCOUNT_STATUS] boolValue]) {
//If this account has the preference set, use its user icon.
[matrix_userIcon selectCellWithTag:1];
} else {
//Otherwise it is using the global icon
[matrix_userIcon selectCellWithTag:0];
}
[imageView_userIcon setMaxSize:NSMakeSize(256, 256)];
[imageView_userIcon setImage:[account userIcon]];
[checkbox_autoconnect setState:[[account preferenceForKey:KEY_AUTOCONNECT
group:GROUP_ACCOUNT_STATUS] boolValue]];
//Insert the custom controls for this account
[self _removeCustomViewAndTabs];
[self _addCustomViewAndTabsForAccount:account];
[self _localizeTabViewItemLabels];
[self configureControlDimming];
}
- (IBAction)showWindow:(id)sender {
[super showWindow:sender];
if([notifyTarget respondsToSelector:@selector(editAccountWindow:didOpenForAccount:)])
[notifyTarget editAccountWindow:[self window] didOpenForAccount:account];
}
/*!
* @brief Window is closing
*/
- (void)windowWillClose:(id)sender
{
[super windowWillClose:sender];
[self autorelease];
}
/*!
* @brief Called as the user list edit sheet closes, dismisses the sheet
*/
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:nil];
}
- (void)configureControlDimming
{
BOOL enableUserIcon = ([[matrix_userIcon selectedCell] tag] == 1);
[imageView_userIcon setEnabled:enableUserIcon];
[button_chooseIcon setEnabled:enableUserIcon];
}
/*!
* @brief The user changed the selection in the icon setting matrix which determines availability of the icon controls
*/
- (IBAction)changedIconSetting:(id)sender
{
[self configureControlDimming];
}
/*!
* @brief Cancel
*
* Close without saving changes.
*/
- (IBAction)cancel:(id)sender
{
if (notifyTarget) [notifyTarget editAccountSheetDidEndForAccount:account withSuccess:NO];
[self closeWindow:nil];
}
/*!
* @brief Okay.
*
* Save changes and close.
*/
- (IBAction)okay:(id)sender
{
[self saveConfiguration];
[accountViewController saveConfiguration];
[accountProxyController saveConfiguration];
[account accountEdited];
if (notifyTarget) [notifyTarget editAccountSheetDidEndForAccount:account withSuccess:YES];
[self closeWindow:nil];
}
/*!
* @brief Save any configuration managed by the window controller
*
* Most configuration is handled by the custom view controllers. Save any other configuration, such as the user icon.
*/
- (void)saveConfiguration
{
BOOL enableUserIcon = ([[matrix_userIcon selectedCell] tag] == 1);
if (!enableUserIcon) {
[userIconData release]; userIconData = nil;
didDeleteUserIcon = YES;
}
/* User icon - save if we have data or we deleted
* (so if we don't have data that's the desired thing to set as the pref) */
if (userIconData || didDeleteUserIcon) {
[account setPreference:userIconData
forKey:KEY_USER_ICON
group:GROUP_ACCOUNT_STATUS];
}
[account setPreference:[NSNumber numberWithBool:[[matrix_userIcon selectedCell] tag]]
forKey:KEY_USE_USER_ICON
group:GROUP_ACCOUNT_STATUS];
[account setPreference:[NSNumber numberWithBool:[checkbox_autoconnect state]]
forKey:KEY_AUTOCONNECT
group:GROUP_ACCOUNT_STATUS];
}
/*!
* @brief Add the custom views for an account
*/
- (void)_addCustomViewAndTabsForAccount:(AIAccount *)inAccount
{
NSRect windowFrame = [[self window] frame];
NSInteger baseHeight = NSHeight([view_accountSetup frame]);
NSInteger baseWidth = NSWidth([view_accountSetup frame]);
NSInteger newHeight = baseHeight, newWidth = baseWidth;
//Configure our account and proxy view controllers
accountViewController = [[inAccount.service accountViewController] retain];
[accountViewController configureForAccount:inAccount];
accountProxyController = ([inAccount.service supportsProxySettings] ?
[[AIAccountProxySettings alloc] init] :
nil);
[accountProxyController configureForAccount:inAccount];
//Account setup view
[self _addCustomView:[accountViewController setupView]
toView:view_accountSetup
tabViewItemIdentifier:@"account"
runningHeight:&newHeight
width:&newWidth];
//Account Profile View
[self _addCustomView:[accountViewController profileView]
toView:view_accountProfile
tabViewItemIdentifier:@"profile"
runningHeight:&newHeight
width:NULL];
//Account Options view
[self _addCustomView:[accountViewController optionsView]
toView:view_accountOptions
tabViewItemIdentifier:@"options"
runningHeight:&newHeight
width:&newWidth];
//Account Privacy view
[self _addCustomView:[accountViewController privacyView]
toView:view_accountPrivacy
tabViewItemIdentifier:@"privacy"
runningHeight:&newHeight
width:&newWidth];
//Add proxy view
[self _addCustomView:[accountProxyController view]
toView:view_accountProxy
tabViewItemIdentifier:@"proxy"
runningHeight:&newHeight
width:&newWidth];
//Resize our window as necessary to make room for the custom views
windowFrame.size.height += newHeight - baseHeight;
windowFrame.size.width += newWidth - baseWidth;
[[self window] setFrame:windowFrame display:YES];
//Responder chains are a pain in 10.3. The tab view will set them up correctly when we switch tabs, but doesn't
//get a chance to setup the responder chain for our default tab. A quick hack to get the tab view to set things
//up correctly is to switch tabs away and then back to our default. This causes little harm, since our window
//isn't visible at this point anyway.
//XXX - I believe we're getting a method that will avoid the need for this hack in 10.4 -ai
[tabView_auxiliary selectLastTabViewItem:nil];
[tabView_auxiliary selectFirstTabViewItem:nil];
}
/*!
* @brief Used when configuring to add custom views and remove tabs as necessary
*
* Add customView to setupView and return the height difference between the two if customView is taller than setupView.
* Remove the tabViewItem with the passed identifier if no customView exists, avoiding empty tabs.
*
* @param customView The view to add
* @param setupView The view within our nib which will be filled by customView
* @param identifier Identifier of the <tt>NSTabViewItem</tt> which will be removed from tabView_auxiliary if customView == nil
* @param requiredHeight The current required view height to display all our views
* @result The new required window height to display our existing views and the newly added view
*/
- (void)_addCustomView:(NSView *)customView toView:(NSView *)setupView tabViewItemIdentifier:(NSString *)identifier
runningHeight:(NSInteger *)height width:(NSInteger *)width
{
if (customView) {
//Adjust height as necessary if our view needs more room
if (NSHeight([customView frame]) > *height) {
*height = NSHeight([customView frame]);
}
//Adjust height as necessary if our view needs more room
if (width && (NSWidth([customView frame]) > *width)) {
*width = NSWidth([customView frame]);
}
//Align our view to the top and insert it into the window
if (width && (NSWidth([setupView frame]) > NSWidth([customView frame])))
[customView setFrameOrigin:NSMakePoint(floor((NSWidth([setupView frame]) - NSWidth([customView frame])) / 2),
NSHeight([setupView frame]) - NSHeight([customView frame]))];
else
[customView setFrameOrigin:NSMakePoint(0,
NSHeight([setupView frame]) - NSHeight([customView frame]))];
[customView setAutoresizingMask:(NSViewMinYMargin | NSViewMinXMargin | NSViewMaxXMargin)];
[setupView addSubview:customView];
} else {
//If no view is available, remove the corresponding tab
[tabView_auxiliary removeTabViewItem:[tabView_auxiliary tabViewItemWithIdentifier:identifier]];
}
}
/*!
* @brief Remove any existing custom views
*/
- (void)_removeCustomViewAndTabs
{
//Close any currently open controllers
[view_accountSetup removeAllSubviews];
[accountViewController release]; accountViewController = nil;
}
/*!
* @brief Localization
*/
- (void)_localizeTabViewItemLabels
{
[[tabView_auxiliary tabViewItemWithIdentifier:@"account"] setLabel:AILocalizedString(@"Account",nil)];
[[tabView_auxiliary tabViewItemWithIdentifier:@"profile"] setLabel:AILocalizedString(@"Personal",nil)];
[[tabView_auxiliary tabViewItemWithIdentifier:@"options"] setLabel:AILocalizedString(@"Options",nil)];
[[tabView_auxiliary tabViewItemWithIdentifier:@"privacy"] setLabel:AILocalizedString(@"Privacy",nil)];
[[tabView_auxiliary tabViewItemWithIdentifier:@"proxy"] setLabel:AILocalizedString(@"Proxy",nil)];
}
// AIImageViewWithImagePicker Delegate ---------------------------------------------------------------------
#pragma mark AIImageViewWithImagePicker Delegate
- (void)deleteInImageViewWithImagePicker:(AIImageViewWithImagePicker *)sender
{
[userIconData release]; userIconData = nil;
didDeleteUserIcon = YES;
//User icon - restore to the default icon
[imageView_userIcon setImage:[account userIcon]];
//We're now using the global icon
[matrix_userIcon selectCellWithTag:0];
}
- (void)imageViewWithImagePicker:(AIImageViewWithImagePicker *)sender didChangeToImageData:(NSData *)imageData
{
[userIconData release];
userIconData = [imageData retain];
if (!userIconData) {
//If we got a nil user icon, that means the icon was deleted
[self deleteInImageViewWithImagePicker:sender];
}
}
- (NSString *)fileNameForImageInImagePicker:(AIImageViewWithImagePicker *)picker
{
NSString *fileName = [account.displayName safeFilenameString];
if ([fileName hasPrefix:@"."]) {
fileName = [fileName substringFromIndex:1];
}
return fileName;
}
- (NSImage *)emptyPictureImageForImageViewWithImagePicker:(AIImageViewWithImagePicker *)picker
{
return [AIServiceIcons serviceIconForObject:account type:AIServiceIconLarge direction:AIIconNormal];
}
@end
|