summaryrefslogtreecommitdiffstats
path: root/ash/wm/workspace
diff options
context:
space:
mode:
authorpkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-22 22:11:38 +0000
committerpkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-22 22:11:38 +0000
commitb042333631e2661e1892a6b42de6e678d5a38f6e (patch)
tree5f86300c793f2bddac7ef75f6a7565f398ff1ebc /ash/wm/workspace
parent82f22bfcce21574e0d1698bd935e7d32d25a989b (diff)
downloadchromium_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')
-rw-r--r--ash/wm/workspace/frame_caption_button_container_view.cc135
-rw-r--r--ash/wm/workspace/frame_caption_button_container_view.h88
-rw-r--r--ash/wm/workspace/frame_caption_button_container_view_unittest.cc74
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