| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/gtk/menu_gtk.h" | 5 #include "chrome/browser/gtk/menu_gtk.h" |
| 6 | 6 |
| 7 #include "base/gfx/gtk_util.h" |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 9 #include "chrome/common/l10n_util.h" | 10 #include "chrome/common/l10n_util.h" |
| 10 #include "skia/include/SkBitmap.h" | 11 #include "skia/include/SkBitmap.h" |
| 11 | 12 |
| 12 namespace { | 13 namespace { |
| 13 | 14 |
| 14 // GTK uses _ for accelerators. Windows uses & with && as an escape for &. | 15 // GTK uses _ for accelerators. Windows uses & with && as an escape for &. |
| 15 std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) { | 16 std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) { |
| 16 std::string ret; | 17 std::string ret; |
| 17 ret.reserve(label.length()); | 18 ret.reserve(label.length()); |
| 18 for (size_t i = 0; i < label.length(); ++i) { | 19 for (size_t i = 0; i < label.length(); ++i) { |
| 19 if ('&' == label[i]) { | 20 if ('&' == label[i]) { |
| 20 if (i + 1 < label.length() && '&' == label[i + 1]) { | 21 if (i + 1 < label.length() && '&' == label[i + 1]) { |
| 21 ret.push_back(label[i]); | 22 ret.push_back(label[i]); |
| 22 ++i; | 23 ++i; |
| 23 } else { | 24 } else { |
| 24 ret.push_back('_'); | 25 ret.push_back('_'); |
| 25 } | 26 } |
| 26 } else { | 27 } else { |
| 27 ret.push_back(label[i]); | 28 ret.push_back(label[i]); |
| 28 } | 29 } |
| 29 } | 30 } |
| 30 | 31 |
| 31 return ret; | 32 return ret; |
| 32 } | 33 } |
| 33 | 34 |
| 34 void FreePixels(guchar* pixels, gpointer data) { | |
| 35 free(data); | |
| 36 } | |
| 37 | |
| 38 // We have to copy the pixels and reverse their order manually. | |
| 39 GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap* bitmap) { | |
| 40 bitmap->lockPixels(); | |
| 41 int width = bitmap->width(); | |
| 42 int height = bitmap->height(); | |
| 43 int stride = bitmap->rowBytes(); | |
| 44 const guchar* orig_data = static_cast<guchar*>(bitmap->getPixels()); | |
| 45 guchar* data = static_cast<guchar*>(malloc(height * stride)); | |
| 46 | |
| 47 // Swap from BGRA to RGBA. | |
| 48 for (int i = 0; i < height; ++i) { | |
| 49 for (int j = 0; j < width; ++j) { | |
| 50 int idx = i * stride + j * 4; | |
| 51 data[idx] = orig_data[idx + 2]; | |
| 52 data[idx + 1] = orig_data[idx + 1]; | |
| 53 data[idx + 2] = orig_data[idx]; | |
| 54 data[idx + 3] = orig_data[idx + 3]; | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 // This pixbuf takes ownership of our malloc()ed data and will | |
| 59 // free it for us when it is destroyed. | |
| 60 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( | |
| 61 data, | |
| 62 GDK_COLORSPACE_RGB, // the only colorspace gtk supports | |
| 63 true, // there is an alpha channel | |
| 64 8, | |
| 65 width, height, stride, &FreePixels, data); | |
| 66 | |
| 67 // Assume ownership of pixbuf. | |
| 68 g_object_ref_sink(pixbuf); | |
| 69 bitmap->unlockPixels(); | |
| 70 return pixbuf; | |
| 71 } | |
| 72 | |
| 73 } // namespace | 35 } // namespace |
| 74 | 36 |
| 75 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, | 37 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, |
| 76 const MenuCreateMaterial* menu_data, | 38 const MenuCreateMaterial* menu_data, |
| 77 GtkAccelGroup* accel_group) | 39 GtkAccelGroup* accel_group) |
| 78 : delegate_(delegate), | 40 : delegate_(delegate), |
| 79 accel_group_(accel_group), | 41 accel_group_(accel_group), |
| 80 menu_(gtk_menu_new()) { | 42 menu_(gtk_menu_new()) { |
| 81 g_object_ref_sink(menu_); | 43 g_object_ref_sink(menu_); |
| 82 BuildMenuIn(menu_, menu_data); | 44 BuildMenuIn(menu_, menu_data); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 // Note that the menu IDs start at 1, not 0. | 158 // Note that the menu IDs start at 1, not 0. |
| 197 for (int i = 1; i <= delegate_->GetItemCount(); ++i) { | 159 for (int i = 1; i <= delegate_->GetItemCount(); ++i) { |
| 198 GtkWidget* menu_item = NULL; | 160 GtkWidget* menu_item = NULL; |
| 199 | 161 |
| 200 if (delegate_->IsItemSeparator(i)) { | 162 if (delegate_->IsItemSeparator(i)) { |
| 201 menu_item = gtk_separator_menu_item_new(); | 163 menu_item = gtk_separator_menu_item_new(); |
| 202 } else if (delegate_->HasIcon(i)) { | 164 } else if (delegate_->HasIcon(i)) { |
| 203 menu_item = gtk_image_menu_item_new_with_label( | 165 menu_item = gtk_image_menu_item_new_with_label( |
| 204 delegate_->GetLabel(i).c_str()); | 166 delegate_->GetLabel(i).c_str()); |
| 205 const SkBitmap* icon = delegate_->GetIcon(i); | 167 const SkBitmap* icon = delegate_->GetIcon(i); |
| 206 GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(icon); | 168 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon); |
| 207 GtkWidget* widget = gtk_image_new_from_pixbuf(pixbuf); | 169 GtkWidget* widget = gtk_image_new_from_pixbuf(pixbuf); |
| 208 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), widget); | 170 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), widget); |
| 209 g_object_unref(pixbuf); | 171 g_object_unref(pixbuf); |
| 210 } else { | 172 } else { |
| 211 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str()); | 173 menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str()); |
| 212 } | 174 } |
| 213 | 175 |
| 214 g_object_set_data(G_OBJECT(menu_item), "menu-id", | 176 g_object_set_data(G_OBJECT(menu_item), "menu-id", |
| 215 reinterpret_cast<void*>(i)); | 177 reinterpret_cast<void*>(i)); |
| 216 | 178 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 widget, menu->delegate_->IsCommandEnabled(data->id)); | 265 widget, menu->delegate_->IsCommandEnabled(data->id)); |
| 304 | 266 |
| 305 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); | 267 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); |
| 306 if (submenu) { | 268 if (submenu) { |
| 307 gtk_container_foreach(GTK_CONTAINER(submenu), &MenuGtk::SetMenuItemInfo, | 269 gtk_container_foreach(GTK_CONTAINER(submenu), &MenuGtk::SetMenuItemInfo, |
| 308 raw_menu); | 270 raw_menu); |
| 309 } | 271 } |
| 310 } | 272 } |
| 311 } | 273 } |
| 312 } | 274 } |
| OLD | NEW |