Index: ui/aura_shell/toplevel_frame_view.cc |
=================================================================== |
--- ui/aura_shell/toplevel_frame_view.cc (revision 0) |
+++ ui/aura_shell/toplevel_frame_view.cc (revision 0) |
@@ -0,0 +1,382 @@ |
+// 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 "ui/aura_shell/toplevel_frame_view.h" |
+ |
+#include "grit/ui_resources.h" |
+#include "ui/base/animation/throb_animation.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/gfx/canvas.h" |
+#include "views/controls/button/custom_button.h" |
+#include "views/widget/widget.h" |
+#include "views/widget/widget_delegate.h" |
+ |
+#if !defined(OS_WIN) |
+#include "views/window/hit_test.h" |
+#endif |
+ |
+namespace aura_shell { |
+namespace internal { |
+ |
+namespace { |
+// The thickness of the left, right and bottom edges of the frame. |
+const int kFrameBorderThickness = 8; |
+const int kFrameOpacity = 50; |
+// The color used to fill the frame. |
+const SkColor kFrameColor = SkColorSetARGB(kFrameOpacity, 0, 0, 0); |
+const int kFrameBorderHiddenOpacity = 0; |
+const int kFrameBorderVisibleOpacity = kFrameOpacity; |
+// How long the hover animation takes if uninterrupted. |
+const int kHoverFadeDurationMs = 250; |
+} // namespace |
+ |
+class WindowControlButton : public views::CustomButton { |
sky
2011/09/22 18:06:19
Add a description.
|
+ public: |
+ WindowControlButton(views::ButtonListener* listener, |
+ SkColor color, |
+ SkBitmap icon) |
sky
2011/09/22 18:06:19
const SkBitmap&
|
+ : views::CustomButton(listener), |
+ color_(color), |
+ icon_(icon) { |
+ } |
+ virtual ~WindowControlButton() {} |
+ |
+ // Overridden from views::View: |
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
+ canvas->FillRectInt(GetBackgroundColor(), 0, 0, width(), height()); |
+ canvas->DrawBitmapInt(icon_, 0, 0); |
+ } |
+ virtual gfx::Size GetPreferredSize() OVERRIDE { |
+ gfx::Size size(icon_.width(), icon_.height()); |
+ size.Enlarge(3, 2); |
+ return size; |
+ } |
+ |
+ private: |
+ SkColor GetBackgroundColor() { |
+ return SkColorSetARGB(hover_animation_->CurrentValueBetween(0, 150), |
+ SkColorGetR(color_), |
+ SkColorGetG(color_), |
+ SkColorGetB(color_)); |
+ } |
+ |
+ SkColor color_; |
+ SkBitmap icon_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WindowControlButton); |
+}; |
+ |
+class SizingBorder : 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_); |
+ } |
+ |
+ void Show() { |
+ animation_->Show(); |
+ } |
+ |
+ void Hide() { |
+ animation_->Hide(); |
+ } |
+ |
+ bool IsShowing() const { |
+ return animation_->IsShowing(); |
+ } |
+ |
+ bool IsHiding() const { |
+ return animation_->IsClosing(); |
+ } |
+ |
+ private: |
+ // Overridden from views::View: |
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
+ // Fill with current opacity value. |
+ int opacity = animation_->CurrentValueBetween(kFrameBorderHiddenOpacity, |
+ kFrameBorderVisibleOpacity); |
+ canvas->FillRectInt(SkColorSetARGB(opacity, |
+ SkColorGetR(kFrameColor), |
+ SkColorGetG(kFrameColor), |
+ SkColorGetB(kFrameColor)), |
+ 0, 0, width(), height()); |
+ } |
+ |
+ // 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); |
+ SchedulePaint(); |
+ } |
+ |
+ // 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); |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ToplevelFrameView, public: |
+ |
+ToplevelFrameView::ToplevelFrameView() |
+ : current_hittest_code_(HTNOWHERE), |
+ 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(left_edge_); |
+ AddChildView(right_edge_); |
+ AddChildView(bottom_edge_); |
+} |
+ |
+ToplevelFrameView::~ToplevelFrameView() { |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ToplevelFrameView, private: |
+ |
+int ToplevelFrameView::NonClientBorderThickness() const { |
+ return kFrameBorderThickness; |
+} |
+ |
+int ToplevelFrameView::NonClientTopBorderHeight() const { |
+ return close_button_->GetPreferredSize().height(); |
+} |
+ |
+int ToplevelFrameView::NonClientHitTestImpl(const gfx::Point& point) { |
+ // Sanity check. |
+ if (!GetLocalBounds().Contains(point)) |
+ return HTNOWHERE; |
+ |
+ // The client view gets first crack at claiming the point. |
+ int frame_component = GetWidget()->client_view()->NonClientHitTest(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; |
+ |
+ // Finally other portions of the frame/sizing border. |
+ frame_component = |
+ GetHTComponentForFrame(point, |
+ NonClientBorderThickness(), |
+ NonClientBorderThickness(), |
+ NonClientBorderThickness(), |
+ NonClientBorderThickness(), |
+ GetWidget()->widget_delegate()->CanResize()); |
+ |
+ // Coerce HTCAPTION as a fallback. |
+ 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()) |
+ left_edge_->Hide(); |
+ if (right_edge_ != sizing_border && !right_edge_->IsHiding()) |
+ right_edge_->Hide(); |
+ if (bottom_edge_ != sizing_border && !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(); |
+ int caption_height = NonClientTopBorderHeight(); |
+ switch (frame_component) { |
+ case HTLEFT: |
+ return gfx::Rect(border_size, caption_height, border_size, |
+ height() - border_size - caption_height); |
+ case HTBOTTOM: |
+ return gfx::Rect(border_size, height() - 2 * border_size, |
+ width() - 2 * border_size, border_size); |
+ case HTRIGHT: |
+ return gfx::Rect(width() - 2 * border_size, caption_height, border_size, |
+ height() - border_size - caption_height); |
+ default: |
+ break; |
+ } |
+ return gfx::Rect(); |
+} |
+ |
+gfx::Rect ToplevelFrameView::GetVisibleBoundsForSizingBorder( |
+ int frame_component) const { |
+ int border_size = NonClientBorderThickness(); |
+ int caption_height = NonClientTopBorderHeight(); |
+ switch (frame_component) { |
+ case HTLEFT: |
+ return gfx::Rect(0, caption_height, border_size, |
+ height() - border_size - caption_height); |
+ case HTBOTTOM: |
+ return gfx::Rect(border_size, height() - border_size, |
+ width() - 2 * border_size, border_size); |
+ case HTRIGHT: |
+ return gfx::Rect(width() - border_size, caption_height, border_size, |
+ height() - border_size - caption_height); |
+ default: |
+ break; |
+ } |
+ return gfx::Rect(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ToplevelFrameView, views::NonClientFrameView overrides: |
+ |
+gfx::Rect ToplevelFrameView::GetBoundsForClientView() const { |
+ return client_view_bounds_; |
+} |
+ |
+gfx::Rect ToplevelFrameView::GetWindowBoundsForClientBounds( |
+ const gfx::Rect& client_bounds) const { |
+ gfx::Rect window_bounds = client_bounds; |
+ window_bounds.Inset(-NonClientBorderThickness(), |
+ -NonClientTopBorderHeight(), |
+ -NonClientBorderThickness(), |
+ -NonClientBorderThickness()); |
+ return window_bounds; |
+} |
+ |
+int ToplevelFrameView::NonClientHitTest(const gfx::Point& point) { |
+ int old_hittest_code = current_hittest_code_; |
+ current_hittest_code_ = NonClientHitTestImpl(point); |
+ return current_hittest_code_; |
+} |
+ |
+void ToplevelFrameView::GetWindowMask(const gfx::Size& size, |
+ gfx::Path* window_mask) { |
+ // Nothing. |
+} |
+ |
+void ToplevelFrameView::EnableClose(bool enable) { |
+ close_button_->SetEnabled(enable); |
+} |
+ |
+void ToplevelFrameView::ResetWindowControls() { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void ToplevelFrameView::UpdateWindowIcon() { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ToplevelFrameView, views::View overrides: |
+ |
+void ToplevelFrameView::Layout() { |
+ client_view_bounds_ = GetLocalBounds(); |
+ client_view_bounds_.Inset(NonClientBorderThickness(), |
+ NonClientTopBorderHeight(), |
+ 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())); |
+ |
+ left_edge_->Configure(GetHiddenBoundsForSizingBorder(HTLEFT), |
+ GetVisibleBoundsForSizingBorder(HTLEFT)); |
+ right_edge_->Configure(GetHiddenBoundsForSizingBorder(HTRIGHT), |
+ GetVisibleBoundsForSizingBorder(HTRIGHT)); |
+ bottom_edge_->Configure(GetHiddenBoundsForSizingBorder(HTBOTTOM), |
+ 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_); |
+ break; |
+ case HTRIGHT: |
+ ShowSizingBorder(right_edge_); |
+ break; |
+ case HTBOTTOM: |
+ ShowSizingBorder(bottom_edge_); |
+ break; |
+ default: |
+ break; |
+ } |
+} |
+ |
+void ToplevelFrameView::OnMouseExited(const views::MouseEvent& event) { |
+ ShowSizingBorder(NULL); |
+} |
+ |
+views::View* ToplevelFrameView::GetEventHandlerForPoint( |
+ const gfx::Point& point) { |
+ if (PointIsInChildView(left_edge_, point) || |
+ PointIsInChildView(right_edge_, point) || |
+ PointIsInChildView(bottom_edge_, 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 |
Property changes on: ui\aura_shell\toplevel_frame_view.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |