diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 21:06:00 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 21:06:00 +0000 |
commit | 32eb60f4c7e4dfc0912a241d9b8705fb63255eea (patch) | |
tree | 6b4075d30e4666c698f4289eb118e46e9168492b /views | |
parent | ce6eccf380ffd58ff21c5e1a43a0472fd4b8893e (diff) | |
download | chromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.zip chromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.tar.gz chromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.tar.bz2 |
Support Windows native textfield, combobox, etc. in new bubbles.
Should allow us to fully convert all bubbles (bookmark, etc.)
Use separate border and contents widgets (like old bubble).
Supports transparency/opacity with fading, etc.
Remove BubbleView remnants; update tests.
BUG=98312
TEST=No views_examples bubble problems.
Review URL: http://codereview.chromium.org/8368006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108167 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/bubble/bubble_delegate.cc | 157 | ||||
-rw-r--r-- | views/bubble/bubble_delegate.h | 27 | ||||
-rw-r--r-- | views/bubble/bubble_delegate_unittest.cc | 13 | ||||
-rw-r--r-- | views/bubble/bubble_frame_view_unittest.cc | 34 | ||||
-rw-r--r-- | views/bubble/bubble_view_unittest.cc | 30 | ||||
-rw-r--r-- | views/examples/bubble_example.cc | 6 | ||||
-rw-r--r-- | views/views.gyp | 1 | ||||
-rw-r--r-- | views/window/client_view.cc | 8 | ||||
-rw-r--r-- | views/window/client_view.h | 3 |
9 files changed, 183 insertions, 96 deletions
diff --git a/views/bubble/bubble_delegate.cc b/views/bubble/bubble_delegate.cc index 1fb7ebf..1b40c29 100644 --- a/views/bubble/bubble_delegate.cc +++ b/views/bubble/bubble_delegate.cc @@ -9,15 +9,76 @@ #include "views/widget/widget.h" // The duration of the fade animation in milliseconds. -static const int kHideFadeDurationMS = 1000; +static const int kHideFadeDurationMS = 200; namespace views { +namespace { + +// Create a widget to host the bubble. +Widget* CreateBubbleWidget(BubbleDelegateView* bubble, Widget* parent) { + Widget* bubble_widget = new Widget(); + Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE); + bubble_params.delegate = bubble; + bubble_params.transparent = true; + bubble_params.parent_widget = parent; + if (!bubble_params.parent_widget) + bubble_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; +#if defined(OS_WIN) && !defined(USE_AURA) + bubble_params.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; + bubble_params.transparent = false; +#endif + bubble_widget->Init(bubble_params); + return bubble_widget; +} + +#if defined(OS_WIN) && !defined(USE_AURA) +// The border widget's delegate, needed for transparent Windows native controls. +// TODO(msw): Remove this when Windows native controls are no longer needed. +class VIEWS_EXPORT BubbleBorderDelegateView : public WidgetDelegateView { + public: + explicit BubbleBorderDelegateView(BubbleDelegateView* bubble) + : bubble_(bubble) {} + virtual ~BubbleBorderDelegateView() {} + + // WidgetDelegateView overrides: + virtual bool CanActivate() const OVERRIDE; + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + + private: + BubbleDelegateView* bubble_; + + DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegateView); +}; + +bool BubbleBorderDelegateView::CanActivate() const { return false; } + +NonClientFrameView* BubbleBorderDelegateView::CreateNonClientFrameView() { + return bubble_->CreateNonClientFrameView(); +} + +// Create a widget to host the bubble's border. +Widget* CreateBorderWidget(BubbleDelegateView* bubble, Widget* parent) { + Widget* border_widget = new Widget(); + Widget::InitParams border_params(Widget::InitParams::TYPE_BUBBLE); + border_params.delegate = new BubbleBorderDelegateView(bubble); + border_params.transparent = true; + border_params.parent_widget = parent; + if (!border_params.parent_widget) + border_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + border_widget->Init(border_params); + return border_widget; +} +#endif + +} // namespace + BubbleDelegateView::BubbleDelegateView() - : WidgetDelegateView(), - close_on_esc_(true), + : close_on_esc_(true), arrow_location_(BubbleBorder::TOP_LEFT), - color_(SK_ColorWHITE) { + color_(SK_ColorWHITE), + border_widget_(NULL) { + set_background(views::Background::CreateSolidBackground(color_)); AddAccelerator(Accelerator(ui::VKEY_ESCAPE, 0)); } @@ -25,30 +86,35 @@ BubbleDelegateView::BubbleDelegateView( const gfx::Point& anchor_point, BubbleBorder::ArrowLocation arrow_location, const SkColor& color) - : WidgetDelegateView(), - close_on_esc_(true), + : close_on_esc_(true), anchor_point_(anchor_point), arrow_location_(arrow_location), color_(color), - original_opacity_(255) { + original_opacity_(255), + border_widget_(NULL) { + set_background(views::Background::CreateSolidBackground(color_)); AddAccelerator(Accelerator(ui::VKEY_ESCAPE, 0)); } -BubbleDelegateView::~BubbleDelegateView() {} +BubbleDelegateView::~BubbleDelegateView() { + if (border_widget_) + border_widget_->Close(); +} // static Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate, Widget* parent_widget) { bubble_delegate->Init(); - views::Widget* bubble_widget = new views::Widget(); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_BUBBLE); - params.delegate = bubble_delegate; - params.transparent = true; - if (!parent_widget) - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent_widget = parent_widget; - bubble_widget->Init(params); + Widget* bubble_widget = CreateBubbleWidget(bubble_delegate, parent_widget); + +#if defined(OS_WIN) && !defined(USE_AURA) + bubble_delegate->InitializeBorderWidget(parent_widget); + bubble_widget->SetContentsView(bubble_delegate->GetContentsView()); + bubble_widget->SetBounds(bubble_delegate->GetBubbleClientBounds()); +#else bubble_widget->SetBounds(bubble_delegate->GetBubbleBounds()); +#endif + return bubble_widget; } @@ -60,10 +126,6 @@ View* BubbleDelegateView::GetContentsView() { return this; } -ClientView* BubbleDelegateView::CreateClientView(Widget* widget) { - return new ClientView(widget, GetContentsView()); -} - NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView() { return new BubbleFrameView(GetArrowLocation(), GetPreferredSize(), @@ -82,7 +144,12 @@ SkColor BubbleDelegateView::GetColor() const { return color_; } -void BubbleDelegateView::Init() {} +void BubbleDelegateView::Show() { + if (border_widget_) + border_widget_->Show(); + GetWidget()->Show(); + GetFocusManager()->SetFocusedView(GetInitiallyFocusedView()); +} void BubbleDelegateView::StartFade(bool fade_in) { fade_animation_.reset(new ui::SlideAnimation(this)); @@ -90,8 +157,10 @@ void BubbleDelegateView::StartFade(bool fade_in) { fade_animation_->Reset(fade_in ? 0.0 : 1.0); if (fade_in) { original_opacity_ = 0; + if (border_widget_) + border_widget_->SetOpacity(original_opacity_); GetWidget()->SetOpacity(original_opacity_); - GetWidget()->Show(); + Show(); fade_animation_->Show(); } else { original_opacity_ = 255; @@ -101,6 +170,8 @@ void BubbleDelegateView::StartFade(bool fade_in) { void BubbleDelegateView::ResetFade() { fade_animation_.reset(); + if (border_widget_) + border_widget_->SetOpacity(original_opacity_); GetWidget()->SetOpacity(original_opacity_); } @@ -113,6 +184,8 @@ bool BubbleDelegateView::AcceleratorPressed(const Accelerator& accelerator) { return true; } +void BubbleDelegateView::Init() {} + void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { DCHECK_EQ(animation, fade_animation_.get()); bool closed = fade_animation_->GetCurrentValue() == 0; @@ -124,17 +197,28 @@ void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { void BubbleDelegateView::AnimationProgressed(const ui::Animation* animation) { DCHECK_EQ(animation, fade_animation_.get()); DCHECK(fade_animation_->is_animating()); - GetWidget()->SetOpacity(fade_animation_->GetCurrentValue() * 255); + unsigned char opacity = fade_animation_->GetCurrentValue() * 255; +#if defined(OS_WIN) && !defined(USE_AURA) + // Explicitly set the content Widget's layered style and set transparency via + // SetLayeredWindowAttributes. This is done because initializing the Widget as + // transparent and setting opacity via UpdateLayeredWindow doesn't support + // hosting child native Windows controls. + const HWND hwnd = GetWidget()->GetNativeView(); + const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE); + if ((opacity == 255) == !!(style & WS_EX_LAYERED)) + SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED); + SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA); + // Update the border widget's opacity. + border_widget_->SetOpacity(opacity); + border_widget_->non_client_view()->SchedulePaint(); +#endif + GetWidget()->SetOpacity(opacity); SchedulePaint(); } -const BubbleView* BubbleDelegateView::GetBubbleView() const { - return GetWidget()->client_view()->AsBubbleView(); -} - -const BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const { - return static_cast<BubbleFrameView*>( - GetWidget()->non_client_view()->frame_view()); +BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const { + const Widget* widget = border_widget_ ? border_widget_ : GetWidget(); + return static_cast<BubbleFrameView*>(widget->non_client_view()->frame_view()); } gfx::Rect BubbleDelegateView::GetBubbleBounds() { @@ -144,4 +228,17 @@ gfx::Rect BubbleDelegateView::GetBubbleBounds() { gfx::Rect(GetAnchorPoint(), GetPreferredSize())); } +#if defined(OS_WIN) && !defined(USE_AURA) +void BubbleDelegateView::InitializeBorderWidget(Widget* parent_widget) { + border_widget_ = CreateBorderWidget(this, parent_widget); + border_widget_->SetBounds(GetBubbleBounds()); +} + +gfx::Rect BubbleDelegateView::GetBubbleClientBounds() const { + gfx::Rect client_bounds(GetBubbleFrameView()->GetBoundsForClientView()); + client_bounds.Offset(border_widget_->GetWindowScreenBounds().origin()); + return client_bounds; +} +#endif + } // namespace views diff --git a/views/bubble/bubble_delegate.h b/views/bubble/bubble_delegate.h index 929f619..a5f6ab9 100644 --- a/views/bubble/bubble_delegate.h +++ b/views/bubble/bubble_delegate.h @@ -6,6 +6,7 @@ #define VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ #pragma once +#include "base/gtest_prod_util.h" #include "ui/base/animation/animation_delegate.h" #include "views/bubble/bubble_border.h" #include "views/widget/widget_delegate.h" @@ -17,7 +18,6 @@ class SlideAnimation; namespace views { class BubbleFrameView; -class BubbleView; // BubbleDelegateView creates frame and client views for bubble Widgets. // BubbleDelegateView itself is the client's contents view. @@ -32,14 +32,13 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, const SkColor& color); virtual ~BubbleDelegateView(); - // Create a bubble Widget from the argument BubbleDelegateView. + // Create and initialize the bubble Widget(s) with proper bounds. static Widget* CreateBubble(BubbleDelegateView* bubble_delegate, Widget* parent_widget); // WidgetDelegate overrides: virtual View* GetInitiallyFocusedView() OVERRIDE; virtual View* GetContentsView() OVERRIDE; - virtual ClientView* CreateClientView(Widget* widget) OVERRIDE; virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; bool close_on_esc() const { return close_on_esc_; } @@ -54,6 +53,9 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, // Get the color used for the background and border. virtual SkColor GetColor() const; + // Show the bubble's widget (and |border_widget_| on Windows). + void Show(); + // Fade the bubble in or out via Widget transparency. // Fade in calls Widget::Show; fade out calls Widget::Close upon completion. void StartFade(bool fade_in); @@ -70,16 +72,26 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, virtual void Init(); private: + FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewBasicTest, NonClientHitTest); + FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate); + // ui::AnimationDelegate overrides: virtual void AnimationEnded(const ui::Animation* animation); virtual void AnimationProgressed(const ui::Animation* animation); - const BubbleView* GetBubbleView() const; - const BubbleFrameView* GetBubbleFrameView() const; + BubbleFrameView* GetBubbleFrameView() const; // Get bubble bounds from the anchor point and client view's preferred size. gfx::Rect GetBubbleBounds(); +#if defined(OS_WIN) && !defined(USE_AURA) + // Initialize the border widget needed for Windows native control hosting. + void InitializeBorderWidget(Widget* parent_widget); + + // Get bounds for the Windows-only widget that hosts the bubble's contents. + gfx::Rect GetBubbleClientBounds() const; +#endif + // Fade animation for bubble. scoped_ptr<ui::SlideAnimation> fade_animation_; @@ -97,6 +109,11 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, // Original opacity of the bubble. int original_opacity_; + + // The widget hosting the border for this bubble (non-Aura Windows only). + Widget* border_widget_; + + DISALLOW_COPY_AND_ASSIGN(BubbleDelegateView); }; } // namespace views diff --git a/views/bubble/bubble_delegate_unittest.cc b/views/bubble/bubble_delegate_unittest.cc index ea3241c..ce561f5d 100644 --- a/views/bubble/bubble_delegate_unittest.cc +++ b/views/bubble/bubble_delegate_unittest.cc @@ -3,26 +3,29 @@ // found in the LICENSE file. #include "views/bubble/bubble_delegate.h" +#include "views/bubble/bubble_frame_view.h" #include "views/test/views_test_base.h" #include "views/widget/widget.h" namespace views { -namespace { - typedef ViewsTestBase BubbleDelegateTest; TEST_F(BubbleDelegateTest, CreateDelegate) { BubbleDelegateView* bubble_delegate = new BubbleDelegateView(); scoped_ptr<Widget> bubble_widget( - views::BubbleDelegateView::CreateBubble(bubble_delegate, NULL)); + BubbleDelegateView::CreateBubble(bubble_delegate, NULL)); EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); + + BubbleBorder* border = static_cast<BubbleBorder*>( + bubble_delegate->GetBubbleFrameView()->border()); + EXPECT_EQ(bubble_delegate->GetArrowLocation(), border->arrow_location()); + EXPECT_EQ(bubble_delegate->GetColor(), border->background_color()); + bubble_widget->CloseNow(); bubble_widget.reset(); RunPendingMessages(); } -} // namespace - } // namespace views diff --git a/views/bubble/bubble_frame_view_unittest.cc b/views/bubble/bubble_frame_view_unittest.cc index 766bcec..bbdd203 100644 --- a/views/bubble/bubble_frame_view_unittest.cc +++ b/views/bubble/bubble_frame_view_unittest.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "views/bubble/bubble_frame_view.h" #include "views/bubble/bubble_delegate.h" +#include "views/bubble/bubble_frame_view.h" #include "views/test/views_test_base.h" #include "views/widget/widget.h" #if !defined(OS_WIN) @@ -32,22 +32,34 @@ TEST_F(BubbleFrameViewBasicTest, GetBoundsForClientView) { EXPECT_EQ(expected_insets.top(), frame.GetBoundsForClientView().y()); } +} // namespace + +class SizedBubbleDelegateView : public BubbleDelegateView { + public: + SizedBubbleDelegateView() {} + virtual ~SizedBubbleDelegateView() {} + + // View overrides: + virtual gfx::Size GetPreferredSize() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(SizedBubbleDelegateView); +}; + +gfx::Size SizedBubbleDelegateView::GetPreferredSize() { return kRect.size(); } + TEST_F(BubbleFrameViewBasicTest, NonClientHitTest) { - BubbleDelegateView* delegate = new BubbleDelegateView(); - scoped_ptr<Widget> widget( - views::BubbleDelegateView::CreateBubble(delegate, NULL)); - widget->SetBounds(kRect); - widget->Show(); + SizedBubbleDelegateView* delegate = new SizedBubbleDelegateView(); + scoped_ptr<Widget> widget(BubbleDelegateView::CreateBubble(delegate, NULL)); + delegate->Show(); gfx::Point kPtInBound(100, 100); gfx::Point kPtOutsideBound(1000, 1000); - EXPECT_EQ(HTCLIENT, widget->non_client_view()->NonClientHitTest(kPtInBound)); - EXPECT_EQ(HTNOWHERE, - widget->non_client_view()->NonClientHitTest(kPtOutsideBound)); + BubbleFrameView* bubble_frame_view = delegate->GetBubbleFrameView(); + EXPECT_EQ(HTCLIENT, bubble_frame_view->NonClientHitTest(kPtInBound)); + EXPECT_EQ(HTNOWHERE, bubble_frame_view->NonClientHitTest(kPtOutsideBound)); widget->CloseNow(); widget.reset(); RunPendingMessages(); } -} // namespace - } // namespace views diff --git a/views/bubble/bubble_view_unittest.cc b/views/bubble/bubble_view_unittest.cc deleted file mode 100644 index c2a04fc..0000000 --- a/views/bubble/bubble_view_unittest.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011 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 "views/bubble/bubble_delegate.h" -#include "views/test/views_test_base.h" -#include "views/widget/widget.h" - -namespace views { - -namespace { - -typedef ViewsTestBase BubbleViewBasicTest; - -TEST_F(BubbleViewBasicTest, CreateArrowBubble) { - BubbleDelegateView* bubble_delegate = new BubbleDelegateView(); - scoped_ptr<Widget> bubble_widget( - views::BubbleDelegateView::CreateBubble(bubble_delegate, NULL)); - - BubbleBorder* border = static_cast<BubbleBorder*>( - bubble_widget->non_client_view()->frame_view()->border()); - EXPECT_EQ(bubble_delegate->GetArrowLocation(), border->arrow_location()); - bubble_widget->CloseNow(); - bubble_widget.reset(); - RunPendingMessages(); -} - -} // namespace - -} // namespace views diff --git a/views/examples/bubble_example.cc b/views/examples/bubble_example.cc index f99155b..b0d5ec4 100644 --- a/views/examples/bubble_example.cc +++ b/views/examples/bubble_example.cc @@ -88,13 +88,13 @@ void BubbleExample::ButtonPressed(views::Button* sender, ExampleBubbleDelegateView* bubble_delegate = new ExampleBubbleDelegateView(config); - views::Widget* bubble = views::BubbleDelegateView::CreateBubble( - bubble_delegate, example_view()->GetWidget()); + views::BubbleDelegateView::CreateBubble(bubble_delegate, + example_view()->GetWidget()); if (config.fade_in) bubble_delegate->StartFade(true); else - bubble->Show(); + bubble_delegate->Show(); if (config.fade_out) { bubble_delegate->set_close_on_esc(false); diff --git a/views/views.gyp b/views/views.gyp index 09cadf9..b8082a4 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -572,7 +572,6 @@ 'animation/bounds_animator_unittest.cc', 'bubble/bubble_delegate_unittest.cc', 'bubble/bubble_frame_view_unittest.cc', - 'bubble/bubble_view_unittest.cc', 'controls/label_unittest.cc', 'controls/progress_bar_unittest.cc', 'controls/single_split_view_unittest.cc', diff --git a/views/window/client_view.cc b/views/window/client_view.cc index 5b0d006..f0dc66a 100644 --- a/views/window/client_view.cc +++ b/views/window/client_view.cc @@ -37,14 +37,6 @@ const DialogClientView* ClientView::AsDialogClientView() const { return NULL; } -BubbleView* ClientView::AsBubbleView() { - return NULL; -} - -const BubbleView* ClientView::AsBubbleView() const { - return NULL; -} - bool ClientView::CanClose() { return true; } diff --git a/views/window/client_view.h b/views/window/client_view.h index f45e508..4cd6f14 100644 --- a/views/window/client_view.h +++ b/views/window/client_view.h @@ -10,7 +10,6 @@ namespace views { -class BubbleView; class DialogClientView; class Widget; @@ -37,8 +36,6 @@ class VIEWS_EXPORT ClientView : public View { // Manual RTTI ftw. virtual DialogClientView* AsDialogClientView(); virtual const DialogClientView* AsDialogClientView() const; - virtual BubbleView* AsBubbleView(); - virtual const BubbleView* AsBubbleView() const; // Returns true to signal that the Widget can be closed. Specialized // ClientView subclasses can override this default behavior to allow the |