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 |