diff options
author | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 16:52:04 +0000 |
---|---|---|
committer | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 16:52:04 +0000 |
commit | f5a51b22795117b60b3d4045eed9039a511d697a (patch) | |
tree | 739a4bdaf9e223fecf61ac407b2cb491098f2dd5 | |
parent | 44ce0b1adb867c77d02c45c2eb2a6c7ee3471167 (diff) | |
download | chromium_src-f5a51b22795117b60b3d4045eed9039a511d697a.zip chromium_src-f5a51b22795117b60b3d4045eed9039a511d697a.tar.gz chromium_src-f5a51b22795117b60b3d4045eed9039a511d697a.tar.bz2 |
Implementation of a progress bar control.
BUG=37960
TEST=Unit tests provided, run chrome_tests.
Checking in patch from Denis Romanov, reviewed as:
http://codereview.chromium.org/889001/show
Review URL: http://codereview.chromium.org/842007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41436 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | views/controls/progress_bar.cc | 212 | ||||
-rw-r--r-- | views/controls/progress_bar.h | 82 | ||||
-rw-r--r-- | views/controls/progress_bar_unittest.cc | 52 | ||||
-rw-r--r-- | views/views.gyp | 2 |
5 files changed, 349 insertions, 0 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index ef4d494..4118beb 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -23,6 +23,7 @@ '../views/view_unittest.cc', '../views/focus/focus_manager_unittest.cc', '../views/controls/label_unittest.cc', + '../views/controls/progress_bar_unittest.cc', '../views/controls/table/table_view_unittest.cc', '../views/grid_layout_unittest.cc', ], diff --git a/views/controls/progress_bar.cc b/views/controls/progress_bar.cc new file mode 100644 index 0000000..96ceb44 --- /dev/null +++ b/views/controls/progress_bar.cc @@ -0,0 +1,212 @@ +// Copyright (c) 2010 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/controls/progress_bar.h" + +#include "app/gfx/canvas.h" +#include "app/gfx/color_utils.h" +#include "app/gfx/font.h" +#include "app/gfx/insets.h" +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "third_party/skia/include/effects/SkGradientShader.h" +#include "third_party/skia/include/effects/SkBlurMaskFilter.h" +#include "views/background.h" +#include "views/border.h" +#include "views/painter.h" + +namespace { + +// Corner radius for the progress bar's border. +const int kCornerRadius = 3; + +// Progress bar's border width +const int kBorderWidth = 1; + +static void AddRoundRectPath(int x, int y, + int w, int h, + int corner_radius, + SkPath* path) { + DCHECK(path); + if (path == NULL) + return; + SkScalar half = SkIntToScalar(1) / 2; + SkRect rect; + rect.set( + SkIntToScalar(x) + half, SkIntToScalar(y) + half, + SkIntToScalar(x + w) - half, SkIntToScalar(y + h) - half); + path->addRoundRect( + rect, + SkIntToScalar(corner_radius - half), + SkIntToScalar(corner_radius - half)); +} + +static void FillRoundRect(gfx::Canvas* canvas, + int x, int y, + int w, int h, + int corner_radius, + SkColor gradient_start_color, + SkColor gradient_end_color, + bool gradient_horizontal) { + SkPath path; + AddRoundRectPath(x, y, w, h, corner_radius, &path); + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setFlags(SkPaint::kAntiAlias_Flag); + if (gradient_start_color != gradient_end_color) { + SkPoint p[2]; + p[0].set(SkIntToScalar(x), SkIntToScalar(y)); + if (gradient_horizontal) { + p[1].set(SkIntToScalar(x + w), SkIntToScalar(y)); + } else { + p[1].set(SkIntToScalar(x), SkIntToScalar(y + h)); + } + SkColor colors[2] = { gradient_start_color, gradient_end_color }; + SkShader* s = SkGradientShader::CreateLinear( + p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL); + paint.setShader(s); + // Need to unref shader, otherwise never deleted. + s->unref(); + } else { + paint.setColor(gradient_start_color); + } + canvas->drawPath(path, paint); +} + +static void StrokeRoundRect(gfx::Canvas* canvas, + int x, int y, + int w, int h, + int corner_radius, + SkColor stroke_color, + int stroke_width) { + SkPath path; + AddRoundRectPath(x, y, w, h, corner_radius, &path); + SkPaint paint; + paint.setShader(NULL); + paint.setColor(stroke_color); + paint.setStyle(SkPaint::kStroke_Style); + paint.setFlags(SkPaint::kAntiAlias_Flag); + paint.setStrokeWidth(SkIntToScalar(stroke_width)); + canvas->drawPath(path, paint); +} + +} // anonymous namespace + +namespace views { + +// static +const char ProgressBar::kViewClassName[] = "views/ProgressBar"; + +ProgressBar::ProgressBar() { + Init(0); +} + +ProgressBar::ProgressBar(double progress) { + Init(progress); +} + +ProgressBar::~ProgressBar() { +} + +gfx::Size ProgressBar::GetPreferredSize() { + return gfx::Size(100, 16); +} + +void ProgressBar::Paint(gfx::Canvas* canvas) { + SkColor bar_color_start = SkColorSetRGB(81, 138, 223); + SkColor bar_color_end = SkColorSetRGB(51, 103, 205); + SkColor background_color_start = SkColorSetRGB(212, 212, 212); + SkColor background_color_end = SkColorSetRGB(252, 252, 252); + SkColor border_color = SkColorSetRGB(144, 144, 144); + + FillRoundRect(canvas, + 0, 0, width(), height(), + kCornerRadius, + background_color_start, + background_color_end, + false); + if (progress_ * width() > 1) { + FillRoundRect(canvas, + 0, 0, + int(progress_ * width()), height(), + kCornerRadius, + bar_color_start, + bar_color_end, + false); + } + StrokeRoundRect(canvas, + 0, 0, + width(), height(), + kCornerRadius, + border_color, + kBorderWidth); +} + +std::string ProgressBar::GetClassName() const { + return kViewClassName; +} + +void ProgressBar::SetProgress(double progress) { + progress_ = progress; + if (progress_ < 0) + progress_ = 0; + else if (progress_ > 1) + progress_ = 1; + SchedulePaint(); +} + +double ProgressBar::GetProgress() const { + return progress_; +} + +void ProgressBar::SetTooltipText(const std::wstring& tooltip_text) { + tooltip_text_ = tooltip_text; +} + +bool ProgressBar::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { + DCHECK(tooltip); + if (tooltip == NULL) + return false; + tooltip->assign(tooltip_text_); + return !tooltip_text_.empty(); +} + +void ProgressBar::SetEnabled(bool enabled) { + if (enabled == enabled_) + return; + View::SetEnabled(enabled); + // TODO(denisromanov): Need to switch progress bar color here? +} + +bool ProgressBar::GetAccessibleRole(AccessibilityTypes::Role* role) { + DCHECK(role); + if (role == NULL) + return false; + *role = AccessibilityTypes::ROLE_TEXT; + return true; +} + +bool ProgressBar::GetAccessibleName(std::wstring* name) { + DCHECK(name); + if (name == NULL) + return false; + // TODO(denisromanov): Return valid text here. + return false; +} + +bool ProgressBar::GetAccessibleState(AccessibilityTypes::State* state) { + DCHECK(state); + if (state == NULL) + return false; + *state = AccessibilityTypes::STATE_READONLY; + return true; +} + +void ProgressBar::Init(double progress) { + progress_ = progress; +} + +} // namespace views diff --git a/views/controls/progress_bar.h b/views/controls/progress_bar.h new file mode 100644 index 0000000..e5587d5 --- /dev/null +++ b/views/controls/progress_bar.h @@ -0,0 +1,82 @@ +// Copyright (c) 2010 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 VIEWS_CONTROLS_PROGRESS_BAR_H_ +#define VIEWS_CONTROLS_PROGRESS_BAR_H_ + +#include "views/view.h" + +namespace gfx { +class Canvas; +class Point; +class Size; +} + +namespace views { + +///////////////////////////////////////////////////////////////////////////// +// +// ProgressBar class +// +// A progress bar is a control that indicates progress visually. +// +///////////////////////////////////////////////////////////////////////////// + +class ProgressBar : public View { + public: + // Creates a new progress bar with progress zero. + ProgressBar(); + + // Creates a new progress bar with specified progress. + explicit ProgressBar(double progress); + + virtual ~ProgressBar(); + + // Overridden to return preferred size of the progress bar. + virtual gfx::Size GetPreferredSize(); + + // Returns views/ProgressBar. + virtual std::string GetClassName() const; + + // Overridden to paint + virtual void Paint(gfx::Canvas* canvas); + + // Set and get the progress bar progress in range [0, 1]. + virtual void SetProgress(double progress); + virtual double GetProgress() const; + + // Sets the tooltip text. Default behavior for a progress bar is to show + // no tooltip on mouse hover. Calling this lets you set a custom tooltip. + // To revert to default behavior, call this with an empty string. + virtual void SetTooltipText(const std::wstring& tooltip_text); + + // Gets the tooltip text if has been specified with SetTooltipText(). + virtual bool GetTooltipText(const gfx::Point& p, std::wstring* tooltip); + + // Sets the enabled state. + virtual void SetEnabled(bool enabled); + + // Accessibility accessors, overridden from View. + virtual bool GetAccessibleRole(AccessibilityTypes::Role* role); + virtual bool GetAccessibleName(std::wstring* name); + virtual bool GetAccessibleState(AccessibilityTypes::State* state); + + private: + void Init(double progress); + + // Progress in range [0, 1]. + double progress_; + + // Tooltip text. + std::wstring tooltip_text_; + + // The view class name. + static const char kViewClassName[]; + + DISALLOW_COPY_AND_ASSIGN(ProgressBar); +}; + +} // namespace views + +#endif // VIEWS_CONTROLS_PROGRESS_BAR_H_ diff --git a/views/controls/progress_bar_unittest.cc b/views/controls/progress_bar_unittest.cc new file mode 100644 index 0000000..1f653b7 --- /dev/null +++ b/views/controls/progress_bar_unittest.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2010 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 "app/l10n_util.h" +#include "base/string_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "views/controls/progress_bar.h" + +namespace views { + +TEST(ProgressBarTest, ProgressProperty) { + ProgressBar bar; + double progress = 0; + bar.SetProgress(-1); + progress = bar.GetProgress(); + EXPECT_EQ(0, progress); + bar.SetProgress(3); + progress = bar.GetProgress(); + EXPECT_EQ(1, progress); + bar.SetProgress(0.618); + progress = bar.GetProgress(); + EXPECT_EQ(0.618, progress); +} + +TEST(ProgressBarTest, TooltipTextProperty) { + ProgressBar bar; + std::wstring tooltip = L"Some text"; + EXPECT_FALSE(bar.GetTooltipText(gfx::Point(), &tooltip)); + EXPECT_EQ(L"", tooltip); + std::wstring tooltip_text = L"My progress"; + bar.SetTooltipText(tooltip_text); + EXPECT_TRUE(bar.GetTooltipText(gfx::Point(), &tooltip)); + EXPECT_EQ(tooltip_text, tooltip); +} + +TEST(ProgressBarTest, Accessibility) { + ProgressBar bar; + bar.SetProgress(0.618); + + AccessibilityTypes::Role role; + EXPECT_TRUE(bar.GetAccessibleRole(&role)); + EXPECT_EQ(AccessibilityTypes::ROLE_TEXT, role); + + // TODO(denisromanov): Test accessibility text here when it's implemented. + + AccessibilityTypes::State state; + EXPECT_TRUE(bar.GetAccessibleState(&state)); + EXPECT_EQ(AccessibilityTypes::STATE_READONLY, state); +} + +} // namespace views diff --git a/views/views.gyp b/views/views.gyp index 91b6b60..5981083 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -153,6 +153,8 @@ 'controls/native/native_view_host_win.cc', 'controls/native/native_view_host_win.h', 'controls/native/native_view_host_wrapper.h', + 'controls/progress_bar.h', + 'controls/progress_bar.cc', 'controls/resize_gripper.cc', 'controls/resize_gripper.h', 'controls/scroll_view.cc', |