Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / ui / libgtk2ui / gtk2_border.cc
blob31a239690e7c9f6c04fe7136c186d124c1f6f77a
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/libgtk2ui/gtk2_border.h"
7 #include <gtk/gtk.h>
9 #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h"
10 #include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h"
11 #include "third_party/skia/include/effects/SkLerpXfermode.h"
12 #include "ui/base/theme_provider.h"
13 #include "ui/gfx/animation/animation.h"
14 #include "ui/gfx/canvas.h"
15 #include "ui/gfx/image/image_skia_source.h"
16 #include "ui/gfx/rect.h"
17 #include "ui/gfx/skia_util.h"
18 #include "ui/views/controls/button/label_button.h"
19 #include "ui/views/native_theme_delegate.h"
21 using views::Button;
22 using views::NativeThemeDelegate;
24 namespace libgtk2ui {
26 namespace {
28 const int kNumberOfFocusedStates = 2;
30 GtkStateType GetGtkState(ui::NativeTheme::State state) {
31 switch (state) {
32 case ui::NativeTheme::kDisabled: return GTK_STATE_INSENSITIVE;
33 case ui::NativeTheme::kHovered: return GTK_STATE_PRELIGHT;
34 case ui::NativeTheme::kNormal: return GTK_STATE_NORMAL;
35 case ui::NativeTheme::kPressed: return GTK_STATE_ACTIVE;
36 case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state;
38 return GTK_STATE_NORMAL;
41 class ButtonImageSkiaSource : public gfx::ImageSkiaSource {
42 public:
43 ButtonImageSkiaSource(const Gtk2UI* gtk2_ui,
44 const GtkStateType state,
45 const bool focused,
46 const gfx::Size& size)
47 : gtk2_ui_(gtk2_ui),
48 state_(state),
49 focused_(focused),
50 size_(size) {
53 virtual ~ButtonImageSkiaSource() {
56 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
57 int w = size_.width() * scale;
58 int h = size_.height() * scale;
59 return gfx::ImageSkiaRep(
60 gtk2_ui_->DrawGtkButtonBorder(state_, focused_, w, h), scale);
63 private:
64 const Gtk2UI* gtk2_ui_;
65 const GtkStateType state_;
66 const bool focused_;
67 const gfx::Size size_;
69 DISALLOW_COPY_AND_ASSIGN(ButtonImageSkiaSource);
72 } // namespace
74 Gtk2Border::Gtk2Border(Gtk2UI* gtk2_ui,
75 views::LabelButton* owning_button)
76 : gtk2_ui_(gtk2_ui),
77 owning_button_(owning_button),
78 observer_manager_(this) {
79 observer_manager_.Add(NativeThemeGtk2::instance());
82 Gtk2Border::~Gtk2Border() {
85 void Gtk2Border::Paint(const views::View& view, gfx::Canvas* canvas) {
86 DCHECK_EQ(&view, owning_button_);
87 const NativeThemeDelegate* native_theme_delegate = owning_button_;
88 gfx::Rect rect(native_theme_delegate->GetThemePaintRect());
89 ui::NativeTheme::ExtraParams extra;
90 ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra);
92 const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation();
93 if (animation && animation->is_animating()) {
94 // Linearly interpolate background and foreground painters during animation.
95 const SkRect sk_rect = gfx::RectToSkRect(rect);
96 canvas->sk_canvas()->saveLayer(&sk_rect, NULL);
97 state = native_theme_delegate->GetBackgroundThemeState(&extra);
98 PaintState(state, extra, rect, canvas);
100 SkPaint paint;
101 skia::RefPtr<SkXfermode> sk_lerp_xfer =
102 skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue()));
103 paint.setXfermode(sk_lerp_xfer.get());
104 canvas->sk_canvas()->saveLayer(&sk_rect, &paint);
105 state = native_theme_delegate->GetForegroundThemeState(&extra);
106 PaintState(state, extra, rect, canvas);
107 canvas->sk_canvas()->restore();
109 canvas->sk_canvas()->restore();
110 } else {
111 PaintState(state, extra, rect, canvas);
115 gfx::Insets Gtk2Border::GetInsets() const {
116 // On STYLE_TEXTUBTTON, we want the smaller insets so we can fit the GTK icon
117 // in the toolbar without cutting off the edges of the GTK image.
118 return gtk2_ui_->GetButtonInsets();
121 gfx::Size Gtk2Border::GetMinimumSize() const {
122 gfx::Insets insets = GetInsets();
123 return gfx::Size(insets.width(), insets.height());
126 void Gtk2Border::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
127 DCHECK_EQ(observed_theme, NativeThemeGtk2::instance());
128 for (int i = 0; i < kNumberOfFocusedStates; ++i) {
129 for (int j = 0; j < views::Button::STATE_COUNT; ++j) {
130 button_images_[i][j] = gfx::ImageSkia();
134 // Our owning view must have its layout invalidated because the insets could
135 // have changed.
136 owning_button_->InvalidateLayout();
139 void Gtk2Border::PaintState(const ui::NativeTheme::State state,
140 const ui::NativeTheme::ExtraParams& extra,
141 const gfx::Rect& rect,
142 gfx::Canvas* canvas) {
143 bool focused = extra.button.is_focused;
144 Button::ButtonState views_state = Button::GetButtonStateFrom(state);
146 if (ShouldDrawBorder(focused, views_state)) {
147 gfx::ImageSkia* image = &button_images_[focused][views_state];
149 if (image->isNull() || image->size() != rect.size()) {
150 GtkStateType gtk_state = GetGtkState(state);
151 *image = gfx::ImageSkia(
152 new ButtonImageSkiaSource(gtk2_ui_, gtk_state, focused, rect.size()),
153 rect.size());
155 canvas->DrawImageInt(*image, rect.x(), rect.y());
159 bool Gtk2Border::ShouldDrawBorder(bool focused,
160 views::Button::ButtonState state) {
161 // This logic should be kept in sync with the LabelButtonBorder constructor.
162 if (owning_button_->style() == Button::STYLE_BUTTON) {
163 return true;
164 } else if (owning_button_->style() == Button::STYLE_TEXTBUTTON) {
165 return focused == false && (state == Button::STATE_HOVERED ||
166 state == Button::STATE_PRESSED);
169 return false;
172 } // namespace libgtk2ui