| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2010 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 <Cocoa/Cocoa.h> |
| 6 #import "chrome/browser/cocoa/translate_infobar.h" |
| 7 |
| 8 #include "app/l10n_util.h" |
| 9 #include "base/logging.h" // for NOTREACHED() |
| 10 #include "base/mac_util.h" |
| 11 #include "base/sys_string_conversions.h" |
| 12 #include "chrome/app/chrome_dll_resource.h" |
| 13 #import "chrome/browser/cocoa/hover_close_button.h" |
| 14 #include "chrome/browser/cocoa/infobar.h" |
| 15 #import "chrome/browser/cocoa/infobar_controller.h" |
| 16 #import "chrome/browser/cocoa/infobar_gradient_view.h" |
| 17 #include "chrome/browser/tab_contents/tab_contents.h" |
| 18 #include "chrome/browser/translate/translate_infobars_delegates.h" |
| 19 #include "chrome/common/notification_service.h" |
| 20 #include "grit/generated_resources.h" |
| 21 #include "grit/locale_settings.h" |
| 22 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" |
| 23 |
| 24 // Colors for translate infobar gradient background. |
| 25 const int kBlueTopColor[] = {0xDA, 0xE7, 0xF9}; |
| 26 const int kBlueBottomColor[] = {0xB3, 0xCA, 0xE7}; |
| 27 |
| 28 #pragma mark Anonymous helper functions. |
| 29 namespace { |
| 30 |
| 31 // Move the |toMove| view |spacing| pixels before/after the |anchor| view. |
| 32 // |after| signifies the side of |anchor| on which to place |toMove|. |
| 33 void MoveControl(NSView* anchor, NSView* toMove, int spacing, bool after) { |
| 34 NSRect anchorFrame = [anchor frame]; |
| 35 NSRect toMoveFrame = [toMove frame]; |
| 36 |
| 37 // At the time of this writing, OS X doesn't natively support BiDi UIs, but |
| 38 // it doesn't hurt to be forward looking. |
| 39 bool toRight = after; |
| 40 |
| 41 if (toRight) { |
| 42 toMoveFrame.origin.x = NSMaxX(anchorFrame) + spacing; |
| 43 } else { |
| 44 // Place toMove to theleft of anchor. |
| 45 toMoveFrame.origin.x = NSMinX(anchorFrame) - |
| 46 spacing - NSWidth(toMoveFrame); |
| 47 } |
| 48 [toMove setFrame:toMoveFrame]; |
| 49 } |
| 50 |
| 51 // Vertically center |toMove| in its container. |
| 52 void VerticallyCenterView(NSView *toMove) { |
| 53 NSRect superViewFrame = [[toMove superview] frame]; |
| 54 NSRect viewFrame = [toMove frame]; |
| 55 |
| 56 viewFrame.origin.y = |
| 57 floor((NSHeight(superViewFrame) - NSHeight(viewFrame))/2.0); |
| 58 [toMove setFrame:viewFrame]; |
| 59 } |
| 60 |
| 61 // Creates a label control in the style we need for the translate infobar's |
| 62 // labels within |bounds|. |
| 63 NSTextField* CreateLabel(NSRect bounds) { |
| 64 NSTextField* ret = [[NSTextField alloc] initWithFrame:bounds]; |
| 65 [ret setEditable:NO]; |
| 66 [ret setDrawsBackground:NO]; |
| 67 [ret setBordered:NO]; |
| 68 return ret; |
| 69 } |
| 70 |
| 71 // Adds an item with the specified properties to |menu|. |
| 72 void AddMenuItem(NSMenu *menu, id target, NSString* title, int tag, |
| 73 bool checked) { |
| 74 NSMenuItem* item = [[[NSMenuItem alloc] |
| 75 initWithTitle:title |
| 76 action:@selector(menuItemSelected:) |
| 77 keyEquivalent:@""] autorelease]; |
| 78 [item setTag:tag]; |
| 79 [menu addItem:item]; |
| 80 [item setTarget:target]; |
| 81 if (checked) |
| 82 [item setState:NSOnState]; |
| 83 } |
| 84 |
| 85 } // namespace |
| 86 |
| 87 #pragma mark TranslateInfoBarMenuModel class definition |
| 88 // Bridge class to handle interfacing with menu controllers from popup |
| 89 // menus in infobar. |
| 90 class TranslateInfoBarMenuModel : public menus::SimpleMenuModel::Delegate { |
| 91 public: |
| 92 TranslateInfoBarMenuModel(TranslateInfoBarDelegate* delegate, |
| 93 TranslateInfoBarController* controller) : |
| 94 translate_delegate_(delegate), |
| 95 controller_(controller) {} |
| 96 |
| 97 // Overridden from menus::SimpleMenuModel::Delegate: |
| 98 virtual bool IsCommandIdChecked(int command_id) const; |
| 99 virtual bool IsCommandIdEnabled(int command_id) const; |
| 100 virtual bool GetAcceleratorForCommandId(int command_id, |
| 101 menus::Accelerator* accelerator); |
| 102 virtual void ExecuteCommand(int command_id); |
| 103 |
| 104 private: |
| 105 TranslateInfoBarDelegate* translate_delegate_; // weak |
| 106 TranslateInfoBarController* controller_; // weak |
| 107 DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarMenuModel); |
| 108 }; |
| 109 |
| 110 #pragma mark TranslateNotificationObserverBridge class definition |
| 111 // Bridge class to allow obj-c TranslateInfoBarController to observe |
| 112 // notifications. |
| 113 class TranslateNotificationObserverBridge : |
| 114 public NotificationObserver { |
| 115 public: |
| 116 TranslateNotificationObserverBridge( |
| 117 TranslateInfoBarDelegate* delegate, |
| 118 TranslateInfoBarController* controller); |
| 119 |
| 120 // Overridden from NotificationObserver: |
| 121 virtual void Observe(NotificationType type, |
| 122 const NotificationSource& source, |
| 123 const NotificationDetails& details); |
| 124 |
| 125 private: |
| 126 TranslateInfoBarDelegate* translate_delegate_; // weak |
| 127 TranslateInfoBarController* controller_; // weak |
| 128 NotificationRegistrar notification_registrar_; |
| 129 DISALLOW_COPY_AND_ASSIGN(TranslateNotificationObserverBridge); |
| 130 }; |
| 131 |
| 132 @interface TranslateInfoBarController (Private) |
| 133 |
| 134 // Returns the main translate delegate. |
| 135 - (TranslateInfoBarDelegate*)delegate; |
| 136 |
| 137 // Main function to update the toolbar graphic state and data model after |
| 138 // the state has changed. |
| 139 // Controls are moved around as needed and visibility changed to match the |
| 140 // current state. |
| 141 // |newState| is the state we're transitioning to. |
| 142 // |initialDisplay| is true if we're being called when initially displaying |
| 143 // and not because of a state transition. |
| 144 - (void)updateState:(TranslateInfoBarDelegate::TranslateState)newState |
| 145 initialDisplay:(bool)initialDisplay; |
| 146 |
| 147 // Make the infobar blue. |
| 148 - (void)setInfoBarGradientColor; |
| 149 |
| 150 // Reloads text for all labels for the current state. |
| 151 - (void)loadLabelText; |
| 152 |
| 153 // Resizes controls and hides/shows them based on state transition. |
| 154 // Called before layout; |
| 155 - (void)resizeAndSetControlVisibility; |
| 156 |
| 157 // Move all the currently visible views into the correct place for the |
| 158 // current mode. |
| 159 - (void)layout; |
| 160 |
| 161 // Create all the various controls we need for the toolbar. |
| 162 - (void)constructViews; |
| 163 |
| 164 // Called when the source or target language selection changes in a menu. |
| 165 // |newLanguageIdx| is the index of the newly selected item in the appropriate |
| 166 // menu. |
| 167 - (void)sourceLanguageModified:(NSInteger)newLanguageIdx; |
| 168 - (void)targetLanguageModified:(NSInteger)newLanguageIdx; |
| 169 |
| 170 // Called when the source or target language have changed to update the |
| 171 // model state and refresh the GUI. |
| 172 - (void)languageModified; |
| 173 |
| 174 // Completely rebuild "from" and "to" language menus from the data model. |
| 175 - (void)populateLanguageMenus; |
| 176 |
| 177 // Teardown and rebuild the options menu. |
| 178 - (void)rebuildOptionsMenu; |
| 179 |
| 180 @end |
| 181 |
| 182 #pragma mark TranslateInfoBarController class |
| 183 @implementation TranslateInfoBarController |
| 184 |
| 185 - (id)initWithDelegate:(InfoBarDelegate*)delegate { |
| 186 if ((self = [super initWithDelegate:delegate])) { |
| 187 observer_bridge_.reset( |
| 188 new TranslateNotificationObserverBridge([self delegate], self)); |
| 189 |
| 190 original_language_menu_model_.reset( |
| 191 new LanguagesMenuModel(menu_model_.get(), [self delegate], |
| 192 /*original_language=*/true)); |
| 193 |
| 194 target_language_menu_model_.reset( |
| 195 new LanguagesMenuModel(menu_model_.get(), [self delegate], |
| 196 /*original_language=*/false)); |
| 197 |
| 198 menu_model_.reset(new TranslateInfoBarMenuModel([self delegate], self)); |
| 199 } |
| 200 return self; |
| 201 } |
| 202 |
| 203 - (TranslateInfoBarDelegate*)delegate { |
| 204 return reinterpret_cast<TranslateInfoBarDelegate*>(delegate_); |
| 205 } |
| 206 |
| 207 - (void)constructViews { |
| 208 // Using a zero or very large frame causes GTMUILocalizerAndLayoutTweaker |
| 209 // to not resize the view properly so we take the bounds of the first label |
| 210 // which is contained in the nib. |
| 211 NSRect bogusFrame = [label_ frame]; |
| 212 label2_.reset(CreateLabel(bogusFrame)); |
| 213 label3_.reset(CreateLabel(bogusFrame)); |
| 214 translatingLabel_.reset(CreateLabel(bogusFrame)); |
| 215 |
| 216 optionsPopUp_.reset([[NSPopUpButton alloc] initWithFrame:bogusFrame |
| 217 pullsDown:YES]); |
| 218 fromLanguagePopUp_.reset([[NSPopUpButton alloc] initWithFrame:bogusFrame |
| 219 pullsDown:NO]); |
| 220 toLanguagePopUp_.reset([[NSPopUpButton alloc] initWithFrame:bogusFrame |
| 221 pullsDown:NO]); |
| 222 } |
| 223 |
| 224 - (void)sourceLanguageModified:(NSInteger)newLanguageIdx { |
| 225 DCHECK_GT(newLanguageIdx, 0); |
| 226 |
| 227 if (newLanguageIdx == [self delegate]->original_lang_index()) |
| 228 return; |
| 229 |
| 230 [self delegate]->ModifyOriginalLanguage(newLanguageIdx); |
| 231 [fromLanguagePopUp_ selectItemAtIndex:newLanguageIdx]; |
| 232 |
| 233 [self languageModified]; |
| 234 } |
| 235 |
| 236 - (void)targetLanguageModified:(NSInteger)newLanguageIdx { |
| 237 DCHECK_GT(newLanguageIdx, 0); |
| 238 if (newLanguageIdx == [self delegate]->target_lang_index()) |
| 239 return; |
| 240 |
| 241 [self delegate]->ModifyTargetLanguage(newLanguageIdx); |
| 242 [toLanguagePopUp_ selectItemAtIndex:newLanguageIdx]; |
| 243 [self languageModified]; |
| 244 } |
| 245 |
| 246 - (void)languageModified { |
| 247 // If necessary, update state and translate. |
| 248 [self rebuildOptionsMenu]; |
| 249 |
| 250 // Selecting an item from the "from language" menu in the before translate |
| 251 // phase shouldn't trigger translation - http://crbug.com/36666 |
| 252 if ([self delegate]->state() == TranslateInfoBarDelegate::kAfterTranslate) |
| 253 [self delegate]->Translate(); |
| 254 } |
| 255 |
| 256 - (void)updateState:(TranslateInfoBarDelegate::TranslateState)newState |
| 257 initialDisplay:(bool)initialDisplay { |
| 258 // If this isn't a call from the constructor, only procede if the state |
| 259 // has changed. |
| 260 if (!initialDisplay && newState == [self delegate]->state()) |
| 261 return; |
| 262 |
| 263 // Update the data model. |
| 264 [self delegate]->UpdateState(newState); |
| 265 |
| 266 // Fixup our GUI. |
| 267 TranslateInfoBarDelegate::TranslateState state = [self delegate]->state(); |
| 268 |
| 269 if (state != TranslateInfoBarDelegate::kTranslating) { |
| 270 [self loadLabelText]; |
| 271 [self rebuildOptionsMenu]; |
| 272 } |
| 273 |
| 274 [self resizeAndSetControlVisibility]; |
| 275 [self layout]; |
| 276 } |
| 277 |
| 278 - (void)setInfoBarGradientColor { |
| 279 // Use blue gradient for the infobars. |
| 280 NSColor* startingColor = |
| 281 [NSColor colorWithCalibratedRed:kBlueTopColor[0] / 255.0 |
| 282 green:kBlueTopColor[1] / 255.0 |
| 283 blue:kBlueTopColor[2] / 255.0 |
| 284 alpha:1.0]; |
| 285 NSColor* endingColor = |
| 286 [NSColor colorWithCalibratedRed:kBlueBottomColor[0] / 255.0 |
| 287 green:kBlueBottomColor[1] / 255.0 |
| 288 blue:kBlueBottomColor[2] / 255.0 |
| 289 alpha:1.0]; |
| 290 NSGradient* translateInfoBarGradient = |
| 291 [[[NSGradient alloc] initWithStartingColor:startingColor |
| 292 endingColor:endingColor] autorelease]; |
| 293 |
| 294 [infoBarView_ setGradient:translateInfoBarGradient]; |
| 295 } |
| 296 |
| 297 - (void)resizeAndSetControlVisibility { |
| 298 switch ([self delegate]->state()) { |
| 299 case TranslateInfoBarDelegate::kBeforeTranslate: { |
| 300 // Size to fit and set resize attributes for all visible controls. |
| 301 NSArray *controls = [NSArray arrayWithObjects:okButton_, cancelButton_, |
| 302 label_, label2_.get(), optionsPopUp_.get(), nil]; |
| 303 for (NSControl* control in controls) { |
| 304 [GTMUILocalizerAndLayoutTweaker sizeToFitView:control]; |
| 305 [control setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin | |
| 306 NSViewMaxYMargin]; |
| 307 } |
| 308 [fromLanguagePopUp_ setAutoresizingMask:NSViewMaxXMargin | |
| 309 NSViewMinYMargin | NSViewMaxYMargin]; |
| 310 [optionsPopUp_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin | |
| 311 NSViewMaxYMargin]; |
| 312 |
| 313 // Make "from language" popup menu the same size as the options menu. |
| 314 // We don't autosize since some languages names are really long causing |
| 315 // the toolbar to overflow. |
| 316 NSRect optionsFrame = [optionsPopUp_ frame]; |
| 317 [fromLanguagePopUp_ setFrame:optionsFrame]; |
| 318 |
| 319 [infoBarView_ addSubview:label2_]; |
| 320 [infoBarView_ addSubview:fromLanguagePopUp_]; |
| 321 |
| 322 // Add "options" popup z-ordered below all other controls so when we |
| 323 // resize the toolbar it doesn't hide them. |
| 324 [infoBarView_ addSubview:optionsPopUp_ |
| 325 positioned:NSWindowBelow |
| 326 relativeTo:nil]; |
| 327 break; |
| 328 } |
| 329 |
| 330 case TranslateInfoBarDelegate::kTranslating: |
| 331 [okButton_ removeFromSuperview]; |
| 332 [cancelButton_ removeFromSuperview]; |
| 333 [infoBarView_ addSubview:translatingLabel_]; |
| 334 [GTMUILocalizerAndLayoutTweaker sizeToFitView:translatingLabel_]; |
| 335 [translatingLabel_ setAutoresizingMask:NSViewMaxXMargin | |
| 336 NSViewMinYMargin | NSViewMaxYMargin]; |
| 337 break; |
| 338 |
| 339 case TranslateInfoBarDelegate::kAfterTranslate: { |
| 340 [translatingLabel_ removeFromSuperview]; |
| 341 |
| 342 [infoBarView_ addSubview:toLanguagePopUp_]; |
| 343 if (numLabelsDisplayed_ == 3) |
| 344 [infoBarView_ addSubview:label3_]; |
| 345 |
| 346 // Label contents may have changed. |
| 347 NSArray *controls = [NSArray arrayWithObjects:label_, label2_.get(), |
| 348 label3_.get(), nil]; |
| 349 for (NSControl* control in controls) { |
| 350 [GTMUILocalizerAndLayoutTweaker sizeToFitView:control]; |
| 351 [control setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin | |
| 352 NSViewMaxYMargin]; |
| 353 } |
| 354 |
| 355 // See note on sizeing fromLanguagePopUp_ above. |
| 356 NSRect optionsFrame = [optionsPopUp_ frame]; |
| 357 [toLanguagePopUp_ setFrame:optionsFrame]; |
| 358 break; |
| 359 } |
| 360 |
| 361 default: |
| 362 NOTREACHED() << "Invalid translate state change"; |
| 363 break; |
| 364 } |
| 365 } |
| 366 |
| 367 - (void)layout { |
| 368 // This method assumes that the toolbar starts out in |kBeforeTranslate| |
| 369 // translate state and progresses unidirectionally and contiguously through |
| 370 // the other states. |
| 371 // Under these assumptions, the changes we make can be cumulative rather than |
| 372 // repositioning elements multiple times. |
| 373 switch ([self delegate]->state()) { |
| 374 case TranslateInfoBarDelegate::kBeforeTranslate: |
| 375 MoveControl(label_, fromLanguagePopUp_, 0, true); |
| 376 MoveControl(fromLanguagePopUp_, label2_, 0, true); |
| 377 MoveControl(label2_, okButton_, spaceBetweenControls_, true); |
| 378 MoveControl(okButton_, cancelButton_, spaceBetweenControls_, true); |
| 379 |
| 380 // 3rd label is only displayed in some locales, but should never be |
| 381 // visible in the before translate stage. |
| 382 // If it ever is visible then we need to move it into position here. |
| 383 DCHECK(numLabelsDisplayed_ < 3); |
| 384 |
| 385 MoveControl(closeButton_, optionsPopUp_, spaceBetweenControls_, false); |
| 386 |
| 387 // Vertically center popup menus. |
| 388 VerticallyCenterView(fromLanguagePopUp_); |
| 389 VerticallyCenterView(optionsPopUp_); |
| 390 break; |
| 391 |
| 392 case TranslateInfoBarDelegate::kTranslating: |
| 393 MoveControl(label2_, translatingLabel_, spaceBetweenControls_ * 2, true); |
| 394 break; |
| 395 |
| 396 |
| 397 case TranslateInfoBarDelegate::kAfterTranslate: |
| 398 MoveControl(label_, fromLanguagePopUp_, 0, true); |
| 399 MoveControl(fromLanguagePopUp_, label2_, 0, true); |
| 400 MoveControl(label2_, toLanguagePopUp_, 0, true); |
| 401 if (numLabelsDisplayed_ == 3) |
| 402 MoveControl(toLanguagePopUp_, label3_, 0, true); |
| 403 VerticallyCenterView(toLanguagePopUp_); |
| 404 break; |
| 405 |
| 406 default: |
| 407 NOTREACHED() << "Invalid translate state change"; |
| 408 break; |
| 409 } |
| 410 } |
| 411 |
| 412 - (void) rebuildOptionsMenu { |
| 413 // The options model doesn't know how to handle state transitions, so rebuild |
| 414 // it each time through here. |
| 415 options_menu_model_.reset( |
| 416 new OptionsMenuModel(menu_model_.get(), [self delegate])); |
| 417 |
| 418 [optionsPopUp_ removeAllItems]; |
| 419 // Set title. |
| 420 NSString* optionsLabel = |
| 421 l10n_util::GetNSString(IDS_TRANSLATE_INFOBAR_OPTIONS); |
| 422 [optionsPopUp_ addItemWithTitle:optionsLabel]; |
| 423 |
| 424 // Populate options menu. |
| 425 NSMenu* optionsMenu = [optionsPopUp_ menu]; |
| 426 for (int i = 0; i < options_menu_model_->GetItemCount(); ++i) { |
| 427 NSString* title = base::SysUTF16ToNSString( |
| 428 options_menu_model_->GetLabelAt(i)); |
| 429 int cmd = options_menu_model_->GetCommandIdAt(i); |
| 430 bool checked = options_menu_model_->IsItemCheckedAt(i); |
| 431 AddMenuItem(optionsMenu, self, title, cmd, checked); |
| 432 } |
| 433 } |
| 434 |
| 435 - (void)populateLanguageMenus { |
| 436 NSMenu* originalLanguageMenu = [fromLanguagePopUp_ menu]; |
| 437 int selectedIndex = [self delegate]->original_lang_index(); |
| 438 for (int i = 0; i < original_language_menu_model_->GetItemCount(); ++i) { |
| 439 NSString* title = base::SysUTF16ToNSString( |
| 440 original_language_menu_model_->GetLabelAt(i)); |
| 441 int cmd = original_language_menu_model_->GetCommandIdAt(i); |
| 442 bool checked = i == selectedIndex; |
| 443 AddMenuItem(originalLanguageMenu, self, title, cmd, checked); |
| 444 } |
| 445 [fromLanguagePopUp_ selectItemAtIndex:selectedIndex]; |
| 446 |
| 447 NSMenu* targetLanguageMenu = [toLanguagePopUp_ menu]; |
| 448 selectedIndex = [self delegate]->target_lang_index(); |
| 449 for (int i = 0; i < target_language_menu_model_->GetItemCount(); ++i) { |
| 450 NSString* title = base::SysUTF16ToNSString( |
| 451 target_language_menu_model_->GetLabelAt(i)); |
| 452 int cmd = target_language_menu_model_->GetCommandIdAt(i); |
| 453 bool checked = i == selectedIndex; |
| 454 if (checked) |
| 455 selectedIndex = i; |
| 456 AddMenuItem(targetLanguageMenu, self, title, cmd, checked); |
| 457 } |
| 458 [toLanguagePopUp_ selectItemAtIndex:selectedIndex]; |
| 459 } |
| 460 |
| 461 - (void)loadLabelText { |
| 462 string16 message_text_utf16; |
| 463 std::vector<size_t> offsets; |
| 464 [self delegate]->GetMessageText(&message_text_utf16, &offsets, |
| 465 &swappedLanguagePlaceholders_); |
| 466 |
| 467 NSString* message_text = base::SysUTF16ToNSString(message_text_utf16); |
| 468 NSRange label1Range = NSMakeRange(0, offsets[0]); |
| 469 NSString* label1Text = [message_text substringWithRange:label1Range]; |
| 470 NSRange label2Range = NSMakeRange(offsets[0], |
| 471 offsets[1] - offsets[0]); |
| 472 NSString* label2Text = [message_text substringWithRange:label2Range]; |
| 473 [label_ setStringValue:label1Text]; |
| 474 [label2_ setStringValue:label2Text]; |
| 475 |
| 476 numLabelsDisplayed_ = 2; |
| 477 |
| 478 // If this locale requires a 3rd label for the status message. |
| 479 if (offsets.size() == 3) { |
| 480 NSRange label3Range = NSMakeRange(offsets[1], |
| 481 offsets[2] - offsets[1]); |
| 482 NSString* label3Text = [message_text substringWithRange:label3Range]; |
| 483 [label3_ setStringValue:label3Text]; |
| 484 numLabelsDisplayed_ = 3; |
| 485 } |
| 486 } |
| 487 |
| 488 - (void)addAdditionalControls { |
| 489 using l10n_util::GetNSString; |
| 490 using l10n_util::GetNSStringWithFixup; |
| 491 |
| 492 // Get layout information from the NIB. |
| 493 NSRect okButtonFrame = [okButton_ frame]; |
| 494 NSRect cancelButtonFrame = [cancelButton_ frame]; |
| 495 spaceBetweenControls_ = NSMinX(cancelButtonFrame) - NSMaxX(okButtonFrame); |
| 496 |
| 497 // Set infobar background color. |
| 498 [self setInfoBarGradientColor]; |
| 499 |
| 500 // Instantiate additional controls. |
| 501 [self constructViews]; |
| 502 |
| 503 [self populateLanguageMenus]; |
| 504 |
| 505 // Set OK & Cancel text. |
| 506 [okButton_ setTitle:GetNSStringWithFixup(IDS_TRANSLATE_INFOBAR_ACCEPT)]; |
| 507 [cancelButton_ setTitle:GetNSStringWithFixup(IDS_TRANSLATE_INFOBAR_DENY)]; |
| 508 [translatingLabel_ |
| 509 setStringValue:GetNSString(IDS_TRANSLATE_INFOBAR_TRANSLATING)]; |
| 510 |
| 511 // Show and place GUI elements. |
| 512 [self updateState:TranslateInfoBarDelegate::kBeforeTranslate |
| 513 initialDisplay:true]; |
| 514 } |
| 515 |
| 516 // Called when "Translate" button is clicked. |
| 517 - (IBAction)ok:(id)sender { |
| 518 DCHECK( |
| 519 [self delegate]->state() == TranslateInfoBarDelegate::kBeforeTranslate); |
| 520 [self updateState:TranslateInfoBarDelegate::kTranslating |
| 521 initialDisplay:false]; |
| 522 [self delegate]->Translate(); |
| 523 } |
| 524 |
| 525 // Called when someone clicks on the "Nope" button. |
| 526 - (IBAction)cancel:(id)sender { |
| 527 DCHECK( |
| 528 [self delegate]->state() == TranslateInfoBarDelegate::kBeforeTranslate); |
| 529 [self delegate]->TranslationDeclined(); |
| 530 [super dismiss:nil]; |
| 531 } |
| 532 |
| 533 - (void)menuItemSelected:(id)item { |
| 534 if ([item respondsToSelector:@selector(tag)]) { |
| 535 int cmd = [item tag]; |
| 536 menu_model_->ExecuteCommand(cmd); |
| 537 } else { |
| 538 NOTREACHED(); |
| 539 } |
| 540 } |
| 541 |
| 542 @end |
| 543 |
| 544 #pragma mark CreateInfoBar implementation. |
| 545 InfoBar* TranslateInfoBarDelegate::CreateInfoBar() { |
| 546 TranslateInfoBarController* controller = |
| 547 [[TranslateInfoBarController alloc] initWithDelegate:this]; |
| 548 return new InfoBar(controller); |
| 549 } |
| 550 |
| 551 #pragma mark menus::SimpleMenuModel::Delegates |
| 552 |
| 553 bool TranslateInfoBarMenuModel::IsCommandIdChecked(int command_id) const { |
| 554 switch (command_id) { |
| 555 case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG : |
| 556 return translate_delegate_->IsLanguageBlacklisted(); |
| 557 |
| 558 case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE : |
| 559 return translate_delegate_->IsSiteBlacklisted(); |
| 560 |
| 561 case IDC_TRANSLATE_OPTIONS_ALWAYS : |
| 562 return translate_delegate_->ShouldAlwaysTranslate(); |
| 563 |
| 564 default: |
| 565 NOTREACHED() << "Invalid command_id from menu"; |
| 566 break; |
| 567 } |
| 568 return false; |
| 569 } |
| 570 |
| 571 bool TranslateInfoBarMenuModel::IsCommandIdEnabled(int command_id) const { |
| 572 return true; |
| 573 } |
| 574 |
| 575 bool TranslateInfoBarMenuModel::GetAcceleratorForCommandId(int command_id, |
| 576 menus::Accelerator* accelerator) { |
| 577 return false; |
| 578 } |
| 579 |
| 580 void TranslateInfoBarMenuModel::ExecuteCommand(int command_id) { |
| 581 if (command_id >= IDC_TRANSLATE_TARGET_LANGUAGE_BASE) { |
| 582 int language_command_id = |
| 583 command_id - IDC_TRANSLATE_TARGET_LANGUAGE_BASE; |
| 584 [controller_ |
| 585 targetLanguageModified:language_command_id]; |
| 586 } else if (command_id >= IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE) { |
| 587 int language_command_id = |
| 588 command_id - IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE; |
| 589 [controller_ |
| 590 sourceLanguageModified:language_command_id]; |
| 591 } else { |
| 592 switch (command_id) { |
| 593 case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG: |
| 594 translate_delegate_->ToggleLanguageBlacklist(); |
| 595 break; |
| 596 |
| 597 case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE: |
| 598 translate_delegate_->ToggleSiteBlacklist(); |
| 599 break; |
| 600 |
| 601 case IDC_TRANSLATE_OPTIONS_ALWAYS: |
| 602 translate_delegate_->ToggleAlwaysTranslate(); |
| 603 break; |
| 604 |
| 605 case IDC_TRANSLATE_OPTIONS_ABOUT: { |
| 606 TabContents* tab_contents = translate_delegate_->tab_contents(); |
| 607 if (tab_contents) { |
| 608 string16 url = l10n_util::GetStringUTF16( |
| 609 IDS_ABOUT_GOOGLE_TRANSLATE_URL); |
| 610 tab_contents->OpenURL(GURL(url), GURL(), NEW_FOREGROUND_TAB, |
| 611 PageTransition::LINK); |
| 612 } |
| 613 break; |
| 614 } |
| 615 |
| 616 default: |
| 617 NOTREACHED() << "Invalid command id from menu."; |
| 618 break; |
| 619 } |
| 620 } |
| 621 } |
| 622 |
| 623 # pragma mark TranslateInfoBarNotificationObserverBridge |
| 624 |
| 625 TranslateNotificationObserverBridge::TranslateNotificationObserverBridge( |
| 626 TranslateInfoBarDelegate* delegate, |
| 627 TranslateInfoBarController* controller) : |
| 628 translate_delegate_(delegate), |
| 629 controller_(controller) { |
| 630 // Register for PAGE_TRANSLATED notification. |
| 631 notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED, |
| 632 Source<TabContents>(translate_delegate_->tab_contents())); |
| 633 }; |
| 634 |
| 635 void TranslateNotificationObserverBridge::Observe(NotificationType type, |
| 636 const NotificationSource& source, const NotificationDetails& details) { |
| 637 if (type.value != NotificationType::PAGE_TRANSLATED) |
| 638 return; |
| 639 TabContents* tab = Source<TabContents>(source).ptr(); |
| 640 if (tab != translate_delegate_->tab_contents()) |
| 641 return; |
| 642 [controller_ updateState:TranslateInfoBarDelegate::kAfterTranslate |
| 643 initialDisplay:false]; |
| 644 |
| 645 } |
| OLD | NEW |