| 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/native_menu_win.h" | 5 #include "ui/views/controls/menu/native_menu_win.h" |
| 6 | 6 |
| 7 #include <Windowsx.h> | 7 #include <Windowsx.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 static const int kItemBottomMargin = 4; | 44 static const int kItemBottomMargin = 4; |
| 45 // Margins between the left of the item and the icon. | 45 // Margins between the left of the item and the icon. |
| 46 static const int kItemLeftMargin = 4; | 46 static const int kItemLeftMargin = 4; |
| 47 // The width for displaying the sub-menu arrow. | 47 // The width for displaying the sub-menu arrow. |
| 48 static const int kArrowWidth = 10; | 48 static const int kArrowWidth = 10; |
| 49 | 49 |
| 50 struct NativeMenuWin::ItemData { | 50 struct NativeMenuWin::ItemData { |
| 51 // The Windows API requires that whoever creates the menus must own the | 51 // The Windows API requires that whoever creates the menus must own the |
| 52 // strings used for labels, and keep them around for the lifetime of the | 52 // strings used for labels, and keep them around for the lifetime of the |
| 53 // created menu. So be it. | 53 // created menu. So be it. |
| 54 string16 label; | 54 base::string16 label; |
| 55 | 55 |
| 56 // Someone needs to own submenus, it may as well be us. | 56 // Someone needs to own submenus, it may as well be us. |
| 57 scoped_ptr<Menu2> submenu; | 57 scoped_ptr<Menu2> submenu; |
| 58 | 58 |
| 59 // We need a pointer back to the containing menu in various circumstances. | 59 // We need a pointer back to the containing menu in various circumstances. |
| 60 NativeMenuWin* native_menu_win; | 60 NativeMenuWin* native_menu_win; |
| 61 | 61 |
| 62 // The index of the item within the menu's model. | 62 // The index of the item within the menu's model. |
| 63 int model_index; | 63 int model_index; |
| 64 }; | 64 }; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* measure_item_struct) { | 171 void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* measure_item_struct) { |
| 172 NativeMenuWin::ItemData* data = GetItemData(measure_item_struct->itemData); | 172 NativeMenuWin::ItemData* data = GetItemData(measure_item_struct->itemData); |
| 173 if (data) { | 173 if (data) { |
| 174 gfx::Font font; | 174 gfx::Font font; |
| 175 measure_item_struct->itemWidth = font.GetStringWidth(data->label) + | 175 measure_item_struct->itemWidth = font.GetStringWidth(data->label) + |
| 176 kIconWidth + kItemLeftMargin + views::kItemLabelSpacing - | 176 kIconWidth + kItemLeftMargin + views::kItemLabelSpacing - |
| 177 GetSystemMetrics(SM_CXMENUCHECK); | 177 GetSystemMetrics(SM_CXMENUCHECK); |
| 178 if (data->submenu.get()) | 178 if (data->submenu.get()) |
| 179 measure_item_struct->itemWidth += kArrowWidth; | 179 measure_item_struct->itemWidth += kArrowWidth; |
| 180 // If the label contains an accelerator, make room for tab. | 180 // If the label contains an accelerator, make room for tab. |
| 181 if (data->label.find(L'\t') != string16::npos) | 181 if (data->label.find(L'\t') != base::string16::npos) |
| 182 measure_item_struct->itemWidth += font.GetStringWidth(L" "); | 182 measure_item_struct->itemWidth += font.GetStringWidth(L" "); |
| 183 measure_item_struct->itemHeight = | 183 measure_item_struct->itemHeight = |
| 184 font.GetHeight() + kItemBottomMargin + kItemTopMargin; | 184 font.GetHeight() + kItemBottomMargin + kItemTopMargin; |
| 185 } else { | 185 } else { |
| 186 // Measure separator size. | 186 // Measure separator size. |
| 187 measure_item_struct->itemHeight = GetSystemMetrics(SM_CYMENU) / 2; | 187 measure_item_struct->itemHeight = GetSystemMetrics(SM_CYMENU) / 2; |
| 188 measure_item_struct->itemWidth = 0; | 188 measure_item_struct->itemWidth = 0; |
| 189 } | 189 } |
| 190 } | 190 } |
| 191 | 191 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 format |= DT_HIDEPREFIX; | 227 format |= DT_HIDEPREFIX; |
| 228 gfx::Font font; | 228 gfx::Font font; |
| 229 HGDIOBJ old_font = | 229 HGDIOBJ old_font = |
| 230 static_cast<HFONT>(SelectObject(dc, font.GetNativeFont())); | 230 static_cast<HFONT>(SelectObject(dc, font.GetNativeFont())); |
| 231 | 231 |
| 232 // If an accelerator is specified (with a tab delimiting the rest of the | 232 // If an accelerator is specified (with a tab delimiting the rest of the |
| 233 // label from the accelerator), we have to justify the fist part on the | 233 // label from the accelerator), we have to justify the fist part on the |
| 234 // left and the accelerator on the right. | 234 // left and the accelerator on the right. |
| 235 // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the | 235 // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the |
| 236 // window system UI font and will not hit here. | 236 // window system UI font and will not hit here. |
| 237 string16 label = data->label; | 237 base::string16 label = data->label; |
| 238 string16 accel; | 238 base::string16 accel; |
| 239 string16::size_type tab_pos = label.find(L'\t'); | 239 base::string16::size_type tab_pos = label.find(L'\t'); |
| 240 if (tab_pos != string16::npos) { | 240 if (tab_pos != base::string16::npos) { |
| 241 accel = label.substr(tab_pos); | 241 accel = label.substr(tab_pos); |
| 242 label = label.substr(0, tab_pos); | 242 label = label.substr(0, tab_pos); |
| 243 } | 243 } |
| 244 DrawTextEx(dc, const_cast<wchar_t*>(label.data()), | 244 DrawTextEx(dc, const_cast<wchar_t*>(label.data()), |
| 245 static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL); | 245 static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL); |
| 246 if (!accel.empty()) | 246 if (!accel.empty()) |
| 247 DrawTextEx(dc, const_cast<wchar_t*>(accel.data()), | 247 DrawTextEx(dc, const_cast<wchar_t*>(accel.data()), |
| 248 static_cast<int>(accel.size()), &rect, | 248 static_cast<int>(accel.size()), &rect, |
| 249 format | DT_RIGHT, NULL); | 249 format | DT_RIGHT, NULL); |
| 250 SelectObject(dc, old_font); | 250 SelectObject(dc, old_font); |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 void NativeMenuWin::AddMenuItemAt(int menu_index, int model_index) { | 619 void NativeMenuWin::AddMenuItemAt(int menu_index, int model_index) { |
| 620 MENUITEMINFO mii = {0}; | 620 MENUITEMINFO mii = {0}; |
| 621 mii.cbSize = sizeof(mii); | 621 mii.cbSize = sizeof(mii); |
| 622 mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA; | 622 mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA; |
| 623 if (!owner_draw_) | 623 if (!owner_draw_) |
| 624 mii.fType = MFT_STRING; | 624 mii.fType = MFT_STRING; |
| 625 else | 625 else |
| 626 mii.fType = MFT_OWNERDRAW; | 626 mii.fType = MFT_OWNERDRAW; |
| 627 | 627 |
| 628 ItemData* item_data = new ItemData; | 628 ItemData* item_data = new ItemData; |
| 629 item_data->label = string16(); | 629 item_data->label = base::string16(); |
| 630 ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); | 630 ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); |
| 631 if (type == ui::MenuModel::TYPE_SUBMENU) { | 631 if (type == ui::MenuModel::TYPE_SUBMENU) { |
| 632 item_data->submenu.reset(new Menu2(model_->GetSubmenuModelAt(model_index))); | 632 item_data->submenu.reset(new Menu2(model_->GetSubmenuModelAt(model_index))); |
| 633 mii.fMask |= MIIM_SUBMENU; | 633 mii.fMask |= MIIM_SUBMENU; |
| 634 mii.hSubMenu = item_data->submenu->GetNativeMenu(); | 634 mii.hSubMenu = item_data->submenu->GetNativeMenu(); |
| 635 GetNativeMenuWinFromHMENU(mii.hSubMenu)->parent_ = this; | 635 GetNativeMenuWinFromHMENU(mii.hSubMenu)->parent_ = this; |
| 636 } else { | 636 } else { |
| 637 if (type == ui::MenuModel::TYPE_RADIO) | 637 if (type == ui::MenuModel::TYPE_RADIO) |
| 638 mii.fType |= MFT_RADIOCHECK; | 638 mii.fType |= MFT_RADIOCHECK; |
| 639 mii.wID = model_->GetCommandIdAt(model_index); | 639 mii.wID = model_->GetCommandIdAt(model_index); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 | 671 |
| 672 MENUITEMINFO mii = {0}; | 672 MENUITEMINFO mii = {0}; |
| 673 mii.cbSize = sizeof(mii); | 673 mii.cbSize = sizeof(mii); |
| 674 mii.fMask = MIIM_STATE; | 674 mii.fMask = MIIM_STATE; |
| 675 mii.fState = state; | 675 mii.fState = state; |
| 676 SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); | 676 SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); |
| 677 } | 677 } |
| 678 | 678 |
| 679 void NativeMenuWin::SetMenuItemLabel(int menu_index, | 679 void NativeMenuWin::SetMenuItemLabel(int menu_index, |
| 680 int model_index, | 680 int model_index, |
| 681 const string16& label) { | 681 const base::string16& label) { |
| 682 if (IsSeparatorItemAt(menu_index)) | 682 if (IsSeparatorItemAt(menu_index)) |
| 683 return; | 683 return; |
| 684 | 684 |
| 685 MENUITEMINFO mii = {0}; | 685 MENUITEMINFO mii = {0}; |
| 686 mii.cbSize = sizeof(mii); | 686 mii.cbSize = sizeof(mii); |
| 687 UpdateMenuItemInfoForString(&mii, model_index, label); | 687 UpdateMenuItemInfoForString(&mii, model_index, label); |
| 688 SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); | 688 SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); |
| 689 } | 689 } |
| 690 | 690 |
| 691 void NativeMenuWin::UpdateMenuItemInfoForString(MENUITEMINFO* mii, | 691 void NativeMenuWin::UpdateMenuItemInfoForString(MENUITEMINFO* mii, |
| 692 int model_index, | 692 int model_index, |
| 693 const string16& label) { | 693 const base::string16& label) { |
| 694 string16 formatted = label; | 694 base::string16 formatted = label; |
| 695 ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); | 695 ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); |
| 696 // Strip out any tabs, otherwise they get interpreted as accelerators and can | 696 // Strip out any tabs, otherwise they get interpreted as accelerators and can |
| 697 // lead to weird behavior. | 697 // lead to weird behavior. |
| 698 ReplaceSubstringsAfterOffset(&formatted, 0, L"\t", L" "); | 698 ReplaceSubstringsAfterOffset(&formatted, 0, L"\t", L" "); |
| 699 if (type != ui::MenuModel::TYPE_SUBMENU) { | 699 if (type != ui::MenuModel::TYPE_SUBMENU) { |
| 700 // Add accelerator details to the label if provided. | 700 // Add accelerator details to the label if provided. |
| 701 ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE); | 701 ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE); |
| 702 if (model_->GetAcceleratorAt(model_index, &accelerator)) { | 702 if (model_->GetAcceleratorAt(model_index, &accelerator)) { |
| 703 formatted += L"\t"; | 703 formatted += L"\t"; |
| 704 formatted += accelerator.GetShortcutText(); | 704 formatted += accelerator.GetShortcutText(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 | 755 |
| 756 //////////////////////////////////////////////////////////////////////////////// | 756 //////////////////////////////////////////////////////////////////////////////// |
| 757 // MenuWrapper, public: | 757 // MenuWrapper, public: |
| 758 | 758 |
| 759 // static | 759 // static |
| 760 MenuWrapper* MenuWrapper::CreateWrapper(ui::MenuModel* model) { | 760 MenuWrapper* MenuWrapper::CreateWrapper(ui::MenuModel* model) { |
| 761 return new NativeMenuWin(model, NULL); | 761 return new NativeMenuWin(model, NULL); |
| 762 } | 762 } |
| 763 | 763 |
| 764 } // namespace views | 764 } // namespace views |
| OLD | NEW |