summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:48:44 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:48:44 +0000
commitcd43e6e776b2283f555f1b59bef06d135504f66f (patch)
tree1d1a074deebfef562a534f79bd0128ed2aa48ba1
parent05d94e79f64a6562ea646e5b3f2e9c6e7b1cc011 (diff)
downloadchromium_src-cd43e6e776b2283f555f1b59bef06d135504f66f.zip
chromium_src-cd43e6e776b2283f555f1b59bef06d135504f66f.tar.gz
chromium_src-cd43e6e776b2283f555f1b59bef06d135504f66f.tar.bz2
Add a function to ResourceBundle to allow loading images that will mirror in RTL. Use this function for custom buttons and for the Off the Record avatar.
for reference, this will be a bit different than Views, which does it per class rather than per image: http://dev.chromium.org/developers/design-documents/ui-mirroring-infrastructure Review URL: http://codereview.chromium.org/147157 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19309 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--app/resource_bundle.h10
-rw-r--r--app/resource_bundle_linux.cc43
-rw-r--r--chrome/browser/gtk/browser_titlebar.cc61
-rw-r--r--chrome/browser/gtk/browser_titlebar.h3
-rw-r--r--chrome/browser/gtk/custom_button.cc16
-rw-r--r--chrome/browser/gtk/custom_button.h2
6 files changed, 63 insertions, 72 deletions
diff --git a/app/resource_bundle.h b/app/resource_bundle.h
index ed17616..c718b9a 100644
--- a/app/resource_bundle.h
+++ b/app/resource_bundle.h
@@ -123,6 +123,16 @@ class ResourceBundle {
// pointer to a shared empty placeholder bitmap so it will be visible what
// is missing.
GdkPixbuf* GetPixbufNamed(int resource_id);
+
+ // As above, but flips it in RTL locales. Note that this will add the flipped
+ // pixbuf to the same cache used by GetPixbufNamed().
+ GdkPixbuf* GetRTLEnabledPixbufNamed(int resource_id);
+
+ private:
+ // Shared implementation for the above two functions.
+ GdkPixbuf* GetPixbufImpl(int resource_id, bool rtl_enabled);
+
+ public:
#endif
// TODO(glen): Move these into theme provider (dialogs still depend on
diff --git a/app/resource_bundle_linux.cc b/app/resource_bundle_linux.cc
index 9d46fb7..47d893d 100644
--- a/app/resource_bundle_linux.cc
+++ b/app/resource_bundle_linux.cc
@@ -25,7 +25,7 @@ namespace {
// Convert the raw image data into a GdkPixbuf. The GdkPixbuf that is returned
// has a ref count of 1 so the caller must call g_object_unref to free the
// memory.
-GdkPixbuf* LoadPixbuf(std::vector<unsigned char>& data) {
+GdkPixbuf* LoadPixbuf(std::vector<unsigned char>& data, bool rtl_enabled) {
ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new());
bool ok = gdk_pixbuf_loader_write(loader.get(),
static_cast<guint8*>(data.data()), data.size(), NULL);
@@ -40,12 +40,18 @@ GdkPixbuf* LoadPixbuf(std::vector<unsigned char>& data) {
if (!pixbuf)
return NULL;
- // The pixbuf is owned by the loader, so add a ref so when we delete the
- // loader (when the ScopedGObject goes out of scope), the pixbuf still
- // exists.
- g_object_ref(pixbuf);
-
- return pixbuf;
+ if ((l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) &&
+ rtl_enabled) {
+ // |pixbuf| will get unreffed and destroyed (see below). The returned value
+ // has ref count 1.
+ return gdk_pixbuf_flip(pixbuf, TRUE);
+ } else {
+ // The pixbuf is owned by the loader, so add a ref so when we delete the
+ // loader (when the ScopedGObject goes out of scope), the pixbuf still
+ // exists.
+ g_object_ref(pixbuf);
+ return pixbuf;
+ }
}
} // namespace
@@ -158,11 +164,14 @@ string16 ResourceBundle::GetLocalizedString(int message_id) {
return msg;
}
-GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) {
+GdkPixbuf* ResourceBundle::GetPixbufImpl(int resource_id, bool rtl_enabled) {
+ // Use the negative |resource_id| for the key for BIDI-aware images.
+ int key = rtl_enabled ? -resource_id : resource_id;
+
// Check to see if we already have the pixbuf in the cache.
{
AutoLock lock_scope(lock_);
- GdkPixbufMap::const_iterator found = gdk_pixbufs_.find(resource_id);
+ GdkPixbufMap::const_iterator found = gdk_pixbufs_.find(key);
if (found != gdk_pixbufs_.end())
return found->second;
}
@@ -170,19 +179,19 @@ GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) {
std::vector<unsigned char> data;
LoadImageResourceBytes(resource_id, &data);
- GdkPixbuf* pixbuf = LoadPixbuf(data);
+ GdkPixbuf* pixbuf = LoadPixbuf(data, rtl_enabled);
// We loaded successfully. Cache the pixbuf.
if (pixbuf) {
AutoLock lock_scope(lock_);
// Another thread raced us, and has already cached the pixbuf.
- if (gdk_pixbufs_.count(resource_id)) {
+ if (gdk_pixbufs_.count(key)) {
g_object_unref(pixbuf);
- return gdk_pixbufs_[resource_id];
+ return gdk_pixbufs_[key];
}
- gdk_pixbufs_[resource_id] = pixbuf;
+ gdk_pixbufs_[key] = pixbuf;
return pixbuf;
}
@@ -206,3 +215,11 @@ GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) {
return empty_bitmap;
}
}
+
+GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) {
+ return GetPixbufImpl(resource_id, false);
+}
+
+GdkPixbuf* ResourceBundle::GetRTLEnabledPixbufNamed(int resource_id) {
+ return GetPixbufImpl(resource_id, true);
+}
diff --git a/chrome/browser/gtk/browser_titlebar.cc b/chrome/browser/gtk/browser_titlebar.cc
index 7ebf916..2efc2bf 100644
--- a/chrome/browser/gtk/browser_titlebar.cc
+++ b/chrome/browser/gtk/browser_titlebar.cc
@@ -52,7 +52,7 @@ GdkPixbuf* GetOTRAvatar() {
static GdkPixbuf* otr_avatar = NULL;
if (!otr_avatar) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- otr_avatar = rb.GetPixbufNamed(IDR_OTR_ICON);
+ otr_avatar = rb.GetRTLEnabledPixbufNamed(IDR_OTR_ICON);
}
return otr_avatar;
}
@@ -69,12 +69,12 @@ void BrowserTitlebar::Init() {
// The widget hierarchy is shown below.
//
// +- HBox (container_) -----------------------------------------------------+
- // |+- Fixed -++- Alignment --------------++- VBox (titlebar_buttons_box_) -+|
- // ||(spy_guy)|| (titlebar_alignment_) ||+- HBox -----------------------+||
- // || || |||+- button -++- button -+ |||
- // || ||+- TabStripGtk ---------+|||| minimize || restore | ... |||
- // || )8\ ||| tab tab tabclose ||||+----------++----------+ |||
- // || ||+------------------------+||+------------------------------+||
+ // |+- Algn. -++- Alignment --------------++- VBox (titlebar_buttons_box_) -+|
+ // ||+ Image +|| (titlebar_alignment_) ||+- HBox -----------------------+||
+ // |||spy_guy||| |||+- button -++- button -+ |||
+ // ||| |||+- TabStripGtk ---------+|||| minimize || restore | ... |||
+ // ||| )8\ |||| tab tab tabclose ||||+----------++----------+ |||
+ // ||+-------+||+------------------------+||+------------------------------+||
// |+---------++--------------------------++--------------------------------+|
// +-------------------------------------------------------------------------+
container_ = gtk_hbox_new(FALSE, 0);
@@ -83,11 +83,16 @@ void BrowserTitlebar::Init() {
G_CALLBACK(OnWindowStateChanged), this);
if (browser_window_->browser()->profile()->IsOffTheRecord()) {
- GtkWidget* spy_guy = gtk_fixed_new();
- gtk_widget_set_size_request(spy_guy, gdk_pixbuf_get_width(GetOTRAvatar()) +
- 2 * kOTRSideSpacing, -1);
- gtk_box_pack_start(GTK_BOX(container_), spy_guy, FALSE, FALSE, 0);
- g_signal_connect(spy_guy, "expose-event", G_CALLBACK(OnAvatarExpose), this);
+ GtkWidget* spy_guy = gtk_image_new_from_pixbuf(GetOTRAvatar());
+ gtk_misc_set_alignment(GTK_MISC(spy_guy), 0.0, 1.0);
+ GtkWidget* spy_frame = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+ // We use this alignment rather than setting padding on the GtkImage because
+ // the image's intrinsic padding doesn't clip the pixbuf during painting.
+ gtk_alignment_set_padding(GTK_ALIGNMENT(spy_frame), kOTRMaximizedTopSpacing,
+ kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
+ gtk_widget_set_size_request(spy_guy, -1, 0);
+ gtk_container_add(GTK_CONTAINER(spy_frame), spy_guy);
+ gtk_box_pack_start(GTK_BOX(container_), spy_frame, FALSE, FALSE, 0);
}
// We use an alignment to control the titlebar height.
@@ -248,35 +253,3 @@ void BrowserTitlebar::ExecuteCommand(int command_id) {
NOTREACHED();
}
}
-
-// static
-gboolean BrowserTitlebar::OnAvatarExpose(
- GtkWidget* widget, GdkEventExpose* event, BrowserTitlebar* titlebar) {
- cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(widget->window));
- cairo_translate(cairo_context, widget->allocation.x, widget->allocation.y);
-
- if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
- cairo_translate(cairo_context, widget->allocation.width, 0.0f);
- cairo_scale(cairo_context, -1.0f, 1.0f);
- }
-
- // Set up a clip rect.
- const int clip_x = kOTRSideSpacing;
- const int clip_width = gdk_pixbuf_get_width(GetOTRAvatar());
- const int clip_y = kOTRMaximizedTopSpacing;
- const int clip_height = widget->allocation.height - kOTRMaximizedTopSpacing -
- kOTRBottomSpacing;
- cairo_rectangle(cairo_context, clip_x, clip_y, clip_width, clip_height);
- cairo_clip(cairo_context);
-
- // Drawing origin, which is calculated relative to the bottom.
- const int x = clip_x;
- const int y = widget->allocation.height - kOTRBottomSpacing -
- gdk_pixbuf_get_height(GetOTRAvatar());
-
- gdk_cairo_set_source_pixbuf(cairo_context, GetOTRAvatar(), x, y);
- cairo_paint(cairo_context);
- cairo_destroy(cairo_context);
-
- return TRUE;
-}
diff --git a/chrome/browser/gtk/browser_titlebar.h b/chrome/browser/gtk/browser_titlebar.h
index 12c4ab8..1dc8121 100644
--- a/chrome/browser/gtk/browser_titlebar.h
+++ b/chrome/browser/gtk/browser_titlebar.h
@@ -66,9 +66,6 @@ class BrowserTitlebar : public MenuGtk::Delegate {
virtual bool IsItemChecked(int command_id) const;
virtual void ExecuteCommand(int command_id);
- static gboolean OnAvatarExpose(
- GtkWidget* widget, GdkEventExpose* event, BrowserTitlebar* titlebar);
-
// Pointers to the browser window that owns us and it's GtkWindow.
BrowserWindowGtk* browser_window_;
GtkWindow* window_;
diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc
index bed3128..e047202 100644
--- a/chrome/browser/gtk/custom_button.cc
+++ b/chrome/browser/gtk/custom_button.cc
@@ -18,13 +18,15 @@ CustomDrawButtonBase::CustomDrawButtonBase(
: paint_override_(-1) {
// Load the button images from the resource bundle.
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- pixbufs_[GTK_STATE_NORMAL] = normal_id ? rb.GetPixbufNamed(normal_id) : NULL;
- pixbufs_[GTK_STATE_ACTIVE] = active_id ? rb.GetPixbufNamed(active_id) : NULL;
+ pixbufs_[GTK_STATE_NORMAL] =
+ normal_id ? rb.GetRTLEnabledPixbufNamed(normal_id) : NULL;
+ pixbufs_[GTK_STATE_ACTIVE] =
+ active_id ? rb.GetRTLEnabledPixbufNamed(active_id) : NULL;
pixbufs_[GTK_STATE_PRELIGHT] =
- highlight_id ? rb.GetPixbufNamed(highlight_id) : NULL;
+ highlight_id ? rb.GetRTLEnabledPixbufNamed(highlight_id) : NULL;
pixbufs_[GTK_STATE_SELECTED] = NULL;
pixbufs_[GTK_STATE_INSENSITIVE] =
- depressed_id ? rb.GetPixbufNamed(depressed_id) : NULL;
+ depressed_id ? rb.GetRTLEnabledPixbufNamed(depressed_id) : NULL;
}
CustomDrawButtonBase::~CustomDrawButtonBase() {
@@ -43,12 +45,6 @@ gboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget, GdkEventExpose* e) {
cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(widget->window));
cairo_translate(cairo_context, widget->allocation.x, widget->allocation.y);
-
- if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
- cairo_translate(cairo_context, widget->allocation.width, 0.0f);
- cairo_scale(cairo_context, -1.0f, 1.0f);
- }
-
gdk_cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0);
cairo_paint(cairo_context);
cairo_destroy(cairo_context);
diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h
index 10cd1e6..0e54732 100644
--- a/chrome/browser/gtk/custom_button.h
+++ b/chrome/browser/gtk/custom_button.h
@@ -13,8 +13,6 @@
#include "base/scoped_ptr.h"
#include "chrome/common/owned_widget_gtk.h"
-class NineBox;
-
// These classes implement two kinds of custom-drawn buttons. They're
// used on the toolbar and the bookmarks bar.