summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/custom_button.cc
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 19:15:02 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 19:15:02 +0000
commite6ba540ce15f791b531cd7ac712e7a5880edf38e (patch)
tree622999398c8e4d2e46e47cf37d726f25b3382ca2 /chrome/browser/gtk/custom_button.cc
parent7a679c414e9812d4139d3afde9d98c4efe8f5bb8 (diff)
downloadchromium_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.cc127
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.
+}
+