diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 19:15:02 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 19:15:02 +0000 |
commit | e6ba540ce15f791b531cd7ac712e7a5880edf38e (patch) | |
tree | 622999398c8e4d2e46e47cf37d726f25b3382ca2 /chrome/browser/gtk/custom_button.cc | |
parent | 7a679c414e9812d4139d3afde9d98c4efe8f5bb8 (diff) | |
download | chromium_src-e6ba540ce15f791b531cd7ac712e7a5880edf38e.zip chromium_src-e6ba540ce15f791b531cd7ac712e7a5880edf38e.tar.gz chromium_src-e6ba540ce15f791b531cd7ac712e7a5880edf38e.tar.bz2 |
Draw custom menu buttons properly.
This is an iterative process towards code to be proud of; the previous
code of mine was horrible, this is less bad, and my next attempt at it
will be pretty, I promise.
Review URL: http://codereview.chromium.org/28001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10111 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk/custom_button.cc')
-rw-r--r-- | chrome/browser/gtk/custom_button.cc | 127 |
1 files changed, 91 insertions, 36 deletions
diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc index 8020464..df57800 100644 --- a/chrome/browser/gtk/custom_button.cc +++ b/chrome/browser/gtk/custom_button.cc @@ -7,17 +7,23 @@ #include "base/basictypes.h" #include "base/logging.h" #include "chrome/common/resource_bundle.h" +#include "chrome/browser/gtk/nine_box.h" + +#include "grit/theme_resources.h" CustomDrawButton::CustomDrawButton(int normal_id, int active_id, int highlight_id, int depressed_id) { widget_ = gtk_button_new(); - // Load the button images from the theme resources .pak file. - pixbufs_[GTK_STATE_NORMAL] = LoadImage(normal_id); - pixbufs_[GTK_STATE_ACTIVE] = LoadImage(active_id); - pixbufs_[GTK_STATE_PRELIGHT] = LoadImage(highlight_id); + // Load the button images from the resource bundle. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + pixbufs_[GTK_STATE_NORMAL] = normal_id ? rb.LoadPixbuf(normal_id) : NULL; + pixbufs_[GTK_STATE_ACTIVE] = active_id ? rb.LoadPixbuf(active_id) : NULL; + pixbufs_[GTK_STATE_PRELIGHT] = + highlight_id ? rb.LoadPixbuf(highlight_id) : NULL; pixbufs_[GTK_STATE_SELECTED] = NULL; - pixbufs_[GTK_STATE_INSENSITIVE] = LoadImage(depressed_id); + pixbufs_[GTK_STATE_INSENSITIVE] = + depressed_id ? rb.LoadPixbuf(depressed_id) : NULL; gtk_widget_set_size_request(widget_, gdk_pixbuf_get_width(pixbufs_[0]), @@ -37,38 +43,9 @@ CustomDrawButton::~CustomDrawButton() { } } -GdkPixbuf* CustomDrawButton::LoadImage(int resource_id) { - if (0 == resource_id) - return NULL; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - std::vector<unsigned char> data; - rb.LoadImageResourceBytes(resource_id, &data); - - GdkPixbufLoader* loader = gdk_pixbuf_loader_new(); - bool ok = gdk_pixbuf_loader_write(loader, static_cast<guint8*>(data.data()), - data.size(), NULL); - DCHECK(ok) << "failed to write " << resource_id; - // Calling gdk_pixbuf_loader_close forces the data to be parsed by the - // loader. We must do this before calling gdk_pixbuf_loader_get_pixbuf. - ok = gdk_pixbuf_loader_close(loader, NULL); - DCHECK(ok) << "close failed " << resource_id; - GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); - DCHECK(pixbuf) << "failed to load " << resource_id << " " << data.size(); - - // The pixbuf is owned by the loader, so add a ref so when we delete the - // loader, the pixbuf still exists. - g_object_ref(pixbuf); - g_object_unref(loader); - - return pixbuf; -} - // static -gboolean CustomDrawButton::OnExpose( - GtkWidget* widget, - GdkEventExpose* e, - CustomDrawButton* button) { +gboolean CustomDrawButton::OnExpose(GtkWidget* widget, GdkEventExpose* e, + CustomDrawButton* button) { GdkPixbuf* pixbuf = button->pixbufs_[GTK_WIDGET_STATE(widget)]; // Fall back to the default image if we don't have one for this state. @@ -84,5 +61,83 @@ gboolean CustomDrawButton::OnExpose( 0, 0, widget->allocation.x, widget->allocation.y, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); + return TRUE; } + +CustomContainerButton::CustomContainerButton() { + GdkPixbuf* images[9]; + int i = 0; + + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_LEFT_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_RIGHT_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_LEFT_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_CENTER_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_RIGHT_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_LEFT_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_H); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_RIGHT_H); + nine_box_prelight_.reset(new NineBox(images)); + + i = 0; + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_LEFT_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_TOP_RIGHT_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_LEFT_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_CENTER_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_RIGHT_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_LEFT_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_P); + images[i++] = rb.LoadPixbuf(IDR_TEXTBUTTON_BOTTOM_RIGHT_P); + nine_box_active_.reset(new NineBox(images)); + + widget_ = gtk_button_new(); + gtk_widget_set_app_paintable(widget_, TRUE); + g_signal_connect(G_OBJECT(widget_), "expose-event", + G_CALLBACK(OnExpose), this); +} + +CustomContainerButton::~CustomContainerButton() { +} + +// static +gboolean CustomContainerButton::OnExpose(GtkWidget* widget, GdkEventExpose* e, + CustomContainerButton* button) { + NineBox* nine_box = NULL; + if (GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) + nine_box = button->nine_box_prelight_.get(); + else if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE) + nine_box = button->nine_box_active_.get(); + + // Only draw theme graphics if we have some. + if (nine_box) { + GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, + true, // alpha + 8, // bits per channel + widget->allocation.width, + widget->allocation.height); + + nine_box->RenderToPixbuf(pixbuf); + + gdk_draw_pixbuf(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + pixbuf, + 0, 0, + widget->allocation.x, widget->allocation.y, -1, -1, + GDK_RGB_DITHER_NONE, 0, 0); + + gdk_pixbuf_unref(pixbuf); + } + + // If we return FALSE from the function, the button paints itself. + // If we return TRUE, no children are painted. + // So we return TRUE and send the expose along directly to the child. + gtk_container_propagate_expose(GTK_CONTAINER(widget), + gtk_bin_get_child(GTK_BIN(widget)), + e); + + return TRUE; // Prevent normal painting. +} + |