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"
9 #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h"
10 #include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
11 #include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h"
12 #include "third_party/skia/include/effects/SkLerpXfermode.h"
13 #include "ui/base/theme_provider.h"
14 #include "ui/gfx/animation/animation.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/geometry/rect.h"
17 #include "ui/gfx/image/image_skia_source.h"
18 #include "ui/gfx/skia_util.h"
19 #include "ui/views/controls/button/label_button.h"
20 #include "ui/views/controls/button/label_button_border.h"
21 #include "ui/views/native_theme_delegate.h"
24 using views::NativeThemeDelegate
;
28 Gtk2Border::Gtk2Border(Gtk2UI
* gtk2_ui
,
29 views::LabelButton
* owning_button
,
30 scoped_ptr
<views::LabelButtonBorder
> border
)
32 owning_button_(owning_button
),
33 border_(border
.Pass()),
34 observer_manager_(this) {
35 observer_manager_
.Add(NativeThemeGtk2::instance());
38 Gtk2Border::~Gtk2Border() {
41 void Gtk2Border::Paint(const views::View
& view
, gfx::Canvas
* canvas
) {
42 DCHECK_EQ(&view
, owning_button_
);
43 const NativeThemeDelegate
* native_theme_delegate
= owning_button_
;
44 gfx::Rect
rect(native_theme_delegate
->GetThemePaintRect());
45 ui::NativeTheme::ExtraParams extra
;
46 ui::NativeTheme::State state
= native_theme_delegate
->GetThemeState(&extra
);
48 const gfx::Animation
* animation
= native_theme_delegate
->GetThemeAnimation();
49 if (animation
&& animation
->is_animating()) {
50 // Linearly interpolate background and foreground painters during animation.
51 const SkRect sk_rect
= gfx::RectToSkRect(rect
);
52 canvas
->sk_canvas()->saveLayer(&sk_rect
, NULL
);
53 state
= native_theme_delegate
->GetBackgroundThemeState(&extra
);
54 PaintState(state
, extra
, rect
, canvas
);
57 skia::RefPtr
<SkXfermode
> sk_lerp_xfer
=
58 skia::AdoptRef(SkLerpXfermode::Create(animation
->GetCurrentValue()));
59 paint
.setXfermode(sk_lerp_xfer
.get());
60 canvas
->sk_canvas()->saveLayer(&sk_rect
, &paint
);
61 state
= native_theme_delegate
->GetForegroundThemeState(&extra
);
62 PaintState(state
, extra
, rect
, canvas
);
63 canvas
->sk_canvas()->restore();
65 canvas
->sk_canvas()->restore();
67 PaintState(state
, extra
, rect
, canvas
);
71 gfx::Insets
Gtk2Border::GetInsets() const {
72 return border_
->GetInsets();
75 gfx::Size
Gtk2Border::GetMinimumSize() const {
76 return border_
->GetMinimumSize();
79 void Gtk2Border::OnNativeThemeUpdated(ui::NativeTheme
* observed_theme
) {
80 DCHECK_EQ(observed_theme
, NativeThemeGtk2::instance());
81 for (int i
= 0; i
< 2; ++i
) {
82 for (int j
= 0; j
< views::Button::STATE_COUNT
; ++j
) {
83 button_images_
[i
][j
] = gfx::ImageSkia();
87 // Our owning view must have its layout invalidated because the insets could
89 owning_button_
->InvalidateLayout();
92 void Gtk2Border::PaintState(const ui::NativeTheme::State state
,
93 const ui::NativeTheme::ExtraParams
& extra
,
94 const gfx::Rect
& rect
,
95 gfx::Canvas
* canvas
) {
96 bool focused
= extra
.button
.is_focused
;
97 Button::ButtonState views_state
= Button::GetButtonStateFrom(state
);
99 if (border_
->PaintsButtonState(focused
, views_state
)) {
100 gfx::ImageSkia
* image
= &button_images_
[focused
][views_state
];
102 if (image
->isNull() || image
->size() != rect
.size()) {
103 *image
= gfx::ImageSkia::CreateFrom1xBitmap(
104 gtk2_ui_
->DrawGtkButtonBorder(owning_button_
->GetClassName(),
109 canvas
->DrawImageInt(*image
, rect
.x(), rect
.y());
113 } // namespace libgtk2ui