blob: b5e7173746b1f09da2edd4da84cc5ff3b20ceb06 [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"
[email protected]82522512009-05-15 07:37:2913#include "app/gfx/canvas.h"
[email protected]a92b8642009-05-05 23:38:5614#include "app/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2915#include "base/logging.h"
16#include "base/message_loop.h"
[email protected]82739cf2008-09-16 00:37:5617#include "base/scoped_handle.h"
[email protected]d55194ca2010-03-11 18:25:4518#include "base/utf_string_conversions.h"
[email protected]5c7293a2010-03-17 06:40:5719#include "gfx/path.h"
[email protected]d5282e72009-05-13 13:16:5220#include "third_party/skia/include/core/SkShader.h"
[email protected]2362e4f2009-05-08 00:34:0521#include "views/background.h"
22#include "views/layout_manager.h"
[email protected]3ee83f2c2009-05-10 05:58:4023#include "views/views_delegate.h"
[email protected]2362e4f2009-05-08 00:34:0524#include "views/widget/root_view.h"
[email protected]319d4ae2009-05-28 19:09:4525#include "views/widget/tooltip_manager.h"
[email protected]2362e4f2009-05-08 00:34:0526#include "views/widget/widget.h"
27#include "views/window/window.h"
[email protected]031e4d32009-12-29 01:13:2328
[email protected]6ff244f2009-01-20 20:38:0829#if defined(OS_WIN)
[email protected]2362e4f2009-05-08 00:34:0530#include "views/accessibility/view_accessibility_wrapper.h"
[email protected]6ff244f2009-01-20 20:38:0831#endif
[email protected]031e4d32009-12-29 01:13:2332#if defined(OS_LINUX)
33#include "app/scoped_handle_gtk.h"
34#endif
initial.commit09911bf2008-07-26 23:55:2935
[email protected]c2dacc92008-10-16 23:51:3836namespace views {
initial.commit09911bf2008-07-26 23:55:2937
38// static
[email protected]3ee83f2c2009-05-10 05:58:4039ViewsDelegate* ViewsDelegate::views_delegate = NULL;
40
41// static
[email protected]2362e4f2009-05-08 00:34:0542char View::kViewClassName[] = "views/View";
initial.commit09911bf2008-07-26 23:55:2943
[email protected]8af4c1992010-02-04 21:38:0744// static
45const int View::kShowFolderDropMenuDelay = 400;
46
initial.commit09911bf2008-07-26 23:55:2947/////////////////////////////////////////////////////////////////////////////
48//
49// View - constructors, destructors, initialization
50//
51/////////////////////////////////////////////////////////////////////////////
52
53View::View()
54 : id_(0),
55 group_(-1),
[email protected]6ff244f2009-01-20 20:38:0856 enabled_(true),
57 focusable_(false),
[email protected]4f3dc372009-02-24 00:10:2958 bounds_(0, 0, 0, 0),
initial.commit09911bf2008-07-26 23:55:2959 parent_(NULL),
initial.commit09911bf2008-07-26 23:55:2960 is_visible_(true),
initial.commit09911bf2008-07-26 23:55:2961 is_parent_owned_(true),
62 notify_when_visible_bounds_in_root_changes_(false),
63 registered_for_visible_bounds_notification_(false),
[email protected]bda9556c2010-01-07 00:55:1664 accelerator_registration_delayed_(false),
initial.commit09911bf2008-07-26 23:55:2965 next_focusable_view_(NULL),
66 previous_focusable_view_(NULL),
[email protected]bda9556c2010-01-07 00:55:1667 accelerator_focus_manager_(NULL),
[email protected]71421c3f2009-06-06 00:41:4468 registered_accelerator_count_(0),
initial.commit09911bf2008-07-26 23:55:2969 context_menu_controller_(NULL),
[email protected]6ff244f2009-01-20 20:38:0870#if defined(OS_WIN)
71 accessibility_(NULL),
72#endif
initial.commit09911bf2008-07-26 23:55:2973 drag_controller_(NULL),
74 ui_mirroring_is_enabled_for_rtl_languages_(true),
75 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() {
169 if (parent_)
170 parent_->ChildPreferredSizeChanged(this);
171}
172
[email protected]154f8bc2008-10-15 18:02:30173gfx::Size View::GetMinimumSize() {
174 return GetPreferredSize();
initial.commit09911bf2008-07-26 23:55:29175}
176
177int View::GetHeightForWidth(int w) {
178 if (layout_manager_.get())
179 return layout_manager_->GetPreferredHeightForWidth(this, w);
[email protected]154f8bc2008-10-15 18:02:30180 return GetPreferredSize().height();
initial.commit09911bf2008-07-26 23:55:29181}
182
[email protected]80f8b9f2008-10-16 18:17:47183void View::DidChangeBounds(const gfx::Rect& previous,
184 const gfx::Rect& current) {
185 Layout();
initial.commit09911bf2008-07-26 23:55:29186}
187
[email protected]e9adf0702010-03-08 23:34:07188void View::ScrollRectToVisible(const gfx::Rect& rect) {
initial.commit09911bf2008-07-26 23:55:29189 View* parent = GetParent();
190
191 // We must take RTL UI mirroring into account when adjusting the position of
192 // the region.
[email protected]e9adf0702010-03-08 23:34:07193 if (parent) {
194 gfx::Rect scroll_rect(rect);
195 scroll_rect.Offset(GetX(APPLY_MIRRORING_TRANSFORMATION), y());
196 parent->ScrollRectToVisible(scroll_rect);
197 }
initial.commit09911bf2008-07-26 23:55:29198}
199
200/////////////////////////////////////////////////////////////////////////////
201//
202// View - layout
203//
204/////////////////////////////////////////////////////////////////////////////
205
206void View::Layout() {
207 // Layout child Views
208 if (layout_manager_.get()) {
209 layout_manager_->Layout(this);
210 SchedulePaint();
[email protected]d5c4f382009-02-24 21:47:36211 // TODO(beng): We believe the right thing to do here is return since the
212 // layout manager should be handling things, but it causes
213 // regressions (missing options from Options dialog and a hang
214 // in interactive_ui_tests).
initial.commit09911bf2008-07-26 23:55:29215 }
216
217 // Lay out contents of child Views
[email protected]09fe9492009-11-07 02:23:06218 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29219 View* child = GetChildViewAt(i);
220 child->Layout();
221 }
222}
223
224LayoutManager* View::GetLayoutManager() const {
225 return layout_manager_.get();
226}
227
228void View::SetLayoutManager(LayoutManager* layout_manager) {
[email protected]09fe9492009-11-07 02:23:06229 if (layout_manager_.get())
initial.commit09911bf2008-07-26 23:55:29230 layout_manager_->Uninstalled(this);
[email protected]09fe9492009-11-07 02:23:06231
initial.commit09911bf2008-07-26 23:55:29232 layout_manager_.reset(layout_manager);
[email protected]09fe9492009-11-07 02:23:06233 if (layout_manager_.get())
initial.commit09911bf2008-07-26 23:55:29234 layout_manager_->Installed(this);
initial.commit09911bf2008-07-26 23:55:29235}
236
[email protected]1eb89e82008-08-15 12:27:03237bool View::UILayoutIsRightToLeft() const {
238 return (ui_mirroring_is_enabled_for_rtl_languages_ &&
239 l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT);
240}
241
initial.commit09911bf2008-07-26 23:55:29242////////////////////////////////////////////////////////////////////////////////
243//
244// View - Right-to-left UI layout
245//
246////////////////////////////////////////////////////////////////////////////////
247
[email protected]c3bca422010-02-19 23:29:02248int View::MirroredX() const {
initial.commit09911bf2008-07-26 23:55:29249 View* parent = GetParent();
[email protected]aaa71da52010-02-19 21:39:24250 return parent ? parent->MirroredLeftPointForRect(bounds_) : x();
initial.commit09911bf2008-07-26 23:55:29251}
252
253int View::MirroredLeftPointForRect(const gfx::Rect& bounds) const {
[email protected]aaa71da52010-02-19 21:39:24254 return UILayoutIsRightToLeft() ?
255 (width() - bounds.x() - bounds.width()) : bounds.x();
initial.commit09911bf2008-07-26 23:55:29256}
257
258////////////////////////////////////////////////////////////////////////////////
259//
260// View - states
261//
262////////////////////////////////////////////////////////////////////////////////
263
264bool View::IsEnabled() const {
265 return enabled_;
266}
267
268void View::SetEnabled(bool state) {
269 if (enabled_ != state) {
270 enabled_ = state;
271 SchedulePaint();
272 }
273}
274
275bool View::IsFocusable() const {
276 return focusable_ && enabled_ && is_visible_;
277}
278
279void View::SetFocusable(bool focusable) {
280 focusable_ = focusable;
281}
282
[email protected]82166b62009-06-30 18:48:00283FocusManager* View::GetFocusManager() {
284 Widget* widget = GetWidget();
285 return widget ? widget->GetFocusManager() : NULL;
286}
287
initial.commit09911bf2008-07-26 23:55:29288bool View::HasFocus() {
initial.commit09911bf2008-07-26 23:55:29289 FocusManager* focus_manager = GetFocusManager();
290 if (focus_manager)
291 return focus_manager->GetFocusedView() == this;
292 return false;
293}
294
[email protected]5c9e97a2009-09-09 23:48:30295void View::Focus() {
[email protected]7f14e1f2009-10-01 15:57:26296 // By default, we clear the native focus. This ensures that no visible native
297 // view as the focus and that we still receive keyboard inputs.
[email protected]5c9e97a2009-09-09 23:48:30298 FocusManager* focus_manager = GetFocusManager();
299 if (focus_manager)
[email protected]7f14e1f2009-10-01 15:57:26300 focus_manager->ClearNativeFocus();
[email protected]5c9e97a2009-09-09 23:48:30301}
302
initial.commit09911bf2008-07-26 23:55:29303void View::SetHotTracked(bool flag) {
304}
305
306/////////////////////////////////////////////////////////////////////////////
307//
308// View - painting
309//
310/////////////////////////////////////////////////////////////////////////////
311
[email protected]0a1d36b22008-10-17 19:33:09312void View::SchedulePaint(const gfx::Rect& r, bool urgent) {
313 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29314 return;
initial.commit09911bf2008-07-26 23:55:29315
316 if (parent_) {
317 // Translate the requested paint rect to the parent's coordinate system
318 // then pass this notification up to the parent.
[email protected]0a1d36b22008-10-17 19:33:09319 gfx::Rect paint_rect = r;
320 paint_rect.Offset(GetPosition());
initial.commit09911bf2008-07-26 23:55:29321 parent_->SchedulePaint(paint_rect, urgent);
322 }
323}
324
325void View::SchedulePaint() {
[email protected]0a1d36b22008-10-17 19:33:09326 SchedulePaint(GetLocalBounds(true), false);
initial.commit09911bf2008-07-26 23:55:29327}
328
[email protected]82522512009-05-15 07:37:29329void View::Paint(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29330 PaintBackground(canvas);
331 PaintFocusBorder(canvas);
332 PaintBorder(canvas);
333}
334
[email protected]82522512009-05-15 07:37:29335void View::PaintBackground(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02336 if (background_.get())
initial.commit09911bf2008-07-26 23:55:29337 background_->Paint(canvas, this);
338}
339
[email protected]82522512009-05-15 07:37:29340void View::PaintBorder(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02341 if (border_.get())
initial.commit09911bf2008-07-26 23:55:29342 border_->Paint(*this, canvas);
343}
344
[email protected]82522512009-05-15 07:37:29345void View::PaintFocusBorder(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29346 if (HasFocus() && IsFocusable())
[email protected]6f3bb6c2008-09-17 22:25:33347 canvas->DrawFocusRect(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:29348}
349
[email protected]82522512009-05-15 07:37:29350void View::PaintChildren(gfx::Canvas* canvas) {
[email protected]09fe9492009-11-07 02:23:06351 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29352 View* child = GetChildViewAt(i);
353 if (!child) {
354 NOTREACHED() << "Should not have a NULL child View for index in bounds";
355 continue;
356 }
357 child->ProcessPaint(canvas);
358 }
359}
360
[email protected]82522512009-05-15 07:37:29361void View::ProcessPaint(gfx::Canvas* canvas) {
[email protected]09fe9492009-11-07 02:23:06362 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29363 return;
initial.commit09911bf2008-07-26 23:55:29364
365 // We're going to modify the canvas, save it's state first.
366 canvas->save();
367
368 // Paint this View and its children, setting the clip rect to the bounds
369 // of this View and translating the origin to the local bounds' top left
370 // point.
371 //
372 // Note that the X (or left) position we pass to ClipRectInt takes into
373 // consideration whether or not the view uses a right-to-left layout so that
374 // we paint our view in its mirrored position if need be.
[email protected]80f8b9f2008-10-16 18:17:47375 if (canvas->ClipRectInt(MirroredX(), y(), width(), height())) {
initial.commit09911bf2008-07-26 23:55:29376 // Non-empty clip, translate the graphics such that 0,0 corresponds to
377 // where this view is located (related to its parent).
[email protected]80f8b9f2008-10-16 18:17:47378 canvas->TranslateInt(MirroredX(), y());
initial.commit09911bf2008-07-26 23:55:29379
380 // Save the state again, so that any changes don't effect PaintChildren.
381 canvas->save();
382
383 // If the View we are about to paint requested the canvas to be flipped, we
384 // should change the transform appropriately.
385 bool flip_canvas = FlipCanvasOnPaintForRTLUI();
386 if (flip_canvas) {
[email protected]6f3bb6c2008-09-17 22:25:33387 canvas->TranslateInt(width(), 0);
initial.commit09911bf2008-07-26 23:55:29388 canvas->ScaleInt(-1, 1);
389 canvas->save();
390 }
391
392 Paint(canvas);
393
394 // We must undo the canvas mirroring once the View is done painting so that
395 // we don't pass the canvas with the mirrored transform to Views that
396 // didn't request the canvas to be flipped.
[email protected]09fe9492009-11-07 02:23:06397 if (flip_canvas)
initial.commit09911bf2008-07-26 23:55:29398 canvas->restore();
[email protected]09fe9492009-11-07 02:23:06399
initial.commit09911bf2008-07-26 23:55:29400 canvas->restore();
401 PaintChildren(canvas);
402 }
403
404 // Restore the canvas's original transform.
405 canvas->restore();
406}
407
408void View::PaintNow() {
[email protected]09fe9492009-11-07 02:23:06409 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29410 return;
initial.commit09911bf2008-07-26 23:55:29411
412 View* view = GetParent();
413 if (view)
414 view->PaintNow();
415}
416
initial.commit09911bf2008-07-26 23:55:29417gfx::Insets View::GetInsets() const {
initial.commit09911bf2008-07-26 23:55:29418 gfx::Insets insets;
[email protected]9a3f0ac22008-11-14 03:24:02419 if (border_.get())
420 border_->GetInsets(&insets);
initial.commit09911bf2008-07-26 23:55:29421 return insets;
422}
423
[email protected]e9adf0702010-03-08 23:34:07424gfx::NativeCursor View::GetCursorForPoint(Event::EventType event_type,
425 const gfx::Point& p) {
[email protected]9abf8dd62009-06-04 06:40:42426 return NULL;
427}
428
[email protected]a52ca4672009-06-05 05:41:09429bool View::HitTest(const gfx::Point& l) const {
[email protected]d7fc97942009-11-20 22:07:11430 if (l.x() >= 0 && l.x() < width() && l.y() >= 0 && l.y() < height()) {
[email protected]a52ca4672009-06-05 05:41:09431 if (HasHitTestMask()) {
432 gfx::Path mask;
433 GetHitTestMask(&mask);
[email protected]a3406972009-11-04 05:05:48434 ScopedRegion rgn(mask.CreateNativeRegion());
435 // TODO: can this use SkRegion's contains instead?
[email protected]a52ca4672009-06-05 05:41:09436#if defined(OS_WIN)
[email protected]a52ca4672009-06-05 05:41:09437 return !!PtInRegion(rgn, l.x(), l.y());
[email protected]10a6e77b2009-12-31 01:03:52438#elif defined(TOOLKIT_USES_GTK)
[email protected]a3406972009-11-04 05:05:48439 return gdk_region_point_in(rgn.Get(), l.x(), l.y());
[email protected]a52ca4672009-06-05 05:41:09440#endif
441 }
442 // No mask, but inside our bounds.
443 return true;
444 }
445 // Outside our bounds.
446 return false;
447}
448
initial.commit09911bf2008-07-26 23:55:29449void View::SetContextMenuController(ContextMenuController* menu_controller) {
450 context_menu_controller_ = menu_controller;
451}
452
[email protected]e9adf0702010-03-08 23:34:07453void View::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) {
[email protected]042811c2008-10-31 21:31:34454 if (!context_menu_controller_)
455 return;
456
[email protected]e9adf0702010-03-08 23:34:07457 context_menu_controller_->ShowContextMenu(this, p, is_mouse_gesture);
[email protected]042811c2008-10-31 21:31:34458}
459
initial.commit09911bf2008-07-26 23:55:29460/////////////////////////////////////////////////////////////////////////////
461//
462// View - tree
463//
464/////////////////////////////////////////////////////////////////////////////
465
466bool View::ProcessMousePressed(const MouseEvent& e, DragInfo* drag_info) {
467 const bool enabled = enabled_;
[email protected]e9adf0702010-03-08 23:34:07468 int drag_operations =
469 (enabled && e.IsOnlyLeftMouseButton() && HitTest(e.location())) ?
470 GetDragOperations(e.location()) : 0;
471 ContextMenuController* context_menu_controller = e.IsRightMouseButton() ?
472 context_menu_controller_ : 0;
initial.commit09911bf2008-07-26 23:55:29473
474 const bool result = OnMousePressed(e);
475 // WARNING: we may have been deleted, don't use any View variables;
476
477 if (!enabled)
478 return result;
479
480 if (drag_operations != DragDropTypes::DRAG_NONE) {
[email protected]e9adf0702010-03-08 23:34:07481 drag_info->PossibleDrag(e.location());
initial.commit09911bf2008-07-26 23:55:29482 return true;
483 }
484 return !!context_menu_controller || result;
485}
486
487bool View::ProcessMouseDragged(const MouseEvent& e, DragInfo* drag_info) {
488 // Copy the field, that way if we're deleted after drag and drop no harm is
489 // done.
490 ContextMenuController* context_menu_controller = context_menu_controller_;
491 const bool possible_drag = drag_info->possible_drag;
[email protected]e9adf0702010-03-08 23:34:07492 if (possible_drag && ExceededDragThreshold(drag_info->start_pt.x() - e.x(),
493 drag_info->start_pt.y() - e.y())) {
[email protected]b5f94de2009-12-04 07:59:00494 if (!drag_controller_ ||
[email protected]e9adf0702010-03-08 23:34:07495 drag_controller_->CanStartDrag(this, drag_info->start_pt, e.location()))
496 DoDrag(e, drag_info->start_pt);
initial.commit09911bf2008-07-26 23:55:29497 } else {
498 if (OnMouseDragged(e))
499 return true;
500 // Fall through to return value based on context menu controller.
501 }
502 // WARNING: we may have been deleted.
503 return (context_menu_controller != NULL) || possible_drag;
504}
505
506void View::ProcessMouseReleased(const MouseEvent& e, bool canceled) {
507 if (!canceled && context_menu_controller_ && e.IsOnlyRightMouseButton()) {
508 // Assume that if there is a context menu controller we won't be deleted
509 // from mouse released.
[email protected]96b667d2008-10-14 20:58:44510 gfx::Point location(e.location());
initial.commit09911bf2008-07-26 23:55:29511 OnMouseReleased(e, canceled);
[email protected]464fdb32009-03-19 20:25:44512 if (HitTest(location)) {
513 ConvertPointToScreen(this, &location);
[email protected]e9adf0702010-03-08 23:34:07514 ShowContextMenu(location, true);
[email protected]464fdb32009-03-19 20:25:44515 }
initial.commit09911bf2008-07-26 23:55:29516 } else {
517 OnMouseReleased(e, canceled);
518 }
519 // WARNING: we may have been deleted.
520}
521
initial.commit09911bf2008-07-26 23:55:29522void View::AddChildView(View* v) {
[email protected]0d52b2302009-05-11 23:50:55523 AddChildView(static_cast<int>(child_views_.size()), v);
initial.commit09911bf2008-07-26 23:55:29524}
525
526void View::AddChildView(int index, View* v) {
[email protected]0b2fa2b2009-12-01 01:06:12527 CHECK(v != this) << "You cannot add a view as its own child";
528
initial.commit09911bf2008-07-26 23:55:29529 // Remove the view from its current parent if any.
530 if (v->GetParent())
531 v->GetParent()->RemoveChildView(v);
532
[email protected]0d52b2302009-05-11 23:50:55533 // Sets the prev/next focus views.
534 InitFocusSiblings(v, index);
initial.commit09911bf2008-07-26 23:55:29535
536 // Let's insert the view.
537 child_views_.insert(child_views_.begin() + index, v);
538 v->SetParent(this);
539
[email protected]09fe9492009-11-07 02:23:06540 for (View* p = this; p; p = p->GetParent())
initial.commit09911bf2008-07-26 23:55:29541 p->ViewHierarchyChangedImpl(false, true, this, v);
[email protected]09fe9492009-11-07 02:23:06542
initial.commit09911bf2008-07-26 23:55:29543 v->PropagateAddNotifications(this, v);
544 UpdateTooltip();
545 RootView* root = GetRootView();
546 if (root)
547 RegisterChildrenForVisibleBoundsNotification(root, v);
548
549 if (layout_manager_.get())
550 layout_manager_->ViewAdded(this, v);
551}
552
553View* View::GetChildViewAt(int index) const {
554 return index < GetChildViewCount() ? child_views_[index] : NULL;
555}
556
557int View::GetChildViewCount() const {
558 return static_cast<int>(child_views_.size());
559}
560
[email protected]3a9c26f2010-03-12 21:04:39561bool View::HasChildView(View* a_view) {
562 return find(child_views_.begin(),
563 child_views_.end(),
564 a_view) != child_views_.end();
565}
566
initial.commit09911bf2008-07-26 23:55:29567void View::RemoveChildView(View* a_view) {
568 DoRemoveChildView(a_view, true, true, false);
569}
570
571void View::RemoveAllChildViews(bool delete_views) {
572 ViewList::iterator iter;
573 while ((iter = child_views_.begin()) != child_views_.end()) {
574 DoRemoveChildView(*iter, false, false, delete_views);
575 }
576 UpdateTooltip();
577}
578
[email protected]e9adf0702010-03-08 23:34:07579void View::DoDrag(const MouseEvent& e, const gfx::Point& press_pt) {
580 int drag_operations = GetDragOperations(press_pt);
[email protected]4768c65b2009-08-28 21:42:59581 if (drag_operations == DragDropTypes::DRAG_NONE)
582 return;
583
584 OSExchangeData data;
[email protected]e9adf0702010-03-08 23:34:07585 WriteDragData(press_pt, &data);
[email protected]4768c65b2009-08-28 21:42:59586
587 // Message the RootView to do the drag and drop. That way if we're removed
588 // the RootView can detect it and avoid calling us back.
589 RootView* root_view = GetRootView();
590 root_view->StartDragForViewFromMouseEvent(this, data, drag_operations);
591}
592
initial.commit09911bf2008-07-26 23:55:29593void View::DoRemoveChildView(View* a_view,
594 bool update_focus_cycle,
595 bool update_tool_tip,
596 bool delete_removed_view) {
597#ifndef NDEBUG
598 DCHECK(!IsProcessingPaint()) << "Should not be removing a child view " <<
599 "during a paint, this will seriously " <<
600 "mess things up!";
601#endif
602 DCHECK(a_view);
603 const ViewList::iterator i = find(child_views_.begin(),
604 child_views_.end(),
605 a_view);
606 if (i != child_views_.end()) {
[email protected]0d52b2302009-05-11 23:50:55607 if (update_focus_cycle) {
initial.commit09911bf2008-07-26 23:55:29608 // Let's remove the view from the focus traversal.
609 View* next_focusable = a_view->next_focusable_view_;
610 View* prev_focusable = a_view->previous_focusable_view_;
611 if (prev_focusable)
612 prev_focusable->next_focusable_view_ = next_focusable;
613 if (next_focusable)
614 next_focusable->previous_focusable_view_ = prev_focusable;
615 }
616
617 RootView* root = GetRootView();
618 if (root)
619 UnregisterChildrenForVisibleBoundsNotification(root, a_view);
620 a_view->PropagateRemoveNotifications(this);
621 a_view->SetParent(NULL);
622
623 if (delete_removed_view && a_view->IsParentOwned())
624 delete a_view;
625
626 child_views_.erase(i);
627 }
628
629 if (update_tool_tip)
630 UpdateTooltip();
631
632 if (layout_manager_.get())
633 layout_manager_->ViewRemoved(this, a_view);
634}
635
636void View::PropagateRemoveNotifications(View* parent) {
[email protected]09fe9492009-11-07 02:23:06637 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29638 GetChildViewAt(i)->PropagateRemoveNotifications(parent);
initial.commit09911bf2008-07-26 23:55:29639
[email protected]09fe9492009-11-07 02:23:06640 for (View* v = this; v; v = v->GetParent())
641 v->ViewHierarchyChangedImpl(true, false, parent, this);
initial.commit09911bf2008-07-26 23:55:29642}
643
644void View::PropagateAddNotifications(View* parent, View* child) {
[email protected]09fe9492009-11-07 02:23:06645 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29646 GetChildViewAt(i)->PropagateAddNotifications(parent, child);
initial.commit09911bf2008-07-26 23:55:29647 ViewHierarchyChangedImpl(true, true, parent, child);
648}
649
[email protected]32670b02009-03-03 00:28:00650void View::ThemeChanged() {
651 int c = GetChildViewCount();
652 for (int i = c - 1; i >= 0; --i)
653 GetChildViewAt(i)->ThemeChanged();
654}
655
initial.commit09911bf2008-07-26 23:55:29656#ifndef NDEBUG
657bool View::IsProcessingPaint() const {
658 return GetParent() && GetParent()->IsProcessingPaint();
659}
660#endif
661
[email protected]f704ee72008-11-10 21:31:59662gfx::Point View::GetKeyboardContextMenuLocation() {
663 gfx::Rect vis_bounds = GetVisibleBounds();
664 gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2,
665 vis_bounds.y() + vis_bounds.height() / 2);
666 ConvertPointToScreen(this, &screen_point);
667 return screen_point;
668}
669
[email protected]82739cf2008-09-16 00:37:56670bool View::HasHitTestMask() const {
671 return false;
672}
673
674void View::GetHitTestMask(gfx::Path* mask) const {
675 DCHECK(mask);
676}
677
[email protected]bb515ed2009-01-15 00:53:43678void View::ViewHierarchyChanged(bool is_add,
679 View* parent,
680 View* child) {
initial.commit09911bf2008-07-26 23:55:29681}
682
683void View::ViewHierarchyChangedImpl(bool register_accelerators,
[email protected]bb515ed2009-01-15 00:53:43684 bool is_add,
685 View* parent,
686 View* child) {
initial.commit09911bf2008-07-26 23:55:29687 if (register_accelerators) {
688 if (is_add) {
689 // If you get this registration, you are part of a subtree that has been
690 // added to the view hierarchy.
[email protected]bda9556c2010-01-07 00:55:16691 if (GetFocusManager()) {
692 RegisterPendingAccelerators();
693 } else {
694 // Delay accelerator registration until visible as we do not have
695 // focus manager until then.
696 accelerator_registration_delayed_ = true;
697 }
initial.commit09911bf2008-07-26 23:55:29698 } else {
699 if (child == this)
[email protected]fa1cf0b82010-01-15 21:49:44700 UnregisterAccelerators(true);
initial.commit09911bf2008-07-26 23:55:29701 }
702 }
703
704 ViewHierarchyChanged(is_add, parent, child);
705}
706
707void View::PropagateVisibilityNotifications(View* start, bool is_visible) {
[email protected]09fe9492009-11-07 02:23:06708 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29709 GetChildViewAt(i)->PropagateVisibilityNotifications(start, is_visible);
initial.commit09911bf2008-07-26 23:55:29710 VisibilityChanged(start, is_visible);
711}
712
713void View::VisibilityChanged(View* starting_from, bool is_visible) {
714}
715
[email protected]bda9556c2010-01-07 00:55:16716void View::PropagateNativeViewHierarchyChanged(bool attached,
717 gfx::NativeView native_view,
718 RootView* root_view) {
719 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
720 GetChildViewAt(i)->PropagateNativeViewHierarchyChanged(attached,
721 native_view,
722 root_view);
723 NativeViewHierarchyChanged(attached, native_view, root_view);
724}
725
726void View::NativeViewHierarchyChanged(bool attached,
727 gfx::NativeView native_view,
728 RootView* root_view) {
729 FocusManager* focus_manager = GetFocusManager();
730 if (!accelerator_registration_delayed_ &&
731 accelerator_focus_manager_ &&
732 accelerator_focus_manager_ != focus_manager) {
733 UnregisterAccelerators(true);
734 accelerator_registration_delayed_ = true;
735 }
736 if (accelerator_registration_delayed_ && attached) {
737 if (focus_manager) {
738 RegisterPendingAccelerators();
739 accelerator_registration_delayed_ = false;
740 }
741 }
742}
743
initial.commit09911bf2008-07-26 23:55:29744void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) {
745 if (notify_when_visible_bounds_in_root_changes_ == value)
746 return;
747 notify_when_visible_bounds_in_root_changes_ = value;
748 RootView* root = GetRootView();
749 if (root) {
750 if (value)
751 root->RegisterViewForVisibleBoundsNotification(this);
752 else
753 root->UnregisterViewForVisibleBoundsNotification(this);
754 }
755}
756
757bool View::GetNotifyWhenVisibleBoundsInRootChanges() {
758 return notify_when_visible_bounds_in_root_changes_;
759}
760
[email protected]0d52b2302009-05-11 23:50:55761View* View::GetViewForPoint(const gfx::Point& point) {
initial.commit09911bf2008-07-26 23:55:29762 // Walk the child Views recursively looking for the View that most
763 // tightly encloses the specified point.
[email protected]09fe9492009-11-07 02:23:06764 for (int i = GetChildViewCount() - 1; i >= 0; --i) {
initial.commit09911bf2008-07-26 23:55:29765 View* child = GetChildViewAt(i);
[email protected]82739cf2008-09-16 00:37:56766 if (!child->IsVisible())
initial.commit09911bf2008-07-26 23:55:29767 continue;
[email protected]82739cf2008-09-16 00:37:56768
[email protected]96b667d2008-10-14 20:58:44769 gfx::Point point_in_child_coords(point);
[email protected]82739cf2008-09-16 00:37:56770 View::ConvertPointToView(this, child, &point_in_child_coords);
[email protected]613b8062008-10-14 23:45:09771 if (child->HitTest(point_in_child_coords))
[email protected]0d52b2302009-05-11 23:50:55772 return child->GetViewForPoint(point_in_child_coords);
initial.commit09911bf2008-07-26 23:55:29773 }
774 return this;
775}
776
[email protected]a0dde122008-11-21 20:51:20777Widget* View::GetWidget() const {
778 // The root view holds a reference to this view hierarchy's Widget.
779 return parent_ ? parent_->GetWidget() : NULL;
initial.commit09911bf2008-07-26 23:55:29780}
781
[email protected]cd8c47902009-04-30 20:55:35782Window* View::GetWindow() const {
783 Widget* widget = GetWidget();
784 return widget ? widget->GetWindow() : NULL;
785}
786
[email protected]2db27be2010-02-10 22:46:47787bool View::ContainsNativeView(gfx::NativeView native_view) const {
788 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
789 if (GetChildViewAt(i)->ContainsNativeView(native_view))
790 return true;
791 }
792 return false;
793}
794
initial.commit09911bf2008-07-26 23:55:29795// Get the containing RootView
796RootView* View::GetRootView() {
[email protected]a0dde122008-11-21 20:51:20797 Widget* widget = GetWidget();
798 return widget ? widget->GetRootView() : NULL;
initial.commit09911bf2008-07-26 23:55:29799}
800
801View* View::GetViewByID(int id) const {
802 if (id == id_)
803 return const_cast<View*>(this);
804
[email protected]09fe9492009-11-07 02:23:06805 for (int i = 0, count = GetChildViewCount(); i < count; ++i) {
initial.commit09911bf2008-07-26 23:55:29806 View* child = GetChildViewAt(i);
807 View* view = child->GetViewByID(id);
808 if (view)
809 return view;
810 }
811 return NULL;
812}
813
814void View::GetViewsWithGroup(int group_id, std::vector<View*>* out) {
815 if (group_ == group_id)
816 out->push_back(this);
817
[email protected]09fe9492009-11-07 02:23:06818 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29819 GetChildViewAt(i)->GetViewsWithGroup(group_id, out);
820}
821
822View* View::GetSelectedViewForGroup(int group_id) {
823 std::vector<View*> views;
824 GetRootView()->GetViewsWithGroup(group_id, &views);
825 if (views.size() > 0)
826 return views[0];
827 else
828 return NULL;
829}
830
831void View::SetID(int id) {
832 id_ = id;
833}
834
835int View::GetID() const {
836 return id_;
837}
838
839void View::SetGroup(int gid) {
[email protected]96f960d2009-09-14 18:45:30840 // Don't change the group id once it's set.
841 DCHECK(group_ == -1 || group_ == gid);
initial.commit09911bf2008-07-26 23:55:29842 group_ = gid;
843}
844
845int View::GetGroup() const {
846 return group_;
847}
848
849void View::SetParent(View* parent) {
[email protected]09fe9492009-11-07 02:23:06850 if (parent != parent_)
initial.commit09911bf2008-07-26 23:55:29851 parent_ = parent;
initial.commit09911bf2008-07-26 23:55:29852}
853
854bool View::IsParentOf(View* v) const {
855 DCHECK(v);
856 View* parent = v->GetParent();
857 while (parent) {
858 if (this == parent)
859 return true;
860 parent = parent->GetParent();
861 }
862 return false;
863}
864
865int View::GetChildIndex(View* v) const {
[email protected]09fe9492009-11-07 02:23:06866 for (int i = 0, count = GetChildViewCount(); i < count; i++) {
initial.commit09911bf2008-07-26 23:55:29867 if (v == GetChildViewAt(i))
868 return i;
869 }
870 return -1;
871}
872
873///////////////////////////////////////////////////////////////////////////////
874//
875// View - focus
876//
877///////////////////////////////////////////////////////////////////////////////
878
879View* View::GetNextFocusableView() {
880 return next_focusable_view_;
881}
882
883View* View::GetPreviousFocusableView() {
884 return previous_focusable_view_;
885}
886
887void View::SetNextFocusableView(View* view) {
888 view->previous_focusable_view_ = this;
889 next_focusable_view_ = view;
890}
891
892void View::InitFocusSiblings(View* v, int index) {
893 int child_count = static_cast<int>(child_views_.size());
894
895 if (child_count == 0) {
896 v->next_focusable_view_ = NULL;
897 v->previous_focusable_view_ = NULL;
898 } else {
899 if (index == child_count) {
900 // We are inserting at the end, but the end of the child list may not be
901 // the last focusable element. Let's try to find an element with no next
902 // focusable element to link to.
903 View* last_focusable_view = NULL;
904 for (std::vector<View*>::iterator iter = child_views_.begin();
905 iter != child_views_.end(); ++iter) {
906 if (!(*iter)->next_focusable_view_) {
907 last_focusable_view = *iter;
908 break;
909 }
910 }
911 if (last_focusable_view == NULL) {
912 // Hum... there is a cycle in the focus list. Let's just insert ourself
913 // after the last child.
914 View* prev = child_views_[index - 1];
915 v->previous_focusable_view_ = prev;
916 v->next_focusable_view_ = prev->next_focusable_view_;
917 prev->next_focusable_view_->previous_focusable_view_ = v;
918 prev->next_focusable_view_ = v;
919 } else {
920 last_focusable_view->next_focusable_view_ = v;
921 v->next_focusable_view_ = NULL;
922 v->previous_focusable_view_ = last_focusable_view;
923 }
924 } else {
925 View* prev = child_views_[index]->GetPreviousFocusableView();
926 v->previous_focusable_view_ = prev;
927 v->next_focusable_view_ = child_views_[index];
928 if (prev)
929 prev->next_focusable_view_ = v;
930 child_views_[index]->previous_focusable_view_ = v;
931 }
932 }
933}
934
935#ifndef NDEBUG
936void View::PrintViewHierarchy() {
937 PrintViewHierarchyImp(0);
938}
939
940void View::PrintViewHierarchyImp(int indent) {
941 std::wostringstream buf;
942 int ind = indent;
943 while (ind-- > 0)
944 buf << L' ';
945 buf << UTF8ToWide(GetClassName());
946 buf << L' ';
947 buf << GetID();
948 buf << L' ';
[email protected]80f8b9f2008-10-16 18:17:47949 buf << bounds_.x() << L"," << bounds_.y() << L",";
950 buf << bounds_.right() << L"," << bounds_.bottom();
initial.commit09911bf2008-07-26 23:55:29951 buf << L' ';
952 buf << this;
953
954 LOG(INFO) << buf.str();
955 std::cout << buf.str() << std::endl;
956
[email protected]09fe9492009-11-07 02:23:06957 for (int i = 0, count = GetChildViewCount(); i < count; ++i)
initial.commit09911bf2008-07-26 23:55:29958 GetChildViewAt(i)->PrintViewHierarchyImp(indent + 2);
initial.commit09911bf2008-07-26 23:55:29959}
960
961
962void View::PrintFocusHierarchy() {
963 PrintFocusHierarchyImp(0);
964}
965
966void View::PrintFocusHierarchyImp(int indent) {
967 std::wostringstream buf;
968 int ind = indent;
969 while (ind-- > 0)
970 buf << L' ';
971 buf << UTF8ToWide(GetClassName());
972 buf << L' ';
973 buf << GetID();
974 buf << L' ';
975 buf << GetClassName().c_str();
976 buf << L' ';
977 buf << this;
978
979 LOG(INFO) << buf.str();
980 std::cout << buf.str() << std::endl;
981
982 if (GetChildViewCount() > 0)
983 GetChildViewAt(0)->PrintFocusHierarchyImp(indent + 2);
984
985 View* v = GetNextFocusableView();
986 if (v)
987 v->PrintFocusHierarchyImp(indent);
988}
989#endif
990
991////////////////////////////////////////////////////////////////////////////////
992//
993// View - accelerators
994//
995////////////////////////////////////////////////////////////////////////////////
996
997void View::AddAccelerator(const Accelerator& accelerator) {
998 if (!accelerators_.get())
999 accelerators_.reset(new std::vector<Accelerator>());
[email protected]71421c3f2009-06-06 00:41:441000
1001 std::vector<Accelerator>::iterator iter =
1002 std::find(accelerators_->begin(), accelerators_->end(), accelerator);
1003 DCHECK(iter == accelerators_->end())
1004 << "Registering the same accelerator multiple times";
1005
initial.commit09911bf2008-07-26 23:55:291006 accelerators_->push_back(accelerator);
[email protected]71421c3f2009-06-06 00:41:441007 RegisterPendingAccelerators();
initial.commit09911bf2008-07-26 23:55:291008}
1009
[email protected]e8e0f362008-11-08 01:13:251010void View::RemoveAccelerator(const Accelerator& accelerator) {
1011 std::vector<Accelerator>::iterator iter;
1012 if (!accelerators_.get() ||
1013 ((iter = std::find(accelerators_->begin(), accelerators_->end(),
1014 accelerator)) == accelerators_->end())) {
1015 NOTREACHED() << "Removing non-existing accelerator";
1016 return;
1017 }
1018
[email protected]4bd23f32009-06-08 20:59:191019 size_t index = iter - accelerators_->begin();
[email protected]e8e0f362008-11-08 01:13:251020 accelerators_->erase(iter);
[email protected]71421c3f2009-06-06 00:41:441021 if (index >= registered_accelerator_count_) {
1022 // The accelerator is not registered to FocusManager.
1023 return;
1024 }
1025 --registered_accelerator_count_;
1026
[email protected]e8e0f362008-11-08 01:13:251027 RootView* root_view = GetRootView();
1028 if (!root_view) {
1029 // We are not part of a view hierarchy, so there is nothing to do as we
1030 // removed ourselves from accelerators_, we won't be registered when added
1031 // to one.
1032 return;
1033 }
1034
[email protected]bda9556c2010-01-07 00:55:161035 // If accelerator_focus_manager_ is NULL then we did not registered
1036 // accelerators so there is nothing to unregister.
1037 if (accelerator_focus_manager_) {
1038 accelerator_focus_manager_->UnregisterAccelerator(accelerator, this);
[email protected]e8e0f362008-11-08 01:13:251039 }
1040}
1041
initial.commit09911bf2008-07-26 23:55:291042void View::ResetAccelerators() {
[email protected]71421c3f2009-06-06 00:41:441043 if (accelerators_.get())
[email protected]bda9556c2010-01-07 00:55:161044 UnregisterAccelerators(false);
initial.commit09911bf2008-07-26 23:55:291045}
1046
[email protected]71421c3f2009-06-06 00:41:441047void View::RegisterPendingAccelerators() {
1048 if (!accelerators_.get() ||
1049 registered_accelerator_count_ == accelerators_->size()) {
1050 // No accelerators are waiting for registration.
initial.commit09911bf2008-07-26 23:55:291051 return;
[email protected]71421c3f2009-06-06 00:41:441052 }
initial.commit09911bf2008-07-26 23:55:291053
1054 RootView* root_view = GetRootView();
1055 if (!root_view) {
1056 // We are not yet part of a view hierarchy, we'll register ourselves once
1057 // added to one.
1058 return;
1059 }
[email protected]f3735c5d2009-03-19 17:26:231060
[email protected]bda9556c2010-01-07 00:55:161061 accelerator_focus_manager_ = GetFocusManager();
1062 if (!accelerator_focus_manager_) {
initial.commit09911bf2008-07-26 23:55:291063 // Some crash reports seem to show that we may get cases where we have no
1064 // focus manager (see bug #1291225). This should never be the case, just
1065 // making sure we don't crash.
[email protected]f8dce002009-09-10 21:07:041066
1067 // TODO(jcampan): This fails for a view under WidgetGtk with TYPE_CHILD.
1068 // (see http://crbug.com/21335) reenable NOTREACHED assertion and
1069 // verify accelerators works as expected.
1070#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291071 NOTREACHED();
[email protected]f8dce002009-09-10 21:07:041072#endif
initial.commit09911bf2008-07-26 23:55:291073 return;
1074 }
[email protected]71421c3f2009-06-06 00:41:441075 std::vector<Accelerator>::const_iterator iter;
1076 for (iter = accelerators_->begin() + registered_accelerator_count_;
initial.commit09911bf2008-07-26 23:55:291077 iter != accelerators_->end(); ++iter) {
[email protected]bda9556c2010-01-07 00:55:161078 accelerator_focus_manager_->RegisterAccelerator(*iter, this);
initial.commit09911bf2008-07-26 23:55:291079 }
[email protected]71421c3f2009-06-06 00:41:441080 registered_accelerator_count_ = accelerators_->size();
initial.commit09911bf2008-07-26 23:55:291081}
1082
[email protected]bda9556c2010-01-07 00:55:161083void View::UnregisterAccelerators(bool leave_data_intact) {
initial.commit09911bf2008-07-26 23:55:291084 if (!accelerators_.get())
1085 return;
1086
1087 RootView* root_view = GetRootView();
1088 if (root_view) {
[email protected]bda9556c2010-01-07 00:55:161089 if (accelerator_focus_manager_) {
initial.commit09911bf2008-07-26 23:55:291090 // We may not have a FocusManager if the window containing us is being
1091 // closed, in which case the FocusManager is being deleted so there is
1092 // nothing to unregister.
[email protected]bda9556c2010-01-07 00:55:161093 accelerator_focus_manager_->UnregisterAccelerators(this);
1094 accelerator_focus_manager_ = NULL;
initial.commit09911bf2008-07-26 23:55:291095 }
[email protected]bda9556c2010-01-07 00:55:161096 if (!leave_data_intact) {
1097 accelerators_->clear();
1098 accelerators_.reset();
1099 }
[email protected]71421c3f2009-06-06 00:41:441100 registered_accelerator_count_ = 0;
initial.commit09911bf2008-07-26 23:55:291101 }
1102}
1103
[email protected]e9adf0702010-03-08 23:34:071104int View::GetDragOperations(const gfx::Point& press_pt) {
1105 return drag_controller_ ?
1106 drag_controller_->GetDragOperations(this, press_pt) :
1107 DragDropTypes::DRAG_NONE;
initial.commit09911bf2008-07-26 23:55:291108}
1109
[email protected]e9adf0702010-03-08 23:34:071110void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) {
initial.commit09911bf2008-07-26 23:55:291111 DCHECK(drag_controller_);
[email protected]e9adf0702010-03-08 23:34:071112 drag_controller_->WriteDragData(this, press_pt, data);
initial.commit09911bf2008-07-26 23:55:291113}
1114
1115void View::OnDragDone() {
1116}
1117
1118bool View::InDrag() {
1119 RootView* root_view = GetRootView();
1120 return root_view ? (root_view->GetDragView() == this) : false;
1121}
1122
initial.commit09911bf2008-07-26 23:55:291123// static
[email protected]bb515ed2009-01-15 00:53:431124void View::ConvertPointToView(const View* src,
1125 const View* dst,
1126 gfx::Point* point) {
initial.commit09911bf2008-07-26 23:55:291127 ConvertPointToView(src, dst, point, true);
1128}
1129
1130// static
[email protected]bb515ed2009-01-15 00:53:431131void View::ConvertPointToView(const View* src,
1132 const View* dst,
1133 gfx::Point* point,
initial.commit09911bf2008-07-26 23:55:291134 bool try_other_direction) {
1135 // src can be NULL
1136 DCHECK(dst);
1137 DCHECK(point);
1138
[email protected]bb515ed2009-01-15 00:53:431139 const View* v;
initial.commit09911bf2008-07-26 23:55:291140 gfx::Point offset;
1141
1142 for (v = dst; v && v != src; v = v->GetParent()) {
1143 offset.SetPoint(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION),
[email protected]6f3bb6c2008-09-17 22:25:331144 offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291145 }
1146
1147 // The source was not found. The caller wants a conversion
1148 // from a view to a transitive parent.
1149 if (src && v == NULL && try_other_direction) {
1150 gfx::Point p;
1151 // note: try_other_direction is force to FALSE so we don't
1152 // end up in an infinite recursion should both src and dst
1153 // are not parented.
1154 ConvertPointToView(dst, src, &p, false);
1155 // since the src and dst are inverted, p should also be negated
1156 point->SetPoint(point->x() - p.x(), point->y() - p.y());
1157 } else {
1158 point->SetPoint(point->x() - offset.x(), point->y() - offset.y());
1159
1160 // If src is NULL, sp is in the screen coordinate system
1161 if (src == NULL) {
[email protected]a0dde122008-11-21 20:51:201162 Widget* widget = dst->GetWidget();
1163 if (widget) {
[email protected]3b680a82008-12-17 02:03:231164 gfx::Rect b;
[email protected]a0dde122008-11-21 20:51:201165 widget->GetBounds(&b, false);
[email protected]3b680a82008-12-17 02:03:231166 point->SetPoint(point->x() - b.x(), point->y() - b.y());
initial.commit09911bf2008-07-26 23:55:291167 }
1168 }
1169 }
1170}
1171
1172// static
[email protected]2fb6d462009-02-13 18:40:101173void View::ConvertPointToWidget(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291174 DCHECK(src);
1175 DCHECK(p);
[email protected]96b667d2008-10-14 20:58:441176
[email protected]96b667d2008-10-14 20:58:441177 gfx::Point offset;
[email protected]2fb6d462009-02-13 18:40:101178 for (const View* v = src; v; v = v->GetParent()) {
[email protected]96b667d2008-10-14 20:58:441179 offset.set_x(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION));
1180 offset.set_y(offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291181 }
[email protected]96b667d2008-10-14 20:58:441182 p->SetPoint(p->x() + offset.x(), p->y() + offset.y());
initial.commit09911bf2008-07-26 23:55:291183}
1184
1185// static
[email protected]2fb6d462009-02-13 18:40:101186void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) {
[email protected]96b667d2008-10-14 20:58:441187 gfx::Point t;
[email protected]2fb6d462009-02-13 18:40:101188 ConvertPointToWidget(dest, &t);
[email protected]96b667d2008-10-14 20:58:441189 p->SetPoint(p->x() - t.x(), p->y() - t.y());
initial.commit09911bf2008-07-26 23:55:291190}
1191
1192// static
[email protected]2fb6d462009-02-13 18:40:101193void View::ConvertPointToScreen(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291194 DCHECK(src);
1195 DCHECK(p);
1196
[email protected]96b667d2008-10-14 20:58:441197 // If the view is not connected to a tree, there's nothing we can do.
[email protected]a0dde122008-11-21 20:51:201198 Widget* widget = src->GetWidget();
1199 if (widget) {
1200 ConvertPointToWidget(src, p);
[email protected]3b680a82008-12-17 02:03:231201 gfx::Rect r;
[email protected]a0dde122008-11-21 20:51:201202 widget->GetBounds(&r, false);
[email protected]3b680a82008-12-17 02:03:231203 p->SetPoint(p->x() + r.x(), p->y() + r.y());
initial.commit09911bf2008-07-26 23:55:291204 }
1205}
1206
1207/////////////////////////////////////////////////////////////////////////////
1208//
1209// View - event handlers
1210//
1211/////////////////////////////////////////////////////////////////////////////
1212
1213bool View::OnMousePressed(const MouseEvent& e) {
1214 return false;
1215}
1216
1217bool View::OnMouseDragged(const MouseEvent& e) {
1218 return false;
1219}
1220
1221void View::OnMouseReleased(const MouseEvent& e, bool canceled) {
1222}
1223
1224void View::OnMouseMoved(const MouseEvent& e) {
1225}
1226
1227void View::OnMouseEntered(const MouseEvent& e) {
1228}
1229
1230void View::OnMouseExited(const MouseEvent& e) {
1231}
1232
1233void View::SetMouseHandler(View *new_mouse_handler) {
1234 // It is valid for new_mouse_handler to be NULL
[email protected]09fe9492009-11-07 02:23:061235 if (parent_)
initial.commit09911bf2008-07-26 23:55:291236 parent_->SetMouseHandler(new_mouse_handler);
initial.commit09911bf2008-07-26 23:55:291237}
1238
1239void View::SetVisible(bool flag) {
1240 if (flag != is_visible_) {
1241 // If the tab is currently visible, schedule paint to
1242 // refresh parent
[email protected]09fe9492009-11-07 02:23:061243 if (IsVisible())
initial.commit09911bf2008-07-26 23:55:291244 SchedulePaint();
initial.commit09911bf2008-07-26 23:55:291245
1246 is_visible_ = flag;
1247
1248 // This notifies all subviews recursively.
1249 PropagateVisibilityNotifications(this, flag);
1250
1251 // If we are newly visible, schedule paint.
[email protected]09fe9492009-11-07 02:23:061252 if (IsVisible())
initial.commit09911bf2008-07-26 23:55:291253 SchedulePaint();
initial.commit09911bf2008-07-26 23:55:291254 }
1255}
1256
1257bool View::IsVisibleInRootView() const {
1258 View* parent = GetParent();
1259 if (IsVisible() && parent)
1260 return parent->IsVisibleInRootView();
1261 else
1262 return false;
1263}
1264
initial.commit09911bf2008-07-26 23:55:291265/////////////////////////////////////////////////////////////////////////////
1266//
1267// View - keyboard and focus
1268//
1269/////////////////////////////////////////////////////////////////////////////
1270
1271void View::RequestFocus() {
1272 RootView* rv = GetRootView();
[email protected]830e2062009-02-13 18:27:381273 if (rv && IsFocusable())
initial.commit09911bf2008-07-26 23:55:291274 rv->FocusView(this);
initial.commit09911bf2008-07-26 23:55:291275}
1276
1277void View::WillGainFocus() {
1278}
1279
1280void View::DidGainFocus() {
1281}
1282
1283void View::WillLoseFocus() {
1284}
1285
1286bool View::OnKeyPressed(const KeyEvent& e) {
1287 return false;
1288}
1289
1290bool View::OnKeyReleased(const KeyEvent& e) {
1291 return false;
1292}
1293
1294bool View::OnMouseWheel(const MouseWheelEvent& e) {
1295 return false;
1296}
1297
1298void View::SetDragController(DragController* drag_controller) {
[email protected]09fe9492009-11-07 02:23:061299 drag_controller_ = drag_controller;
initial.commit09911bf2008-07-26 23:55:291300}
1301
1302DragController* View::GetDragController() {
1303 return drag_controller_;
1304}
1305
[email protected]134c47b92009-08-19 03:33:441306bool View::GetDropFormats(
1307 int* formats,
1308 std::set<OSExchangeData::CustomFormat>* custom_formats) {
1309 return false;
1310}
1311
1312bool View::AreDropTypesRequired() {
1313 return false;
1314}
1315
initial.commit09911bf2008-07-26 23:55:291316bool View::CanDrop(const OSExchangeData& data) {
[email protected]134c47b92009-08-19 03:33:441317 // TODO(sky): when I finish up migration, this should default to true.
initial.commit09911bf2008-07-26 23:55:291318 return false;
1319}
1320
1321void View::OnDragEntered(const DropTargetEvent& event) {
1322}
1323
1324int View::OnDragUpdated(const DropTargetEvent& event) {
1325 return DragDropTypes::DRAG_NONE;
1326}
1327
1328void View::OnDragExited() {
1329}
1330
1331int View::OnPerformDrop(const DropTargetEvent& event) {
1332 return DragDropTypes::DRAG_NONE;
1333}
1334
initial.commit09911bf2008-07-26 23:55:291335// static
1336bool View::ExceededDragThreshold(int delta_x, int delta_y) {
1337 return (abs(delta_x) > GetHorizontalDragThreshold() ||
1338 abs(delta_y) > GetVerticalDragThreshold());
1339}
1340
initial.commit09911bf2008-07-26 23:55:291341// Tooltips -----------------------------------------------------------------
[email protected]e9adf0702010-03-08 23:34:071342bool View::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
initial.commit09911bf2008-07-26 23:55:291343 return false;
1344}
1345
[email protected]e9adf0702010-03-08 23:34:071346bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) {
initial.commit09911bf2008-07-26 23:55:291347 return false;
1348}
1349
1350void View::TooltipTextChanged() {
[email protected]a0dde122008-11-21 20:51:201351 Widget* widget = GetWidget();
1352 if (widget && widget->GetTooltipManager())
1353 widget->GetTooltipManager()->TooltipTextChanged(this);
initial.commit09911bf2008-07-26 23:55:291354}
1355
1356void View::UpdateTooltip() {
[email protected]a0dde122008-11-21 20:51:201357 Widget* widget = GetWidget();
1358 if (widget && widget->GetTooltipManager())
1359 widget->GetTooltipManager()->UpdateTooltip();
initial.commit09911bf2008-07-26 23:55:291360}
1361
initial.commit09911bf2008-07-26 23:55:291362std::string View::GetClassName() const {
1363 return kViewClassName;
1364}
1365
[email protected]5c2b98b2009-03-09 20:55:541366View* View::GetAncestorWithClassName(const std::string& name) {
1367 for (View* view = this; view; view = view->GetParent()) {
1368 if (view->GetClassName() == name)
1369 return view;
1370 }
1371 return NULL;
1372}
1373
initial.commit09911bf2008-07-26 23:55:291374gfx::Rect View::GetVisibleBounds() {
[email protected]b6296fd2009-02-13 17:34:161375 if (!IsVisibleInRootView())
1376 return gfx::Rect();
[email protected]6f3bb6c2008-09-17 22:25:331377 gfx::Rect vis_bounds(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:291378 gfx::Rect ancestor_bounds;
1379 View* view = this;
1380 int root_x = 0;
1381 int root_y = 0;
initial.commit09911bf2008-07-26 23:55:291382 while (view != NULL && !vis_bounds.IsEmpty()) {
1383 root_x += view->GetX(APPLY_MIRRORING_TRANSFORMATION);
[email protected]6f3bb6c2008-09-17 22:25:331384 root_y += view->y();
1385 vis_bounds.Offset(view->GetX(APPLY_MIRRORING_TRANSFORMATION), view->y());
initial.commit09911bf2008-07-26 23:55:291386 View* ancestor = view->GetParent();
1387 if (ancestor != NULL) {
[email protected]6f3bb6c2008-09-17 22:25:331388 ancestor_bounds.SetRect(0, 0, ancestor->width(),
1389 ancestor->height());
initial.commit09911bf2008-07-26 23:55:291390 vis_bounds = vis_bounds.Intersect(ancestor_bounds);
[email protected]a0dde122008-11-21 20:51:201391 } else if (!view->GetWidget()) {
1392 // If the view has no Widget, we're not visible. Return an empty rect.
initial.commit09911bf2008-07-26 23:55:291393 return gfx::Rect();
1394 }
1395 view = ancestor;
1396 }
1397 if (vis_bounds.IsEmpty())
1398 return vis_bounds;
1399 // Convert back to this views coordinate system.
1400 vis_bounds.Offset(-root_x, -root_y);
1401 return vis_bounds;
1402}
1403
1404int View::GetPageScrollIncrement(ScrollView* scroll_view,
1405 bool is_horizontal, bool is_positive) {
1406 return 0;
1407}
1408
1409int View::GetLineScrollIncrement(ScrollView* scroll_view,
1410 bool is_horizontal, bool is_positive) {
1411 return 0;
1412}
1413
[email protected]45da6c72009-10-28 20:45:421414ThemeProvider* View::GetThemeProvider() const {
[email protected]4a190632009-05-09 01:07:421415 Widget* widget = GetWidget();
1416 return widget ? widget->GetThemeProvider() : NULL;
1417}
1418
initial.commit09911bf2008-07-26 23:55:291419// static
1420void View::RegisterChildrenForVisibleBoundsNotification(
1421 RootView* root, View* view) {
1422 DCHECK(root && view);
1423 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1424 root->RegisterViewForVisibleBoundsNotification(view);
1425 for (int i = 0; i < view->GetChildViewCount(); ++i)
1426 RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i));
1427}
1428
1429// static
1430void View::UnregisterChildrenForVisibleBoundsNotification(
1431 RootView* root, View* view) {
1432 DCHECK(root && view);
1433 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1434 root->UnregisterViewForVisibleBoundsNotification(view);
1435 for (int i = 0; i < view->GetChildViewCount(); ++i)
1436 UnregisterChildrenForVisibleBoundsNotification(root,
1437 view->GetChildViewAt(i));
1438}
1439
1440void View::AddDescendantToNotify(View* view) {
1441 DCHECK(view);
1442 if (!descendants_to_notify_.get())
1443 descendants_to_notify_.reset(new ViewList());
1444 descendants_to_notify_->push_back(view);
1445}
1446
1447void View::RemoveDescendantToNotify(View* view) {
1448 DCHECK(view && descendants_to_notify_.get());
1449 ViewList::iterator i = find(descendants_to_notify_->begin(),
1450 descendants_to_notify_->end(),
1451 view);
1452 DCHECK(i != descendants_to_notify_->end());
1453 descendants_to_notify_->erase(i);
1454 if (descendants_to_notify_->empty())
1455 descendants_to_notify_.reset();
1456}
1457
initial.commit09911bf2008-07-26 23:55:291458// DropInfo --------------------------------------------------------------------
1459
1460void View::DragInfo::Reset() {
1461 possible_drag = false;
[email protected]e9adf0702010-03-08 23:34:071462 start_pt = gfx::Point();
initial.commit09911bf2008-07-26 23:55:291463}
1464
[email protected]e9adf0702010-03-08 23:34:071465void View::DragInfo::PossibleDrag(const gfx::Point& p) {
initial.commit09911bf2008-07-26 23:55:291466 possible_drag = true;
[email protected]e9adf0702010-03-08 23:34:071467 start_pt = p;
initial.commit09911bf2008-07-26 23:55:291468}
1469
1470} // namespace