OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/controls/menu/menu_win.h" | 5 #include "ui/views/controls/menu/menu_win.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 // Margins between the left of the item and the icon. | 31 // Margins between the left of the item and the icon. |
32 const int kItemLeftMargin = 4; | 32 const int kItemLeftMargin = 4; |
33 // The width for displaying the sub-menu arrow. | 33 // The width for displaying the sub-menu arrow. |
34 const int kArrowWidth = 10; | 34 const int kArrowWidth = 10; |
35 | 35 |
36 // Current active MenuHostWindow. If NULL, no menu is active. | 36 // Current active MenuHostWindow. If NULL, no menu is active. |
37 static MenuHostWindow* active_host_window = NULL; | 37 static MenuHostWindow* active_host_window = NULL; |
38 | 38 |
39 // The data of menu items needed to display. | 39 // The data of menu items needed to display. |
40 struct MenuWin::ItemData { | 40 struct MenuWin::ItemData { |
41 string16 label; | 41 base::string16 label; |
42 gfx::ImageSkia icon; | 42 gfx::ImageSkia icon; |
43 bool submenu; | 43 bool submenu; |
44 }; | 44 }; |
45 | 45 |
46 namespace { | 46 namespace { |
47 | 47 |
48 static int ChromeGetMenuItemID(HMENU hMenu, int pos) { | 48 static int ChromeGetMenuItemID(HMENU hMenu, int pos) { |
49 // The built-in Windows GetMenuItemID doesn't work for submenus, | 49 // The built-in Windows GetMenuItemID doesn't work for submenus, |
50 // so here's our own implementation. | 50 // so here's our own implementation. |
51 MENUITEMINFO mii = {0}; | 51 MENUITEMINFO mii = {0}; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 MenuWin::ItemData* data = | 102 MenuWin::ItemData* data = |
103 reinterpret_cast<MenuWin::ItemData*>(lpmis->itemData); | 103 reinterpret_cast<MenuWin::ItemData*>(lpmis->itemData); |
104 if (data != NULL) { | 104 if (data != NULL) { |
105 gfx::Font font; | 105 gfx::Font font; |
106 lpmis->itemWidth = font.GetStringWidth(data->label) + kIconWidth + | 106 lpmis->itemWidth = font.GetStringWidth(data->label) + kIconWidth + |
107 kItemLeftMargin + views::kItemLabelSpacing - | 107 kItemLeftMargin + views::kItemLabelSpacing - |
108 GetSystemMetrics(SM_CXMENUCHECK); | 108 GetSystemMetrics(SM_CXMENUCHECK); |
109 if (data->submenu) | 109 if (data->submenu) |
110 lpmis->itemWidth += kArrowWidth; | 110 lpmis->itemWidth += kArrowWidth; |
111 // If the label contains an accelerator, make room for tab. | 111 // If the label contains an accelerator, make room for tab. |
112 if (data->label.find(L'\t') != string16::npos) | 112 if (data->label.find(L'\t') != base::string16::npos) |
113 lpmis->itemWidth += font.GetStringWidth(L" "); | 113 lpmis->itemWidth += font.GetStringWidth(L" "); |
114 lpmis->itemHeight = font.GetHeight() + kItemBottomMargin + kItemTopMargin; | 114 lpmis->itemHeight = font.GetHeight() + kItemBottomMargin + kItemTopMargin; |
115 } else { | 115 } else { |
116 // Measure separator size. | 116 // Measure separator size. |
117 lpmis->itemHeight = GetSystemMetrics(SM_CYMENU) / 2; | 117 lpmis->itemHeight = GetSystemMetrics(SM_CYMENU) / 2; |
118 lpmis->itemWidth = 0; | 118 lpmis->itemWidth = 0; |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 void OnDrawItem(UINT wParam, DRAWITEMSTRUCT* lpdis) { | 122 void OnDrawItem(UINT wParam, DRAWITEMSTRUCT* lpdis) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 format |= DT_HIDEPREFIX; | 158 format |= DT_HIDEPREFIX; |
159 gfx::Font font; | 159 gfx::Font font; |
160 HGDIOBJ old_font = | 160 HGDIOBJ old_font = |
161 static_cast<HFONT>(SelectObject(hDC, font.GetNativeFont())); | 161 static_cast<HFONT>(SelectObject(hDC, font.GetNativeFont())); |
162 | 162 |
163 // If an accelerator is specified (with a tab delimiting the rest of the | 163 // If an accelerator is specified (with a tab delimiting the rest of the |
164 // label from the accelerator), we have to justify the fist part on the | 164 // label from the accelerator), we have to justify the fist part on the |
165 // left and the accelerator on the right. | 165 // left and the accelerator on the right. |
166 // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the | 166 // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the |
167 // window system UI font and will not hit here. | 167 // window system UI font and will not hit here. |
168 string16 label = data->label; | 168 base::string16 label = data->label; |
169 string16 accel; | 169 base::string16 accel; |
170 string16::size_type tab_pos = label.find(L'\t'); | 170 base::string16::size_type tab_pos = label.find(L'\t'); |
171 if (tab_pos != string16::npos) { | 171 if (tab_pos != base::string16::npos) { |
172 accel = label.substr(tab_pos); | 172 accel = label.substr(tab_pos); |
173 label = label.substr(0, tab_pos); | 173 label = label.substr(0, tab_pos); |
174 } | 174 } |
175 DrawTextEx(hDC, const_cast<wchar_t*>(label.data()), | 175 DrawTextEx(hDC, const_cast<wchar_t*>(label.data()), |
176 static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL); | 176 static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL); |
177 if (!accel.empty()) | 177 if (!accel.empty()) |
178 DrawTextEx(hDC, const_cast<wchar_t*>(accel.data()), | 178 DrawTextEx(hDC, const_cast<wchar_t*>(accel.data()), |
179 static_cast<int>(accel.size()), &rect, | 179 static_cast<int>(accel.size()), &rect, |
180 format | DT_RIGHT, NULL); | 180 format | DT_RIGHT, NULL); |
181 SelectObject(hDC, old_font); | 181 SelectObject(hDC, old_font); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 } | 255 } |
256 | 256 |
257 MenuWin::~MenuWin() { | 257 MenuWin::~MenuWin() { |
258 STLDeleteContainerPointers(submenus_.begin(), submenus_.end()); | 258 STLDeleteContainerPointers(submenus_.begin(), submenus_.end()); |
259 STLDeleteContainerPointers(item_data_.begin(), item_data_.end()); | 259 STLDeleteContainerPointers(item_data_.begin(), item_data_.end()); |
260 DestroyMenu(menu_); | 260 DestroyMenu(menu_); |
261 } | 261 } |
262 | 262 |
263 void MenuWin::AddMenuItemWithIcon(int index, | 263 void MenuWin::AddMenuItemWithIcon(int index, |
264 int item_id, | 264 int item_id, |
265 const string16& label, | 265 const base::string16& label, |
266 const gfx::ImageSkia& icon) { | 266 const gfx::ImageSkia& icon) { |
267 owner_draw_ = true; | 267 owner_draw_ = true; |
268 Menu::AddMenuItemWithIcon(index, item_id, label, icon); | 268 Menu::AddMenuItemWithIcon(index, item_id, label, icon); |
269 } | 269 } |
270 | 270 |
271 Menu* MenuWin::AddSubMenuWithIcon(int index, | 271 Menu* MenuWin::AddSubMenuWithIcon(int index, |
272 int item_id, | 272 int item_id, |
273 const string16& label, | 273 const base::string16& label, |
274 const gfx::ImageSkia& icon) { | 274 const gfx::ImageSkia& icon) { |
275 MenuWin* submenu = new MenuWin(this); | 275 MenuWin* submenu = new MenuWin(this); |
276 submenus_.push_back(submenu); | 276 submenus_.push_back(submenu); |
277 AddMenuItemInternal(index, item_id, label, icon, submenu->menu_, NORMAL); | 277 AddMenuItemInternal(index, item_id, label, icon, submenu->menu_, NORMAL); |
278 return submenu; | 278 return submenu; |
279 } | 279 } |
280 | 280 |
281 void MenuWin::AddSeparator(int index) { | 281 void MenuWin::AddSeparator(int index) { |
282 MENUITEMINFO mii; | 282 MENUITEMINFO mii; |
283 mii.cbSize = sizeof(mii); | 283 mii.cbSize = sizeof(mii); |
284 mii.fMask = MIIM_FTYPE; | 284 mii.fMask = MIIM_FTYPE; |
285 mii.fType = MFT_SEPARATOR; | 285 mii.fType = MFT_SEPARATOR; |
286 InsertMenuItem(menu_, index, TRUE, &mii); | 286 InsertMenuItem(menu_, index, TRUE, &mii); |
287 } | 287 } |
288 | 288 |
289 void MenuWin::EnableMenuItemByID(int item_id, bool enabled) { | 289 void MenuWin::EnableMenuItemByID(int item_id, bool enabled) { |
290 UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED; | 290 UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED; |
291 EnableMenuItem(menu_, item_id, MF_BYCOMMAND | enable_flags); | 291 EnableMenuItem(menu_, item_id, MF_BYCOMMAND | enable_flags); |
292 } | 292 } |
293 | 293 |
294 void MenuWin::EnableMenuItemAt(int index, bool enabled) { | 294 void MenuWin::EnableMenuItemAt(int index, bool enabled) { |
295 UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED; | 295 UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED; |
296 EnableMenuItem(menu_, index, MF_BYPOSITION | enable_flags); | 296 EnableMenuItem(menu_, index, MF_BYPOSITION | enable_flags); |
297 } | 297 } |
298 | 298 |
299 void MenuWin::SetMenuLabel(int item_id, const string16& label) { | 299 void MenuWin::SetMenuLabel(int item_id, const base::string16& label) { |
300 MENUITEMINFO mii = {0}; | 300 MENUITEMINFO mii = {0}; |
301 mii.cbSize = sizeof(mii); | 301 mii.cbSize = sizeof(mii); |
302 mii.fMask = MIIM_STRING; | 302 mii.fMask = MIIM_STRING; |
303 mii.dwTypeData = const_cast<wchar_t*>(label.c_str()); | 303 mii.dwTypeData = const_cast<wchar_t*>(label.c_str()); |
304 mii.cch = static_cast<UINT>(label.size()); | 304 mii.cch = static_cast<UINT>(label.size()); |
305 SetMenuItemInfo(menu_, item_id, false, &mii); | 305 SetMenuItemInfo(menu_, item_id, false, &mii); |
306 } | 306 } |
307 | 307 |
308 bool MenuWin::SetIcon(const gfx::ImageSkia& icon, int item_id) { | 308 bool MenuWin::SetIcon(const gfx::ImageSkia& icon, int item_id) { |
309 if (!owner_draw_) | 309 if (!owner_draw_) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 DCHECK(is_menu_visible_); | 378 DCHECK(is_menu_visible_); |
379 EndMenu(); | 379 EndMenu(); |
380 } | 380 } |
381 | 381 |
382 int MenuWin::ItemCount() { | 382 int MenuWin::ItemCount() { |
383 return GetMenuItemCount(menu_); | 383 return GetMenuItemCount(menu_); |
384 } | 384 } |
385 | 385 |
386 void MenuWin::AddMenuItemInternal(int index, | 386 void MenuWin::AddMenuItemInternal(int index, |
387 int item_id, | 387 int item_id, |
388 const string16& label, | 388 const base::string16& label, |
389 const gfx::ImageSkia& icon, | 389 const gfx::ImageSkia& icon, |
390 MenuItemType type) { | 390 MenuItemType type) { |
391 AddMenuItemInternal(index, item_id, label, icon, NULL, type); | 391 AddMenuItemInternal(index, item_id, label, icon, NULL, type); |
392 } | 392 } |
393 | 393 |
394 void MenuWin::AddMenuItemInternal(int index, | 394 void MenuWin::AddMenuItemInternal(int index, |
395 int item_id, | 395 int item_id, |
396 const string16& label, | 396 const base::string16& label, |
397 const gfx::ImageSkia& icon, | 397 const gfx::ImageSkia& icon, |
398 HMENU submenu, | 398 HMENU submenu, |
399 MenuItemType type) { | 399 MenuItemType type) { |
400 DCHECK(type != SEPARATOR) << "Call AddSeparator instead!"; | 400 DCHECK(type != SEPARATOR) << "Call AddSeparator instead!"; |
401 | 401 |
402 if (!owner_draw_ && !icon.isNull()) | 402 if (!owner_draw_ && !icon.isNull()) |
403 owner_draw_ = true; | 403 owner_draw_ = true; |
404 | 404 |
405 if (label.empty() && !delegate()) { | 405 if (label.empty() && !delegate()) { |
406 // No label and no delegate; don't add an empty menu. | 406 // No label and no delegate; don't add an empty menu. |
(...skipping 23 matching lines...) Expand all Loading... |
430 if (type == RADIO) | 430 if (type == RADIO) |
431 mii.fType |= MFT_RADIOCHECK; | 431 mii.fType |= MFT_RADIOCHECK; |
432 | 432 |
433 mii.wID = item_id; | 433 mii.wID = item_id; |
434 | 434 |
435 // Set the item data. | 435 // Set the item data. |
436 MenuWin::ItemData* data = new ItemData; | 436 MenuWin::ItemData* data = new ItemData; |
437 item_data_.push_back(data); | 437 item_data_.push_back(data); |
438 data->submenu = submenu != NULL; | 438 data->submenu = submenu != NULL; |
439 | 439 |
440 string16 actual_label(label.empty() ? delegate()->GetLabel(item_id) : label); | 440 base::string16 actual_label( |
| 441 label.empty() ? delegate()->GetLabel(item_id) : label); |
441 | 442 |
442 // Find out if there is a shortcut we need to append to the label. | 443 // Find out if there is a shortcut we need to append to the label. |
443 ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE); | 444 ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE); |
444 if (delegate() && delegate()->GetAcceleratorInfo(item_id, &accelerator)) { | 445 if (delegate() && delegate()->GetAcceleratorInfo(item_id, &accelerator)) { |
445 actual_label += L'\t'; | 446 actual_label += L'\t'; |
446 actual_label += accelerator.GetShortcutText(); | 447 actual_label += accelerator.GetShortcutText(); |
447 } | 448 } |
448 labels_.push_back(actual_label); | 449 labels_.push_back(actual_label); |
449 | 450 |
450 if (owner_draw_) { | 451 if (owner_draw_) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 mii.fType = MFT_STRING; | 489 mii.fType = MFT_STRING; |
489 if (owner_draw_) | 490 if (owner_draw_) |
490 mii.fType |= MFT_OWNERDRAW; | 491 mii.fType |= MFT_OWNERDRAW; |
491 // If the menu originally has radiocheck type, we should follow it. | 492 // If the menu originally has radiocheck type, we should follow it. |
492 if (mii_info.fType & MFT_RADIOCHECK) | 493 if (mii_info.fType & MFT_RADIOCHECK) |
493 mii.fType |= MFT_RADIOCHECK; | 494 mii.fType |= MFT_RADIOCHECK; |
494 mii.fState = GetStateFlagsForItemID(id); | 495 mii.fState = GetStateFlagsForItemID(id); |
495 | 496 |
496 // Validate the label. If there is a contextual label, use it, otherwise | 497 // Validate the label. If there is a contextual label, use it, otherwise |
497 // default to the static label | 498 // default to the static label |
498 string16 label; | 499 base::string16 label; |
499 if (!delegate()->GetContextualLabel(id, &label)) | 500 if (!delegate()->GetContextualLabel(id, &label)) |
500 label = labels_[i - sep_count]; | 501 label = labels_[i - sep_count]; |
501 | 502 |
502 if (owner_draw_) { | 503 if (owner_draw_) { |
503 item_data_[i - sep_count]->label = label; | 504 item_data_[i - sep_count]->label = label; |
504 mii.dwItemData = reinterpret_cast<ULONG_PTR>(item_data_[i - sep_count]); | 505 mii.dwItemData = reinterpret_cast<ULONG_PTR>(item_data_[i - sep_count]); |
505 } | 506 } |
506 mii.dwTypeData = const_cast<wchar_t*>(label.c_str()); | 507 mii.dwTypeData = const_cast<wchar_t*>(label.c_str()); |
507 mii.cch = static_cast<UINT>(label.size()); | 508 mii.cch = static_cast<UINT>(label.size()); |
508 SetMenuItemInfo(menu_, i, true, &mii); | 509 SetMenuItemInfo(menu_, i, true, &mii); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 break; | 564 break; |
564 | 565 |
565 default: | 566 default: |
566 NOTREACHED(); | 567 NOTREACHED(); |
567 return 0; | 568 return 0; |
568 } | 569 } |
569 return align_flags; | 570 return align_flags; |
570 } | 571 } |
571 | 572 |
572 } // namespace views | 573 } // namespace views |
OLD | NEW |