Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / translate / translate_bubble_controller.mm
1 // Copyright 2014 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.
4
5 #import "chrome/browser/ui/cocoa/translate/translate_bubble_controller.h"
6
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/strings/sys_string_conversions.h"
10 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
11 #import "chrome/browser/ui/cocoa/bubble_combobox.h"
12 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
13 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
14 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
15 #include "chrome/browser/ui/translate/language_combobox_model.h"
16 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "components/translate/core/browser/translate_ui_delegate.h"
19 #include "content/public/browser/browser_context.h"
20 #import "ui/base/cocoa/controls/hyperlink_button_cell.h"
21 #import "ui/base/cocoa/window_size_constants.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/models/combobox_model.h"
24
25 // TODO(hajimehoshi): This class is almost same as that of views. Refactor them.
26 class TranslateDenialComboboxModel : public ui::ComboboxModel {
27  public:
28   explicit TranslateDenialComboboxModel(
29       const base::string16& original_language_name) {
30     // Dummy menu item, which is shown on the top of a NSPopUpButton. The top
31     // text of the denial pop up menu should be IDS_TRANSLATE_BUBBLE_DENY, while
32     // it is impossible to use it here because NSPopUpButtons' addItemWithTitle
33     // removes a duplicated menu item. Instead, the title will be set later by
34     // NSMenuItem's setTitle.
35     items_.push_back(base::string16());
36
37     // Menu items in the drop down menu.
38     items_.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
39     items_.push_back(l10n_util::GetStringFUTF16(
40         IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
41         original_language_name));
42     items_.push_back(l10n_util::GetStringUTF16(
43         IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
44   }
45   ~TranslateDenialComboboxModel() override {}
46
47  private:
48   // ComboboxModel:
49   int GetItemCount() const override { return items_.size(); }
50   base::string16 GetItemAt(int index) override { return items_[index]; }
51   bool IsItemSeparatorAt(int index) override { return false; }
52   int GetDefaultIndex() const override { return 0; }
53
54   std::vector<base::string16> items_;
55
56   DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel);
57 };
58
59 const CGFloat kWindowWidth = 320;
60
61 // Padding between the window frame and content.
62 const CGFloat kFramePadding = 16;
63
64 const CGFloat kRelatedControlHorizontalSpacing = -2;
65
66 const CGFloat kRelatedControlVerticalSpacing = 4;
67 const CGFloat kUnrelatedControlVerticalSpacing = 20;
68
69 const CGFloat kContentWidth = kWindowWidth - 2 * kFramePadding;
70
71 @interface TranslateBubbleController()
72
73 - (void)performLayout;
74 - (NSView*)newBeforeTranslateView;
75 - (NSView*)newTranslatingView;
76 - (NSView*)newAfterTranslateView;
77 - (NSView*)newErrorView;
78 - (NSView*)newAdvancedView;
79 - (void)updateAdvancedView;
80 - (NSTextField*)addText:(NSString*)text
81                  toView:(NSView*)view;
82 - (NSButton*)addLinkButtonWithText:(NSString*)text
83                             action:(SEL)action
84                             toView:(NSView*)view;
85 - (NSButton*)addButton:(NSString*)title
86                 action:(SEL)action
87                 toView:(NSView*)view;
88 - (NSButton*)addCheckbox:(NSString*)title
89                   toView:(NSView*)view;
90 - (NSPopUpButton*)addPopUpButton:(ui::ComboboxModel*)model
91                           action:(SEL)action
92                           toView:(NSView*)view;
93 - (void)handleTranslateButtonPressed;
94 - (void)handleNopeButtonPressed;
95 - (void)handleDoneButtonPressed;
96 - (void)handleCancelButtonPressed;
97 - (void)handleShowOriginalButtonPressed;
98 - (void)handleAdvancedLinkButtonPressed;
99 - (void)handleDenialPopUpButtonNopeSelected;
100 - (void)handleDenialPopUpButtonNeverTranslateLanguageSelected;
101 - (void)handleDenialPopUpButtonNeverTranslateSiteSelected;
102 - (void)handleSourceLanguagePopUpButtonSelectedItemChanged:(id)sender;
103 - (void)handleTargetLanguagePopUpButtonSelectedItemChanged:(id)sender;
104
105 @end
106
107 @implementation TranslateBubbleController
108
109 - (id)initWithParentWindow:(BrowserWindowController*)controller
110                      model:(scoped_ptr<TranslateBubbleModel>)model
111                webContents:(content::WebContents*)webContents {
112   NSWindow* parentWindow = [controller window];
113
114   // Use an arbitrary size; it will be changed in performLayout.
115   NSRect contentRect = ui::kWindowSizeDeterminedLater;
116   base::scoped_nsobject<InfoBubbleWindow> window(
117       [[InfoBubbleWindow alloc] initWithContentRect:contentRect
118                                           styleMask:NSBorderlessWindowMask
119                                             backing:NSBackingStoreBuffered
120                                               defer:NO]);
121
122   if ((self = [super initWithWindow:window
123                        parentWindow:parentWindow
124                          anchoredAt:NSZeroPoint])) {
125     webContents_ = webContents;
126     model_ = model.Pass();
127     if (model_->GetViewState() !=
128         TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
129       translateExecuted_ = YES;
130     }
131
132     views_.reset([@{
133         @(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE):
134             [self newBeforeTranslateView],
135         @(TranslateBubbleModel::VIEW_STATE_TRANSLATING):
136             [self newTranslatingView],
137         @(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE):
138             [self newAfterTranslateView],
139         @(TranslateBubbleModel::VIEW_STATE_ERROR):
140             [self newErrorView],
141         @(TranslateBubbleModel::VIEW_STATE_ADVANCED):
142             [self newAdvancedView],
143     } retain]);
144
145     [self performLayout];
146   }
147   return self;
148 }
149
150 @synthesize webContents = webContents_;
151
152 - (NSView*)currentView {
153   NSNumber* key = @(model_->GetViewState());
154   NSView* view = [views_ objectForKey:key];
155   DCHECK(view);
156   return view;
157 }
158
159 - (const TranslateBubbleModel*)model {
160   return model_.get();
161 }
162
163 - (void)showWindow:(id)sender {
164   BrowserWindowController* controller = [[self parentWindow] windowController];
165   NSPoint anchorPoint = [[controller toolbarController] translateBubblePoint];
166   anchorPoint = [[self parentWindow] convertBaseToScreen:anchorPoint];
167   [self setAnchorPoint:anchorPoint];
168   [super showWindow:sender];
169 }
170
171 - (void)switchView:(TranslateBubbleModel::ViewState)viewState {
172   if (model_->GetViewState() == viewState)
173     return;
174
175   model_->SetViewState(viewState);
176   [self performLayout];
177 }
178
179 - (void)switchToErrorView:(translate::TranslateErrors::Type)errorType {
180   // FIXME: Implement this.
181 }
182
183 - (void)performLayout {
184   NSWindow* window = [self window];
185   [[window contentView] setSubviews:@[ [self currentView] ]];
186
187   CGFloat height = NSHeight([[self currentView] frame]) +
188       2 * kFramePadding + info_bubble::kBubbleArrowHeight;
189
190   NSRect windowFrame = [window contentRectForFrameRect:[[self window] frame]];
191   NSRect newWindowFrame = [window frameRectForContentRect:NSMakeRect(
192       NSMinX(windowFrame), NSMaxY(windowFrame) - height, kWindowWidth, height)];
193   [window setFrame:newWindowFrame
194            display:YES
195            animate:[[self window] isVisible]];
196 }
197
198 - (NSView*)newBeforeTranslateView {
199   NSRect contentFrame = NSMakeRect(
200       kFramePadding,
201       kFramePadding,
202       kContentWidth,
203       0);
204   NSView* view = [[NSView alloc] initWithFrame:contentFrame];
205
206   NSString* message =
207       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE);
208   NSTextField* textLabel = [self addText:message
209                                   toView:view];
210   message = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ADVANCED);
211   NSButton* advancedLinkButton =
212       [self addLinkButtonWithText:message
213                            action:@selector(handleAdvancedLinkButtonPressed)
214                            toView:view];
215
216   NSString* title =
217       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ACCEPT);
218   NSButton* translateButton =
219       [self addButton:title
220                action:@selector(handleTranslateButtonPressed)
221                toView:view];
222
223   base::string16 originalLanguageName =
224       model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
225   // TODO(hajimehoshi): When TranslateDenialComboboxModel is factored out as a
226   // common model, ui::MenuModel will be used here.
227   translateDenialComboboxModel_.reset(
228       new TranslateDenialComboboxModel(originalLanguageName));
229   NSPopUpButton* denyPopUpButton =
230       [self addPopUpButton:translateDenialComboboxModel_.get()
231                     action:nil
232                     toView:view];
233   [denyPopUpButton setPullsDown:YES];
234   [[denyPopUpButton itemAtIndex:1] setTarget:self];
235   [[denyPopUpButton itemAtIndex:1]
236     setAction:@selector(handleDenialPopUpButtonNopeSelected)];
237   [[denyPopUpButton itemAtIndex:2] setTarget:self];
238   [[denyPopUpButton itemAtIndex:2]
239     setAction:@selector(handleDenialPopUpButtonNeverTranslateLanguageSelected)];
240   [[denyPopUpButton itemAtIndex:3] setTarget:self];
241   [[denyPopUpButton itemAtIndex:3]
242     setAction:@selector(handleDenialPopUpButtonNeverTranslateSiteSelected)];
243
244   title = base::SysUTF16ToNSString(
245       l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
246   [[denyPopUpButton itemAtIndex:0] setTitle:title];
247
248   // Adjust width for the first item.
249   base::scoped_nsobject<NSMenu> originalMenu([[denyPopUpButton menu] copy]);
250   [denyPopUpButton removeAllItems];
251   [denyPopUpButton addItemWithTitle:[[originalMenu itemAtIndex:0] title]];
252   [denyPopUpButton sizeToFit];
253   [denyPopUpButton setMenu:originalMenu];
254
255   // Layout
256   CGFloat yPos = 0;
257
258   [translateButton setFrameOrigin:NSMakePoint(
259       kContentWidth - NSWidth([translateButton frame]), yPos)];
260
261   NSRect denyPopUpButtonFrame = [denyPopUpButton frame];
262   CGFloat diffY = [[denyPopUpButton cell]
263     titleRectForBounds:[denyPopUpButton bounds]].origin.y;
264   [denyPopUpButton setFrameOrigin:NSMakePoint(
265       NSMinX([translateButton frame]) - denyPopUpButtonFrame.size.width
266       - kRelatedControlHorizontalSpacing,
267       yPos + diffY)];
268
269   yPos += NSHeight([translateButton frame]) +
270       kUnrelatedControlVerticalSpacing;
271
272   [textLabel setFrameOrigin:NSMakePoint(0, yPos)];
273   [advancedLinkButton setFrameOrigin:NSMakePoint(
274       NSWidth([textLabel frame]), yPos)];
275
276   [view setFrameSize:NSMakeSize(kContentWidth, NSMaxY([textLabel frame]))];
277
278   return view;
279 }
280
281 - (NSView*)newTranslatingView {
282   NSRect contentFrame = NSMakeRect(
283       kFramePadding,
284       kFramePadding,
285       kContentWidth,
286       0);
287   NSView* view = [[NSView alloc] initWithFrame:contentFrame];
288
289   NSString* message =
290       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_TRANSLATING);
291   NSTextField* textLabel = [self addText:message
292                                   toView:view];
293   NSString* title =
294       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_REVERT);
295   NSButton* showOriginalButton =
296       [self addButton:title
297                action:@selector(handleShowOriginalButtonPressed)
298                toView:view];
299   [showOriginalButton setEnabled:NO];
300
301   // Layout
302   // TODO(hajimehoshi): Use l10n_util::VerticallyReflowGroup.
303   CGFloat yPos = 0;
304
305   [showOriginalButton setFrameOrigin:NSMakePoint(
306       kContentWidth - NSWidth([showOriginalButton frame]), yPos)];
307
308   yPos += NSHeight([showOriginalButton frame]) +
309       kUnrelatedControlVerticalSpacing;
310
311   [textLabel setFrameOrigin:NSMakePoint(0, yPos)];
312
313   [view setFrameSize:NSMakeSize(kContentWidth, NSMaxY([textLabel frame]))];
314
315   return view;
316 }
317
318 - (NSView*)newAfterTranslateView {
319   NSRect contentFrame = NSMakeRect(
320       kFramePadding,
321       kFramePadding,
322       kContentWidth,
323       0);
324   NSView* view = [[NSView alloc] initWithFrame:contentFrame];
325
326   NSString* message =
327       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_TRANSLATED);
328   NSTextField* textLabel = [self addText:message
329                                   toView:view];
330   message = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ADVANCED);
331   NSButton* advancedLinkButton =
332       [self addLinkButtonWithText:message
333                            action:@selector(handleAdvancedLinkButtonPressed)
334                            toView:view];
335   NSString* title =
336       l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_REVERT);
337   NSButton* showOriginalButton =
338       [self addButton:title
339                action:@selector(handleShowOriginalButtonPressed)
340                toView:view];
341
342   // Layout
343   CGFloat yPos = 0;
344
345   [showOriginalButton setFrameOrigin:NSMakePoint(
346       kContentWidth - NSWidth([showOriginalButton frame]), yPos)];
347
348   yPos += NSHeight([showOriginalButton frame]) +
349       kUnrelatedControlVerticalSpacing;
350
351   [textLabel setFrameOrigin:NSMakePoint(0, yPos)];
352   [advancedLinkButton setFrameOrigin:NSMakePoint(
353       NSMaxX([textLabel frame]), yPos)];
354
355   [view setFrameSize:NSMakeSize(kContentWidth, NSMaxY([textLabel frame]))];
356
357   return view;
358 }
359
360 - (NSView*)newErrorView {
361   NSRect contentFrame = NSMakeRect(
362       kFramePadding,
363       kFramePadding,
364       kContentWidth,
365       0);
366   NSView* view = [[NSView alloc] initWithFrame:contentFrame];
367
368   // TODO(hajimehoshi): Implement this.
369
370   return view;
371 }
372
373 - (NSView*)newAdvancedView {
374   NSRect contentFrame = NSMakeRect(
375       kFramePadding,
376       kFramePadding,
377       kContentWidth,
378       0);
379   NSView* view = [[NSView alloc] initWithFrame:contentFrame];
380
381   NSString* title = l10n_util::GetNSStringWithFixup(
382       IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE);
383   NSTextField* sourceLanguageLabel = [self addText:title
384                                             toView:view];
385   title = l10n_util::GetNSStringWithFixup(
386       IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE);
387   NSTextField* targetLanguageLabel = [self addText:title
388                                             toView:view];
389
390   // combobox
391   int sourceDefaultIndex = model_->GetOriginalLanguageIndex();
392   int targetDefaultIndex = model_->GetTargetLanguageIndex();
393   sourceLanguageComboboxModel_.reset(
394       new LanguageComboboxModel(sourceDefaultIndex, model_.get()));
395   targetLanguageComboboxModel_.reset(
396       new LanguageComboboxModel(targetDefaultIndex, model_.get()));
397   SEL action = @selector(handleSourceLanguagePopUpButtonSelectedItemChanged:);
398   NSPopUpButton* sourcePopUpButton =
399       [self addPopUpButton:sourceLanguageComboboxModel_.get()
400                     action:action
401                     toView:view];
402   action = @selector(handleTargetLanguagePopUpButtonSelectedItemChanged:);
403   NSPopUpButton* targetPopUpButton =
404       [self addPopUpButton:targetLanguageComboboxModel_.get()
405                     action:action
406                     toView:view];
407
408   // 'Always translate' checkbox
409   BOOL isIncognitoWindow = webContents_ ?
410       webContents_->GetBrowserContext()->IsOffTheRecord() : NO;
411   if (!isIncognitoWindow) {
412     NSString* title =
413         l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ALWAYS);
414     alwaysTranslateCheckbox_ = [self addCheckbox:title
415                                           toView:view];
416   }
417
418   // Buttons
419   advancedDoneButton_ =
420       [self addButton:l10n_util::GetNSStringWithFixup(IDS_DONE)
421                action:@selector(handleDoneButtonPressed)
422                toView:view];
423   advancedCancelButton_ =
424       [self addButton:l10n_util::GetNSStringWithFixup(IDS_CANCEL)
425                action:@selector(handleCancelButtonPressed)
426                toView:view];
427
428   // Layout
429   CGFloat textLabelWidth = NSWidth([sourceLanguageLabel frame]);
430   if (textLabelWidth < NSWidth([targetLanguageLabel frame]))
431     textLabelWidth = NSWidth([targetLanguageLabel frame]);
432
433   CGFloat yPos = 0;
434
435   [advancedDoneButton_ setFrameOrigin:NSMakePoint(0, yPos)];
436   [advancedCancelButton_ setFrameOrigin:NSMakePoint(0, yPos)];
437
438   yPos += NSHeight([advancedDoneButton_ frame]) +
439       kUnrelatedControlVerticalSpacing;
440
441   if (alwaysTranslateCheckbox_) {
442     [alwaysTranslateCheckbox_ setFrameOrigin:NSMakePoint(textLabelWidth, yPos)];
443
444     yPos += NSHeight([alwaysTranslateCheckbox_ frame]) +
445         kRelatedControlVerticalSpacing;
446   }
447
448   CGFloat diffY = [[sourcePopUpButton cell]
449                    titleRectForBounds:[sourcePopUpButton bounds]].origin.y;
450
451   [targetLanguageLabel setFrameOrigin:NSMakePoint(
452       textLabelWidth - NSWidth([targetLanguageLabel frame]), yPos + diffY)];
453
454   NSRect frame = [targetPopUpButton frame];
455   frame.origin = NSMakePoint(textLabelWidth, yPos);
456   frame.size.width = (kWindowWidth - 2 * kFramePadding) - textLabelWidth;
457   [targetPopUpButton setFrame:frame];
458
459   yPos += NSHeight([targetPopUpButton frame]) +
460       kRelatedControlVerticalSpacing;
461
462   [sourceLanguageLabel setFrameOrigin:NSMakePoint(
463       textLabelWidth - NSWidth([sourceLanguageLabel frame]), yPos + diffY)];
464
465   frame = [sourcePopUpButton frame];
466   frame.origin = NSMakePoint(textLabelWidth, yPos);
467   frame.size.width = NSWidth([targetPopUpButton frame]);
468   [sourcePopUpButton setFrame:frame];
469
470   [view setFrameSize:NSMakeSize(kContentWidth,
471                                 NSMaxY([sourcePopUpButton frame]))];
472
473   [self updateAdvancedView];
474
475   return view;
476 }
477
478 - (void)updateAdvancedView {
479   NSInteger state = model_->ShouldAlwaysTranslate() ? NSOnState : NSOffState;
480   [alwaysTranslateCheckbox_ setState:state];
481
482   NSString* title;
483   if (model_->IsPageTranslatedInCurrentLanguages())
484     title = l10n_util::GetNSStringWithFixup(IDS_DONE);
485   else
486     title = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ACCEPT);
487   [advancedDoneButton_ setTitle:title];
488   [advancedDoneButton_ sizeToFit];
489
490   NSRect frame = [advancedDoneButton_ frame];
491   frame.origin.x = (kWindowWidth - 2 * kFramePadding) - NSWidth(frame);
492   [advancedDoneButton_ setFrameOrigin:frame.origin];
493
494   frame = [advancedCancelButton_ frame];
495   frame.origin.x = NSMinX([advancedDoneButton_ frame]) - NSWidth(frame)
496       - kRelatedControlHorizontalSpacing;
497   [advancedCancelButton_ setFrameOrigin:frame.origin];
498 }
499
500 - (NSTextField*)addText:(NSString*)text
501                  toView:(NSView*)view {
502   base::scoped_nsobject<NSTextField> textField(
503       [[NSTextField alloc] initWithFrame:NSZeroRect]);
504   [textField setEditable:NO];
505   [textField setSelectable:YES];
506   [textField setDrawsBackground:NO];
507   [textField setBezeled:NO];
508   [textField setStringValue:text];
509   NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
510   [textField setFont:font];
511   [textField setAutoresizingMask:NSViewWidthSizable];
512   [view addSubview:textField.get()];
513
514   [textField sizeToFit];
515   return textField.get();
516 }
517
518 - (NSButton*)addLinkButtonWithText:(NSString*)text
519                             action:(SEL)action
520                             toView:(NSView*)view {
521   base::scoped_nsobject<NSButton> button(
522       [[HyperlinkButtonCell buttonWithString:text] retain]);
523
524   [button setButtonType:NSMomentaryPushInButton];
525   [button setBezelStyle:NSRegularSquareBezelStyle];
526   [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
527   [button sizeToFit];
528   [button setTarget:self];
529   [button setAction:action];
530
531   [view addSubview:button.get()];
532
533   return button.get();
534 }
535
536 - (NSButton*)addButton:(NSString*)title
537                 action:(SEL)action
538                 toView:(NSView*)view {
539   base::scoped_nsobject<NSButton> button(
540       [[NSButton alloc] initWithFrame:NSZeroRect]);
541   [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
542   [button setTitle:title];
543   [button setBezelStyle:NSRoundedBezelStyle];
544   [[button cell] setControlSize:NSSmallControlSize];
545   [button sizeToFit];
546   [button setTarget:self];
547   [button setAction:action];
548
549   [view addSubview:button.get()];
550
551   return button.get();
552 }
553
554 - (NSButton*)addCheckbox:(NSString*)title
555                   toView:(NSView*)view {
556   base::scoped_nsobject<NSButton> button(
557       [[NSButton alloc] initWithFrame:NSZeroRect]);
558   [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
559   [button setTitle:title];
560   [[button cell] setControlSize:NSSmallControlSize];
561   [button setButtonType:NSSwitchButton];
562   [button sizeToFit];
563
564   [view addSubview:button.get()];
565
566   return button.get();
567 }
568
569 - (NSPopUpButton*)addPopUpButton:(ui::ComboboxModel*)model
570                           action:(SEL)action
571                           toView:(NSView*)view {
572   base::scoped_nsobject<NSPopUpButton> button(
573       [[BubbleCombobox alloc] initWithFrame:NSZeroRect
574                                   pullsDown:NO
575                                       model:model]);
576   [button setTarget:self];
577   [button setAction:action];
578   [button sizeToFit];
579   [view addSubview:button.get()];
580   return button.get();
581 }
582
583 - (void)handleTranslateButtonPressed {
584   translateExecuted_ = YES;
585   model_->Translate();
586 }
587
588 - (void)handleNopeButtonPressed {
589   [self close];
590 }
591
592 - (void)handleDoneButtonPressed {
593   if (alwaysTranslateCheckbox_) {
594     model_->SetAlwaysTranslate(
595         [alwaysTranslateCheckbox_ state] == NSOnState);
596   }
597   if (model_->IsPageTranslatedInCurrentLanguages()) {
598     model_->GoBackFromAdvanced();
599     [self performLayout];
600   } else {
601     translateExecuted_ = true;
602     model_->Translate();
603     [self switchView:TranslateBubbleModel::VIEW_STATE_TRANSLATING];
604   }
605 }
606
607 - (void)handleCancelButtonPressed {
608   model_->GoBackFromAdvanced();
609   [self performLayout];
610 }
611
612 - (void)handleShowOriginalButtonPressed {
613   model_->RevertTranslation();
614   [self close];
615 }
616
617 - (void)handleAdvancedLinkButtonPressed {
618   [self switchView:TranslateBubbleModel::VIEW_STATE_ADVANCED];
619 }
620
621 - (void)handleDenialPopUpButtonNopeSelected {
622   [self close];
623 }
624
625 - (void)handleDenialPopUpButtonNeverTranslateLanguageSelected {
626   model_->SetNeverTranslateLanguage(true);
627   [self close];
628 }
629
630 - (void)handleDenialPopUpButtonNeverTranslateSiteSelected {
631   model_->SetNeverTranslateSite(true);
632   [self close];
633 }
634
635 - (void)handleSourceLanguagePopUpButtonSelectedItemChanged:(id)sender {
636   NSPopUpButton* button = base::mac::ObjCCastStrict<NSPopUpButton>(sender);
637   model_->UpdateOriginalLanguageIndex([button indexOfSelectedItem]);
638   [self updateAdvancedView];
639 }
640
641 - (void)handleTargetLanguagePopUpButtonSelectedItemChanged:(id)sender {
642   NSPopUpButton* button = base::mac::ObjCCastStrict<NSPopUpButton>(sender);
643   model_->UpdateTargetLanguageIndex([button indexOfSelectedItem]);
644   [self updateAdvancedView];
645 }
646
647 @end