diff options
author | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-08 17:26:45 +0000 |
---|---|---|
committer | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-08 17:26:45 +0000 |
commit | 3002f55e44a6d87e8d2e32c9ac34bb09ba514580 (patch) | |
tree | 5de5091ba7befe59e52aebf4e30696eeb7f158d3 /views | |
parent | c97d3965f903c15cb16724f82698ca11d998b410 (diff) | |
download | chromium_src-3002f55e44a6d87e8d2e32c9ac34bb09ba514580.zip chromium_src-3002f55e44a6d87e8d2e32c9ac34bb09ba514580.tar.gz chromium_src-3002f55e44a6d87e8d2e32c9ac34bb09ba514580.tar.bz2 |
Adding a native theme painter, to allow Views to use NativeTheme to draw
their background. Added example code to show it in use. I still have not
hooked this into any existing View-based controls.
This CL depends on changes currently being made to native theme, see
http://codereview.chromium.org/6728029/ for details.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/6771056
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80952 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/examples/examples_main.cc | 5 | ||||
-rw-r--r-- | views/examples/native_theme_button_example.cc | 268 | ||||
-rw-r--r-- | views/examples/native_theme_button_example.h | 91 | ||||
-rw-r--r-- | views/native_theme_painter.cc | 54 | ||||
-rw-r--r-- | views/native_theme_painter.h | 79 | ||||
-rw-r--r-- | views/views.gyp | 4 |
6 files changed, 501 insertions, 0 deletions
diff --git a/views/examples/examples_main.cc b/views/examples/examples_main.cc index 0ab98f6..1326672 100644 --- a/views/examples/examples_main.cc +++ b/views/examples/examples_main.cc @@ -18,6 +18,7 @@ #include "views/examples/combobox_example.h" #include "views/examples/menu_example.h" #include "views/examples/message_box_example.h" +#include "views/examples/native_theme_button_example.h" #include "views/examples/radio_button_example.h" #include "views/examples/scroll_view_example.h" #include "views/examples/single_split_view_example.h" @@ -101,6 +102,10 @@ void ExamplesMain::Run() { views::Window* window = views::Window::CreateChromeWindow(NULL, gfx::Rect(0, 0, 850, 300), this); + examples::NativeThemeButtonExample native_theme_button_example(this); + tabbed_pane->AddTab(native_theme_button_example.GetExampleTitle(), + native_theme_button_example.GetExampleView()); + examples::TextfieldExample textfield_example(this); tabbed_pane->AddTab(textfield_example.GetExampleTitle(), textfield_example.GetExampleView()); diff --git a/views/examples/native_theme_button_example.cc b/views/examples/native_theme_button_example.cc new file mode 100644 index 0000000..b6bee09 --- /dev/null +++ b/views/examples/native_theme_button_example.cc @@ -0,0 +1,268 @@ +// 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 "views/examples/native_theme_button_example.h" + +#include "base/logging.h" +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "ui/base/animation/throb_animation.h" +#include "ui/base/models/combobox_model.h" +#include "ui/gfx/canvas.h" +#include "views/controls/label.h" +#include "views/native_theme_painter.h" +#include "views/layout/grid_layout.h" + +namespace { + +class ExampleComboboxModel : public ui::ComboboxModel { + public: + ExampleComboboxModel(const wchar_t** strings, int count) + : strings_(strings), count_(count) { + } + + void set_data(const wchar_t** strings, int count) { + strings_ = strings; + count_ = count; + } + + // Overridden from ui::ComboboxModel: + virtual int GetItemCount() OVERRIDE { + return count_; + } + virtual string16 GetItemAt(int index) OVERRIDE { + return WideToUTF16Hack(strings_[index]); + } + + private: + const wchar_t** strings_; + int count_; + + DISALLOW_COPY_AND_ASSIGN(ExampleComboboxModel); +}; + +const wchar_t* kParts[] = { + L"PushButton", + L"RadioButton", + L"Checkbox", +}; + +const wchar_t* kStates[] = { + L"Disabled", + L"Normal", + L"Hot", + L"Pressed", + L"<Dynamic>", +}; + +} // anonymous namespace + +namespace examples { + +ExampleNativeThemeButton::ExampleNativeThemeButton( + views::ButtonListener* listener, + views::Combobox* cb_part, + views::Combobox* cb_state) + : CustomButton(listener), + cb_part_(cb_part), + cb_state_(cb_state), + count_(0), + is_checked_(false), + is_indeterminate_(false) { + cb_part_->set_listener(this); + cb_state_->set_listener(this); + + painter_.reset(new views::NativeThemePainter(this)); + set_background(views::Background::CreateBackgroundPainter( + false, painter_.get())); +} + +std::wstring ExampleNativeThemeButton::MessWithState() { + const wchar_t* message; + switch(GetThemePart()) { + case gfx::NativeTheme::kPushButton: + message = L"Pressed! count:%d"; + break; + case gfx::NativeTheme::kRadio: + is_checked_ = !is_checked_; + message = is_checked_ ? L"Checked! count:%d" : L"Unchecked! count:%d"; + break; + case gfx::NativeTheme::kCheckbox: + if (is_indeterminate_) { + is_checked_ = false; + is_indeterminate_ = false; + } else if (!is_checked_) { + is_checked_ = true; + } else { + is_checked_ = false; + is_indeterminate_ = true; + } + + message = is_checked_ ? L"Checked! count:%d" : + is_indeterminate_ ? L"Indeterminate! count:%d" : L"Unchecked! count:%d"; + break; + default: + DCHECK(false); + } + + return base::StringPrintf(message, ++count_); +} + +void ExampleNativeThemeButton::ItemChanged(views::Combobox* combo_box, + int prev_index, + int new_index) { + SchedulePaint(); +} + +gfx::NativeTheme::Part ExampleNativeThemeButton::GetThemePart() const { + int selected = cb_part_->selected_item(); + switch(selected) { + case 0: + return gfx::NativeTheme::kPushButton; + case 1: + return gfx::NativeTheme::kRadio; + case 2: + return gfx::NativeTheme::kCheckbox; + default: + DCHECK(false); + } + return gfx::NativeTheme::kPushButton; +} + +gfx::NativeTheme::State ExampleNativeThemeButton::GetThemeState( + gfx::NativeTheme::ExtraParams* params) const { + GetExtraParams(params); + + int selected = cb_state_->selected_item(); + if (selected > 3) { + switch(state()) { + case BS_DISABLED: + return gfx::NativeTheme::kDisabled; + case BS_NORMAL: + return gfx::NativeTheme::kNormal; + case BS_HOT: + return gfx::NativeTheme::kHovered; + case BS_PUSHED: + return gfx::NativeTheme::kPressed; + default: + DCHECK(false); + } + } + + switch(selected) { + case 0: + return gfx::NativeTheme::kDisabled; + case 1: + return gfx::NativeTheme::kNormal; + case 2: + return gfx::NativeTheme::kHovered; + case 3: + return gfx::NativeTheme::kPressed; + default: + DCHECK(false); + } + return gfx::NativeTheme::kNormal; +} + +void ExampleNativeThemeButton::GetExtraParams( + gfx::NativeTheme::ExtraParams* params) const { + + params->button.checked = is_checked_; + params->button.indeterminate = is_indeterminate_; + params->button.is_default = false; + params->button.has_border = false; + params->button.classic_state = 0; + params->button.background_color = SkColorSetARGB(0, 0, 0, 0); +} + +ui::Animation* ExampleNativeThemeButton::GetThemeAnimation() const { + int selected = cb_state_->selected_item(); + return selected <= 3 ? NULL : hover_animation_.get(); +} + +gfx::NativeTheme::State ExampleNativeThemeButton::GetBackgroundThemeState( + gfx::NativeTheme::ExtraParams* params) const { + GetExtraParams(params); + return gfx::NativeTheme::kNormal; +} + +gfx::NativeTheme::State ExampleNativeThemeButton::GetForegroundThemeState( + gfx::NativeTheme::ExtraParams* params) const { + GetExtraParams(params); + return gfx::NativeTheme::kHovered; +} + +gfx::Size ExampleNativeThemeButton::GetPreferredSize() { + return painter_.get() == NULL ? gfx::Size() : painter_->GetPreferredSize(); +} + +void ExampleNativeThemeButton::OnPaintBackground(gfx::Canvas* canvas) { + // Fill the background with a known colour so that we know where the bounds + // of the View are. + canvas->FillRectInt(SkColorSetRGB(255, 128, 128), 0, 0, width(), height()); + CustomButton::OnPaintBackground(canvas); +} + +//////////////////////////////////////////////////////////////////////////////// + +NativeThemeButtonExample::NativeThemeButtonExample(ExamplesMain* main) + : ExampleBase(main) { +} + +NativeThemeButtonExample::~NativeThemeButtonExample() { +} + +std::wstring NativeThemeButtonExample::GetExampleTitle() { + return L"Native Theme Button"; +} + +void NativeThemeButtonExample::CreateExampleView(views::View* container) { + views::GridLayout* layout = new views::GridLayout(container); + container->SetLayoutManager(layout); + + layout->AddPaddingRow(0, 8); + + views::ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddPaddingColumn(0, 8); + column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, + 0.1f, views::GridLayout::USE_PREF, 0, 0); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, + 0.9f, views::GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, 8); + + layout->StartRow(0, 0); + layout->AddView(new views::Label(L"Part:")); + views::Combobox* cb_part = new views::Combobox( + new ExampleComboboxModel(kParts, arraysize(kParts))); + cb_part->SetSelectedItem(0); + layout->AddView(cb_part); + + layout->StartRow(0, 0); + layout->AddView(new views::Label(L"State:")); + views::Combobox* cb_state = new views::Combobox( + new ExampleComboboxModel(kStates, arraysize(kStates))); + cb_state->SetSelectedItem(0); + layout->AddView(cb_state); + + layout->AddPaddingRow(0, 32); + + button_ = new ExampleNativeThemeButton(this, cb_part, cb_state); + + column_set = layout->AddColumnSet(1); + column_set->AddPaddingColumn(0, 16); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, + 1, views::GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, 16); + layout->StartRow(1, 1); + layout->AddView(button_); + + layout->AddPaddingRow(0, 8); +} + +void NativeThemeButtonExample::ButtonPressed(views::Button* sender, + const views::Event& event) { + PrintStatus(button_->MessWithState().c_str()); +} + +} // namespace examples diff --git a/views/examples/native_theme_button_example.h b/views/examples/native_theme_button_example.h new file mode 100644 index 0000000..702eab8 --- /dev/null +++ b/views/examples/native_theme_button_example.h @@ -0,0 +1,91 @@ +// 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. + +#ifndef VIEWS_EXAMPLES_NATIVE_THEME_BUTTON_EXAMPLE_H_ +#define VIEWS_EXAMPLES_NATIVE_THEME_BUTTON_EXAMPLE_H_ +#pragma once + +#include "base/basictypes.h" +#include "ui/gfx/native_theme.h" +#include "views/controls/button/custom_button.h" +#include "views/controls/combobox/combobox.h" +#include "views/examples/example_base.h" +#include "views/native_theme_painter.h" + +namespace views { +class Combobox; +class NativeThemePainter; +} + +namespace examples { + +// A subclass of button to test native theme rendering. +class ExampleNativeThemeButton : public views::CustomButton, + public views::NativeThemePainter::Delegate, + public views::Combobox::Listener { + public: + ExampleNativeThemeButton(views::ButtonListener* listener, + views::Combobox* cb_part, + views::Combobox* cb_state); + + std::wstring MessWithState(); + + private: + // Overridden from View: + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; + + // Overridden from views::Combobox::Listener: + virtual void ItemChanged(views::Combobox* combo_box, + int prev_index, + int new_index) OVERRIDE; + + // Overridden from views::NativeThemePainter::Delegate: + virtual gfx::NativeTheme::Part GetThemePart() const OVERRIDE; + virtual gfx::NativeTheme::State GetThemeState( + gfx::NativeTheme::ExtraParams* params) const OVERRIDE; + virtual ui::Animation* GetThemeAnimation() const OVERRIDE; + virtual gfx::NativeTheme::State GetBackgroundThemeState( + gfx::NativeTheme::ExtraParams* params) const OVERRIDE; + virtual gfx::NativeTheme::State GetForegroundThemeState( + gfx::NativeTheme::ExtraParams* params) const OVERRIDE; + + void GetExtraParams(gfx::NativeTheme::ExtraParams* params) const; + + scoped_ptr<views::NativeThemePainter> painter_; + views::Combobox* cb_part_; + views::Combobox* cb_state_; + int count_; + bool is_checked_; + bool is_indeterminate_; + + DISALLOW_COPY_AND_ASSIGN(ExampleNativeThemeButton); +}; + +// NativeThemeButtonExample shows how a View can use the NativeThemePainter +// to paints its background and get a native look. +class NativeThemeButtonExample : public ExampleBase, + public views::ButtonListener { + public: + explicit NativeThemeButtonExample(ExamplesMain* main); + virtual ~NativeThemeButtonExample(); + + // Overridden from ExampleBase: + virtual std::wstring GetExampleTitle() OVERRIDE; + virtual void CreateExampleView(views::View* container) OVERRIDE; + + private: + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) OVERRIDE; + + // The only control in this test. + ExampleNativeThemeButton* button_; + + DISALLOW_COPY_AND_ASSIGN(NativeThemeButtonExample); +}; + +} // namespace examples + +#endif // VIEWS_EXAMPLES_NATIVE_THEME_BUTTON_EXAMPLE_H_ diff --git a/views/native_theme_painter.cc b/views/native_theme_painter.cc new file mode 100644 index 0000000..1d4ab21 --- /dev/null +++ b/views/native_theme_painter.cc @@ -0,0 +1,54 @@ +// 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 "views/native_theme_painter.h" + +#include "base/logging.h" +#include "ui/base/animation/animation.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/canvas_skia.h" +#include "ui/gfx/rect.h" + +namespace views { + +NativeThemePainter::NativeThemePainter(Delegate* delegate) + : delegate_(delegate) { + DCHECK(delegate_); +} + +gfx::Size NativeThemePainter::GetPreferredSize() { + const gfx::NativeTheme* theme = gfx::NativeTheme::instance(); + return theme->GetPartSize(delegate_->GetThemePart()); +} + +void NativeThemePainter::Paint(int w, int h, gfx::Canvas* canvas) { + const gfx::NativeTheme* native_theme = gfx::NativeTheme::instance(); + gfx::NativeTheme::Part part = delegate_->GetThemePart(); + gfx::CanvasSkia* skia_canvas = canvas->AsCanvasSkia(); + gfx::Rect rect(0, 0, w, h); + + if (delegate_->GetThemeAnimation() != NULL && + delegate_->GetThemeAnimation()->is_animating()) { + + // Paint background state. + gfx::NativeTheme::ExtraParams prev_extra; + gfx::NativeTheme::State prev_state = + delegate_->GetBackgroundThemeState(&prev_extra); + native_theme->Paint(skia_canvas, part, prev_state, rect, prev_extra); + + // Composite foreground state above it. + gfx::NativeTheme::ExtraParams extra; + gfx::NativeTheme::State state = delegate_->GetForegroundThemeState(&extra); + int alpha = delegate_->GetThemeAnimation()->CurrentValueBetween(0, 255); + skia_canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); + native_theme->Paint(skia_canvas, part, state, rect, extra); + skia_canvas->Restore(); + } else { + gfx::NativeTheme::ExtraParams extra; + gfx::NativeTheme::State state = delegate_->GetThemeState(&extra); + native_theme->Paint(skia_canvas, part, state, rect, extra); + } +} + +} // namespace views diff --git a/views/native_theme_painter.h b/views/native_theme_painter.h new file mode 100644 index 0000000..75b8866 --- /dev/null +++ b/views/native_theme_painter.h @@ -0,0 +1,79 @@ +// 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. + +#ifndef VIEWS_NATIVE_THEME_PAINTER_H_ +#define VIEWS_NATIVE_THEME_PAINTER_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "ui/gfx/native_theme.h" +#include "views/painter.h" + +namespace gfx { +class Canvas; +class Size; +} + +namespace ui { +class Animation; +} + +namespace views { + +// A Painter that uses NativeTheme to implement painting and sizing. A +// theme delegate must be given at construction time so that the appropriate +// painting and sizing can be done. +class NativeThemePainter : public Painter { + public: + // A delagate that supports animating transtions between different native + // theme states. If animation is onging, the native theme painter will + // composite the foreground state over the backgroud state using an alpha + // between 0 and 255 based on the current value of the animation. + class Delegate { + public: + virtual ~Delegate() {} + + // Get the part that this native theme painter should draw. + virtual gfx::NativeTheme::Part GetThemePart() const = 0; + + // Get the state of the part, along with any extra data needed for painting. + virtual gfx::NativeTheme::State GetThemeState( + gfx::NativeTheme::ExtraParams* params) const = 0; + + // If the native theme painter is animated, return the Animation object + // that is controlling it. If no animation is ongoing, NULL may be + // returned. + virtual ui::Animation* GetThemeAnimation() const = 0; + + // If animation is onging, this returns the background native theme state. + virtual gfx::NativeTheme::State GetBackgroundThemeState( + gfx::NativeTheme::ExtraParams* params) const = 0; + + // If animation is onging, this returns the foreground native theme state. + // This state will be composited over the background using an alpha value + // based on the current value of the animation. + virtual gfx::NativeTheme::State GetForegroundThemeState( + gfx::NativeTheme::ExtraParams* params) const = 0; + }; + + explicit NativeThemePainter(Delegate* delegate); + + virtual ~NativeThemePainter() {} + + // Returns the preferred size of the native part being painted. + gfx::Size GetPreferredSize(); + + private: + // The delegate the controls the appearance of this painter. + Delegate* delegate_; + + // Overridden from Painter: + virtual void Paint(int w, int h, gfx::Canvas* canvas) OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(NativeThemePainter); +}; + +} // namespace views + +#endif // VIEWS_NATIVE_THEME_PAINTER_H_
\ No newline at end of file diff --git a/views/views.gyp b/views/views.gyp index c7fac12..deca1c4 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -311,6 +311,8 @@ 'metrics_win.cc', 'mouse_watcher.cc', 'mouse_watcher.h', + 'native_theme_painter.cc', + 'native_theme_painter.h', 'painter.cc', 'painter.h', 'repeat_controller.cc', @@ -587,6 +589,8 @@ 'examples/message_box_example.h', 'examples/menu_example.cc', 'examples/menu_example.h', + 'examples/native_theme_button_example.cc', + 'examples/native_theme_button_example.h', 'examples/radio_button_example.cc', 'examples/radio_button_example.h', 'examples/scroll_view_example.cc', |