- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / libgtk2ui / native_theme_gtk2.cc
1 // Copyright (c) 2013 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.
4
5 #include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h"
6
7 #include <gtk/gtk.h>
8
9 #include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h"
10 #include "ui/gfx/color_utils.h"
11 #include "ui/gfx/path.h"
12 #include "ui/gfx/rect.h"
13 #include "ui/gfx/size.h"
14 #include "ui/gfx/skia_util.h"
15 #include "ui/native_theme/common_theme.h"
16
17 namespace {
18
19 // Theme colors returned by GetSystemColor().
20 const SkColor kInvalidColorIdColor = SkColorSetRGB(255, 0, 128);
21 // Tree
22 const SkColor kTreeBackground = SK_ColorWHITE;
23 const SkColor kTreeTextColor = SK_ColorBLACK;
24 const SkColor kTreeSelectedTextColor = SK_ColorBLACK;
25 const SkColor kTreeSelectionBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE);
26 const SkColor kTreeArrowColor = SkColorSetRGB(0x7A, 0x7A, 0x7A);
27 // Table
28 const SkColor kTableBackground = SK_ColorWHITE;
29 const SkColor kTableTextColor = SK_ColorBLACK;
30 const SkColor kTableSelectedTextColor = SK_ColorBLACK;
31 const SkColor kTableSelectionBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE);
32 const SkColor kTableGroupingIndicatorColor = SkColorSetRGB(0xCC, 0xCC, 0xCC);
33
34 }  // namespace
35
36
37 namespace libgtk2ui {
38
39 // static
40 NativeThemeGtk2* NativeThemeGtk2::instance() {
41   CR_DEFINE_STATIC_LOCAL(NativeThemeGtk2, s_native_theme, ());
42   return &s_native_theme;
43 }
44
45 NativeThemeGtk2::NativeThemeGtk2()
46     : fake_window_(NULL),
47       fake_menu_item_(NULL) {
48 }
49
50 NativeThemeGtk2::~NativeThemeGtk2() {
51   if (fake_window_)
52     gtk_widget_destroy(fake_window_);
53   fake_entry_.Destroy();
54   fake_label_.Destroy();
55   fake_button_.Destroy();
56   fake_menu_.Destroy();
57 }
58
59 SkColor NativeThemeGtk2::GetSystemColor(ColorId color_id) const {
60   switch (color_id) {
61     // TODO(erg): Still need to fish the colors out of trees and tables.
62
63     // Tree
64     case kColorId_TreeBackground:
65       return kTreeBackground;
66     case kColorId_TreeText:
67       return kTreeTextColor;
68     case kColorId_TreeSelectedText:
69     case kColorId_TreeSelectedTextUnfocused:
70       return kTreeSelectedTextColor;
71     case kColorId_TreeSelectionBackgroundFocused:
72     case kColorId_TreeSelectionBackgroundUnfocused:
73       return kTreeSelectionBackgroundColor;
74     case kColorId_TreeArrow:
75       return kTreeArrowColor;
76
77     // Table
78     case kColorId_TableBackground:
79       return kTableBackground;
80     case kColorId_TableText:
81       return kTableTextColor;
82     case kColorId_TableSelectedText:
83     case kColorId_TableSelectedTextUnfocused:
84       return kTableSelectedTextColor;
85     case kColorId_TableSelectionBackgroundFocused:
86     case kColorId_TableSelectionBackgroundUnfocused:
87       return kTableSelectionBackgroundColor;
88     case kColorId_TableGroupingIndicatorColor:
89       return kTableGroupingIndicatorColor;
90
91     default:
92       // Fall through.
93       break;
94   }
95
96   return GdkColorToSkColor(GetSystemGdkColor(color_id));
97 }
98
99 void NativeThemeGtk2::PaintMenuPopupBackground(
100     SkCanvas* canvas,
101     const gfx::Size& size,
102     const MenuBackgroundExtraParams& menu_background) const {
103   if (menu_background.corner_radius > 0) {
104     SkPaint paint;
105     paint.setStyle(SkPaint::kFill_Style);
106     paint.setFlags(SkPaint::kAntiAlias_Flag);
107     paint.setColor(GetSystemColor(kColorId_MenuBackgroundColor));
108
109     gfx::Path path;
110     SkRect rect = SkRect::MakeWH(SkIntToScalar(size.width()),
111                                  SkIntToScalar(size.height()));
112     SkScalar radius = SkIntToScalar(menu_background.corner_radius);
113     SkScalar radii[8] = {radius, radius, radius, radius,
114                          radius, radius, radius, radius};
115     path.addRoundRect(rect, radii);
116
117     canvas->drawPath(path, paint);
118   } else {
119     canvas->drawColor(GetSystemColor(kColorId_MenuBackgroundColor),
120                       SkXfermode::kSrc_Mode);
121   }
122 }
123
124 void NativeThemeGtk2::PaintMenuItemBackground(
125     SkCanvas* canvas,
126     State state,
127     const gfx::Rect& rect,
128     const MenuListExtraParams& menu_list) const {
129   SkColor color;
130   SkPaint paint;
131   switch (state) {
132     case NativeTheme::kNormal:
133     case NativeTheme::kDisabled:
134       color = GetSystemColor(NativeTheme::kColorId_MenuBackgroundColor);
135       paint.setColor(color);
136       break;
137     case NativeTheme::kHovered:
138       color = GetSystemColor(
139           NativeTheme::kColorId_FocusedMenuItemBackgroundColor);
140       paint.setColor(color);
141       break;
142     default:
143       NOTREACHED() << "Invalid state " << state;
144       break;
145   }
146   canvas->drawRect(gfx::RectToSkRect(rect), paint);
147 }
148
149 GdkColor NativeThemeGtk2::GetSystemGdkColor(ColorId color_id) const {
150   switch (color_id) {
151     // Windows
152     case kColorId_WindowBackground:
153       return GetWindowStyle()->bg[GTK_STATE_NORMAL];
154
155     // Dialogs
156     case kColorId_DialogBackground:
157       return GetWindowStyle()->bg[GTK_STATE_NORMAL];
158
159     // FocusableBorder
160     case kColorId_FocusedBorderColor:
161       return GetEntryStyle()->bg[GTK_STATE_SELECTED];
162     case kColorId_UnfocusedBorderColor:
163       return GetEntryStyle()->text_aa[GTK_STATE_NORMAL];
164
165     // MenuItem
166     case kColorId_EnabledMenuItemForegroundColor:
167       return GetMenuItemStyle()->text[GTK_STATE_NORMAL];
168     case kColorId_DisabledMenuItemForegroundColor:
169       return GetMenuItemStyle()->text[GTK_STATE_INSENSITIVE];
170     case kColorId_SelectedMenuItemForegroundColor:
171       return GetMenuItemStyle()->text[GTK_STATE_SELECTED];
172     case kColorId_FocusedMenuItemBackgroundColor:
173       return GetMenuItemStyle()->bg[GTK_STATE_SELECTED];
174     case kColorId_HoverMenuItemBackgroundColor:
175       return GetMenuItemStyle()->bg[GTK_STATE_PRELIGHT];
176     case kColorId_FocusedMenuButtonBorderColor:
177       return GetEntryStyle()->bg[GTK_STATE_NORMAL];
178     case kColorId_HoverMenuButtonBorderColor:
179       return GetEntryStyle()->text_aa[GTK_STATE_PRELIGHT];
180     case kColorId_MenuBorderColor:
181     case kColorId_EnabledMenuButtonBorderColor:
182     case kColorId_MenuSeparatorColor: {
183       return GetMenuItemStyle()->text[GTK_STATE_INSENSITIVE];
184     }
185     case kColorId_MenuBackgroundColor:
186       return GetMenuStyle()->bg[GTK_STATE_NORMAL];
187
188     // Label
189     case kColorId_LabelEnabledColor:
190       return GetLabelStyle()->text[GTK_STATE_NORMAL];
191     case kColorId_LabelDisabledColor:
192       return GetLabelStyle()->text[GTK_STATE_INSENSITIVE];
193     case kColorId_LabelBackgroundColor:
194       return GetWindowStyle()->bg[GTK_STATE_NORMAL];
195
196     // Button
197     case kColorId_ButtonBackgroundColor:
198       return GetButtonStyle()->bg[GTK_STATE_NORMAL];
199     case kColorId_ButtonEnabledColor:
200       return GetButtonStyle()->text[GTK_STATE_NORMAL];
201     case kColorId_ButtonDisabledColor:
202       return GetButtonStyle()->text[GTK_STATE_INSENSITIVE];
203     case kColorId_ButtonHighlightColor:
204       return GetButtonStyle()->base[GTK_STATE_SELECTED];
205     case kColorId_ButtonHoverColor:
206       return GetButtonStyle()->text[GTK_STATE_PRELIGHT];
207
208     // Textfield
209     case kColorId_TextfieldDefaultColor:
210       return GetEntryStyle()->text[GTK_STATE_NORMAL];
211     case kColorId_TextfieldDefaultBackground:
212       return GetEntryStyle()->base[GTK_STATE_NORMAL];
213     case kColorId_TextfieldReadOnlyColor:
214       return GetEntryStyle()->text[GTK_STATE_INSENSITIVE];
215     case kColorId_TextfieldReadOnlyBackground:
216       return GetEntryStyle()->base[GTK_STATE_INSENSITIVE];
217     case kColorId_TextfieldSelectionColor:
218       return GetEntryStyle()->text[GTK_STATE_SELECTED];
219     case kColorId_TextfieldSelectionBackgroundFocused:
220       return GetEntryStyle()->base[GTK_STATE_SELECTED];
221
222     // Tree
223     // Table
224
225     default:
226       // Fall through
227       break;
228   }
229
230   return SkColorToGdkColor(kInvalidColorIdColor);
231 }
232
233 GtkWidget* NativeThemeGtk2::GetRealizedWindow() const {
234   if (!fake_window_) {
235     fake_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
236     gtk_widget_realize(fake_window_);
237   }
238
239   return fake_window_;
240 }
241
242 GtkStyle* NativeThemeGtk2::GetWindowStyle() const {
243   return gtk_rc_get_style(GetRealizedWindow());
244 }
245
246 GtkStyle* NativeThemeGtk2::GetEntryStyle() const {
247   if (!fake_entry_.get()) {
248     fake_entry_.Own(gtk_entry_new());
249
250     // The fake entry needs to be in the window so it can be realized sow e can
251     // use the computed parts of the style.
252     gtk_container_add(GTK_CONTAINER(GetRealizedWindow()), fake_entry_.get());
253     gtk_widget_realize(fake_entry_.get());
254   }
255   return gtk_rc_get_style(fake_entry_.get());
256 }
257
258 GtkStyle* NativeThemeGtk2::GetLabelStyle() const {
259   if (!fake_label_.get())
260     fake_label_.Own(gtk_label_new(""));
261
262   return gtk_rc_get_style(fake_label_.get());
263 }
264
265 GtkStyle* NativeThemeGtk2::GetButtonStyle() const {
266   if (!fake_button_.get())
267     fake_button_.Own(gtk_button_new());
268
269   return gtk_rc_get_style(fake_button_.get());
270 }
271
272 GtkStyle* NativeThemeGtk2::GetMenuStyle() const {
273   if (!fake_menu_.get())
274     fake_menu_.Own(gtk_menu_new());
275   return gtk_rc_get_style(fake_menu_.get());
276 }
277
278 GtkStyle* NativeThemeGtk2::GetMenuItemStyle() const {
279   if (!fake_menu_item_) {
280     if (!fake_menu_.get())
281       fake_menu_.Own(gtk_menu_new());
282
283     fake_menu_item_ = gtk_menu_item_new();
284     gtk_menu_shell_append(GTK_MENU_SHELL(fake_menu_.get()), fake_menu_item_);
285   }
286
287   return gtk_rc_get_style(fake_menu_item_);
288 }
289
290 }  // namespace libgtk2ui