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