diff options
author | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 22:11:38 +0000 |
---|---|---|
committer | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 22:11:38 +0000 |
commit | b042333631e2661e1892a6b42de6e678d5a38f6e (patch) | |
tree | 5f86300c793f2bddac7ef75f6a7565f398ff1ebc /ash/wm/workspace | |
parent | 82f22bfcce21574e0d1698bd935e7d32d25a989b (diff) | |
download | chromium_src-b042333631e2661e1892a6b42de6e678d5a38f6e.zip chromium_src-b042333631e2661e1892a6b42de6e678d5a38f6e.tar.gz chromium_src-b042333631e2661e1892a6b42de6e678d5a38f6e.tar.bz2 |
Add a container view for the window controls part 1.
This CL creates a new class FrameCaptionButtonContainerView which contains the caption buttons.
This CL makes AppNonClientFrameViewAsh use this new class.
The new class will help:
- Creating different buttons based on whether the new window control style is used or not
- Will be used as a delegate for FrameMaximizeButton so that the FrameMaximizeButton can alter how the minimize and close buttons look after a drag.
- Will remove complexity from ash::FramePainter
TEST=FrameCaptionButtonContainerViewTest.*
BUG=274171
Review URL: https://chromiumcodereview.appspot.com/23280002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219126 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm/workspace')
3 files changed, 297 insertions, 0 deletions
diff --git a/ash/wm/workspace/frame_caption_button_container_view.cc b/ash/wm/workspace/frame_caption_button_container_view.cc new file mode 100644 index 0000000..7f1d020e --- /dev/null +++ b/ash/wm/workspace/frame_caption_button_container_view.cc @@ -0,0 +1,135 @@ +// Copyright 2013 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 "ash/wm/workspace/frame_caption_button_container_view.h" + +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "ash/wm/workspace/frame_maximize_button.h" +#include "grit/ash_resources.h" +#include "grit/ui_strings.h" // Accessibility names +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/widget/widget.h" +#include "ui/views/window/non_client_view.h" + +namespace ash { + +namespace { + +// The space between the buttons. +const int kButtonGap = -1; + +} // namespace + +// static +const char FrameCaptionButtonContainerView::kViewClassName[] = + "FrameCaptionButtonContainerView"; + +FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( + views::NonClientFrameView* frame_view, + views::Widget* frame) + : frame_(frame), + size_button_(new FrameMaximizeButton(this, frame_view)), + close_button_(new views::ImageButton(this)) { + // Insert the buttons left to right. + size_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); + if (ash::Shell::IsForcedMaximizeMode()) + size_button_->SetVisible(false); + AddChildView(size_button_); + + close_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); + AddChildView(close_button_); +} + +FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() { +} + +void FrameCaptionButtonContainerView::ResetWindowControls() { + size_button_->SetState(views::CustomButton::STATE_NORMAL); +} + +gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { + int width = 0; + bool first_visible = true; + for (int i = 0; i < child_count(); ++i) { + views::View* child = child_at(i); + if (!child->visible()) + continue; + + width += child_at(i)->GetPreferredSize().width(); + if (!first_visible) + width += kButtonGap; + first_visible = false; + } + gfx::Insets insets(GetInsets()); + return gfx::Size( + width + insets.width(), + close_button_->GetPreferredSize().height() + insets.height()); +} + +void FrameCaptionButtonContainerView::Layout() { + SetButtonImages(size_button_, + IDR_AURA_WINDOW_FULLSCREEN_RESTORE, + IDR_AURA_WINDOW_FULLSCREEN_RESTORE_H, + IDR_AURA_WINDOW_FULLSCREEN_RESTORE_P); + SetButtonImages(close_button_, + IDR_AURA_WINDOW_FULLSCREEN_CLOSE, + IDR_AURA_WINDOW_FULLSCREEN_CLOSE_H, + IDR_AURA_WINDOW_FULLSCREEN_CLOSE_P); + + gfx::Insets insets(GetInsets()); + int x = insets.left(); + int y_inset = insets.top(); + for (int i = 0; i < child_count(); ++i) { + views::View* child = child_at(i); + if (!child->visible()) + continue; + + gfx::Size size = child->GetPreferredSize(); + child->SetBounds(x, y_inset, size.width(), size.height()); + x += size.width() + kButtonGap; + } +} + +const char* FrameCaptionButtonContainerView::GetClassName() const { + return kViewClassName; +} + +void FrameCaptionButtonContainerView::SetButtonImages( + views::ImageButton* button, + int normal_image_id, + int hot_image_id, + int pushed_image_id) { + ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); + button->SetImage(views::CustomButton::STATE_NORMAL, + resource_bundle.GetImageSkiaNamed(normal_image_id)); + button->SetImage(views::CustomButton::STATE_HOVERED, + resource_bundle.GetImageSkiaNamed(hot_image_id)); + button->SetImage(views::CustomButton::STATE_PRESSED, + resource_bundle.GetImageSkiaNamed(pushed_image_id)); +} + +void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + ash::UserMetricsAction action = + ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE; + if (sender == size_button_) { + // The maximize button may move out from under the cursor. + ResetWindowControls(); + frame_->Restore(); + } else if (sender == close_button_) { + action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK; + frame_->Close(); + } else { + return; + } + ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(action); +} + +} // namespace ash diff --git a/ash/wm/workspace/frame_caption_button_container_view.h b/ash/wm/workspace/frame_caption_button_container_view.h new file mode 100644 index 0000000..0fe256b --- /dev/null +++ b/ash/wm/workspace/frame_caption_button_container_view.h @@ -0,0 +1,88 @@ +// Copyright 2013 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 ASH_WM_WORKSPACE_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ +#define ASH_WM_WORKSPACE_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ + +#include "ash/ash_export.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/view.h" + +namespace views { +class ImageButton; +class NonClientFrameView; +class Widget; +} + +namespace ash { + +// Container view for the frame caption buttons. It performs the appropriate +// action when a caption button is clicked. +class ASH_EXPORT FrameCaptionButtonContainerView + : public views::View, + public views::ButtonListener { + public: + static const char kViewClassName[]; + + // |frame_view| and |frame| are the NonClientFrameView and the views::Widget + // that the caption buttons act on. + // TODO(pkotwicz): Remove the |frame_view| parameter once FrameMaximizeButton + // is refactored to take in a views::Widget instead. + FrameCaptionButtonContainerView(views::NonClientFrameView* frame_view, + views::Widget* frame); + virtual ~FrameCaptionButtonContainerView(); + + // For testing. + class TestApi { + public: + explicit TestApi(FrameCaptionButtonContainerView* container_view) + : container_view_(container_view) { + } + + views::ImageButton* size_button() const { + return container_view_->size_button_; + } + + views::ImageButton* close_button() const { + return container_view_->close_button_; + } + + private: + FrameCaptionButtonContainerView* container_view_; + + DISALLOW_COPY_AND_ASSIGN(TestApi); + }; + + // Tell the window controls to reset themselves to the normal state. + void ResetWindowControls(); + + // views::View overrides: + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void Layout() OVERRIDE; + virtual const char* GetClassName() const OVERRIDE; + + private: + // Sets the images for a button based on the given ids. + void SetButtonImages(views::ImageButton* button, + int normal_image_id, + int hot_image_id, + int pushed_image_id); + + // views::ButtonListener override: + virtual void ButtonPressed(views::Button* sender, + const ui::Event& event) OVERRIDE; + + // The widget that the buttons act on. + views::Widget* frame_; + + // The buttons. + views::ImageButton* size_button_; + views::ImageButton* close_button_; + + DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerView); +}; + +} // namesapace ash + +#endif // ASH_WM_WORKSPACE_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ diff --git a/ash/wm/workspace/frame_caption_button_container_view_unittest.cc b/ash/wm/workspace/frame_caption_button_container_view_unittest.cc new file mode 100644 index 0000000..69bb97b --- /dev/null +++ b/ash/wm/workspace/frame_caption_button_container_view_unittest.cc @@ -0,0 +1,74 @@ +// Copyright 2013 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 "ash/wm/workspace/frame_caption_button_container_view.h" + +#include "ash/ash_switches.h" +#include "base/command_line.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/image_button.h" + +namespace ash { + +typedef testing::Test FrameCaptionButtonContainerViewTest; + +TEST_F(FrameCaptionButtonContainerViewTest, Sanity) { + // 1) Test the layout and the caption button visibility in the default case. + // Both the size button and the close button should be visible. + FrameCaptionButtonContainerView c1(NULL, NULL); + c1.Layout(); + FrameCaptionButtonContainerView::TestApi t1(&c1); + views::ImageButton* size_button = t1.size_button(); + views::ImageButton* close_button = t1.close_button(); + EXPECT_TRUE(size_button->visible()); + EXPECT_TRUE(close_button->visible()); + + // The size button should be left of the close button. (in non-RTL) + EXPECT_LT(size_button->x(), close_button->x()); + + // The container's bounds should be flush with the caption buttons. + EXPECT_EQ(0, size_button->x()); + EXPECT_EQ(c1.GetPreferredSize().width(), close_button->bounds().right()); + EXPECT_EQ(c1.GetPreferredSize().height(), close_button->bounds().height()); + + // 2) Test the layout and the caption button visibility when the + // "force-maximize-mode" experiment is turned on. Only the close button + // should be visible. + CommandLine::ForCurrentProcess()->AppendSwitch(switches::kForcedMaximizeMode); + + FrameCaptionButtonContainerView c2(NULL, NULL); + c2.Layout(); + FrameCaptionButtonContainerView::TestApi t2(&c2); + size_button = t2.size_button(); + close_button = t2.close_button(); + + EXPECT_FALSE(size_button->visible()); + EXPECT_TRUE(close_button->visible()); + EXPECT_EQ(c2.GetPreferredSize().width(), close_button->width()); + EXPECT_EQ(c2.GetPreferredSize().height(), close_button->height()); +} + +// Test the layout when a border is set on the container. +TEST_F(FrameCaptionButtonContainerViewTest, Border) { + const int kTopInset = 1; + const int kLeftInset = 2; + const int kBottomInset = 3; + const int kRightInset = 4; + + FrameCaptionButtonContainerView c(NULL, NULL); + c.set_border(views::Border::CreateEmptyBorder( + kTopInset, kLeftInset, kBottomInset, kRightInset)); + c.Layout(); + FrameCaptionButtonContainerView::TestApi t(&c); + + EXPECT_EQ(kLeftInset, t.size_button()->x()); + EXPECT_EQ(kTopInset, t.close_button()->y()); + EXPECT_EQ(c.GetPreferredSize().height(), + t.close_button()->bounds().bottom() + kBottomInset); + EXPECT_EQ(c.GetPreferredSize().width(), + t.close_button()->bounds().right() + kRightInset); +} + +} // namespace ash |