cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / third_party / active_doc / in_place_menu.h
blob4b7be502b5f5ff96fce1f6167fdc1a761aee4c56
1 // in_place_menu.h : menu merging implementation
2 //
3 // This file is a modified version of the menu.h file, which is
4 // part of the ActiveDoc MSDN sample. The modifications are largely
5 // conversions to Google coding guidelines. Below is the original header
6 // from the file.
8 // This is a part of the Active Template Library.
9 // Copyright (c) Microsoft Corporation. All rights reserved.
11 // This source code is only intended as a supplement to the
12 // Active Template Library Reference and related
13 // electronic documentation provided with the library.
14 // See these sources for detailed information regarding the
15 // Active Template Library product.
17 #ifndef CHROME_FRAME_IN_PLACE_MENU_H_
18 #define CHROME_FRAME_IN_PLACE_MENU_H_
20 #include "base/logging.h"
21 #include "base/win/scoped_comptr.h"
23 template <class T>
24 class InPlaceMenu {
25 public:
26 InPlaceMenu() : shared_menu_(NULL), ole_menu_(NULL), our_menu_(NULL) {
29 ~InPlaceMenu() {
30 InPlaceMenuDestroy();
33 HRESULT InPlaceMenuCreate(LPCWSTR menu_name) {
34 // We might already have an in-place menu set, because we set menus
35 // IOleDocumentView::UIActivate as well as in
36 // IOleInPlaceActiveObject::OnDocWindowActivate. If we have already
37 // done our work, just return silently
38 if (ole_menu_ || shared_menu_)
39 return S_OK;
41 base::win::ScopedComPtr<IOleInPlaceFrame> in_place_frame;
42 GetInPlaceFrame(in_place_frame.Receive());
43 // We have no IOleInPlaceFrame, no menu merging possible
44 if (!in_place_frame) {
45 NOTREACHED();
46 return E_FAIL;
48 // Create a blank menu and ask the container to add
49 // its menus into the OLEMENUGROUPWIDTHS structure
50 shared_menu_ = ::CreateMenu();
51 OLEMENUGROUPWIDTHS mgw = {0};
52 HRESULT hr = in_place_frame->InsertMenus(shared_menu_, &mgw);
53 if (FAILED(hr)) {
54 ::DestroyMenu(shared_menu_);
55 shared_menu_ = NULL;
56 return hr;
58 // Insert our menus
59 our_menu_ = LoadMenu(_AtlBaseModule.GetResourceInstance(),menu_name);
60 MergeMenus(shared_menu_, our_menu_, &mgw.width[0], 1);
61 // Send the menu to the client
62 ole_menu_ = (HMENU)OleCreateMenuDescriptor(shared_menu_, &mgw);
63 T* t = static_cast<T*>(this);
64 in_place_frame->SetMenu(shared_menu_, ole_menu_, t->m_hWnd);
65 return S_OK;
68 HRESULT InPlaceMenuDestroy() {
69 base::win::ScopedComPtr<IOleInPlaceFrame> in_place_frame;
70 GetInPlaceFrame(in_place_frame.Receive());
71 if (in_place_frame) {
72 in_place_frame->RemoveMenus(shared_menu_);
73 in_place_frame->SetMenu(NULL, NULL, NULL);
75 if (ole_menu_) {
76 OleDestroyMenuDescriptor(ole_menu_);
77 ole_menu_ = NULL;
79 if (shared_menu_) {
80 UnmergeMenus(shared_menu_, our_menu_);
81 DestroyMenu(shared_menu_);
82 shared_menu_ = NULL;
84 if (our_menu_) {
85 DestroyMenu(our_menu_);
86 our_menu_ = NULL;
88 return S_OK;
91 void MergeMenus(HMENU shared_menu, HMENU source_menu, LONG* menu_widths,
92 unsigned int width_index) {
93 // Copy the popups from the source menu
94 // Insert at appropriate spot depending on width_index
95 DCHECK(width_index == 0 || width_index == 1);
96 int position = 0;
97 if (width_index == 1)
98 position = (int)menu_widths[0];
99 int group_width = 0;
100 int menu_items = GetMenuItemCount(source_menu);
101 for (int index = 0; index < menu_items; index++) {
102 // Get the HMENU of the popup
103 HMENU popup_menu = ::GetSubMenu(source_menu, index);
104 // Separators move us to next group
105 UINT state = GetMenuState(source_menu, index, MF_BYPOSITION);
106 if (!popup_menu && (state & MF_SEPARATOR)) {
107 // Servers should not touch past 5
108 DCHECK(width_index <= 5);
109 menu_widths[width_index] = group_width;
110 group_width = 0;
111 if (width_index < 5)
112 position += static_cast<int>(menu_widths[width_index+1]);
113 width_index += 2;
114 } else {
115 // Get the menu item text
116 TCHAR item_text[256] = {0};
117 int text_length = GetMenuString(source_menu, index, item_text,
118 ARRAYSIZE(item_text), MF_BYPOSITION);
119 // Popups are handled differently than normal menu items
120 if (popup_menu) {
121 if (::GetMenuItemCount(popup_menu) != 0) {
122 // Strip the HIBYTE because it contains a count of items
123 state = LOBYTE(state) | MF_POPUP; // Must be popup
124 // Non-empty popup -- add it to the shared menu bar
125 InsertMenu(shared_menu, position, state|MF_BYPOSITION,
126 reinterpret_cast<UINT_PTR>(popup_menu), item_text);
127 ++position;
128 ++group_width;
130 } else if (text_length > 0) {
131 // only non-empty items are added
132 DCHECK(item_text[0] != 0);
133 // here the state does not contain a count in the HIBYTE
134 InsertMenu(shared_menu, position, state|MF_BYPOSITION,
135 GetMenuItemID(source_menu, index), item_text);
136 ++position;
137 ++group_width;
143 void UnmergeMenus(HMENU shared_menu, HMENU source_menu) {
144 int our_item_count = GetMenuItemCount(source_menu);
145 int shared_item_count = GetMenuItemCount(shared_menu);
147 for (int index = shared_item_count - 1; index >= 0; index--) {
148 // Check the popup menus
149 HMENU popup_menu = ::GetSubMenu(shared_menu, index);
150 if (popup_menu) {
151 // If it is one of ours, remove it from the shared menu
152 for (int sub_index = 0; sub_index < our_item_count; sub_index++) {
153 if (::GetSubMenu(source_menu, sub_index) == popup_menu) {
154 // Remove the menu from hMenuShared
155 RemoveMenu(shared_menu, index, MF_BYPOSITION);
156 break;
163 protected:
164 HRESULT GetInPlaceFrame(IOleInPlaceFrame** in_place_frame) {
165 if (!in_place_frame) {
166 NOTREACHED();
167 return E_POINTER;
169 T* t = static_cast<T*>(this);
170 HRESULT hr = E_FAIL;
171 if (S_OK != t->GetInPlaceFrame(in_place_frame)) {
172 // We weren't given an IOleInPlaceFrame pointer, so
173 // we'll have to get it ourselves.
174 if (t->m_spInPlaceSite) {
175 t->frame_info_.cb = sizeof(OLEINPLACEFRAMEINFO);
176 base::win::ScopedComPtr<IOleInPlaceUIWindow> in_place_ui_window;
177 RECT position_rect = {0};
178 RECT clip_rect = {0};
179 hr = t->m_spInPlaceSite->GetWindowContext(in_place_frame,
180 in_place_ui_window.Receive(),
181 &position_rect, &clip_rect,
182 &t->frame_info_);
185 return hr;
188 protected:
189 // The OLE menu descriptor created by the OleCreateMenuDescriptor
190 HMENU ole_menu_;
191 // The shared menu that we pass to IOleInPlaceFrame::SetMenu
192 HMENU shared_menu_;
193 // Our menu resource that we want to insert
194 HMENU our_menu_;
197 #endif // CHROME_FRAME_IN_PLACE_MENU_H_