blob: e1a5fef0d349b1afdd3bffa3715c3fd2ca1ceda9 [file] [log] [blame]
[email protected]8af4c1992010-02-04 21:38:071// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]2362e4f2009-05-08 00:34:055#include "views/view.h"
initial.commit09911bf2008-07-26 23:55:296
7#include <algorithm>
[email protected]1eb89e82008-08-15 12:27:038#ifndef NDEBUG
initial.commit09911bf2008-07-26 23:55:299#include <iostream>
[email protected]1eb89e82008-08-15 12:27:0310#endif
initial.commit09911bf2008-07-26 23:55:2911
[email protected]37126212009-05-06 02:23:3112#include "app/drag_drop_types.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/logging.h"
14#include "base/message_loop.h"
[email protected]82739cf2008-09-16 00:37:5615#include "base/scoped_handle.h"
[email protected]d55194ca2010-03-11 18:25:4516#include "base/utf_string_conversions.h"
[email protected]74db48eb2010-06-25 16:33:2317#include "gfx/canvas_skia.h"
[email protected]5c7293a2010-03-17 06:40:5718#include "gfx/path.h"
[email protected]d5282e72009-05-13 13:16:5219#include "third_party/skia/include/core/SkShader.h"
[email protected]2362e4f2009-05-08 00:34:0520#include "views/background.h"
21#include "views/layout_manager.h"
[email protected]3ee83f2c2009-05-10 05:58:4022#include "views/views_delegate.h"
[email protected]2362e4f2009-05-08 00:34:0523#include "views/widget/root_view.h"
[email protected]319d4ae2009-05-28 19:09:4524#include "views/widget/tooltip_manager.h"
[email protected]2362e4f2009-05-08 00:34:0525#include "views/widget/widget.h"
26#include "views/window/window.h"
[email protected]031e4d32009-12-29 01:13:2327
[email protected]6ff244f2009-01-20 20:38:0828#if defined(OS_WIN)
[email protected]2362e4f2009-05-08 00:34:0529#include "views/accessibility/view_accessibility_wrapper.h"
[email protected]6ff244f2009-01-20 20:38:0830#endif
[email protected]031e4d32009-12-29 01:13:2331#if defined(OS_LINUX)
32#include "app/scoped_handle_gtk.h"
33#endif
initial.commit09911bf2008-07-26 23:55:2934
[email protected]c2dacc92008-10-16 23:51:3835namespace views {
initial.commit09911bf2008-07-26 23:55:2936
37// static
[email protected]3ee83f2c2009-05-10 05:58:4038ViewsDelegate* ViewsDelegate::views_delegate = NULL;
39
40// static
[email protected]2362e4f2009-05-08 00:34:0541char View::kViewClassName[] = "views/View";
initial.commit09911bf2008-07-26 23:55:2942
[email protected]8af4c1992010-02-04 21:38:0743// static
44const int View::kShowFolderDropMenuDelay = 400;
45
initial.commit09911bf2008-07-26 23:55:2946/////////////////////////////////////////////////////////////////////////////
47//
48// View - constructors, destructors, initialization
49//
50/////////////////////////////////////////////////////////////////////////////
51
52View::View()
53 : id_(0),
54 group_(-1),
[email protected]6ff244f2009-01-20 20:38:0855 enabled_(true),
56 focusable_(false),
[email protected]83548a42010-06-18 13:53:3757 accessibility_focusable_(false),
[email protected]4f3dc372009-02-24 00:10:2958 bounds_(0, 0, 0, 0),
[email protected]9ea053e2010-07-15 08:19:0559 needs_layout_(true),
initial.commit09911bf2008-07-26 23:55:2960 parent_(NULL),
initial.commit09911bf2008-07-26 23:55:2961 is_visible_(true),
initial.commit09911bf2008-07-26 23:55:2962 is_parent_owned_(true),
63 notify_when_visible_bounds_in_root_changes_(false),
64 registered_for_visible_bounds_notification_(false),
[email protected]bda9556c2010-01-07 00:55:1665 accelerator_registration_delayed_(false),
initial.commit09911bf2008-07-26 23:55:2966 next_focusable_view_(NULL),
67 previous_focusable_view_(NULL),
[email protected]bda9556c2010-01-07 00:55:1668 accelerator_focus_manager_(NULL),
[email protected]71421c3f2009-06-06 00:41:4469 registered_accelerator_count_(0),
initial.commit09911bf2008-07-26 23:55:2970 context_menu_controller_(NULL),
[email protected]6ff244f2009-01-20 20:38:0871#if defined(OS_WIN)
72 accessibility_(NULL),
73#endif
initial.commit09911bf2008-07-26 23:55:2974 drag_controller_(NULL),
initial.commit09911bf2008-07-26 23:55:2975 flip_canvas_on_paint_for_rtl_ui_(false) {
76}
77
78View::~View() {
[email protected]8c57de22010-03-12 21:06:0479 if (parent_)
80 parent_->RemoveChildView(this);
81
initial.commit09911bf2008-07-26 23:55:2982 int c = static_cast<int>(child_views_.size());
83 while (--c >= 0) {
[email protected]8c57de22010-03-12 21:06:0484 child_views_[c]->SetParent(NULL);
initial.commit09911bf2008-07-26 23:55:2985 if (child_views_[c]->IsParentOwned())
86 delete child_views_[c];
initial.commit09911bf2008-07-26 23:55:2987 }
[email protected]a64f33902009-10-10 05:41:2388
89#if defined(OS_WIN)
[email protected]09fe9492009-11-07 02:23:0690 if (accessibility_.get())
[email protected]a64f33902009-10-10 05:41:2391 accessibility_->Uninitialize();
[email protected]a64f33902009-10-10 05:41:2392#endif
initial.commit09911bf2008-07-26 23:55:2993}
94
95/////////////////////////////////////////////////////////////////////////////
96//
97// View - sizing
98//
99/////////////////////////////////////////////////////////////////////////////
100
[email protected]0d8ea702008-10-14 17:03:07101gfx::Rect View::GetBounds(PositionMirroringSettings settings) const {
102 gfx::Rect bounds(bounds_);
initial.commit09911bf2008-07-26 23:55:29103
104 // If the parent uses an RTL UI layout and if we are asked to transform the
105 // bounds to their mirrored position if necessary, then we should shift the
106 // rectangle appropriately.
[email protected]0d8ea702008-10-14 17:03:07107 if (settings == APPLY_MIRRORING_TRANSFORMATION)
108 bounds.set_x(MirroredX());
[email protected]4f3dc372009-02-24 00:10:29109
[email protected]0d8ea702008-10-14 17:03:07110 return bounds;
initial.commit09911bf2008-07-26 23:55:29111}
112
[email protected]6f3bb6c2008-09-17 22:25:33113// y(), width() and height() are agnostic to the RTL UI layout of the
114// parent view. x(), on the other hand, is not.
initial.commit09911bf2008-07-26 23:55:29115int View::GetX(PositionMirroringSettings settings) const {
[email protected]80f8b9f2008-10-16 18:17:47116 return settings == IGNORE_MIRRORING_TRANSFORMATION ? x() : MirroredX();
initial.commit09911bf2008-07-26 23:55:29117}
118
[email protected]80f8b9f2008-10-16 18:17:47119void View::SetBounds(const gfx::Rect& bounds) {
120 if (bounds == bounds_)
initial.commit09911bf2008-07-26 23:55:29121 return;
initial.commit09911bf2008-07-26 23:55:29122
[email protected]80f8b9f2008-10-16 18:17:47123 gfx::Rect prev = bounds_;
initial.commit09911bf2008-07-26 23:55:29124 bounds_ = bounds;
[email protected]b97c8a22010-02-05 19:36:43125 bool size_changed = prev.size() != bounds_.size();
126 bool position_changed = prev.origin() != bounds_.origin();
initial.commit09911bf2008-07-26 23:55:29127
[email protected]b97c8a22010-02-05 19:36:43128 if (size_changed || position_changed) {
129 DidChangeBounds(prev, bounds_);
130
131 RootView* root = GetRootView();
132 if (root)
initial.commit09911bf2008-07-26 23:55:29133 root->ViewBoundsChanged(this, size_changed, position_changed);
134 }
135}
136
[email protected]80f8b9f2008-10-16 18:17:47137gfx::Rect View::GetLocalBounds(bool include_border) const {
[email protected]9a3f0ac22008-11-14 03:24:02138 if (include_border || !border_.get())
[email protected]80f8b9f2008-10-16 18:17:47139 return gfx::Rect(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:29140
[email protected]80f8b9f2008-10-16 18:17:47141 gfx::Insets insets;
142 border_->GetInsets(&insets);
143 return gfx::Rect(insets.left(), insets.top(),
[email protected]4a8d3272009-03-10 19:15:08144 std::max(0, width() - insets.width()),
145 std::max(0, height() - insets.height()));
initial.commit09911bf2008-07-26 23:55:29146}
147
[email protected]0a1d36b22008-10-17 19:33:09148gfx::Point View::GetPosition() const {
149 return gfx::Point(GetX(APPLY_MIRRORING_TRANSFORMATION), y());
initial.commit09911bf2008-07-26 23:55:29150}
151
[email protected]154f8bc2008-10-15 18:02:30152gfx::Size View::GetPreferredSize() {
153 if (layout_manager_.get())
154 return layout_manager_->GetPreferredSize(this);
155 return gfx::Size();
initial.commit09911bf2008-07-26 23:55:29156}
157
[email protected]a1360162009-11-30 21:19:07158int View::GetBaseline() {
159 return -1;
160}
161
initial.commit09911bf2008-07-26 23:55:29162void View::SizeToPreferredSize() {
[email protected]154f8bc2008-10-15 18:02:30163 gfx::Size prefsize = GetPreferredSize();
164 if ((prefsize.width() != width()) || (prefsize.height() != height()))
165 SetBounds(x(), y(), prefsize.width(), prefsize.height());
initial.commit09911bf2008-07-26 23:55:29166}
167
[email protected]7ccc52b72009-05-08 21:09:11168void View::PreferredSizeChanged() {
[email protected]9ea053e2010-07-15 08:19:05169 InvalidateLayout();
[email protected]7ccc52b72009-05-08 21:09:11170 if (parent_)
171 parent_->ChildPreferredSizeChanged(this);
172}
173
[email protected]154f8bc2008-10-15 18:02:30174gfx::Size View::GetMinimumSize() {
175 return GetPreferredSize();
initial.commit09911bf2008-07-26 23:55:29176}
177
178int View::GetHeightForWidth(int w) {
179 if (layout_manager_.get())
180 return layout_manager_->GetPreferredHeightForWidth(this, w);
[email protected]154f8bc2008-10-15 18:02:30181 return GetPreferredSize().height();
initial.commit09911bf2008-07-26 23:55:29182}
183
[email protected]80f8b9f2008-10-16 18:17:47184void View::DidChangeBounds(const gfx::Rect& previous,
185 const gfx::Rect& current) {
[email protected]9ea053e2010-07-15 08:19:05186 needs_layout_ = false;
[email protected]80f8b9f2008-10-16 18:17:47187 Layout();
initial.commit09911bf2008-07-26 23:55:29188}
189
[email protected]e9adf0702010-03-08 23:34:07190void View::ScrollRectToVisible(const gfx::Rect& rect) {
initial.commit09911bf2008-07-26 23:55:29191 View* parent = GetParent();
192
193 // We must take RTL UI mirroring into account when adjusting the position of
194 // the region.
[email protected]e9adf0702010-03-08 23:34:07195 if (parent) {
196 gfx::Rect scroll_rect(rect);
197 scroll_rect.Offset(GetX(APPLY_MIRRORING_TRANSFORMATION), y());
198 parent->ScrollRectToVisible(scroll_rect);
199 }
initial.commit09911bf2008-07-26 23:55:29200}
201
202/////////////////////////////////////////////////////////////////////////////
203//
204// View - layout
205//
206/////////////////////////////////////////////////////////////////////////////
207
208void View::Layout() {
[email protected]9ea053e2010-07-15 08:19:05209 needs_layout_ = false;
210
[email protected]f8617192010-07-05 07:57:10211 // If we have a layout manager, let it handle the layout for us.
initial.commit09911bf2008-07-26 23:55:29212 if (layout_manager_.get()) {
213 layout_manager_->Layout(this);
214 SchedulePaint();
215 }
216
[email protected]9ea053e2010-07-15 08:19:05217 // Make sure to propagate the Layout() call to any children that haven't
218 // received it yet through the layout manager and need to be laid out. This
219 // is needed for the case when the child requires a layout but its bounds
220 // weren't changed by the layout manager. If there is no layout manager, we
221 // just propagate the Layout() call down the hierarchy, so whoever receives
222 // the call can take appropriate action.
[email protected]09fe9492009-11-07 02:23:06223 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29224 View* child = GetChildViewAt(i);
[email protected]9ea053e2010-07-15 08:19:05225 if (child->needs_layout_ || !layout_manager_.get()) {
226 child->needs_layout_ = false;
227 child->Layout();
228 }
initial.commit09911bf2008-07-26 23:55:29229 }
230}
231
[email protected]9ea053e2010-07-15 08:19:05232void View::InvalidateLayout() {
233 if (needs_layout_)
234 return;
235 needs_layout_ = true;
236 if (parent_)
237 parent_->InvalidateLayout();
238}
239
initial.commit09911bf2008-07-26 23:55:29240LayoutManager* View::GetLayoutManager() const {
241 return layout_manager_.get();
242}
243
244void View::SetLayoutManager(LayoutManager* layout_manager) {
[email protected]09fe9492009-11-07 02:23:06245 if (layout_manager_.get())
initial.commit09911bf2008-07-26 23:55:29246 layout_manager_->Uninstalled(this);
[email protected]09fe9492009-11-07 02:23:06247
initial.commit09911bf2008-07-26 23:55:29248 layout_manager_.reset(layout_manager);
[email protected]09fe9492009-11-07 02:23:06249 if (layout_manager_.get())
initial.commit09911bf2008-07-26 23:55:29250 layout_manager_->Installed(this);
initial.commit09911bf2008-07-26 23:55:29251}
252
253////////////////////////////////////////////////////////////////////////////////
254//
255// View - Right-to-left UI layout
256//
257////////////////////////////////////////////////////////////////////////////////
258
[email protected]c3bca422010-02-19 23:29:02259int View::MirroredX() const {
initial.commit09911bf2008-07-26 23:55:29260 View* parent = GetParent();
[email protected]aaa71da52010-02-19 21:39:24261 return parent ? parent->MirroredLeftPointForRect(bounds_) : x();
initial.commit09911bf2008-07-26 23:55:29262}
263
264int View::MirroredLeftPointForRect(const gfx::Rect& bounds) const {
[email protected]c2f4bdb72010-05-10 23:15:21265 return base::i18n::IsRTL() ?
[email protected]aaa71da52010-02-19 21:39:24266 (width() - bounds.x() - bounds.width()) : bounds.x();
initial.commit09911bf2008-07-26 23:55:29267}
268
269////////////////////////////////////////////////////////////////////////////////
270//
271// View - states
272//
273////////////////////////////////////////////////////////////////////////////////
274
275bool View::IsEnabled() const {
276 return enabled_;
277}
278
279void View::SetEnabled(bool state) {
280 if (enabled_ != state) {
281 enabled_ = state;
282 SchedulePaint();
283 }
284}
285
initial.commit09911bf2008-07-26 23:55:29286void View::SetFocusable(bool focusable) {
287 focusable_ = focusable;
288}
289
[email protected]59461d22010-07-21 15:41:09290bool View::IsFocusableInRootView() const {
291 return IsFocusable() && IsVisibleInRootView();
292}
293
294bool View::IsAccessibilityFocusableInRootView() const {
[email protected]1aa36552010-07-14 08:21:25295 return (focusable_ || accessibility_focusable_) && IsEnabled() &&
296 IsVisibleInRootView();
[email protected]83548a42010-06-18 13:53:37297}
298
[email protected]82166b62009-06-30 18:48:00299FocusManager* View::GetFocusManager() {
300 Widget* widget = GetWidget();
301 return widget ? widget->GetFocusManager() : NULL;
302}
303
initial.commit09911bf2008-07-26 23:55:29304bool View::HasFocus() {
initial.commit09911bf2008-07-26 23:55:29305 FocusManager* focus_manager = GetFocusManager();
306 if (focus_manager)
307 return focus_manager->GetFocusedView() == this;
308 return false;
309}
310
[email protected]5c9e97a2009-09-09 23:48:30311void View::Focus() {
[email protected]7f14e1f2009-10-01 15:57:26312 // By default, we clear the native focus. This ensures that no visible native
313 // view as the focus and that we still receive keyboard inputs.
[email protected]5c9e97a2009-09-09 23:48:30314 FocusManager* focus_manager = GetFocusManager();
315 if (focus_manager)
[email protected]7f14e1f2009-10-01 15:57:26316 focus_manager->ClearNativeFocus();
[email protected]6a054ffa2010-08-06 07:07:18317
318 // Notify assistive technologies of the focus change.
319 NotifyAccessibilityEvent(AccessibilityTypes::EVENT_FOCUS);
320}
321
322void View::NotifyAccessibilityEvent(AccessibilityTypes::Event event_type) {
323 NotifyAccessibilityEvent(event_type, true);
[email protected]5c9e97a2009-09-09 23:48:30324}
325
initial.commit09911bf2008-07-26 23:55:29326void View::SetHotTracked(bool flag) {
327}
328
329/////////////////////////////////////////////////////////////////////////////
330//
331// View - painting
332//
333/////////////////////////////////////////////////////////////////////////////
334
[email protected]0a1d36b22008-10-17 19:33:09335void View::SchedulePaint(const gfx::Rect& r, bool urgent) {
336 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29337 return;
initial.commit09911bf2008-07-26 23:55:29338
339 if (parent_) {
340 // Translate the requested paint rect to the parent's coordinate system
341 // then pass this notification up to the parent.
[email protected]0a1d36b22008-10-17 19:33:09342 gfx::Rect paint_rect = r;
343 paint_rect.Offset(GetPosition());
initial.commit09911bf2008-07-26 23:55:29344 parent_->SchedulePaint(paint_rect, urgent);
345 }
346}
347
348void View::SchedulePaint() {
[email protected]0a1d36b22008-10-17 19:33:09349 SchedulePaint(GetLocalBounds(true), false);
initial.commit09911bf2008-07-26 23:55:29350}
351
[email protected]82522512009-05-15 07:37:29352void View::Paint(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29353 PaintBackground(canvas);
354 PaintFocusBorder(canvas);
355 PaintBorder(canvas);
356}
357
[email protected]82522512009-05-15 07:37:29358void View::PaintBackground(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02359 if (background_.get())
initial.commit09911bf2008-07-26 23:55:29360 background_->Paint(canvas, this);
361}
362
[email protected]82522512009-05-15 07:37:29363void View::PaintBorder(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02364 if (border_.get())
initial.commit09911bf2008-07-26 23:55:29365 border_->Paint(*this, canvas);
366}
367
[email protected]82522512009-05-15 07:37:29368void View::PaintFocusBorder(gfx::Canvas* canvas) {
[email protected]59461d22010-07-21 15:41:09369 if (HasFocus() && (IsFocusable() || IsAccessibilityFocusableInRootView()))
[email protected]6f3bb6c2008-09-17 22:25:33370 canvas->DrawFocusRect(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:29371}
372
[email protected]82522512009-05-15 07:37:29373void View::PaintChildren(gfx::Canvas* canvas) {
[email protected]09fe9492009-11-07 02:23:06374 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29375 View* child = GetChildViewAt(i);
376 if (!child) {
377 NOTREACHED() << "Should not have a NULL child View for index in bounds";
378 continue;
379 }
380 child->ProcessPaint(canvas);
381 }
382}
383
[email protected]82522512009-05-15 07:37:29384void View::ProcessPaint(gfx::Canvas* canvas) {
[email protected]09fe9492009-11-07 02:23:06385 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29386 return;
initial.commit09911bf2008-07-26 23:55:29387
388 // We're going to modify the canvas, save it's state first.
[email protected]bd026802010-06-29 22:08:44389 canvas->Save();
initial.commit09911bf2008-07-26 23:55:29390
391 // Paint this View and its children, setting the clip rect to the bounds
392 // of this View and translating the origin to the local bounds' top left
393 // point.
394 //
395 // Note that the X (or left) position we pass to ClipRectInt takes into
396 // consideration whether or not the view uses a right-to-left layout so that
397 // we paint our view in its mirrored position if need be.
[email protected]80f8b9f2008-10-16 18:17:47398 if (canvas->ClipRectInt(MirroredX(), y(), width(), height())) {
initial.commit09911bf2008-07-26 23:55:29399 // Non-empty clip, translate the graphics such that 0,0 corresponds to
400 // where this view is located (related to its parent).
[email protected]80f8b9f2008-10-16 18:17:47401 canvas->TranslateInt(MirroredX(), y());
initial.commit09911bf2008-07-26 23:55:29402
initial.commit09911bf2008-07-26 23:55:29403 // If the View we are about to paint requested the canvas to be flipped, we
404 // should change the transform appropriately.
[email protected]abffeda2010-08-13 22:35:50405 canvas->Save();
406 if (FlipCanvasOnPaintForRTLUI()) {
[email protected]6f3bb6c2008-09-17 22:25:33407 canvas->TranslateInt(width(), 0);
initial.commit09911bf2008-07-26 23:55:29408 canvas->ScaleInt(-1, 1);
initial.commit09911bf2008-07-26 23:55:29409 }
410
411 Paint(canvas);
412
413 // We must undo the canvas mirroring once the View is done painting so that
414 // we don't pass the canvas with the mirrored transform to Views that
415 // didn't request the canvas to be flipped.
[email protected]bd026802010-06-29 22:08:44416 canvas->Restore();
[email protected]abffeda2010-08-13 22:35:50417
initial.commit09911bf2008-07-26 23:55:29418 PaintChildren(canvas);
419 }
420
421 // Restore the canvas's original transform.
[email protected]bd026802010-06-29 22:08:44422 canvas->Restore();
initial.commit09911bf2008-07-26 23:55:29423}
424
425void View::PaintNow() {
[email protected]09fe9492009-11-07 02:23:06426 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29427 return;
initial.commit09911bf2008-07-26 23:55:29428
429 View* view = GetParent();
430 if (view)
431 view->PaintNow();
432}
433
initial.commit09911bf2008-07-26 23:55:29434gfx::Insets View::GetInsets() const {
initial.commit09911bf2008-07-26 23:55:29435 gfx::Insets insets;
[email protected]9a3f0ac22008-11-14 03:24:02436 if (border_.get())
437 border_->GetInsets(&insets);
initial.commit09911bf2008-07-26 23:55:29438 return insets;
439}
440
[email protected]e9adf0702010-03-08 23:34:07441gfx::NativeCursor View::GetCursorForPoint(Event::EventType event_type,
442 const gfx::Point& p) {
[email protected]9abf8dd62009-06-04 06:40:42443 return NULL;
444}
445
[email protected]a52ca4672009-06-05 05:41:09446bool View::HitTest(const gfx::Point& l) const {
[email protected]d7fc97942009-11-20 22:07:11447 if (l.x() >= 0 && l.x() < width() && l.y() >= 0 && l.y() < height()) {
[email protected]a52ca4672009-06-05 05:41:09448 if (HasHitTestMask()) {
449 gfx::Path mask;
450 GetHitTestMask(&mask);
[email protected]a3406972009-11-04 05:05:48451 ScopedRegion rgn(mask.CreateNativeRegion());
452 // TODO: can this use SkRegion's contains instead?
[email protected]a52ca4672009-06-05 05:41:09453#if defined(OS_WIN)
[email protected]a52ca4672009-06-05 05:41:09454 return !!PtInRegion(rgn, l.x(), l.y());
[email protected]10a6e77b2009-12-31 01:03:52455#elif defined(TOOLKIT_USES_GTK)
[email protected]a3406972009-11-04 05:05:48456 return gdk_region_point_in(rgn.Get(), l.x(), l.y());
[email protected]a52ca4672009-06-05 05:41:09457#endif
458 }
459 // No mask, but inside our bounds.
460 return true;
461 }
462 // Outside our bounds.
463 return false;
464}
465
initial.commit09911bf2008-07-26 23:55:29466void View::SetContextMenuController(ContextMenuController* menu_controller) {
467 context_menu_controller_ = menu_controller;
468}
469
[email protected]e9adf0702010-03-08 23:34:07470void View::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) {
[email protected]042811c2008-10-31 21:31:34471 if (!context_menu_controller_)
472 return;
473
[email protected]e9adf0702010-03-08 23:34:07474 context_menu_controller_->ShowContextMenu(this, p, is_mouse_gesture);
[email protected]042811c2008-10-31 21:31:34475}
476
initial.commit09911bf2008-07-26 23:55:29477/////////////////////////////////////////////////////////////////////////////
478//
479// View - tree
480//
481/////////////////////////////////////////////////////////////////////////////
482
483bool View::ProcessMousePressed(const MouseEvent& e, DragInfo* drag_info) {
[email protected]83548a42010-06-18 13:53:37484 const bool enabled = IsEnabled();
[email protected]e9adf0702010-03-08 23:34:07485 int drag_operations =
486 (enabled && e.IsOnlyLeftMouseButton() && HitTest(e.location())) ?
487 GetDragOperations(e.location()) : 0;
488 ContextMenuController* context_menu_controller = e.IsRightMouseButton() ?
489 context_menu_controller_ : 0;
initial.commit09911bf2008-07-26 23:55:29490
491 const bool result = OnMousePressed(e);
492 // WARNING: we may have been deleted, don't use any View variables;
493
494 if (!enabled)
495 return result;
496
497 if (drag_operations != DragDropTypes::DRAG_NONE) {
[email protected]e9adf0702010-03-08 23:34:07498 drag_info->PossibleDrag(e.location());
initial.commit09911bf2008-07-26 23:55:29499 return true;
500 }
501 return !!context_menu_controller || result;
502}
503
504bool View::ProcessMouseDragged(const MouseEvent& e, DragInfo* drag_info) {
505 // Copy the field, that way if we're deleted after drag and drop no harm is
506 // done.
507 ContextMenuController* context_menu_controller = context_menu_controller_;
508 const bool possible_drag = drag_info->possible_drag;
[email protected]e9adf0702010-03-08 23:34:07509 if (possible_drag && ExceededDragThreshold(drag_info->start_pt.x() - e.x(),
510 drag_info->start_pt.y() - e.y())) {
[email protected]b5f94de2009-12-04 07:59:00511 if (!drag_controller_ ||
[email protected]e9adf0702010-03-08 23:34:07512 drag_controller_->CanStartDrag(this, drag_info->start_pt, e.location()))
513 DoDrag(e, drag_info->start_pt);
initial.commit09911bf2008-07-26 23:55:29514 } else {
515 if (OnMouseDragged(e))
516 return true;
517 // Fall through to return value based on context menu controller.
518 }
519 // WARNING: we may have been deleted.
520 return (context_menu_controller != NULL) || possible_drag;
521}
522
523void View::ProcessMouseReleased(const MouseEvent& e, bool canceled) {
524 if (!canceled && context_menu_controller_ && e.IsOnlyRightMouseButton()) {
525 // Assume that if there is a context menu controller we won't be deleted
526 // from mouse released.
[email protected]96b667d2008-10-14 20:58:44527 gfx::Point location(e.location());
initial.commit09911bf2008-07-26 23:55:29528 OnMouseReleased(e, canceled);
[email protected]464fdb32009-03-19 20:25:44529 if (HitTest(location)) {
530 ConvertPointToScreen(this, &location);
[email protected]e9adf0702010-03-08 23:34:07531 ShowContextMenu(location, true);
[email protected]464fdb32009-03-19 20:25:44532 }
initial.commit09911bf2008-07-26 23:55:29533 } else {
534 OnMouseReleased(e, canceled);
535 }
536 // WARNING: we may have been deleted.
537}
538
[email protected]ad84c8f2010-09-08 14:06:10539#if defined(TOUCH_UI)
540bool View::ProcessTouchEvent(const TouchEvent& e) {
541 // TODO(rjkroege): Implement a grab scheme similar to as
542 // as is found in MousePressed.
543 const bool result = OnTouchEvent(e);
544 return result;
545}
546#endif
547
initial.commit09911bf2008-07-26 23:55:29548void View::AddChildView(View* v) {
[email protected]0d52b2302009-05-11 23:50:55549 AddChildView(static_cast<int>(child_views_.size()), v);
initial.commit09911bf2008-07-26 23:55:29550}
551
552void View::AddChildView(int index, View* v) {
[email protected]0b2fa2b2009-12-01 01:06:12553 CHECK(v != this) << "You cannot add a view as its own child";
554
initial.commit09911bf2008-07-26 23:55:29555 // Remove the view from its current parent if any.
556 if (v->GetParent())
557 v->GetParent()->RemoveChildView(v);
558
[email protected]0d52b2302009-05-11 23:50:55559 // Sets the prev/next focus views.
560 InitFocusSiblings(v, index);
initial.commit09911bf2008-07-26 23:55:29561
562 // Let's insert the view.
563 child_views_.insert(child_views_.begin() + index, v);
564 v->SetParent(this);
565
[email protected]09fe9492009-11-07 02:23:06566 for (View* p = this; p; p = p->GetParent())
initial.commit09911bf2008-07-26 23:55:29567 p->ViewHierarchyChangedImpl(false, true, this, v);
[email protected]09fe9492009-11-07 02:23:06568
initial.commit09911bf2008-07-26 23:55:29569 v->PropagateAddNotifications(this, v);
570 UpdateTooltip();
571 RootView* root = GetRootView();
572 if (root)
[email protected]9fc4f202010-07-07 15:38:19573 RegisterChildrenForVisibleBoundsNotification(root, v);
initial.commit09911bf2008-07-26 23:55:29574
575 if (layout_manager_.get())
576 layout_manager_->ViewAdded(this, v);
577}
578
579View* View::GetChildViewAt(int index) const {
580 return index < GetChildViewCount() ? child_views_[index] : NULL;
581}
582
583int View::GetChildViewCount() const {
584 return static_cast<int>(child_views_.size());
585}
586
[email protected]3a9c26f2010-03-12 21:04:39587bool View::HasChildView(View* a_view) {
588 return find(child_views_.begin(),
589 child_views_.end(),
590 a_view) != child_views_.end();
591}
592
initial.commit09911bf2008-07-26 23:55:29593void View::RemoveChildView(View* a_view) {
594 DoRemoveChildView(a_view, true, true, false);
595}
596
597void View::RemoveAllChildViews(bool delete_views) {
598 ViewList::iterator iter;
599 while ((iter = child_views_.begin()) != child_views_.end()) {
600 DoRemoveChildView(*iter, false, false, delete_views);
601 }
602 UpdateTooltip();
603}
604
[email protected]e9adf0702010-03-08 23:34:07605void View::DoDrag(const MouseEvent& e, const gfx::Point& press_pt) {
606 int drag_operations = GetDragOperations(press_pt);
[email protected]4768c65b2009-08-28 21:42:59607 if (drag_operations == DragDropTypes::DRAG_NONE)
608 return;
609
610 OSExchangeData data;
[email protected]e9adf0702010-03-08 23:34:07611 WriteDragData(press_pt, &data);
[email protected]4768c65b2009-08-28 21:42:59612
613 // Message the RootView to do the drag and drop. That way if we're removed
614 // the RootView can detect it and avoid calling us back.
615 RootView* root_view = GetRootView();
616 root_view->StartDragForViewFromMouseEvent(this, data, drag_operations);
617}
618
initial.commit09911bf2008-07-26 23:55:29619void View::DoRemoveChildView(View* a_view,
620 bool update_focus_cycle,
621 bool update_tool_tip,
622 bool delete_removed_view) {
623#ifndef NDEBUG
624 DCHECK(!IsProcessingPaint()) << "Should not be removing a child view " <<
625 "during a paint, this will seriously " <<
626 "mess things up!";
627#endif
628 DCHECK(a_view);
629 const ViewList::iterator i = find(child_views_.begin(),
630 child_views_.end(),
631 a_view);
632 if (i != child_views_.end()) {
[email protected]0d52b2302009-05-11 23:50:55633 if (update_focus_cycle) {
initial.commit09911bf2008-07-26 23:55:29634 // Let's remove the view from the focus traversal.
635 View* next_focusable = a_view->next_focusable_view_;
636 View* prev_focusable = a_view->previous_focusable_view_;
637 if (prev_focusable)
638 prev_focusable->next_focusable_view_ = next_focusable;
639 if (next_focusable)
640 next_focusable->previous_focusable_view_ = prev_focusable;
641 }
642
643 RootView* root = GetRootView();
644 if (root)
[email protected]9fc4f202010-07-07 15:38:19645 UnregisterChildrenForVisibleBoundsNotification(root, a_view);
initial.commit09911bf2008-07-26 23:55:29646 a_view->PropagateRemoveNotifications(this);
647 a_view->SetParent(NULL);
648
649 if (delete_removed_view && a_view->IsParentOwned())
650 delete a_view;
651
652 child_views_.erase(i);
653 }
654
655 if (update_tool_tip)
656 UpdateTooltip();
657
658 if (layout_manager_.get())
659 layout_manager_->ViewRemoved(this, a_view);
660}
661
662void View::PropagateRemoveNotifications(View* parent) {
[email protected]09fe9492009-11-07 02:23:06663 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29664 GetChildViewAt(i)->PropagateRemoveNotifications(parent);
initial.commit09911bf2008-07-26 23:55:29665
[email protected]09fe9492009-11-07 02:23:06666 for (View* v = this; v; v = v->GetParent())
667 v->ViewHierarchyChangedImpl(true, false, parent, this);
initial.commit09911bf2008-07-26 23:55:29668}
669
670void View::PropagateAddNotifications(View* parent, View* child) {
[email protected]09fe9492009-11-07 02:23:06671 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29672 GetChildViewAt(i)->PropagateAddNotifications(parent, child);
initial.commit09911bf2008-07-26 23:55:29673 ViewHierarchyChangedImpl(true, true, parent, child);
674}
675
[email protected]59461d22010-07-21 15:41:09676bool View::IsFocusable() const {
677 return focusable_ && IsEnabled() && IsVisible();
678}
679
[email protected]8b9a8f12010-07-27 01:39:13680void View::PropagateThemeChanged() {
[email protected]b2b718012010-03-25 15:09:06681 for (int i = GetChildViewCount() - 1; i >= 0; --i)
[email protected]8b9a8f12010-07-27 01:39:13682 GetChildViewAt(i)->PropagateThemeChanged();
683 OnThemeChanged();
[email protected]32670b02009-03-03 00:28:00684}
685
[email protected]8b9a8f12010-07-27 01:39:13686void View::PropagateLocaleChanged() {
[email protected]b2b718012010-03-25 15:09:06687 for (int i = GetChildViewCount() - 1; i >= 0; --i)
[email protected]8b9a8f12010-07-27 01:39:13688 GetChildViewAt(i)->PropagateLocaleChanged();
689 OnLocaleChanged();
[email protected]b2b718012010-03-25 15:09:06690}
691
initial.commit09911bf2008-07-26 23:55:29692#ifndef NDEBUG
693bool View::IsProcessingPaint() const {
694 return GetParent() && GetParent()->IsProcessingPaint();
695}
696#endif
697
[email protected]f704ee72008-11-10 21:31:59698gfx::Point View::GetKeyboardContextMenuLocation() {
699 gfx::Rect vis_bounds = GetVisibleBounds();
700 gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2,
701 vis_bounds.y() + vis_bounds.height() / 2);
702 ConvertPointToScreen(this, &screen_point);
703 return screen_point;
704}
705
[email protected]82739cf2008-09-16 00:37:56706bool View::HasHitTestMask() const {
707 return false;
708}
709
710void View::GetHitTestMask(gfx::Path* mask) const {
711 DCHECK(mask);
712}
713
[email protected]bb515ed2009-01-15 00:53:43714void View::ViewHierarchyChanged(bool is_add,
715 View* parent,
716 View* child) {
initial.commit09911bf2008-07-26 23:55:29717}
718
719void View::ViewHierarchyChangedImpl(bool register_accelerators,
[email protected]bb515ed2009-01-15 00:53:43720 bool is_add,
721 View* parent,
722 View* child) {
initial.commit09911bf2008-07-26 23:55:29723 if (register_accelerators) {
724 if (is_add) {
725 // If you get this registration, you are part of a subtree that has been
726 // added to the view hierarchy.
[email protected]bda9556c2010-01-07 00:55:16727 if (GetFocusManager()) {
728 RegisterPendingAccelerators();
729 } else {
730 // Delay accelerator registration until visible as we do not have
731 // focus manager until then.
732 accelerator_registration_delayed_ = true;
733 }
initial.commit09911bf2008-07-26 23:55:29734 } else {
735 if (child == this)
[email protected]fa1cf0b82010-01-15 21:49:44736 UnregisterAccelerators(true);
initial.commit09911bf2008-07-26 23:55:29737 }
738 }
739
740 ViewHierarchyChanged(is_add, parent, child);
[email protected]9ea053e2010-07-15 08:19:05741 parent->needs_layout_ = true;
initial.commit09911bf2008-07-26 23:55:29742}
743
744void View::PropagateVisibilityNotifications(View* start, bool is_visible) {
[email protected]09fe9492009-11-07 02:23:06745 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29746 GetChildViewAt(i)->PropagateVisibilityNotifications(start, is_visible);
initial.commit09911bf2008-07-26 23:55:29747 VisibilityChanged(start, is_visible);
748}
749
750void View::VisibilityChanged(View* starting_from, bool is_visible) {
751}
752
[email protected]bda9556c2010-01-07 00:55:16753void View::PropagateNativeViewHierarchyChanged(bool attached,
754 gfx::NativeView native_view,
755 RootView* root_view) {
756 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
757 GetChildViewAt(i)->PropagateNativeViewHierarchyChanged(attached,
758 native_view,
759 root_view);
760 NativeViewHierarchyChanged(attached, native_view, root_view);
761}
762
763void View::NativeViewHierarchyChanged(bool attached,
764 gfx::NativeView native_view,
765 RootView* root_view) {
766 FocusManager* focus_manager = GetFocusManager();
767 if (!accelerator_registration_delayed_ &&
768 accelerator_focus_manager_ &&
769 accelerator_focus_manager_ != focus_manager) {
770 UnregisterAccelerators(true);
771 accelerator_registration_delayed_ = true;
772 }
773 if (accelerator_registration_delayed_ && attached) {
774 if (focus_manager) {
775 RegisterPendingAccelerators();
776 accelerator_registration_delayed_ = false;
777 }
778 }
779}
780
initial.commit09911bf2008-07-26 23:55:29781void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) {
782 if (notify_when_visible_bounds_in_root_changes_ == value)
783 return;
784 notify_when_visible_bounds_in_root_changes_ = value;
785 RootView* root = GetRootView();
786 if (root) {
787 if (value)
788 root->RegisterViewForVisibleBoundsNotification(this);
789 else
790 root->UnregisterViewForVisibleBoundsNotification(this);
791 }
792}
793
794bool View::GetNotifyWhenVisibleBoundsInRootChanges() {
795 return notify_when_visible_bounds_in_root_changes_;
796}
797
[email protected]0d52b2302009-05-11 23:50:55798View* View::GetViewForPoint(const gfx::Point& point) {
initial.commit09911bf2008-07-26 23:55:29799 // Walk the child Views recursively looking for the View that most
800 // tightly encloses the specified point.
[email protected]09fe9492009-11-07 02:23:06801 for (int i = GetChildViewCount() - 1; i >= 0; --i) {
initial.commit09911bf2008-07-26 23:55:29802 View* child = GetChildViewAt(i);
[email protected]82739cf2008-09-16 00:37:56803 if (!child->IsVisible())
initial.commit09911bf2008-07-26 23:55:29804 continue;
[email protected]82739cf2008-09-16 00:37:56805
[email protected]96b667d2008-10-14 20:58:44806 gfx::Point point_in_child_coords(point);
[email protected]82739cf2008-09-16 00:37:56807 View::ConvertPointToView(this, child, &point_in_child_coords);
[email protected]613b8062008-10-14 23:45:09808 if (child->HitTest(point_in_child_coords))
[email protected]0d52b2302009-05-11 23:50:55809 return child->GetViewForPoint(point_in_child_coords);
initial.commit09911bf2008-07-26 23:55:29810 }
811 return this;
812}
813
[email protected]a0dde122008-11-21 20:51:20814Widget* View::GetWidget() const {
815 // The root view holds a reference to this view hierarchy's Widget.
816 return parent_ ? parent_->GetWidget() : NULL;
initial.commit09911bf2008-07-26 23:55:29817}
818
[email protected]cd8c47902009-04-30 20:55:35819Window* View::GetWindow() const {
820 Widget* widget = GetWidget();
821 return widget ? widget->GetWindow() : NULL;
822}
823
[email protected]2db27be2010-02-10 22:46:47824bool View::ContainsNativeView(gfx::NativeView native_view) const {
825 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
826 if (GetChildViewAt(i)->ContainsNativeView(native_view))
827 return true;
828 }
829 return false;
830}
831
initial.commit09911bf2008-07-26 23:55:29832// Get the containing RootView
833RootView* View::GetRootView() {
[email protected]a0dde122008-11-21 20:51:20834 Widget* widget = GetWidget();
835 return widget ? widget->GetRootView() : NULL;
initial.commit09911bf2008-07-26 23:55:29836}
837
838View* View::GetViewByID(int id) const {
839 if (id == id_)
840 return const_cast<View*>(this);
841
[email protected]09fe9492009-11-07 02:23:06842 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29843 View* child = GetChildViewAt(i);
844 View* view = child->GetViewByID(id);
845 if (view)
846 return view;
847 }
848 return NULL;
849}
850
851void View::GetViewsWithGroup(int group_id, std::vector<View*>* out) {
852 if (group_ == group_id)
853 out->push_back(this);
854
[email protected]09fe9492009-11-07 02:23:06855 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29856 GetChildViewAt(i)->GetViewsWithGroup(group_id, out);
857}
858
859View* View::GetSelectedViewForGroup(int group_id) {
860 std::vector<View*> views;
861 GetRootView()->GetViewsWithGroup(group_id, &views);
862 if (views.size() > 0)
863 return views[0];
864 else
865 return NULL;
866}
867
868void View::SetID(int id) {
869 id_ = id;
870}
871
872int View::GetID() const {
873 return id_;
874}
875
876void View::SetGroup(int gid) {
[email protected]96f960d2009-09-14 18:45:30877 // Don't change the group id once it's set.
878 DCHECK(group_ == -1 || group_ == gid);
initial.commit09911bf2008-07-26 23:55:29879 group_ = gid;
880}
881
882int View::GetGroup() const {
883 return group_;
884}
885
886void View::SetParent(View* parent) {
[email protected]09fe9492009-11-07 02:23:06887 if (parent != parent_)
initial.commit09911bf2008-07-26 23:55:29888 parent_ = parent;
initial.commit09911bf2008-07-26 23:55:29889}
890
891bool View::IsParentOf(View* v) const {
892 DCHECK(v);
893 View* parent = v->GetParent();
894 while (parent) {
895 if (this == parent)
896 return true;
897 parent = parent->GetParent();
898 }
899 return false;
900}
901
[email protected]5e26d9d42010-05-13 22:11:03902int View::GetChildIndex(const View* v) const {
[email protected]09fe9492009-11-07 02:23:06903 for (int i = 0, count = GetChildViewCount(); i < count; i++) {
initial.commit09911bf2008-07-26 23:55:29904 if (v == GetChildViewAt(i))
905 return i;
906 }
907 return -1;
908}
909
910///////////////////////////////////////////////////////////////////////////////
911//
912// View - focus
913//
914///////////////////////////////////////////////////////////////////////////////
915
916View* View::GetNextFocusableView() {
917 return next_focusable_view_;
918}
919
920View* View::GetPreviousFocusableView() {
921 return previous_focusable_view_;
922}
923
924void View::SetNextFocusableView(View* view) {
925 view->previous_focusable_view_ = this;
926 next_focusable_view_ = view;
927}
928
929void View::InitFocusSiblings(View* v, int index) {
930 int child_count = static_cast<int>(child_views_.size());
931
932 if (child_count == 0) {
933 v->next_focusable_view_ = NULL;
934 v->previous_focusable_view_ = NULL;
935 } else {
936 if (index == child_count) {
937 // We are inserting at the end, but the end of the child list may not be
938 // the last focusable element. Let's try to find an element with no next
939 // focusable element to link to.
940 View* last_focusable_view = NULL;
941 for (std::vector<View*>::iterator iter = child_views_.begin();
942 iter != child_views_.end(); ++iter) {
943 if (!(*iter)->next_focusable_view_) {
944 last_focusable_view = *iter;
945 break;
946 }
947 }
948 if (last_focusable_view == NULL) {
949 // Hum... there is a cycle in the focus list. Let's just insert ourself
950 // after the last child.
951 View* prev = child_views_[index - 1];
952 v->previous_focusable_view_ = prev;
953 v->next_focusable_view_ = prev->next_focusable_view_;
954 prev->next_focusable_view_->previous_focusable_view_ = v;
955 prev->next_focusable_view_ = v;
956 } else {
957 last_focusable_view->next_focusable_view_ = v;
958 v->next_focusable_view_ = NULL;
959 v->previous_focusable_view_ = last_focusable_view;
960 }
961 } else {
962 View* prev = child_views_[index]->GetPreviousFocusableView();
963 v->previous_focusable_view_ = prev;
964 v->next_focusable_view_ = child_views_[index];
965 if (prev)
966 prev->next_focusable_view_ = v;
967 child_views_[index]->previous_focusable_view_ = v;
968 }
969 }
970}
971
972#ifndef NDEBUG
973void View::PrintViewHierarchy() {
974 PrintViewHierarchyImp(0);
975}
976
977void View::PrintViewHierarchyImp(int indent) {
978 std::wostringstream buf;
979 int ind = indent;
980 while (ind-- > 0)
981 buf << L' ';
982 buf << UTF8ToWide(GetClassName());
983 buf << L' ';
984 buf << GetID();
985 buf << L' ';
[email protected]80f8b9f2008-10-16 18:17:47986 buf << bounds_.x() << L"," << bounds_.y() << L",";
987 buf << bounds_.right() << L"," << bounds_.bottom();
initial.commit09911bf2008-07-26 23:55:29988 buf << L' ';
989 buf << this;
990
991 LOG(INFO) << buf.str();
992 std::cout << buf.str() << std::endl;
993
[email protected]09fe9492009-11-07 02:23:06994 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29995 GetChildViewAt(i)->PrintViewHierarchyImp(indent + 2);
initial.commit09911bf2008-07-26 23:55:29996}
997
998
999void View::PrintFocusHierarchy() {
1000 PrintFocusHierarchyImp(0);
1001}
1002
1003void View::PrintFocusHierarchyImp(int indent) {
1004 std::wostringstream buf;
1005 int ind = indent;
1006 while (ind-- > 0)
1007 buf << L' ';
1008 buf << UTF8ToWide(GetClassName());
1009 buf << L' ';
1010 buf << GetID();
1011 buf << L' ';
1012 buf << GetClassName().c_str();
1013 buf << L' ';
1014 buf << this;
1015
1016 LOG(INFO) << buf.str();
1017 std::cout << buf.str() << std::endl;
1018
1019 if (GetChildViewCount() > 0)
1020 GetChildViewAt(0)->PrintFocusHierarchyImp(indent + 2);
1021
1022 View* v = GetNextFocusableView();
1023 if (v)
1024 v->PrintFocusHierarchyImp(indent);
1025}
1026#endif
1027
1028////////////////////////////////////////////////////////////////////////////////
1029//
1030// View - accelerators
1031//
1032////////////////////////////////////////////////////////////////////////////////
1033
1034void View::AddAccelerator(const Accelerator& accelerator) {
1035 if (!accelerators_.get())
1036 accelerators_.reset(new std::vector<Accelerator>());
[email protected]71421c3f2009-06-06 00:41:441037
1038 std::vector<Accelerator>::iterator iter =
1039 std::find(accelerators_->begin(), accelerators_->end(), accelerator);
1040 DCHECK(iter == accelerators_->end())
1041 << "Registering the same accelerator multiple times";
1042
initial.commit09911bf2008-07-26 23:55:291043 accelerators_->push_back(accelerator);
[email protected]71421c3f2009-06-06 00:41:441044 RegisterPendingAccelerators();
initial.commit09911bf2008-07-26 23:55:291045}
1046
[email protected]e8e0f362008-11-08 01:13:251047void View::RemoveAccelerator(const Accelerator& accelerator) {
1048 std::vector<Accelerator>::iterator iter;
1049 if (!accelerators_.get() ||
1050 ((iter = std::find(accelerators_->begin(), accelerators_->end(),
1051 accelerator)) == accelerators_->end())) {
1052 NOTREACHED() << "Removing non-existing accelerator";
1053 return;
1054 }
1055
[email protected]4bd23f32009-06-08 20:59:191056 size_t index = iter - accelerators_->begin();
[email protected]e8e0f362008-11-08 01:13:251057 accelerators_->erase(iter);
[email protected]71421c3f2009-06-06 00:41:441058 if (index >= registered_accelerator_count_) {
1059 // The accelerator is not registered to FocusManager.
1060 return;
1061 }
1062 --registered_accelerator_count_;
1063
[email protected]e8e0f362008-11-08 01:13:251064 RootView* root_view = GetRootView();
1065 if (!root_view) {
1066 // We are not part of a view hierarchy, so there is nothing to do as we
1067 // removed ourselves from accelerators_, we won't be registered when added
1068 // to one.
1069 return;
1070 }
1071
[email protected]bda9556c2010-01-07 00:55:161072 // If accelerator_focus_manager_ is NULL then we did not registered
1073 // accelerators so there is nothing to unregister.
1074 if (accelerator_focus_manager_) {
1075 accelerator_focus_manager_->UnregisterAccelerator(accelerator, this);
[email protected]e8e0f362008-11-08 01:13:251076 }
1077}
1078
initial.commit09911bf2008-07-26 23:55:291079void View::ResetAccelerators() {
[email protected]71421c3f2009-06-06 00:41:441080 if (accelerators_.get())
[email protected]bda9556c2010-01-07 00:55:161081 UnregisterAccelerators(false);
initial.commit09911bf2008-07-26 23:55:291082}
1083
[email protected]71421c3f2009-06-06 00:41:441084void View::RegisterPendingAccelerators() {
1085 if (!accelerators_.get() ||
1086 registered_accelerator_count_ == accelerators_->size()) {
1087 // No accelerators are waiting for registration.
initial.commit09911bf2008-07-26 23:55:291088 return;
[email protected]71421c3f2009-06-06 00:41:441089 }
initial.commit09911bf2008-07-26 23:55:291090
1091 RootView* root_view = GetRootView();
1092 if (!root_view) {
1093 // We are not yet part of a view hierarchy, we'll register ourselves once
1094 // added to one.
1095 return;
1096 }
[email protected]f3735c5d2009-03-19 17:26:231097
[email protected]bda9556c2010-01-07 00:55:161098 accelerator_focus_manager_ = GetFocusManager();
1099 if (!accelerator_focus_manager_) {
initial.commit09911bf2008-07-26 23:55:291100 // Some crash reports seem to show that we may get cases where we have no
1101 // focus manager (see bug #1291225). This should never be the case, just
1102 // making sure we don't crash.
[email protected]f8dce002009-09-10 21:07:041103
1104 // TODO(jcampan): This fails for a view under WidgetGtk with TYPE_CHILD.
1105 // (see http://crbug.com/21335) reenable NOTREACHED assertion and
1106 // verify accelerators works as expected.
1107#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291108 NOTREACHED();
[email protected]f8dce002009-09-10 21:07:041109#endif
initial.commit09911bf2008-07-26 23:55:291110 return;
1111 }
[email protected]71421c3f2009-06-06 00:41:441112 std::vector<Accelerator>::const_iterator iter;
1113 for (iter = accelerators_->begin() + registered_accelerator_count_;
initial.commit09911bf2008-07-26 23:55:291114 iter != accelerators_->end(); ++iter) {
[email protected]bda9556c2010-01-07 00:55:161115 accelerator_focus_manager_->RegisterAccelerator(*iter, this);
initial.commit09911bf2008-07-26 23:55:291116 }
[email protected]71421c3f2009-06-06 00:41:441117 registered_accelerator_count_ = accelerators_->size();
initial.commit09911bf2008-07-26 23:55:291118}
1119
[email protected]bda9556c2010-01-07 00:55:161120void View::UnregisterAccelerators(bool leave_data_intact) {
initial.commit09911bf2008-07-26 23:55:291121 if (!accelerators_.get())
1122 return;
1123
1124 RootView* root_view = GetRootView();
1125 if (root_view) {
[email protected]bda9556c2010-01-07 00:55:161126 if (accelerator_focus_manager_) {
initial.commit09911bf2008-07-26 23:55:291127 // We may not have a FocusManager if the window containing us is being
1128 // closed, in which case the FocusManager is being deleted so there is
1129 // nothing to unregister.
[email protected]bda9556c2010-01-07 00:55:161130 accelerator_focus_manager_->UnregisterAccelerators(this);
1131 accelerator_focus_manager_ = NULL;
initial.commit09911bf2008-07-26 23:55:291132 }
[email protected]bda9556c2010-01-07 00:55:161133 if (!leave_data_intact) {
1134 accelerators_->clear();
1135 accelerators_.reset();
1136 }
[email protected]71421c3f2009-06-06 00:41:441137 registered_accelerator_count_ = 0;
initial.commit09911bf2008-07-26 23:55:291138 }
1139}
1140
[email protected]e9adf0702010-03-08 23:34:071141int View::GetDragOperations(const gfx::Point& press_pt) {
1142 return drag_controller_ ?
1143 drag_controller_->GetDragOperations(this, press_pt) :
1144 DragDropTypes::DRAG_NONE;
initial.commit09911bf2008-07-26 23:55:291145}
1146
[email protected]e9adf0702010-03-08 23:34:071147void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) {
initial.commit09911bf2008-07-26 23:55:291148 DCHECK(drag_controller_);
[email protected]e9adf0702010-03-08 23:34:071149 drag_controller_->WriteDragData(this, press_pt, data);
initial.commit09911bf2008-07-26 23:55:291150}
1151
1152void View::OnDragDone() {
1153}
1154
1155bool View::InDrag() {
1156 RootView* root_view = GetRootView();
1157 return root_view ? (root_view->GetDragView() == this) : false;
1158}
1159
[email protected]d5c81012010-04-03 00:56:121160bool View::GetAccessibleName(std::wstring* name) {
1161 DCHECK(name);
1162
1163 if (accessible_name_.empty())
1164 return false;
1165 *name = accessible_name_;
1166 return true;
1167}
1168
[email protected]4c671e12010-09-28 19:30:231169AccessibilityTypes::Role View::GetAccessibleRole() {
1170 return AccessibilityTypes::ROLE_CLIENT;
[email protected]b82a0492010-05-27 23:00:031171}
1172
[email protected]d5c81012010-04-03 00:56:121173void View::SetAccessibleName(const std::wstring& name) {
1174 accessible_name_ = name;
1175}
1176
initial.commit09911bf2008-07-26 23:55:291177// static
[email protected]bb515ed2009-01-15 00:53:431178void View::ConvertPointToView(const View* src,
1179 const View* dst,
1180 gfx::Point* point) {
initial.commit09911bf2008-07-26 23:55:291181 ConvertPointToView(src, dst, point, true);
1182}
1183
1184// static
[email protected]bb515ed2009-01-15 00:53:431185void View::ConvertPointToView(const View* src,
1186 const View* dst,
1187 gfx::Point* point,
initial.commit09911bf2008-07-26 23:55:291188 bool try_other_direction) {
1189 // src can be NULL
1190 DCHECK(dst);
1191 DCHECK(point);
1192
[email protected]bb515ed2009-01-15 00:53:431193 const View* v;
initial.commit09911bf2008-07-26 23:55:291194 gfx::Point offset;
1195
1196 for (v = dst; v && v != src; v = v->GetParent()) {
1197 offset.SetPoint(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION),
[email protected]6f3bb6c2008-09-17 22:25:331198 offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291199 }
1200
1201 // The source was not found. The caller wants a conversion
1202 // from a view to a transitive parent.
1203 if (src && v == NULL && try_other_direction) {
1204 gfx::Point p;
1205 // note: try_other_direction is force to FALSE so we don't
1206 // end up in an infinite recursion should both src and dst
1207 // are not parented.
1208 ConvertPointToView(dst, src, &p, false);
1209 // since the src and dst are inverted, p should also be negated
1210 point->SetPoint(point->x() - p.x(), point->y() - p.y());
1211 } else {
1212 point->SetPoint(point->x() - offset.x(), point->y() - offset.y());
1213
1214 // If src is NULL, sp is in the screen coordinate system
1215 if (src == NULL) {
[email protected]a0dde122008-11-21 20:51:201216 Widget* widget = dst->GetWidget();
1217 if (widget) {
[email protected]3b680a82008-12-17 02:03:231218 gfx::Rect b;
[email protected]a0dde122008-11-21 20:51:201219 widget->GetBounds(&b, false);
[email protected]3b680a82008-12-17 02:03:231220 point->SetPoint(point->x() - b.x(), point->y() - b.y());
initial.commit09911bf2008-07-26 23:55:291221 }
1222 }
1223 }
1224}
1225
1226// static
[email protected]2fb6d462009-02-13 18:40:101227void View::ConvertPointToWidget(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291228 DCHECK(src);
1229 DCHECK(p);
[email protected]96b667d2008-10-14 20:58:441230
[email protected]96b667d2008-10-14 20:58:441231 gfx::Point offset;
[email protected]2fb6d462009-02-13 18:40:101232 for (const View* v = src; v; v = v->GetParent()) {
[email protected]96b667d2008-10-14 20:58:441233 offset.set_x(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION));
1234 offset.set_y(offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291235 }
[email protected]96b667d2008-10-14 20:58:441236 p->SetPoint(p->x() + offset.x(), p->y() + offset.y());
initial.commit09911bf2008-07-26 23:55:291237}
1238
1239// static
[email protected]2fb6d462009-02-13 18:40:101240void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) {
[email protected]96b667d2008-10-14 20:58:441241 gfx::Point t;
[email protected]2fb6d462009-02-13 18:40:101242 ConvertPointToWidget(dest, &t);
[email protected]96b667d2008-10-14 20:58:441243 p->SetPoint(p->x() - t.x(), p->y() - t.y());
initial.commit09911bf2008-07-26 23:55:291244}
1245
1246// static
[email protected]2fb6d462009-02-13 18:40:101247void View::ConvertPointToScreen(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291248 DCHECK(src);
1249 DCHECK(p);
1250
[email protected]96b667d2008-10-14 20:58:441251 // If the view is not connected to a tree, there's nothing we can do.
[email protected]a0dde122008-11-21 20:51:201252 Widget* widget = src->GetWidget();
1253 if (widget) {
1254 ConvertPointToWidget(src, p);
[email protected]3b680a82008-12-17 02:03:231255 gfx::Rect r;
[email protected]a0dde122008-11-21 20:51:201256 widget->GetBounds(&r, false);
[email protected]3b680a82008-12-17 02:03:231257 p->SetPoint(p->x() + r.x(), p->y() + r.y());
initial.commit09911bf2008-07-26 23:55:291258 }
1259}
1260
[email protected]a0949a42010-08-23 16:03:051261gfx::Rect View::GetScreenBounds() const {
1262 gfx::Point origin;
1263 View::ConvertPointToScreen(this, &origin);
1264 return gfx::Rect(origin, size());
1265}
1266
initial.commit09911bf2008-07-26 23:55:291267/////////////////////////////////////////////////////////////////////////////
1268//
1269// View - event handlers
1270//
1271/////////////////////////////////////////////////////////////////////////////
1272
1273bool View::OnMousePressed(const MouseEvent& e) {
1274 return false;
1275}
1276
1277bool View::OnMouseDragged(const MouseEvent& e) {
1278 return false;
1279}
1280
1281void View::OnMouseReleased(const MouseEvent& e, bool canceled) {
1282}
1283
1284void View::OnMouseMoved(const MouseEvent& e) {
1285}
1286
1287void View::OnMouseEntered(const MouseEvent& e) {
1288}
1289
1290void View::OnMouseExited(const MouseEvent& e) {
1291}
1292
[email protected]ad84c8f2010-09-08 14:06:101293#if defined(TOUCH_UI)
1294bool View::OnTouchEvent(const TouchEvent& event) {
1295 DLOG(INFO) << "visited the OnTouchEvent";
1296 return false;
1297}
1298#endif
1299
initial.commit09911bf2008-07-26 23:55:291300void View::SetMouseHandler(View *new_mouse_handler) {
1301 // It is valid for new_mouse_handler to be NULL
[email protected]09fe9492009-11-07 02:23:061302 if (parent_)
initial.commit09911bf2008-07-26 23:55:291303 parent_->SetMouseHandler(new_mouse_handler);
initial.commit09911bf2008-07-26 23:55:291304}
1305
1306void View::SetVisible(bool flag) {
1307 if (flag != is_visible_) {
1308 // If the tab is currently visible, schedule paint to
1309 // refresh parent
[email protected]09fe9492009-11-07 02:23:061310 if (IsVisible())
initial.commit09911bf2008-07-26 23:55:291311 SchedulePaint();
initial.commit09911bf2008-07-26 23:55:291312
1313 is_visible_ = flag;
1314
1315 // This notifies all subviews recursively.
1316 PropagateVisibilityNotifications(this, flag);
1317
1318 // If we are newly visible, schedule paint.
[email protected]09fe9492009-11-07 02:23:061319 if (IsVisible())
initial.commit09911bf2008-07-26 23:55:291320 SchedulePaint();
initial.commit09911bf2008-07-26 23:55:291321 }
1322}
1323
1324bool View::IsVisibleInRootView() const {
1325 View* parent = GetParent();
1326 if (IsVisible() && parent)
1327 return parent->IsVisibleInRootView();
1328 else
1329 return false;
1330}
1331
initial.commit09911bf2008-07-26 23:55:291332/////////////////////////////////////////////////////////////////////////////
1333//
1334// View - keyboard and focus
1335//
1336/////////////////////////////////////////////////////////////////////////////
1337
1338void View::RequestFocus() {
1339 RootView* rv = GetRootView();
[email protected]59461d22010-07-21 15:41:091340 if (rv && IsFocusableInRootView())
initial.commit09911bf2008-07-26 23:55:291341 rv->FocusView(this);
initial.commit09911bf2008-07-26 23:55:291342}
1343
1344void View::WillGainFocus() {
1345}
1346
1347void View::DidGainFocus() {
1348}
1349
1350void View::WillLoseFocus() {
1351}
1352
1353bool View::OnKeyPressed(const KeyEvent& e) {
1354 return false;
1355}
1356
1357bool View::OnKeyReleased(const KeyEvent& e) {
1358 return false;
1359}
1360
1361bool View::OnMouseWheel(const MouseWheelEvent& e) {
1362 return false;
1363}
1364
1365void View::SetDragController(DragController* drag_controller) {
[email protected]09fe9492009-11-07 02:23:061366 drag_controller_ = drag_controller;
initial.commit09911bf2008-07-26 23:55:291367}
1368
1369DragController* View::GetDragController() {
1370 return drag_controller_;
1371}
1372
[email protected]134c47b92009-08-19 03:33:441373bool View::GetDropFormats(
1374 int* formats,
1375 std::set<OSExchangeData::CustomFormat>* custom_formats) {
1376 return false;
1377}
1378
1379bool View::AreDropTypesRequired() {
1380 return false;
1381}
1382
initial.commit09911bf2008-07-26 23:55:291383bool View::CanDrop(const OSExchangeData& data) {
[email protected]134c47b92009-08-19 03:33:441384 // TODO(sky): when I finish up migration, this should default to true.
initial.commit09911bf2008-07-26 23:55:291385 return false;
1386}
1387
1388void View::OnDragEntered(const DropTargetEvent& event) {
1389}
1390
1391int View::OnDragUpdated(const DropTargetEvent& event) {
1392 return DragDropTypes::DRAG_NONE;
1393}
1394
1395void View::OnDragExited() {
1396}
1397
1398int View::OnPerformDrop(const DropTargetEvent& event) {
1399 return DragDropTypes::DRAG_NONE;
1400}
1401
initial.commit09911bf2008-07-26 23:55:291402// static
1403bool View::ExceededDragThreshold(int delta_x, int delta_y) {
1404 return (abs(delta_x) > GetHorizontalDragThreshold() ||
1405 abs(delta_y) > GetVerticalDragThreshold());
1406}
1407
initial.commit09911bf2008-07-26 23:55:291408// Tooltips -----------------------------------------------------------------
[email protected]e9adf0702010-03-08 23:34:071409bool View::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
initial.commit09911bf2008-07-26 23:55:291410 return false;
1411}
1412
[email protected]e9adf0702010-03-08 23:34:071413bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) {
initial.commit09911bf2008-07-26 23:55:291414 return false;
1415}
1416
1417void View::TooltipTextChanged() {
[email protected]a0dde122008-11-21 20:51:201418 Widget* widget = GetWidget();
1419 if (widget && widget->GetTooltipManager())
1420 widget->GetTooltipManager()->TooltipTextChanged(this);
initial.commit09911bf2008-07-26 23:55:291421}
1422
1423void View::UpdateTooltip() {
[email protected]a0dde122008-11-21 20:51:201424 Widget* widget = GetWidget();
1425 if (widget && widget->GetTooltipManager())
1426 widget->GetTooltipManager()->UpdateTooltip();
initial.commit09911bf2008-07-26 23:55:291427}
1428
initial.commit09911bf2008-07-26 23:55:291429std::string View::GetClassName() const {
1430 return kViewClassName;
1431}
1432
[email protected]5c2b98b2009-03-09 20:55:541433View* View::GetAncestorWithClassName(const std::string& name) {
1434 for (View* view = this; view; view = view->GetParent()) {
1435 if (view->GetClassName() == name)
1436 return view;
1437 }
1438 return NULL;
1439}
1440
initial.commit09911bf2008-07-26 23:55:291441gfx::Rect View::GetVisibleBounds() {
[email protected]b6296fd2009-02-13 17:34:161442 if (!IsVisibleInRootView())
1443 return gfx::Rect();
[email protected]6f3bb6c2008-09-17 22:25:331444 gfx::Rect vis_bounds(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:291445 gfx::Rect ancestor_bounds;
1446 View* view = this;
1447 int root_x = 0;
1448 int root_y = 0;
initial.commit09911bf2008-07-26 23:55:291449 while (view != NULL && !vis_bounds.IsEmpty()) {
1450 root_x += view->GetX(APPLY_MIRRORING_TRANSFORMATION);
[email protected]6f3bb6c2008-09-17 22:25:331451 root_y += view->y();
1452 vis_bounds.Offset(view->GetX(APPLY_MIRRORING_TRANSFORMATION), view->y());
initial.commit09911bf2008-07-26 23:55:291453 View* ancestor = view->GetParent();
1454 if (ancestor != NULL) {
[email protected]6f3bb6c2008-09-17 22:25:331455 ancestor_bounds.SetRect(0, 0, ancestor->width(),
1456 ancestor->height());
initial.commit09911bf2008-07-26 23:55:291457 vis_bounds = vis_bounds.Intersect(ancestor_bounds);
[email protected]a0dde122008-11-21 20:51:201458 } else if (!view->GetWidget()) {
1459 // If the view has no Widget, we're not visible. Return an empty rect.
initial.commit09911bf2008-07-26 23:55:291460 return gfx::Rect();
1461 }
1462 view = ancestor;
1463 }
1464 if (vis_bounds.IsEmpty())
1465 return vis_bounds;
1466 // Convert back to this views coordinate system.
1467 vis_bounds.Offset(-root_x, -root_y);
1468 return vis_bounds;
1469}
1470
1471int View::GetPageScrollIncrement(ScrollView* scroll_view,
1472 bool is_horizontal, bool is_positive) {
1473 return 0;
1474}
1475
1476int View::GetLineScrollIncrement(ScrollView* scroll_view,
1477 bool is_horizontal, bool is_positive) {
1478 return 0;
1479}
1480
[email protected]45da6c72009-10-28 20:45:421481ThemeProvider* View::GetThemeProvider() const {
[email protected]4a190632009-05-09 01:07:421482 Widget* widget = GetWidget();
1483 return widget ? widget->GetThemeProvider() : NULL;
1484}
1485
initial.commit09911bf2008-07-26 23:55:291486// static
[email protected]9fc4f202010-07-07 15:38:191487void View::RegisterChildrenForVisibleBoundsNotification(
1488 RootView* root, View* view) {
initial.commit09911bf2008-07-26 23:55:291489 DCHECK(root && view);
1490 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1491 root->RegisterViewForVisibleBoundsNotification(view);
1492 for (int i = 0; i < view->GetChildViewCount(); ++i)
[email protected]9fc4f202010-07-07 15:38:191493 RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i));
initial.commit09911bf2008-07-26 23:55:291494}
1495
1496// static
[email protected]9fc4f202010-07-07 15:38:191497void View::UnregisterChildrenForVisibleBoundsNotification(
initial.commit09911bf2008-07-26 23:55:291498 RootView* root, View* view) {
1499 DCHECK(root && view);
1500 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1501 root->UnregisterViewForVisibleBoundsNotification(view);
1502 for (int i = 0; i < view->GetChildViewCount(); ++i)
[email protected]9fc4f202010-07-07 15:38:191503 UnregisterChildrenForVisibleBoundsNotification(root,
1504 view->GetChildViewAt(i));
initial.commit09911bf2008-07-26 23:55:291505}
1506
1507void View::AddDescendantToNotify(View* view) {
1508 DCHECK(view);
1509 if (!descendants_to_notify_.get())
1510 descendants_to_notify_.reset(new ViewList());
1511 descendants_to_notify_->push_back(view);
1512}
1513
1514void View::RemoveDescendantToNotify(View* view) {
1515 DCHECK(view && descendants_to_notify_.get());
1516 ViewList::iterator i = find(descendants_to_notify_->begin(),
1517 descendants_to_notify_->end(),
1518 view);
1519 DCHECK(i != descendants_to_notify_->end());
1520 descendants_to_notify_->erase(i);
1521 if (descendants_to_notify_->empty())
1522 descendants_to_notify_.reset();
1523}
1524
initial.commit09911bf2008-07-26 23:55:291525// DropInfo --------------------------------------------------------------------
1526
1527void View::DragInfo::Reset() {
1528 possible_drag = false;
[email protected]e9adf0702010-03-08 23:34:071529 start_pt = gfx::Point();
initial.commit09911bf2008-07-26 23:55:291530}
1531
[email protected]e9adf0702010-03-08 23:34:071532void View::DragInfo::PossibleDrag(const gfx::Point& p) {
initial.commit09911bf2008-07-26 23:55:291533 possible_drag = true;
[email protected]e9adf0702010-03-08 23:34:071534 start_pt = p;
initial.commit09911bf2008-07-26 23:55:291535}
1536
1537} // namespace