diff options
author | pkasting <pkasting@chromium.org> | 2014-12-11 19:34:22 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-12 03:34:40 +0000 |
commit | 07622896891ccc5e8279be55bae52c6323f025ff (patch) | |
tree | d14263e37c072929a54b8523d317fbe0771cb9a2 | |
parent | 41ec9ff4ad115e94ed3e9b2d96c42e5f6eb07f2c (diff) | |
download | chromium_src-07622896891ccc5e8279be55bae52c6323f025ff.zip chromium_src-07622896891ccc5e8279be55bae52c6323f025ff.tar.gz chromium_src-07622896891ccc5e8279be55bae52c6323f025ff.tar.bz2 |
Move infobar constants and the code that uses them from components/ to chrome/.
Both the infobar and the infobar container were making use of various infobar
constants that were declared in components/ but (usually) defined in chrome/.
This was a symptom of having put code in the component that really probably
belonged in the embedder.
This CL hoists the relevant logic to a new cross-platform
InfoBarContainerDelegate class defined on the chrome side, which implements some
of the methods of InfoBarContainer::Delegate. Platforms then subclass this to
implement the remaining, platform-specific bits.
This means that the constants in question now live solely in chrome/, avoiding a
bunch of link-time nastiness when trying to build the components code
separately.
BUG=382924
TEST=none
TBR=finnur
Review URL: https://codereview.chromium.org/793783003
Cr-Commit-Position: refs/heads/master@{#308046}
24 files changed, 271 insertions, 198 deletions
diff --git a/chrome/browser/extensions/extension_infobar_delegate.cc b/chrome/browser/extensions/extension_infobar_delegate.cc index ba16960..52050b6 100644 --- a/chrome/browser/extensions/extension_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_infobar_delegate.cc @@ -10,6 +10,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "components/infobars/core/infobar.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" @@ -55,9 +56,10 @@ ExtensionInfoBarDelegate::ExtensionInfoBarDelegate( content::Source<Profile>(browser->profile())); height_ = std::max(0, height); - height_ = std::min(2 * infobars::InfoBar::kDefaultBarTargetHeight, height_); + height_ = + std::min(2 * InfoBarContainerDelegate::kDefaultBarTargetHeight, height_); if (height_ == 0) - height_ = infobars::InfoBar::kDefaultBarTargetHeight; + height_ = InfoBarContainerDelegate::kDefaultBarTargetHeight; } content::WebContents* ExtensionInfoBarDelegate::GetWebContents() { diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm index 4852517..317bbd8 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm @@ -34,6 +34,7 @@ #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/ui/find_bar/find_bar.h" #include "chrome/browser/ui/find_bar/find_bar_controller.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" @@ -603,8 +604,9 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, EXPECT_FALSE([[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]); - NSInteger max_tip_height = infobars::InfoBar::kMaximumArrowTargetHeight + - infobars::InfoBar::kSeparatorLineHeight; + NSInteger max_tip_height = + InfoBarContainerDelegate::kMaximumArrowTargetHeight + + InfoBarContainerDelegate::kSeparatorLineHeight; chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); WaitForBookmarkBarAnimationToFinish(); diff --git a/chrome/browser/ui/cocoa/infobars/infobar_cocoa.mm b/chrome/browser/ui/cocoa/infobars/infobar_cocoa.mm index dd25e54..c3183a1 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_cocoa.mm +++ b/chrome/browser/ui/cocoa/infobars/infobar_cocoa.mm @@ -6,14 +6,6 @@ #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h" -const int infobars::InfoBar::kSeparatorLineHeight = 1; -const int infobars::InfoBar::kDefaultArrowTargetHeight = 11; -const int infobars::InfoBar::kMaximumArrowTargetHeight = 24; -const int infobars::InfoBar::kDefaultArrowTargetHalfWidth = - kDefaultArrowTargetHeight; -const int infobars::InfoBar::kMaximumArrowTargetHalfWidth = 14; -const int infobars::InfoBar::kDefaultBarTargetHeight = 36; - InfoBarCocoa::InfoBarCocoa(scoped_ptr<infobars::InfoBarDelegate> delegate) : infobars::InfoBar(delegate.Pass()), weak_ptr_factory_(this) { diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h b/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h index efd1a1d..50d3633f 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h +++ b/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h @@ -5,14 +5,14 @@ #ifndef CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_CONTAINER_COCOA_H_ #define CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_CONTAINER_COCOA_H_ -#include "components/infobars/core/infobar_container.h" +#include "chrome/browser/ui/infobar_container_delegate.h" @class InfoBarContainerController; // The cocoa specific implementation of InfoBarContainer. This mostly serves as // a bridge for InfoBarContainerController. class InfoBarContainerCocoa : public infobars::InfoBarContainer, - public infobars::InfoBarContainer::Delegate { + public InfoBarContainerDelegate { public: explicit InfoBarContainerCocoa(InfoBarContainerController* controller); ~InfoBarContainerCocoa() override; @@ -23,7 +23,7 @@ class InfoBarContainerCocoa : public infobars::InfoBarContainer, size_t position) override; void PlatformSpecificRemoveInfoBar(infobars::InfoBar* infobar) override; - // InfoBarContainer::Delegate: + // InfoBarContainerDelegate: SkColor GetInfoBarSeparatorColor() const override; void InfoBarContainerStateChanged(bool is_animating) override; bool DrawInfoBarArrows(int* x) const override; diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.mm index cd9c907..a834ec0 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.mm +++ b/chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.mm @@ -7,6 +7,9 @@ #import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h" #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" +const int InfoBarContainerDelegate::kSeparatorLineHeight = 1; +const int InfoBarContainerDelegate::kDefaultArrowTargetHeight = 11; + InfoBarContainerCocoa::InfoBarContainerCocoa( InfoBarContainerController* controller) : infobars::InfoBarContainer(this), diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm index b3c5c63..af5e46b 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm +++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm @@ -154,7 +154,7 @@ } - (void)setMaxTopArrowHeight:(NSInteger)height { - containerCocoa_->SetMaxTopArrowHeight(height); + containerCocoa_->SetMaxTopArrowHeight(height, containerCocoa_.get()); } - (CGFloat)heightOfInfoBars { diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm index 0e58c15..0f737f0 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm +++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm @@ -10,6 +10,7 @@ #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" #import "chrome/browser/ui/cocoa/themed_window.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "components/infobars/core/infobar.h" #include "skia/ext/skia_utils_mac.h" #import "ui/base/cocoa/nsview_additions.h" @@ -58,7 +59,7 @@ - (void)drawRect:(NSRect)rect { NSRect bounds = [self bounds]; - bounds.size.height = infobars::InfoBar::kDefaultBarTargetHeight; + bounds.size.height = InfoBarContainerDelegate::kDefaultBarTargetHeight; CGFloat tipXOffset = arrowX_ - arrowHalfWidth_; diff --git a/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm b/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm index 2ff64d0..29831ff 100644 --- a/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm +++ b/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm @@ -7,6 +7,7 @@ #include "base/mac/scoped_nsobject.h" #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #import "components/infobars/core/infobar.h" #import "ui/base/cocoa/nsview_additions.h" @@ -66,7 +67,7 @@ void VerticallyCenterView(NSView* toMove) { // rather than in the total height (which includes the bulge). CGFloat superHeight = NSHeight(superViewFrame); if ([[toMove superview] isKindOfClass:[InfoBarGradientView class]]) - superHeight = infobars::InfoBar::kDefaultBarTargetHeight; + superHeight = InfoBarContainerDelegate::kDefaultBarTargetHeight; viewFrame.origin.y = floor((superHeight - NSHeight(viewFrame)) / 2.0); [toMove setFrame:viewFrame]; diff --git a/chrome/browser/ui/infobar_container_delegate.cc b/chrome/browser/ui/infobar_container_delegate.cc new file mode 100644 index 0000000..129cf43 --- /dev/null +++ b/chrome/browser/ui/infobar_container_delegate.cc @@ -0,0 +1,85 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/infobar_container_delegate.h" +#include "ui/gfx/animation/slide_animation.h" + +const int InfoBarContainerDelegate::kDefaultBarTargetHeight = 36; +const int InfoBarContainerDelegate::kMaximumArrowTargetHeight = 24; +const int InfoBarContainerDelegate::kDefaultArrowTargetHalfWidth = + kDefaultArrowTargetHeight; +const int InfoBarContainerDelegate::kMaximumArrowTargetHalfWidth = 14; + +InfoBarContainerDelegate::InfoBarContainerDelegate() + : top_arrow_target_height_(kDefaultArrowTargetHeight) { +} + +InfoBarContainerDelegate::~InfoBarContainerDelegate() { +} + +void InfoBarContainerDelegate::SetMaxTopArrowHeight( + int height, + infobars::InfoBarContainer* container) { + // Decrease the height by the arrow stroke thickness, which is the separator + // line height, because the infobar arrow target heights are without-stroke. + top_arrow_target_height_ = std::min( + std::max(height - kSeparatorLineHeight, 0), kMaximumArrowTargetHeight); + container->UpdateInfoBarArrowTargetHeights(); +} + +int InfoBarContainerDelegate::ArrowTargetHeightForInfoBar( + size_t index, + const gfx::SlideAnimation& animation) const { + if (!DrawInfoBarArrows(nullptr)) + return 0; + if (index == 0) + return top_arrow_target_height_; + if ((index > 1) || animation.IsShowing()) + return kDefaultArrowTargetHeight; + // When the first infobar is animating closed, we animate the second infobar's + // arrow target height from the default to the top target height. Note that + // the animation values here are going from 1.0 -> 0.0 as the top bar closes. + return top_arrow_target_height_ + static_cast<int>( + (kDefaultArrowTargetHeight - top_arrow_target_height_) * + animation.GetCurrentValue()); +} + +void InfoBarContainerDelegate::ComputeInfoBarElementSizes( + const gfx::SlideAnimation& animation, + int arrow_target_height, + int bar_target_height, + int* arrow_height, + int* arrow_half_width, + int* bar_height) const { + // Find the desired arrow height/half-width. The arrow area is + // *arrow_height * *arrow_half_width. When the bar is opening or closing, + // scaling each of these with the square root of the animation value causes a + // linear animation of the area, which matches the perception of the animation + // of the bar portion. + double scale_factor = sqrt(animation.GetCurrentValue()); + *arrow_height = static_cast<int>(arrow_target_height * scale_factor); + if (animation.is_animating()) { + *arrow_half_width = static_cast<int>( + std::min(arrow_target_height, kMaximumArrowTargetHalfWidth) * + scale_factor); + } else { + // When the infobar is not animating (i.e. fully open), we set the + // half-width to be proportionally the same distance between its default and + // maximum values as the height is between its. + *arrow_half_width = kDefaultArrowTargetHalfWidth + + ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) * + ((*arrow_height - kDefaultArrowTargetHeight) / + (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight))); + } + // Add pixels for the stroke, if the arrow is to be visible at all. Without + // this, changing the arrow height from 0 to kSeparatorLineHeight would + // produce no visible effect, because the stroke would paint atop the divider + // line above the infobar. + if (*arrow_height) + *arrow_height += kSeparatorLineHeight; + + *bar_height = animation.CurrentValueBetween( + 0, + (bar_target_height == -1) ? kDefaultBarTargetHeight : bar_target_height); +} diff --git a/chrome/browser/ui/infobar_container_delegate.h b/chrome/browser/ui/infobar_container_delegate.h new file mode 100644 index 0000000..d88b3d5 --- /dev/null +++ b/chrome/browser/ui/infobar_container_delegate.h @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_INFOBAR_CONTAINER_DELEGATE_H_ +#define CHROME_BROWSER_UI_INFOBAR_CONTAINER_DELEGATE_H_ + +#include "components/infobars/core/infobar_container.h" + +class InfoBarContainerDelegate : public infobars::InfoBarContainer::Delegate { + public: + static const int kDefaultBarTargetHeight; + static const int kSeparatorLineHeight; + static const int kDefaultArrowTargetHeight; + static const int kMaximumArrowTargetHeight; + static const int kDefaultArrowTargetHalfWidth; + static const int kMaximumArrowTargetHalfWidth; + + InfoBarContainerDelegate(); + ~InfoBarContainerDelegate() override; + + // Called when the distance between what the top infobar's "unspoofable" arrow + // would point to and the top infobar itself changes. Sets the maximum height + // of the top arrow to the new |height| and asks |container| to update its + // infobars accordingly. This enables the top infobar to show a longer arrow + // (e.g. because of a visible bookmark bar) or shorter (e.g. due to being in a + // popup window) if desired. + void SetMaxTopArrowHeight(int height, infobars::InfoBarContainer* container); + + // infobars::InfoBarContainer::Delegate: + int ArrowTargetHeightForInfoBar( + size_t index, + const gfx::SlideAnimation& animation) const override; + void ComputeInfoBarElementSizes(const gfx::SlideAnimation& animation, + int arrow_target_height, + int bar_target_height, + int* arrow_height, + int* arrow_half_width, + int* bar_height) const override; + + private: + int top_arrow_target_height_; + + DISALLOW_COPY_AND_ASSIGN(InfoBarContainerDelegate); +}; + +#endif // CHROME_BROWSER_UI_INFOBAR_CONTAINER_DELEGATE_H_ diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 5d081a8..b820b22 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -957,10 +957,10 @@ void BrowserView::FullscreenStateChanged() { } void BrowserView::ToolbarSizeChanged(bool is_animating) { - // The call to InfoBarContainer::SetMaxTopArrowHeight() below can result in - // reentrancy; |call_state| tracks whether we're reentrant. We can't just - // early-return in this case because we need to layout again so the infobar - // container's bounds are set correctly. + // The call to SetMaxTopArrowHeight() below can result in reentrancy; + // |call_state| tracks whether we're reentrant. We can't just early-return in + // this case because we need to layout again so the infobar container's bounds + // are set correctly. static CallState call_state = NORMAL; // A reentrant call can (and should) use the fast resize path unless both it @@ -979,7 +979,7 @@ void BrowserView::ToolbarSizeChanged(bool is_animating) { { base::AutoReset<CallState> resetter(&call_state, is_animating ? REENTRANT_FORCE_FAST_RESIZE : REENTRANT); - infobar_container_->SetMaxTopArrowHeight(GetMaxTopInfoBarArrowHeight()); + SetMaxTopArrowHeight(GetMaxTopInfoBarArrowHeight(), infobar_container_); } // When transitioning from animating to not animating we need to make sure the @@ -1899,11 +1899,15 @@ bool BrowserView::AcceleratorPressed(const ui::Accelerator& accelerator) { /////////////////////////////////////////////////////////////////////////////// // BrowserView, OmniboxPopupModelObserver overrides: void BrowserView::OnOmniboxPopupShownOrHidden() { - infobar_container_->SetMaxTopArrowHeight(GetMaxTopInfoBarArrowHeight()); + SetMaxTopArrowHeight(GetMaxTopInfoBarArrowHeight(), infobar_container_); } /////////////////////////////////////////////////////////////////////////////// -// BrowserView, InfoBarContainer::Delegate overrides: +// BrowserView, InfoBarContainerDelegate overrides: + +const int InfoBarContainerDelegate::kSeparatorLineHeight = + views::NonClientFrameView::kClientEdgeThickness; +const int InfoBarContainerDelegate::kDefaultArrowTargetHeight = 9; SkColor BrowserView::GetInfoBarSeparatorColor() const { // NOTE: Keep this in sync with ToolbarView::OnPaint()! diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 5c5bf6d..ed8eea2 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -18,6 +18,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window_testing_views.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "chrome/browser/ui/omnibox/omnibox_popup_model_observer.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/views/frame/browser_frame.h" @@ -25,7 +26,6 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/browser/ui/views/frame/web_contents_close_handler.h" #include "chrome/browser/ui/views/load_complete_listener.h" -#include "components/infobars/core/infobar_container.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/models/simple_menu_model.h" #include "ui/gfx/native_widget_types.h" @@ -91,7 +91,7 @@ class BrowserView : public BrowserWindow, public views::WidgetDelegate, public views::WidgetObserver, public views::ClientView, - public infobars::InfoBarContainer::Delegate, + public InfoBarContainerDelegate, public LoadCompleteListener::Delegate, public OmniboxPopupModelObserver { public: @@ -423,7 +423,7 @@ class BrowserView : public BrowserWindow, int NonClientHitTest(const gfx::Point& point) override; gfx::Size GetMinimumSize() const override; - // InfoBarContainer::Delegate overrides + // InfoBarContainerDelegate: SkColor GetInfoBarSeparatorColor() const override; void InfoBarContainerStateChanged(bool is_animating) override; bool DrawInfoBarArrows(int* x) const override; diff --git a/chrome/browser/ui/views/infobars/extension_infobar.cc b/chrome/browser/ui/views/infobars/extension_infobar.cc index 92d665b..3493806 100644 --- a/chrome/browser/ui/views/infobars/extension_infobar.cc +++ b/chrome/browser/ui/views/infobars/extension_infobar.cc @@ -8,6 +8,7 @@ #include "chrome/browser/extensions/extension_infobar_delegate.h" #include "chrome/browser/extensions/extension_view_host.h" #include "chrome/browser/platform_util.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "chrome/browser/ui/views/extensions/extension_view_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "extensions/browser/image_loader.h" @@ -105,10 +106,12 @@ void ExtensionInfoBar::Layout() { // but the NativeViewHost inside does not seem to be clipped by the ClipRect() // call in InfoBarView::PaintChildren(), so we have to manually clamp the size // here. - extension_view->SetSize( - gfx::Size(std::max(0, EndX() - StartX() - NonExtensionViewWidth()), - std::min(height() - kSeparatorLineHeight - arrow_height(), - GetDelegate()->height()))); + extension_view->SetSize(gfx::Size( + std::max(0, EndX() - StartX() - NonExtensionViewWidth()), + std::min( + height() - InfoBarContainerDelegate::kSeparatorLineHeight - + arrow_height(), + GetDelegate()->height()))); // We do SetPosition() separately after SetSize() so OffsetY() will work. extension_view->SetPosition( gfx::Point(infobar_icon_->bounds().right() + kIconHorizontalMargin, diff --git a/chrome/browser/ui/views/infobars/infobar_background.cc b/chrome/browser/ui/views/infobars/infobar_background.cc index 09e4191..9a93fef 100644 --- a/chrome/browser/ui/views/infobars/infobar_background.cc +++ b/chrome/browser/ui/views/infobars/infobar_background.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/infobars/infobar_background.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "chrome/browser/ui/views/infobars/infobar_view.h" #include "components/infobars/core/infobar.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -32,7 +33,8 @@ void InfoBarBackground::Paint(gfx::Canvas* canvas, views::View* view) const { SkGradientShader::CreateLinear(gradient_points, gradient_colors, NULL, 2, SkShader::kClamp_TileMode)); SkPaint paint; - paint.setStrokeWidth(SkIntToScalar(infobars::InfoBar::kSeparatorLineHeight)); + paint.setStrokeWidth( + SkIntToScalar(InfoBarContainerDelegate::kSeparatorLineHeight)); paint.setStyle(SkPaint::kFill_Style); paint.setStrokeCap(SkPaint::kRound_Cap); paint.setShader(gradient_shader.get()); @@ -54,7 +56,8 @@ void InfoBarBackground::Paint(gfx::Canvas* canvas, views::View* view) const { // Now draw the separator at the bottom. canvas->FillRect( - gfx::Rect(0, view->height() - infobars::InfoBar::kSeparatorLineHeight, - view->width(), infobars::InfoBar::kSeparatorLineHeight), + gfx::Rect(0, + view->height() - InfoBarContainerDelegate::kSeparatorLineHeight, + view->width(), InfoBarContainerDelegate::kSeparatorLineHeight), separator_color_); } diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc index fc620e9..f651a8d 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.cc +++ b/chrome/browser/ui/views/infobars/infobar_view.cc @@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/infobar_container_delegate.h" #include "chrome/browser/ui/views/infobars/infobar_background.h" #include "chrome/grit/generated_resources.h" #include "components/infobars/core/infobar_delegate.h" @@ -48,18 +49,6 @@ bool SortLabelsByDecreasingWidth(views::Label* label_1, views::Label* label_2) { } // namespace -// InfoBar -------------------------------------------------------------------- - -// static -const int infobars::InfoBar::kSeparatorLineHeight = - views::NonClientFrameView::kClientEdgeThickness; -const int infobars::InfoBar::kDefaultArrowTargetHeight = 9; -const int infobars::InfoBar::kMaximumArrowTargetHeight = 24; -const int infobars::InfoBar::kDefaultArrowTargetHalfWidth = - kDefaultArrowTargetHeight; -const int infobars::InfoBar::kMaximumArrowTargetHalfWidth = 14; -const int infobars::InfoBar::kDefaultBarTargetHeight = 36; - // InfoBarView ---------------------------------------------------------------- // static @@ -154,10 +143,11 @@ void InfoBarView::Layout() { static_cast<InfoBarBackground*>(background())->set_separator_color( delegate->GetInfoBarSeparatorColor()); int arrow_x; - SkScalar arrow_fill_height = - SkIntToScalar(std::max(arrow_height() - kSeparatorLineHeight, 0)); + SkScalar arrow_fill_height = SkIntToScalar(std::max( + arrow_height() - InfoBarContainerDelegate::kSeparatorLineHeight, 0)); SkScalar arrow_fill_half_width = SkIntToScalar(arrow_half_width()); - SkScalar separator_height = SkIntToScalar(kSeparatorLineHeight); + SkScalar separator_height = + SkIntToScalar(InfoBarContainerDelegate::kSeparatorLineHeight); if (delegate->DrawInfoBarArrows(&arrow_x) && arrow_fill_height) { // Skia pixel centers are at the half-values, so the arrow is horizontally // centered at |arrow_x| + 0.5. Vertically, the stroke path is the center @@ -184,8 +174,10 @@ void InfoBarView::Layout() { } } if (bar_height()) { - fill_path_.addRect(0.0, SkIntToScalar(arrow_height()), - SkIntToScalar(width()), SkIntToScalar(height() - kSeparatorLineHeight)); + fill_path_.addRect( + 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()), + SkIntToScalar( + height() - InfoBarContainerDelegate::kSeparatorLineHeight)); } int start_x = kEdgeItemPadding; @@ -239,7 +231,7 @@ void InfoBarView::ViewHierarchyChanged( // Ensure the infobar is tall enough to display its contents. const int kMinimumVerticalPadding = 6; - int height = kDefaultBarTargetHeight; + int height = InfoBarContainerDelegate::kDefaultBarTargetHeight; for (int i = 0; i < child_count(); ++i) { const int child_height = child_at(i)->height(); height = std::max(height, child_height + kMinimumVerticalPadding); diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index cff9778..abd5b1a 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1428,6 +1428,8 @@ 'browser/ui/fullscreen/fullscreen_exit_bubble_type.h', 'browser/ui/fullscreen/fullscreen_within_tab_helper.cc', 'browser/ui/fullscreen/fullscreen_within_tab_helper.h', + 'browser/ui/infobar_container_delegate.cc', + 'browser/ui/infobar_container_delegate.h', 'browser/ui/location_bar/location_bar.cc', 'browser/ui/location_bar/location_bar.h', 'browser/ui/location_bar/location_bar_util.cc', diff --git a/components/infobars.gypi b/components/infobars.gypi index 172a7b6..ad13b70 100644 --- a/components/infobars.gypi +++ b/components/infobars.gypi @@ -27,7 +27,6 @@ 'infobars/core/confirm_infobar_delegate.h', 'infobars/core/infobar.cc', 'infobars/core/infobar.h', - 'infobars/core/infobar_android.cc', 'infobars/core/infobar_container.cc', 'infobars/core/infobar_container.h', 'infobars/core/infobar_delegate.cc', diff --git a/components/infobars/core/BUILD.gn b/components/infobars/core/BUILD.gn index 13499c4..2959e0d 100644 --- a/components/infobars/core/BUILD.gn +++ b/components/infobars/core/BUILD.gn @@ -8,7 +8,6 @@ static_library("core") { "confirm_infobar_delegate.h", "infobar.cc", "infobar.h", - "infobar_android.cc", "infobar_container.cc", "infobar_container.h", "infobar_delegate.cc", diff --git a/components/infobars/core/infobar.cc b/components/infobars/core/infobar.cc index 1ddfffd..6e7aca7 100644 --- a/components/infobars/core/infobar.cc +++ b/components/infobars/core/infobar.cc @@ -20,10 +20,10 @@ InfoBar::InfoBar(scoped_ptr<InfoBarDelegate> delegate) container_(NULL), animation_(this), arrow_height_(0), - arrow_target_height_(kDefaultArrowTargetHeight), + arrow_target_height_(0), arrow_half_width_(0), bar_height_(0), - bar_target_height_(kDefaultBarTargetHeight) { + bar_target_height_(-1) { DCHECK(delegate_ != NULL); animation_.SetTweenType(gfx::Tween::LINEAR); delegate_->set_infobar(this); @@ -85,7 +85,6 @@ void InfoBar::Hide(bool animate) { } void InfoBar::SetArrowTargetHeight(int height) { - DCHECK_LE(height, kMaximumArrowTargetHeight); // Once the closing animation starts, we ignore further requests to change the // target height. if ((arrow_target_height_ != height) && !animation_.IsClosing()) { @@ -126,36 +125,20 @@ void InfoBar::AnimationEnded(const gfx::Animation* animation) { } void InfoBar::RecalculateHeights(bool force_notify) { + // If there's no container delegate, there's no way to compute new element + // sizes, so return immediately. We don't need to worry that this might leave + // us with bogus sizes, because if we're ever re-added to a container, it will + // call Show(false) while re-adding us, which will compute a correct set of + // sizes. + if (!container_ || !container_->delegate()) + return; + int old_arrow_height = arrow_height_; int old_bar_height = bar_height_; - // Find the desired arrow height/half-width. The arrow area is - // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing, - // scaling each of these with the square root of the animation value causes a - // linear animation of the area, which matches the perception of the animation - // of the bar portion. - double scale_factor = sqrt(animation_.GetCurrentValue()); - arrow_height_ = static_cast<int>(arrow_target_height_ * scale_factor); - if (animation_.is_animating()) { - arrow_half_width_ = static_cast<int>(std::min(arrow_target_height_, - kMaximumArrowTargetHalfWidth) * scale_factor); - } else { - // When the infobar is not animating (i.e. fully open), we set the - // half-width to be proportionally the same distance between its default and - // maximum values as the height is between its. - arrow_half_width_ = kDefaultArrowTargetHalfWidth + - ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) * - ((arrow_height_ - kDefaultArrowTargetHeight) / - (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight))); - } - // Add pixels for the stroke, if the arrow is to be visible at all. Without - // this, changing the arrow height from 0 to kSeparatorLineHeight would - // produce no visible effect, because the stroke would paint atop the divider - // line above the infobar. - if (arrow_height_) - arrow_height_ += kSeparatorLineHeight; - - bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_); + container_->delegate()->ComputeInfoBarElementSizes( + animation_, arrow_target_height_, bar_target_height_, &arrow_height_, + &arrow_half_width_, &bar_height_); // Don't re-layout if nothing has changed, e.g. because the animation step was // not large enough to actually change the heights by at least a pixel. @@ -164,7 +147,7 @@ void InfoBar::RecalculateHeights(bool force_notify) { if (heights_differ) PlatformSpecificOnHeightsRecalculated(); - if (container_ && (heights_differ || force_notify)) + if (heights_differ || force_notify) container_->OnInfoBarStateChanged(animation_.is_animating()); } diff --git a/components/infobars/core/infobar.h b/components/infobars/core/infobar.h index 6124d88..8c1284a 100644 --- a/components/infobars/core/infobar.h +++ b/components/infobars/core/infobar.h @@ -40,16 +40,6 @@ class InfoBar : public gfx::AnimationDelegate { typedef InfoBar AddedDetails; typedef std::pair<InfoBar*, bool> RemovedDetails; - // Platforms must define these. - static const int kDefaultBarTargetHeight; - static const int kSeparatorLineHeight; - static const int kDefaultArrowTargetHeight; - static const int kMaximumArrowTargetHeight; - // The half-width (see comments on |arrow_half_width_| below) scales to its - // default and maximum values proportionally to how the height scales to its. - static const int kDefaultArrowTargetHalfWidth; - static const int kMaximumArrowTargetHalfWidth; - explicit InfoBar(scoped_ptr<InfoBarDelegate> delegate); ~InfoBar() override; @@ -136,12 +126,13 @@ class InfoBar : public gfx::AnimationDelegate { // The current and target heights of the arrow and bar portions, and half the // current arrow width. (It's easier to work in half-widths as we draw the - // arrow as two halves on either side of a center point.) + // arrow as two halves on either side of a center point.) All these values + // scale in unison to the container delegate's default and maximum values. int arrow_height_; // Includes both fill and top stroke. - int arrow_target_height_; + int arrow_target_height_; // Should always be set by the time we read it. int arrow_half_width_; // Includes only fill. int bar_height_; // Includes both fill and bottom separator. - int bar_target_height_; + int bar_target_height_; // May be left as -1, meaning "use default". DISALLOW_COPY_AND_ASSIGN(InfoBar); }; diff --git a/components/infobars/core/infobar_android.cc b/components/infobars/core/infobar_android.cc deleted file mode 100644 index 60258f8..0000000 --- a/components/infobars/core/infobar_android.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/infobars/core/infobar.h" - -// Static constants defined in infobar.h. We don't really use them for anything -// but they are required. The values are copied from the GTK implementation. -const int infobars::InfoBar::kSeparatorLineHeight = 1; -const int infobars::InfoBar::kDefaultArrowTargetHeight = 9; -const int infobars::InfoBar::kMaximumArrowTargetHeight = 24; -const int infobars::InfoBar::kDefaultArrowTargetHalfWidth = - kDefaultArrowTargetHeight; -const int infobars::InfoBar::kMaximumArrowTargetHalfWidth = 14; -const int infobars::InfoBar::kDefaultBarTargetHeight = 36; diff --git a/components/infobars/core/infobar_container.cc b/components/infobars/core/infobar_container.cc index b683112..90ba064 100644 --- a/components/infobars/core/infobar_container.cc +++ b/components/infobars/core/infobar_container.cc @@ -6,11 +6,11 @@ #include <algorithm> +#include "base/auto_reset.h" #include "base/logging.h" #include "build/build_config.h" #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_delegate.h" -#include "ui/gfx/animation/slide_animation.h" namespace infobars { @@ -20,7 +20,7 @@ InfoBarContainer::Delegate::~Delegate() { InfoBarContainer::InfoBarContainer(Delegate* delegate) : delegate_(delegate), infobar_manager_(NULL), - top_arrow_target_height_(InfoBar::kDefaultArrowTargetHeight) { + ignore_infobar_state_changed_(false) { } InfoBarContainer::~InfoBarContainer() { @@ -34,23 +34,26 @@ void InfoBarContainer::ChangeInfoBarManager(InfoBarManager* infobar_manager) { if (infobar_manager_) infobar_manager_->RemoveObserver(this); - // Hides all infobars in this container without animation. - while (!infobars_.empty()) { - InfoBar* infobar = infobars_.front(); - // Inform the infobar that it's hidden. If it was already closing, this - // deletes it. Otherwise, this ensures the infobar will be deleted if it's - // closed while it's not in an InfoBarContainer. - infobar->Hide(false); - } + { + // Ignore intermediate state changes. We'll manually trigger processing + // once we're finished. + base::AutoReset<bool> ignore_changes(&ignore_infobar_state_changed_, true); + + // Hides all infobars in this container without animation. + while (!infobars_.empty()) { + InfoBar* infobar = infobars_.front(); + // Inform the infobar that it's hidden. If it was already closing, this + // deletes it. Otherwise, this ensures the infobar will be deleted if + // it's closed while it's not in an InfoBarContainer. + infobar->Hide(false); + } - infobar_manager_ = infobar_manager; - if (infobar_manager_) { - infobar_manager_->AddObserver(this); + infobar_manager_ = infobar_manager; + if (infobar_manager_) { + infobar_manager_->AddObserver(this); - for (size_t i = 0; i < infobar_manager_->infobar_count(); ++i) { - // As when we removed the infobars above, we prevent callbacks to - // OnInfoBarStateChanged() for each infobar. - AddInfoBar(infobar_manager_->infobar_at(i), i, false, NO_CALLBACK); + for (size_t i = 0; i < infobar_manager_->infobar_count(); ++i) + AddInfoBar(infobar_manager_->infobar_at(i), i, false); } } @@ -77,16 +80,17 @@ int InfoBarContainer::GetVerticalOverlap(int* total_height) const { return vertical_overlap; } -void InfoBarContainer::SetMaxTopArrowHeight(int height) { - // Decrease the height by the arrow stroke thickness, which is the separator - // line height, because the infobar arrow target heights are without-stroke. - top_arrow_target_height_ = std::min( - std::max(height - InfoBar::kSeparatorLineHeight, 0), - InfoBar::kMaximumArrowTargetHeight); - UpdateInfoBarArrowTargetHeights(); +void InfoBarContainer::UpdateInfoBarArrowTargetHeights() { + for (size_t i = 0; i < infobars_.size(); ++i) { + infobars_[i]->SetArrowTargetHeight(delegate_ ? + delegate_->ArrowTargetHeightForInfoBar( + i, const_cast<const InfoBar*>(infobars_[i])->animation()) : 0); + } } void InfoBarContainer::OnInfoBarStateChanged(bool is_animating) { + if (ignore_infobar_state_changed_) + return; if (delegate_) delegate_->InfoBarContainerStateChanged(is_animating); UpdateInfoBarArrowTargetHeights(); @@ -112,7 +116,7 @@ void InfoBarContainer::RemoveAllInfoBarsForDestruction() { } void InfoBarContainer::OnInfoBarAdded(InfoBar* infobar) { - AddInfoBar(infobar, infobars_.size(), true, WANT_CALLBACK); + AddInfoBar(infobar, infobars_.size(), true); } void InfoBarContainer::OnInfoBarRemoved(InfoBar* infobar, bool animate) { @@ -128,7 +132,7 @@ void InfoBarContainer::OnInfoBarReplaced(InfoBar* old_infobar, DCHECK(i != infobars_.end()); size_t position = i - infobars_.begin(); old_infobar->Hide(false); - AddInfoBar(new_infobar, position, false, WANT_CALLBACK); + AddInfoBar(new_infobar, position, false); } void InfoBarContainer::OnManagerShuttingDown(InfoBarManager* manager) { @@ -139,41 +143,15 @@ void InfoBarContainer::OnManagerShuttingDown(InfoBarManager* manager) { void InfoBarContainer::AddInfoBar(InfoBar* infobar, size_t position, - bool animate, - CallbackStatus callback_status) { + bool animate) { DCHECK(std::find(infobars_.begin(), infobars_.end(), infobar) == infobars_.end()); DCHECK_LE(position, infobars_.size()); infobars_.insert(infobars_.begin() + position, infobar); UpdateInfoBarArrowTargetHeights(); PlatformSpecificAddInfoBar(infobar, position); - if (callback_status == WANT_CALLBACK) - infobar->set_container(this); + infobar->set_container(this); infobar->Show(animate); - if (callback_status == NO_CALLBACK) - infobar->set_container(this); -} - -void InfoBarContainer::UpdateInfoBarArrowTargetHeights() { - for (size_t i = 0; i < infobars_.size(); ++i) - infobars_[i]->SetArrowTargetHeight(ArrowTargetHeightForInfoBar(i)); -} - -int InfoBarContainer::ArrowTargetHeightForInfoBar(size_t infobar_index) const { - if (!delegate_ || !delegate_->DrawInfoBarArrows(NULL)) - return 0; - if (infobar_index == 0) - return top_arrow_target_height_; - const gfx::SlideAnimation& first_infobar_animation = - const_cast<const InfoBar*>(infobars_.front())->animation(); - if ((infobar_index > 1) || first_infobar_animation.IsShowing()) - return InfoBar::kDefaultArrowTargetHeight; - // When the first infobar is animating closed, we animate the second infobar's - // arrow target height from the default to the top target height. Note that - // the animation values here are going from 1.0 -> 0.0 as the top bar closes. - return top_arrow_target_height_ + static_cast<int>( - (InfoBar::kDefaultArrowTargetHeight - top_arrow_target_height_) * - first_infobar_animation.GetCurrentValue()); } } // namespace infobars diff --git a/components/infobars/core/infobar_container.h b/components/infobars/core/infobar_container.h index f802ab1..d0b076a 100644 --- a/components/infobars/core/infobar_container.h +++ b/components/infobars/core/infobar_container.h @@ -12,6 +12,10 @@ #include "components/infobars/core/infobar_manager.h" #include "third_party/skia/include/core/SkColor.h" +namespace gfx { +class SlideAnimation; +} + namespace infobars { class InfoBar; @@ -38,6 +42,24 @@ class InfoBarContainer : public InfoBarManager::Observer { // drawn, and if so, at what |x| coordinate. |x| may be NULL. virtual bool DrawInfoBarArrows(int* x) const = 0; + // Computes the target arrow height for infobar number |index|, given its + // animation. + virtual int ArrowTargetHeightForInfoBar( + size_t index, + const gfx::SlideAnimation& animation) const = 0; + + // Computes the sizes of the infobar arrow (height and half width) and bar + // (height) given the infobar's animation and its target element heights. + // |bar_target_height| may be -1, which means "use the default bar target + // height". + virtual void ComputeInfoBarElementSizes( + const gfx::SlideAnimation& animation, + int arrow_target_height, + int bar_target_height, + int* arrow_height, + int* arrow_half_width, + int* bar_height) const = 0; + protected: virtual ~Delegate(); }; @@ -56,16 +78,12 @@ class InfoBarContainer : public InfoBarManager::Observer { // (including overlap). int GetVerticalOverlap(int* total_height) const; - // Called by the delegate when the distance between what the top infobar's - // "unspoofable" arrow would point to and the top infobar itself changes. - // This enables the top infobar to show a longer arrow (e.g. because of a - // visible bookmark bar) or shorter (e.g. due to being in a popup window) if - // desired. + // Triggers a recalculation of all infobar arrow heights. // // IMPORTANT: This MUST NOT result in a call back to // Delegate::InfoBarContainerStateChanged() unless it causes an actual // change, lest we infinitely recurse. - void SetMaxTopArrowHeight(int height); + void UpdateInfoBarArrowTargetHeights(); // Called when a contained infobar has animated or by some other means changed // its height, or when it stops animating. The container is expected to do @@ -109,24 +127,18 @@ class InfoBarContainer : public InfoBarManager::Observer { // Adds |infobar| to this container before the existing infobar at position // |position| and calls Show() on it. |animate| is passed along to - // infobar->Show(). Depending on the value of |callback_status|, this calls - // infobar->set_container(this) either before or after the call to Show() so - // that OnInfoBarStateChanged() either will or won't be called as a result. - enum CallbackStatus { NO_CALLBACK, WANT_CALLBACK }; - void AddInfoBar(InfoBar* infobar, - size_t position, - bool animate, - CallbackStatus callback_status); - - void UpdateInfoBarArrowTargetHeights(); - int ArrowTargetHeightForInfoBar(size_t infobar_index) const; + // infobar->Show(). + void AddInfoBar(InfoBar* infobar, size_t position, bool animate); Delegate* delegate_; InfoBarManager* infobar_manager_; InfoBars infobars_; - // Calculated in SetMaxTopArrowHeight(). - int top_arrow_target_height_; + // Normally false. When true, OnInfoBarStateChanged() becomes a no-op. We + // use this to ensure that ChangeInfoBarManager() only executes the + // functionality in OnInfoBarStateChanged() once, to minimize unnecessary + // layout and painting. + bool ignore_infobar_state_changed_; DISALLOW_COPY_AND_ASSIGN(InfoBarContainer); }; diff --git a/components/infobars/test/infobar_test.cc b/components/infobars/test/infobar_test.cc index b661b50..1fef50f 100644 --- a/components/infobars/test/infobar_test.cc +++ b/components/infobars/test/infobar_test.cc @@ -13,17 +13,6 @@ // defining; instead, this information should be obtained via a client, // which can have a test implementation. crbug.com/386171 -// On Android, these variables are defined in ../core/infobar_android.cc. -#if !defined(OS_ANDROID) -const int infobars::InfoBar::kSeparatorLineHeight = 1; -const int infobars::InfoBar::kDefaultArrowTargetHeight = 9; -const int infobars::InfoBar::kMaximumArrowTargetHeight = 24; -const int infobars::InfoBar::kDefaultArrowTargetHalfWidth = - kDefaultArrowTargetHeight; -const int infobars::InfoBar::kMaximumArrowTargetHalfWidth = 14; -const int infobars::InfoBar::kDefaultBarTargetHeight = 36; -#endif - // Some components' unittests exercise code that requires that // ConfirmInfoBarDelegate::CreateInfoBar() return a non-NULL infobar. scoped_ptr<infobars::InfoBar> ConfirmInfoBarDelegate::CreateInfoBar( |