summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/infobars
diff options
context:
space:
mode:
authorkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-29 16:41:53 +0000
committerkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-29 16:41:53 +0000
commit8db841ac0528a7eba71e89260526da9ba33dbb54 (patch)
tree79501d52aa828b2bbaf87e91064f978851d702d2 /chrome/browser/views/infobars
parent89e29d25efa776ed1f564e576d764fd3e9ddecfc (diff)
downloadchromium_src-8db841ac0528a7eba71e89260526da9ba33dbb54.zip
chromium_src-8db841ac0528a7eba71e89260526da9ba33dbb54.tar.gz
chromium_src-8db841ac0528a7eba71e89260526da9ba33dbb54.tar.bz2
implement error state for translate infobar
- this cl implements the UI on Windows and the partial backend of IPC messaging to include error type - implement error state - add translate error types - use a structure as details for IPC messaging between render view and browser so as to include error type (was using std::pair) - translate delegate handles error state and provides mapping to error messages - infobar handles visual error states - modify background painting to handle normal and error backgrounds, and animation of cross-fading between the 2 backgrounds - infobar now stores state (and translation_pending flag) that it's currently displaying to user, instead of just relying on TransateInfoBarDelegate's - if infobar receives PAGE_TRANSLAED notification before delegate does (possible because order is not fixed), delegate's state won't be updated to be used by infobar. - after all the observers have received the notification, both infobar and delegate will end up with matching states, so there's no worries of out-of-sync. - update unittests accordingly - update mac and linux code accordingly to make build pass - jay will implement the remaining backend to pass actual translate error types to the IPC message (tracked by bug 37778) BUG=38548 TEST=none yet, until bug 37778 is also fixed. Review URL: http://codereview.chromium.org/1321003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42953 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/infobars')
-rw-r--r--chrome/browser/views/infobars/infobars.cc83
-rw-r--r--chrome/browser/views/infobars/infobars.h15
-rw-r--r--chrome/browser/views/infobars/translate_infobars.cc257
-rw-r--r--chrome/browser/views/infobars/translate_infobars.h31
4 files changed, 294 insertions, 92 deletions
diff --git a/chrome/browser/views/infobars/infobars.cc b/chrome/browser/views/infobars/infobars.cc
index 3c5504d..71382e2 100644
--- a/chrome/browser/views/infobars/infobars.cc
+++ b/chrome/browser/views/infobars/infobars.cc
@@ -51,55 +51,48 @@ static const SkColor kPageActionBackgroundColorBottom =
static const int kSeparatorLineHeight = 1;
-// InfoBarBackground -----------------------------------------------------------
-
-class InfoBarBackground : public views::Background {
- public:
- explicit InfoBarBackground(InfoBarDelegate::Type infobar_type) {
- SkColor top_color;
- SkColor bottom_color;
- switch (infobar_type) {
- case InfoBarDelegate::INFO_TYPE:
- top_color = kInfoBackgroundColorTop;
- bottom_color = kInfoBackgroundColorBottom;
- break;
- case InfoBarDelegate::WARNING_TYPE:
- top_color = kWarningBackgroundColorTop;
- bottom_color = kWarningBackgroundColorBottom;
- break;
- case InfoBarDelegate::ERROR_TYPE:
- top_color = kErrorBackgroundColorTop;
- bottom_color = kErrorBackgroundColorBottom;
- break;
- case InfoBarDelegate::PAGE_ACTION_TYPE:
- top_color = kPageActionBackgroundColorTop;
- bottom_color = kPageActionBackgroundColorBottom;
- break;
- default:
- NOTREACHED();
- break;
- }
- gradient_background_.reset(
- views::Background::CreateVerticalGradientBackground(top_color,
- bottom_color));
+// InfoBarBackground, public: --------------------------------------------------
+
+InfoBarBackground::InfoBarBackground(InfoBarDelegate::Type infobar_type) {
+ SkColor top_color;
+ SkColor bottom_color;
+ switch (infobar_type) {
+ case InfoBarDelegate::INFO_TYPE:
+ top_color = kInfoBackgroundColorTop;
+ bottom_color = kInfoBackgroundColorBottom;
+ break;
+ case InfoBarDelegate::WARNING_TYPE:
+ top_color = kWarningBackgroundColorTop;
+ bottom_color = kWarningBackgroundColorBottom;
+ break;
+ case InfoBarDelegate::ERROR_TYPE:
+ top_color = kErrorBackgroundColorTop;
+ bottom_color = kErrorBackgroundColorBottom;
+ break;
+ case InfoBarDelegate::PAGE_ACTION_TYPE:
+ top_color = kPageActionBackgroundColorTop;
+ bottom_color = kPageActionBackgroundColorBottom;
+ break;
+ default:
+ NOTREACHED();
+ break;
}
+ gradient_background_.reset(
+ views::Background::CreateVerticalGradientBackground(top_color,
+ bottom_color));
+}
- // Overridden from views::View:
- virtual void Paint(gfx::Canvas* canvas, views::View* view) const {
- // First paint the gradient background.
- gradient_background_->Paint(canvas, view);
+// InfoBarBackground, views::Background overrides: -----------------------------
- // Now paint the separator line.
- canvas->FillRectInt(ResourceBundle::toolbar_separator_color, 0,
- view->height() - kSeparatorLineHeight, view->width(),
- kSeparatorLineHeight);
- }
+void InfoBarBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
+ // First paint the gradient background.
+ gradient_background_->Paint(canvas, view);
- private:
- scoped_ptr<views::Background> gradient_background_;
-
- DISALLOW_COPY_AND_ASSIGN(InfoBarBackground);
-};
+ // Now paint the separator line.
+ canvas->FillRectInt(ResourceBundle::toolbar_separator_color, 0,
+ view->height() - kSeparatorLineHeight, view->width(),
+ kSeparatorLineHeight);
+}
// InfoBar, public: ------------------------------------------------------------
diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h
index 60067ba..c222824 100644
--- a/chrome/browser/views/infobars/infobars.h
+++ b/chrome/browser/views/infobars/infobars.h
@@ -24,6 +24,19 @@ class NativeButton;
// chrome/browser/tab_contents/infobar_delegate.h for the delegate interface(s)
// that you must implement to use these.
+class InfoBarBackground : public views::Background {
+ public:
+ explicit InfoBarBackground(InfoBarDelegate::Type infobar_type);
+
+ // Overridden from views::Background:
+ virtual void Paint(gfx::Canvas* canvas, views::View* view) const;
+
+ private:
+ scoped_ptr<views::Background> gradient_background_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarBackground);
+};
+
class InfoBar : public views::View,
public views::ButtonListener,
public AnimationDelegate {
@@ -98,11 +111,11 @@ class InfoBar : public views::View,
// Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
- private:
// Overridden from AnimationDelegate:
virtual void AnimationProgressed(const Animation* animation);
virtual void AnimationEnded(const Animation* animation);
+ private:
// Called when an InfoBar is added or removed from a view hierarchy to do
// setup and shutdown.
void InfoBarAdded();
diff --git a/chrome/browser/views/infobars/translate_infobars.cc b/chrome/browser/views/infobars/translate_infobars.cc
index 60e0f62..040642e 100644
--- a/chrome/browser/views/infobars/translate_infobars.cc
+++ b/chrome/browser/views/infobars/translate_infobars.cc
@@ -9,12 +9,14 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "app/slide_animation.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/notification_service.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/languages_menu_model.h"
#include "chrome/browser/translate/options_menu_model.h"
+#include "chrome/browser/translate/page_translated_details.h"
#include "gfx/canvas.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
@@ -234,15 +236,34 @@ bool TranslateTextButton::OnMousePressed(const views::MouseEvent& e) {
TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate)
: InfoBar(delegate),
+ state_(TranslateInfoBarDelegate::kTranslateNone),
+ translation_pending_(false),
label_1_(NULL),
label_2_(NULL),
label_3_(NULL),
translating_label_(NULL),
+ error_label_(NULL),
accept_button_(NULL),
deny_button_(NULL),
target_language_menu_button_(NULL),
revert_button_(NULL),
+ retry_button_(NULL),
swapped_language_placeholders_(false) {
+ // Clear background set in base class InfoBarBackground, so that we can
+ // handle special background requirements for translate infobar.
+ set_background(NULL);
+
+ // Initialize backgrounds.
+ normal_background_.reset(
+ new InfoBarBackground(InfoBarDelegate::PAGE_ACTION_TYPE));
+ error_background_.reset(
+ new InfoBarBackground(InfoBarDelegate::ERROR_TYPE));
+
+ // Initialize slide animation for transitioning to and from error state.
+ error_animation_.reset(new SlideAnimation(this));
+ error_animation_->SetTweenType(SlideAnimation::NONE);
+ error_animation_->SetSlideDuration(500);
+
// Initialize icon.
icon_ = new views::ImageView;
SkBitmap* image = delegate->GetIcon();
@@ -263,7 +284,8 @@ TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate)
AddChildView(options_menu_button_);
// Create state-dependent controls.
- UpdateState(GetDelegate()->state());
+ UpdateState(GetDelegate()->state(), GetDelegate()->translation_pending(),
+ GetDelegate()->error_type());
// Register for PAGE_TRANSLATED notification.
notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
@@ -277,10 +299,17 @@ TranslateInfoBar::~TranslateInfoBar() {
}
void TranslateInfoBar::UpdateState(
- TranslateInfoBarDelegate::TranslateState new_state) {
+ TranslateInfoBarDelegate::TranslateState new_state,
+ bool new_translation_pending, TranslateErrors::Type error_type) {
+ if (state_ == new_state && translation_pending_ == new_translation_pending)
+ return;
+
+ TranslateInfoBarDelegate::TranslateState old_state = state_;
+ state_ = new_state;
+ translation_pending_ = new_translation_pending;
+
// Create and initialize state-dependent controls if necessary.
- bool translation_pending = GetDelegate()->translation_pending();
- switch (new_state) {
+ switch (state_) {
case TranslateInfoBarDelegate::kAfterTranslate:
if (!target_language_menu_button_) {
CreateLabels();
@@ -313,33 +342,85 @@ void TranslateInfoBar::UpdateState(
}
break;
+ case TranslateInfoBarDelegate::kTranslateError: {
+ string16 error_message_utf16 = GetDelegate()->GetErrorMessage(error_type);
+ std::wstring error_message = UTF16ToWideHack(error_message_utf16);
+ if (error_label_) {
+ error_label_->SetText(error_message);
+ } else {
+ error_label_ = CreateLabel(error_message);
+ AddChildView(error_label_);
+ }
+ if (!retry_button_) {
+ retry_button_ = new TranslateTextButton(this,
+ IDS_TRANSLATE_INFOBAR_RETRY);
+ AddChildView(retry_button_);
+ }
+ break;
+ }
+
default:
NOTREACHED() << "Invalid translate state change";
break;
}
// If translation is pending, create "Translating..." label.
- if (translation_pending && !translating_label_) {
+ if (translation_pending_ && !translating_label_) {
translating_label_ = CreateLabel(
l10n_util::GetString(IDS_TRANSLATE_INFOBAR_TRANSLATING));
AddChildView(translating_label_);
}
- // Determine visibility of state-dependent controls.
+ // Determine visibility of controls.
+ if (label_1_)
+ label_1_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
+ if (label_2_)
+ label_2_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
+ if (label_3_ && !label_3_->GetText().empty())
+ label_3_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
if (accept_button_)
- accept_button_->SetVisible(!translation_pending &&
- new_state == TranslateInfoBarDelegate::kBeforeTranslate);
+ accept_button_->SetVisible(!translation_pending_ &&
+ state_ == TranslateInfoBarDelegate::kBeforeTranslate);
if (deny_button_)
- deny_button_->SetVisible(!translation_pending &&
- new_state == TranslateInfoBarDelegate::kBeforeTranslate);
+ deny_button_->SetVisible(!translation_pending_ &&
+ state_ == TranslateInfoBarDelegate::kBeforeTranslate);
if (target_language_menu_button_)
target_language_menu_button_->SetVisible(
- new_state == TranslateInfoBarDelegate::kAfterTranslate);
+ state_ == TranslateInfoBarDelegate::kAfterTranslate);
if (revert_button_)
- revert_button_->SetVisible(!translation_pending &&
- new_state == TranslateInfoBarDelegate::kAfterTranslate);
+ revert_button_->SetVisible(!translation_pending_ &&
+ state_ == TranslateInfoBarDelegate::kAfterTranslate);
if (translating_label_)
- translating_label_->SetVisible(translation_pending);
+ translating_label_->SetVisible(translation_pending_);
+ if (error_label_)
+ error_label_->SetVisible(!translation_pending_ &&
+ state_ == TranslateInfoBarDelegate::kTranslateError);
+ if (retry_button_)
+ retry_button_->SetVisible(!translation_pending_ &&
+ state_ == TranslateInfoBarDelegate::kTranslateError);
+ if (options_menu_button_)
+ options_menu_button_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
+ if (original_language_menu_button_)
+ original_language_menu_button_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
+ if (target_language_menu_button_)
+ target_language_menu_button_->SetVisible(
+ state_ != TranslateInfoBarDelegate::kTranslateError);
+
+ // If background should change per state, trigger animation of transition
+ // accordingly.
+ if (old_state != TranslateInfoBarDelegate::kTranslateError &&
+ state_ == TranslateInfoBarDelegate::kTranslateError)
+ error_animation_->Show(); // Transition to error state.
+ else if (old_state == TranslateInfoBarDelegate::kTranslateError &&
+ state_ != TranslateInfoBarDelegate::kTranslateError)
+ error_animation_->Hide(); // Transition from error state.
+ else
+ error_animation_->Stop(); // No transition.
// Trigger layout and repaint.
Layout();
@@ -357,19 +438,45 @@ void TranslateInfoBar::Layout() {
icon_->SetBounds(InfoBar::kHorizontalPadding, InfoBar::OffsetY(this, icon_ps),
icon_ps.width(), icon_ps.height());
+ // Check if translation is pending.
+ gfx::Size translating_ps;
+ if (translation_pending_)
+ translating_ps = translating_label_->GetPreferredSize();
+ int translating_width = translating_ps.width();
+
+ // Handle error state.
+ if (state_ == TranslateInfoBarDelegate::kTranslateError) {
+ int available_text_width = std::max(GetAvailableWidth(), 0);
+ if (translation_pending_) { // Layout "Translating..." label.
+ translating_label_->SetBounds(icon_->bounds().right() +
+ InfoBar::kIconLabelSpacing, InfoBar::OffsetY(this, translating_ps),
+ std::min(translating_width, available_text_width),
+ translating_ps.height());
+ } else { // Layout error label and retry button.
+ gfx::Size error_ps = error_label_->GetPreferredSize();
+ error_label_->SetBounds(icon_->bounds().right() +
+ InfoBar::kIconLabelSpacing, InfoBar::OffsetY(this, error_ps),
+ std::min(error_ps.width(), available_text_width), error_ps.height());
+ gfx::Size retry_ps = retry_button_->GetPreferredSize();
+ retry_button_->SetBounds(error_label_->bounds().right() +
+ InfoBar::kEndOfLabelSpacing, InfoBar::OffsetY(this, retry_ps),
+ retry_ps.width(), retry_ps.height());
+ }
+ return;
+ }
+
+ // Handle normal states.
// Layout the options menu button on right of bar.
int available_width = InfoBar::GetAvailableWidth();
gfx::Size options_ps = options_menu_button_->GetPreferredSize();
options_menu_button_->SetBounds(available_width - options_ps.width(),
OffsetY(this, options_ps), options_ps.width(), options_ps.height());
- TranslateInfoBarDelegate::TranslateState state = GetDelegate()->state();
-
// Layout the controls between icon and options i.e. labels, original language
// menu button, and if available, target language menu button.
views::MenuButton* button1 = original_language_menu_button_;
views::MenuButton* button2 =
- (state == TranslateInfoBarDelegate::kAfterTranslate ?
+ (state_ == TranslateInfoBarDelegate::kAfterTranslate ?
target_language_menu_button_ : NULL);
if (button2 && swapped_language_placeholders_) {
button1 = button2;
@@ -380,16 +487,11 @@ void TranslateInfoBar::Layout() {
gfx::Size label1_ps = label_1_->GetPreferredSize();
gfx::Size label2_ps = label_2_->GetPreferredSize();
gfx::Size label3_ps;
- gfx::Size translating_ps;
if (label_3_)
label3_ps = label_3_->GetPreferredSize();
- bool translation_pending = GetDelegate()->translation_pending();
- if (translation_pending)
- translating_ps = translating_label_->GetPreferredSize();
int text1_width = label1_ps.width();
int text2_width = label2_ps.width();
int text3_width = label3_ps.width();
- int translating_width = translating_ps.width();
int total_text_width = text1_width + text2_width + text3_width +
translating_width;
if (total_text_width > available_text_width) {
@@ -431,7 +533,7 @@ void TranslateInfoBar::Layout() {
}
// If no translation is pending, layout revert button.
- if (!translation_pending && revert_button_) {
+ if (!translation_pending_ && revert_button_) {
gfx::Size revert_ps = revert_button_->GetPreferredSize();
revert_button_->SetBounds(prev_right + InfoBar::kEndOfLabelSpacing,
OffsetY(this, revert_ps), revert_ps.width(), revert_ps.height());
@@ -440,8 +542,8 @@ void TranslateInfoBar::Layout() {
// If translate state is kBeforeTranslate with no pending translation,
// layout accept and deny butons.
- if (state == TranslateInfoBarDelegate::kBeforeTranslate &&
- !translation_pending) {
+ if (state_ == TranslateInfoBarDelegate::kBeforeTranslate &&
+ !translation_pending_) {
gfx::Size accept_ps = accept_button_->GetPreferredSize();
accept_button_->SetBounds(prev_right + InfoBar::kEndOfLabelSpacing,
OffsetY(this, accept_ps), accept_ps.width(), accept_ps.height());
@@ -452,7 +554,7 @@ void TranslateInfoBar::Layout() {
}
// If translation is pending, layout "Translating..." label.
- if (translation_pending) {
+ if (translation_pending_) {
translating_label_->SetBounds(
prev_right + InfoBar::kEndOfLabelSpacing,
InfoBar::OffsetY(this, translating_ps),
@@ -460,10 +562,47 @@ void TranslateInfoBar::Layout() {
}
}
+void TranslateInfoBar::PaintBackground(gfx::Canvas* canvas) {
+ // If we're not animating, simply paint background for current state.
+ if (!error_animation_->IsAnimating()) {
+ GetBackground(state_)->Paint(canvas, this);
+ return;
+ }
+
+ // Animate cross-fading between error and normal states;
+ // since all normal states use the same background, just use kAfterTranslate.
+ if (error_animation_->IsShowing()) { // Transitioning to error state.
+ // Fade out normal state.
+ FadeBackground(canvas, 1.0 - error_animation_->GetCurrentValue(),
+ TranslateInfoBarDelegate::kAfterTranslate);
+ // Fade in error state.
+ FadeBackground(canvas, error_animation_->GetCurrentValue(),
+ TranslateInfoBarDelegate::kTranslateError);
+ } else { // Transitioning from error state.
+ // Fade out error state.
+ FadeBackground(canvas, error_animation_->GetCurrentValue(),
+ TranslateInfoBarDelegate::kTranslateError);
+ // Fade in normal state.
+ FadeBackground(canvas, 1.0 - error_animation_->GetCurrentValue(),
+ TranslateInfoBarDelegate::kAfterTranslate);
+ }
+}
+
// TranslateInfoBar, InfoBar overrides: ----------------------------------------
int TranslateInfoBar::GetAvailableWidth() const {
- gfx::Size icon_ps = icon_->GetPreferredSize();
+ int available_width = InfoBar::GetAvailableWidth() -
+ icon_->bounds().right() - InfoBar::kIconLabelSpacing;
+
+ // Handle the simplest state - error state, with the least no. of controls.
+ if (state_ == TranslateInfoBarDelegate::kTranslateError) {
+ if (!translation_pending_)
+ available_width -= InfoBar::kEndOfLabelSpacing +
+ retry_button_->bounds().width();
+ return available_width;
+ }
+
+ // Handle the normal states, which have more controls.
// For language button, reserve spacing before and after it.
gfx::Size language_ps = original_language_menu_button_->GetPreferredSize();
int language_spacing = InfoBar::kButtonInLabelSpacing +
@@ -480,17 +619,14 @@ int TranslateInfoBar::GetAvailableWidth() const {
(label_3_ ? InfoBar::kButtonInLabelSpacing + InfoBar::kEndOfLabelSpacing :
(target_language_menu_button_ ? InfoBar::kEndOfLabelSpacing :
InfoBar::kButtonButtonSpacing));
- int available_width = (InfoBar::GetAvailableWidth() -
- options_ps.width() - options_spacing -
- language_ps.width() - language_spacing -
- icon_->bounds().right() - InfoBar::kIconLabelSpacing);
- TranslateInfoBarDelegate::TranslateState state = GetDelegate()->state();
- if (state == TranslateInfoBarDelegate::kBeforeTranslate) {
+ available_width -= options_ps.width() + options_spacing +
+ language_ps.width() + language_spacing;
+ if (state_ == TranslateInfoBarDelegate::kBeforeTranslate) {
gfx::Size accept_ps = accept_button_->GetPreferredSize();
gfx::Size deny_ps = deny_button_->GetPreferredSize();
available_width -= accept_ps.width() + InfoBar::kEndOfLabelSpacing +
deny_ps.width() + InfoBar::kButtonButtonSpacing;
- } else if (state == TranslateInfoBarDelegate::kAfterTranslate) {
+ } else if (state_ == TranslateInfoBarDelegate::kAfterTranslate) {
gfx::Size target_ps = target_language_menu_button_->GetPreferredSize();
available_width -= target_ps.width() + InfoBar::kButtonInLabelSpacing;
}
@@ -511,7 +647,7 @@ void TranslateInfoBar::RunMenu(views::View* source, const gfx::Point& pt) {
}
case kMenuIDOriginalLanguage: {
- if (!translating_label_ || !translating_label_->IsVisible()) {
+ if (!translation_pending_) {
if (!original_language_menu_model_.get()) {
original_language_menu_model_.reset(
new LanguagesMenuModel(this, GetDelegate(), true));
@@ -527,7 +663,7 @@ void TranslateInfoBar::RunMenu(views::View* source, const gfx::Point& pt) {
}
case kMenuIDTargetLanguage: {
- if (!translating_label_ || !translating_label_->IsVisible()) {
+ if (!translation_pending_) {
if (!target_language_menu_model_.get()) {
target_language_menu_model_.reset(
new LanguagesMenuModel(this, GetDelegate(), false));
@@ -626,9 +762,10 @@ void TranslateInfoBar::ExecuteCommand(int command_id) {
void TranslateInfoBar::ButtonPressed(
views::Button* sender, const views::Event& event) {
- if (sender == accept_button_) {
+ if (sender == accept_button_ || sender == retry_button_) {
GetDelegate()->Translate();
- UpdateState(GetDelegate()->state());
+ UpdateState(GetDelegate()->state(), GetDelegate()->translation_pending(),
+ GetDelegate()->error_type());
UMA_HISTOGRAM_COUNTS("Translate.Translate", 1);
} else if (sender == deny_button_) {
GetDelegate()->TranslationDeclined();
@@ -641,6 +778,15 @@ void TranslateInfoBar::ButtonPressed(
}
}
+// TranslateInfoBar, AnimationDelegate overrides: ------------------------------
+
+void TranslateInfoBar::AnimationProgressed(const Animation* animation) {
+ if (animation == error_animation_.get())
+ SchedulePaint();
+ else
+ InfoBar::AnimationProgressed(animation);
+}
+
// TranslateInfoBar, NotificationObserver overrides: ---------------------------
void TranslateInfoBar::Observe(NotificationType type,
@@ -650,7 +796,12 @@ void TranslateInfoBar::Observe(NotificationType type,
TabContents* tab = Source<TabContents>(source).ptr();
if (tab != GetDelegate()->tab_contents())
return;
- UpdateState(TranslateInfoBarDelegate::kAfterTranslate);
+ PageTranslatedDetails* page_translated_details =
+ Details<PageTranslatedDetails>(details).ptr();
+ UpdateState((page_translated_details->error_type == TranslateErrors::NONE ?
+ TranslateInfoBarDelegate::kAfterTranslate :
+ TranslateInfoBarDelegate::kTranslateError), false,
+ page_translated_details->error_type);
}
// TranslateInfoBar, private: --------------------------------------------------
@@ -659,7 +810,7 @@ void TranslateInfoBar::CreateLabels() {
// Determine text for labels.
std::vector<size_t> offsets;
string16 message_text_utf16;
- GetDelegate()->GetMessageText(&message_text_utf16, &offsets,
+ GetDelegate()->GetMessageText(state_, &message_text_utf16, &offsets,
&swapped_language_placeholders_);
std::wstring message_text = UTF16ToWideHack(message_text_utf16);
@@ -691,6 +842,8 @@ void TranslateInfoBar::CreateLabels() {
label_3_ = CreateLabel(label_3);
AddChildView(label_3_);
}
+ } else if (label_3_) {
+ label_3_->SetText(std::wstring());
}
}
@@ -772,21 +925,39 @@ void TranslateInfoBar::OnLanguageModified(views::MenuButton* menu_button,
// Selecting an item from the "from language" menu in the before translate
// phase shouldn't trigger translation - http://crbug.com/36666
- if (GetDelegate()->state() == TranslateInfoBarDelegate::kAfterTranslate) {
+ if (state_ == TranslateInfoBarDelegate::kAfterTranslate) {
GetDelegate()->Translate();
- UpdateState(GetDelegate()->state());
+ UpdateState(GetDelegate()->state(), GetDelegate()->translation_pending(),
+ GetDelegate()->error_type());
}
Layout();
SchedulePaint();
}
+void TranslateInfoBar::FadeBackground(gfx::Canvas* canvas,
+ double animation_value, TranslateInfoBarDelegate::TranslateState state) {
+ // Draw background into an offscreen buffer with alpha value per animation
+ // value, then blend it back into the current canvas.
+ canvas->saveLayerAlpha(NULL, static_cast<int>(animation_value * 255),
+ SkCanvas::kARGB_NoClipLayer_SaveFlag);
+ canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
+ GetBackground(state)->Paint(canvas, this);
+ canvas->restore();
+}
+
inline TranslateInfoBarDelegate* TranslateInfoBar::GetDelegate() const {
return static_cast<TranslateInfoBarDelegate*>(delegate());
}
+inline InfoBarBackground* TranslateInfoBar::GetBackground(
+ TranslateInfoBarDelegate::TranslateState state) const {
+ return (state == TranslateInfoBarDelegate::kTranslateError ?
+ error_background_.get() : normal_background_.get());
+}
+
inline int TranslateInfoBar::GetSpacingAfterFirstLanguageButton() const {
- return (GetDelegate()->state() == TranslateInfoBarDelegate::kAfterTranslate ?
+ return (state_ == TranslateInfoBarDelegate::kAfterTranslate ?
kButtonInLabelSpacing : 10);
}
diff --git a/chrome/browser/views/infobars/translate_infobars.h b/chrome/browser/views/infobars/translate_infobars.h
index 713863a..60e3dcb 100644
--- a/chrome/browser/views/infobars/translate_infobars.h
+++ b/chrome/browser/views/infobars/translate_infobars.h
@@ -9,6 +9,7 @@
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/views/infobars/infobars.h"
#include "chrome/common/notification_registrar.h"
+#include "chrome/common/translate_errors.h"
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/view_menu_delegate.h"
@@ -32,10 +33,9 @@ class TranslateInfoBar : public InfoBar,
explicit TranslateInfoBar(TranslateInfoBarDelegate* delegate);
virtual ~TranslateInfoBar();
- void UpdateState(TranslateInfoBarDelegate::TranslateState new_state);
-
// Overridden from views::View:
virtual void Layout();
+ virtual void PaintBackground(gfx::Canvas* canvas);
// Overridden from views::MenuDelegate:
virtual void RunMenu(views::View* source, const gfx::Point& pt);
@@ -58,6 +58,9 @@ class TranslateInfoBar : public InfoBar,
// Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+ // Overridden from AnimationDelegate:
+ virtual void AnimationProgressed(const Animation* animation);
+
private:
void CreateLabels();
views::Label* CreateLabel(const std::wstring& label);
@@ -65,22 +68,40 @@ class TranslateInfoBar : public InfoBar,
bool normal_has_border);
gfx::Point DetermineMenuPositionAndAlignment(views::MenuButton* menu_button,
views::Menu2::Alignment* alignment);
+ void UpdateState(TranslateInfoBarDelegate::TranslateState new_state,
+ bool translation_pending, TranslateErrors::Type error_type);
void OnLanguageModified(views::MenuButton* menu_button,
int new_language_index);
- inline int GetSpacingAfterFirstLanguageButton() const;
+ void FadeBackground(gfx::Canvas* canvas, double animation_value,
+ TranslateInfoBarDelegate::TranslateState state);
inline TranslateInfoBarDelegate* GetDelegate() const;
+ inline InfoBarBackground* GetBackground(
+ TranslateInfoBarDelegate::TranslateState new_state) const;
+ inline int GetSpacingAfterFirstLanguageButton() const;
+
+ // Infobar keeps track of the state it is displaying, which should match that
+ // in the TranslateInfoBarDelegate. UI needs to keep track separately because
+ // infobar may receive PAGE_TRANSLATED notifications before delegate does, in
+ // which case, delegate's state is not updated and hence can't be used to
+ // update display. After the notification is sent out to all observers, both
+ // infobar and delegate would end up with the same state.
+ TranslateInfoBarDelegate::TranslateState state_;
+ bool translation_pending_;
+ TranslateErrors::Type error_type_;
views::ImageView* icon_;
views::Label* label_1_;
views::Label* label_2_;
views::Label* label_3_;
views::Label* translating_label_;
+ views::Label* error_label_;
TranslateTextButton* accept_button_;
TranslateTextButton* deny_button_;
views::MenuButton* original_language_menu_button_;
views::MenuButton* target_language_menu_button_;
TranslateTextButton* revert_button_;
views::MenuButton* options_menu_button_;
+ TranslateTextButton* retry_button_;
scoped_ptr<LanguagesMenuModel> original_language_menu_model_;
scoped_ptr<LanguagesMenuModel> target_language_menu_model_;
@@ -95,6 +116,10 @@ class TranslateInfoBar : public InfoBar,
NotificationRegistrar notification_registrar_;
+ scoped_ptr<InfoBarBackground> normal_background_;
+ scoped_ptr<InfoBarBackground> error_background_;
+ scoped_ptr<SlideAnimation> error_animation_;
+
DISALLOW_COPY_AND_ASSIGN(TranslateInfoBar);
};