diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-24 00:45:40 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-24 00:45:40 +0000 |
commit | 4a232aa8b83a3744f5f060c085d4acb26b03ee28 (patch) | |
tree | 2c8b46265440f3650cf5f80a78d05d81bbc4ff90 | |
parent | 0058be738828caec160643c177dcb809e2fdbf05 (diff) | |
download | chromium_src-4a232aa8b83a3744f5f060c085d4acb26b03ee28.zip chromium_src-4a232aa8b83a3744f5f060c085d4acb26b03ee28.tar.gz chromium_src-4a232aa8b83a3744f5f060c085d4acb26b03ee28.tar.bz2 |
Add caption animations and clean up the frame component code a bit.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8020002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102629 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/aura_shell/examples/toplevel_window.cc | 24 | ||||
-rw-r--r-- | ui/aura_shell/examples/toplevel_window.h | 15 | ||||
-rw-r--r-- | ui/aura_shell/examples/window_type_launcher.cc | 16 | ||||
-rw-r--r-- | ui/aura_shell/examples/window_type_launcher.h | 1 | ||||
-rw-r--r-- | ui/aura_shell/toplevel_frame_view.cc | 285 | ||||
-rw-r--r-- | ui/aura_shell/toplevel_frame_view.h | 21 |
6 files changed, 244 insertions, 118 deletions
diff --git a/ui/aura_shell/examples/toplevel_window.cc b/ui/aura_shell/examples/toplevel_window.cc index 8ef3fd2..875a077 100644 --- a/ui/aura_shell/examples/toplevel_window.cc +++ b/ui/aura_shell/examples/toplevel_window.cc @@ -6,22 +6,28 @@ #include "base/utf_string_conversions.h" #include "ui/aura/window.h" +#include "ui/aura_shell/toplevel_frame_view.h" #include "ui/gfx/canvas.h" #include "views/widget/widget.h" namespace aura_shell { namespace examples { +ToplevelWindow::CreateParams::CreateParams() + : can_resize(false), + can_maximize(false) { +} + // static -void ToplevelWindow::CreateToplevelWindow() { +void ToplevelWindow::CreateToplevelWindow(const CreateParams& params) { views::Widget* widget = - views::Widget::CreateWindowWithBounds(new ToplevelWindow, + views::Widget::CreateWindowWithBounds(new ToplevelWindow(params), gfx::Rect(120, 150, 400, 300)); widget->GetNativeView()->set_name(ASCIIToUTF16("Examples:ToplevelWindow")); widget->Show(); } -ToplevelWindow::ToplevelWindow() { +ToplevelWindow::ToplevelWindow(const CreateParams& params) : params_(params) { } ToplevelWindow::~ToplevelWindow() { @@ -39,5 +45,17 @@ views::View* ToplevelWindow::GetContentsView() { return this; } +bool ToplevelWindow::CanResize() const { + return params_.can_resize; +} + +bool ToplevelWindow::CanMaximize() const { + return params_.can_maximize; +} + +views::NonClientFrameView* ToplevelWindow::CreateNonClientFrameView() { + return new aura_shell::internal::ToplevelFrameView; +} + } // namespace examples } // namespace aura_shell diff --git a/ui/aura_shell/examples/toplevel_window.h b/ui/aura_shell/examples/toplevel_window.h index 3541b4a..8b61743 100644 --- a/ui/aura_shell/examples/toplevel_window.h +++ b/ui/aura_shell/examples/toplevel_window.h @@ -13,10 +13,16 @@ namespace examples { class ToplevelWindow : public views::WidgetDelegateView { public: - static void CreateToplevelWindow(); + struct CreateParams { + CreateParams(); + + bool can_resize; + bool can_maximize; + }; + static void CreateToplevelWindow(const CreateParams& params); private: - ToplevelWindow(); + explicit ToplevelWindow(const CreateParams& params); virtual ~ToplevelWindow(); // Overridden from views::View: @@ -25,6 +31,11 @@ class ToplevelWindow : public views::WidgetDelegateView { // Overridden from views::WidgetDelegate: virtual std::wstring GetWindowTitle() const OVERRIDE; virtual View* GetContentsView() OVERRIDE; + virtual bool CanResize() const OVERRIDE; + virtual bool CanMaximize() const OVERRIDE; + virtual views::NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + + const CreateParams params_; DISALLOW_COPY_AND_ASSIGN(ToplevelWindow); }; diff --git a/ui/aura_shell/examples/window_type_launcher.cc b/ui/aura_shell/examples/window_type_launcher.cc index 1957ad2..e620088 100644 --- a/ui/aura_shell/examples/window_type_launcher.cc +++ b/ui/aura_shell/examples/window_type_launcher.cc @@ -32,9 +32,13 @@ void InitWindowTypeLauncher() { WindowTypeLauncher::WindowTypeLauncher() : ALLOW_THIS_IN_INITIALIZER_LIST( create_button_(new views::NativeTextButton(this, L"Create Window"))), + ALLOW_THIS_IN_INITIALIZER_LIST( + create_nonresizable_button_(new views::NativeTextButton( + this, L"Create Non-Resizable Window"))), ALLOW_THIS_IN_INITIALIZER_LIST(bubble_button_( new views::NativeTextButton(this, L"Create Pointy Bubble"))) { AddChildView(create_button_); + AddChildView(create_nonresizable_button_); AddChildView(bubble_button_); set_context_menu_controller(this); } @@ -57,6 +61,12 @@ void WindowTypeLauncher::Layout() { bubble_button_->SetBounds( 5, create_button_->y() - bubble_button_ps.height() - 5, bubble_button_ps.width(), bubble_button_ps.height()); + + gfx::Size create_nr_button_ps = + create_nonresizable_button_->GetPreferredSize(); + create_nonresizable_button_->SetBounds( + 5, bubble_button_->y() - create_nr_button_ps.height() - 5, + create_nr_button_ps.width(), create_nr_button_ps.height()); } gfx::Size WindowTypeLauncher::GetPreferredSize() { @@ -87,7 +97,11 @@ views::NonClientFrameView* WindowTypeLauncher::CreateNonClientFrameView() { void WindowTypeLauncher::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == create_button_) { - ToplevelWindow::CreateToplevelWindow(); + ToplevelWindow::CreateParams params; + params.can_resize = true; + ToplevelWindow::CreateToplevelWindow(params); + } else if (sender == create_nonresizable_button_) { + ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams()); } else if (sender == bubble_button_) { gfx::Point origin = bubble_button_->bounds().origin(); views::View::ConvertPointToWidget(bubble_button_->parent(), &origin); diff --git a/ui/aura_shell/examples/window_type_launcher.h b/ui/aura_shell/examples/window_type_launcher.h index 303e255..aab1126 100644 --- a/ui/aura_shell/examples/window_type_launcher.h +++ b/ui/aura_shell/examples/window_type_launcher.h @@ -59,6 +59,7 @@ class WindowTypeLauncher : public views::WidgetDelegateView, bool is_mouse_gesture) OVERRIDE; views::NativeTextButton* create_button_; + views::NativeTextButton* create_nonresizable_button_; views::NativeTextButton* bubble_button_; scoped_ptr<views::MenuRunner> menu_runner_; diff --git a/ui/aura_shell/toplevel_frame_view.cc b/ui/aura_shell/toplevel_frame_view.cc index 526893f..11590c7 100644 --- a/ui/aura_shell/toplevel_frame_view.cc +++ b/ui/aura_shell/toplevel_frame_view.cc @@ -68,42 +68,50 @@ class WindowControlButton : public views::CustomButton { DISALLOW_COPY_AND_ASSIGN(WindowControlButton); }; -class SizingBorder : public views::View, - public ui::AnimationDelegate { +// Base class for all animatable frame components such as sizing borders and +// the window's caption. Provides shared animation and event-handling logic. +class FrameComponent : public views::View, + public ui::AnimationDelegate { public: - SizingBorder() - : ALLOW_THIS_IN_INITIALIZER_LIST( - animation_(new ui::SlideAnimation(this))) { - animation_->SetSlideDuration(kHoverFadeDurationMs); - } - virtual ~SizingBorder() {} - - void Configure(const gfx::Rect& hidden_bounds, - const gfx::Rect& visible_bounds) { - hidden_bounds_ = hidden_bounds; - visible_bounds_ = visible_bounds; - SetBoundsRect(hidden_bounds_); + virtual ~FrameComponent() { } + // Control animations. void Show() { animation_->Show(); } - void Hide() { animation_->Hide(); } + // Current animation state. bool IsShowing() const { return animation_->IsShowing(); } - bool IsHiding() const { return animation_->IsClosing(); } - private: - // Overridden from views::View: - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + // Returns true if the view ignores events to itself or its children at the + // specified point in its parent's coordinates. By default, any events within + // the bounds of this view are ignored so that the parent (the NCFV) can + // handle them instead. Derived classes can override to disable this for some + // of their children. + virtual bool IgnoreEventsForPoint(const gfx::Point& point) { + gfx::Point translated_point(point); + ConvertPointToView(parent(), this, &translated_point); + return HitTest(translated_point); + } + + protected: + FrameComponent() + : ALLOW_THIS_IN_INITIALIZER_LIST( + animation_(new ui::SlideAnimation(this))) { + animation_->SetSlideDuration(kHoverFadeDurationMs); + } + + // Most of the frame components are rendered with a transparent bg. + void PaintTransparentBackground(gfx::Canvas* canvas) { // Fill with current opacity value. int opacity = animation_->CurrentValueBetween(kFrameBorderHiddenOpacity, kFrameBorderVisibleOpacity); @@ -115,21 +123,147 @@ class SizingBorder : public views::View, } // Overridden from ui::AnimationDelegate: - void AnimationProgressed(const ui::Animation* animation) OVERRIDE { - // TODO: update bounds. - gfx::Rect current_bounds = animation_->CurrentValueBetween(hidden_bounds_, - visible_bounds_); - SetBoundsRect(current_bounds); + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { SchedulePaint(); } + private: + scoped_ptr<ui::SlideAnimation> animation_; + + DISALLOW_COPY_AND_ASSIGN(FrameComponent); +}; + +// A view that renders the title bar of the window, and also hosts the window +// controls. +class WindowCaption : public FrameComponent, + public views::ButtonListener { + public: + WindowCaption() { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + close_button_ = + new WindowControlButton(this, SK_ColorRED, + *rb.GetBitmapNamed(IDR_AURA_WINDOW_CLOSE_ICON)); + zoom_button_ = + new WindowControlButton(this, SK_ColorGREEN, + *rb.GetBitmapNamed(IDR_AURA_WINDOW_ZOOM_ICON)); + AddChildView(close_button_); + AddChildView(zoom_button_); + } + virtual ~WindowCaption() {} + + // Returns the hit-test code for the specified point in parent coordinates. + int NonClientHitTest(const gfx::Point& point) { + gfx::Point translated_point(point); + View::ConvertPointToView(parent(), this, &translated_point); + // The window controls come second. + if (close_button_->GetMirroredBounds().Contains(translated_point)) + return HTCLOSE; + else if (zoom_button_->GetMirroredBounds().Contains(translated_point)) + return HTMAXBUTTON; + return HTNOWHERE; + } + + // Updates the enabled state of the close button. + void EnableClose(bool enable) { + close_button_->SetEnabled(enable); + } + + // Overridden from FrameComponent: + virtual bool IgnoreEventsForPoint(const gfx::Point& point) OVERRIDE { + gfx::Point translated_point(point); + ConvertPointToView(parent(), this, &translated_point); + if (PointIsInChildView(close_button_, translated_point)) + return false; + if (PointIsInChildView(zoom_button_, translated_point)) + return false; + return FrameComponent::IgnoreEventsForPoint(point); + } + + // Overridden from views::View: + virtual gfx::Size GetPreferredSize() OVERRIDE { + return gfx::Size(0, close_button_->GetPreferredSize().height()); + } + + private: + // Returns true if the specified |point| in this view's coordinates hit tests + // against |child|, a child view of this view. + bool PointIsInChildView(views::View* child, + const gfx::Point& point) const { + gfx::Point child_point(point); + ConvertPointToView(this, child, &child_point); + return child->HitTest(child_point); + } + + // Overridden from views::View: + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + PaintTransparentBackground(canvas); + } + virtual void Layout() OVERRIDE { + gfx::Size close_button_ps = close_button_->GetPreferredSize(); + close_button_->SetBoundsRect( + gfx::Rect(width() - close_button_ps.width(), + 0, close_button_ps.width(), close_button_ps.height())); + + gfx::Size zoom_button_ps = zoom_button_->GetPreferredSize(); + zoom_button_->SetBoundsRect( + gfx::Rect(close_button_->x() - zoom_button_ps.width(), 0, + zoom_button_ps.width(), zoom_button_ps.height())); + } + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) OVERRIDE { + if (sender == close_button_) { + GetWidget()->Close(); + } else if (sender == zoom_button_) { + if (GetWidget()->IsMaximized()) + GetWidget()->Restore(); + else + GetWidget()->Maximize(); + } + } + + views::Button* close_button_; + views::Button* zoom_button_; + + DISALLOW_COPY_AND_ASSIGN(WindowCaption); +}; + +// A class that renders the sizing border that appears when the user moves +// their mouse over a sizing edge. This view is not actually responsible for +// resizing the window, the EventFilter is. +class SizingBorder : public FrameComponent { + public: + SizingBorder() {} + virtual ~SizingBorder() {} + + void Configure(const gfx::Rect& hidden_bounds, + const gfx::Rect& visible_bounds) { + hidden_bounds_ = hidden_bounds; + visible_bounds_ = visible_bounds; + SetBoundsRect(hidden_bounds_); + } + + protected: + // Overridden from ui::AnimationDelegate: + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { + gfx::Rect current_bounds = animation->CurrentValueBetween(hidden_bounds_, + visible_bounds_); + SetBoundsRect(current_bounds); + FrameComponent::AnimationProgressed(animation); + } + + private: + // Overridden from views::View: + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + PaintTransparentBackground(canvas); + } + // Each of these represents the hidden/visible states of the sizing border. // When the view is shown or hidden it animates between them. gfx::Rect hidden_bounds_; gfx::Rect visible_bounds_; - scoped_ptr<ui::SlideAnimation> animation_; - DISALLOW_COPY_AND_ASSIGN(SizingBorder); }; @@ -138,19 +272,11 @@ class SizingBorder : public views::View, ToplevelFrameView::ToplevelFrameView() : current_hittest_code_(HTNOWHERE), + caption_(new WindowCaption), left_edge_(new SizingBorder), right_edge_(new SizingBorder), bottom_edge_(new SizingBorder) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - close_button_ = - new WindowControlButton(this, SK_ColorRED, - *rb.GetBitmapNamed(IDR_AURA_WINDOW_CLOSE_ICON)); - zoom_button_ = - new WindowControlButton(this, SK_ColorGREEN, - *rb.GetBitmapNamed(IDR_AURA_WINDOW_ZOOM_ICON)); - AddChildView(close_button_); - AddChildView(zoom_button_); - + AddChildView(caption_); AddChildView(left_edge_); AddChildView(right_edge_); AddChildView(bottom_edge_); @@ -167,7 +293,7 @@ int ToplevelFrameView::NonClientBorderThickness() const { } int ToplevelFrameView::NonClientTopBorderHeight() const { - return close_button_->GetPreferredSize().height(); + return caption_->GetPreferredSize().height(); } int ToplevelFrameView::NonClientHitTestImpl(const gfx::Point& point) { @@ -180,11 +306,9 @@ int ToplevelFrameView::NonClientHitTestImpl(const gfx::Point& point) { if (frame_component != HTNOWHERE) return frame_component; - // The window controls come second. - if (close_button_->GetMirroredBounds().Contains(point)) - return HTCLOSE; - else if (zoom_button_->GetMirroredBounds().Contains(point)) - return HTMAXBUTTON; + frame_component = caption_->NonClientHitTest(point); + if (frame_component != HTNOWHERE) + return frame_component; // Finally other portions of the frame/sizing border. frame_component = @@ -199,24 +323,19 @@ int ToplevelFrameView::NonClientHitTestImpl(const gfx::Point& point) { return frame_component == HTNOWHERE ? HTCAPTION : frame_component; } -void ToplevelFrameView::ShowSizingBorder(SizingBorder* sizing_border) { - if (sizing_border && !sizing_border->IsShowing()) - sizing_border->Show(); - if (left_edge_ != sizing_border && !left_edge_->IsHiding()) +void ToplevelFrameView::ShowFrameComponent(FrameComponent* frame_component) { + if (frame_component && !frame_component->IsShowing()) + frame_component->Show(); + if (caption_ != frame_component && !caption_->IsHiding()) + caption_->Hide(); + if (left_edge_ != frame_component && !left_edge_->IsHiding()) left_edge_->Hide(); - if (right_edge_ != sizing_border && !right_edge_->IsHiding()) + if (right_edge_ != frame_component && !right_edge_->IsHiding()) right_edge_->Hide(); - if (bottom_edge_ != sizing_border && !bottom_edge_->IsHiding()) + if (bottom_edge_ != frame_component && !bottom_edge_->IsHiding()) bottom_edge_->Hide(); } -bool ToplevelFrameView::PointIsInChildView(views::View* child, - const gfx::Point& point) const { - gfx::Point child_point(point); - ConvertPointToView(this, child, &child_point); - return child->HitTest(child_point); -} - gfx::Rect ToplevelFrameView::GetHiddenBoundsForSizingBorder( int frame_component) const { int border_size = NonClientBorderThickness(); @@ -285,7 +404,7 @@ void ToplevelFrameView::GetWindowMask(const gfx::Size& size, } void ToplevelFrameView::EnableClose(bool enable) { - close_button_->SetEnabled(enable); + caption_->EnableClose(enable); } void ToplevelFrameView::ResetWindowControls() { @@ -306,15 +425,9 @@ void ToplevelFrameView::Layout() { NonClientBorderThickness(), NonClientBorderThickness()); - gfx::Size close_button_ps = close_button_->GetPreferredSize(); - close_button_->SetBoundsRect( - gfx::Rect(width() - close_button_ps.width() - NonClientBorderThickness(), - 0, close_button_ps.width(), close_button_ps.height())); - - gfx::Size zoom_button_ps = zoom_button_->GetPreferredSize(); - zoom_button_->SetBoundsRect( - gfx::Rect(close_button_->x() - zoom_button_ps.width(), 0, - zoom_button_ps.width(), zoom_button_ps.height())); + caption_->SetBounds(NonClientBorderThickness(), 0, + width() - 2 * NonClientBorderThickness(), + NonClientTopBorderHeight()); left_edge_->Configure(GetHiddenBoundsForSizingBorder(HTLEFT), GetVisibleBoundsForSizingBorder(HTLEFT)); @@ -324,24 +437,19 @@ void ToplevelFrameView::Layout() { GetVisibleBoundsForSizingBorder(HTBOTTOM)); } -void ToplevelFrameView::OnPaint(gfx::Canvas* canvas) { - gfx::Rect caption_rect(NonClientBorderThickness(), 0, - width() - 2 * NonClientBorderThickness(), - NonClientTopBorderHeight()); - canvas->FillRectInt(kFrameColor, caption_rect.x(), caption_rect.y(), - caption_rect.width(), caption_rect.height()); -} - void ToplevelFrameView::OnMouseMoved(const views::MouseEvent& event) { switch (current_hittest_code_) { case HTLEFT: - ShowSizingBorder(left_edge_); + ShowFrameComponent(left_edge_); break; case HTRIGHT: - ShowSizingBorder(right_edge_); + ShowFrameComponent(right_edge_); break; case HTBOTTOM: - ShowSizingBorder(bottom_edge_); + ShowFrameComponent(bottom_edge_); + break; + case HTCAPTION: + ShowFrameComponent(caption_); break; default: break; @@ -349,34 +457,19 @@ void ToplevelFrameView::OnMouseMoved(const views::MouseEvent& event) { } void ToplevelFrameView::OnMouseExited(const views::MouseEvent& event) { - ShowSizingBorder(NULL); + ShowFrameComponent(NULL); } views::View* ToplevelFrameView::GetEventHandlerForPoint( const gfx::Point& point) { - if (PointIsInChildView(left_edge_, point) || - PointIsInChildView(right_edge_, point) || - PointIsInChildView(bottom_edge_, point)) { + if (left_edge_->IgnoreEventsForPoint(point) || + right_edge_->IgnoreEventsForPoint(point) || + bottom_edge_->IgnoreEventsForPoint(point) || + caption_->IgnoreEventsForPoint(point)) { return this; } return View::GetEventHandlerForPoint(point); } - -//////////////////////////////////////////////////////////////////////////////// -// ToplevelFrameView, views::ButtonListener implementation: - -void ToplevelFrameView::ButtonPressed(views::Button* sender, - const views::Event& event) { - if (sender == close_button_) { - GetWidget()->Close(); - } else if (sender == zoom_button_) { - if (GetWidget()->IsMaximized()) - GetWidget()->Restore(); - else - GetWidget()->Maximize(); - } -} - } // namespace internal } // namespace aura_shell diff --git a/ui/aura_shell/toplevel_frame_view.h b/ui/aura_shell/toplevel_frame_view.h index 2d9aa67..10772dc 100644 --- a/ui/aura_shell/toplevel_frame_view.h +++ b/ui/aura_shell/toplevel_frame_view.h @@ -7,25 +7,21 @@ #pragma once #include "ui/aura_shell/aura_shell_export.h" -#include "ui/base/animation/animation_delegate.h" #include "views/controls/button/button.h" #include "views/window/non_client_view.h" -namespace ui { -class SlideAnimation; -} - namespace aura_shell { namespace internal { +class FrameComponent; class SizingBorder; +class WindowCaption; // A NonClientFrameView implementation for generic top-level windows in Aura. // TODO(beng): Find a way to automatically this for all top-level windows in // Aura. Right now windows have to override CreateNonClientFrameView // on WidgetDelegate to specify this. -class AURA_SHELL_EXPORT ToplevelFrameView : public views::NonClientFrameView, - public views::ButtonListener { +class AURA_SHELL_EXPORT ToplevelFrameView : public views::NonClientFrameView { public: ToplevelFrameView(); virtual ~ToplevelFrameView(); @@ -42,7 +38,7 @@ class AURA_SHELL_EXPORT ToplevelFrameView : public views::NonClientFrameView, // Shows the specified |sizing_border|, hiding all others. // If |sizing_border| is NULL, all other sizing borders are hidden. - void ShowSizingBorder(SizingBorder* sizing_border); + void ShowFrameComponent(FrameComponent* sizing_border); // Returns true if the specified point (in FrameView coordinates) hit-tests // against the specified child. @@ -66,23 +62,16 @@ class AURA_SHELL_EXPORT ToplevelFrameView : public views::NonClientFrameView, // Overridden from views::View: virtual void Layout() OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; virtual void OnMouseMoved(const views::MouseEvent& event) OVERRIDE; virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; virtual views::View* GetEventHandlerForPoint( const gfx::Point& point) OVERRIDE; - // Overridden from views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const views::Event& event) OVERRIDE; - gfx::Rect client_view_bounds_; - views::Button* close_button_; - views::Button* zoom_button_; - int current_hittest_code_; + WindowCaption* caption_; SizingBorder* left_edge_; SizingBorder* right_edge_; SizingBorder* bottom_edge_; |