blob: b93c3c8695f51e605007c7ad705ceeb168d0f70f [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
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"
initial.commit09911bf2008-07-26 23:55:2918#include "base/string_util.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]6ff244f2009-01-20 20:38:0827#if defined(OS_WIN)
[email protected]2362e4f2009-05-08 00:34:0528#include "views/accessibility/view_accessibility_wrapper.h"
[email protected]6ff244f2009-01-20 20:38:0829#endif
initial.commit09911bf2008-07-26 23:55:2930
[email protected]c2dacc92008-10-16 23:51:3831namespace views {
initial.commit09911bf2008-07-26 23:55:2932
33// static
[email protected]3ee83f2c2009-05-10 05:58:4034ViewsDelegate* ViewsDelegate::views_delegate = NULL;
35
36// static
[email protected]2362e4f2009-05-08 00:34:0537char View::kViewClassName[] = "views/View";
initial.commit09911bf2008-07-26 23:55:2938
initial.commit09911bf2008-07-26 23:55:2939/////////////////////////////////////////////////////////////////////////////
40//
41// View - constructors, destructors, initialization
42//
43/////////////////////////////////////////////////////////////////////////////
44
45View::View()
46 : id_(0),
47 group_(-1),
[email protected]6ff244f2009-01-20 20:38:0848 enabled_(true),
49 focusable_(false),
[email protected]4f3dc372009-02-24 00:10:2950 bounds_(0, 0, 0, 0),
initial.commit09911bf2008-07-26 23:55:2951 parent_(NULL),
initial.commit09911bf2008-07-26 23:55:2952 is_visible_(true),
initial.commit09911bf2008-07-26 23:55:2953 is_parent_owned_(true),
54 notify_when_visible_bounds_in_root_changes_(false),
55 registered_for_visible_bounds_notification_(false),
56 next_focusable_view_(NULL),
57 previous_focusable_view_(NULL),
initial.commit09911bf2008-07-26 23:55:2958 context_menu_controller_(NULL),
[email protected]6ff244f2009-01-20 20:38:0859#if defined(OS_WIN)
60 accessibility_(NULL),
61#endif
initial.commit09911bf2008-07-26 23:55:2962 drag_controller_(NULL),
63 ui_mirroring_is_enabled_for_rtl_languages_(true),
64 flip_canvas_on_paint_for_rtl_ui_(false) {
65}
66
67View::~View() {
initial.commit09911bf2008-07-26 23:55:2968 int c = static_cast<int>(child_views_.size());
69 while (--c >= 0) {
70 if (child_views_[c]->IsParentOwned())
71 delete child_views_[c];
72 else
73 child_views_[c]->SetParent(NULL);
74 }
initial.commit09911bf2008-07-26 23:55:2975}
76
77/////////////////////////////////////////////////////////////////////////////
78//
79// View - sizing
80//
81/////////////////////////////////////////////////////////////////////////////
82
[email protected]0d8ea702008-10-14 17:03:0783gfx::Rect View::GetBounds(PositionMirroringSettings settings) const {
84 gfx::Rect bounds(bounds_);
initial.commit09911bf2008-07-26 23:55:2985
86 // If the parent uses an RTL UI layout and if we are asked to transform the
87 // bounds to their mirrored position if necessary, then we should shift the
88 // rectangle appropriately.
[email protected]0d8ea702008-10-14 17:03:0789 if (settings == APPLY_MIRRORING_TRANSFORMATION)
90 bounds.set_x(MirroredX());
[email protected]4f3dc372009-02-24 00:10:2991
[email protected]0d8ea702008-10-14 17:03:0792 return bounds;
initial.commit09911bf2008-07-26 23:55:2993}
94
[email protected]6f3bb6c2008-09-17 22:25:3395// y(), width() and height() are agnostic to the RTL UI layout of the
96// parent view. x(), on the other hand, is not.
initial.commit09911bf2008-07-26 23:55:2997int View::GetX(PositionMirroringSettings settings) const {
[email protected]80f8b9f2008-10-16 18:17:4798 return settings == IGNORE_MIRRORING_TRANSFORMATION ? x() : MirroredX();
initial.commit09911bf2008-07-26 23:55:2999}
100
[email protected]80f8b9f2008-10-16 18:17:47101void View::SetBounds(const gfx::Rect& bounds) {
102 if (bounds == bounds_)
initial.commit09911bf2008-07-26 23:55:29103 return;
initial.commit09911bf2008-07-26 23:55:29104
[email protected]80f8b9f2008-10-16 18:17:47105 gfx::Rect prev = bounds_;
initial.commit09911bf2008-07-26 23:55:29106 bounds_ = bounds;
initial.commit09911bf2008-07-26 23:55:29107 DidChangeBounds(prev, bounds_);
108
109 RootView* root = GetRootView();
110 if (root) {
[email protected]80f8b9f2008-10-16 18:17:47111 bool size_changed = prev.size() != bounds_.size();
112 bool position_changed = prev.origin() != bounds_.origin();
initial.commit09911bf2008-07-26 23:55:29113 if (size_changed || position_changed)
114 root->ViewBoundsChanged(this, size_changed, position_changed);
115 }
116}
117
[email protected]80f8b9f2008-10-16 18:17:47118gfx::Rect View::GetLocalBounds(bool include_border) const {
[email protected]9a3f0ac22008-11-14 03:24:02119 if (include_border || !border_.get())
[email protected]80f8b9f2008-10-16 18:17:47120 return gfx::Rect(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:29121
[email protected]80f8b9f2008-10-16 18:17:47122 gfx::Insets insets;
123 border_->GetInsets(&insets);
124 return gfx::Rect(insets.left(), insets.top(),
[email protected]4a8d3272009-03-10 19:15:08125 std::max(0, width() - insets.width()),
126 std::max(0, height() - insets.height()));
initial.commit09911bf2008-07-26 23:55:29127}
128
[email protected]0a1d36b22008-10-17 19:33:09129gfx::Point View::GetPosition() const {
130 return gfx::Point(GetX(APPLY_MIRRORING_TRANSFORMATION), y());
initial.commit09911bf2008-07-26 23:55:29131}
132
[email protected]154f8bc2008-10-15 18:02:30133gfx::Size View::GetPreferredSize() {
134 if (layout_manager_.get())
135 return layout_manager_->GetPreferredSize(this);
136 return gfx::Size();
initial.commit09911bf2008-07-26 23:55:29137}
138
139void View::SizeToPreferredSize() {
[email protected]154f8bc2008-10-15 18:02:30140 gfx::Size prefsize = GetPreferredSize();
141 if ((prefsize.width() != width()) || (prefsize.height() != height()))
142 SetBounds(x(), y(), prefsize.width(), prefsize.height());
initial.commit09911bf2008-07-26 23:55:29143}
144
[email protected]7ccc52b72009-05-08 21:09:11145void View::PreferredSizeChanged() {
146 if (parent_)
147 parent_->ChildPreferredSizeChanged(this);
148}
149
[email protected]154f8bc2008-10-15 18:02:30150gfx::Size View::GetMinimumSize() {
151 return GetPreferredSize();
initial.commit09911bf2008-07-26 23:55:29152}
153
154int View::GetHeightForWidth(int w) {
155 if (layout_manager_.get())
156 return layout_manager_->GetPreferredHeightForWidth(this, w);
[email protected]154f8bc2008-10-15 18:02:30157 return GetPreferredSize().height();
initial.commit09911bf2008-07-26 23:55:29158}
159
[email protected]80f8b9f2008-10-16 18:17:47160void View::DidChangeBounds(const gfx::Rect& previous,
161 const gfx::Rect& current) {
162 Layout();
initial.commit09911bf2008-07-26 23:55:29163}
164
165void View::ScrollRectToVisible(int x, int y, int width, int height) {
166 View* parent = GetParent();
167
168 // We must take RTL UI mirroring into account when adjusting the position of
169 // the region.
170 if (parent)
171 parent->ScrollRectToVisible(
[email protected]6f3bb6c2008-09-17 22:25:33172 GetX(APPLY_MIRRORING_TRANSFORMATION) + x, View::y() + y, width, height);
initial.commit09911bf2008-07-26 23:55:29173}
174
175/////////////////////////////////////////////////////////////////////////////
176//
177// View - layout
178//
179/////////////////////////////////////////////////////////////////////////////
180
181void View::Layout() {
182 // Layout child Views
183 if (layout_manager_.get()) {
184 layout_manager_->Layout(this);
185 SchedulePaint();
[email protected]d5c4f382009-02-24 21:47:36186 // TODO(beng): We believe the right thing to do here is return since the
187 // layout manager should be handling things, but it causes
188 // regressions (missing options from Options dialog and a hang
189 // in interactive_ui_tests).
initial.commit09911bf2008-07-26 23:55:29190 }
191
192 // Lay out contents of child Views
193 int child_count = GetChildViewCount();
194 for (int i = 0; i < child_count; ++i) {
195 View* child = GetChildViewAt(i);
196 child->Layout();
197 }
198}
199
200LayoutManager* View::GetLayoutManager() const {
201 return layout_manager_.get();
202}
203
204void View::SetLayoutManager(LayoutManager* layout_manager) {
205 if (layout_manager_.get()) {
206 layout_manager_->Uninstalled(this);
207 }
208 layout_manager_.reset(layout_manager);
209 if (layout_manager_.get()) {
210 layout_manager_->Installed(this);
211 }
212}
213
[email protected]1eb89e82008-08-15 12:27:03214bool View::UILayoutIsRightToLeft() const {
215 return (ui_mirroring_is_enabled_for_rtl_languages_ &&
216 l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT);
217}
218
initial.commit09911bf2008-07-26 23:55:29219////////////////////////////////////////////////////////////////////////////////
220//
221// View - Right-to-left UI layout
222//
223////////////////////////////////////////////////////////////////////////////////
224
225inline int View::MirroredX() const {
[email protected]63329982008-10-10 21:56:57226 // TODO(beng): reimplement in terms of MirroredLeftPointForRect.
initial.commit09911bf2008-07-26 23:55:29227 View* parent = GetParent();
[email protected]80f8b9f2008-10-16 18:17:47228 if (parent && parent->UILayoutIsRightToLeft())
229 return parent->width() - x() - width();
230 return x();
initial.commit09911bf2008-07-26 23:55:29231}
232
233int View::MirroredLeftPointForRect(const gfx::Rect& bounds) const {
234 if (!UILayoutIsRightToLeft()) {
235 return bounds.x();
236 }
[email protected]6f3bb6c2008-09-17 22:25:33237 return width() - bounds.x() - bounds.width();
initial.commit09911bf2008-07-26 23:55:29238}
239
240////////////////////////////////////////////////////////////////////////////////
241//
242// View - states
243//
244////////////////////////////////////////////////////////////////////////////////
245
246bool View::IsEnabled() const {
247 return enabled_;
248}
249
250void View::SetEnabled(bool state) {
251 if (enabled_ != state) {
252 enabled_ = state;
253 SchedulePaint();
254 }
255}
256
257bool View::IsFocusable() const {
258 return focusable_ && enabled_ && is_visible_;
259}
260
261void View::SetFocusable(bool focusable) {
262 focusable_ = focusable;
263}
264
initial.commit09911bf2008-07-26 23:55:29265bool View::HasFocus() {
initial.commit09911bf2008-07-26 23:55:29266 FocusManager* focus_manager = GetFocusManager();
267 if (focus_manager)
268 return focus_manager->GetFocusedView() == this;
269 return false;
270}
271
272void View::SetHotTracked(bool flag) {
273}
274
275/////////////////////////////////////////////////////////////////////////////
276//
277// View - painting
278//
279/////////////////////////////////////////////////////////////////////////////
280
[email protected]0a1d36b22008-10-17 19:33:09281void View::SchedulePaint(const gfx::Rect& r, bool urgent) {
282 if (!IsVisible())
initial.commit09911bf2008-07-26 23:55:29283 return;
initial.commit09911bf2008-07-26 23:55:29284
285 if (parent_) {
286 // Translate the requested paint rect to the parent's coordinate system
287 // then pass this notification up to the parent.
[email protected]0a1d36b22008-10-17 19:33:09288 gfx::Rect paint_rect = r;
289 paint_rect.Offset(GetPosition());
initial.commit09911bf2008-07-26 23:55:29290 parent_->SchedulePaint(paint_rect, urgent);
291 }
292}
293
294void View::SchedulePaint() {
[email protected]0a1d36b22008-10-17 19:33:09295 SchedulePaint(GetLocalBounds(true), false);
initial.commit09911bf2008-07-26 23:55:29296}
297
298void View::SchedulePaint(int x, int y, int w, int h) {
[email protected]0a1d36b22008-10-17 19:33:09299 SchedulePaint(gfx::Rect(x, y, w, h), false);
initial.commit09911bf2008-07-26 23:55:29300}
301
[email protected]82522512009-05-15 07:37:29302void View::Paint(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29303 PaintBackground(canvas);
304 PaintFocusBorder(canvas);
305 PaintBorder(canvas);
306}
307
[email protected]82522512009-05-15 07:37:29308void View::PaintBackground(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02309 if (background_.get())
initial.commit09911bf2008-07-26 23:55:29310 background_->Paint(canvas, this);
311}
312
[email protected]82522512009-05-15 07:37:29313void View::PaintBorder(gfx::Canvas* canvas) {
[email protected]9a3f0ac22008-11-14 03:24:02314 if (border_.get())
initial.commit09911bf2008-07-26 23:55:29315 border_->Paint(*this, canvas);
316}
317
[email protected]82522512009-05-15 07:37:29318void View::PaintFocusBorder(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29319 if (HasFocus() && IsFocusable())
[email protected]6f3bb6c2008-09-17 22:25:33320 canvas->DrawFocusRect(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:29321}
322
[email protected]82522512009-05-15 07:37:29323void View::PaintChildren(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29324 int i, c;
325 for (i = 0, c = GetChildViewCount(); i < c; ++i) {
326 View* child = GetChildViewAt(i);
327 if (!child) {
328 NOTREACHED() << "Should not have a NULL child View for index in bounds";
329 continue;
330 }
331 child->ProcessPaint(canvas);
332 }
333}
334
[email protected]82522512009-05-15 07:37:29335void View::ProcessPaint(gfx::Canvas* canvas) {
initial.commit09911bf2008-07-26 23:55:29336 if (!IsVisible()) {
337 return;
338 }
339
340 // We're going to modify the canvas, save it's state first.
341 canvas->save();
342
343 // Paint this View and its children, setting the clip rect to the bounds
344 // of this View and translating the origin to the local bounds' top left
345 // point.
346 //
347 // Note that the X (or left) position we pass to ClipRectInt takes into
348 // consideration whether or not the view uses a right-to-left layout so that
349 // we paint our view in its mirrored position if need be.
[email protected]80f8b9f2008-10-16 18:17:47350 if (canvas->ClipRectInt(MirroredX(), y(), width(), height())) {
initial.commit09911bf2008-07-26 23:55:29351 // Non-empty clip, translate the graphics such that 0,0 corresponds to
352 // where this view is located (related to its parent).
[email protected]80f8b9f2008-10-16 18:17:47353 canvas->TranslateInt(MirroredX(), y());
initial.commit09911bf2008-07-26 23:55:29354
355 // Save the state again, so that any changes don't effect PaintChildren.
356 canvas->save();
357
358 // If the View we are about to paint requested the canvas to be flipped, we
359 // should change the transform appropriately.
360 bool flip_canvas = FlipCanvasOnPaintForRTLUI();
361 if (flip_canvas) {
[email protected]6f3bb6c2008-09-17 22:25:33362 canvas->TranslateInt(width(), 0);
initial.commit09911bf2008-07-26 23:55:29363 canvas->ScaleInt(-1, 1);
364 canvas->save();
365 }
366
367 Paint(canvas);
368
369 // We must undo the canvas mirroring once the View is done painting so that
370 // we don't pass the canvas with the mirrored transform to Views that
371 // didn't request the canvas to be flipped.
372 if (flip_canvas) {
373 canvas->restore();
374 }
375 canvas->restore();
376 PaintChildren(canvas);
377 }
378
379 // Restore the canvas's original transform.
380 canvas->restore();
381}
382
383void View::PaintNow() {
384 if (!IsVisible()) {
385 return;
386 }
387
388 View* view = GetParent();
389 if (view)
390 view->PaintNow();
391}
392
initial.commit09911bf2008-07-26 23:55:29393gfx::Insets View::GetInsets() const {
initial.commit09911bf2008-07-26 23:55:29394 gfx::Insets insets;
[email protected]9a3f0ac22008-11-14 03:24:02395 if (border_.get())
396 border_->GetInsets(&insets);
initial.commit09911bf2008-07-26 23:55:29397 return insets;
398}
399
400void View::SetContextMenuController(ContextMenuController* menu_controller) {
401 context_menu_controller_ = menu_controller;
402}
403
[email protected]042811c2008-10-31 21:31:34404void View::ShowContextMenu(int x, int y, bool is_mouse_gesture) {
405 if (!context_menu_controller_)
406 return;
407
[email protected]4f3dc372009-02-24 00:10:29408 context_menu_controller_->ShowContextMenu(this, x, y, is_mouse_gesture);
[email protected]042811c2008-10-31 21:31:34409}
410
initial.commit09911bf2008-07-26 23:55:29411/////////////////////////////////////////////////////////////////////////////
412//
413// View - tree
414//
415/////////////////////////////////////////////////////////////////////////////
416
417bool View::ProcessMousePressed(const MouseEvent& e, DragInfo* drag_info) {
418 const bool enabled = enabled_;
419 int drag_operations;
[email protected]613b8062008-10-14 23:45:09420 if (enabled && e.IsOnlyLeftMouseButton() && HitTest(e.location()))
[email protected]6f3bb6c2008-09-17 22:25:33421 drag_operations = GetDragOperations(e.x(), e.y());
initial.commit09911bf2008-07-26 23:55:29422 else
423 drag_operations = 0;
[email protected]6c50fc52009-03-26 19:58:51424 ContextMenuController* context_menu_controller =
425 e.IsRightMouseButton() ? context_menu_controller_ : 0;
initial.commit09911bf2008-07-26 23:55:29426
427 const bool result = OnMousePressed(e);
428 // WARNING: we may have been deleted, don't use any View variables;
429
430 if (!enabled)
431 return result;
432
433 if (drag_operations != DragDropTypes::DRAG_NONE) {
[email protected]6f3bb6c2008-09-17 22:25:33434 drag_info->PossibleDrag(e.x(), e.y());
initial.commit09911bf2008-07-26 23:55:29435 return true;
436 }
437 return !!context_menu_controller || result;
438}
439
440bool View::ProcessMouseDragged(const MouseEvent& e, DragInfo* drag_info) {
441 // Copy the field, that way if we're deleted after drag and drop no harm is
442 // done.
443 ContextMenuController* context_menu_controller = context_menu_controller_;
444 const bool possible_drag = drag_info->possible_drag;
[email protected]6f3bb6c2008-09-17 22:25:33445 if (possible_drag && ExceededDragThreshold(drag_info->start_x - e.x(),
446 drag_info->start_y - e.y())) {
initial.commit09911bf2008-07-26 23:55:29447 DoDrag(e, drag_info->start_x, drag_info->start_y);
448 } else {
449 if (OnMouseDragged(e))
450 return true;
451 // Fall through to return value based on context menu controller.
452 }
453 // WARNING: we may have been deleted.
454 return (context_menu_controller != NULL) || possible_drag;
455}
456
457void View::ProcessMouseReleased(const MouseEvent& e, bool canceled) {
458 if (!canceled && context_menu_controller_ && e.IsOnlyRightMouseButton()) {
459 // Assume that if there is a context menu controller we won't be deleted
460 // from mouse released.
[email protected]96b667d2008-10-14 20:58:44461 gfx::Point location(e.location());
initial.commit09911bf2008-07-26 23:55:29462 OnMouseReleased(e, canceled);
[email protected]464fdb32009-03-19 20:25:44463 if (HitTest(location)) {
464 ConvertPointToScreen(this, &location);
465 ShowContextMenu(location.x(), location.y(), true);
466 }
initial.commit09911bf2008-07-26 23:55:29467 } else {
468 OnMouseReleased(e, canceled);
469 }
470 // WARNING: we may have been deleted.
471}
472
initial.commit09911bf2008-07-26 23:55:29473void View::AddChildView(View* v) {
[email protected]0d52b2302009-05-11 23:50:55474 AddChildView(static_cast<int>(child_views_.size()), v);
initial.commit09911bf2008-07-26 23:55:29475}
476
477void View::AddChildView(int index, View* v) {
initial.commit09911bf2008-07-26 23:55:29478 // Remove the view from its current parent if any.
479 if (v->GetParent())
480 v->GetParent()->RemoveChildView(v);
481
[email protected]0d52b2302009-05-11 23:50:55482 // Sets the prev/next focus views.
483 InitFocusSiblings(v, index);
initial.commit09911bf2008-07-26 23:55:29484
485 // Let's insert the view.
486 child_views_.insert(child_views_.begin() + index, v);
487 v->SetParent(this);
488
489 for (View* p = this; p; p = p->GetParent()) {
490 p->ViewHierarchyChangedImpl(false, true, this, v);
491 }
492 v->PropagateAddNotifications(this, v);
493 UpdateTooltip();
494 RootView* root = GetRootView();
495 if (root)
496 RegisterChildrenForVisibleBoundsNotification(root, v);
497
498 if (layout_manager_.get())
499 layout_manager_->ViewAdded(this, v);
500}
501
502View* View::GetChildViewAt(int index) const {
503 return index < GetChildViewCount() ? child_views_[index] : NULL;
504}
505
506int View::GetChildViewCount() const {
507 return static_cast<int>(child_views_.size());
508}
509
510void View::RemoveChildView(View* a_view) {
511 DoRemoveChildView(a_view, true, true, false);
512}
513
514void View::RemoveAllChildViews(bool delete_views) {
515 ViewList::iterator iter;
516 while ((iter = child_views_.begin()) != child_views_.end()) {
517 DoRemoveChildView(*iter, false, false, delete_views);
518 }
519 UpdateTooltip();
520}
521
522void View::DoRemoveChildView(View* a_view,
523 bool update_focus_cycle,
524 bool update_tool_tip,
525 bool delete_removed_view) {
526#ifndef NDEBUG
527 DCHECK(!IsProcessingPaint()) << "Should not be removing a child view " <<
528 "during a paint, this will seriously " <<
529 "mess things up!";
530#endif
531 DCHECK(a_view);
532 const ViewList::iterator i = find(child_views_.begin(),
533 child_views_.end(),
534 a_view);
535 if (i != child_views_.end()) {
[email protected]0d52b2302009-05-11 23:50:55536 if (update_focus_cycle) {
initial.commit09911bf2008-07-26 23:55:29537 // Let's remove the view from the focus traversal.
538 View* next_focusable = a_view->next_focusable_view_;
539 View* prev_focusable = a_view->previous_focusable_view_;
540 if (prev_focusable)
541 prev_focusable->next_focusable_view_ = next_focusable;
542 if (next_focusable)
543 next_focusable->previous_focusable_view_ = prev_focusable;
544 }
545
546 RootView* root = GetRootView();
547 if (root)
548 UnregisterChildrenForVisibleBoundsNotification(root, a_view);
549 a_view->PropagateRemoveNotifications(this);
550 a_view->SetParent(NULL);
551
552 if (delete_removed_view && a_view->IsParentOwned())
553 delete a_view;
554
555 child_views_.erase(i);
556 }
557
558 if (update_tool_tip)
559 UpdateTooltip();
560
561 if (layout_manager_.get())
562 layout_manager_->ViewRemoved(this, a_view);
563}
564
565void View::PropagateRemoveNotifications(View* parent) {
566 int i, c;
567 for (i = 0, c = GetChildViewCount(); i < c; ++i) {
568 GetChildViewAt(i)->PropagateRemoveNotifications(parent);
569 }
570
571 View *t;
572 for (t = this; t; t = t->GetParent()) {
573 t->ViewHierarchyChangedImpl(true, false, parent, this);
574 }
575}
576
577void View::PropagateAddNotifications(View* parent, View* child) {
578 int i, c;
579 for (i = 0, c = GetChildViewCount(); i < c; ++i) {
580 GetChildViewAt(i)->PropagateAddNotifications(parent, child);
581 }
582 ViewHierarchyChangedImpl(true, true, parent, child);
583}
584
[email protected]32670b02009-03-03 00:28:00585void View::ThemeChanged() {
586 int c = GetChildViewCount();
587 for (int i = c - 1; i >= 0; --i)
588 GetChildViewAt(i)->ThemeChanged();
589}
590
initial.commit09911bf2008-07-26 23:55:29591#ifndef NDEBUG
592bool View::IsProcessingPaint() const {
593 return GetParent() && GetParent()->IsProcessingPaint();
594}
595#endif
596
[email protected]f704ee72008-11-10 21:31:59597gfx::Point View::GetKeyboardContextMenuLocation() {
598 gfx::Rect vis_bounds = GetVisibleBounds();
599 gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2,
600 vis_bounds.y() + vis_bounds.height() / 2);
601 ConvertPointToScreen(this, &screen_point);
602 return screen_point;
603}
604
[email protected]82739cf2008-09-16 00:37:56605bool View::HasHitTestMask() const {
606 return false;
607}
608
609void View::GetHitTestMask(gfx::Path* mask) const {
610 DCHECK(mask);
611}
612
[email protected]bb515ed2009-01-15 00:53:43613void View::ViewHierarchyChanged(bool is_add,
614 View* parent,
615 View* child) {
initial.commit09911bf2008-07-26 23:55:29616}
617
618void View::ViewHierarchyChangedImpl(bool register_accelerators,
[email protected]bb515ed2009-01-15 00:53:43619 bool is_add,
620 View* parent,
621 View* child) {
initial.commit09911bf2008-07-26 23:55:29622 if (register_accelerators) {
623 if (is_add) {
624 // If you get this registration, you are part of a subtree that has been
625 // added to the view hierarchy.
626 RegisterAccelerators();
627 } else {
628 if (child == this)
629 UnregisterAccelerators();
630 }
631 }
632
633 ViewHierarchyChanged(is_add, parent, child);
634}
635
636void View::PropagateVisibilityNotifications(View* start, bool is_visible) {
637 int i, c;
638 for (i = 0, c = GetChildViewCount(); i < c; ++i) {
639 GetChildViewAt(i)->PropagateVisibilityNotifications(start, is_visible);
640 }
641 VisibilityChanged(start, is_visible);
642}
643
644void View::VisibilityChanged(View* starting_from, bool is_visible) {
645}
646
initial.commit09911bf2008-07-26 23:55:29647void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) {
648 if (notify_when_visible_bounds_in_root_changes_ == value)
649 return;
650 notify_when_visible_bounds_in_root_changes_ = value;
651 RootView* root = GetRootView();
652 if (root) {
653 if (value)
654 root->RegisterViewForVisibleBoundsNotification(this);
655 else
656 root->UnregisterViewForVisibleBoundsNotification(this);
657 }
658}
659
660bool View::GetNotifyWhenVisibleBoundsInRootChanges() {
661 return notify_when_visible_bounds_in_root_changes_;
662}
663
[email protected]0d52b2302009-05-11 23:50:55664View* View::GetViewForPoint(const gfx::Point& point) {
initial.commit09911bf2008-07-26 23:55:29665 // Walk the child Views recursively looking for the View that most
666 // tightly encloses the specified point.
667 for (int i = GetChildViewCount() - 1 ; i >= 0 ; --i) {
668 View* child = GetChildViewAt(i);
[email protected]82739cf2008-09-16 00:37:56669 if (!child->IsVisible())
initial.commit09911bf2008-07-26 23:55:29670 continue;
[email protected]82739cf2008-09-16 00:37:56671
[email protected]96b667d2008-10-14 20:58:44672 gfx::Point point_in_child_coords(point);
[email protected]82739cf2008-09-16 00:37:56673 View::ConvertPointToView(this, child, &point_in_child_coords);
[email protected]613b8062008-10-14 23:45:09674 if (child->HitTest(point_in_child_coords))
[email protected]0d52b2302009-05-11 23:50:55675 return child->GetViewForPoint(point_in_child_coords);
initial.commit09911bf2008-07-26 23:55:29676 }
677 return this;
678}
679
[email protected]a0dde122008-11-21 20:51:20680Widget* View::GetWidget() const {
681 // The root view holds a reference to this view hierarchy's Widget.
682 return parent_ ? parent_->GetWidget() : NULL;
initial.commit09911bf2008-07-26 23:55:29683}
684
[email protected]cd8c47902009-04-30 20:55:35685Window* View::GetWindow() const {
686 Widget* widget = GetWidget();
687 return widget ? widget->GetWindow() : NULL;
688}
689
initial.commit09911bf2008-07-26 23:55:29690// Get the containing RootView
691RootView* View::GetRootView() {
[email protected]a0dde122008-11-21 20:51:20692 Widget* widget = GetWidget();
693 return widget ? widget->GetRootView() : NULL;
initial.commit09911bf2008-07-26 23:55:29694}
695
696View* View::GetViewByID(int id) const {
697 if (id == id_)
698 return const_cast<View*>(this);
699
700 int view_count = GetChildViewCount();
701 for (int i = 0; i < view_count; ++i) {
702 View* child = GetChildViewAt(i);
703 View* view = child->GetViewByID(id);
704 if (view)
705 return view;
706 }
707 return NULL;
708}
709
710void View::GetViewsWithGroup(int group_id, std::vector<View*>* out) {
711 if (group_ == group_id)
712 out->push_back(this);
713
714 int view_count = GetChildViewCount();
715 for (int i = 0; i < view_count; ++i)
716 GetChildViewAt(i)->GetViewsWithGroup(group_id, out);
717}
718
719View* View::GetSelectedViewForGroup(int group_id) {
720 std::vector<View*> views;
721 GetRootView()->GetViewsWithGroup(group_id, &views);
722 if (views.size() > 0)
723 return views[0];
724 else
725 return NULL;
726}
727
728void View::SetID(int id) {
729 id_ = id;
730}
731
732int View::GetID() const {
733 return id_;
734}
735
736void View::SetGroup(int gid) {
737 group_ = gid;
738}
739
740int View::GetGroup() const {
741 return group_;
742}
743
744void View::SetParent(View* parent) {
745 if (parent != parent_) {
746 parent_ = parent;
747 }
748}
749
750bool View::IsParentOf(View* v) const {
751 DCHECK(v);
752 View* parent = v->GetParent();
753 while (parent) {
754 if (this == parent)
755 return true;
756 parent = parent->GetParent();
757 }
758 return false;
759}
760
761int View::GetChildIndex(View* v) const {
762 for (int i = 0; i < GetChildViewCount(); i++) {
763 if (v == GetChildViewAt(i))
764 return i;
765 }
766 return -1;
767}
768
769///////////////////////////////////////////////////////////////////////////////
770//
771// View - focus
772//
773///////////////////////////////////////////////////////////////////////////////
774
775View* View::GetNextFocusableView() {
776 return next_focusable_view_;
777}
778
779View* View::GetPreviousFocusableView() {
780 return previous_focusable_view_;
781}
782
783void View::SetNextFocusableView(View* view) {
784 view->previous_focusable_view_ = this;
785 next_focusable_view_ = view;
786}
787
788void View::InitFocusSiblings(View* v, int index) {
789 int child_count = static_cast<int>(child_views_.size());
790
791 if (child_count == 0) {
792 v->next_focusable_view_ = NULL;
793 v->previous_focusable_view_ = NULL;
794 } else {
795 if (index == child_count) {
796 // We are inserting at the end, but the end of the child list may not be
797 // the last focusable element. Let's try to find an element with no next
798 // focusable element to link to.
799 View* last_focusable_view = NULL;
800 for (std::vector<View*>::iterator iter = child_views_.begin();
801 iter != child_views_.end(); ++iter) {
802 if (!(*iter)->next_focusable_view_) {
803 last_focusable_view = *iter;
804 break;
805 }
806 }
807 if (last_focusable_view == NULL) {
808 // Hum... there is a cycle in the focus list. Let's just insert ourself
809 // after the last child.
810 View* prev = child_views_[index - 1];
811 v->previous_focusable_view_ = prev;
812 v->next_focusable_view_ = prev->next_focusable_view_;
813 prev->next_focusable_view_->previous_focusable_view_ = v;
814 prev->next_focusable_view_ = v;
815 } else {
816 last_focusable_view->next_focusable_view_ = v;
817 v->next_focusable_view_ = NULL;
818 v->previous_focusable_view_ = last_focusable_view;
819 }
820 } else {
821 View* prev = child_views_[index]->GetPreviousFocusableView();
822 v->previous_focusable_view_ = prev;
823 v->next_focusable_view_ = child_views_[index];
824 if (prev)
825 prev->next_focusable_view_ = v;
826 child_views_[index]->previous_focusable_view_ = v;
827 }
828 }
829}
830
831#ifndef NDEBUG
832void View::PrintViewHierarchy() {
833 PrintViewHierarchyImp(0);
834}
835
836void View::PrintViewHierarchyImp(int indent) {
837 std::wostringstream buf;
838 int ind = indent;
839 while (ind-- > 0)
840 buf << L' ';
841 buf << UTF8ToWide(GetClassName());
842 buf << L' ';
843 buf << GetID();
844 buf << L' ';
[email protected]80f8b9f2008-10-16 18:17:47845 buf << bounds_.x() << L"," << bounds_.y() << L",";
846 buf << bounds_.right() << L"," << bounds_.bottom();
initial.commit09911bf2008-07-26 23:55:29847 buf << L' ';
848 buf << this;
849
850 LOG(INFO) << buf.str();
851 std::cout << buf.str() << std::endl;
852
853 for (int i = 0; i < GetChildViewCount(); ++i) {
854 GetChildViewAt(i)->PrintViewHierarchyImp(indent + 2);
855 }
856}
857
858
859void View::PrintFocusHierarchy() {
860 PrintFocusHierarchyImp(0);
861}
862
863void View::PrintFocusHierarchyImp(int indent) {
864 std::wostringstream buf;
865 int ind = indent;
866 while (ind-- > 0)
867 buf << L' ';
868 buf << UTF8ToWide(GetClassName());
869 buf << L' ';
870 buf << GetID();
871 buf << L' ';
872 buf << GetClassName().c_str();
873 buf << L' ';
874 buf << this;
875
876 LOG(INFO) << buf.str();
877 std::cout << buf.str() << std::endl;
878
879 if (GetChildViewCount() > 0)
880 GetChildViewAt(0)->PrintFocusHierarchyImp(indent + 2);
881
882 View* v = GetNextFocusableView();
883 if (v)
884 v->PrintFocusHierarchyImp(indent);
885}
886#endif
887
888////////////////////////////////////////////////////////////////////////////////
889//
890// View - accelerators
891//
892////////////////////////////////////////////////////////////////////////////////
893
894void View::AddAccelerator(const Accelerator& accelerator) {
895 if (!accelerators_.get())
896 accelerators_.reset(new std::vector<Accelerator>());
897 accelerators_->push_back(accelerator);
898 RegisterAccelerators();
899}
900
[email protected]e8e0f362008-11-08 01:13:25901void View::RemoveAccelerator(const Accelerator& accelerator) {
902 std::vector<Accelerator>::iterator iter;
903 if (!accelerators_.get() ||
904 ((iter = std::find(accelerators_->begin(), accelerators_->end(),
905 accelerator)) == accelerators_->end())) {
906 NOTREACHED() << "Removing non-existing accelerator";
907 return;
908 }
909
910 accelerators_->erase(iter);
911 RootView* root_view = GetRootView();
912 if (!root_view) {
913 // We are not part of a view hierarchy, so there is nothing to do as we
914 // removed ourselves from accelerators_, we won't be registered when added
915 // to one.
916 return;
917 }
918
[email protected]f3735c5d2009-03-19 17:26:23919 // TODO(port): Fix this once we have a FocusManger for Linux.
920#if defined(OS_WIN)
[email protected]e8e0f362008-11-08 01:13:25921 FocusManager* focus_manager = GetFocusManager();
922 if (focus_manager) {
923 // We may not have a FocusManager if the window containing us is being
924 // closed, in which case the FocusManager is being deleted so there is
925 // nothing to unregister.
926 focus_manager->UnregisterAccelerator(accelerator, this);
927 }
[email protected]f3735c5d2009-03-19 17:26:23928#endif
[email protected]e8e0f362008-11-08 01:13:25929}
930
initial.commit09911bf2008-07-26 23:55:29931void View::ResetAccelerators() {
932 if (accelerators_.get()) {
933 UnregisterAccelerators();
934 accelerators_->clear();
935 accelerators_.reset();
936 }
937}
938
939void View::RegisterAccelerators() {
940 if (!accelerators_.get())
941 return;
942
943 RootView* root_view = GetRootView();
944 if (!root_view) {
945 // We are not yet part of a view hierarchy, we'll register ourselves once
946 // added to one.
947 return;
948 }
[email protected]f3735c5d2009-03-19 17:26:23949
950 // TODO(port): Fix this once we have a FocusManger for Linux.
951#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29952 FocusManager* focus_manager = GetFocusManager();
953 if (!focus_manager) {
954 // Some crash reports seem to show that we may get cases where we have no
955 // focus manager (see bug #1291225). This should never be the case, just
956 // making sure we don't crash.
957 NOTREACHED();
958 return;
959 }
960 for (std::vector<Accelerator>::const_iterator iter = accelerators_->begin();
961 iter != accelerators_->end(); ++iter) {
962 focus_manager->RegisterAccelerator(*iter, this);
963 }
[email protected]f3735c5d2009-03-19 17:26:23964#endif
initial.commit09911bf2008-07-26 23:55:29965}
966
967void View::UnregisterAccelerators() {
968 if (!accelerators_.get())
969 return;
970
971 RootView* root_view = GetRootView();
972 if (root_view) {
[email protected]f3735c5d2009-03-19 17:26:23973 // TODO(port): Fix this once we have a FocusManger for Linux.
974#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29975 FocusManager* focus_manager = GetFocusManager();
976 if (focus_manager) {
977 // We may not have a FocusManager if the window containing us is being
978 // closed, in which case the FocusManager is being deleted so there is
979 // nothing to unregister.
980 focus_manager->UnregisterAccelerators(this);
981 }
[email protected]f3735c5d2009-03-19 17:26:23982#endif
initial.commit09911bf2008-07-26 23:55:29983 }
984}
985
initial.commit09911bf2008-07-26 23:55:29986int View::GetDragOperations(int press_x, int press_y) {
987 if (!drag_controller_)
988 return DragDropTypes::DRAG_NONE;
989 return drag_controller_->GetDragOperations(this, press_x, press_y);
990}
991
992void View::WriteDragData(int press_x, int press_y, OSExchangeData* data) {
993 DCHECK(drag_controller_);
994 drag_controller_->WriteDragData(this, press_x, press_y, data);
995}
996
997void View::OnDragDone() {
998}
999
1000bool View::InDrag() {
1001 RootView* root_view = GetRootView();
1002 return root_view ? (root_view->GetDragView() == this) : false;
1003}
1004
initial.commit09911bf2008-07-26 23:55:291005// static
[email protected]bb515ed2009-01-15 00:53:431006void View::ConvertPointToView(const View* src,
1007 const View* dst,
1008 gfx::Point* point) {
initial.commit09911bf2008-07-26 23:55:291009 ConvertPointToView(src, dst, point, true);
1010}
1011
1012// static
[email protected]bb515ed2009-01-15 00:53:431013void View::ConvertPointToView(const View* src,
1014 const View* dst,
1015 gfx::Point* point,
initial.commit09911bf2008-07-26 23:55:291016 bool try_other_direction) {
1017 // src can be NULL
1018 DCHECK(dst);
1019 DCHECK(point);
1020
[email protected]bb515ed2009-01-15 00:53:431021 const View* v;
initial.commit09911bf2008-07-26 23:55:291022 gfx::Point offset;
1023
1024 for (v = dst; v && v != src; v = v->GetParent()) {
1025 offset.SetPoint(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION),
[email protected]6f3bb6c2008-09-17 22:25:331026 offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291027 }
1028
1029 // The source was not found. The caller wants a conversion
1030 // from a view to a transitive parent.
1031 if (src && v == NULL && try_other_direction) {
1032 gfx::Point p;
1033 // note: try_other_direction is force to FALSE so we don't
1034 // end up in an infinite recursion should both src and dst
1035 // are not parented.
1036 ConvertPointToView(dst, src, &p, false);
1037 // since the src and dst are inverted, p should also be negated
1038 point->SetPoint(point->x() - p.x(), point->y() - p.y());
1039 } else {
1040 point->SetPoint(point->x() - offset.x(), point->y() - offset.y());
1041
1042 // If src is NULL, sp is in the screen coordinate system
1043 if (src == NULL) {
[email protected]a0dde122008-11-21 20:51:201044 Widget* widget = dst->GetWidget();
1045 if (widget) {
[email protected]3b680a82008-12-17 02:03:231046 gfx::Rect b;
[email protected]a0dde122008-11-21 20:51:201047 widget->GetBounds(&b, false);
[email protected]3b680a82008-12-17 02:03:231048 point->SetPoint(point->x() - b.x(), point->y() - b.y());
initial.commit09911bf2008-07-26 23:55:291049 }
1050 }
1051 }
1052}
1053
1054// static
[email protected]2fb6d462009-02-13 18:40:101055void View::ConvertPointToWidget(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291056 DCHECK(src);
1057 DCHECK(p);
[email protected]96b667d2008-10-14 20:58:441058
[email protected]96b667d2008-10-14 20:58:441059 gfx::Point offset;
[email protected]2fb6d462009-02-13 18:40:101060 for (const View* v = src; v; v = v->GetParent()) {
[email protected]96b667d2008-10-14 20:58:441061 offset.set_x(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION));
1062 offset.set_y(offset.y() + v->y());
initial.commit09911bf2008-07-26 23:55:291063 }
[email protected]96b667d2008-10-14 20:58:441064 p->SetPoint(p->x() + offset.x(), p->y() + offset.y());
initial.commit09911bf2008-07-26 23:55:291065}
1066
1067// static
[email protected]2fb6d462009-02-13 18:40:101068void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) {
[email protected]96b667d2008-10-14 20:58:441069 gfx::Point t;
[email protected]2fb6d462009-02-13 18:40:101070 ConvertPointToWidget(dest, &t);
[email protected]96b667d2008-10-14 20:58:441071 p->SetPoint(p->x() - t.x(), p->y() - t.y());
initial.commit09911bf2008-07-26 23:55:291072}
1073
1074// static
[email protected]2fb6d462009-02-13 18:40:101075void View::ConvertPointToScreen(const View* src, gfx::Point* p) {
initial.commit09911bf2008-07-26 23:55:291076 DCHECK(src);
1077 DCHECK(p);
1078
[email protected]96b667d2008-10-14 20:58:441079 // If the view is not connected to a tree, there's nothing we can do.
[email protected]a0dde122008-11-21 20:51:201080 Widget* widget = src->GetWidget();
1081 if (widget) {
1082 ConvertPointToWidget(src, p);
[email protected]3b680a82008-12-17 02:03:231083 gfx::Rect r;
[email protected]a0dde122008-11-21 20:51:201084 widget->GetBounds(&r, false);
[email protected]3b680a82008-12-17 02:03:231085 p->SetPoint(p->x() + r.x(), p->y() + r.y());
initial.commit09911bf2008-07-26 23:55:291086 }
1087}
1088
1089/////////////////////////////////////////////////////////////////////////////
1090//
1091// View - event handlers
1092//
1093/////////////////////////////////////////////////////////////////////////////
1094
1095bool View::OnMousePressed(const MouseEvent& e) {
1096 return false;
1097}
1098
1099bool View::OnMouseDragged(const MouseEvent& e) {
1100 return false;
1101}
1102
1103void View::OnMouseReleased(const MouseEvent& e, bool canceled) {
1104}
1105
1106void View::OnMouseMoved(const MouseEvent& e) {
1107}
1108
1109void View::OnMouseEntered(const MouseEvent& e) {
1110}
1111
1112void View::OnMouseExited(const MouseEvent& e) {
1113}
1114
1115void View::SetMouseHandler(View *new_mouse_handler) {
1116 // It is valid for new_mouse_handler to be NULL
1117 if (parent_) {
1118 parent_->SetMouseHandler(new_mouse_handler);
1119 }
1120}
1121
1122void View::SetVisible(bool flag) {
1123 if (flag != is_visible_) {
1124 // If the tab is currently visible, schedule paint to
1125 // refresh parent
1126 if (IsVisible()) {
1127 SchedulePaint();
1128 }
1129
1130 is_visible_ = flag;
1131
1132 // This notifies all subviews recursively.
1133 PropagateVisibilityNotifications(this, flag);
1134
1135 // If we are newly visible, schedule paint.
1136 if (IsVisible()) {
1137 SchedulePaint();
1138 }
1139 }
1140}
1141
1142bool View::IsVisibleInRootView() const {
1143 View* parent = GetParent();
1144 if (IsVisible() && parent)
1145 return parent->IsVisibleInRootView();
1146 else
1147 return false;
1148}
1149
initial.commit09911bf2008-07-26 23:55:291150/////////////////////////////////////////////////////////////////////////////
1151//
1152// View - keyboard and focus
1153//
1154/////////////////////////////////////////////////////////////////////////////
1155
1156void View::RequestFocus() {
1157 RootView* rv = GetRootView();
[email protected]830e2062009-02-13 18:27:381158 if (rv && IsFocusable())
initial.commit09911bf2008-07-26 23:55:291159 rv->FocusView(this);
initial.commit09911bf2008-07-26 23:55:291160}
1161
1162void View::WillGainFocus() {
1163}
1164
1165void View::DidGainFocus() {
1166}
1167
1168void View::WillLoseFocus() {
1169}
1170
1171bool View::OnKeyPressed(const KeyEvent& e) {
1172 return false;
1173}
1174
1175bool View::OnKeyReleased(const KeyEvent& e) {
1176 return false;
1177}
1178
1179bool View::OnMouseWheel(const MouseWheelEvent& e) {
1180 return false;
1181}
1182
1183void View::SetDragController(DragController* drag_controller) {
1184 drag_controller_ = drag_controller;
1185}
1186
1187DragController* View::GetDragController() {
1188 return drag_controller_;
1189}
1190
1191bool View::CanDrop(const OSExchangeData& data) {
1192 return false;
1193}
1194
1195void View::OnDragEntered(const DropTargetEvent& event) {
1196}
1197
1198int View::OnDragUpdated(const DropTargetEvent& event) {
1199 return DragDropTypes::DRAG_NONE;
1200}
1201
1202void View::OnDragExited() {
1203}
1204
1205int View::OnPerformDrop(const DropTargetEvent& event) {
1206 return DragDropTypes::DRAG_NONE;
1207}
1208
initial.commit09911bf2008-07-26 23:55:291209// static
1210bool View::ExceededDragThreshold(int delta_x, int delta_y) {
1211 return (abs(delta_x) > GetHorizontalDragThreshold() ||
1212 abs(delta_y) > GetVerticalDragThreshold());
1213}
1214
initial.commit09911bf2008-07-26 23:55:291215// Tooltips -----------------------------------------------------------------
1216bool View::GetTooltipText(int x, int y, std::wstring* tooltip) {
1217 return false;
1218}
1219
[email protected]0a1d36b22008-10-17 19:33:091220bool View::GetTooltipTextOrigin(int x, int y, gfx::Point* loc) {
initial.commit09911bf2008-07-26 23:55:291221 return false;
1222}
1223
1224void View::TooltipTextChanged() {
[email protected]a0dde122008-11-21 20:51:201225 Widget* widget = GetWidget();
1226 if (widget && widget->GetTooltipManager())
1227 widget->GetTooltipManager()->TooltipTextChanged(this);
initial.commit09911bf2008-07-26 23:55:291228}
1229
1230void View::UpdateTooltip() {
[email protected]a0dde122008-11-21 20:51:201231 Widget* widget = GetWidget();
1232 if (widget && widget->GetTooltipManager())
1233 widget->GetTooltipManager()->UpdateTooltip();
initial.commit09911bf2008-07-26 23:55:291234}
1235
1236void View::SetParentOwned(bool f) {
1237 is_parent_owned_ = f;
1238}
1239
1240bool View::IsParentOwned() const {
1241 return is_parent_owned_;
1242}
1243
1244std::string View::GetClassName() const {
1245 return kViewClassName;
1246}
1247
[email protected]5c2b98b2009-03-09 20:55:541248View* View::GetAncestorWithClassName(const std::string& name) {
1249 for (View* view = this; view; view = view->GetParent()) {
1250 if (view->GetClassName() == name)
1251 return view;
1252 }
1253 return NULL;
1254}
1255
initial.commit09911bf2008-07-26 23:55:291256gfx::Rect View::GetVisibleBounds() {
[email protected]b6296fd2009-02-13 17:34:161257 if (!IsVisibleInRootView())
1258 return gfx::Rect();
[email protected]6f3bb6c2008-09-17 22:25:331259 gfx::Rect vis_bounds(0, 0, width(), height());
initial.commit09911bf2008-07-26 23:55:291260 gfx::Rect ancestor_bounds;
1261 View* view = this;
1262 int root_x = 0;
1263 int root_y = 0;
initial.commit09911bf2008-07-26 23:55:291264 while (view != NULL && !vis_bounds.IsEmpty()) {
1265 root_x += view->GetX(APPLY_MIRRORING_TRANSFORMATION);
[email protected]6f3bb6c2008-09-17 22:25:331266 root_y += view->y();
1267 vis_bounds.Offset(view->GetX(APPLY_MIRRORING_TRANSFORMATION), view->y());
initial.commit09911bf2008-07-26 23:55:291268 View* ancestor = view->GetParent();
1269 if (ancestor != NULL) {
[email protected]6f3bb6c2008-09-17 22:25:331270 ancestor_bounds.SetRect(0, 0, ancestor->width(),
1271 ancestor->height());
initial.commit09911bf2008-07-26 23:55:291272 vis_bounds = vis_bounds.Intersect(ancestor_bounds);
[email protected]a0dde122008-11-21 20:51:201273 } else if (!view->GetWidget()) {
1274 // If the view has no Widget, we're not visible. Return an empty rect.
initial.commit09911bf2008-07-26 23:55:291275 return gfx::Rect();
1276 }
1277 view = ancestor;
1278 }
1279 if (vis_bounds.IsEmpty())
1280 return vis_bounds;
1281 // Convert back to this views coordinate system.
1282 vis_bounds.Offset(-root_x, -root_y);
1283 return vis_bounds;
1284}
1285
1286int View::GetPageScrollIncrement(ScrollView* scroll_view,
1287 bool is_horizontal, bool is_positive) {
1288 return 0;
1289}
1290
1291int View::GetLineScrollIncrement(ScrollView* scroll_view,
1292 bool is_horizontal, bool is_positive) {
1293 return 0;
1294}
1295
[email protected]4a190632009-05-09 01:07:421296ThemeProvider* View::GetThemeProvider() {
1297 Widget* widget = GetWidget();
1298 return widget ? widget->GetThemeProvider() : NULL;
1299}
1300
initial.commit09911bf2008-07-26 23:55:291301// static
1302void View::RegisterChildrenForVisibleBoundsNotification(
1303 RootView* root, View* view) {
1304 DCHECK(root && view);
1305 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1306 root->RegisterViewForVisibleBoundsNotification(view);
1307 for (int i = 0; i < view->GetChildViewCount(); ++i)
1308 RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i));
1309}
1310
1311// static
1312void View::UnregisterChildrenForVisibleBoundsNotification(
1313 RootView* root, View* view) {
1314 DCHECK(root && view);
1315 if (view->GetNotifyWhenVisibleBoundsInRootChanges())
1316 root->UnregisterViewForVisibleBoundsNotification(view);
1317 for (int i = 0; i < view->GetChildViewCount(); ++i)
1318 UnregisterChildrenForVisibleBoundsNotification(root,
1319 view->GetChildViewAt(i));
1320}
1321
1322void View::AddDescendantToNotify(View* view) {
1323 DCHECK(view);
1324 if (!descendants_to_notify_.get())
1325 descendants_to_notify_.reset(new ViewList());
1326 descendants_to_notify_->push_back(view);
1327}
1328
1329void View::RemoveDescendantToNotify(View* view) {
1330 DCHECK(view && descendants_to_notify_.get());
1331 ViewList::iterator i = find(descendants_to_notify_->begin(),
1332 descendants_to_notify_->end(),
1333 view);
1334 DCHECK(i != descendants_to_notify_->end());
1335 descendants_to_notify_->erase(i);
1336 if (descendants_to_notify_->empty())
1337 descendants_to_notify_.reset();
1338}
1339
initial.commit09911bf2008-07-26 23:55:291340// DropInfo --------------------------------------------------------------------
1341
1342void View::DragInfo::Reset() {
1343 possible_drag = false;
1344 start_x = start_y = 0;
1345}
1346
1347void View::DragInfo::PossibleDrag(int x, int y) {
1348 possible_drag = true;
1349 start_x = x;
1350 start_y = y;
1351}
1352
1353} // namespace