// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "chrome/browser/cocoa/font_language_settings_controller.h" #import #import "base/mac_util.h" #include "base/sys_string_conversions.h" #include "chrome/browser/character_encoding.h" #include "chrome/browser/fonts_languages_window.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/common/pref_names.h" NSString* const kCharacterInfoEncoding = @"encoding"; NSString* const kCharacterInfoName = @"name"; NSString* const kCharacterInfoID = @"id"; void ShowFontsLanguagesWindow(gfx::NativeWindow window, FontsLanguagesPage page, Profile* profile) { NOTIMPLEMENTED(); } @interface FontLanguageSettingsController (Private) - (void)updateDisplayField:(NSTextField*)field withFont:(NSFont*)font withLabel:(NSTextField*)label; @end @implementation FontLanguageSettingsController - (id)initWithProfile:(Profile*)profile { DCHECK(profile); NSString* nibpath = [mac_util::MainAppBundle() pathForResource:@"FontLanguageSettings" ofType:@"nib"]; if ((self = [super initWithWindowNibPath:nibpath owner:self])) { profile_ = profile; // Convert the name/size preference values to NSFont objects. serifName_.Init(prefs::kWebKitSerifFontFamily, profile->GetPrefs(), NULL); serifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(), NULL); NSString* serif = base::SysUTF8ToNSString(serifName_.GetValue()); serifFont_.reset( [[NSFont fontWithName:serif size:serifSize_.GetValue()] retain]); sansSerifName_.Init(prefs::kWebKitSansSerifFontFamily, profile->GetPrefs(), NULL); sansSerifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(), NULL); NSString* sansSerif = base::SysUTF8ToNSString(sansSerifName_.GetValue()); sansSerifFont_.reset( [[NSFont fontWithName:sansSerif size:sansSerifSize_.GetValue()] retain]); fixedWidthName_.Init(prefs::kWebKitFixedFontFamily, profile->GetPrefs(), NULL); fixedWidthSize_.Init(prefs::kWebKitDefaultFixedFontSize, profile->GetPrefs(), NULL); NSString* fixedWidth = base::SysUTF8ToNSString(fixedWidthName_.GetValue()); fixedWidthFont_.reset( [[NSFont fontWithName:fixedWidth size:fixedWidthSize_.GetValue()] retain]); // Generate a list of encodings. NSInteger count = CharacterEncoding::GetSupportCanonicalEncodingCount(); NSMutableArray* encodings = [NSMutableArray arrayWithCapacity:count]; for (NSInteger i = 0; i < count; ++i) { int commandId = CharacterEncoding::GetEncodingCommandIdByIndex(i); string16 name = CharacterEncoding::\ GetCanonicalEncodingDisplayNameByCommandId(commandId); std::string encoding = CharacterEncoding::GetCanonicalEncodingNameByCommandId(commandId); NSDictionary* strings = [NSDictionary dictionaryWithObjectsAndKeys: base::SysUTF16ToNSString(name), kCharacterInfoName, base::SysUTF8ToNSString(encoding), kCharacterInfoEncoding, [NSNumber numberWithInt:commandId], kCharacterInfoID, nil ]; [encodings addObject:strings]; } // Sort the encodings. scoped_nsobject sorter( [[NSSortDescriptor alloc] initWithKey:kCharacterInfoName ascending:YES]); NSArray* sorterArray = [NSArray arrayWithObject:sorter.get()]; encodings_.reset( [[encodings sortedArrayUsingDescriptors:sorterArray] retain]); // Find and set the default encoding. defaultEncoding_.Init(prefs::kDefaultCharset, profile->GetPrefs(), NULL); NSString* defaultEncoding = base::SysUTF8ToNSString(defaultEncoding_.GetValue()); NSUInteger index = 0; for (NSDictionary* entry in encodings_.get()) { NSString* encoding = [entry objectForKey:kCharacterInfoEncoding]; if ([encoding isEqualToString:defaultEncoding]) { defaultEncodingIndex_ = index; break; } ++index; } // Register as a KVO observer so we can receive updates when the encoding // changes. [self addObserver:self forKeyPath:@"defaultEncodingIndex_" options:NSKeyValueObservingOptionNew context:NULL]; } return self; } - (void)dealloc { [self removeObserver:self forKeyPath:@"defaultEncodingIndex_"]; [super dealloc]; } - (void)awakeFromNib { DCHECK([self window]); [[self window] setDelegate:self]; // Set up the font display. [self updateDisplayField:serifField_ withFont:serifFont_.get() withLabel:serifLabel_]; [self updateDisplayField:sansSerifField_ withFont:sansSerifFont_.get() withLabel:sansSerifLabel_]; [self updateDisplayField:fixedWidthField_ withFont:fixedWidthFont_.get() withLabel:fixedWidthLabel_]; } - (void)windowWillClose:(NSNotification*)notif { [self autorelease]; } - (IBAction)selectFont:(id)sender { if (sender == serifButton_) { currentFont_ = serifFont_.get(); currentType_ = FontSettingSerif; } else if (sender == sansSerifButton_) { currentFont_ = sansSerifFont_.get(); currentType_ = FontSettingSansSerif; } else if (sender == fixedWidthButton_) { currentFont_ = fixedWidthFont_.get(); currentType_ = FontSettingFixed; } else { NOTREACHED(); } // Validate whatever editing is currently happening. if ([[self window] makeFirstResponder:nil]) { NSFontManager* manager = [NSFontManager sharedFontManager]; [manager setTarget:self]; [manager setSelectedFont:currentFont_ isMultiple:NO]; [manager orderFrontFontPanel:self]; } } // Called by the font manager when the user has selected a new font. We should // then persist those changes into the preference system. - (void)changeFont:(id)fontManager { switch (currentType_) { case FontSettingSerif: serifFont_.reset([[fontManager convertFont:serifFont_] retain]); [self updateDisplayField:serifField_ withFont:serifFont_.get() withLabel:serifLabel_]; changedSerif_ = YES; break; case FontSettingSansSerif: sansSerifFont_.reset([[fontManager convertFont:sansSerifFont_] retain]); [self updateDisplayField:sansSerifField_ withFont:sansSerifFont_.get() withLabel:sansSerifLabel_]; changedSansSerif_ = YES; break; case FontSettingFixed: fixedWidthFont_.reset( [[fontManager convertFont:fixedWidthFont_] retain]); [self updateDisplayField:fixedWidthField_ withFont:fixedWidthFont_.get() withLabel:fixedWidthLabel_]; changedFixedWidth_ = YES; break; default: NOTREACHED(); } } - (IBAction)closeSheet:(id)sender { NSFontPanel* panel = [[NSFontManager sharedFontManager] fontPanel:NO]; [panel close]; [NSApp endSheet:[self window]]; } - (IBAction)save:(id)sender { if (changedSerif_) { serifName_.SetValue(base::SysNSStringToUTF8([serifFont_ fontName])); serifSize_.SetValue([serifFont_ pointSize]); } if (changedSansSerif_) { sansSerifName_.SetValue( base::SysNSStringToUTF8([sansSerifFont_ fontName])); sansSerifSize_.SetValue([sansSerifFont_ pointSize]); } if (changedFixedWidth_) { fixedWidthName_.SetValue( base::SysNSStringToUTF8([fixedWidthFont_ fontName])); fixedWidthSize_.SetValue([fixedWidthFont_ pointSize]); } if (changedEncoding_) { NSDictionary* object = [encodings_ objectAtIndex:defaultEncodingIndex_]; NSString* newEncoding = [object objectForKey:kCharacterInfoEncoding]; std::string encoding = base::SysNSStringToUTF8(newEncoding); defaultEncoding_.SetValue(encoding); } [self closeSheet:sender]; } - (NSArray*)encodings { return encodings_.get(); } // KVO notification. - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { // If this is the default encoding, then set the flag to persist the value. if ([keyPath isEqual:@"defaultEncodingIndex_"]) { changedEncoding_ = YES; return; } [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } #pragma mark Private // Set the baseline for the font field to be aligned with the baseline // of its corresponding label. - (NSPoint)getFontFieldOrigin:(NSTextField*)field forLabel:(NSTextField*)label { [field sizeToFit]; NSRect labelFrame = [label frame]; NSPoint newOrigin = [[label superview] convertPoint:labelFrame.origin toView:[field superview]]; newOrigin.x = 0; // Left-align font field. newOrigin.y += [[field font] descender] - [[label font] descender]; return newOrigin; } // This will set the font on |field| to be |font|, and will set the string // value to something human-readable. - (void)updateDisplayField:(NSTextField*)field withFont:(NSFont*)font withLabel:(NSTextField*)label { if (!font) { // Something has gone really wrong. Don't make things worse by showing the // user "(null)". return; } [field setFont:font]; NSString* value = [NSString stringWithFormat:@"%@, %g", [font fontName], [font pointSize]]; [field setStringValue:value]; [field setFrameOrigin:[self getFontFieldOrigin:field forLabel:label]]; } @end