1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
7 #include "base/logging.h"
8 #include "base/mac/bundle_locations.h"
9 #import "base/mac/mac_util.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "chrome/browser/search_engines/template_url.h"
13 #include "grit/generated_resources.h"
14 #include "grit/theme_resources.h"
15 #include "grit/ui_resources.h"
16 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
17 #include "ui/base/l10n/l10n_util_mac.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/image/image.h"
23 void ShiftOriginY(NSView* view, CGFloat amount) {
24 NSPoint origin = [view frame].origin;
26 [view setFrameOrigin:origin];
31 @implementation EditSearchEngineCocoaController
33 - (id)initWithProfile:(Profile*)profile
34 delegate:(EditSearchEngineControllerDelegate*)delegate
35 templateURL:(TemplateURL*)url {
37 NSString* nibpath = [base::mac::FrameworkBundle()
38 pathForResource:@"EditSearchEngine"
40 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
44 new EditSearchEngineController(templateURL_, delegate, profile_));
49 - (void)awakeFromNib {
50 DCHECK([self window]);
51 DCHECK_EQ(self, [[self window] delegate]);
53 // Make sure the url description field fits the text in it.
54 CGFloat descriptionShift = [GTMUILocalizerAndLayoutTweaker
55 sizeToFitFixedWidthTextField:urlDescriptionField_];
57 // Move the label container above the url description.
58 ShiftOriginY(labelContainer_, descriptionShift);
59 // There was no way via view containment to use a helper view to move all
60 // the textfields and images at once, most move them all on their own so
61 // they stay above the url description.
62 ShiftOriginY(nameField_, descriptionShift);
63 ShiftOriginY(keywordField_, descriptionShift);
64 ShiftOriginY(urlField_, descriptionShift);
65 ShiftOriginY(nameImage_, descriptionShift);
66 ShiftOriginY(keywordImage_, descriptionShift);
67 ShiftOriginY(urlImage_, descriptionShift);
69 // Resize the containing box for the name/keyword/url fields/images since it
70 // also contains the url description (which just grew).
71 [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:NO];
72 NSRect rect = [fieldAndImageContainer_ frame];
73 rect.size.height += descriptionShift;
74 [fieldAndImageContainer_ setFrame:rect];
75 [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:YES];
78 NSWindow* window = [self window];
79 NSSize windowDelta = NSMakeSize(0, descriptionShift);
80 [GTMUILocalizerAndLayoutTweaker
81 resizeWindowWithoutAutoResizingSubViews:window
85 // Defaults to |..._NEW_WINDOW_TITLE|.
86 [window setTitle:l10n_util::GetNSString(
87 IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE)];
88 [nameField_ setStringValue:
89 base::SysUTF16ToNSString(templateURL_->short_name())];
90 [keywordField_ setStringValue:
91 base::SysUTF16ToNSString(templateURL_->keyword())];
92 [urlField_ setStringValue:
93 base::SysUTF16ToNSString(templateURL_->url_ref().DisplayURL())];
94 [urlField_ setEnabled:(templateURL_->prepopulate_id() == 0)];
96 // When creating a new keyword, this will mark the fields as "invalid" and
97 // will not let the user save. If this is an edit, then this will set all
98 // the images to the "valid" state.
99 [self validateFields];
102 // When the window closes, clean ourselves up.
103 - (void)windowWillClose:(NSNotification*)notif {
107 // Performs the logic of closing the window. If we are a sheet, then it ends the
108 // modal session; otherwise, it closes the window.
110 if ([[self window] isSheet]) {
111 [NSApp endSheet:[self window]];
113 [[self window] close];
117 - (IBAction)cancel:(id)sender {
121 - (IBAction)save:(id)sender {
122 DCHECK([self validateFields]);
123 string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
124 string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
125 std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
126 controller_->AcceptAddOrEdit(title, keyword, url);
130 // Delegate method for the text fields.
132 - (void)controlTextDidChange:(NSNotification*)notif {
133 [self validateFields];
136 - (void)controlTextDidEndEditing:(NSNotification*)notif {
137 [self validateFields];
140 // Private /////////////////////////////////////////////////////////////////////
142 // Sets the appropriate image and tooltip based on a boolean |valid|.
143 - (void)setIsValid:(BOOL)valid
144 toolTip:(int)messageID
145 forImageView:(NSImageView*)imageView
146 textField:(NSTextField*)textField {
147 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
148 NSImage* image = valid ? rb.GetNativeImageNamed(IDR_INPUT_GOOD).ToNSImage()
149 : rb.GetNativeImageNamed(IDR_INPUT_ALERT).ToNSImage();
150 [imageView setImage:image];
152 NSString* toolTip = nil;
154 toolTip = l10n_util::GetNSString(messageID);
155 [textField setToolTip:toolTip];
156 [imageView setToolTip:toolTip];
159 // This sets the image state for all the controls and enables or disables the
160 // done button. Returns YES if all the fields are valid.
161 - (BOOL)validateFields {
162 string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
163 BOOL titleValid = controller_->IsTitleValid(title);
164 [self setIsValid:titleValid
165 toolTip:IDS_SEARCH_ENGINES_INVALID_TITLE_TT
166 forImageView:nameImage_
167 textField:nameField_];
169 string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
170 BOOL keywordValid = controller_->IsKeywordValid(keyword);
171 [self setIsValid:keywordValid
172 toolTip:IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT
173 forImageView:keywordImage_
174 textField:keywordField_];
176 std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
177 BOOL urlValid = controller_->IsURLValid(url);
178 [self setIsValid:urlValid
179 toolTip:IDS_SEARCH_ENGINES_INVALID_URL_TT
180 forImageView:urlImage_
181 textField:urlField_];
183 BOOL isValid = (titleValid && keywordValid && urlValid);
184 [doneButton_ setEnabled:isValid];