Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(606)

Side by Side Diff: views/controls/native_control.cc

Issue 8687031: views: Move the remaining files to ui/views/controls/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/controls/native_control.h ('k') | views/controls/native_control_gtk.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "views/controls/native_control.h"
6
7 #include <atlbase.h>
8 #include <atlapp.h>
9 #include <atlcrack.h>
10 #include <atlframe.h>
11 #include <atlmisc.h>
12
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "ui/base/accessibility/accessibility_types.h"
16 #include "ui/base/keycodes/keyboard_code_conversion_win.h"
17 #include "ui/base/keycodes/keyboard_codes.h"
18 #include "ui/base/l10n/l10n_util_win.h"
19 #include "ui/base/view_prop.h"
20 #include "ui/base/win/hwnd_util.h"
21 #include "ui/views/controls/native/native_view_host.h"
22 #include "ui/views/focus/focus_manager.h"
23 #include "ui/views/widget/widget.h"
24 #include "views/background.h"
25 #include "views/border.h"
26
27 using ui::ViewProp;
28
29 namespace views {
30
31 // Maps to the NativeControl.
32 static const char* const kNativeControlKey = "__NATIVE_CONTROL__";
33
34 class NativeControlContainer : public CWindowImpl<NativeControlContainer,
35 CWindow,
36 CWinTraits<WS_CHILD | WS_CLIPSIBLINGS |
37 WS_CLIPCHILDREN>> {
38 public:
39 explicit NativeControlContainer(NativeControl* parent)
40 : parent_(parent),
41 control_(NULL),
42 original_handler_(NULL) {
43 }
44
45 void Init() {
46 Create(parent_->GetWidget()->GetNativeView());
47 ::ShowWindow(m_hWnd, SW_SHOW);
48 }
49
50 virtual ~NativeControlContainer() {
51 }
52
53 // NOTE: If you add a new message, be sure and verify parent_ is valid before
54 // calling into parent_.
55 DECLARE_FRAME_WND_CLASS(L"ChromeViewsNativeControlContainer", NULL);
56 BEGIN_MSG_MAP(NativeControlContainer);
57 MSG_WM_CREATE(OnCreate);
58 MSG_WM_ERASEBKGND(OnEraseBkgnd);
59 MSG_WM_PAINT(OnPaint);
60 MSG_WM_SIZE(OnSize);
61 MSG_WM_NOTIFY(OnNotify);
62 MSG_WM_COMMAND(OnCommand);
63 MSG_WM_DESTROY(OnDestroy);
64 MSG_WM_CONTEXTMENU(OnContextMenu);
65 MSG_WM_CTLCOLORBTN(OnCtlColorBtn);
66 MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic)
67 END_MSG_MAP();
68
69 HWND GetControl() {
70 return control_;
71 }
72
73 // Called when the parent is getting deleted. This control stays around until
74 // it gets the OnFinalMessage call.
75 void ResetParent() {
76 parent_ = NULL;
77 }
78
79 void OnFinalMessage(HWND hwnd) {
80 if (parent_)
81 parent_->NativeControlDestroyed();
82 delete this;
83 }
84
85 private:
86 friend class NativeControl;
87
88 LRESULT OnCreate(LPCREATESTRUCT create_struct) {
89 control_ = parent_->CreateNativeControl(m_hWnd);
90
91 // We subclass the control hwnd so we get the WM_KEYDOWN messages.
92 original_handler_ = ui::SetWindowProc(
93 control_, &NativeControl::NativeControlWndProc);
94 prop_.reset(new ViewProp(control_, kNativeControlKey , parent_));
95
96 ::ShowWindow(control_, SW_SHOW);
97 return 1;
98 }
99
100 LRESULT OnEraseBkgnd(HDC dc) {
101 return 1;
102 }
103
104 void OnPaint(HDC ignore) {
105 PAINTSTRUCT ps;
106 HDC dc = ::BeginPaint(*this, &ps);
107 ::EndPaint(*this, &ps);
108 }
109
110 void OnSize(int type, const CSize& sz) {
111 ::MoveWindow(control_, 0, 0, sz.cx, sz.cy, TRUE);
112 }
113
114 LRESULT OnCommand(UINT code, int id, HWND source) {
115 return parent_ ? parent_->OnCommand(code, id, source) : 0;
116 }
117
118 LRESULT OnNotify(int w_param, LPNMHDR l_param) {
119 if (parent_)
120 return parent_->OnNotify(w_param, l_param);
121 else
122 return 0;
123 }
124
125 void OnDestroy() {
126 if (parent_)
127 parent_->OnDestroy();
128 }
129
130 void OnContextMenu(HWND window, const POINT& location) {
131 if (parent_)
132 parent_->OnContextMenu(location);
133 }
134
135 // We need to find an ancestor with a non-null background, and
136 // ask it for a (solid color) brush that approximates
137 // the background. The caller will use this when drawing
138 // the native control as a background color, particularly
139 // for radiobuttons and XP style pushbuttons.
140 LRESULT OnCtlColor(UINT msg, HDC dc, HWND control) {
141 const View *ancestor = parent_;
142 while (ancestor) {
143 const Background *background = ancestor->background();
144 if (background) {
145 HBRUSH brush = background->GetNativeControlBrush();
146 if (brush)
147 return reinterpret_cast<LRESULT>(brush);
148 }
149 ancestor = ancestor->parent();
150 }
151
152 // COLOR_BTNFACE is the default for dialog box backgrounds.
153 return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_BTNFACE));
154 }
155
156 LRESULT OnCtlColorBtn(HDC dc, HWND control) {
157 return OnCtlColor(WM_CTLCOLORBTN, dc, control);
158 }
159
160 LRESULT OnCtlColorStatic(HDC dc, HWND control) {
161 return OnCtlColor(WM_CTLCOLORSTATIC, dc, control);
162 }
163
164 NativeControl* parent_;
165 HWND control_;
166
167 // Message handler that was set before we reset it.
168 WNDPROC original_handler_;
169
170 scoped_ptr<ViewProp> prop_;
171
172 DISALLOW_COPY_AND_ASSIGN(NativeControlContainer);
173 };
174
175 NativeControl::NativeControl() : hwnd_view_(NULL),
176 container_(NULL),
177 fixed_width_(-1),
178 horizontal_alignment_(CENTER),
179 fixed_height_(-1),
180 vertical_alignment_(CENTER) {
181 set_focusable(true);
182 }
183
184 NativeControl::~NativeControl() {
185 if (container_) {
186 container_->ResetParent();
187 ::DestroyWindow(*container_);
188 }
189 }
190
191 void NativeControl::ValidateNativeControl() {
192 if (hwnd_view_ == NULL) {
193 hwnd_view_ = new NativeViewHost;
194 AddChildView(hwnd_view_);
195 }
196
197 if (!container_ && IsVisible()) {
198 container_ = new NativeControlContainer(this);
199 container_->Init();
200 hwnd_view_->Attach(*container_);
201 if (!IsEnabled())
202 EnableWindow(GetNativeControlHWND(), IsEnabled());
203
204 // This message ensures that the focus border is shown.
205 ::SendMessage(container_->GetControl(),
206 WM_CHANGEUISTATE,
207 MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS),
208 0);
209 }
210 }
211
212 void NativeControl::ViewHierarchyChanged(bool is_add, View *parent,
213 View *child) {
214 if (is_add && parent != this && !container_ && GetWidget()) {
215 ValidateNativeControl();
216 Layout();
217 }
218 }
219
220 void NativeControl::Layout() {
221 if (!container_ && GetWidget())
222 ValidateNativeControl();
223
224 if (hwnd_view_) {
225 gfx::Rect lb = GetLocalBounds();
226
227 int x = lb.x();
228 int y = lb.y();
229 int width = lb.width();
230 int height = lb.height();
231 if (fixed_width_ > 0) {
232 width = std::min(fixed_width_, width);
233 switch (horizontal_alignment_) {
234 case LEADING:
235 // Nothing to do.
236 break;
237 case CENTER:
238 x += (lb.width() - width) / 2;
239 break;
240 case TRAILING:
241 x = x + lb.width() - width;
242 break;
243 default:
244 NOTREACHED();
245 }
246 }
247
248 if (fixed_height_ > 0) {
249 height = std::min(fixed_height_, height);
250 switch (vertical_alignment_) {
251 case LEADING:
252 // Nothing to do.
253 break;
254 case CENTER:
255 y += (lb.height() - height) / 2;
256 break;
257 case TRAILING:
258 y = y + lb.height() - height;
259 break;
260 default:
261 NOTREACHED();
262 }
263 }
264
265 hwnd_view_->SetBounds(x, y, width, height);
266 }
267 }
268
269 void NativeControl::OnContextMenu(const POINT& location) {
270 if (!context_menu_controller())
271 return;
272
273 if (location.x == -1 && location.y == -1)
274 ShowContextMenu(GetKeyboardContextMenuLocation(), false);
275 else
276 ShowContextMenu(gfx::Point(location), true);
277 }
278
279 void NativeControl::OnFocus() {
280 if (container_) {
281 DCHECK(container_->GetControl());
282 ::SetFocus(container_->GetControl());
283 if (GetWidget()) {
284 GetWidget()->NotifyAccessibilityEvent(
285 this, ui::AccessibilityTypes::EVENT_FOCUS, false);
286 }
287 }
288 }
289
290 HWND NativeControl::GetNativeControlHWND() {
291 if (container_)
292 return container_->GetControl();
293 else
294 return NULL;
295 }
296
297 void NativeControl::NativeControlDestroyed() {
298 if (hwnd_view_)
299 hwnd_view_->Detach();
300 container_ = NULL;
301 }
302
303 void NativeControl::SetVisible(bool f) {
304 if (f != IsVisible()) {
305 View::SetVisible(f);
306 if (!f && container_) {
307 ::DestroyWindow(*container_);
308 } else if (f && !container_) {
309 ValidateNativeControl();
310 }
311 }
312 }
313
314 void NativeControl::OnEnabledChanged() {
315 View::OnEnabledChanged();
316 if (GetNativeControlHWND())
317 EnableWindow(GetNativeControlHWND(), IsEnabled());
318 }
319
320 void NativeControl::OnPaint(gfx::Canvas* canvas) {
321 }
322
323 void NativeControl::VisibilityChanged(View* starting_from, bool is_visible) {
324 SetVisible(is_visible);
325 }
326
327 void NativeControl::SetFixedWidth(int width, Alignment alignment) {
328 DCHECK_GT(width, 0);
329 fixed_width_ = width;
330 horizontal_alignment_ = alignment;
331 }
332
333 void NativeControl::SetFixedHeight(int height, Alignment alignment) {
334 DCHECK_GT(height, 0);
335 fixed_height_ = height;
336 vertical_alignment_ = alignment;
337 }
338
339 DWORD NativeControl::GetAdditionalExStyle() const {
340 // If the UI for the view is mirrored, we should make sure we add the
341 // extended window style for a right-to-left layout so the subclass creates
342 // a mirrored HWND for the underlying control.
343 DWORD ex_style = 0;
344 if (base::i18n::IsRTL())
345 ex_style |= l10n_util::GetExtendedStyles();
346
347 return ex_style;
348 }
349
350 DWORD NativeControl::GetAdditionalRTLStyle() const {
351 // If the UI for the view is mirrored, we should make sure we add the
352 // extended window style for a right-to-left layout so the subclass creates
353 // a mirrored HWND for the underlying control.
354 DWORD ex_style = 0;
355 if (base::i18n::IsRTL())
356 ex_style |= l10n_util::GetExtendedTooltipStyles();
357
358 return ex_style;
359 }
360
361 // static
362 LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window,
363 UINT message,
364 WPARAM w_param,
365 LPARAM l_param) {
366 NativeControl* native_control = static_cast<NativeControl*>(
367 ViewProp::GetValue(window, kNativeControlKey));
368 DCHECK(native_control);
369 WNDPROC original_handler = native_control->container_->original_handler_;
370 DCHECK(original_handler);
371
372 if (message == WM_KEYDOWN &&
373 native_control->OnKeyDown(ui::KeyboardCodeForWindowsKeyCode(w_param))) {
374 return 0;
375 } else if (message == WM_SETFOCUS) {
376 // Let the focus manager know that the focus changed.
377 FocusManager* focus_manager = native_control->GetFocusManager();
378 if (focus_manager) {
379 focus_manager->SetFocusedView(native_control);
380 } else {
381 NOTREACHED();
382 }
383 } else if (message == WM_DESTROY) {
384 ui::SetWindowProc(window, reinterpret_cast<WNDPROC>(original_handler));
385 native_control->container_->prop_.reset();
386 }
387
388 return CallWindowProc(reinterpret_cast<WNDPROC>(original_handler), window,
389 message, w_param, l_param);
390 }
391
392 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/native_control.h ('k') | views/controls/native_control_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698