blob: ae36e5c2d5481f4e155c844375c3afe0d9bbe673 [file] [log] [blame]
// Copyright (c) 2012 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/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
#include "base/logging.h"
#include "base/mac/bundle_locations.h"
#import "base/mac/mac_util.h"
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/search_engines/template_url.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
namespace {
void ShiftOriginY(NSView* view, CGFloat amount) {
NSPoint origin = [view frame].origin;
origin.y += amount;
[view setFrameOrigin:origin];
}
} // namespace
@implementation EditSearchEngineCocoaController
- (id)initWithProfile:(Profile*)profile
delegate:(EditSearchEngineControllerDelegate*)delegate
templateURL:(TemplateURL*)url {
DCHECK(profile);
NSString* nibpath = [base::mac::FrameworkBundle()
pathForResource:@"EditSearchEngine"
ofType:@"nib"];
if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
profile_ = profile;
templateURL_ = url;
controller_.reset(
new EditSearchEngineController(templateURL_, delegate, profile_));
}
return self;
}
- (void)awakeFromNib {
DCHECK([self window]);
DCHECK_EQ(self, [[self window] delegate]);
// Make sure the url description field fits the text in it.
CGFloat descriptionShift = [GTMUILocalizerAndLayoutTweaker
sizeToFitFixedWidthTextField:urlDescriptionField_];
// Move the label container above the url description.
ShiftOriginY(labelContainer_, descriptionShift);
// There was no way via view containment to use a helper view to move all
// the textfields and images at once, most move them all on their own so
// they stay above the url description.
ShiftOriginY(nameField_, descriptionShift);
ShiftOriginY(keywordField_, descriptionShift);
ShiftOriginY(urlField_, descriptionShift);
ShiftOriginY(nameImage_, descriptionShift);
ShiftOriginY(keywordImage_, descriptionShift);
ShiftOriginY(urlImage_, descriptionShift);
// Resize the containing box for the name/keyword/url fields/images since it
// also contains the url description (which just grew).
[[fieldAndImageContainer_ contentView] setAutoresizesSubviews:NO];
NSRect rect = [fieldAndImageContainer_ frame];
rect.size.height += descriptionShift;
[fieldAndImageContainer_ setFrame:rect];
[[fieldAndImageContainer_ contentView] setAutoresizesSubviews:YES];
// Resize the window.
NSWindow* window = [self window];
NSSize windowDelta = NSMakeSize(0, descriptionShift);
[GTMUILocalizerAndLayoutTweaker
resizeWindowWithoutAutoResizingSubViews:window
delta:windowDelta];
if (templateURL_) {
// Defaults to |..._NEW_WINDOW_TITLE|.
[window setTitle:l10n_util::GetNSString(
IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE)];
[nameField_ setStringValue:
base::SysUTF16ToNSString(templateURL_->short_name())];
[keywordField_ setStringValue:
base::SysUTF16ToNSString(templateURL_->keyword())];
[urlField_ setStringValue:
base::SysUTF16ToNSString(templateURL_->url_ref().DisplayURL())];
[urlField_ setEnabled:(templateURL_->prepopulate_id() == 0)];
}
// When creating a new keyword, this will mark the fields as "invalid" and
// will not let the user save. If this is an edit, then this will set all
// the images to the "valid" state.
[self validateFields];
}
// When the window closes, clean ourselves up.
- (void)windowWillClose:(NSNotification*)notif {
[self autorelease];
}
// Performs the logic of closing the window. If we are a sheet, then it ends the
// modal session; otherwise, it closes the window.
- (void)doClose {
if ([[self window] isSheet]) {
[NSApp endSheet:[self window]];
} else {
[[self window] close];
}
}
- (IBAction)cancel:(id)sender {
[self doClose];
}
- (IBAction)save:(id)sender {
DCHECK([self validateFields]);
base::string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
base::string16 keyword =
base::SysNSStringToUTF16([keywordField_ stringValue]);
std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
controller_->AcceptAddOrEdit(title, keyword, url);
[self doClose];
}
// Delegate method for the text fields.
- (void)controlTextDidChange:(NSNotification*)notif {
[self validateFields];
}
- (void)controlTextDidEndEditing:(NSNotification*)notif {
[self validateFields];
}
// Private /////////////////////////////////////////////////////////////////////
// Sets the appropriate image and tooltip based on a boolean |valid|.
- (void)setIsValid:(BOOL)valid
toolTip:(int)messageID
forImageView:(NSImageView*)imageView
textField:(NSTextField*)textField {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
NSImage* image = valid ? rb.GetNativeImageNamed(IDR_INPUT_GOOD).ToNSImage()
: rb.GetNativeImageNamed(IDR_INPUT_ALERT).ToNSImage();
[imageView setImage:image];
NSString* toolTip = nil;
if (!valid)
toolTip = l10n_util::GetNSString(messageID);
[textField setToolTip:toolTip];
[imageView setToolTip:toolTip];
}
// This sets the image state for all the controls and enables or disables the
// done button. Returns YES if all the fields are valid.
- (BOOL)validateFields {
base::string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
BOOL titleValid = controller_->IsTitleValid(title);
[self setIsValid:titleValid
toolTip:IDS_SEARCH_ENGINES_INVALID_TITLE_TT
forImageView:nameImage_
textField:nameField_];
base::string16 keyword =
base::SysNSStringToUTF16([keywordField_ stringValue]);
BOOL keywordValid = controller_->IsKeywordValid(keyword);
[self setIsValid:keywordValid
toolTip:IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT
forImageView:keywordImage_
textField:keywordField_];
std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
BOOL urlValid = controller_->IsURLValid(url);
[self setIsValid:urlValid
toolTip:IDS_SEARCH_ENGINES_INVALID_URL_TT
forImageView:urlImage_
textField:urlField_];
BOOL isValid = (titleValid && keywordValid && urlValid);
[doneButton_ setEnabled:isValid];
return isValid;
}
@end