diff options
author | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-09 01:07:42 +0000 |
---|---|---|
committer | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-09 01:07:42 +0000 |
commit | 4a19063d1459a4c9c8c4c50ed86eb9048f69ea3f (patch) | |
tree | 69a1e9f78b3a5fa8b909cfab336826b09c44235f | |
parent | 5085ee0b4bfbe4625e63ee6975bb95702e13e0aa (diff) | |
download | chromium_src-4a19063d1459a4c9c8c4c50ed86eb9048f69ea3f.zip chromium_src-4a19063d1459a4c9c8c4c50ed86eb9048f69ea3f.tar.gz chromium_src-4a19063d1459a4c9c8c4c50ed86eb9048f69ea3f.tar.bz2 |
This is the first pass at themes.
This CL is paired with http://codereview.chromium.org/67284
This CL (for commit purposes) includes http://codereview.chromium.org/67284
BUG=4463,11232,11233,11234,11235
Review URL: http://codereview.chromium.org/99030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15704 0039d316-1c4b-4281-b951-d872f2087c98
162 files changed, 2116 insertions, 1039 deletions
@@ -1,19 +1,16 @@ -include_rules = [ +include_rules = [
# TODO(beng): Modify this link to be more specific about what resource # headers are included once app gets its own strings. - "+grit", - "+net", - # TODO(beng): Sever these links once we have extracted all deps from - # chrome/common. - "+chrome/common/chrome_paths.h", - "+chrome/common/chrome_switches.h", - "+chrome/common/gtk_util.h", + "+grit",
+ "+net",
+ # TODO(beng): Sever these links once we have extracted all deps from
+ # chrome/common.
+ "+chrome/common/chrome_paths.h",
+ "+chrome/common/chrome_switches.h",
+ "+chrome/common/gtk_util.h",
- # TODO(beng): l10n_util_unittest.cc: - "+chrome/test/data/resource.h", - - # TODO(beng): resource_bundle.cc: Sever this link after glen fixes it. - "+chrome/browser/extensions/extension.h", - - "+skia", -] + # TODO(beng): l10n_util_unittest.cc:
+ "+chrome/test/data/resource.h",
+
+ "+skia",
+]
diff --git a/app/app.vcproj b/app/app.vcproj index 507a28a..d940bf9 100644 --- a/app/app.vcproj +++ b/app/app.vcproj @@ -145,14 +145,14 @@ >
</File>
<File
- RelativePath=".\gfx\color_utils.cc"
- >
- </File>
- <File
- RelativePath=".\gfx\color_utils.h"
- >
- </File>
- <File
+ RelativePath=".\gfx\color_utils.cc" + > + </File> + <File + RelativePath=".\gfx\color_utils.h" + > + </File> + <File RelativePath=".\gfx\favicon_size.h"
>
</File>
@@ -176,14 +176,14 @@ RelativePath=".\gfx\path_win.cc"
>
</File>
- <File
- RelativePath=".\gfx\text_elider.cc"
- >
- </File>
- <File
- RelativePath=".\gfx\text_elider.h"
- >
- </File>
+ <File + RelativePath=".\gfx\text_elider.cc" + > + </File> + <File + RelativePath=".\gfx\text_elider.h" + > + </File> </Filter>
<File
RelativePath=".\animation.cc"
@@ -250,6 +250,10 @@ >
</File>
<File
+ RelativePath=".\theme_provider.h"
+ >
+ </File>
+ <File
RelativePath=".\throb_animation.cc"
>
</File>
diff --git a/app/resource_bundle.cc b/app/resource_bundle.cc index c3d6923..85fd0b9 100644 --- a/app/resource_bundle.cc +++ b/app/resource_bundle.cc @@ -15,6 +15,22 @@ ResourceBundle* ResourceBundle::g_shared_instance_ = NULL; /* static */ +// TODO(glen): Finish moving these into theme provider (dialogs still +// depend on these colors). +const SkColor ResourceBundle::frame_color = + SkColorSetRGB(77, 139, 217); +const SkColor ResourceBundle::frame_color_inactive = + SkColorSetRGB(184, 209, 240); +const SkColor ResourceBundle::frame_color_incognito = + SkColorSetRGB(83, 106, 139); +const SkColor ResourceBundle::frame_color_incognito_inactive = + SkColorSetRGB(126, 139, 156); +const SkColor ResourceBundle::toolbar_color = + SkColorSetRGB(210, 225, 246); +const SkColor ResourceBundle::toolbar_separator_color = + SkColorSetRGB(182, 186, 192); + +/* static */ void ResourceBundle::InitSharedInstance(const std::wstring& pref_locale) { DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; g_shared_instance_ = new ResourceBundle(); @@ -51,39 +67,11 @@ void ResourceBundle::FreeImages() { skia_images_.clear(); } -void ResourceBundle::SetThemeExtension(const Extension& e) { - theme_extension_.reset(new Extension(e)); -} - /* static */ SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) { std::vector<unsigned char> raw_data, png_data; bool success = false; - // First check to see if we have a registered theme extension and whether - // it can handle this resource. - // TODO(erikkay): It would be nice to use something less brittle than - // resource_id here. - if (g_shared_instance_->theme_extension_.get()) { - FilePath path = - g_shared_instance_->theme_extension_->GetThemeResourcePath(resource_id); - if (!path.empty()) { - net::FileStream file; - int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; - if (file.Open(path, flags) == net::OK) { - int64 avail = file.Available(); - if (avail > 0 && avail < INT_MAX) { - size_t size = static_cast<size_t>(avail); - raw_data.resize(size); - char* data = reinterpret_cast<char*>(&(raw_data.front())); - if (file.ReadUntilComplete(data, size) == avail) { - success= true; - } else { - raw_data.resize(0); - } - } - } - } - } + if (!success) success = LoadResourceBytes(data_handle, resource_id, &raw_data); if (!success) diff --git a/app/resource_bundle.h b/app/resource_bundle.h index e939edc..1ed44b0 100644 --- a/app/resource_bundle.h +++ b/app/resource_bundle.h @@ -18,7 +18,7 @@ #include "base/file_path.h" #include "base/lock.h" #include "base/scoped_ptr.h" -#include "chrome/browser/extensions/extension.h" +#include "base/string16.h" #if defined(OS_LINUX) || defined(OS_MACOSX) namespace base { @@ -29,8 +29,8 @@ class DataPack; typedef struct _GdkPixbuf GdkPixbuf; #endif class ChromeFont; -class Extension; class SkBitmap; +typedef uint32 SkColor; class StringPiece; // ResourceBundle is a central facility to load images and other resources, @@ -123,8 +123,14 @@ class ResourceBundle { GdkPixbuf* GetPixbufNamed(int resource_id); #endif - // Sets an Extension object that can handle theme resource requests. - void SetThemeExtension(const Extension& e); + // TODO(glen): Move these into theme provider (dialogs still depend on + // ResourceBundle). + static const SkColor frame_color; + static const SkColor frame_color_inactive; + static const SkColor frame_color_incognito; + static const SkColor frame_color_incognito_inactive; + static const SkColor toolbar_color; + static const SkColor toolbar_separator_color; private: // We define a DataHandle typedef to abstract across how data is stored @@ -195,8 +201,6 @@ class ResourceBundle { static ResourceBundle* g_shared_instance_; - scoped_ptr<Extension> theme_extension_; - DISALLOW_EVIL_CONSTRUCTORS(ResourceBundle); }; diff --git a/app/theme_provider.h b/app/theme_provider.h new file mode 100644 index 0000000..ebc94c6 --- /dev/null +++ b/app/theme_provider.h @@ -0,0 +1,33 @@ +// Copyright (c) 2009 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 APP_THEME_PROVIDER_H_ +#define APP_THEME_PROVIDER_H_ + +#include "skia/include/SkColor.h" + +class SkBitmap; + +//////////////////////////////////////////////////////////////////////////////// +// +// ThemeProvider +// +// ThemeProvider is an abstract class that defines the API that should be +// implemented to provide bitmaps and color information for a given theme. +// +//////////////////////////////////////////////////////////////////////////////// + +class ThemeProvider { + public: + virtual ~ThemeProvider() { } + + // Get the bitmap specified by |id|. An implementation of ThemeProvider should + // have its own source of ids (e.g. an enum, or external resource bundle). + virtual SkBitmap* GetBitmapNamed(int id) = 0; + + // Get the color specified by |id|. + virtual SkColor GetColor(int id) = 0; +}; + +#endif // APP_THEME_PROVIDER_H_ diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c192afb..05c02db 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3099,6 +3099,13 @@ each locale. --> Save text from forms to make them easier to fill out </message> + <message name="IDS_THEMES_GROUP_NAME" desc="The title of the themes group"> + Themes: + </message> + <message name="IDS_THEMES_RESET_BUTTON" desc="The button to reset your theme"> + Reset to default theme + </message> + <message name="IDS_OPTIONS_FONTSANDLANGUAGES_GROUP_NAME" desc="The label of the 'Fonts and Languages' group"> Fonts and Languages: </message> diff --git a/chrome/app/theme/app_top_center.png b/chrome/app/theme/app_top_center.png Binary files differindex 863ff19..46f8f96 100644 --- a/chrome/app/theme/app_top_center.png +++ b/chrome/app/theme/app_top_center.png diff --git a/chrome/app/theme/app_top_left.png b/chrome/app/theme/app_top_left.png Binary files differindex 79723bc..78dc306f 100644 --- a/chrome/app/theme/app_top_left.png +++ b/chrome/app/theme/app_top_left.png diff --git a/chrome/app/theme/app_top_right.png b/chrome/app/theme/app_top_right.png Binary files differindex b00c3ea..df3b9a3 100644 --- a/chrome/app/theme/app_top_right.png +++ b/chrome/app/theme/app_top_right.png diff --git a/chrome/app/theme/back.png b/chrome/app/theme/back.png Binary files differindex 4f7a2d2..b983fca 100644 --- a/chrome/app/theme/back.png +++ b/chrome/app/theme/back.png diff --git a/chrome/app/theme/back_d.png b/chrome/app/theme/back_d.png Binary files differindex b216b18..1b51a59 100644 --- a/chrome/app/theme/back_d.png +++ b/chrome/app/theme/back_d.png diff --git a/chrome/app/theme/constrained_bottom_center.png b/chrome/app/theme/constrained_bottom_center.png Binary files differdeleted file mode 100644 index e1014b5..0000000 --- a/chrome/app/theme/constrained_bottom_center.png +++ /dev/null diff --git a/chrome/app/theme/constrained_bottom_left_corner.png b/chrome/app/theme/constrained_bottom_left_corner.png Binary files differdeleted file mode 100644 index 4ba2342..0000000 --- a/chrome/app/theme/constrained_bottom_left_corner.png +++ /dev/null diff --git a/chrome/app/theme/constrained_bottom_right_corner.png b/chrome/app/theme/constrained_bottom_right_corner.png Binary files differdeleted file mode 100644 index 8221cc3..0000000 --- a/chrome/app/theme/constrained_bottom_right_corner.png +++ /dev/null diff --git a/chrome/app/theme/constrained_left_side.png b/chrome/app/theme/constrained_left_side.png Binary files differdeleted file mode 100644 index 0a00529..0000000 --- a/chrome/app/theme/constrained_left_side.png +++ /dev/null diff --git a/chrome/app/theme/constrained_right_side.png b/chrome/app/theme/constrained_right_side.png Binary files differdeleted file mode 100644 index 0d97721..0000000 --- a/chrome/app/theme/constrained_right_side.png +++ /dev/null diff --git a/chrome/app/theme/constrained_top_center.png b/chrome/app/theme/constrained_top_center.png Binary files differdeleted file mode 100644 index 89ab107..0000000 --- a/chrome/app/theme/constrained_top_center.png +++ /dev/null diff --git a/chrome/app/theme/constrained_top_left_corner.png b/chrome/app/theme/constrained_top_left_corner.png Binary files differdeleted file mode 100644 index b0ec4a9..0000000 --- a/chrome/app/theme/constrained_top_left_corner.png +++ /dev/null diff --git a/chrome/app/theme/constrained_top_right_corner.png b/chrome/app/theme/constrained_top_right_corner.png Binary files differdeleted file mode 100644 index 7dd550e..0000000 --- a/chrome/app/theme/constrained_top_right_corner.png +++ /dev/null diff --git a/chrome/app/theme/content_bottom_center.png b/chrome/app/theme/content_bottom_center.png Binary files differindex a9bdb3d..efce9cf 100644 --- a/chrome/app/theme/content_bottom_center.png +++ b/chrome/app/theme/content_bottom_center.png diff --git a/chrome/app/theme/content_bottom_left_corner.png b/chrome/app/theme/content_bottom_left_corner.png Binary files differindex 0f0d629..db7b04f 100644 --- a/chrome/app/theme/content_bottom_left_corner.png +++ b/chrome/app/theme/content_bottom_left_corner.png diff --git a/chrome/app/theme/content_bottom_right_corner.png b/chrome/app/theme/content_bottom_right_corner.png Binary files differindex 77fe4ac..d4c0136 100644 --- a/chrome/app/theme/content_bottom_right_corner.png +++ b/chrome/app/theme/content_bottom_right_corner.png diff --git a/chrome/app/theme/content_left_side.png b/chrome/app/theme/content_left_side.png Binary files differindex e952fcb..93bc64b 100644 --- a/chrome/app/theme/content_left_side.png +++ b/chrome/app/theme/content_left_side.png diff --git a/chrome/app/theme/content_right_side.png b/chrome/app/theme/content_right_side.png Binary files differindex 35e3d74..598858b 100644 --- a/chrome/app/theme/content_right_side.png +++ b/chrome/app/theme/content_right_side.png diff --git a/chrome/app/theme/content_top_center.png b/chrome/app/theme/content_top_center.png Binary files differindex 07cd04a..4bd39e3 100644 --- a/chrome/app/theme/content_top_center.png +++ b/chrome/app/theme/content_top_center.png diff --git a/chrome/app/theme/content_top_left_corner.png b/chrome/app/theme/content_top_left_corner.png Binary files differindex 3ca40b6..2baaf4e 100644 --- a/chrome/app/theme/content_top_left_corner.png +++ b/chrome/app/theme/content_top_left_corner.png diff --git a/chrome/app/theme/content_top_right_corner.png b/chrome/app/theme/content_top_right_corner.png Binary files differindex 91fe2de..25fd15a 100644 --- a/chrome/app/theme/content_top_right_corner.png +++ b/chrome/app/theme/content_top_right_corner.png diff --git a/chrome/app/theme/dewindow_bottom_center.png b/chrome/app/theme/dewindow_bottom_center.png Binary files differdeleted file mode 100644 index 78c0409..0000000 --- a/chrome/app/theme/dewindow_bottom_center.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_bottom_center_otr.png b/chrome/app/theme/dewindow_bottom_center_otr.png Binary files differdeleted file mode 100644 index 8fa9f44..0000000 --- a/chrome/app/theme/dewindow_bottom_center_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_bottom_left_corner.png b/chrome/app/theme/dewindow_bottom_left_corner.png Binary files differdeleted file mode 100644 index d961eaf..0000000 --- a/chrome/app/theme/dewindow_bottom_left_corner.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_bottom_left_corner_otr.png b/chrome/app/theme/dewindow_bottom_left_corner_otr.png Binary files differdeleted file mode 100644 index 934aaf9..0000000 --- a/chrome/app/theme/dewindow_bottom_left_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_bottom_right_corner.png b/chrome/app/theme/dewindow_bottom_right_corner.png Binary files differdeleted file mode 100644 index e5a2e3d..0000000 --- a/chrome/app/theme/dewindow_bottom_right_corner.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_bottom_right_corner_otr.png b/chrome/app/theme/dewindow_bottom_right_corner_otr.png Binary files differdeleted file mode 100644 index a262d91..0000000 --- a/chrome/app/theme/dewindow_bottom_right_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_left_side.png b/chrome/app/theme/dewindow_left_side.png Binary files differdeleted file mode 100644 index f84abc3..0000000 --- a/chrome/app/theme/dewindow_left_side.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_left_side_otr.png b/chrome/app/theme/dewindow_left_side_otr.png Binary files differdeleted file mode 100644 index 4b0fbce..0000000 --- a/chrome/app/theme/dewindow_left_side_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_right_side.png b/chrome/app/theme/dewindow_right_side.png Binary files differdeleted file mode 100644 index 3e79e27..0000000 --- a/chrome/app/theme/dewindow_right_side.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_right_side_otr.png b/chrome/app/theme/dewindow_right_side_otr.png Binary files differdeleted file mode 100644 index bf64f90..0000000 --- a/chrome/app/theme/dewindow_right_side_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_center.png b/chrome/app/theme/dewindow_top_center.png Binary files differdeleted file mode 100644 index 6a5ba27..0000000 --- a/chrome/app/theme/dewindow_top_center.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_center_otr.png b/chrome/app/theme/dewindow_top_center_otr.png Binary files differdeleted file mode 100644 index 6b9baf1..0000000 --- a/chrome/app/theme/dewindow_top_center_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_left_corner.png b/chrome/app/theme/dewindow_top_left_corner.png Binary files differdeleted file mode 100644 index d7af76f..0000000 --- a/chrome/app/theme/dewindow_top_left_corner.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_left_corner_otr.png b/chrome/app/theme/dewindow_top_left_corner_otr.png Binary files differdeleted file mode 100644 index c8ca568..0000000 --- a/chrome/app/theme/dewindow_top_left_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_right_corner.png b/chrome/app/theme/dewindow_top_right_corner.png Binary files differdeleted file mode 100644 index ca6659c..0000000 --- a/chrome/app/theme/dewindow_top_right_corner.png +++ /dev/null diff --git a/chrome/app/theme/dewindow_top_right_corner_otr.png b/chrome/app/theme/dewindow_top_right_corner_otr.png Binary files differdeleted file mode 100644 index 3a4300b..0000000 --- a/chrome/app/theme/dewindow_top_right_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/forward.png b/chrome/app/theme/forward.png Binary files differindex a2dd01d..a1ae190 100644 --- a/chrome/app/theme/forward.png +++ b/chrome/app/theme/forward.png diff --git a/chrome/app/theme/forward_d.png b/chrome/app/theme/forward_d.png Binary files differindex d4a1426..28012fe 100644 --- a/chrome/app/theme/forward_d.png +++ b/chrome/app/theme/forward_d.png diff --git a/chrome/app/theme/go.png b/chrome/app/theme/go.png Binary files differindex 571fb75..c4df2164 100644 --- a/chrome/app/theme/go.png +++ b/chrome/app/theme/go.png diff --git a/chrome/app/theme/locationbg.png b/chrome/app/theme/locationbg.png Binary files differindex 875e47d..974b443 100644 --- a/chrome/app/theme/locationbg.png +++ b/chrome/app/theme/locationbg.png diff --git a/chrome/app/theme/menu_chrome.png b/chrome/app/theme/menu_chrome.png Binary files differindex aabd07d..6fc9f5c 100644 --- a/chrome/app/theme/menu_chrome.png +++ b/chrome/app/theme/menu_chrome.png diff --git a/chrome/app/theme/menu_page.png b/chrome/app/theme/menu_page.png Binary files differindex 10b8def..75897ef 100644 --- a/chrome/app/theme/menu_page.png +++ b/chrome/app/theme/menu_page.png diff --git a/chrome/app/theme/notused.png b/chrome/app/theme/notused.png Binary files differnew file mode 100644 index 0000000..42ad610 --- /dev/null +++ b/chrome/app/theme/notused.png diff --git a/chrome/app/theme/ntp_background.png b/chrome/app/theme/ntp_background.png Binary files differnew file mode 100644 index 0000000..fb75b9f --- /dev/null +++ b/chrome/app/theme/ntp_background.png diff --git a/chrome/app/theme/reload.png b/chrome/app/theme/reload.png Binary files differindex 20ab352..f63d5188 100644 --- a/chrome/app/theme/reload.png +++ b/chrome/app/theme/reload.png diff --git a/chrome/app/theme/reload_d.png b/chrome/app/theme/reload_d.png Binary files differindex 15a6a1e..ec5811a 100644 --- a/chrome/app/theme/reload_d.png +++ b/chrome/app/theme/reload_d.png diff --git a/chrome/app/theme/star.png b/chrome/app/theme/star.png Binary files differindex 6284d4a..987aa04 100644 --- a/chrome/app/theme/star.png +++ b/chrome/app/theme/star.png diff --git a/chrome/app/theme/star_d.png b/chrome/app/theme/star_d.png Binary files differindex a6111a5..cf23eda 100644 --- a/chrome/app/theme/star_d.png +++ b/chrome/app/theme/star_d.png diff --git a/chrome/app/theme/starred.png b/chrome/app/theme/starred.png Binary files differindex 1b20148..bf0ba85 100644 --- a/chrome/app/theme/starred.png +++ b/chrome/app/theme/starred.png diff --git a/chrome/app/theme/stop.png b/chrome/app/theme/stop.png Binary files differindex 8b91fca..f25d62a 100644 --- a/chrome/app/theme/stop.png +++ b/chrome/app/theme/stop.png diff --git a/chrome/app/theme/tab_active_center.png b/chrome/app/theme/tab_active_center.png Binary files differindex 653b8fe..24b9a64 100644 --- a/chrome/app/theme/tab_active_center.png +++ b/chrome/app/theme/tab_active_center.png diff --git a/chrome/app/theme/tab_active_left.png b/chrome/app/theme/tab_active_left.png Binary files differindex 65d627c..b926a48 100644 --- a/chrome/app/theme/tab_active_left.png +++ b/chrome/app/theme/tab_active_left.png diff --git a/chrome/app/theme/tab_active_right.png b/chrome/app/theme/tab_active_right.png Binary files differindex b7d6134..bec77a2 100644 --- a/chrome/app/theme/tab_active_right.png +++ b/chrome/app/theme/tab_active_right.png diff --git a/chrome/app/theme/tab_hover_center.png b/chrome/app/theme/tab_hover_center.png Binary files differdeleted file mode 100644 index 4a639da..0000000 --- a/chrome/app/theme/tab_hover_center.png +++ /dev/null diff --git a/chrome/app/theme/tab_hover_left.png b/chrome/app/theme/tab_hover_left.png Binary files differdeleted file mode 100644 index cedd81d..0000000 --- a/chrome/app/theme/tab_hover_left.png +++ /dev/null diff --git a/chrome/app/theme/tab_hover_right.png b/chrome/app/theme/tab_hover_right.png Binary files differdeleted file mode 100644 index 3bda1fd..0000000 --- a/chrome/app/theme/tab_hover_right.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_center.png b/chrome/app/theme/tab_inactive_center.png Binary files differindex 1cb0ce2..50b6826 100644 --- a/chrome/app/theme/tab_inactive_center.png +++ b/chrome/app/theme/tab_inactive_center.png diff --git a/chrome/app/theme/tab_inactive_center_otr.png b/chrome/app/theme/tab_inactive_center_otr.png Binary files differdeleted file mode 100644 index 781635c..0000000 --- a/chrome/app/theme/tab_inactive_center_otr.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_center_v.png b/chrome/app/theme/tab_inactive_center_v.png Binary files differdeleted file mode 100644 index bdc9591..0000000 --- a/chrome/app/theme/tab_inactive_center_v.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_left.png b/chrome/app/theme/tab_inactive_left.png Binary files differindex 31fc0ca..67f0bbc 100644 --- a/chrome/app/theme/tab_inactive_left.png +++ b/chrome/app/theme/tab_inactive_left.png diff --git a/chrome/app/theme/tab_inactive_left_otr.png b/chrome/app/theme/tab_inactive_left_otr.png Binary files differdeleted file mode 100644 index 99c5af5..0000000 --- a/chrome/app/theme/tab_inactive_left_otr.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_left_v.png b/chrome/app/theme/tab_inactive_left_v.png Binary files differdeleted file mode 100644 index cf9477f..0000000 --- a/chrome/app/theme/tab_inactive_left_v.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_right.png b/chrome/app/theme/tab_inactive_right.png Binary files differindex 3fce47d..fae4add 100644 --- a/chrome/app/theme/tab_inactive_right.png +++ b/chrome/app/theme/tab_inactive_right.png diff --git a/chrome/app/theme/tab_inactive_right_otr.png b/chrome/app/theme/tab_inactive_right_otr.png Binary files differdeleted file mode 100644 index 6b5bc26..0000000 --- a/chrome/app/theme/tab_inactive_right_otr.png +++ /dev/null diff --git a/chrome/app/theme/tab_inactive_right_v.png b/chrome/app/theme/tab_inactive_right_v.png Binary files differdeleted file mode 100644 index 82aac4d..0000000 --- a/chrome/app/theme/tab_inactive_right_v.png +++ /dev/null diff --git a/chrome/app/theme/theme_frame_default.png b/chrome/app/theme/theme_frame_default.png Binary files differnew file mode 100644 index 0000000..3f4f7e9 --- /dev/null +++ b/chrome/app/theme/theme_frame_default.png diff --git a/chrome/app/theme/theme_frame_default_inactive.png b/chrome/app/theme/theme_frame_default_inactive.png Binary files differnew file mode 100644 index 0000000..a1eff41 --- /dev/null +++ b/chrome/app/theme/theme_frame_default_inactive.png diff --git a/chrome/app/theme/theme_frame_default_incognito.png b/chrome/app/theme/theme_frame_default_incognito.png Binary files differnew file mode 100644 index 0000000..179ea6c --- /dev/null +++ b/chrome/app/theme/theme_frame_default_incognito.png diff --git a/chrome/app/theme/theme_frame_default_incognito_inactive.png b/chrome/app/theme/theme_frame_default_incognito_inactive.png Binary files differnew file mode 100644 index 0000000..a86b08c --- /dev/null +++ b/chrome/app/theme/theme_frame_default_incognito_inactive.png diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index ee1f619..c89f5db 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -75,9 +75,6 @@ <include name="IDR_TAB_INACTIVE_CENTER" file="tab_inactive_center.png" type="BINDATA" /> <include name="IDR_TAB_INACTIVE_LEFT" file="tab_inactive_left.png" type="BINDATA" /> <include name="IDR_TAB_INACTIVE_RIGHT" file="tab_inactive_right.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_LEFT_OTR" file="tab_inactive_left_otr.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_CENTER_OTR" file="tab_inactive_center_otr.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_RIGHT_OTR" file="tab_inactive_right_otr.png" type="BINDATA" /> <include name="IDR_THROBBER" file="throbber.png" type="BINDATA" /> <include name="IDR_WINDOW_BOTTOM_CENTER" file="window_bottom_center.png" type="BINDATA" /> <include name="IDR_WINDOW_BOTTOM_LEFT_CORNER" file="window_bottom_left_corner.png" type="BINDATA" /> @@ -87,36 +84,9 @@ <include name="IDR_WINDOW_TOP_CENTER" file="window_top_center.png" type="BINDATA" /> <include name="IDR_WINDOW_TOP_LEFT_CORNER" file="window_top_left_corner.png" type="BINDATA" /> <include name="IDR_WINDOW_TOP_RIGHT_CORNER" file="window_top_right_corner.png" type="BINDATA" /> - <include name="IDR_WINDOW_BOTTOM_CENTER_OTR" file="window_bottom_center_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_BOTTOM_LEFT_CORNER_OTR" file="window_bottom_left_corner_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_BOTTOM_RIGHT_CORNER_OTR" file="window_bottom_right_corner_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_LEFT_SIDE_OTR" file="window_left_side_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_RIGHT_SIDE_OTR" file="window_right_side_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_TOP_CENTER_OTR" file="window_top_center_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_TOP_LEFT_CORNER_OTR" file="window_top_left_corner_otr.png" type="BINDATA" /> - <include name="IDR_WINDOW_TOP_RIGHT_CORNER_OTR" file="window_top_right_corner_otr.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_CENTER_V" file="tab_inactive_center_v.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_LEFT_V" file="tab_inactive_left_v.png" type="BINDATA" /> - <include name="IDR_TAB_INACTIVE_RIGHT_V" file="tab_inactive_right_v.png" type="BINDATA" /> <include name="IDR_RESTORE" file="restore.png" type="BINDATA" /> <include name="IDR_RESTORE_H" file="restore_h.png" type="BINDATA" /> <include name="IDR_RESTORE_P" file="restore_p.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_CENTER" file="dewindow_bottom_center.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_LEFT_CORNER" file="dewindow_bottom_left_corner.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_RIGHT_CORNER" file="dewindow_bottom_right_corner.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_LEFT_SIDE" file="dewindow_left_side.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_RIGHT_SIDE" file="dewindow_right_side.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_CENTER" file="dewindow_top_center.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_LEFT_CORNER" file="dewindow_top_left_corner.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_RIGHT_CORNER" file="dewindow_top_right_corner.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_CENTER_OTR" file="dewindow_bottom_center_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_LEFT_CORNER_OTR" file="dewindow_bottom_left_corner_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_BOTTOM_RIGHT_CORNER_OTR" file="dewindow_bottom_right_corner_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_LEFT_SIDE_OTR" file="dewindow_left_side_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_RIGHT_SIDE_OTR" file="dewindow_right_side_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_CENTER_OTR" file="dewindow_top_center_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_LEFT_CORNER_OTR" file="dewindow_top_left_corner_otr.png" type="BINDATA" /> - <include name="IDR_DEWINDOW_TOP_RIGHT_CORNER_OTR" file="dewindow_top_right_corner_otr.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM" file="download_button_center_bottom.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H" file="download_button_center_bottom_h.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P" file="download_button_center_bottom_p.png" type="BINDATA" /> @@ -161,14 +131,6 @@ <include name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="download_progress_background32.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="download_progress_foreground32.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_ICON" file="download_icon.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_BOTTOM_CENTER" file="constrained_bottom_center.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_BOTTOM_LEFT_CORNER" file="constrained_bottom_left_corner.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER" file="constrained_bottom_right_corner.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_LEFT_SIDE" file="constrained_left_side.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_RIGHT_SIDE" file="constrained_right_side.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_TOP_CENTER" file="constrained_top_center.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_TOP_LEFT_CORNER" file="constrained_top_left_corner.png" type="BINDATA" /> - <include name="IDR_CONSTRAINED_TOP_RIGHT_CORNER" file="constrained_top_right_corner.png" type="BINDATA" /> <include name="IDR_FIND_BOX_BACKGROUND" file="find_box_bg.png" type="BINDATA" /> <include name="IDR_FIND_BOX_BACKGROUND_LEFT" file="find_box_bg_left.png" type="BINDATA" /> <include name="IDR_FIND_BOX_BACKGROUND_LEFT_RTL" file="find_box_bg_left_rtl.png" type="BINDATA" /> @@ -292,9 +254,6 @@ <include name="IDR_MENU_PAGE_RTL" file="menu_page_rtl.png" type="BINDATA" /> <include name="IDR_MENU_CHROME_RTL" file="menu_chrome_rtl.png" type="BINDATA" /> <include name="IDR_DOWNLOAD_ANIMATION_BEGIN" file="download_animation_begin.png" type="BINDATA" /> - <include name="IDR_TAB_HOVER_LEFT" file="tab_hover_left.png" type="BINDATA" /> - <include name="IDR_TAB_HOVER_CENTER" file="tab_hover_center.png" type="BINDATA" /> - <include name="IDR_TAB_HOVER_RIGHT" file="tab_hover_right.png" type="BINDATA" /> <include name="IDR_FOLDER_CLOSED_RTL" file="folder_closed_rtl.png" type="BINDATA" /> <include name="IDR_FOLDER_OPEN_RTL" file="folder_open_rtl.png" type="BINDATA" /> <include name="IDR_BOOKMARK_BAR_FOLDER" file="bookmark_bar_folder.png" type="BINDATA" /> @@ -306,6 +265,8 @@ <include name="IDR_BOOKMARK_MANAGER_RECENT_ICON" file="bookmark_manager_recent.png" type="BINDATA" /> <include name="IDR_BOOKMARK_MANAGER_SEARCH_ICON" file="bookmark_manager_search.png" type="BINDATA" /> <include name="IDR_MENU_DROPARROW" file="menu_droparrow.png" type="BINDATA" /> + <include name="IDR_TAB_ALPHA_LEFT" file="tab_alpha_left.png" type="BINDATA" /> + <include name="IDR_TAB_ALPHA_RIGHT" file="tab_alpha_right.png" type="BINDATA" /> <include name="IDR_DOCK_MAX" file="dock_tab_max.png" type="BINDATA" /> <include name="IDR_DOCK_HIGH" file="dock_tab_high.png" type="BINDATA" /> <include name="IDR_DOCK_WIDE" file="dock_tab_wide.png" type="BINDATA" /> @@ -335,6 +296,16 @@ <include name="IDR_O2_STAR_SELECTED_DARK" file="o2_star_selected_dark.png" type="BINDATA" /> <include name="IDR_CLOSED_WINDOW" file="closed_window.png" type="BINDATA" /> + <include name="IDR_THEME_FRAME" file="theme_frame_default.png" type="BINDATA" /> + <include name="IDR_THEME_FRAME_INACTIVE" file="theme_frame_default_inactive.png" type="BINDATA" /> + <include name="IDR_THEME_FRAME_INCOGNITO" file="theme_frame_default_incognito.png" type="BINDATA" /> + <include name="IDR_THEME_FRAME_INCOGNITO_INACTIVE" file="theme_frame_default_incognito_inactive.png" type="BINDATA" /> + <include name="IDR_THEME_TOOLBAR" file="theme_toolbar_default.png" type="BINDATA" /> + <include name="IDR_THEME_TAB_BACKGROUND" file="theme_tab_background.png" type="BINDATA" /> + <include name="IDR_THEME_TAB_BACKGROUND_INCOGNITO" file="theme_tab_background_incognito.png" type="BINDATA" /> + <include name="IDR_THEME_TAB_BACKGROUND_V" file="theme_tab_background_glass.png" type="BINDATA" /> + <include name="IDR_THEME_NEWTAB_BACKGROUND" file="ntp_background.png" type="BINDATA" /> + <if expr="pp_ifdef('_google_chrome')"> <include name="IDR_ABOUT_BACKGROUND" file="google_chrome/about_background.png" type="BINDATA" /> <include name="IDR_ABOUT_BACKGROUND_RTL" file="google_chrome/about_background_rtl.png" type="BINDATA" /> @@ -359,5 +330,11 @@ <include name="IDR_PRODUCT_ICON_32" file="chromium/chromium_icon_32.png" type="BINDATA" /> </if> </includes> + <messages> + <message name="IDS_COLOR_FRAME" use_name_for_id="true">frame</message> + <message name="IDS_COLOR_TOOLBAR" use_name_for_id="true">toolbar</message> + <message name="IDS_COLOR_TEXT_TAB" use_name_for_id="true">text_tab</message> + <message name="IDS_TINT_BUTTONS" use_name_for_id="true">buttons</message> + </messages> </release> </grit> diff --git a/chrome/app/theme/theme_tab_background.png b/chrome/app/theme/theme_tab_background.png Binary files differnew file mode 100644 index 0000000..d043bc3 --- /dev/null +++ b/chrome/app/theme/theme_tab_background.png diff --git a/chrome/app/theme/theme_tab_background_glass.png b/chrome/app/theme/theme_tab_background_glass.png Binary files differnew file mode 100644 index 0000000..df43d6f --- /dev/null +++ b/chrome/app/theme/theme_tab_background_glass.png diff --git a/chrome/app/theme/theme_tab_background_incognito.png b/chrome/app/theme/theme_tab_background_incognito.png Binary files differnew file mode 100644 index 0000000..042c243 --- /dev/null +++ b/chrome/app/theme/theme_tab_background_incognito.png diff --git a/chrome/app/theme/theme_toolbar_default.png b/chrome/app/theme/theme_toolbar_default.png Binary files differnew file mode 100644 index 0000000..21678f8 --- /dev/null +++ b/chrome/app/theme/theme_toolbar_default.png diff --git a/chrome/app/theme/window_bottom_center.png b/chrome/app/theme/window_bottom_center.png Binary files differindex e6a191c..3fb76f1 100644 --- a/chrome/app/theme/window_bottom_center.png +++ b/chrome/app/theme/window_bottom_center.png diff --git a/chrome/app/theme/window_bottom_center_otr.png b/chrome/app/theme/window_bottom_center_otr.png Binary files differdeleted file mode 100644 index 8d6cdb0..0000000 --- a/chrome/app/theme/window_bottom_center_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_bottom_left_corner.png b/chrome/app/theme/window_bottom_left_corner.png Binary files differindex db9cb72..1d3c066 100644 --- a/chrome/app/theme/window_bottom_left_corner.png +++ b/chrome/app/theme/window_bottom_left_corner.png diff --git a/chrome/app/theme/window_bottom_left_corner_otr.png b/chrome/app/theme/window_bottom_left_corner_otr.png Binary files differdeleted file mode 100644 index 803f2b8..0000000 --- a/chrome/app/theme/window_bottom_left_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_bottom_right_corner.png b/chrome/app/theme/window_bottom_right_corner.png Binary files differindex f0522a3..83cf5b9 100644 --- a/chrome/app/theme/window_bottom_right_corner.png +++ b/chrome/app/theme/window_bottom_right_corner.png diff --git a/chrome/app/theme/window_bottom_right_corner_otr.png b/chrome/app/theme/window_bottom_right_corner_otr.png Binary files differdeleted file mode 100644 index b21c63f..0000000 --- a/chrome/app/theme/window_bottom_right_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_left_side.png b/chrome/app/theme/window_left_side.png Binary files differindex d614d2c..2553d1b 100644 --- a/chrome/app/theme/window_left_side.png +++ b/chrome/app/theme/window_left_side.png diff --git a/chrome/app/theme/window_left_side_otr.png b/chrome/app/theme/window_left_side_otr.png Binary files differdeleted file mode 100644 index f632f049..0000000 --- a/chrome/app/theme/window_left_side_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_right_side.png b/chrome/app/theme/window_right_side.png Binary files differindex 97939ef..c89b47b 100644 --- a/chrome/app/theme/window_right_side.png +++ b/chrome/app/theme/window_right_side.png diff --git a/chrome/app/theme/window_right_side_otr.png b/chrome/app/theme/window_right_side_otr.png Binary files differdeleted file mode 100644 index ac6bdc1..0000000 --- a/chrome/app/theme/window_right_side_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_top_center.png b/chrome/app/theme/window_top_center.png Binary files differindex 8e13cc2..e2c393e 100644 --- a/chrome/app/theme/window_top_center.png +++ b/chrome/app/theme/window_top_center.png diff --git a/chrome/app/theme/window_top_center_otr.png b/chrome/app/theme/window_top_center_otr.png Binary files differdeleted file mode 100644 index 49b3ab1..0000000 --- a/chrome/app/theme/window_top_center_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_top_left_corner.png b/chrome/app/theme/window_top_left_corner.png Binary files differindex 89e5f23..4bb52ce 100644 --- a/chrome/app/theme/window_top_left_corner.png +++ b/chrome/app/theme/window_top_left_corner.png diff --git a/chrome/app/theme/window_top_left_corner_otr.png b/chrome/app/theme/window_top_left_corner_otr.png Binary files differdeleted file mode 100644 index 9521ae0b..0000000 --- a/chrome/app/theme/window_top_left_corner_otr.png +++ /dev/null diff --git a/chrome/app/theme/window_top_right_corner.png b/chrome/app/theme/window_top_right_corner.png Binary files differindex 60686b3..d1da9ca 100644 --- a/chrome/app/theme/window_top_right_corner.png +++ b/chrome/app/theme/window_top_right_corner.png diff --git a/chrome/app/theme/window_top_right_corner_otr.png b/chrome/app/theme/window_top_right_corner_otr.png Binary files differdeleted file mode 100644 index 0b05ca1..0000000 --- a/chrome/app/theme/window_top_right_corner_otr.png +++ /dev/null diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 91e7a36..7642876 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -290,6 +290,14 @@ > </File> <File + RelativePath=".\browser_theme_provider.cc" + > + </File> + <File + RelativePath=".\browser_theme_provider.h" + > + </File> + <File RelativePath=".\browser_url_handler.cc" > </File> @@ -1542,6 +1550,14 @@ > </File> <File + RelativePath=".\dom_ui\dom_ui_theme_source.cc" + > + </File> + <File + RelativePath=".\dom_ui\dom_ui_theme_source.h" + > + </File> + <File RelativePath=".\dom_ui\dom_ui_thumbnail_source.cc" > </File> diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index fa6a00a..5488ef6 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/first_run.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/profile.h" diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc new file mode 100644 index 0000000..cb68ed0c --- /dev/null +++ b/chrome/browser/browser_theme_provider.cc @@ -0,0 +1,527 @@ +// Copyright (c) 2009 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 "browser_theme_provider.h" + +#include "base/gfx/png_decoder.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/extensions/extension.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/theme_resources_util.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "grit/theme_resources.h" +#include "net/base/file_stream.h" +#include "net/base/net_errors.h" +#include "skia/ext/image_operations.h" +#include "skia/ext/skia_utils.h" +#include "SkBitmap.h" + +// Strings used by themes to identify colors for different parts of our UI. +static const std::string kColorFrame = "frame"; +static const std::string kColorFrameInactive = "frame_inactive"; +static const std::string kColorFrameIncognito = "frame_incognito"; +static const std::string kColorFrameIncognitoInactive = + "frame_incognito_inactive"; +static const std::string kColorToolbar = "toolbar"; +static const std::string kColorTabText = "tab_text"; +static const std::string kColorBackgroundTabText = "background_tab_text"; +static const std::string kColorBookmarkText = "bookmark_text"; +static const std::string kColorNTPText = "ntp_text"; +static const std::string kColorNTPLink = "ntp_link"; +static const std::string kColorNTPSection = "ntp_section"; + +// Strings used by themes to identify tints to apply to different parts of +// our UI. The frame tints apply to the frame color and produce the +// COLOR_FRAME* colors. +static const std::string kTintButtons = "buttons"; +static const std::string kTintFrame = "frame"; +static const std::string kTintFrameInactive = "frame_inactive"; +static const std::string kTintFrameIncognito = "frame_incognito"; +static const std::string kTintFrameIncognitoInactive = + "frame_incognito_inactive"; +static const std::string kTintBackgroundTab = "background_tab"; + +// Default colors. +static const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217); +static const SkColor kDefaultColorFrameInactive = SkColorSetRGB(152, 188, 233); +static const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139); +static const SkColor kDefaultColorFrameIncognitoInactive = + SkColorSetRGB(126, 139, 156); +static const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246); +static const SkColor kDefaultColorTabText = SkColorSetRGB(0, 0, 0); +static const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64); + +// Default tints. +static const skia::HSL kDefaultTintButtons = { -1, -1, -1 }; +static const skia::HSL kDefaultTintFrame = { -1, -1, -1 }; +static const skia::HSL kDefaultTintFrameInactive = { -1, 0.5f, 0.72f }; +static const skia::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f }; +static const skia::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f }; +static const skia::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 }; + +// The image resources that will be tinted by the 'button' tint value. +static const int kToolbarButtonIDs[] = { + IDR_BACK, IDR_BACK_D, IDR_BACK_H, IDR_BACK_P, + IDR_FORWARD, IDR_FORWARD_D, IDR_FORWARD_H, IDR_FORWARD_P, + IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P, + IDR_HOME, IDR_HOME_H, IDR_HOME_P, + IDR_STAR, IDR_STAR_D, IDR_STAR_H, IDR_STAR_P, + IDR_STARRED, IDR_STARRED_H, IDR_STARRED_P, + IDR_GO, IDR_GO_H, IDR_GO_P, + IDR_STOP, IDR_STOP_H, IDR_STOP_P, + IDR_MENU_PAGE, IDR_MENU_PAGE_RTL, + IDR_MENU_CHROME, IDR_MENU_CHROME_RTL, + IDR_MENU_DROPARROW, + IDR_THROBBER, +}; + +// A map for kToolbarButtonIDs. +static std::map<const int, bool> button_images_; + +// A map of frame image IDs to the tints for those ids. +static std::map<const int, int> frame_tints_; + +BrowserThemeProvider::BrowserThemeProvider() + : rb_(ResourceBundle::GetSharedInstance()) { + static bool initialized = false; + if (!initialized) { + for (int i = 0; i < sizeof(kToolbarButtonIDs); ++i) { + button_images_[kToolbarButtonIDs[i]] = true; + } + frame_tints_[IDR_THEME_FRAME] = TINT_FRAME; + frame_tints_[IDR_THEME_FRAME_INACTIVE] = TINT_FRAME_INACTIVE; + frame_tints_[IDR_THEME_FRAME_INCOGNITO] = TINT_FRAME_INCOGNITO; + frame_tints_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] = + TINT_FRAME_INCOGNITO_INACTIVE; + } +} + +BrowserThemeProvider::~BrowserThemeProvider() { } + +void BrowserThemeProvider::Init(Profile* profile) { + profile_ = profile; + LoadThemePrefs(); +} + +SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) { + // Check to see if we already have the Skia image in the cache. + ImageCache::const_iterator found = image_cache_.find(id); + if (found != image_cache_.end()) + return found->second; + + scoped_ptr<SkBitmap> result; + + // Try to load the image from the extension. + result.reset(LoadThemeBitmap(id)); + + // If the extension doesn't provide the requested image, but has provided + // a custom frame, then we may be able to generate the image required. + if (!result.get()) + result.reset(GenerateBitmap(id)); + + // If we still don't have an image, load it from resourcebundle. + if (!result.get()) + result.reset(rb_.GetBitmapNamed(id)); + + // If the requested image is part of the toolbar button set, and we have + // a provided tint for that set, tint it appropriately. + if (button_images_.count(id) && tints_.count(kTintButtons)) { + SkBitmap* tinted = + new SkBitmap(TintBitmap(*result.release(), TINT_BUTTONS)); + result.reset(tinted); + } + + if (result.get()) { + // We loaded successfully. Cache the bitmap. + image_cache_[id] = result.get(); + return result.release(); + } else { + NOTREACHED() << "Failed to load a requested image"; + return NULL; + } +} + +SkColor BrowserThemeProvider::GetColor(int id) { + // TODO(glen): Figure out if we need to tint these. http://crbug.com/11578 + switch (id) { + case COLOR_FRAME: + return (colors_.find(kColorFrame) != colors_.end()) ? + colors_[kColorFrame] : kDefaultColorFrame; + case COLOR_FRAME_INACTIVE: + return (colors_.find(kColorFrameInactive) != colors_.end()) ? + colors_[kColorFrameInactive] : kDefaultColorFrameInactive; + case COLOR_FRAME_INCOGNITO: + return (colors_.find(kColorFrameIncognito) != colors_.end()) ? + colors_[kColorFrameIncognito] : kDefaultColorFrameIncognito; + case COLOR_FRAME_INCOGNITO_INACTIVE: + return (colors_.find(kColorFrameIncognitoInactive) != colors_.end()) ? + colors_[kColorFrameIncognitoInactive] : + kDefaultColorFrameIncognitoInactive; + case COLOR_TOOLBAR: + return (colors_.find(kColorToolbar) != colors_.end()) ? + colors_[kColorToolbar] : kDefaultColorToolbar; + case COLOR_TAB_TEXT: + return (colors_.find(kColorTabText) != colors_.end()) ? + colors_[kColorTabText] : kDefaultColorTabText; + case COLOR_BACKGROUND_TAB_TEXT: + return (colors_.find(kColorBackgroundTabText) != colors_.end()) ? + colors_[kColorBackgroundTabText] : + kDefaultColorBackgroundTabText; + default: + NOTREACHED() << "Unknown color requested"; + } + + // Return a debugging red color. + return 0xffff0000; +} + +void BrowserThemeProvider::SetTheme(Extension* extension) { + // Clear our image cache. + image_cache_.clear(); + + DCHECK(extension); + DCHECK(extension->IsTheme()); + SetImageData(extension->GetThemeImages(), + extension->path()); + SetColorData(extension->GetThemeColors()); + SetTintData(extension->GetThemeTints()); + GenerateFrameColors(); + GenerateFrameImages(); + + SaveImageData(extension->GetThemeImages()); + SaveColorData(); + SaveTintData(); + + NotifyThemeChanged(); + UserMetrics::RecordAction(L"Themes_Installed", profile_); +} + +void BrowserThemeProvider::UseDefaultTheme() { + // Clear our image cache. + image_cache_.clear(); + + images_.clear(); + colors_.clear(); + tints_.clear(); + + SaveImageData(NULL); + SaveColorData(); + SaveTintData(); + + NotifyThemeChanged(); +} + +SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) { + // Attempt to find the image in our theme bundle. + std::vector<unsigned char> raw_data, png_data; + if (images_.count(id)) { + // First check to see if we have a registered theme extension and whether + // it can handle this resource. + FilePath path = FilePath(UTF8ToWide(images_[id])); + if (!path.empty()) { + net::FileStream file; + int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; + if (file.Open(path, flags) == net::OK) { + int64 avail = file.Available(); + if (avail > 0 && avail < INT_MAX) { + size_t size = static_cast<size_t>(avail); + raw_data.resize(size); + char* data = reinterpret_cast<char*>(&(raw_data.front())); + if (file.ReadUntilComplete(data, size) == avail) { + // Decode the PNG. + int image_width = 0; + int image_height = 0; + + if (!PNGDecoder::Decode(&raw_data.front(), raw_data.size(), + PNGDecoder::FORMAT_BGRA, &png_data, + &image_width, &image_height)) { + NOTREACHED() << "Unable to decode theme image resource " << id; + return NULL; + } + + return PNGDecoder::CreateSkBitmapFromBGRAFormat(png_data, + image_width, + image_height); + } + } + } else { + // TODO(glen): File no-longer exists, we're out of date. We should + // clear the theme (or maybe just the pref that points to this + // image). + return NULL; + } + } + } + + return NULL; +} + +skia::HSL BrowserThemeProvider::GetTint(int id) { + switch (id) { + case TINT_FRAME: + return (tints_.find(kTintFrame) != tints_.end()) ? + tints_[kTintFrame] : kDefaultTintFrame; + case TINT_FRAME_INACTIVE: + return (tints_.find(kTintFrameInactive) != tints_.end()) ? + tints_[kTintFrameInactive] : kDefaultTintFrameInactive; + case TINT_FRAME_INCOGNITO: + return (tints_.count(kTintFrameIncognito)) ? + tints_[kTintFrameIncognito] : kDefaultTintFrameIncognito; + case TINT_FRAME_INCOGNITO_INACTIVE: + return (tints_.count(kTintFrameIncognitoInactive)) ? + tints_[kTintFrameIncognitoInactive] : + kDefaultTintFrameIncognitoInactive; + case TINT_BUTTONS: + return (tints_.find(kTintButtons) != tints_.end()) ? + tints_[kTintButtons] : + kDefaultTintButtons; + case TINT_BACKGROUND_TAB: + return (tints_.find(kTintBackgroundTab) != tints_.end()) ? + tints_[kTintBackgroundTab] : + kDefaultTintBackgroundTab; + default: + NOTREACHED() << "Unknown tint requested"; + } + skia::HSL result = {-1, -1, -1}; + return result; +} + +SkBitmap BrowserThemeProvider::TintBitmap(const SkBitmap& bitmap, int hsl_id) { + return skia::ImageOperations::CreateHSLShiftedBitmap(bitmap, GetTint(hsl_id)); +} + +void BrowserThemeProvider::SetImageData(DictionaryValue* images_value, + FilePath images_path) { + images_.clear(); + + if (images_value) { + DictionaryValue::key_iterator iter = images_value->begin_keys(); + while (iter != images_value->end_keys()) { + std::string val; + if (images_value->GetString(*iter, &val)) { + int id = ThemeResourcesUtil::GetId(WideToUTF8(*iter)); + if (id != -1) { + if (!images_path.empty()) { + images_[id] = WideToUTF8(images_path.AppendASCII(val) + .ToWStringHack()); + } else { + images_[id] = val; + } + } + } + ++iter; + } + } +} + +void BrowserThemeProvider::SetColorData(DictionaryValue* colors_value) { + colors_.clear(); + + if (colors_value) { + DictionaryValue::key_iterator iter = colors_value->begin_keys(); + while (iter != colors_value->end_keys()) { + ListValue* color_list; + if (colors_value->GetList(*iter, &color_list) && + color_list->GetSize() == 3) { + int r, g, b; + color_list->GetInteger(0, &r); + color_list->GetInteger(1, &g); + color_list->GetInteger(2, &b); + colors_[WideToUTF8(*iter)] = SkColorSetRGB(r, g, b); + } + ++iter; + } + } +} + +void BrowserThemeProvider::SetTintData(DictionaryValue* tints_value) { + tints_.clear(); + + if (tints_value) { + DictionaryValue::key_iterator iter = tints_value->begin_keys(); + while (iter != tints_value->end_keys()) { + ListValue* tint_list; + if (tints_value->GetList(*iter, &tint_list) && + tint_list->GetSize() == 3) { + skia::HSL hsl = { -1, -1, -1 }; + // TODO(glen): Make this work with integer values. + tint_list->GetReal(0, &hsl.h); + tint_list->GetReal(1, &hsl.s); + tint_list->GetReal(2, &hsl.l); + tints_[WideToUTF8(*iter)] = hsl; + } + ++iter; + } + } +} + +void BrowserThemeProvider::GenerateFrameColors() { + // Generate any secondary frame colors that weren't provided. + skia::HSL frame_hsl = { 0, 0, 0 }; + skia::SkColorToHSL(GetColor(COLOR_FRAME), frame_hsl); + + if (colors_.find(kColorFrame) == colors_.end()) + colors_[kColorFrame] = HSLShift(frame_hsl, GetTint(TINT_FRAME)); + if (colors_.find(kColorFrameInactive) == colors_.end()) { + colors_[kColorFrameInactive] = + HSLShift(frame_hsl, GetTint(TINT_FRAME_INACTIVE)); + } + if (colors_.find(kColorFrameIncognito) == colors_.end()) { + colors_[kColorFrameIncognito] = + HSLShift(frame_hsl, GetTint(TINT_FRAME_INCOGNITO)); + } + if (colors_.find(kColorFrameIncognitoInactive) == colors_.end()) { + colors_[kColorFrameIncognitoInactive] = + HSLShift(frame_hsl, GetTint(TINT_FRAME_INCOGNITO_INACTIVE)); + } +} + +void BrowserThemeProvider::GenerateFrameImages() { + std::map<const int, int>::iterator iter = frame_tints_.begin(); + while (iter != frame_tints_.end()) { + int id = iter->first; + SkBitmap* frame; + // If there's no frame image provided for the specified id, then load + // the default provided frame. If that's not provided, skip this whole + // thing and just use the default images. + int base_id = (id == IDR_THEME_FRAME_INCOGNITO || + id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) ? + IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME; + + if (images_.find(id) != images_.end()) { + frame = LoadThemeBitmap(id); + } else if (base_id != id && images_.find(base_id) != images_.end()) { + frame = LoadThemeBitmap(base_id); + } else { + if (id == IDR_THEME_FRAME_INCOGNITO || + id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) + frame = rb_.GetBitmapNamed(IDR_THEME_FRAME_INCOGNITO); + else + frame = rb_.GetBitmapNamed(IDR_THEME_FRAME); + } + + if (frame) { + SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, frame_tints_[id])); + image_cache_[id] = tinted; + } + ++iter; + } +} + +SkBitmap* BrowserThemeProvider::GenerateBitmap(int id) { + if (id == IDR_THEME_TAB_BACKGROUND || + id == IDR_THEME_TAB_BACKGROUND_INCOGNITO) { + // The requested image is a background tab. Get a frame to create the + // tab against. As themes don't use the glass frame, we don't have to + // worry about compositing them together, as our default theme provides + // the necessary bitmaps. + SkBitmap* frame; + if (id == IDR_THEME_TAB_BACKGROUND) + frame = image_cache_.find(IDR_THEME_FRAME)->second; + else + frame = image_cache_.find(IDR_THEME_FRAME_INCOGNITO)->second; + + if (frame) { + SkBitmap blurred = + skia::ImageOperations::CreateBlurredBitmap(*frame, 5); + SkBitmap* bg_tab = + new SkBitmap(TintBitmap(blurred, TINT_BACKGROUND_TAB)); + return bg_tab; + } + } + + return NULL; +} + +void BrowserThemeProvider::NotifyThemeChanged() { + // TODO(glen): If we're in glass and IDR_THEME_FRAME has been provided, + // swap us back to opaque frame. + + // Redraw! + for (BrowserList::const_iterator browser = BrowserList::begin(); + browser != BrowserList::end(); ++browser) { + (*browser)->window()->UserChangedTheme(); + } +} + +void BrowserThemeProvider::LoadThemePrefs() { + PrefService* prefs = profile_->GetPrefs(); + + // Our prefs already have the extension path baked in, so we don't need + // to provide it. + SetImageData(prefs->GetMutableDictionary(prefs::kCurrentThemeImages), + FilePath()); + SetColorData(prefs->GetMutableDictionary(prefs::kCurrentThemeColors)); + SetTintData(prefs->GetMutableDictionary(prefs::kCurrentThemeTints)); + GenerateFrameColors(); + GenerateFrameImages(); + + // TODO(glen): Figure out if any custom prefs were loaded, and if so + // UMA-log the fact that a theme was loaded. + if (prefs->HasPrefPath(prefs::kCurrentThemeImages) || + prefs->HasPrefPath(prefs::kCurrentThemeColors) || + prefs->HasPrefPath(prefs::kCurrentThemeTints)) { + UserMetrics::RecordAction(L"Themes_loaded", profile_); + } +} + +void BrowserThemeProvider::SaveImageData(DictionaryValue* images_value) { + // Save our images data. + DictionaryValue* pref_images = + profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages); + pref_images->Clear(); + + DictionaryValue::key_iterator iter = images_value->begin_keys(); + while (iter != images_value->end_keys()) { + std::string val; + if (images_value->GetString(*iter, &val)) { + int id = ThemeResourcesUtil::GetId(WideToUTF8(*iter)); + if (id != -1) + pref_images->SetString(*iter, images_[id]); + } + ++iter; + } +} + +void BrowserThemeProvider::SaveColorData() { + // Save our color data. + DictionaryValue* pref_colors = + profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeColors); + pref_colors->Clear(); + if (colors_.size()) { + ColorMap::iterator iter = colors_.begin(); + while (iter != colors_.end()) { + SkColor rgb = (*iter).second; + ListValue* rgb_list = new ListValue(); + rgb_list->Set(0, Value::CreateIntegerValue(SkColorGetR(rgb))); + rgb_list->Set(1, Value::CreateIntegerValue(SkColorGetG(rgb))); + rgb_list->Set(2, Value::CreateIntegerValue(SkColorGetB(rgb))); + pref_colors->Set(UTF8ToWide((*iter).first), rgb_list); + ++iter; + } + } +} + +void BrowserThemeProvider::SaveTintData() { + // Save our tint data. + DictionaryValue* pref_tints = + profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeTints); + pref_tints->Clear(); + if (tints_.size()) { + TintMap::iterator iter = tints_.begin(); + while (iter != tints_.end()) { + skia::HSL hsl = (*iter).second; + ListValue* hsl_list = new ListValue(); + hsl_list->Set(0, Value::CreateRealValue(hsl.h)); + hsl_list->Set(1, Value::CreateRealValue(hsl.s)); + hsl_list->Set(2, Value::CreateRealValue(hsl.l)); + pref_tints->Set(UTF8ToWide((*iter).first), hsl_list); + ++iter; + } + } +} diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h new file mode 100644 index 0000000..bf16a0d --- /dev/null +++ b/chrome/browser/browser_theme_provider.h @@ -0,0 +1,125 @@ +// Copyright (c) 2009 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 CHROME_BROWSER_THEME_PROVIDER_H_ +#define CHROME_BROWSER_THEME_PROVIDER_H_ + +#include "app/resource_bundle.h" +#include "app/theme_provider.h" +#include "base/ref_counted.h" +#include "skia/ext/skia_utils.h" + +class Extension; +class Profile; +class DictionaryValue; + +class BrowserThemeProvider : + public base::RefCountedThreadSafe<BrowserThemeProvider>, + public ThemeProvider { + public: + BrowserThemeProvider(); + virtual ~BrowserThemeProvider(); + + enum { + COLOR_FRAME, + COLOR_FRAME_INACTIVE, + COLOR_FRAME_INCOGNITO, + COLOR_FRAME_INCOGNITO_INACTIVE, + COLOR_TOOLBAR, + COLOR_TAB_TEXT, + COLOR_BACKGROUND_TAB_TEXT, + COLOR_BOOKMARK_TEXT, + COLOR_NTP_TEXT, + COLOR_NTP_LINK, + COLOR_NTP_SECTION, + TINT_BUTTONS, + TINT_FRAME, + TINT_FRAME_INACTIVE, + TINT_FRAME_INCOGNITO, + TINT_FRAME_INCOGNITO_INACTIVE, + TINT_BACKGROUND_TAB + }; + + void Init(Profile* profile); + + // ThemeProvider implementation. + virtual SkBitmap* GetBitmapNamed(int id); + virtual SkColor GetColor(int id); + + // Set the current theme to the theme defined in |extension|. + void SetTheme(Extension* extension); + + // Reset the theme to default. + void UseDefaultTheme(); + + private: + typedef std::map<const int, std::string> ImageMap; + typedef std::map<const std::string, SkColor> ColorMap; + typedef std::map<const std::string, skia::HSL> TintMap; + + // Loads a bitmap from the theme, which may be tinted or + // otherwise modified, or an application default. + SkBitmap* LoadThemeBitmap(int id); + + // Get the specified tint - |id| is one of the TINT_* enum values. + skia::HSL GetTint(int id); + + // Tint |bitmap| with the tint specified by |hsl_id| + SkBitmap TintBitmap(const SkBitmap& bitmap, int hsl_id); + + // The following load data from specified dictionaries (either from + // preferences or from an extension manifest) and update our theme + // data appropriately. + // Allow any ResourceBundle image to be overridden. |images| should + // contain keys defined in ThemeResourceMap, and values as paths to + // the images on-disk. + void SetImageData(DictionaryValue* images, + FilePath images_path); + // Set our theme colors. The keys of |colors| are any of the kColor* + // constants, and the values are a three-item list containing 8-bit + // RGB values. + void SetColorData(DictionaryValue* colors); + // Set tint data for our images and colors. The keys of |tints| are + // any of the kTint* contstants, and the values are a three-item list + // containing real numbers in the range 0-1 (and -1 for 'null'). + void SetTintData(DictionaryValue* tints); + + // Generate any frame colors that weren't specified. + void GenerateFrameColors(); + + // Generate any frame images that weren't specified. The resulting images + // will be stored in our cache. + void GenerateFrameImages(); + + // Create any images that aren't pregenerated (e.g. background tab images). + SkBitmap* GenerateBitmap(int id); + + // Save our data - when saving images we need the original dictionary + // from the extension because it contains the text ids that we want to save. + void SaveImageData(DictionaryValue* images); + void SaveColorData(); + void SaveTintData(); + + // Let all the browser views know that themes have changed. + void NotifyThemeChanged(); + + // Load theme data from preferences. + void LoadThemePrefs(); + + // Cached images. We cache all retrieved and generated bitmaps and keep + // track of the pointers. + typedef std::map<int, SkBitmap*> ImageCache; + ImageCache image_cache_; + + ResourceBundle& rb_; + Profile* profile_; + + ImageMap images_; + ColorMap colors_; + TintMap tints_; + + DISALLOW_COPY_AND_ASSIGN(BrowserThemeProvider); +}; + +#endif // CHROME_BROWSER_THEME_PROVIDER_H_ diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h index 440c66d..c5e2027 100644 --- a/chrome/browser/browser_window.h +++ b/chrome/browser/browser_window.h @@ -176,6 +176,10 @@ class BrowserWindow { virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate, void* parent_window) = 0; + // BrowserThemeProvider calls this when a user has changed his or her theme, + // indicating that it's time to redraw everything. + virtual void UserChangedTheme() = 0; + // Construct a BrowserWindow implementation for the specified |browser|. static BrowserWindow* CreateBrowserWindow(Browser* browser); diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc index f8e0405..ff49039 100644 --- a/chrome/browser/dom_ui/dom_ui.cc +++ b/chrome/browser/dom_ui/dom_ui.cc @@ -10,7 +10,10 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/values.h" +#include "base/win_util.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" DOMUI::DOMUI(TabContents* contents) : hide_favicon_(false), @@ -79,6 +82,10 @@ void DOMUI::CallJavascriptFunction( ExecuteJavascript(javascript); } +ThemeProvider* DOMUI::GetThemeProvider() const { + return tab_contents_->profile()->GetThemeProvider(); +} + void DOMUI::RegisterMessageCallback(const std::string &message, MessageCallback *callback) { message_callbacks_.insert(std::make_pair(message, callback)); diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h index 3c2dc16..fadff05 100644 --- a/chrome/browser/dom_ui/dom_ui.h +++ b/chrome/browser/dom_ui/dom_ui.h @@ -21,6 +21,7 @@ class Profile; class RenderViewHost; class Value; class TabContents; +class ThemeProvider; // A DOMUI sets up the datasources and message handlers for a given HTML-based // UI. It is contained by a DOMUIManager. @@ -44,7 +45,7 @@ class DOMUI { bool hide_favicon() const { return hide_favicon_; } - + // Returns true if the bookmark bar should be forced to being visible, // overriding the user's preference. bool force_bookmark_bar_visible() const { @@ -89,6 +90,8 @@ class DOMUI { const Value& arg1, const Value& arg2); + ThemeProvider* GetThemeProvider() const; + TabContents* tab_contents() { return tab_contents_; } Profile* GetProfile(); diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.cc b/chrome/browser/dom_ui/dom_ui_theme_source.cc new file mode 100644 index 0000000..31ff1f8 --- /dev/null +++ b/chrome/browser/dom_ui/dom_ui_theme_source.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2009 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 "chrome/browser/dom_ui/dom_ui_theme_source.h" + +#include "app/resource_bundle.h" +#include "app/theme_provider.h" +#include "base/gfx/png_encoder.h" +#include "base/message_loop.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/theme_resources_util.h" +#include "chrome/common/url_constants.h" +#include "grit/theme_resources.h" + +DOMUIThemeSource::DOMUIThemeSource(Profile* profile) + : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()), + profile_(profile) { +} + +void DOMUIThemeSource::StartDataRequest(const std::string& path, + int request_id) { + ThemeProvider* tp = profile_->GetThemeProvider(); + if (tp) { + int id = ThemeResourcesUtil::GetId(path); + if (id != -1) { + SkBitmap* image = tp->GetBitmapNamed(id); + if (image) { + std::vector<unsigned char> png_bytes; + PNGEncoder::EncodeBGRASkBitmap(*image, false, &png_bytes); + + scoped_refptr<RefCountedBytes> image_data = new RefCountedBytes(png_bytes); + SendResponse(request_id, image_data); + } + } + } +} diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.h b/chrome/browser/dom_ui/dom_ui_theme_source.h new file mode 100644 index 0000000..279042d --- /dev/null +++ b/chrome/browser/dom_ui/dom_ui_theme_source.h @@ -0,0 +1,30 @@ +// Copyright (c) 2009 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 CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_ +#define CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_ + +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" + +class Profile; + +// ThumbnailSource is the gateway between network-level chrome: +// requests for thumbnails and the history backend that serves these. +class DOMUIThemeSource : public ChromeURLDataManager::DataSource { +public: + explicit DOMUIThemeSource(Profile* profile); + + // Called when the network layer has requested a resource underneath + // the path we registered. + virtual void StartDataRequest(const std::string& path, int request_id); + virtual std::string GetMimeType(const std::string& path) const { + return "image/png"; + } + +private: + Profile* profile_; + DISALLOW_COPY_AND_ASSIGN(DOMUIThemeSource); +}; + +#endif // CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_ diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index d4bdf97..b13fbb2 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -16,6 +16,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/dom_ui/dom_ui_favicon_source.h" #include "chrome/browser/dom_ui/dom_ui_thumbnail_source.h" +#include "chrome/browser/dom_ui/dom_ui_theme_source.h" #include "chrome/browser/dom_ui/history_ui.h" #include "chrome/browser/history/page_usage_data.h" #include "chrome/browser/metrics/user_metrics.h" @@ -1165,6 +1166,11 @@ NewTabUI::NewTabUI(TabContents* contents) // In testing mode there may not be an I/O thread. if (g_browser_process->io_thread()) { + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(&chrome_url_data_manager, + &ChromeURLDataManager::AddDataSource, + new DOMUIThemeSource(GetProfile()))); + NewTabHTMLSource* html_source = new NewTabHTMLSource(); g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(&chrome_url_data_manager, diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc index 0f9c24e..e1533db6 100644 --- a/chrome/browser/extensions/extension.cc +++ b/chrome/browser/extensions/extension.cc @@ -30,6 +30,9 @@ const wchar_t* Extension::kPluginsDirKey = L"plugins_dir"; const wchar_t* Extension::kBackgroundKey = L"background_page"; const wchar_t* Extension::kRunAtKey = L"run_at"; const wchar_t* Extension::kThemeKey = L"theme"; +const wchar_t* Extension::kThemeImagesKey = L"images"; +const wchar_t* Extension::kThemeColorsKey = L"colors"; +const wchar_t* Extension::kThemeTintsKey = L"tints"; const wchar_t* Extension::kToolstripsKey = L"toolstrips"; const wchar_t* Extension::kTooltipKey = L"tooltip"; const wchar_t* Extension::kTypeKey = L"type"; @@ -110,6 +113,16 @@ const char* Extension::kMissingFileError = "At least one js or css file is required for 'content_scripts[*]'."; const char* Extension::kMissingPageActionIcon = "Unable to find 'page_actions[*].icon'"; +const char* Extension::kInvalidThemeError = + "Invalid value for 'theme'."; +const char* Extension::kInvalidThemeImagesError = + "Invalid value for theme images - images must be strings."; +const char* Extension::kInvalidThemeImagesMissingError = + "Am image specified in the theme is missing."; +const char* Extension::kInvalidThemeColorsError = + "Invalid value for theme colors - colors must be integers"; +const char* Extension::kInvalidThemeTintsError = + "Invalid value for theme images - tints must be decimal numbers."; const size_t Extension::kIdSize = 20; // SHA1 (160 bits) == 20 bytes @@ -124,7 +137,10 @@ Extension::Extension(const Extension& rhs) page_actions_(rhs.page_actions_), plugins_dir_(rhs.plugins_dir_), zip_hash_(rhs.zip_hash_), - theme_paths_(rhs.theme_paths_) { + theme_images_(rhs.theme_images_), + theme_colors_(rhs.theme_colors_), + theme_tints_(rhs.theme_tints_), + is_theme_(rhs.is_theme_) { } Extension::~Extension() { @@ -149,14 +165,6 @@ GURL Extension::GetResourceURL(const GURL& extension_url, return ret_val; } -FilePath Extension::GetThemeResourcePath(const int resource_id) { - std::wstring id = IntToWString(resource_id); - std::string path = theme_paths_[id]; - if (path.size()) - return path_.AppendASCII(path.c_str()); - return FilePath(); -} - const PageAction* Extension::GetPageAction(std::string id) const { PageActionMap::const_iterator it = page_actions_.find(id); if (it == page_actions_.end()) @@ -500,6 +508,81 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, } } + // Initialize themes. If a theme is included, no other items may be processed + // (we currently don't want people bundling themes and extension stuff + // together). + // + // TODO(glen): Error if other items *are* included. + is_theme_ = false; + if (source.HasKey(kThemeKey)) { + DictionaryValue* theme_value; + if (!source.GetDictionary(kThemeKey, &theme_value)) { + *error = kInvalidThemeError; + return false; + } + is_theme_ = true; + + theme_images_ = new DictionaryValue; + DictionaryValue* images_value; + if (theme_value->GetDictionary(kThemeImagesKey, &images_value)) { + // Validate that the images are all strings + DictionaryValue::key_iterator iter = images_value->begin_keys(); + while (iter != images_value->end_keys()) { + std::string val; + if (!images_value->GetString(*iter, &val)) { + *error = kInvalidThemeImagesError; + return false; + } + ++iter; + } + theme_images_ = static_cast<DictionaryValue*>(images_value->DeepCopy()); + } + + theme_colors_ = new DictionaryValue; + DictionaryValue* colors_value; + if (theme_value->GetDictionary(kThemeColorsKey, &colors_value)) { + // Validate that the colors are all three-item lists + DictionaryValue::key_iterator iter = colors_value->begin_keys(); + while (iter != colors_value->end_keys()) { + std::string val; + int color = 0; + ListValue* color_list; + if (!colors_value->GetList(*iter, &color_list) || + color_list->GetSize() != 3 || + !color_list->GetInteger(0, &color) || + !color_list->GetInteger(1, &color) || + !color_list->GetInteger(2, &color)) { + *error = kInvalidThemeColorsError; + return false; + } + ++iter; + } + theme_colors_ = static_cast<DictionaryValue*>(colors_value->DeepCopy()); + } + + theme_tints_ = new DictionaryValue; + DictionaryValue* tints_value; + if (theme_value->GetDictionary(kThemeTintsKey, &tints_value)) { + // Validate that the tints are all reals. + DictionaryValue::key_iterator iter = tints_value->begin_keys(); + while (iter != tints_value->end_keys()) { + ListValue* tint_list; + double hue = 0; + if (!tints_value->GetList(*iter, &tint_list) && + tint_list->GetSize() != 3 || + !tint_list->GetReal(0, &hue) || + !tint_list->GetReal(1, &hue) || + !tint_list->GetReal(2, &hue)) { + *error = kInvalidThemeTintsError; + return false; + } + ++iter; + } + theme_tints_ = static_cast<DictionaryValue*>(tints_value->DeepCopy()); + } + return true; + } + // Initialize plugins dir (optional). if (source.HasKey(kPluginsDirKey)) { std::string plugins_dir; @@ -538,22 +621,6 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, } } - if (source.HasKey(kThemeKey)) { - DictionaryValue* dict_value; - if (source.GetDictionary(kThemeKey, &dict_value)) { - DictionaryValue::key_iterator iter = dict_value->begin_keys(); - while (iter != dict_value->end_keys()) { - std::string val; - if (dict_value->GetString(*iter, &val)) { - std::wstring id = *iter; - theme_paths_[id] = val; - } - ++iter; - } - ResourceBundle::GetSharedInstance().SetThemeExtension(*this); - } - } - // Initialize content scripts (optional). if (source.HasKey(kContentScriptsKey)) { ListValue* list_value; diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h index c612203..4e19c9a 100644 --- a/chrome/browser/extensions/extension.h +++ b/chrome/browser/extensions/extension.h @@ -18,6 +18,7 @@ #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/page_action.h" #include "googleurl/src/gurl.h" +#include "SkColor.h" // Represents a Chromium extension. class Extension { @@ -45,6 +46,9 @@ class Extension { static const wchar_t* kBackgroundKey; static const wchar_t* kRunAtKey; static const wchar_t* kThemeKey; + static const wchar_t* kThemeImagesKey; + static const wchar_t* kThemeColorsKey; + static const wchar_t* kThemeTintsKey; static const wchar_t* kToolstripsKey; static const wchar_t* kTooltipKey; static const wchar_t* kTypeKey; @@ -87,6 +91,11 @@ class Extension { static const char* kInvalidPermissionError; static const char* kInvalidPermissionSchemeError; static const char* kInvalidZipHashError; + static const char* kInvalidThemeError; + static const char* kInvalidThemeImagesMissingError; + static const char* kInvalidThemeImagesError; + static const char* kInvalidThemeColorsError; + static const char* kInvalidThemeTintsError; static const char* kMissingFileError; static const char* kMissingPageActionIcon; @@ -115,19 +124,17 @@ class Extension { return GetResourcePath(path(), relative_path); } + DictionaryValue* GetThemeImages() { return theme_images_; } + DictionaryValue* GetThemeColors() { return theme_colors_; } + DictionaryValue* GetThemeTints() { return theme_tints_; } + bool IsTheme() { return is_theme_; } + // Initialize the extension from a parsed manifest. // If |require_id| is true, will return an error if the "id" key is missing // from the value. bool InitFromValue(const DictionaryValue& value, bool require_id, std::string* error); - // Returns an absolute path to a resource inside of an extension if the - // extension has a theme defined with the given |resource_id|. Otherwise - // the path will be empty. Note that this method is not static as it is - // only intended to be called on an extension which has registered itself - // as providing a theme. - FilePath GetThemeResourcePath(const int resource_id); - // Retrieves a page action by |id|. const PageAction* GetPageAction(std::string id) const; @@ -207,7 +214,16 @@ class Extension { std::string zip_hash_; // A map of resource id's to relative file paths. - std::map<const std::wstring, std::string> theme_paths_; + DictionaryValue* theme_images_; + + // A map of color names to colors. + DictionaryValue* theme_colors_; + + // A map of color names to colors. + DictionaryValue* theme_tints_; + + // Whether the extension is a theme - if it is, certain things are disabled. + bool is_theme_; // The sites this extension has permission to talk to (using XHR, etc). std::vector<URLPattern> permissions_; diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index da5db0f1..2a152e1 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -183,11 +183,30 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension, NotificationType::EXTENSION_INSTALLED, NotificationService::AllSources(), Details<Extension>(extension)); + + // If the extension is a theme, tell the profile (and therefore ThemeProvider) + // to apply it. + if (extension->IsTheme()) { + NotificationService::current()->Notify( + NotificationType::THEME_INSTALLED, + NotificationService::AllSources(), + Details<Extension>(extension)); + } +} + +void ExtensionsService::OnExtensionVersionReinstalled(const std::string& id) { + Extension* extension = GetExtensionByID(id); + if (extension && extension->IsTheme()) { + NotificationService::current()->Notify( + NotificationType::THEME_INSTALLED, + NotificationService::AllSources(), + Details<Extension>(extension)); + } } Extension* ExtensionsService::GetExtensionByID(std::string id) { for (ExtensionList::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { + iter != extensions_.end(); ++iter) { if ((*iter)->id() == id) return *iter; } @@ -329,7 +348,24 @@ Extension* ExtensionsServiceBackend::LoadExtension( return NULL; } - // Validate that claimed resources actually exist. + // Validate that claimed image resources actually exist. + DictionaryValue* images_value = extension->GetThemeImages(); + if (images_value) { + DictionaryValue::key_iterator iter = images_value->begin_keys(); + while (iter != images_value->end_keys()) { + std::string val; + images_value->GetString(*iter, &val); + const FilePath& path = extension->path().AppendASCII(val); + if (!file_util::PathExists(path)) { + ReportExtensionLoadError(extension_path, + StringPrintf("Could not load '%s' for theme.", + WideToUTF8(path.ToWStringHack()).c_str())); + return NULL; + } + ++iter; + } + } + // Validate that claimed script resources actually exist. for (size_t i = 0; i < extension->content_scripts().size(); ++i) { const UserScript& script = extension->content_scripts()[i]; @@ -532,8 +568,9 @@ bool ExtensionsServiceBackend::CheckCurrentVersion( // has actually loaded successfully. FilePath version_dir = dest_dir.AppendASCII(current_version_str); if (file_util::PathExists(version_dir)) { - ReportExtensionInstallError(dest_dir, - "Existing version is already up to date."); + std::string id = WideToASCII(dest_dir.BaseName().ToWStringHack()); + StringToLowerASCII(&id); + ReportExtensionVersionReinstalled(id); return false; } } @@ -727,6 +764,14 @@ void ExtensionsServiceBackend::ReportExtensionInstallError( ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_); } +void ExtensionsServiceBackend::ReportExtensionVersionReinstalled( + const std::string& id) { + frontend_->GetMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod( + frontend_, + &ExtensionsServiceFrontendInterface::OnExtensionVersionReinstalled, + id)); +} + void ExtensionsServiceBackend::ReportExtensionInstalled( const FilePath& path, bool update) { // After it's installed, load it right away with the same settings. diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index 9a83c99..31b8f90e 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -51,8 +51,15 @@ class ExtensionsServiceFrontendInterface // installed extension rather than a new installation. virtual void OnExtensionInstalled(Extension* extension, bool is_update) = 0; + // Called when an existing extension is installed by the user. We may wish to + // notify the user about the prior existence of the extension, or take some + // action using the fact that the user chose to reinstall the extension as a + // signal (for example, setting the default theme to the extension). + virtual void OnExtensionVersionReinstalled(const std::string& id) = 0; + // Lookup an extension by |id|. virtual Extension* GetExtensionByID(std::string id) = 0; + }; @@ -77,6 +84,7 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface { virtual void OnExtensionsLoaded(ExtensionList* extensions); virtual void OnExtensionInstalled(Extension* extension, bool is_update); virtual Extension* GetExtensionByID(std::string id); + virtual void OnExtensionVersionReinstalled(const std::string& id); // The name of the file that the current active version number is stored in. static const char* kCurrentVersionFileName; @@ -176,6 +184,9 @@ class ExtensionsServiceBackend void ReportExtensionInstallError(const FilePath& extension_path, const std::string& error); + // Notify the frontend that the extension had already been installed. + void ReportExtensionVersionReinstalled(const std::string& id); + // Notify the frontend that extensions were installed. // |is_update| is true if this was an update to an existing extension. void ReportExtensionInstalled(const FilePath& path, bool is_update); diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index e6c27df..dc9be78 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -66,10 +66,19 @@ class ExtensionsServiceTestFrontend return &extensions_; } + void ClearInstalledReinstalled() { + installed_ = NULL; + reinstalled_id_ = std::string(); + } + Extension* installed() { return installed_; } + std::string reinstalled_id() { + return reinstalled_id_; + } + // ExtensionsServiceFrontendInterface virtual MessageLoop* GetMessageLoop() { return &message_loop_; @@ -94,6 +103,10 @@ class ExtensionsServiceTestFrontend installed_ = extension; } + virtual void OnExtensionVersionReinstalled(const std::string& id) { + reinstalled_id_ = id; + } + virtual Extension* GetExtensionByID(std::string id) { return NULL; } @@ -122,11 +135,11 @@ class ExtensionsServiceTestFrontend ExtensionErrorReporter::GetInstance()->ClearErrors(); } - private: MessageLoop message_loop_; ExtensionList extensions_; Extension* installed_; + std::string reinstalled_id_; }; // make the test a PlatformTest to setup autorelease pools properly on mac @@ -277,9 +290,6 @@ TEST_F(ExtensionsServiceTest, InstallExtension) { frontend->TestInstallExtension(path, backend, true); // TODO(erikkay): verify the contents of the installed extension. - // Installing the same extension twice should fail. - frontend->TestInstallExtension(path, backend, false); - // 0-length extension file. path = extensions_path.AppendASCII("not_an_extension.crx"); frontend->TestInstallExtension(path, backend, false); @@ -300,6 +310,65 @@ TEST_F(ExtensionsServiceTest, InstallExtension) { // TODO(erikkay): add tests for upgrade cases. } +TEST_F(ExtensionsServiceTest, ReinstallExtension) { + // In this test, we install two extensions, verify that they both install + // correctly, then install the first extension again and verify that it was + // not installed, and that VersionReinstalled was called instead. + FilePath extensions_path; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); + extensions_path = extensions_path.AppendASCII("extensions"); + + FilePath install_dir; + file_util::CreateNewTempDirectory(FILE_PATH_LITERAL("ext_test"), + &install_dir); + scoped_refptr<ExtensionsServiceBackend> backend( + new ExtensionsServiceBackend(install_dir)); + scoped_refptr<ExtensionsServiceTestFrontend> frontend( + new ExtensionsServiceTestFrontend); + + FilePath path = extensions_path.AppendASCII("good.crx"); + FilePath path2 = extensions_path.AppendASCII("theme.crx"); + + // Verify that our extensions are valid. + ASSERT_TRUE(file_util::PathExists(path)); + ASSERT_TRUE(file_util::PathExists(path2)); + + frontend->ClearInstalledReinstalled(); + // Install an extension. + backend->InstallExtension(path, + scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get())); + frontend->GetMessageLoop()->RunAllPending(); + std::vector<std::string> errors = GetErrors(); + + // Verify that it was installed. + EXPECT_TRUE(frontend->installed()) << path.value(); + EXPECT_EQ(0u, errors.size()) << path.value(); + + // Install our second extension. + frontend->ClearInstalledReinstalled(); + backend->InstallExtension(path2, + scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get())); + frontend->GetMessageLoop()->RunAllPending(); + errors = GetErrors(); + + // Verify that it was installed without reinstall getting called. + EXPECT_TRUE(frontend->installed()) << path2.value(); + EXPECT_TRUE(frontend->reinstalled_id().empty()); + EXPECT_EQ(0u, errors.size()) << path.value(); + + // Install the first extension again. + frontend->ClearInstalledReinstalled(); + backend->InstallExtension(path, + scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get())); + frontend->GetMessageLoop()->RunAllPending(); + errors = GetErrors(); + + // Verify that reinstall was called and installed was not. + EXPECT_FALSE(frontend->installed()) << path.value(); + EXPECT_FALSE(frontend->reinstalled_id().empty()) << path.value(); + EXPECT_EQ(0u, errors.size()) << path.value(); +} + TEST_F(ExtensionsServiceTest, LoadExtension) { FilePath extensions_path; ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index d74b802..d05e39a 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -9,12 +9,14 @@ #include "base/string_util.h" #include "base/thread.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/common/extensions/user_script.h" #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h index c0effce..f3a186d 100644 --- a/chrome/browser/external_tab_container.h +++ b/chrome/browser/external_tab_container.h @@ -113,6 +113,7 @@ class ExternalTabContainer : public TabContentsDelegate, virtual gfx::NativeView GetNativeView() const; virtual void PaintNow(const gfx::Rect& update_rect); virtual views::RootView* GetRootView(); + virtual Widget* GetRootWidget() const { return NULL; } virtual bool IsVisible() const; virtual bool IsActive() const; virtual bool GetAccelerator(int cmd_id, diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 86f32b6..9406216 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -28,6 +28,7 @@ #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/spellchecker.h" #include "chrome/browser/ssl/ssl_host_state.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/visitedlink_master.h" #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/chrome_constants.h" @@ -38,7 +39,6 @@ #include "chrome/common/render_messages.h" #include "grit/locale_settings.h" - using base::Time; using base::TimeDelta; @@ -59,6 +59,10 @@ void Profile::RegisterUserPrefs(PrefService* prefs) { IDS_SPELLCHECK_DICTIONARY); prefs->RegisterBooleanPref(prefs::kEnableSpellCheck, true); prefs->RegisterBooleanPref(prefs::kEnableUserScripts, false); + prefs->RegisterStringPref(prefs::kCurrentThemeID, L""); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeImages); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeColors); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeTints); prefs->RegisterBooleanPref(prefs::kEnableExtensions, false); } @@ -76,7 +80,7 @@ URLRequestContext* Profile::GetDefaultRequestContext() { //////////////////////////////////////////////////////////////////////////////// // // OffTheRecordProfileImpl is a profile subclass that wraps an existing profile -// to make it suitable for the off the record mode. +// to make it suitable for the off the record mode. // //////////////////////////////////////////////////////////////////////////////// class OffTheRecordProfileImpl : public Profile, @@ -204,6 +208,22 @@ class OffTheRecordProfileImpl : public Profile, return (download_manager_.get() != NULL); } + virtual void InitThemes() { + GetOriginalProfile()->InitThemes(); + } + + virtual void SetTheme(Extension* extension) { + GetOriginalProfile()->SetTheme(extension); + } + + virtual void ClearTheme() { + GetOriginalProfile()->ClearTheme(); + } + + virtual ThemeProvider* GetThemeProvider() { + return GetOriginalProfile()->GetThemeProvider(); + } + virtual URLRequestContext* GetRequestContext() { return request_context_; } @@ -341,6 +361,9 @@ class OffTheRecordProfileImpl : public Profile, // The download manager that only stores downloaded items in memory. scoped_refptr<DownloadManager> download_manager_; + // The download manager that only stores downloaded items in memory. + scoped_refptr<BrowserThemeProvider> theme_provider_; + // We don't want SSLHostState from the OTR profile to leak back to the main // profile because then the main profile would learn some of the host names // the user visited while OTR. @@ -362,6 +385,7 @@ ProfileImpl::ProfileImpl(const FilePath& path) history_service_created_(false), created_web_data_service_(false), created_download_manager_(false), + created_theme_provider_(false), start_time_(Time::Now()), spellchecker_(NULL), shutdown_session_service_(false) { @@ -387,6 +411,10 @@ ProfileImpl::ProfileImpl(const FilePath& path) prefs->transient()->SetString(prefs::kHomePage, "about:linux-splash"); prefs->transient()->SetBoolean(prefs::kHomePageIsNewTabPage, false); #endif + + // Listen for theme installation. + NotificationService::current()->AddObserver(this, + NotificationType::THEME_INSTALLED, NotificationService::AllSources()); } void ProfileImpl::InitExtensions() { @@ -440,6 +468,9 @@ ProfileImpl::~ProfileImpl() { // before the history is shutdown so it can properly cancel all requests. download_manager_ = NULL; + // The theme provider provides bitmaps to whoever wants them. + theme_provider_ = NULL; + // Remove pref observers. PrefService* prefs = GetPrefs(); prefs->RemovePrefObserver(prefs::kSpellCheckDictionary, this); @@ -449,6 +480,10 @@ ProfileImpl::~ProfileImpl() { personalization_.reset(); #endif + // Remove theme observer. + NotificationService::current()->RemoveObserver(this, + NotificationType::THEME_INSTALLED, NotificationService::AllSources()); + // Both HistoryService and WebDataService maintain threads for background // processing. Its possible each thread still has tasks on it that have // increased the ref count of the service. In such a situation, when we @@ -731,6 +766,30 @@ bool ProfileImpl::HasCreatedDownloadManager() const { return created_download_manager_; } +void ProfileImpl::InitThemes() { + if (!created_theme_provider_) { + scoped_refptr<BrowserThemeProvider> themes(new BrowserThemeProvider); + themes->Init(this); + created_theme_provider_ = true; + theme_provider_.swap(themes); + } +} + +void ProfileImpl::SetTheme(Extension* extension) { + InitThemes(); + theme_provider_.get()->SetTheme(extension); +} + +void ProfileImpl::ClearTheme() { + InitThemes(); + theme_provider_.get()->UseDefaultTheme(); +} + +ThemeProvider* ProfileImpl::GetThemeProvider() { + InitThemes(); + return theme_provider_.get(); +} + SessionService* ProfileImpl::GetSessionService() { if (!session_service_.get() && !shutdown_session_service_) { session_service_ = new SessionService(this); @@ -911,6 +970,9 @@ void ProfileImpl::Observe(NotificationType type, *pref_name_in == prefs::kEnableSpellCheck) { InitializeSpellChecker(true); } + } else if (NotificationType::THEME_INSTALLED == type) { + Extension* extension = Details<Extension>(details).ptr(); + SetTheme(extension); } } diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 2a96277..a83d76a 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -10,6 +10,7 @@ #include <set> #include <string> +#include "app/theme_provider.h" #include "base/basictypes.h" #include "base/file_path.h" #include "base/scoped_ptr.h" @@ -22,6 +23,7 @@ class BookmarkModel; class ChromeURLRequestContext; class DownloadManager; +class Extension; class ExtensionProcessManager; class ExtensionsService; class HistoryService; @@ -33,6 +35,7 @@ class SSLHostState; class TabRestoreService; class TemplateURLFetcher; class TemplateURLModel; +class BrowserThemeProvider; class URLRequestContext; class UserScriptMaster; class VisitedLinkMaster; @@ -162,6 +165,18 @@ class Profile { virtual DownloadManager* GetDownloadManager() = 0; virtual bool HasCreatedDownloadManager() const = 0; + // Init our themes system. + virtual void InitThemes() = 0; + + // Set the theme to the specified extension. + virtual void SetTheme(Extension* extension) = 0; + + // Clear the theme and reset it to default. + virtual void ClearTheme() = 0; + + // Returns or creates the ThemeProvider associated with this profile + virtual ThemeProvider* GetThemeProvider() = 0; + // Returns the request context information associated with this profile. Call // this only on the UI thread, since it can send notifications that should // happen on the UI thread. @@ -289,6 +304,10 @@ class ProfileImpl : public Profile, virtual TemplateURLModel* GetTemplateURLModel(); virtual TemplateURLFetcher* GetTemplateURLFetcher(); virtual DownloadManager* GetDownloadManager(); + virtual void InitThemes(); + virtual void SetTheme(Extension* extension); + virtual void ClearTheme(); + virtual ThemeProvider* GetThemeProvider(); virtual bool HasCreatedDownloadManager() const; virtual URLRequestContext* GetRequestContext(); virtual URLRequestContext* GetRequestContextForMedia(); @@ -363,9 +382,11 @@ class ProfileImpl : public Profile, scoped_refptr<HistoryService> history_service_; scoped_refptr<WebDataService> web_data_service_; scoped_refptr<SessionService> session_service_; + scoped_refptr<BrowserThemeProvider> theme_provider_; bool history_service_created_; bool created_web_data_service_; bool created_download_manager_; + bool created_theme_provider_; // Whether or not the last session exited cleanly. This is set only once. bool last_session_exited_cleanly_; diff --git a/chrome/browser/resources/new_tab.html b/chrome/browser/resources/new_tab.html index 2b27e00..5daf5c5 100644 --- a/chrome/browser/resources/new_tab.html +++ b/chrome/browser/resources/new_tab.html @@ -133,6 +133,8 @@ logEvent('log start'); body { background-color:white; margin:0px; + background-image:url(chrome-ui://theme/theme_newtab_background); + background-repeat:repeat-x; } html[firstview='true'] #main { opacity:0.0; diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index 51beca0a..88264f2 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -87,7 +87,6 @@ static const SkColor kBackgroundColor = SkColorSetRGB(237, 244, 252); // Border colors for the BookmarBarView. static const SkColor kTopBorderColor = SkColorSetRGB(222, 234, 248); -static const SkColor kBottomBorderColor = SkColorSetRGB(178, 178, 178); // Background color for when the bookmarks bar is only being displayed on the // new tab page - this color should match the background color of the new tab @@ -222,30 +221,6 @@ class BookmarkButton : public views::TextButton { return event_utils::IsPossibleDispositionEvent(e); } - virtual void Paint(ChromeCanvas *canvas) { - views::TextButton::Paint(canvas); - - PaintAnimation(this, canvas, show_animation_->GetCurrentValue()); - } - - static void PaintAnimation(views::View* view, - ChromeCanvas* canvas, - double animation_value) { - // Since we can't change the alpha of the button (it contains un-alphable - // text), we paint the bar background over the front of the button. As the - // bar background is a gradient, we have to paint the gradient at the - // size of the parent (hence all the margin math below). We can't use - // the parent's actual bounds because they differ from what is painted. - SkPaint paint; - paint.setAlpha(static_cast<int>((1.0 - animation_value) * 255)); - paint.setShader(skia::CreateGradientShader(0, - view->height() + kTopMargin + kBottomMargin, - kTopBorderColor, - kBackgroundColor))->safeUnref(); - canvas->FillRectInt(0, -kTopMargin, view->width(), - view->height() + kTopMargin + kBottomMargin, paint); - } - private: const GURL& url_; Profile* profile_; @@ -283,9 +258,6 @@ class BookmarkFolderButton : public views::MenuButton { virtual void Paint(ChromeCanvas *canvas) { views::MenuButton::Paint(canvas, false); - - BookmarkButton::PaintAnimation(this, canvas, - show_animation_->GetCurrentValue()); } private: @@ -588,7 +560,8 @@ void BookmarkBarView::Paint(ChromeCanvas* canvas) { canvas->FillRectInt(kNewtabBackgroundColor, 0, 0, width(), height()); // Draw the 'bottom' of the toolbar above our bubble. - canvas->FillRectInt(kBottomBorderColor, 0, 0, width(), 1); + canvas->FillRectInt(ResourceBundle::toolbar_separator_color, + 0, 0, width(), 1); SkRect rect; @@ -632,15 +605,14 @@ void BookmarkBarView::Paint(ChromeCanvas* canvas) { SkDoubleToScalar(roundness), SkDoubleToScalar(roundness), border_paint); } else { - SkPaint paint; - paint.setShader(skia::CreateGradientShader(0, - height(), - kTopBorderColor, - kBackgroundColor))->safeUnref(); - canvas->FillRectInt(0, 0, width(), height(), paint); - - canvas->FillRectInt(kTopBorderColor, 0, 0, width(), 1); - canvas->FillRectInt(kBottomBorderColor, 0, height() - 1, width(), 1); + gfx::Rect bounds = GetBounds(views::View::APPLY_MIRRORING_TRANSFORMATION); + + // +1 is for toolbar outdent. + canvas->TileImageInt(*GetThemeProvider()-> + GetBitmapNamed(IDR_THEME_TOOLBAR), + bounds.x() + 1, bounds.y(), 0, 0, width(), height()); + canvas->FillRectInt(ResourceBundle::toolbar_separator_color, + 0, height() - 1, width(), 1); } } diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_impl.cc index cde0327..9b4ee70 100644 --- a/chrome/browser/views/constrained_window_impl.cc +++ b/chrome/browser/views/constrained_window_impl.cc @@ -61,16 +61,23 @@ enum { FRAME_TOP_LEFT_CORNER, FRAME_TOP_RIGHT_CORNER, + FRAME_WINDOW, + FRAME_WINDOW_INACTIVE, + FRAME_WINDOW_INCOGNITO, + FRAME_WINDOW_INCOGNITO_INACTIVE, + FRAME_PART_BITMAP_COUNT // Must be last. }; static const int kXPFramePartIDs[] = { 0, IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_CONSTRAINED_BOTTOM_CENTER, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER, - IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER, IDR_CONSTRAINED_LEFT_SIDE, - IDR_CONSTRAINED_RIGHT_SIDE, IDR_CONSTRAINED_TOP_CENTER, - IDR_CONSTRAINED_TOP_LEFT_CORNER, IDR_CONSTRAINED_TOP_RIGHT_CORNER, + IDR_WINDOW_BOTTOM_CENTER, IDR_WINDOW_BOTTOM_LEFT_CORNER, + IDR_WINDOW_BOTTOM_RIGHT_CORNER, IDR_WINDOW_LEFT_SIDE, + IDR_WINDOW_RIGHT_SIDE, IDR_WINDOW_TOP_CENTER, + IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_RIGHT_CORNER, + IDR_THEME_FRAME, IDR_THEME_FRAME_INACTIVE, IDR_THEME_FRAME_INCOGNITO, + IDR_THEME_FRAME_INCOGNITO_INACTIVE, 0 }; static const int kVistaFramePartIDs[] = { 0, @@ -79,14 +86,8 @@ static const int kVistaFramePartIDs[] = { IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER_V, IDR_CONSTRAINED_LEFT_SIDE_V, IDR_CONSTRAINED_RIGHT_SIDE_V, IDR_CONSTRAINED_TOP_CENTER_V, IDR_CONSTRAINED_TOP_LEFT_CORNER_V, IDR_CONSTRAINED_TOP_RIGHT_CORNER_V, - 0 }; -static const int kOTRFramePartIDs[] = { - 0, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_WINDOW_BOTTOM_CENTER_OTR, IDR_WINDOW_BOTTOM_LEFT_CORNER_OTR, - IDR_WINDOW_BOTTOM_RIGHT_CORNER_OTR, IDR_WINDOW_LEFT_SIDE_OTR, - IDR_WINDOW_RIGHT_SIDE_OTR, IDR_WINDOW_TOP_CENTER_OTR, - IDR_WINDOW_TOP_LEFT_CORNER_OTR, IDR_WINDOW_TOP_RIGHT_CORNER_OTR, + IDR_THEME_FRAME, IDR_THEME_FRAME_INACTIVE, IDR_THEME_FRAME_INCOGNITO, + IDR_THEME_FRAME_INCOGNITO_INACTIVE, 0 }; class XPWindowResources : public views::WindowResources { @@ -149,39 +150,8 @@ class VistaWindowResources : public views::WindowResources { DISALLOW_EVIL_CONSTRUCTORS(VistaWindowResources); }; -class OTRWindowResources : public views::WindowResources { - public: - OTRWindowResources() { - InitClass(); - } - virtual ~OTRWindowResources() {} - - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part_id) const { - return bitmaps_[part_id]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) { - int id = kOTRFramePartIDs[i]; - if (id != 0) - bitmaps_[i] = rb.GetBitmapNamed(id); - } - initialized = true; - } - } - - static SkBitmap* bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(OTRWindowResources); -}; - SkBitmap* XPWindowResources::bitmaps_[]; SkBitmap* VistaWindowResources::bitmaps_[]; -SkBitmap* OTRWindowResources::bitmaps_[]; //////////////////////////////////////////////////////////////////////////////// // ConstrainedWindowFrameView @@ -299,7 +269,6 @@ const int kTitleCaptionSpacing = 5; const int kCaptionTopSpacing = 1; const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); -const SkColor kContentsBorderColor = SkColorSetRGB(219, 235, 255); } //////////////////////////////////////////////////////////////////////////////// @@ -479,6 +448,29 @@ void ConstrainedWindowFrameView::PaintFrameBorder(ChromeCanvas* canvas) { resources_->GetPartBitmap(FRAME_BOTTOM_RIGHT_CORNER); SkBitmap* bottom_edge = resources_->GetPartBitmap(FRAME_BOTTOM_EDGE); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + SkBitmap* theme_frame = rb.GetBitmapNamed(IDR_THEME_FRAME); + SkColor frame_color = ResourceBundle::frame_color; + + // Fill with the frame color first so we have a constant background for + // areas not covered by the theme image. + canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height()); + // Now fill down the sides + canvas->FillRectInt(frame_color, + 0, theme_frame->height(), + left_edge->width(), height() - theme_frame->height()); + canvas->FillRectInt(frame_color, + width() - right_edge->width(), theme_frame->height(), + right_edge->width(), height() - theme_frame->height()); + // Now fill the bottom area. + canvas->FillRectInt(frame_color, + left_edge->width(), height() - bottom_edge->height(), + width() - left_edge->width() - right_edge->width(), + bottom_edge->height()); + + // Draw the theme frame. + canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height()); + // Top. canvas->DrawBitmapInt(*top_left_corner, 0, 0); canvas->TileImageInt(*top_edge, top_left_corner->width(), 0, @@ -526,7 +518,7 @@ void ConstrainedWindowFrameView::PaintClientEdge(ChromeCanvas* canvas) { frame_shadow_bounds.y(), frame_shadow_bounds.width(), frame_shadow_bounds.height()); - canvas->FillRectInt(kContentsBorderColor, client_edge_bounds.x(), + canvas->FillRectInt(ResourceBundle::toolbar_color, client_edge_bounds.x(), client_edge_bounds.y(), client_edge_bounds.width(), client_edge_bounds.height()); } @@ -565,14 +557,10 @@ gfx::Rect ConstrainedWindowFrameView::CalculateClientAreaBounds( } void ConstrainedWindowFrameView::InitWindowResources() { - if (container_->owner()->profile()->IsOffTheRecord()) { - resources_.reset(new OTRWindowResources); + if (win_util::ShouldUseVistaFrame()) { + resources_.reset(new VistaWindowResources); } else { - if (win_util::ShouldUseVistaFrame()) { - resources_.reset(new VistaWindowResources); - } else { - resources_.reset(new XPWindowResources); - } + resources_.reset(new XPWindowResources); } } diff --git a/chrome/browser/views/frame/browser_frame.cc b/chrome/browser/views/frame/browser_frame.cc index c022b6a..0d39521 100644 --- a/chrome/browser/views/frame/browser_frame.cc +++ b/chrome/browser/views/frame/browser_frame.cc @@ -9,6 +9,7 @@ #include "app/resource_bundle.h" #include "app/win_util.h" +#include "chrome/browser/profile.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/views/frame/browser_root_view.h" #include "chrome/browser/views/frame/browser_view.h" @@ -23,10 +24,11 @@ static const int kClientEdgeThickness = 3; /////////////////////////////////////////////////////////////////////////////// // BrowserFrame, public: -BrowserFrame::BrowserFrame(BrowserView* browser_view) +BrowserFrame::BrowserFrame(BrowserView* browser_view, Profile* profile) : WindowWin(browser_view), browser_view_(browser_view), - frame_initialized_(false) { + frame_initialized_(false), + profile_(profile) { browser_view_->set_frame(this); GetNonClientView()->SetFrameView(CreateFrameViewForWindow()); // Don't focus anything on creation, selecting a tab will set the focus. @@ -60,6 +62,14 @@ void BrowserFrame::UpdateThrobber(bool running) { browser_frame_view_->UpdateThrobber(running); } +ThemeProvider* BrowserFrame::GetThemeProvider() const { + return profile_->GetThemeProvider(); +} + +ThemeProvider* BrowserFrame::GetDialogThemeProvider() const { + return profile_->GetThemeProvider(); +} + #if defined(FRAME_WINDOW) void BrowserFrame::SetBrowserNonClientFrameView( BrowserNonClientFrameView* view) { @@ -221,7 +231,6 @@ void BrowserFrame::UpdateFrameAfterFrameChange() { UpdateDWMFrame(); } - views::RootView* BrowserFrame::CreateRootView() { return new BrowserRootView(this); } diff --git a/chrome/browser/views/frame/browser_frame.h b/chrome/browser/views/frame/browser_frame.h index 140f25e..792e90e 100644 --- a/chrome/browser/views/frame/browser_frame.h +++ b/chrome/browser/views/frame/browser_frame.h @@ -10,6 +10,7 @@ class AeroGlassNonClientView; class BrowserView; class NonClientFrameView; +class Profile; class TabStrip; // A specialization of the NonClientFrameView object that provides additional @@ -34,7 +35,7 @@ class BrowserNonClientFrameView : public views::NonClientFrameView { // class BrowserFrame : public views::WindowWin { public: - explicit BrowserFrame(BrowserView* browser_view); + explicit BrowserFrame(BrowserView* browser_view, Profile* profile); virtual ~BrowserFrame(); // Initialize the frame. Creates the Window. @@ -51,6 +52,10 @@ class BrowserFrame : public views::WindowWin { // Tells the frame to update the throbber. void UpdateThrobber(bool running); + // Overridden from views::Widget. + virtual ThemeProvider* GetThemeProvider() const; + virtual ThemeProvider* GetDialogThemeProvider() const; + BrowserView* browser_view() const { return browser_view_; } #if defined(FRAME_WINDOW) @@ -92,6 +97,8 @@ class BrowserFrame : public views::WindowWin { bool frame_initialized_; + Profile* profile_; + DISALLOW_EVIL_CONSTRUCTORS(BrowserFrame); }; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index a3acb80..f2f24b5 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -855,6 +855,11 @@ void BrowserView::ShowHTMLDialog(HtmlDialogUIDelegate* delegate, html_view->window()->Show(); } +void BrowserView::UserChangedTheme() { + frame_->GetRootView()->ThemeChanged(); + frame_->GetRootView()->SchedulePaint(); +} + /////////////////////////////////////////////////////////////////////////////// // BrowserView, BrowserWindowTesting implementation: @@ -1662,7 +1667,7 @@ void BrowserView::InitClass() { // static BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) { BrowserView* browser_view = new BrowserView(browser); - (new BrowserFrame(browser_view))->Init(); + (new BrowserFrame(browser_view, browser->profile()))->Init(); return browser_view; } diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 7357333..40afbc5 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -201,6 +201,7 @@ class BrowserView : public BrowserWindow, virtual void ConfirmBrowserCloseWithPendingDownloads(); virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate, void* parent_window); + virtual void UserChangedTheme(); // Overridden from BrowserWindowTesting: virtual BookmarkBarView* GetBookmarkBarView() const; diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc index bbebd3a..6eaf547 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/views/frame/glass_browser_frame_view.cc @@ -6,66 +6,15 @@ #include "app/gfx/chrome_canvas.h" #include "app/resource_bundle.h" +#include "app/theme_provider.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/tab_strip.h" #include "grit/theme_resources.h" #include "views/window/client_view.h" #include "views/window/window_resources.h" -// An enumeration of bitmap resources used by this window. -enum { - // Client Edge Border. - FRAME_CLIENT_EDGE_TOP_LEFT, - FRAME_CLIENT_EDGE_TOP, - FRAME_CLIENT_EDGE_TOP_RIGHT, - FRAME_CLIENT_EDGE_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM, - FRAME_CLIENT_EDGE_BOTTOM_LEFT, - FRAME_CLIENT_EDGE_LEFT, - - FRAME_PART_BITMAP_COUNT // Must be last. -}; - -class GlassBrowserWindowResources { - public: - GlassBrowserWindowResources() { - InitClass(); - } - virtual ~GlassBrowserWindowResources() { } - - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER, - IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE, - IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, - IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE, - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(kFramePartBitmapIds[i]); - - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(GlassBrowserWindowResources); -}; - // static -SkBitmap* GlassBrowserWindowResources::standard_frame_bitmaps_[]; - -GlassBrowserWindowResources* GlassBrowserFrameView::resources_ = NULL; SkBitmap* GlassBrowserFrameView::distributor_logo_ = NULL; HICON GlassBrowserFrameView::throbber_icons_[ GlassBrowserFrameView::kThrobberIconCount]; @@ -281,23 +230,34 @@ void GlassBrowserFrameView::PaintDistributorLogo(ChromeCanvas* canvas) { } void GlassBrowserFrameView::PaintToolbarBackground(ChromeCanvas* canvas) { + ThemeProvider* tp = GetThemeProvider(); + gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds()); gfx::Point toolbar_origin(toolbar_bounds.origin()); View::ConvertPointToView(frame_->GetClientView(), this, &toolbar_origin); toolbar_bounds.set_origin(toolbar_origin); + SkBitmap* theme_toolbar = tp->GetBitmapNamed(IDR_THEME_TOOLBAR); + + // Draw the toolbar background, setting src_y of the paint to the tab + // strip height as the toolbar background begins at the top of the tabs. + canvas->TileImageInt(*theme_toolbar, + 0, browser_view_->GetTabStripHeight() - 1, + toolbar_bounds.x() - 1, toolbar_bounds.y() + 2, + toolbar_bounds.width() + 2, theme_toolbar->height()); + SkBitmap* toolbar_left = - resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); + tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER); canvas->DrawBitmapInt(*toolbar_left, toolbar_bounds.x() - toolbar_left->width(), toolbar_bounds.y()); SkBitmap* toolbar_center = - resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); + tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER); canvas->TileImageInt(*toolbar_center, toolbar_bounds.x(), toolbar_bounds.y(), toolbar_bounds.width(), toolbar_center->height()); - canvas->DrawBitmapInt(*resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT), + canvas->DrawBitmapInt(*tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER), toolbar_bounds.right(), toolbar_bounds.y()); } @@ -314,35 +274,50 @@ void GlassBrowserFrameView::PaintOTRAvatar(ChromeCanvas* canvas) { } void GlassBrowserFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + // The client edges start below the toolbar upper corner images regardless // of how tall the toolbar itself is. int client_area_top = frame_->GetClientView()->y() + browser_view_->GetToolbarBounds().y() + - resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT)->height(); + rb.GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(); gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); int client_area_bottom = std::max(client_area_top, height() - NonClientBorderThickness()); int client_area_height = client_area_bottom - client_area_top; - SkBitmap* right = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); + SkBitmap* right = rb.GetBitmapNamed(IDR_CONTENT_RIGHT_SIDE); canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, right->width(), client_area_height); + // Draw the toolbar color so that the one pixel areas down the sides + // show the right color even if not covered by the toolbar image. + canvas->DrawRectInt(GetThemeProvider()-> + GetColor(BrowserThemeProvider::COLOR_TOOLBAR), + client_area_bounds.x() - 1, client_area_top, + client_area_bounds.width() + 1, client_area_bottom - client_area_top); + + // Draw the content/toolbar separator. + canvas->DrawLineInt(ResourceBundle::toolbar_separator_color, + client_area_bounds.x(), client_area_top, + client_area_bounds.x() + client_area_bounds.width(), + client_area_top); + canvas->DrawBitmapInt( - *resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT), + *rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER), client_area_bounds.right(), client_area_bottom); - SkBitmap* bottom = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); + SkBitmap* bottom = rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER); canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom, client_area_bounds.width(), bottom->height()); SkBitmap* bottom_left = - resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); + rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); canvas->DrawBitmapInt(*bottom_left, client_area_bounds.x() - bottom_left->width(), client_area_bottom); - SkBitmap* left = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); + SkBitmap* left = rb.GetBitmapNamed(IDR_CONTENT_LEFT_SIDE); canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), client_area_top, left->width(), client_area_height); } @@ -437,8 +412,6 @@ void GlassBrowserFrameView::InitThrobberIcons() { void GlassBrowserFrameView::InitClass() { static bool initialized = false; if (!initialized) { - resources_ = new GlassBrowserWindowResources; - #if defined(GOOGLE_CHROME_BUILD) distributor_logo_ = ResourceBundle::GetSharedInstance(). GetBitmapNamed(IDR_DISTRIBUTOR_LOGO); diff --git a/chrome/browser/views/frame/glass_browser_frame_view.h b/chrome/browser/views/frame/glass_browser_frame_view.h index d110fe9..3a00db3 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/views/frame/glass_browser_frame_view.h @@ -10,7 +10,6 @@ #include "views/window/non_client_view.h" class BrowserView; -class GlassBrowserWindowResources; class SkBitmap; class GlassBrowserFrameView : public BrowserNonClientFrameView { @@ -95,7 +94,6 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView { static void InitClass(); static SkBitmap* distributor_logo_; - static GlassBrowserWindowResources* resources_; static const int kThrobberIconCount = 24; static HICON throbber_icons_[kThrobberIconCount]; diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index 10c604c..317e307 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -9,7 +9,9 @@ #include "app/gfx/path.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "app/theme_provider.h" #include "app/win_util.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/views/frame/browser_frame.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/tab_strip.h" @@ -20,244 +22,7 @@ #include "views/widget/root_view.h" #include "views/window/window_resources.h" -// An enumeration of bitmap resources used by this window. -enum { - // Window Controls. - FRAME_CLOSE_BUTTON_ICON, - FRAME_CLOSE_BUTTON_ICON_H, - FRAME_CLOSE_BUTTON_ICON_P, - FRAME_CLOSE_BUTTON_ICON_SA, - FRAME_CLOSE_BUTTON_ICON_SA_H, - FRAME_CLOSE_BUTTON_ICON_SA_P, - FRAME_RESTORE_BUTTON_ICON, - FRAME_RESTORE_BUTTON_ICON_H, - FRAME_RESTORE_BUTTON_ICON_P, - FRAME_MAXIMIZE_BUTTON_ICON, - FRAME_MAXIMIZE_BUTTON_ICON_H, - FRAME_MAXIMIZE_BUTTON_ICON_P, - FRAME_MINIMIZE_BUTTON_ICON, - FRAME_MINIMIZE_BUTTON_ICON_H, - FRAME_MINIMIZE_BUTTON_ICON_P, - - // Window Frame Border. - FRAME_BOTTOM_EDGE, - FRAME_BOTTOM_LEFT_CORNER, - FRAME_BOTTOM_RIGHT_CORNER, - FRAME_LEFT_EDGE, - FRAME_RIGHT_EDGE, - FRAME_TOP_EDGE, - FRAME_TOP_LEFT_CORNER, - FRAME_TOP_RIGHT_CORNER, - - // Client Edge Border. - FRAME_CLIENT_EDGE_TOP_LEFT, - FRAME_CLIENT_EDGE_TOP, - FRAME_CLIENT_EDGE_TOP_RIGHT, - FRAME_CLIENT_EDGE_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM, - FRAME_CLIENT_EDGE_BOTTOM_LEFT, - FRAME_CLIENT_EDGE_LEFT, - - // No-toolbar client edge. - FRAME_NO_TOOLBAR_TOP_LEFT, - FRAME_NO_TOOLBAR_TOP_CENTER, - FRAME_NO_TOOLBAR_TOP_RIGHT, - - FRAME_PART_BITMAP_COUNT // Must be last. -}; - -class ActiveWindowResources : public views::WindowResources { - public: - ActiveWindowResources() { - InitClass(); - } - virtual ~ActiveWindowResources() { } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_WINDOW_BOTTOM_CENTER, IDR_WINDOW_BOTTOM_LEFT_CORNER, - IDR_WINDOW_BOTTOM_RIGHT_CORNER, IDR_WINDOW_LEFT_SIDE, - IDR_WINDOW_RIGHT_SIDE, IDR_WINDOW_TOP_CENTER, - IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_RIGHT_CORNER, - IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER, - IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE, - IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, - IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(kFramePartBitmapIds[i]); - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(ActiveWindowResources); -}; - -class InactiveWindowResources : public views::WindowResources { - public: - InactiveWindowResources() { - InitClass(); - } - virtual ~InactiveWindowResources() { } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_DEWINDOW_BOTTOM_CENTER, IDR_DEWINDOW_BOTTOM_LEFT_CORNER, - IDR_DEWINDOW_BOTTOM_RIGHT_CORNER, IDR_DEWINDOW_LEFT_SIDE, - IDR_DEWINDOW_RIGHT_SIDE, IDR_DEWINDOW_TOP_CENTER, - IDR_DEWINDOW_TOP_LEFT_CORNER, IDR_DEWINDOW_TOP_RIGHT_CORNER, - IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER, - IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE, - IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, - IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(kFramePartBitmapIds[i]); - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(InactiveWindowResources); -}; - -class OTRActiveWindowResources : public views::WindowResources { - public: - OTRActiveWindowResources() { - InitClass(); - } - virtual ~OTRActiveWindowResources() { } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_WINDOW_BOTTOM_CENTER_OTR, IDR_WINDOW_BOTTOM_LEFT_CORNER_OTR, - IDR_WINDOW_BOTTOM_RIGHT_CORNER_OTR, IDR_WINDOW_LEFT_SIDE_OTR, - IDR_WINDOW_RIGHT_SIDE_OTR, IDR_WINDOW_TOP_CENTER_OTR, - IDR_WINDOW_TOP_LEFT_CORNER_OTR, IDR_WINDOW_TOP_RIGHT_CORNER_OTR, - IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER, - IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE, - IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, - IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(kFramePartBitmapIds[i]); - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(OTRActiveWindowResources); -}; - -class OTRInactiveWindowResources : public views::WindowResources { - public: - OTRInactiveWindowResources() { - InitClass(); - } - virtual ~OTRInactiveWindowResources() { } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_DEWINDOW_BOTTOM_CENTER_OTR, IDR_DEWINDOW_BOTTOM_LEFT_CORNER_OTR, - IDR_DEWINDOW_BOTTOM_RIGHT_CORNER_OTR, IDR_DEWINDOW_LEFT_SIDE_OTR, - IDR_DEWINDOW_RIGHT_SIDE_OTR, IDR_DEWINDOW_TOP_CENTER_OTR, - IDR_DEWINDOW_TOP_LEFT_CORNER_OTR, - IDR_DEWINDOW_TOP_RIGHT_CORNER_OTR, - IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER, - IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE, - IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, - IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(kFramePartBitmapIds[i]); - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(OTRInactiveWindowResources); -}; - // static -SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[]; -SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[]; -SkBitmap* OTRActiveWindowResources::standard_frame_bitmaps_[]; -SkBitmap* OTRInactiveWindowResources::standard_frame_bitmaps_[]; - -views::WindowResources* OpaqueBrowserFrameView::active_resources_ = NULL; -views::WindowResources* OpaqueBrowserFrameView::inactive_resources_ = NULL; -views::WindowResources* OpaqueBrowserFrameView::active_otr_resources_ = NULL; -views::WindowResources* OpaqueBrowserFrameView::inactive_otr_resources_ = NULL; SkBitmap* OpaqueBrowserFrameView::distributor_logo_ = NULL; ChromeFont* OpaqueBrowserFrameView::title_font_ = NULL; @@ -341,68 +106,57 @@ OpaqueBrowserFrameView::OpaqueBrowserFrameView(BrowserFrame* frame, frame_(frame), browser_view_(browser_view) { InitClass(); - if (browser_view->IsOffTheRecord()) { - if (!active_otr_resources_) { - // Lazy load OTR resources only when we first show an OTR frame. - active_otr_resources_ = new OTRActiveWindowResources; - inactive_otr_resources_ = new OTRInactiveWindowResources; - } - current_active_resources_ = active_otr_resources_; - current_inactive_resources_= inactive_otr_resources_; - } else { - current_active_resources_ = active_resources_; - current_inactive_resources_ = inactive_resources_; - } - views::WindowResources* resources = current_active_resources_; + ThemeProvider* tp = frame_->GetThemeProvider(); + minimize_button_->SetImage( views::CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_MINIMIZE)); minimize_button_->SetImage( views::CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_MINIMIZE_H)); minimize_button_->SetImage( views::CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_MINIMIZE_P)); minimize_button_->SetAccessibleName( l10n_util::GetString(IDS_ACCNAME_MINIMIZE)); AddChildView(minimize_button_); maximize_button_->SetImage( views::CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_MAXIMIZE)); maximize_button_->SetImage( views::CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_MAXIMIZE_H)); maximize_button_->SetImage( views::CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_MAXIMIZE_P)); maximize_button_->SetAccessibleName( l10n_util::GetString(IDS_ACCNAME_MAXIMIZE)); AddChildView(maximize_button_); restore_button_->SetImage( views::CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_RESTORE)); restore_button_->SetImage( views::CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_RESTORE_H)); restore_button_->SetImage( views::CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_RESTORE_P)); restore_button_->SetAccessibleName( l10n_util::GetString(IDS_ACCNAME_RESTORE)); AddChildView(restore_button_); close_button_->SetImage( views::CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_CLOSE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_CLOSE)); close_button_->SetImage( views::CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_CLOSE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_CLOSE_H)); close_button_->SetImage( views::CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_CLOSE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_CLOSE_P)); close_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE)); AddChildView(close_button_); @@ -753,17 +507,61 @@ int OpaqueBrowserFrameView::IconSize(int* title_top_spacing_ptr, } void OpaqueBrowserFrameView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { - SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); + ThemeProvider* tp = GetThemeProvider(); + + SkBitmap* top_left_corner = tp->GetBitmapNamed(IDR_WINDOW_TOP_LEFT_CORNER); SkBitmap* top_right_corner = - resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); - SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); - SkBitmap* right_edge = resources()->GetPartBitmap(FRAME_RIGHT_EDGE); - SkBitmap* left_edge = resources()->GetPartBitmap(FRAME_LEFT_EDGE); + tp->GetBitmapNamed(IDR_WINDOW_TOP_RIGHT_CORNER); + SkBitmap* top_edge = tp->GetBitmapNamed(IDR_WINDOW_TOP_CENTER); + SkBitmap* right_edge = tp->GetBitmapNamed(IDR_WINDOW_RIGHT_SIDE); + SkBitmap* left_edge = tp->GetBitmapNamed(IDR_WINDOW_LEFT_SIDE); SkBitmap* bottom_left_corner = - resources()->GetPartBitmap(FRAME_BOTTOM_LEFT_CORNER); + tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER); SkBitmap* bottom_right_corner = - resources()->GetPartBitmap(FRAME_BOTTOM_RIGHT_CORNER); - SkBitmap* bottom_edge = resources()->GetPartBitmap(FRAME_BOTTOM_EDGE); + tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER); + SkBitmap* bottom_edge = tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_CENTER); + + + // Window frame mode and color + SkBitmap* theme_frame; + SkColor frame_color; + if (!browser_view_->IsOffTheRecord()) { + if (frame_->IsActive()) { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME); + frame_color = tp->GetColor(BrowserThemeProvider::COLOR_FRAME); + } else { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME_INACTIVE); + frame_color = tp->GetColor(BrowserThemeProvider::COLOR_FRAME_INACTIVE); + } + } else { + if (frame_->IsActive()) { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME_INCOGNITO); + frame_color = tp->GetColor(BrowserThemeProvider::COLOR_FRAME_INCOGNITO); + } else { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME_INCOGNITO_INACTIVE); + frame_color = tp->GetColor( + BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE); + } + } + + // Fill with the frame color first so we have a constant background for + // areas not covered by the theme image. + canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height()); + // Now fill down the sides + canvas->FillRectInt(frame_color, + 0, theme_frame->height(), + left_edge->width(), height() - theme_frame->height()); + canvas->FillRectInt(frame_color, + width() - right_edge->width(), theme_frame->height(), + right_edge->width(), height() - theme_frame->height()); + // Now fill the bottom area. + canvas->FillRectInt(frame_color, + left_edge->width(), height() - bottom_edge->height(), + width() - left_edge->width() - right_edge->width(), + bottom_edge->height()); + + // Draw the theme frame. + canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height()); // Top. int top_left_height = std::min(top_left_corner->height(), @@ -804,8 +602,11 @@ void OpaqueBrowserFrameView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { height() - top_left_height - bottom_left_corner->height()); } + void OpaqueBrowserFrameView::PaintMaximizedFrameBorder(ChromeCanvas* canvas) { - SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); + ThemeProvider* tp = GetThemeProvider(); + + SkBitmap* top_edge = tp->GetBitmapNamed(IDR_WINDOW_TOP_CENTER); canvas->TileImageInt(*top_edge, 0, FrameBorderThickness(), width(), top_edge->height()); @@ -814,7 +615,7 @@ void OpaqueBrowserFrameView::PaintMaximizedFrameBorder(ChromeCanvas* canvas) { // edge. The graphic we use for this has a built in client edge, so we clip // it off the bottom. SkBitmap* top_center = - resources()->GetPartBitmap(FRAME_NO_TOOLBAR_TOP_CENTER); + tp->GetBitmapNamed(IDR_APP_TOP_CENTER); int edge_height = top_center->height() - kClientEdgeThickness; canvas->TileImageInt(*top_center, 0, frame_->GetClientView()->y() - edge_height, width(), edge_height); @@ -851,19 +652,32 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(ChromeCanvas* canvas) { if (!browser_view_->IsToolbarVisible()) return; + ThemeProvider* tp = GetThemeProvider(); gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds()); gfx::Point toolbar_origin(toolbar_bounds.origin()); View::ConvertPointToView(frame_->GetClientView(), this, &toolbar_origin); toolbar_bounds.set_origin(toolbar_origin); + int strip_height = browser_view_->GetTabStripHeight(); + SkBitmap* theme_toolbar = tp->GetBitmapNamed(IDR_THEME_TOOLBAR); + + canvas->TileImageInt(*theme_toolbar, + 0, strip_height - 1, // crop src + toolbar_bounds.x() - 1, toolbar_bounds.y() + 2, + toolbar_bounds.width() + 2, theme_toolbar->height()); + + SkBitmap* toolbar_left = + tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER); + canvas->DrawBitmapInt(*toolbar_left, + toolbar_bounds.x() - toolbar_left->width(), + toolbar_bounds.y()); + // Gross hack: We split the toolbar images into two pieces, since sometimes // (popup mode) the toolbar isn't tall enough to show the whole image. The // split happens between the top shadow section and the bottom gradient // section so that we never break the gradient. int split_point = kFrameShadowThickness * 2; int bottom_y = toolbar_bounds.y() + split_point; - SkBitmap* toolbar_left = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); int bottom_edge_height = std::min(toolbar_left->height(), toolbar_bounds.height()) - split_point; @@ -876,7 +690,7 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(ChromeCanvas* canvas) { toolbar_left->width(), bottom_edge_height, false); SkBitmap* toolbar_center = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); + tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER); canvas->TileImageInt(*toolbar_center, 0, 0, toolbar_bounds.x(), toolbar_bounds.y(), toolbar_bounds.width(), split_point); int bottom_center_height = @@ -885,8 +699,7 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(ChromeCanvas* canvas) { toolbar_center->height() - bottom_center_height, toolbar_bounds.x(), bottom_y, toolbar_bounds.width(), bottom_center_height); - SkBitmap* toolbar_right = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); + SkBitmap* toolbar_right = tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER); canvas->DrawBitmapInt(*toolbar_right, 0, 0, toolbar_right->width(), split_point, toolbar_bounds.right(), toolbar_bounds.y(), toolbar_right->width(), split_point, false); @@ -909,6 +722,7 @@ void OpaqueBrowserFrameView::PaintOTRAvatar(ChromeCanvas* canvas) { } void OpaqueBrowserFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { + ThemeProvider* tp = GetThemeProvider(); int client_area_top = frame_->GetClientView()->y(); gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); @@ -916,9 +730,9 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { // The client edges start below the toolbar or its corner images, whichever // is shorter. gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds()); - client_area_top += toolbar_bounds.y() + std::min( - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT)->height(), - toolbar_bounds.height()); + client_area_top += browser_view_->GetToolbarBounds().y() + + std::min(tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(), + toolbar_bounds.height()); } else { // The toolbar isn't going to draw a client edge for us, so draw one // ourselves. @@ -926,12 +740,11 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { // shorter than the top left and right bitmaps. We need their top edges to // line up, and we need the left and right edges to start below the corners' // bottoms. - SkBitmap* top_left = resources()->GetPartBitmap(FRAME_NO_TOOLBAR_TOP_LEFT); - SkBitmap* top_center = - resources()->GetPartBitmap(FRAME_NO_TOOLBAR_TOP_CENTER); - SkBitmap* top_right = - resources()->GetPartBitmap(FRAME_NO_TOOLBAR_TOP_RIGHT); + SkBitmap* top_left = tp->GetBitmapNamed(IDR_APP_TOP_LEFT); + SkBitmap* top_center = tp->GetBitmapNamed(IDR_APP_TOP_CENTER); + SkBitmap* top_right = tp->GetBitmapNamed(IDR_APP_TOP_RIGHT); int top_edge_y = client_area_top - top_center->height(); + client_area_top = std::min(top_edge_y + top_left->height(), height() - NonClientBorderThickness()); int height = client_area_top - top_edge_y; @@ -945,28 +758,42 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { top_right->width(), height, false); } + int client_area_bottom = std::max(client_area_top, height() - NonClientBorderThickness()); int client_area_height = client_area_bottom - client_area_top; - SkBitmap* right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); + + // Draw the toolbar color so that the one pixel areas down the sides + // show the right color even if not covered by the toolbar image. + canvas->DrawRectInt(ResourceBundle::toolbar_color, + client_area_bounds.x() - kClientEdgeThickness, client_area_top, + client_area_bounds.width() + kClientEdgeThickness, + client_area_bottom - client_area_top); + + // Draw the content/toolbar separator. + canvas->DrawLineInt(ResourceBundle::toolbar_separator_color, + client_area_bounds.x(), client_area_top, + client_area_bounds.x() + client_area_bounds.width(), + client_area_top); + + SkBitmap* right = tp->GetBitmapNamed(IDR_CONTENT_RIGHT_SIDE); canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, right->width(), client_area_height); - canvas->DrawBitmapInt( - *resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT), + *tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER), client_area_bounds.right(), client_area_bottom); - SkBitmap* bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); + SkBitmap* bottom = tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER); canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom, client_area_bounds.width(), bottom->height()); SkBitmap* bottom_left = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); + tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); canvas->DrawBitmapInt(*bottom_left, client_area_bounds.x() - bottom_left->width(), client_area_bottom); - SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); + SkBitmap* left = tp->GetBitmapNamed(IDR_CONTENT_LEFT_SIDE); canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), client_area_top, left->width(), client_area_height); } @@ -1102,9 +929,6 @@ gfx::Rect OpaqueBrowserFrameView::CalculateClientAreaBounds(int width, void OpaqueBrowserFrameView::InitClass() { static bool initialized = false; if (!initialized) { - active_resources_ = new ActiveWindowResources; - inactive_resources_ = new InactiveWindowResources; - #if defined(GOOGLE_CHROME_BUILD) distributor_logo_ = ResourceBundle::GetSharedInstance(). GetBitmapNamed(IDR_DISTRIBUTOR_LOGO_LIGHT); diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.h b/chrome/browser/views/frame/opaque_browser_frame_view.h index 1e917e9..08aee7e 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/views/frame/opaque_browser_frame_view.h @@ -16,7 +16,6 @@ class TabContents; class TabStrip; namespace views { class ImageButton; -class WindowResources; } class OpaqueBrowserFrameView : public BrowserNonClientFrameView, @@ -118,12 +117,6 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView, // Returns the bounds of the client area for the specified view size. gfx::Rect CalculateClientAreaBounds(int width, int height) const; - // Returns the set of resources to use to paint this view. - views::WindowResources* resources() const { - return frame_->IsActive() || paint_as_active() ? - current_active_resources_ : current_inactive_resources_; - } - // The layout rect of the title, if visible. gfx::Rect title_bounds_; @@ -151,20 +144,12 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView, // The bounds of the ClientView. gfx::Rect client_view_bounds_; - // The resources currently used to paint this view. - views::WindowResources* current_active_resources_; - views::WindowResources* current_inactive_resources_; - // The accessible name of this view. std::wstring accessible_name_; static void InitClass(); static void InitAppWindowResources(); static SkBitmap* distributor_logo_; - static views::WindowResources* active_resources_; - static views::WindowResources* inactive_resources_; - static views::WindowResources* active_otr_resources_; - static views::WindowResources* inactive_otr_resources_; static ChromeFont* title_font_; DISALLOW_EVIL_CONSTRUCTORS(OpaqueBrowserFrameView); diff --git a/chrome/browser/views/infobars/infobars.cc b/chrome/browser/views/infobars/infobars.cc index 4a04040..6749dec 100644 --- a/chrome/browser/views/infobars/infobars.cc +++ b/chrome/browser/views/infobars/infobars.cc @@ -34,7 +34,6 @@ static const SkColor kBackgroundColorTop = SkColorSetRGB(255, 242, 183); static const SkColor kBackgroundColorBottom = SkColorSetRGB(250, 230, 145); static const int kSeparatorLineHeight = 1; -static const SkColor kSeparatorColor = SkColorSetRGB(165, 165, 165); namespace { // Returns a centered y-position of a control of height specified in |prefsize| @@ -70,7 +69,7 @@ class InfoBarBackground : public views::Background { gradient_background_->Paint(canvas, view); // Now paint the separator line. - canvas->FillRectInt(kSeparatorColor, 0, + canvas->FillRectInt(ResourceBundle::toolbar_separator_color, 0, view->height() - kSeparatorLineHeight, view->width(), kSeparatorLineHeight); } diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index c1354f1..8490c58 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -16,6 +16,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/command_updater.h" +#include "chrome/browser/extensions/extension.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extensions_service.h" @@ -27,6 +28,7 @@ #include "chrome/browser/views/info_bubble.h" #include "chrome/browser/views/first_run_bubble.h" #include "chrome/browser/views/page_info_window.h" +#include "chrome/common/page_action.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "views/background.h" diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc index 6e3aff2..badd2f6 100644 --- a/chrome/browser/views/options/content_page_view.cc +++ b/chrome/browser/views/options/content_page_view.cc @@ -12,6 +12,7 @@ #include "app/gfx/chrome_canvas.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/gfx/native_theme.h" #include "chrome/browser/browser_process.h" @@ -19,6 +20,7 @@ #include "chrome/browser/views/options/fonts_languages_window_view.h" #include "chrome/browser/views/options/options_group_view.h" #include "chrome/browser/views/options/passwords_exceptions_window_view.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "grit/generated_resources.h" @@ -181,6 +183,8 @@ ContentPageView::ContentPageView(Profile* profile) passwords_neversave_radio_(NULL), fonts_lang_group_(NULL), fonts_and_languages_label_(NULL), + themes_group_(NULL), + themes_reset_button_(NULL), change_content_fonts_button_(NULL), OptionsPageView(profile) { } @@ -257,6 +261,9 @@ void ContentPageView::ButtonPressed(views::Button* sender) { GetRootWindow(), gfx::Rect(), new FontsLanguagesWindowView(profile()))->Show(); + } else if (sender == themes_reset_button_) { + UserMetricsRecordAction(L"Options_ThemesReset", profile()->GetPrefs()); + profile()->ClearTheme(); } } @@ -299,6 +306,14 @@ void ContentPageView::InitControlLayout() { layout->AddView(form_autofill_group_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + if (CommandLine::ForCurrentProcess()-> + HasSwitch(switches::kEnableExtensions)) { + layout->StartRow(0, single_column_view_set_id); + InitThemesGroup(); + layout->AddView(themes_group_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + } + // Init member prefs so we can update the controls if prefs change. default_download_location_.Init(prefs::kDownloadDefaultDirectory, profile()->GetPrefs(), this); @@ -445,6 +460,39 @@ void ContentPageView::InitPasswordSavingGroup() { true); } +void ContentPageView::InitFontsLangGroup() { + fonts_and_languages_label_ = new views::Label( + l10n_util::GetString(IDS_OPTIONS_FONTSETTINGS_INFO)); + fonts_and_languages_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + fonts_and_languages_label_->SetMultiLine(true); + change_content_fonts_button_ = new views::NativeButton( + this, + l10n_util::GetString(IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON)); + + using views::GridLayout; + using views::ColumnSet; + + views::View* contents = new views::View; + GridLayout* layout = new GridLayout(contents); + contents->SetLayoutManager(layout); + + const int single_column_view_set_id = 1; + ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); + column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1, + GridLayout::USE_PREF, 0, 0); + + layout->StartRow(0, single_column_view_set_id); + layout->AddView(fonts_and_languages_label_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, single_column_view_set_id); + layout->AddView(change_content_fonts_button_); + + fonts_lang_group_ = new OptionsGroupView( + contents, + l10n_util::GetString(IDS_OPTIONS_FONTSANDLANGUAGES_GROUP_NAME), + L"", true); +} + void ContentPageView::InitFormAutofillGroup() { form_autofill_checkbox_ = new views::Checkbox( l10n_util::GetString(IDS_AUTOFILL_SAVEFORMS)); @@ -468,17 +516,12 @@ void ContentPageView::InitFormAutofillGroup() { form_autofill_group_ = new OptionsGroupView( contents, l10n_util::GetString(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME), - L"", false); + L"", true); } -void ContentPageView::InitFontsLangGroup() { - fonts_and_languages_label_ = new views::Label( - l10n_util::GetString(IDS_OPTIONS_FONTSETTINGS_INFO)); - fonts_and_languages_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - fonts_and_languages_label_->SetMultiLine(true); - change_content_fonts_button_ = new views::NativeButton( - this, - l10n_util::GetString(IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON)); +void ContentPageView::InitThemesGroup() { + themes_reset_button_ = new views::NativeButton(this, + l10n_util::GetString(IDS_THEMES_RESET_BUTTON)); using views::GridLayout; using views::ColumnSet; @@ -490,18 +533,14 @@ void ContentPageView::InitFontsLangGroup() { const int single_column_view_set_id = 1; ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1, - GridLayout::USE_PREF, 0, 0); + GridLayout::USE_PREF, 0, 0); layout->StartRow(0, single_column_view_set_id); - layout->AddView(fonts_and_languages_label_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - layout->StartRow(0, single_column_view_set_id); - layout->AddView(change_content_fonts_button_); + layout->AddView(themes_reset_button_); - fonts_lang_group_ = new OptionsGroupView( - contents, - l10n_util::GetString(IDS_OPTIONS_FONTSANDLANGUAGES_GROUP_NAME), - L"", true); + themes_group_ = new OptionsGroupView( + contents, l10n_util::GetString(IDS_THEMES_GROUP_NAME), + L"", false); } void ContentPageView::UpdateDownloadDirectoryDisplay() { diff --git a/chrome/browser/views/options/content_page_view.h b/chrome/browser/views/options/content_page_view.h index 7d96e00..ff133e3 100644 --- a/chrome/browser/views/options/content_page_view.h +++ b/chrome/browser/views/options/content_page_view.h @@ -51,8 +51,9 @@ class ContentPageView : public OptionsPageView, // Init all the dialog controls. void InitDownloadLocation(); void InitPasswordSavingGroup(); - void InitFormAutofillGroup(); void InitFontsLangGroup(); + void InitFormAutofillGroup(); + void InitThemesGroup(); // Updates the directory displayed in the default download location view with // the current value of the pref. @@ -71,20 +72,24 @@ class ContentPageView : public OptionsPageView, views::RadioButton* passwords_asktosave_radio_; views::RadioButton* passwords_neversave_radio_; + // Controls for the Fonts and Languages group. + OptionsGroupView* fonts_lang_group_; + views::Label* fonts_and_languages_label_; + views::NativeButton* change_content_fonts_button_; + // Controls for the Form Autofill group OptionsGroupView* form_autofill_group_; views::Checkbox* form_autofill_checkbox_; + // Controls for the Themes group + OptionsGroupView* themes_group_; + views::NativeButton* themes_reset_button_; + // Controls for the Popup Blocking group. OptionsGroupView* popups_group_; views::RadioButton* popups_show_minimized_radio_; views::RadioButton* popups_block_all_radio_; - // Controls for the Fonts and Languages group. - OptionsGroupView* fonts_lang_group_; - views::Label* fonts_and_languages_label_; - views::NativeButton* change_content_fonts_button_; - StringPrefMember default_download_location_; BooleanPrefMember ask_for_save_location_; BooleanPrefMember ask_to_save_passwords_; diff --git a/chrome/browser/views/options/cookies_view.cc b/chrome/browser/views/options/cookies_view.cc index 593487b..cc8d65c 100644 --- a/chrome/browser/views/options/cookies_view.cc +++ b/chrome/browser/views/options/cookies_view.cc @@ -10,6 +10,7 @@ #include "app/gfx/color_utils.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "base/message_loop.h" #include "base/string_util.h" #include "base/time_format.h" #include "chrome/browser/profile.h" diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc index 87d0d01..e7b664b 100644 --- a/chrome/browser/views/tabs/tab_renderer.cc +++ b/chrome/browser/views/tabs/tab_renderer.cc @@ -12,6 +12,7 @@ #include "app/resource_bundle.h" #include "app/win_util.h" #include "chrome/browser/browser.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" @@ -43,7 +44,6 @@ static const int kPulseDurationMs = 200; // How opaque to make the hover state (out of 1). static const double kHoverOpacity = 0.33; -static const double kHoverOpacityVista = 0.7; // TODO(beng): (Cleanup) This stuff should move onto the class. static ChromeFont* title_font = NULL; @@ -53,6 +53,7 @@ static SkBitmap* close_button_h = NULL; static SkBitmap* close_button_p = NULL; static int close_button_height = 0; static int close_button_width = 0; + static SkBitmap* waiting_animation_frames = NULL; static SkBitmap* loading_animation_frames = NULL; static SkBitmap* crashed_fav_icon = NULL; @@ -63,16 +64,16 @@ static SkBitmap* download_icon = NULL; static int download_icon_width = 0; static int download_icon_height = 0; +TabRenderer::TabImage TabRenderer::tab_alpha = {0}; TabRenderer::TabImage TabRenderer::tab_active = {0}; TabRenderer::TabImage TabRenderer::tab_inactive = {0}; -TabRenderer::TabImage TabRenderer::tab_inactive_otr = {0}; -TabRenderer::TabImage TabRenderer::tab_hover = {0}; namespace { void InitResources() { static bool initialized = false; if (!initialized) { + // TODO(glen): Allow theming of these. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); title_font = new ChromeFont(rb.GetFont(ResourceBundle::BaseFont)); title_font_height = title_font->height(); @@ -83,7 +84,7 @@ void InitResources() { close_button_width = close_button_n->width(); close_button_height = close_button_n->height(); - TabRenderer::LoadTabImages(win_util::ShouldUseVistaFrame()); + TabRenderer::LoadTabImages(); // The loading animation image is a strip of states. Each state must be // square, so the height must divide the width evenly. @@ -215,7 +216,8 @@ TabRenderer::TabRenderer() showing_close_button_(false), crash_animation_(NULL), fav_icon_hiding_offset_(0), - should_display_crashed_favicon_(false) { + should_display_crashed_favicon_(false), + theme_provider_(NULL) { InitResources(); // Add the Close Button. @@ -236,6 +238,24 @@ TabRenderer::~TabRenderer() { delete crash_animation_; } +void TabRenderer::ViewHierarchyChanged(bool is_add, View* parent, View* child) { + if (parent->GetThemeProvider()) + SetThemeProvider(parent->GetThemeProvider()); +} + +ThemeProvider* TabRenderer::GetThemeProvider() { + ThemeProvider* tp = View::GetThemeProvider(); + if (tp) + return tp; + + if (theme_provider_) + return theme_provider_; + + // return contents->profile()->GetThemeProvider(); + NOTREACHED() << "Unable to find a theme provider"; + return NULL; +} + void TabRenderer::UpdateData(TabContents* contents, bool loading_only) { DCHECK(contents); if (!loading_only) { @@ -246,6 +266,9 @@ void TabRenderer::UpdateData(TabContents* contents, bool loading_only) { data_.favicon = contents->GetFavIcon(); } + // TODO(glen): Temporary hax. + theme_provider_ = contents->profile()->GetThemeProvider(); + // Loading state also involves whether we show the favicon, since that's where // we display the throbber. data_.loading = contents->is_loading(); @@ -411,8 +434,11 @@ void TabRenderer::Paint(ChromeCanvas* canvas) { Browser::FormatTitleForDisplay(&title); } - SkColor title_color = IsSelected() ? kSelectedTitleColor - : kUnselectedTitleColor; + SkColor title_color = GetThemeProvider()-> + GetColor(IsSelected() ? + BrowserThemeProvider::COLOR_TAB_TEXT : + BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT); + canvas->DrawStringInt(title, *title_font, title_color, title_bounds_.x(), title_bounds_.y(), title_bounds_.width(), title_bounds_.height()); @@ -507,8 +533,7 @@ void TabRenderer::OnMouseExited(const views::MouseEvent& e) { } void TabRenderer::ThemeChanged() { - if (GetWindow()) - LoadTabImages(GetWindow()->GetNonClientView()->UseNativeFrame()); + LoadTabImages(); View::ThemeChanged(); } @@ -541,33 +566,111 @@ void TabRenderer::PaintTabBackground(ChromeCanvas* canvas) { Animation* animation = hover_animation_.get(); if (pulse_animation_->IsAnimating()) animation = pulse_animation_.get(); + + PaintInactiveTabBackground(canvas); if (animation->GetCurrentValue() > 0) { - PaintHoverTabBackground(canvas, animation->GetCurrentValue() * - (GetWindow()->GetNonClientView()->UseNativeFrame() ? - kHoverOpacityVista : kHoverOpacity)); - } else { - PaintInactiveTabBackground(canvas); + SkRect bounds; + bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); + canvas->saveLayerAlpha(&bounds, + static_cast<int>(animation->GetCurrentValue() * kHoverOpacity * 0xff), + SkCanvas::kARGB_ClipLayer_SaveFlag); + canvas->drawARGB(0, 255, 255, 255, SkPorterDuff::kClear_Mode); + PaintActiveTabBackground(canvas); + canvas->restore(); } } } void TabRenderer::PaintInactiveTabBackground(ChromeCanvas* canvas) { bool is_otr = data_.off_the_record; - canvas->DrawBitmapInt(is_otr ? *tab_inactive_otr.image_l : - *tab_inactive.image_l, 0, 0); - canvas->TileImageInt(is_otr ? *tab_inactive_otr.image_c : - *tab_inactive.image_c, tab_inactive.l_width, 0, - width() - tab_inactive.l_width - - tab_inactive.r_width, height()); - canvas->DrawBitmapInt(is_otr ? *tab_inactive_otr.image_r : - *tab_inactive.image_r, + + // The tab image needs to be lined up with the background image + // so that it feels partially transparent. + int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) + 1; + int offset_y = 20; + + int tab_id; + if (GetWidget() && + GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) { + tab_id = IDR_THEME_TAB_BACKGROUND_V; + } else { + tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : + IDR_THEME_TAB_BACKGROUND; + } + + SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id); + + // Draw left edge. + SkBitmap tab_l = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, offset, offset_y, + tab_active.l_width, height()); + SkBitmap theme_l = skia::ImageOperations::CreateMaskedBitmap( + tab_l, *tab_alpha.image_l); + canvas->DrawBitmapInt(theme_l, + 0, 0, theme_l.width(), theme_l.height() - 1, + 0, 0, theme_l.width(), theme_l.height() - 1, + false); + + // Draw right edge. + SkBitmap tab_r = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, + offset + width() - tab_active.r_width, offset_y, + tab_active.r_width, height()); + SkBitmap theme_r = skia::ImageOperations::CreateMaskedBitmap( + tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, + 0, 0, theme_r.width(), theme_r.height() - 1, + width() - theme_r.width(), 0, theme_r.width(), theme_r.height() - 1, + false); + + // Draw center. + canvas->TileImageInt(*tab_bg, + offset + tab_active.l_width, 2 + offset_y, // 2 is the drop shadow offset. + tab_active.l_width, 2, + width() - tab_active.l_width - tab_active.r_width, height() - 3); + + canvas->DrawBitmapInt(*tab_inactive.image_l, 0, 0); + canvas->TileImageInt(*tab_inactive.image_c, + tab_inactive.l_width, 0, + width() - tab_inactive.l_width - tab_inactive.r_width, + height()); + canvas->DrawBitmapInt(*tab_inactive.image_r, width() - tab_inactive.r_width, 0); } void TabRenderer::PaintActiveTabBackground(ChromeCanvas* canvas) { + int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) + 1; + ThemeProvider* tp = GetThemeProvider(); + if (!tp) + NOTREACHED() << "Unable to get theme provider"; + + SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR); + + // Draw left edge. + SkBitmap tab_l = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, offset, 0, tab_active.l_width, height()); + SkBitmap theme_l = skia::ImageOperations::CreateMaskedBitmap( + tab_l, *tab_alpha.image_l); + canvas->DrawBitmapInt(theme_l, 0, 0); + + // Draw right edge. + SkBitmap tab_r = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, + offset + width() - tab_active.r_width, 0, + tab_active.r_width, height()); + SkBitmap theme_r = skia::ImageOperations::CreateMaskedBitmap( + tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, width() - tab_active.r_width, 0); + + // Draw center. + canvas->TileImageInt(*tab_bg, + offset + tab_active.l_width, 2, + tab_active.l_width, 2, + width() - tab_active.l_width - tab_active.r_width, height() - 2); + canvas->DrawBitmapInt(*tab_active.image_l, 0, 0); canvas->TileImageInt(*tab_active.image_c, tab_active.l_width, 0, - width() - tab_active.l_width - tab_active.r_width, height()); + width() - tab_active.l_width - tab_active.r_width, height()); canvas->DrawBitmapInt(*tab_active.image_r, width() - tab_active.r_width, 0); } @@ -575,15 +678,11 @@ void TabRenderer::PaintHoverTabBackground(ChromeCanvas* canvas, double opacity) { bool is_otr = data_.off_the_record; SkBitmap left = skia::ImageOperations::CreateBlendedBitmap( - (is_otr ? *tab_inactive_otr.image_l : - *tab_inactive.image_l), *tab_hover.image_l, opacity); + *tab_inactive.image_l, *tab_active.image_l, opacity); SkBitmap center = skia::ImageOperations::CreateBlendedBitmap( - (is_otr ? *tab_inactive_otr.image_c : - *tab_inactive.image_c), *tab_hover.image_c, opacity); + *tab_inactive.image_c, *tab_active.image_c, opacity); SkBitmap right = skia::ImageOperations::CreateBlendedBitmap( - (is_otr ? *tab_inactive_otr.image_r : - *tab_inactive.image_r), - *tab_hover.image_r, opacity); + *tab_inactive.image_r, *tab_active.image_r, opacity); canvas->DrawBitmapInt(left, 0, 0); canvas->TileImageInt(center, tab_active.l_width, 0, @@ -668,41 +767,26 @@ void TabRenderer::ResetCrashedFavIcon() { } // static -void TabRenderer::LoadTabImages(bool use_vista_images) { +void TabRenderer::LoadTabImages() { + // We're not letting people override tab images just yet. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT); + tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT); + tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT); tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER); tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT); tab_active.l_width = tab_active.image_l->width(); tab_active.r_width = tab_active.image_r->width(); - tab_hover.image_l = rb.GetBitmapNamed(IDR_TAB_HOVER_LEFT); - tab_hover.image_c = rb.GetBitmapNamed(IDR_TAB_HOVER_CENTER); - tab_hover.image_r = rb.GetBitmapNamed(IDR_TAB_HOVER_RIGHT); - - if (use_vista_images) { - tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_V); - tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_V); - tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_V); - - // Our Vista frame doesn't change background color to show OTR, - // so we continue to use the existing background tabs. - tab_inactive_otr.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_V); - tab_inactive_otr.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_V); - tab_inactive_otr.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_V); - } else { - tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); - tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); - tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); - - tab_inactive_otr.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_OTR); - tab_inactive_otr.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_OTR); - tab_inactive_otr.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_OTR); - } + tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); + tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); + tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); tab_inactive.l_width = tab_inactive.image_l->width(); tab_inactive.r_width = tab_inactive.image_r->width(); - // tab_[hover,inactive_otr] width are not used and are initialized to 0 - // during static initialization. + + loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); + waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); } diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h index f498c2a..d278fb5 100644 --- a/chrome/browser/views/tabs/tab_renderer.h +++ b/chrome/browser/views/tabs/tab_renderer.h @@ -36,6 +36,10 @@ class TabRenderer : public views::View, TabRenderer(); virtual ~TabRenderer(); + // Overridden from views: + void ViewHierarchyChanged(bool is_add, View* parent, View* child); + ThemeProvider* GetThemeProvider(); + // Updates the data the Tab uses to render itself from the specified // TabContents. // @@ -56,6 +60,13 @@ class TabRenderer : public views::View, void StartPulse(); void StopPulse(); + // Set the theme provider - because we get detached, we are frequently + // outside of a hierarchy with a theme provider at the top. This should be + // called whenever we're detached or attached to a hierarchy. + void SetThemeProvider(ThemeProvider* provider) { + theme_provider_ = provider; + } + // Returns the minimum possible size of a single unselected Tab. static gfx::Size GetMinimumUnselectedSize(); // Returns the minimum possible size of a selected Tab. Selected tabs must @@ -66,9 +77,8 @@ class TabRenderer : public views::View, // available. static gfx::Size GetStandardSize(); - // Loads the images to be used for the tab background. Uses the images for - // Vista if |use_vista_images| is true. - static void LoadTabImages(bool use_vista_images); + // Loads the images to be used for the tab background. + static void LoadTabImages(); protected: views::ImageButton* close_button() const { return close_button_; } @@ -166,7 +176,7 @@ class TabRenderer : public views::View, }; static TabImage tab_active; static TabImage tab_inactive; - static TabImage tab_inactive_otr; + static TabImage tab_alpha; static TabImage tab_hover; // Whether we're showing the icon. It is cached so that we can detect when it @@ -189,6 +199,8 @@ class TabRenderer : public views::View, bool should_display_crashed_favicon_; + ThemeProvider* theme_provider_; + static void InitClass(); static bool initialized_; diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index c3c98d2..333dcf4 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -23,6 +23,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/user_data_manager.h" #include "chrome/browser/views/bookmark_menu_button.h" #include "chrome/browser/views/dom_view.h" @@ -138,86 +139,49 @@ void BrowserToolbarView::SetProfile(Profile* profile) { } void BrowserToolbarView::CreateLeftSideControls() { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - back_ = new views::ButtonDropDown(this, back_menu_model_.get()); back_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN | views::Event::EF_MIDDLE_BUTTON_DOWN); back_->set_tag(IDC_BACK); back_->SetImageAlignment(views::ImageButton::ALIGN_RIGHT, views::ImageButton::ALIGN_TOP); - back_->SetImage(views::CustomButton::BS_NORMAL, rb.GetBitmapNamed(IDR_BACK)); - back_->SetImage(views::CustomButton::BS_HOT, rb.GetBitmapNamed(IDR_BACK_H)); - back_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_BACK_P)); - back_->SetImage(views::CustomButton::BS_DISABLED, - rb.GetBitmapNamed(IDR_BACK_D)); back_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_BACK)); back_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_BACK)); back_->SetID(VIEW_ID_BACK_BUTTON); - AddChildView(back_); forward_ = new views::ButtonDropDown(this, forward_menu_model_.get()); forward_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN | - views::Event::EF_MIDDLE_BUTTON_DOWN); + views::Event::EF_MIDDLE_BUTTON_DOWN); forward_->set_tag(IDC_FORWARD); - forward_->SetImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_FORWARD)); - forward_->SetImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_FORWARD_H)); - forward_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_FORWARD_P)); - forward_->SetImage(views::CustomButton::BS_DISABLED, - rb.GetBitmapNamed(IDR_FORWARD_D)); forward_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_FORWARD)); forward_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_FORWARD)); forward_->SetID(VIEW_ID_FORWARD_BUTTON); - AddChildView(forward_); reload_ = new views::ImageButton(this); reload_->set_tag(IDC_RELOAD); - reload_->SetImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_RELOAD)); - reload_->SetImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_RELOAD_H)); - reload_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_RELOAD_P)); reload_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_RELOAD)); reload_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_RELOAD)); reload_->SetID(VIEW_ID_RELOAD_BUTTON); - AddChildView(reload_); home_ = new views::ImageButton(this); home_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN | views::Event::EF_MIDDLE_BUTTON_DOWN); home_->set_tag(IDC_HOME); - home_->SetImage(views::CustomButton::BS_NORMAL, rb.GetBitmapNamed(IDR_HOME)); - home_->SetImage(views::CustomButton::BS_HOT, rb.GetBitmapNamed(IDR_HOME_H)); - home_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_HOME_P)); home_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_HOME)); home_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_HOME)); home_->SetID(VIEW_ID_HOME_BUTTON); + + LoadLeftSideControlsImages(); + + AddChildView(back_); + AddChildView(forward_); + AddChildView(reload_); AddChildView(home_); } void BrowserToolbarView::CreateCenterStack(Profile *profile) { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - star_ = new ToolbarStarToggle(this, this); star_->set_tag(IDC_STAR); - star_->SetImage(views::CustomButton::BS_NORMAL, rb.GetBitmapNamed(IDR_STAR)); - star_->SetImage(views::CustomButton::BS_HOT, rb.GetBitmapNamed(IDR_STAR_H)); - star_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_STAR_P)); - star_->SetImage(views::CustomButton::BS_DISABLED, - rb.GetBitmapNamed(IDR_STAR_D)); - star_->SetToggledImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_STARRED)); - star_->SetToggledImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_STARRED_H)); - star_->SetToggledImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_STARRED_P)); star_->SetDragController(this); star_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_STAR)); star_->SetToggledTooltipText(l10n_util::GetString(IDS_TOOLTIP_STARRED)); @@ -229,68 +193,37 @@ void BrowserToolbarView::CreateCenterStack(Profile *profile) { model_, this, display_mode_ == DISPLAYMODE_LOCATION, this); - AddChildView(location_bar_); - location_bar_->Init(); // The Go button. go_ = new GoButton(location_bar_, browser_); - go_->SetImage(views::CustomButton::BS_NORMAL, rb.GetBitmapNamed(IDR_GO)); - go_->SetImage(views::CustomButton::BS_HOT, rb.GetBitmapNamed(IDR_GO_H)); - go_->SetImage(views::CustomButton::BS_PUSHED, rb.GetBitmapNamed(IDR_GO_P)); - go_->SetToggledImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_STOP)); - go_->SetToggledImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_STOP_H)); - go_->SetToggledImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_STOP_P)); go_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_GO)); go_->SetID(VIEW_ID_GO_BUTTON); - AddChildView(go_); -} - -void BrowserToolbarView::Update(TabContents* tab, bool should_restore_state) { - tab_ = tab; - if (!location_bar_) - return; + LoadCenterStackImages(); - location_bar_->Update(should_restore_state ? tab : NULL); -} - -void BrowserToolbarView::OnInputInProgress(bool in_progress) { - // The edit should make sure we're only notified when something changes. - DCHECK(model_->input_in_progress() != in_progress); - - model_->set_input_in_progress(in_progress); - location_bar_->Update(NULL); + AddChildView(location_bar_); + location_bar_->Init(); + AddChildView(go_); } void BrowserToolbarView::CreateRightSideControls(Profile* profile) { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); + ThemeProvider* tp = GetThemeProvider(); page_menu_ = new views::MenuButton(NULL, std::wstring(), this, false); - - // We use different menu button images if the locale is right-to-left. - if (UILayoutIsRightToLeft()) - page_menu_->SetIcon(*rb.GetBitmapNamed(IDR_MENU_PAGE_RTL)); - else - page_menu_->SetIcon(*rb.GetBitmapNamed(IDR_MENU_PAGE)); - page_menu_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_PAGE)); page_menu_->SetTooltipText(l10n_util::GetString(IDS_PAGEMENU_TOOLTIP)); page_menu_->SetID(VIEW_ID_PAGE_MENU); - AddChildView(page_menu_); - app_menu_ = new views::MenuButton(NULL, std::wstring(), this, false); - if (UILayoutIsRightToLeft()) - app_menu_->SetIcon(*rb.GetBitmapNamed(IDR_MENU_CHROME_RTL)); - else - app_menu_->SetIcon(*rb.GetBitmapNamed(IDR_MENU_CHROME)); + app_menu_ = new views::MenuButton(NULL, std::wstring(), this, false); app_menu_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_APP)); app_menu_->SetTooltipText(l10n_util::GetStringF(IDS_APPMENU_TOOLTIP, l10n_util::GetString(IDS_PRODUCT_NAME))); app_menu_->SetID(VIEW_ID_APP_MENU); + + LoadRightSideControlsImages(); + + AddChildView(page_menu_); AddChildView(app_menu_); if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kBookmarkMenu)) { @@ -301,6 +234,96 @@ void BrowserToolbarView::CreateRightSideControls(Profile* profile) { } } +void BrowserToolbarView::LoadLeftSideControlsImages() { + ThemeProvider* tp = GetThemeProvider(); + + back_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_BACK)); + back_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_BACK_H)); + back_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_BACK_P)); + back_->SetImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_BACK_D)); + + forward_->SetImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_FORWARD)); + forward_->SetImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_FORWARD_H)); + forward_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_FORWARD_P)); + forward_->SetImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_FORWARD_D)); + + reload_->SetImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_RELOAD)); + reload_->SetImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_RELOAD_H)); + reload_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_RELOAD_P)); + + home_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_HOME)); + home_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_HOME_H)); + home_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_HOME_P)); +} + +void BrowserToolbarView::LoadCenterStackImages() { + ThemeProvider* tp = GetThemeProvider(); + + star_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_STAR)); + star_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_STAR_H)); + star_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_STAR_P)); + star_->SetImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_STAR_D)); + star_->SetToggledImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_STARRED)); + star_->SetToggledImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_STARRED_H)); + star_->SetToggledImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_STARRED_P)); + + go_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_GO)); + go_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_GO_H)); + go_->SetImage(views::CustomButton::BS_PUSHED, tp->GetBitmapNamed(IDR_GO_P)); + go_->SetToggledImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_STOP)); + go_->SetToggledImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_STOP_H)); + go_->SetToggledImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_STOP_P)); +} + +void BrowserToolbarView::LoadRightSideControlsImages() { + ThemeProvider* tp = GetThemeProvider(); + + // We use different menu button images if the locale is right-to-left. + if (UILayoutIsRightToLeft()) + page_menu_->SetIcon(*tp->GetBitmapNamed(IDR_MENU_PAGE_RTL)); + else + page_menu_->SetIcon(*tp->GetBitmapNamed(IDR_MENU_PAGE)); + if (UILayoutIsRightToLeft()) + app_menu_->SetIcon(*tp->GetBitmapNamed(IDR_MENU_CHROME_RTL)); + else + app_menu_->SetIcon(*tp->GetBitmapNamed(IDR_MENU_CHROME)); +} + +void BrowserToolbarView::Update(TabContents* tab, bool should_restore_state) { + tab_ = tab; + + if (!location_bar_) + return; + + location_bar_->Update(should_restore_state ? tab : NULL); +} + +void BrowserToolbarView::OnInputInProgress(bool in_progress) { + // The edit should make sure we're only notified when something changes. + DCHECK(model_->input_in_progress() != in_progress); + + model_->set_input_in_progress(in_progress); + location_bar_->Update(NULL); +} + void BrowserToolbarView::Layout() { // If we have not been initialized yet just do nothing. if (back_ == NULL) @@ -758,6 +781,12 @@ void BrowserToolbarView::SetAccessibleName(const std::wstring& name) { accessible_name_.assign(name); } +void BrowserToolbarView::ThemeChanged() { + LoadLeftSideControlsImages(); + LoadCenterStackImages(); + LoadRightSideControlsImages(); +} + int BrowserToolbarView::GetNextAccessibleViewIndex(int view_index, bool nav_left) { int modifier = 1; diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h index c5a9f83..b5f3861 100644 --- a/chrome/browser/views/toolbar_view.h +++ b/chrome/browser/views/toolbar_view.h @@ -63,6 +63,7 @@ class BrowserToolbarView : public views::View, virtual bool GetAccessibleName(std::wstring* name); virtual bool GetAccessibleRole(AccessibilityTypes::Role* role); virtual void SetAccessibleName(const std::wstring& name); + virtual void ThemeChanged(); // Overridden from EncodingMenuControllerDelegate: virtual bool IsItemChecked(int id) const; @@ -147,6 +148,9 @@ class BrowserToolbarView : public views::View, void CreateLeftSideControls(); void CreateCenterStack(Profile* profile); void CreateRightSideControls(Profile* profile); + void LoadLeftSideControlsImages(); + void LoadCenterStackImages(); + void LoadRightSideControlsImages(); // Updates the controls to display the security appropriately (highlighted if // secure). diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 6941455..8878444 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -167,6 +167,7 @@ '../app/resource_bundle_mac.mm', '../app/slide_animation.cc', '../app/slide_animation.h', + '../app/theme_provider.h', '../app/throb_animation.cc', '../app/throb_animation.h', '../app/win_util.cc', diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 82d62e0..3364fc1 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -534,6 +534,9 @@ class NotificationType { // Sent when new extensions are loaded. The details are an ExtensionList*. EXTENSIONS_LOADED, + // Sent when a new theme is installed. The details are an extension. + THEME_INSTALLED, + // Sent when new extensions are installed. The details are a FilePath. EXTENSION_INSTALLED, diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 266e60b..f414d27 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -246,6 +246,10 @@ const wchar_t kPrintingPageHeaderRight[] = L"printing.page.header.right"; const wchar_t kPrintingPageFooterLeft[] = L"printing.page.footer.left"; const wchar_t kPrintingPageFooterCenter[] = L"printing.page.footer.center"; const wchar_t kPrintingPageFooterRight[] = L"printing.page.footer.right"; +const wchar_t kCurrentThemeID[] = L"extensions.theme.id"; +const wchar_t kCurrentThemeImages[] = L"extensions.theme.images"; +const wchar_t kCurrentThemeColors[] = L"extensions.theme.colors"; +const wchar_t kCurrentThemeTints[] = L"extensions.theme.tints"; // Boolean that indicates whether we should check if we are the default browser // on start-up. diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 92c674d..83fdfd1 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -88,6 +88,10 @@ extern const wchar_t kPrintingPageHeaderRight[]; extern const wchar_t kPrintingPageFooterLeft[]; extern const wchar_t kPrintingPageFooterCenter[]; extern const wchar_t kPrintingPageFooterRight[]; +extern const wchar_t kCurrentThemeID[]; +extern const wchar_t kCurrentThemeImages[]; +extern const wchar_t kCurrentThemeColors[]; +extern const wchar_t kCurrentThemeTints[]; extern const wchar_t kCheckDefaultBrowser[]; // Local state diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index e8c9416..316a83a 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -49,5 +49,6 @@ const char kChromeUIHistoryHost[] = "history"; const char kChromeUIInspectorHost[] = "inspector"; const char kChromeUINewTabHost[] = "newtab"; const char kChromeUIThumbnailPath[] = "thumb"; +const char kChromeUIThemePath[] = "theme"; } // namespace chrome diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 21dff62..b06bcb8 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -56,6 +56,7 @@ extern const char kChromeUIHistoryHost[]; extern const char kChromeUIInspectorHost[]; extern const char kChromeUINewTabHost[]; extern const char kChromeUIThumbnailPath[]; +extern const char kChromeUIThemePath[]; } // namespace chrome diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h index f7dbba3..7f336c3 100755 --- a/chrome/renderer/extensions/bindings_utils.h +++ b/chrome/renderer/extensions/bindings_utils.h @@ -7,6 +7,7 @@ #include "app/resource_bundle.h" #include "base/singleton.h" +#include "base/string_piece.h" #include <string> diff --git a/chrome/test/data/extensions/theme.crx b/chrome/test/data/extensions/theme.crx Binary files differnew file mode 100644 index 0000000..bcdb04c --- /dev/null +++ b/chrome/test/data/extensions/theme.crx diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index d715210..6d7e92e 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -62,6 +62,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void ConfirmBrowserCloseWithPendingDownloads() {} virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate, void* parent_window) {} + virtual void UserChangedTheme() {} protected: virtual void DestroyBrowser() {} diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h index e0bbc0b..310eac8 100644 --- a/chrome/test/testing_profile.h +++ b/chrome/test/testing_profile.h @@ -119,6 +119,12 @@ class TestingProfile : public Profile { virtual bool HasCreatedDownloadManager() const { return false; } + virtual void InitThemes() { } + virtual void SetTheme(Extension* extension) { } + virtual void ClearTheme() { } + virtual ThemeProvider* GetThemeProvider() { + return NULL; + } virtual URLRequestContext* GetRequestContext() { return NULL; } diff --git a/skia/ext/image_operations.cc b/skia/ext/image_operations.cc index a6ccec4..07fb97b 100644 --- a/skia/ext/image_operations.cc +++ b/skia/ext/image_operations.cc @@ -16,7 +16,6 @@ #include "SkBitmap.h" #include "skia/ext/convolver.h" #include "skia/include/SkColorPriv.h" -#include "skia/ext/skia_utils.h" namespace skia { @@ -460,7 +459,7 @@ SkBitmap ImageOperations::CreateBlurredBitmap(const SkBitmap& bitmap, // static SkBitmap ImageOperations::CreateHSLShiftedBitmap(const SkBitmap& bitmap, - float hsl_shift[3]) { + HSL hsl_shift) { DCHECK(bitmap.empty() == false); DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config); @@ -494,30 +493,30 @@ SkBitmap ImageOperations::CreateHSLShiftedBitmap(const SkBitmap& bitmap, static_cast<int>(b * 255.0)); } - float pixel_hsl[3]; + HSL pixel_hsl = { 0, 0, 0 }; SkColorToHSL(color, pixel_hsl); // Replace the hue with the tint's hue. - if (hsl_shift[0] >= 0) - pixel_hsl[0] = hsl_shift[0]; + if (hsl_shift.h >= 0) + pixel_hsl.h = hsl_shift.h; // Change the saturation. - if (hsl_shift[1] >= 0) { - if (hsl_shift[1] <= 0.5) { - pixel_hsl[1] *= hsl_shift[1] * 2.0; + if (hsl_shift.s >= 0) { + if (hsl_shift.s <= 0.5) { + pixel_hsl.s *= hsl_shift.s * 2.0; } else { - pixel_hsl[1] = pixel_hsl[1] + (1.0 - pixel_hsl[1]) * - ((hsl_shift[1] - 0.5) * 2.0); + pixel_hsl.s = pixel_hsl.s + (1.0 - pixel_hsl.s) * + ((hsl_shift.s - 0.5) * 2.0); } } // Change the lightness. - if (hsl_shift[2] >= 0) { - if (hsl_shift[2] <= 0.5) { - pixel_hsl[2] *= hsl_shift[2] * 2.0; + if (hsl_shift.l >= 0) { + if (hsl_shift.l <= 0.5) { + pixel_hsl.l *= hsl_shift.l * 2.0; } else { - pixel_hsl[2] = pixel_hsl[2] + (1.0 - pixel_hsl[2]) * - ((hsl_shift[2] - 0.5) * 2.0); + pixel_hsl.l = pixel_hsl.l + (1.0 - pixel_hsl.l) * + ((hsl_shift.l - 0.5) * 2.0); } } diff --git a/skia/ext/image_operations.h b/skia/ext/image_operations.h index 5c46b36..b5e049d 100644 --- a/skia/ext/image_operations.h +++ b/skia/ext/image_operations.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/gfx/rect.h" +#include "skia/ext/skia_utils.h" #include "SkColor.h" class SkBitmap; @@ -80,7 +81,7 @@ class ImageOperations { // 0.5 = leave unchanged. // 1 = full lightness (make all pixels white). static SkBitmap CreateHSLShiftedBitmap(const SkBitmap& bitmap, - float hsl_shift[3]); + HSL hsl_shift); // Create a bitmap that is cropped from another bitmap. This is special // because it tiles the original bitmap, so your coordinates can extend diff --git a/skia/ext/image_operations_unittest.cc b/skia/ext/image_operations_unittest.cc index 5ed69da..8f7e9be 100644 --- a/skia/ext/image_operations_unittest.cc +++ b/skia/ext/image_operations_unittest.cc @@ -309,7 +309,7 @@ TEST(ImageOperations, CreateHSLShiftedBitmapToSame) { } } - float hsl[3] = { -1, -1, -1 }; + skia::HSL hsl = { -1, -1, -1 }; SkBitmap shifted = skia::ImageOperations::CreateHSLShiftedBitmap(src, hsl); @@ -340,7 +340,7 @@ TEST(ImageOperations, CreateHSLShiftedBitmapHueOnly) { } // Shift to red. - float hsl[3] = { 0, -1, -1 }; + skia::HSL hsl = { 0, -1, -1 }; SkBitmap shifted = skia::ImageOperations::CreateHSLShiftedBitmap(src, hsl); diff --git a/skia/ext/skia_utils.cc b/skia/ext/skia_utils.cc index 1424957..3b5484f 100644 --- a/skia/ext/skia_utils.cc +++ b/skia/ext/skia_utils.cc @@ -39,25 +39,25 @@ static inline double calcHue(double temp1, double temp2, double hueVal) { return temp1; } -SkPMColor HSLToSKColor(U8CPU alpha, float hsl[3]) { - double hue = SkScalarToDouble(hsl[0]); - double saturation = SkScalarToDouble(hsl[1]); - double lightness = SkScalarToDouble(hsl[2]); +SkPMColor HSLToSKColor(U8CPU alpha, HSL hsl) { + double hue = hsl.h; + double saturation = hsl.s; + double lightness = hsl.l; double scaleFactor = 256.0; // If there's no color, we don't care about hue and can do everything based // on brightness. if (!saturation) { - U8CPU lightness; + U8CPU light; - if (hsl[2] < 0) - lightness = 0; - else if (hsl[2] >= SK_Scalar1) - lightness = 255; + if (lightness < 0) + light = 0; + else if (lightness >= SK_Scalar1) + light = 255; else - lightness = SkScalarToFixed(hsl[2]) >> 8; + light = SkDoubleToFixed(lightness) >> 8; - unsigned greyValue = SkAlphaMul(lightness, alpha); + unsigned greyValue = SkAlphaMul(light, alpha); return SkColorSetARGB(alpha, greyValue, greyValue, greyValue); } @@ -76,7 +76,7 @@ SkPMColor HSLToSKColor(U8CPU alpha, float hsl[3]) { SkAlphaMul(static_cast<int>(bh * scaleFactor), alpha)); } -void SkColorToHSL(SkPMColor c, float hsl[3]) { +void SkColorToHSL(SkPMColor c, HSL& hsl) { double r = SkColorGetR(c) / 255.0; double g = SkColorGetG(c) / 255.0; double b = SkColorGetB(c) / 255.0; @@ -115,9 +115,37 @@ void SkColorToHSL(SkPMColor c, float hsl[3]) { if (h > 1) h -= 1; } - hsl[0] = h; - hsl[1] = s; - hsl[2] = l; + hsl.h = h; + hsl.s = s; + hsl.l = l; +} + +SkColor HSLShift(HSL hsl, HSL shift) { + // Replace the hue with the tint's hue. + if (shift.h >= 0) + hsl.h = shift.h; + + // Change the saturation. + if (shift.s >= 0) { + if (shift.s <= 0.5) { + hsl.s *= shift.s * 2.0; + } else { + hsl.s = hsl.s + (1.0 - hsl.s) * + ((shift.s - 0.5) * 2.0); + } + } + + // Change the lightness. + if (shift.l >= 0) { + if (shift.l <= 0.5) { + hsl.l *= shift.l * 2.0; + } else { + hsl.l = hsl.l + (1.0 - hsl.l) * + ((shift.l - 0.5) * 2.0); + } + } + + return skia::HSLToSKColor(0xff, hsl); } diff --git a/skia/ext/skia_utils.h b/skia/ext/skia_utils.h index 98fa1b0..0f61b18 100644 --- a/skia/ext/skia_utils.h +++ b/skia/ext/skia_utils.h @@ -10,6 +10,12 @@ namespace skia { +struct HSL { + double h; + double s; + double l; +}; + // Creates a vertical gradient shader. The caller owns the shader. // Example usage to avoid leaks: // paint.setShader(gfx::CreateGradientShader(0, 10, red, blue))->safeUnref(); @@ -22,10 +28,27 @@ SkShader* CreateGradientShader(int start_point, SkColor end_color); // Convert a premultiplied SkColor to a HSL value. -void SkColorToHSL(SkPMColor c, float hsl[3]); +void SkColorToHSL(SkPMColor c, HSL& hsl); // Convert a HSL color to a premultiplied SkColor. -SkPMColor HSLToSKColor(U8CPU alpha, float hsl[3]); +SkPMColor HSLToSKColor(U8CPU alpha, HSL hsl); + +// Shift an HSL value. The shift values are in the range of 0-1, +// with the option to specify -1 for 'no change'. The shift values are +// defined as: +// hsl_shift[0] (hue): The absolute hue value - 0 and 1 map +// to 0 and 360 on the hue color wheel (red). +// hsl_shift[1] (saturation): A saturation shift, with the +// following key values: +// 0 = remove all color. +// 0.5 = leave unchanged. +// 1 = fully saturate the image. +// hsl_shift[2] (lightness): A lightness shift, with the +// following key values: +// 0 = remove all lightness (make all pixels black). +// 0.5 = leave unchanged. +// 1 = full lightness (make all pixels white). +SkColor HSLShift(skia::HSL hsl, skia::HSL shift); } // namespace skia diff --git a/skia/ext/skia_utils_unittest.cc b/skia/ext/skia_utils_unittest.cc index f7b00b1..444a5fc9 100644 --- a/skia/ext/skia_utils_unittest.cc +++ b/skia/ext/skia_utils_unittest.cc @@ -11,20 +11,20 @@ TEST(SkiaUtils, SkColorToHSLRed) { SkColor red = SkColorSetARGB(255, 255, 0, 0); - SkScalar hsl[3]; + skia::HSL hsl = { 0, 0, 0 }; skia::SkColorToHSL(red, hsl); - EXPECT_EQ(hsl[0], 0); - EXPECT_EQ(hsl[1], 1); - EXPECT_EQ(hsl[2], 0.5); + EXPECT_EQ(hsl.h, 0); + EXPECT_EQ(hsl.s, 1); + EXPECT_EQ(hsl.l, 0.5); } TEST(SkiaUtils, SkColorToHSLGrey) { SkColor red = SkColorSetARGB(255, 128, 128, 128); - SkScalar hsl[3]; + skia::HSL hsl = { 0, 0, 0 }; skia::SkColorToHSL(red, hsl); - EXPECT_EQ(hsl[0], 0); - EXPECT_EQ(hsl[1], 0); - EXPECT_EQ(static_cast<int>(hsl[2] * 100), + EXPECT_EQ(hsl.h, 0); + EXPECT_EQ(hsl.s, 0); + EXPECT_EQ(static_cast<int>(hsl.l * 100), static_cast<int>(0.5 * 100)); // Accurate to two decimal places. } @@ -32,11 +32,7 @@ TEST(SkiaUtils, HSLToSkColorWithAlpha) { // Premultiplied alpha - this is full red. SkColor red = SkColorSetARGB(128, 128, 0, 0); - SkScalar hsl[3] = { - SkDoubleToScalar(0), - SkDoubleToScalar(1), - SkDoubleToScalar(0.5), - }; + skia::HSL hsl = { 0, 1, 0.5 }; SkColor result = skia::HSLToSKColor(128, hsl); EXPECT_EQ(SkColorGetA(red), SkColorGetA(result)); diff --git a/views/view.cc b/views/view.cc index b2951d9..f4ef13d 100644 --- a/views/view.cc +++ b/views/view.cc @@ -1568,6 +1568,11 @@ int View::GetLineScrollIncrement(ScrollView* scroll_view, return 0; } +ThemeProvider* View::GetThemeProvider() { + Widget* widget = GetWidget(); + return widget ? widget->GetThemeProvider() : NULL; +} + // static void View::RegisterChildrenForVisibleBoundsNotification( RootView* root, View* view) { diff --git a/views/view.h b/views/view.h index e3a78f7..561632d 100644 --- a/views/view.h +++ b/views/view.h @@ -33,6 +33,7 @@ class Path; class ChromeCanvas; class OSExchangeData; class ViewAccessibilityWrapper; +class ThemeProvider; namespace views { @@ -995,6 +996,9 @@ class View : public AcceleratorTarget { virtual int GetLineScrollIncrement(ScrollView* scroll_view, bool is_horizontal, bool is_positive); + // Get the theme provider from the parent widget. + ThemeProvider* GetThemeProvider(); + protected: // The id of this View. Used to find this View. int id_; diff --git a/views/views.vcproj b/views/views.vcproj index 2c98260..1d1c269 100644 --- a/views/views.vcproj +++ b/views/views.vcproj @@ -201,6 +201,36 @@ > </File> <File + RelativePath=".\widget\default_theme_provider.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\widget\default_theme_provider.h" + > + </File> + <File + RelativePath=".\widget\hwnd_notification_source.h" + > + </File> + <File RelativePath=".\widget\root_view.cc" > <FileConfiguration diff --git a/views/widget/default_theme_provider.cc b/views/widget/default_theme_provider.cc new file mode 100644 index 0000000..be348a9 --- /dev/null +++ b/views/widget/default_theme_provider.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2009 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/widget/default_theme_provider.h" + +#include "app/resource_bundle.h" + +namespace views { + +SkBitmap* DefaultThemeProvider::GetBitmapNamed(int id) { + return ResourceBundle::GetSharedInstance().GetBitmapNamed(id); +} + +SkColor DefaultThemeProvider::GetColor(int id) { + // Return debugging-blue. + return 0xff0000ff; +} + +} // namespace views diff --git a/views/widget/default_theme_provider.h b/views/widget/default_theme_provider.h new file mode 100644 index 0000000..1060c8e --- /dev/null +++ b/views/widget/default_theme_provider.h @@ -0,0 +1,30 @@ +// Copyright (c) 2009 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_DEFAULT_THEME_PROVIDER_H_ +#define VIEWS_DEFAULT_THEME_PROVIDER_H_ + +#include "app/theme_provider.h" +#include "base/basictypes.h" + +class ResourceBundle; + +namespace views { + +class DefaultThemeProvider : public ThemeProvider { + public: + DefaultThemeProvider() { }; + virtual ~DefaultThemeProvider() { }; + + // Overridden from ThemeProvider. + virtual SkBitmap* GetBitmapNamed(int id); + virtual SkColor GetColor(int id); + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultThemeProvider); +}; + +} // namespace views + +#endif // VIEWS_DEFAULT_THEME_PROVIDER_H_ diff --git a/views/widget/widget.h b/views/widget/widget.h index 8dd3f2e..b2c3551 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -7,6 +7,8 @@ #include "base/gfx/native_widget_types.h" +class ThemeProvider; + namespace gfx { class Rect; } @@ -53,6 +55,9 @@ class Widget { // Returns the RootView contained by this Widget. virtual RootView* GetRootView() = 0; + // Returns the Widget associated with the root ancestor. + virtual Widget* GetRootWidget() const = 0; + // Returns whether the Widget is visible to the user. virtual bool IsVisible() const = 0; @@ -74,6 +79,14 @@ class Widget { // window. virtual Window* GetWindow() { return NULL; } virtual const Window* GetWindow() const { return NULL; } + + // Get the theme provider. + virtual ThemeProvider* GetThemeProvider() const { return NULL; } + + // Get the dialog theme provider; this is necessary for when a dialog has + // no profile (and ThemeProvider) associated with it. The dialog theme + // provider provides a default set of bitmaps that such dialogs can use. + virtual ThemeProvider* GetDialogThemeProvider() { return NULL; } }; } // namespace views diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index c59f512..25f25da 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -15,6 +15,7 @@ #include "views/fill_layout.h" #include "views/focus/focus_util_win.h" #include "views/widget/aero_tooltip_manager.h" +#include "views/widget/default_theme_provider.h" #include "views/widget/root_view.h" #include "views/window/window_win.h" @@ -166,6 +167,8 @@ void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, // Force creation of the RootView if it hasn't been created yet. GetRootView(); + default_theme_provider_.reset(new DefaultThemeProvider()); + // Ensures the parent we have been passed is valid, otherwise CreateWindowEx // will fail. if (parent && !::IsWindow(parent)) { @@ -293,6 +296,11 @@ RootView* WidgetWin::GetRootView() { return root_view_.get(); } +Widget* WidgetWin::GetRootWidget() const { + return reinterpret_cast<WidgetWin*>( + win_util::GetWindowUserData(GetAncestor(hwnd_, GA_ROOT))); +} + bool WidgetWin::IsVisible() const { return !!::IsWindowVisible(GetNativeView()); } @@ -305,6 +313,16 @@ TooltipManager* WidgetWin::GetTooltipManager() { return tooltip_manager_.get(); } +ThemeProvider* WidgetWin::GetThemeProvider() const { + Widget* widget = GetRootWidget(); + if (widget) { + ThemeProvider* provider = widget->GetDialogThemeProvider(); + if (provider) + return provider; + } + return default_theme_provider_.get(); +} + Window* WidgetWin::GetWindow() { return GetWindowImpl(hwnd_); } diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 09efa21..d948e66 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -24,6 +24,7 @@ namespace views { class RootView; class TooltipManager; +class DefaultThemeProvider; class Window; bool SetRootViewForHWND(HWND hwnd, RootView* root_view); @@ -235,9 +236,11 @@ class WidgetWin : public Widget, virtual gfx::NativeView GetNativeView() const; virtual void PaintNow(const gfx::Rect& update_rect); virtual RootView* GetRootView(); + virtual Widget* GetRootWidget() const; virtual bool IsVisible() const; virtual bool IsActive() const; virtual TooltipManager* GetTooltipManager(); + virtual ThemeProvider* GetThemeProvider() const; virtual Window* GetWindow(); virtual const Window* GetWindow() const; @@ -627,6 +630,8 @@ class WidgetWin : public Widget, // Instance of accessibility information and handling for MSAA root CComPtr<IAccessible> accessibility_root_; + scoped_ptr<DefaultThemeProvider> default_theme_provider_; + // Our hwnd. HWND hwnd_; }; diff --git a/views/window/custom_frame_view.cc b/views/window/custom_frame_view.cc index 1816fdc..88251b8 100644 --- a/views/window/custom_frame_view.cc +++ b/views/window/custom_frame_view.cc @@ -8,6 +8,7 @@ #include "app/gfx/chrome_font.h" #include "app/gfx/path.h" #include "app/resource_bundle.h" +#include "app/theme_provider.h" #if defined(OS_WIN) #include "app/win_util.h" #include "base/win_util.h" @@ -21,157 +22,7 @@ namespace views { -// An enumeration of bitmap resources used by this window. -enum { - FRAME_PART_BITMAP_FIRST = 0, // Must be first. - - // Window Controls. - FRAME_CLOSE_BUTTON_ICON, - FRAME_CLOSE_BUTTON_ICON_H, - FRAME_CLOSE_BUTTON_ICON_P, - FRAME_CLOSE_BUTTON_ICON_SA, - FRAME_CLOSE_BUTTON_ICON_SA_H, - FRAME_CLOSE_BUTTON_ICON_SA_P, - FRAME_RESTORE_BUTTON_ICON, - FRAME_RESTORE_BUTTON_ICON_H, - FRAME_RESTORE_BUTTON_ICON_P, - FRAME_MAXIMIZE_BUTTON_ICON, - FRAME_MAXIMIZE_BUTTON_ICON_H, - FRAME_MAXIMIZE_BUTTON_ICON_P, - FRAME_MINIMIZE_BUTTON_ICON, - FRAME_MINIMIZE_BUTTON_ICON_H, - FRAME_MINIMIZE_BUTTON_ICON_P, - - // Window Frame Border. - FRAME_BOTTOM_EDGE, - FRAME_BOTTOM_LEFT_CORNER, - FRAME_BOTTOM_RIGHT_CORNER, - FRAME_LEFT_EDGE, - FRAME_RIGHT_EDGE, - FRAME_TOP_EDGE, - FRAME_TOP_LEFT_CORNER, - FRAME_TOP_RIGHT_CORNER, - - // Client Edge Border. - FRAME_CLIENT_EDGE_TOP_LEFT, - FRAME_CLIENT_EDGE_TOP, - FRAME_CLIENT_EDGE_TOP_RIGHT, - FRAME_CLIENT_EDGE_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM_RIGHT, - FRAME_CLIENT_EDGE_BOTTOM, - FRAME_CLIENT_EDGE_BOTTOM_LEFT, - FRAME_CLIENT_EDGE_LEFT, - - FRAME_PART_BITMAP_COUNT // Must be last. -}; - -class ActiveWindowResources : public WindowResources { - public: - ActiveWindowResources() { - InitClass(); - } - virtual ~ActiveWindowResources() { - } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - 0, - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_WINDOW_BOTTOM_CENTER, IDR_WINDOW_BOTTOM_LEFT_CORNER, - IDR_WINDOW_BOTTOM_RIGHT_CORNER, IDR_WINDOW_LEFT_SIDE, - IDR_WINDOW_RIGHT_SIDE, IDR_WINDOW_TOP_CENTER, - IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_RIGHT_CORNER, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - IDR_CONTENT_RIGHT_SIDE, IDR_CONTENT_BOTTOM_RIGHT_CORNER, - IDR_CONTENT_BOTTOM_CENTER, IDR_CONTENT_BOTTOM_LEFT_CORNER, - IDR_CONTENT_LEFT_SIDE, - 0 - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) { - int id = kFramePartBitmapIds[i]; - if (id != 0) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(id); - } - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(ActiveWindowResources); -}; - -class InactiveWindowResources : public WindowResources { - public: - InactiveWindowResources() { - InitClass(); - } - virtual ~InactiveWindowResources() { - } - - // WindowResources implementation: - virtual SkBitmap* GetPartBitmap(FramePartBitmap part) const { - return standard_frame_bitmaps_[part]; - } - - private: - static void InitClass() { - static bool initialized = false; - if (!initialized) { - static const int kFramePartBitmapIds[] = { - 0, - IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, - IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, - IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, - IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, - IDR_DEWINDOW_BOTTOM_CENTER, IDR_DEWINDOW_BOTTOM_LEFT_CORNER, - IDR_DEWINDOW_BOTTOM_RIGHT_CORNER, IDR_DEWINDOW_LEFT_SIDE, - IDR_DEWINDOW_RIGHT_SIDE, IDR_DEWINDOW_TOP_CENTER, - IDR_DEWINDOW_TOP_LEFT_CORNER, IDR_DEWINDOW_TOP_RIGHT_CORNER, - IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, IDR_APP_TOP_RIGHT, - IDR_CONTENT_RIGHT_SIDE, IDR_CONTENT_BOTTOM_RIGHT_CORNER, - IDR_CONTENT_BOTTOM_CENTER, IDR_CONTENT_BOTTOM_LEFT_CORNER, - IDR_CONTENT_LEFT_SIDE, - 0 - }; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) { - int id = kFramePartBitmapIds[i]; - if (id != 0) - standard_frame_bitmaps_[i] = rb.GetBitmapNamed(id); - } - initialized = true; - } - } - - static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; - - DISALLOW_EVIL_CONSTRUCTORS(InactiveWindowResources); -}; - -// static -SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[]; -SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[]; - // static -WindowResources* CustomFrameView::active_resources_ = NULL; -WindowResources* CustomFrameView::inactive_resources_ = NULL; ChromeFont* CustomFrameView::title_font_ = NULL; namespace { @@ -231,33 +82,34 @@ CustomFrameView::CustomFrameView(Window* frame) should_show_minmax_buttons_(false), frame_(frame) { InitClass(); - WindowResources* resources = active_resources_; + + ThemeProvider* tp = GetThemeProvider(); // Close button images will be set in LayoutWindowControls(). AddChildView(close_button_); restore_button_->SetImage(CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_RESTORE)); restore_button_->SetImage(CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_RESTORE_H)); restore_button_->SetImage(CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_RESTORE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_RESTORE_P)); AddChildView(restore_button_); maximize_button_->SetImage(CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_MAXIMIZE)); maximize_button_->SetImage(CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_MAXIMIZE_H)); maximize_button_->SetImage(CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_MAXIMIZE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_MAXIMIZE_P)); AddChildView(maximize_button_); minimize_button_->SetImage(CustomButton::BS_NORMAL, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON)); + tp->GetBitmapNamed(IDR_MINIMIZE)); minimize_button_->SetImage(CustomButton::BS_HOT, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON_H)); + tp->GetBitmapNamed(IDR_MINIMIZE_H)); minimize_button_->SetImage(CustomButton::BS_PUSHED, - resources->GetPartBitmap(FRAME_MINIMIZE_BUTTON_ICON_P)); + tp->GetBitmapNamed(IDR_MINIMIZE_P)); AddChildView(minimize_button_); should_show_minmax_buttons_ = frame_->GetDelegate()->CanMaximize(); @@ -443,17 +295,50 @@ int CustomFrameView::TitleCoordinates(int* title_top_spacing, } void CustomFrameView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { - SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); + // Window frame mode. + ThemeProvider* tp = GetThemeProvider(); + + SkBitmap* theme_frame; + SkColor frame_color; + + if (frame_->IsActive()) { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME); + frame_color = ResourceBundle::frame_color; + } else { + theme_frame = tp->GetBitmapNamed(IDR_THEME_FRAME_INACTIVE); + frame_color = ResourceBundle::frame_color_inactive; + } + + SkBitmap* top_left_corner = tp->GetBitmapNamed(IDR_WINDOW_TOP_LEFT_CORNER); SkBitmap* top_right_corner = - resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); - SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); - SkBitmap* right_edge = resources()->GetPartBitmap(FRAME_RIGHT_EDGE); - SkBitmap* left_edge = resources()->GetPartBitmap(FRAME_LEFT_EDGE); + tp->GetBitmapNamed(IDR_WINDOW_TOP_RIGHT_CORNER); + SkBitmap* top_edge = tp->GetBitmapNamed(IDR_WINDOW_TOP_CENTER); + SkBitmap* right_edge = tp->GetBitmapNamed(IDR_WINDOW_RIGHT_SIDE); + SkBitmap* left_edge = tp->GetBitmapNamed(IDR_WINDOW_LEFT_SIDE); SkBitmap* bottom_left_corner = - resources()->GetPartBitmap(FRAME_BOTTOM_LEFT_CORNER); + tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER); SkBitmap* bottom_right_corner = - resources()->GetPartBitmap(FRAME_BOTTOM_RIGHT_CORNER); - SkBitmap* bottom_edge = resources()->GetPartBitmap(FRAME_BOTTOM_EDGE); + tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER); + SkBitmap* bottom_edge = tp->GetBitmapNamed(IDR_WINDOW_BOTTOM_CENTER); + + // Fill with the frame color first so we have a constant background for + // areas not covered by the theme image. + canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height()); + // Now fill down the sides + canvas->FillRectInt(frame_color, + 0, theme_frame->height(), + left_edge->width(), height() - theme_frame->height()); + canvas->FillRectInt(frame_color, + width() - right_edge->width(), theme_frame->height(), + right_edge->width(), height() - theme_frame->height()); + // Now fill the bottom area. + canvas->FillRectInt(frame_color, + left_edge->width(), height() - bottom_edge->height(), + width() - left_edge->width() - right_edge->width(), + bottom_edge->height()); + + // Draw the theme frame. + canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height()); // Top. canvas->DrawBitmapInt(*top_left_corner, 0, 0); @@ -488,13 +373,15 @@ void CustomFrameView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { void CustomFrameView::PaintMaximizedFrameBorder( ChromeCanvas* canvas) { - SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); + ThemeProvider* tp = GetThemeProvider(); + + SkBitmap* top_edge = tp->GetBitmapNamed(IDR_WINDOW_TOP_CENTER); canvas->TileImageInt(*top_edge, 0, FrameBorderThickness(), width(), top_edge->height()); // The bottom of the titlebar actually comes from the top of the Client Edge // graphic, with the actual client edge clipped off the bottom. - SkBitmap* titlebar_bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); + SkBitmap* titlebar_bottom = tp->GetBitmapNamed(IDR_APP_TOP_CENTER); int edge_height = titlebar_bottom->height() - kClientEdgeThickness; canvas->TileImageInt(*titlebar_bottom, 0, frame_->GetClientView()->y() - edge_height, width(), edge_height); @@ -518,16 +405,17 @@ void CustomFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { gfx::Rect client_area_bounds = frame_->GetClientView()->bounds(); int client_area_top = client_area_bounds.y(); - SkBitmap* top_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); - SkBitmap* top = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); - SkBitmap* top_right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); - SkBitmap* right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); + ThemeProvider* tp = GetThemeProvider(); + SkBitmap* top_left = tp->GetBitmapNamed(IDR_APP_TOP_LEFT); + SkBitmap* top = tp->GetBitmapNamed(IDR_APP_TOP_CENTER); + SkBitmap* top_right = tp->GetBitmapNamed(IDR_APP_TOP_RIGHT); + SkBitmap* right = tp->GetBitmapNamed(IDR_CONTENT_RIGHT_SIDE); SkBitmap* bottom_right = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT); - SkBitmap* bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); + tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER); + SkBitmap* bottom = tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER); SkBitmap* bottom_left = - resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); - SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); + tp->GetBitmapNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); + SkBitmap* left = tp->GetBitmapNamed(IDR_CONTENT_LEFT_SIDE); // Top. // This next calculation is necessary because the top center bitmap is shorter @@ -559,6 +447,11 @@ void CustomFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) { // Left. canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), client_area_top, left->width(), client_area_height); + + // Draw the toolbar color to fill in the edges. + canvas->DrawRectInt(ResourceBundle::toolbar_color, + client_area_bounds.x() - 1, client_area_top - 2, + client_area_bounds.width() + 1, client_area_bottom - client_area_top + 2); } void CustomFrameView::LayoutWindowControls() { @@ -609,24 +502,26 @@ void CustomFrameView::LayoutWindowControls() { minimize_button_size.width(), minimize_button_size.height() + top_extra_height); - normal_part = FRAME_CLOSE_BUTTON_ICON; - hot_part = FRAME_CLOSE_BUTTON_ICON_H; - pushed_part = FRAME_CLOSE_BUTTON_ICON_P; + normal_part = IDR_CLOSE; + hot_part = IDR_CLOSE_H; + pushed_part = IDR_CLOSE_P; } else { visible_button->SetVisible(false); minimize_button_->SetVisible(false); - normal_part = FRAME_CLOSE_BUTTON_ICON_SA; - hot_part = FRAME_CLOSE_BUTTON_ICON_SA_H; - pushed_part = FRAME_CLOSE_BUTTON_ICON_SA_P; + normal_part = IDR_CLOSE_SA; + hot_part = IDR_CLOSE_SA_H; + pushed_part = IDR_CLOSE_SA_P; } + ThemeProvider* tp = GetThemeProvider(); + close_button_->SetImage(CustomButton::BS_NORMAL, - active_resources_->GetPartBitmap(normal_part)); + tp->GetBitmapNamed(normal_part)); close_button_->SetImage(CustomButton::BS_HOT, - active_resources_->GetPartBitmap(hot_part)); + tp->GetBitmapNamed(hot_part)); close_button_->SetImage(CustomButton::BS_PUSHED, - active_resources_->GetPartBitmap(pushed_part)); + tp->GetBitmapNamed(pushed_part)); } void CustomFrameView::LayoutTitleBar() { @@ -688,9 +583,6 @@ void CustomFrameView::LayoutClientView() { void CustomFrameView::InitClass() { static bool initialized = false; if (!initialized) { - active_resources_ = new ActiveWindowResources; - inactive_resources_ = new InactiveWindowResources; - #if defined(OS_WIN) title_font_ = new ChromeFont(win_util::GetWindowTitleFont()); #elif defined(OS_LINUX) diff --git a/views/window/custom_frame_view.h b/views/window/custom_frame_view.h index f071692..ac0b114 100644 --- a/views/window/custom_frame_view.h +++ b/views/window/custom_frame_view.h @@ -85,12 +85,6 @@ class CustomFrameView : public NonClientFrameView, void LayoutTitleBar(); void LayoutClientView(); - // Returns the resource collection to be used when rendering the window. - WindowResources* resources() const { - return frame_->IsActive() || paint_as_active() ? active_resources_ - : inactive_resources_; - } - // The bounds of the client view, in this view's coordinates. gfx::Rect client_view_bounds_; @@ -110,8 +104,6 @@ class CustomFrameView : public NonClientFrameView, // Initialize various static resources. static void InitClass(); - static WindowResources* active_resources_; - static WindowResources* inactive_resources_; static ChromeFont* title_font_; DISALLOW_EVIL_CONSTRUCTORS(CustomFrameView); |