Chromium Code Reviews| Index: chrome/browser/ui/libgtk2ui/gtk2_border.cc |
| diff --git a/chrome/browser/ui/libgtk2ui/gtk2_border.cc b/chrome/browser/ui/libgtk2ui/gtk2_border.cc |
| index 57b6f5da5c0aa506a4d56bac684d4b3cb1d8e5d3..3fdfd48df35d3cdd4ce044fb253044c25cb2dbdc 100644 |
| --- a/chrome/browser/ui/libgtk2ui/gtk2_border.cc |
| +++ b/chrome/browser/ui/libgtk2ui/gtk2_border.cc |
| @@ -7,34 +7,42 @@ |
| #include <gtk/gtk.h> |
| #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h" |
| +#include "third_party/skia/include/effects/SkLerpXfermode.h" |
| +#include "ui/gfx/animation/animation.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/image/image_skia_source.h" |
| -#include "ui/views/controls/button/custom_button.h" |
| +#include "ui/gfx/rect.h" |
| +#include "ui/gfx/skia_util.h" |
| +#include "ui/views/controls/button/label_button.h" |
| +#include "ui/views/native_theme_delegate.h" |
| + |
| +using views::Button; |
| +using views::NativeThemeDelegate; |
| namespace libgtk2ui { |
| namespace { |
| -GtkStateType ViewsToGtkState(views::Button::ButtonState state) { |
| +GtkStateType GetGtkState(ui::NativeTheme::State state) { |
| switch (state) { |
| - case views::Button::STATE_HOVERED: |
| - return GTK_STATE_PRELIGHT; |
| - case views::Button::STATE_PRESSED: |
| - return GTK_STATE_ACTIVE; |
| - case views::Button::STATE_DISABLED: |
| - return GTK_STATE_INSENSITIVE; |
| - default: |
| - return GTK_STATE_NORMAL; |
| + case ui::NativeTheme::kDisabled: return GTK_STATE_INSENSITIVE; |
| + case ui::NativeTheme::kHovered: return GTK_STATE_PRELIGHT; |
| + case ui::NativeTheme::kNormal: return GTK_STATE_NORMAL; |
| + case ui::NativeTheme::kPressed: return GTK_STATE_ACTIVE; |
| + case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state; |
| } |
| + return GTK_STATE_NORMAL; |
| } |
| class ButtonImageSkiaSource : public gfx::ImageSkiaSource { |
| public: |
| ButtonImageSkiaSource(const Gtk2UI* gtk2_ui, |
| - GtkStateType state, |
| + const GtkStateType state, |
| + const bool focused, |
| const gfx::Size& size) |
| : gtk2_ui_(gtk2_ui), |
| state_(state), |
| + focused_(focused), |
| size_(size) { |
| } |
| @@ -45,13 +53,14 @@ class ButtonImageSkiaSource : public gfx::ImageSkiaSource { |
| int w = size_.width() * scale; |
| int h = size_.height() * scale; |
| return gfx::ImageSkiaRep( |
| - gtk2_ui_->DrawGtkButtonBorder(state_, w, h), scale); |
| + gtk2_ui_->DrawGtkButtonBorder(state_, focused_, w, h), scale); |
| } |
| private: |
| const Gtk2UI* gtk2_ui_; |
| - GtkStateType state_; |
| - gfx::Size size_; |
| + const GtkStateType state_; |
| + const bool focused_; |
| + const gfx::Size size_; |
| DISALLOW_COPY_AND_ASSIGN(ButtonImageSkiaSource); |
| }; |
| @@ -59,7 +68,7 @@ class ButtonImageSkiaSource : public gfx::ImageSkiaSource { |
| } // namespace |
| Gtk2Border::Gtk2Border(Gtk2UI* gtk2_ui, |
| - views::CustomButton* owning_button, |
| + views::LabelButton* owning_button, |
| views::Border* border) |
| : gtk2_ui_(gtk2_ui), |
| use_gtk_(gtk2_ui_->GetUseSystemTheme()), |
| @@ -73,8 +82,9 @@ Gtk2Border::~Gtk2Border() { |
| } |
| void Gtk2Border::InvalidateAndSetUsesGtk(bool use_gtk) { |
| - hovered_ = gfx::ImageSkia(); |
| - pressed_ = gfx::ImageSkia(); |
| + for (int i = 0; i < 2; ++i) |
| + for (int j = 0; j < views::Button::STATE_COUNT; ++j) |
| + button_images_[i][j] = gfx::ImageSkia(); |
| // Our owning view must have its layout invalidated because the insets could |
| // have changed. |
| @@ -90,22 +100,31 @@ void Gtk2Border::Paint(const views::View& view, gfx::Canvas* canvas) { |
| } |
| DCHECK_EQ(&view, owning_button_); |
| - GtkStateType state = ViewsToGtkState(owning_button_->state()); |
| - |
| - if (state == GTK_STATE_PRELIGHT) { |
| - if (hovered_.isNull() || hovered_.size() != view.size()) { |
| - hovered_ = gfx::ImageSkia( |
| - new ButtonImageSkiaSource(gtk2_ui_, state, view.size()), view.size()); |
| - } |
| - |
| - canvas->DrawImageInt(hovered_, 0, 0); |
| - } else if (state == GTK_STATE_ACTIVE) { |
| - if (pressed_.isNull() || pressed_.size() != view.size()) { |
| - pressed_ = gfx::ImageSkia( |
| - new ButtonImageSkiaSource(gtk2_ui_, state, view.size()), view.size()); |
| - } |
| - |
| - canvas->DrawImageInt(pressed_, 0, 0); |
| + const NativeThemeDelegate* native_theme_delegate = owning_button_; |
| + gfx::Rect rect(native_theme_delegate->GetThemePaintRect()); |
| + ui::NativeTheme::ExtraParams extra; |
| + ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra); |
| + |
| + const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation(); |
| + if (animation && animation->is_animating()) { |
| + // Linearly interpolate background and foreground painters during animation. |
| + const SkRect sk_rect = gfx::RectToSkRect(rect); |
| + canvas->sk_canvas()->saveLayer(&sk_rect, NULL); |
| + state = native_theme_delegate->GetBackgroundThemeState(&extra); |
| + PaintState(state, extra, rect, canvas); |
| + |
| + SkPaint paint; |
| + skia::RefPtr<SkXfermode> sk_lerp_xfer = |
| + skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue())); |
| + paint.setXfermode(sk_lerp_xfer.get()); |
| + canvas->sk_canvas()->saveLayer(&sk_rect, &paint); |
| + state = native_theme_delegate->GetForegroundThemeState(&extra); |
| + PaintState(state, extra, rect, canvas); |
| + canvas->sk_canvas()->restore(); |
| + |
| + canvas->sk_canvas()->restore(); |
| + } else { |
| + PaintState(state, extra, rect, canvas); |
| } |
| } |
| @@ -124,4 +143,39 @@ gfx::Size Gtk2Border::GetMinimumSize() const { |
| return gfx::Size(insets.width(), insets.height()); |
| } |
| +void Gtk2Border::PaintState(const ui::NativeTheme::State state, |
| + const ui::NativeTheme::ExtraParams& extra, |
| + const gfx::Rect& rect, |
| + gfx::Canvas* canvas) { |
| + bool focused = extra.button.is_focused; |
| + Button::ButtonState views_state = Button::GetButtonStateFrom(state); |
| + |
| + if (ShouldDrawBorder(focused, views_state)) { |
| + gfx::ImageSkia* image = &button_images_[focused][views_state]; |
| + |
| + if (image->isNull() || image->size() != rect.size()) { |
| + GtkStateType gtk_state = GetGtkState(state); |
| + *image = gfx::ImageSkia( |
| + new ButtonImageSkiaSource(gtk2_ui_, gtk_state, focused, rect.size()), |
| + rect.size()); |
| + } |
| + canvas->DrawImageInt(*image, rect.x(), rect.y()); |
| + } |
| +} |
| + |
| +bool Gtk2Border::ShouldDrawBorder(bool focused, |
| + views::Button::ButtonState state) { |
| + // This logic should be kept in sync with the LabelButtonBorder constructor. |
| + if (owning_button_->style() == Button::STYLE_BUTTON) { |
| + return true; |
| + } else if (owning_button_->style() == Button::STYLE_TEXTBUTTON && |
| + focused == false && |
|
msw
2014/01/24 23:57:17
nit: consider making the focused/state conditions
|
| + (state == Button::STATE_HOVERED || |
| + state == Button::STATE_PRESSED)) { |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| } // namespace libgtk2ui |