summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 21:28:01 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 21:28:01 +0000
commit6260f9e685ffa86d44750e61e1695bc57e9e122d (patch)
tree78250b5e4a4c2f66c64701d5edbe222e36845f05 /views
parentd73d5f66e9c1d054e58b3966e9eaab7ab0020999 (diff)
downloadchromium_src-6260f9e685ffa86d44750e61e1695bc57e9e122d.zip
chromium_src-6260f9e685ffa86d44750e61e1695bc57e9e122d.tar.gz
chromium_src-6260f9e685ffa86d44750e61e1695bc57e9e122d.tar.bz2
Remove "visible bounds in root changed" functions from RootView, move them to View.
Clean up the API a little. Adds a BoundsChanged() processing function to View that does default processing for bounds-changed events, including notifying the view via OnBoundsChanged() and potentially notifying of visible bounds changing. Adds a unit test for OnVisibleBoundsChanged. http://crbug.com/72040 TEST=unit test Review URL: http://codereview.chromium.org/6534001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75182 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/controls/native/native_view_host.cc13
-rw-r--r--views/controls/native/native_view_host.h3
-rw-r--r--views/view.cc95
-rw-r--r--views/view.h43
-rw-r--r--views/view_unittest.cc76
-rw-r--r--views/widget/root_view.cc38
-rw-r--r--views/widget/root_view.h11
7 files changed, 160 insertions, 119 deletions
diff --git a/views/controls/native/native_view_host.cc b/views/controls/native/native_view_host.cc
index 81f1f2f..4566b80 100644
--- a/views/controls/native/native_view_host.cc
+++ b/views/controls/native/native_view_host.cc
@@ -33,10 +33,6 @@ NativeViewHost::NativeViewHost()
views_view_(NULL),
fast_resize_(false),
focus_view_(NULL) {
- // The native widget is placed relative to the root. As such, we need to
- // know when the position of any ancestor changes, or our visibility relative
- // to other views changed as it'll effect our position relative to the root.
- SetNotifyWhenVisibleBoundsInRootChanges(true);
}
NativeViewHost::~NativeViewHost() {
@@ -156,7 +152,14 @@ void NativeViewHost::VisibilityChanged(View* starting_from, bool is_visible) {
Layout();
}
-void NativeViewHost::VisibleBoundsInRootChanged() {
+bool NativeViewHost::NeedsNotificationWhenVisibleBoundsChange() const {
+ // The native widget is placed relative to the root. As such, we need to
+ // know when the position of any ancestor changes, or our visibility relative
+ // to other views changed as it'll effect our position relative to the root.
+ return true;
+}
+
+void NativeViewHost::OnVisibleBoundsChanged() {
Layout();
}
diff --git a/views/controls/native/native_view_host.h b/views/controls/native/native_view_host.h
index da8e540..9c06f35 100644
--- a/views/controls/native/native_view_host.h
+++ b/views/controls/native/native_view_host.h
@@ -84,7 +84,8 @@ class NativeViewHost : public View {
virtual bool ContainsNativeView(gfx::NativeView native_view) const;
protected:
- virtual void VisibleBoundsInRootChanged();
+ virtual bool NeedsNotificationWhenVisibleBoundsChange() const;
+ virtual void OnVisibleBoundsChanged();
virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
virtual std::string GetClassName() const;
diff --git a/views/view.cc b/views/view.cc
index ab79197..4d75272 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -63,7 +63,6 @@ View::View()
is_parent_owned_(true),
parent_(NULL),
is_visible_(true),
- notify_when_visible_bounds_in_root_changes_(false),
registered_for_visible_bounds_notification_(false),
clip_x_(0),
clip_y_(0),
@@ -129,9 +128,8 @@ void View::AddChildViewAt(View* view, int index) {
view->PropagateAddNotifications(this, view);
UpdateTooltip();
- RootView* root = GetRootView();
- if (root)
- RegisterChildrenForVisibleBoundsNotification(root, view);
+ if (GetWidget())
+ RegisterChildrenForVisibleBoundsNotification(view);
if (layout_manager_.get())
layout_manager_->ViewAdded(this, view);
@@ -199,9 +197,6 @@ RootView* View::GetRootView() {
return widget ? widget->GetRootView() : NULL;
}
-#ifndef NDEBUG
-#endif
-
// Size and disposition --------------------------------------------------------
void View::SetBounds(int x, int y, int width, int height) {
@@ -222,13 +217,8 @@ void View::SetBoundsRect(const gfx::Rect& bounds) {
bool size_changed = prev.size() != bounds_.size();
bool position_changed = prev.origin() != bounds_.origin();
- if (size_changed || position_changed) {
- OnBoundsChanged();
-
- RootView* root = GetRootView();
- if (root)
- root->ViewBoundsChanged(this, size_changed, position_changed);
- }
+ if (size_changed || position_changed)
+ BoundsChanged();
}
void View::SetSize(const gfx::Size& size) {
@@ -1009,21 +999,11 @@ void View::PreferredSizeChanged() {
parent_->ChildPreferredSizeChanged(this);
}
-void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) {
- if (notify_when_visible_bounds_in_root_changes_ == value)
- return;
- notify_when_visible_bounds_in_root_changes_ = value;
- RootView* root = GetRootView();
- if (root) {
- if (value)
- root->RegisterViewForVisibleBoundsNotification(this);
- else
- root->UnregisterViewForVisibleBoundsNotification(this);
- }
+bool View::NeedsNotificationWhenVisibleBoundsChange() const {
+ return false;
}
-bool View::GetNotifyWhenVisibleBoundsInRootChanges() {
- return notify_when_visible_bounds_in_root_changes_;
+void View::OnVisibleBoundsChanged() {
}
// Tree operations -------------------------------------------------------------
@@ -1198,9 +1178,8 @@ void View::DoRemoveChildView(View* view,
next_focusable->previous_focusable_view_ = prev_focusable;
}
- RootView* root = GetRootView();
- if (root)
- UnregisterChildrenForVisibleBoundsNotification(root, view);
+ if (GetWidget())
+ UnregisterChildrenForVisibleBoundsNotification(view);
view->PropagateRemoveNotifications(this);
view->SetParent(NULL);
@@ -1287,25 +1266,55 @@ void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
VisibilityChanged(starting_from, is_visible);
}
+void View::BoundsChanged() {
+ OnBoundsChanged();
+
+ // Notify interested Views that visible bounds within the root view may have
+ // changed.
+ if (descendants_to_notify_.get()) {
+ for (std::vector<View*>::iterator i = descendants_to_notify_->begin();
+ i != descendants_to_notify_->end(); ++i) {
+ (*i)->OnVisibleBoundsChanged();
+ }
+ }
+}
+
// static
-void View::RegisterChildrenForVisibleBoundsNotification(
- RootView* root, View* view) {
- DCHECK(root && view);
- if (view->GetNotifyWhenVisibleBoundsInRootChanges())
- root->RegisterViewForVisibleBoundsNotification(view);
+void View::RegisterChildrenForVisibleBoundsNotification(View* view) {
+ if (view->NeedsNotificationWhenVisibleBoundsChange())
+ view->RegisterForVisibleBoundsNotification();
for (int i = 0; i < view->child_count(); ++i)
- RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i));
+ RegisterChildrenForVisibleBoundsNotification(view->GetChildViewAt(i));
}
// static
-void View::UnregisterChildrenForVisibleBoundsNotification(
- RootView* root, View* view) {
- DCHECK(root && view);
- if (view->GetNotifyWhenVisibleBoundsInRootChanges())
- root->UnregisterViewForVisibleBoundsNotification(view);
+void View::UnregisterChildrenForVisibleBoundsNotification(View* view) {
+ if (view->NeedsNotificationWhenVisibleBoundsChange())
+ view->UnregisterForVisibleBoundsNotification();
for (int i = 0; i < view->child_count(); ++i)
- UnregisterChildrenForVisibleBoundsNotification(root,
- view->GetChildViewAt(i));
+ UnregisterChildrenForVisibleBoundsNotification(view->GetChildViewAt(i));
+}
+
+void View::RegisterForVisibleBoundsNotification() {
+ if (registered_for_visible_bounds_notification_)
+ return;
+ registered_for_visible_bounds_notification_ = true;
+ View* ancestor = parent();
+ while (ancestor) {
+ ancestor->AddDescendantToNotify(this);
+ ancestor = ancestor->parent();
+ }
+}
+
+void View::UnregisterForVisibleBoundsNotification() {
+ if (!registered_for_visible_bounds_notification_)
+ return;
+ registered_for_visible_bounds_notification_ = false;
+ View* ancestor = parent();
+ while (ancestor) {
+ ancestor->RemoveDescendantToNotify(this);
+ ancestor = ancestor->parent();
+ }
}
void View::AddDescendantToNotify(View* view) {
diff --git a/views/view.h b/views/view.h
index 4080070..6104ff1 100644
--- a/views/view.h
+++ b/views/view.h
@@ -986,17 +986,15 @@ class View : public AcceleratorTarget {
// overriding such that the layout is properly invalidated.
virtual void PreferredSizeChanged();
- // Sets whether this view wants notification when its visible bounds relative
- // to the root view changes. If true, this view is notified any time the
- // origin of one its ancestors changes, or the portion of the bounds not
- // obscured by ancestors changes. The default is false.
- void SetNotifyWhenVisibleBoundsInRootChanges(bool value);
- bool GetNotifyWhenVisibleBoundsInRootChanges();
-
- // Notification that this views visible bounds, relative to the RootView
- // has changed. The visible bounds corresponds to the region of the
- // view not obscured by other ancestors.
- virtual void VisibleBoundsInRootChanged() {}
+ // Override returning true when the view needs to be notified when its visible
+ // bounds relative to the root view may have changed. Only used by
+ // NativeViewHost.
+ virtual bool NeedsNotificationWhenVisibleBoundsChange() const;
+
+ // Notification that this View's visible bounds relative to the root view may
+ // have changed. The visible bounds are the region of the View not clipped by
+ // its ancestors. This is used for clipping NativeViewHost.
+ virtual void OnVisibleBoundsChanged();
// TODO(beng): eliminate in protected.
// Whether this view is enabled.
@@ -1233,13 +1231,19 @@ class View : public AcceleratorTarget {
// VisibilityChanged().
void VisibilityChangedImpl(View* starting_from, bool is_visible);
- // Recursively descends through all descendant views,
- // registering/unregistering all views that want visible bounds in root
- // view notification.
- static void RegisterChildrenForVisibleBoundsNotification(RootView* root,
- View* view);
- static void UnregisterChildrenForVisibleBoundsNotification(RootView* root,
- View* view);
+ // Responsible for propagating bounds change notifications to relevant
+ // views.
+ void BoundsChanged();
+
+ // Visible bounds notification registration.
+ // When a view is added to a hierarchy, it and all its children are asked if
+ // they need to be registered for "visible bounds within root" notifications
+ // (see comment on OnVisibleBoundsChanged()). If they do, they are registered
+ // with every ancestor between them and the root of the hierarchy.
+ static void RegisterChildrenForVisibleBoundsNotification(View* view);
+ static void UnregisterChildrenForVisibleBoundsNotification(View* view);
+ void RegisterForVisibleBoundsNotification();
+ void UnregisterForVisibleBoundsNotification();
// Adds/removes view to the list of descendants that are notified any time
// this views location and possibly size are changed.
@@ -1347,9 +1351,6 @@ class View : public AcceleratorTarget {
// Visible state
bool is_visible_;
- // See SetNotifyWhenVisibleBoundsInRootChanges.
- bool notify_when_visible_bounds_in_root_changes_;
-
// Whether or not RegisterViewForVisibleBoundsNotification on the RootView
// has been invoked.
bool registered_for_visible_bounds_notification_;
diff --git a/views/view_unittest.cc b/views/view_unittest.cc
index 3b1dcfe..6ae69c5 100644
--- a/views/view_unittest.cc
+++ b/views/view_unittest.cc
@@ -1557,3 +1557,79 @@ TEST_F(ViewTest, TransformPaint) {
widget->CloseNow();
}
+
+////////////////////////////////////////////////////////////////////////////////
+// OnVisibleBoundsChanged()
+
+class VisibleBoundsView : public View {
+ public:
+ VisibleBoundsView() : received_notification_(false) {}
+ virtual ~VisibleBoundsView() {}
+
+ bool received_notification() const { return received_notification_; }
+ void set_received_notification(bool received) {
+ received_notification_ = received;
+ }
+
+ private:
+ // Overridden from View:
+ virtual bool NeedsNotificationWhenVisibleBoundsChange() const {
+ return true;
+ }
+ virtual void OnVisibleBoundsChanged() {
+ received_notification_ = true;
+ }
+
+ bool received_notification_;
+
+ DISALLOW_COPY_AND_ASSIGN(VisibleBoundsView);
+};
+
+#if defined(OS_WIN)
+// TODO(beng): This can be cross platform when widget construction/init is.
+TEST_F(ViewTest, OnVisibleBoundsChanged) {
+ gfx::Rect viewport_bounds(0, 0, 100, 100);
+
+ scoped_ptr<Widget> widget(CreateWidget());
+ WidgetWin* widget_win = static_cast<WidgetWin*>(widget.get());
+ widget_win->set_delete_on_destroy(false);
+ widget_win->set_window_style(WS_OVERLAPPEDWINDOW);
+ widget_win->Init(NULL, viewport_bounds);
+ widget->GetRootView()->SetBoundsRect(viewport_bounds);
+
+ View* viewport = new View;
+ widget->GetRootView()->SetContentsView(viewport);
+ View* contents = new View;
+ viewport->AddChildView(contents);
+ viewport->SetBoundsRect(viewport_bounds);
+ contents->SetBounds(0, 0, 100, 200);
+
+ // Create a view that cares about visible bounds notifications, and position
+ // it just outside the visible bounds of the viewport.
+ VisibleBoundsView* child = new VisibleBoundsView;
+ contents->AddChildView(child);
+ child->SetBounds(10, 110, 50, 50);
+
+ // The child bound should be fully clipped.
+ EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
+
+ // Now scroll the contents, but not enough to make the child visible.
+ contents->SetY(contents->y() - 1);
+
+ // We should have received the notification since the visible bounds may have
+ // changed (even though they didn't).
+ EXPECT_TRUE(child->received_notification());
+ EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
+ child->set_received_notification(false);
+
+ // Now scroll the contents, this time by enough to make the child visible by
+ // one pixel.
+ contents->SetY(contents->y() - 10);
+ EXPECT_TRUE(child->received_notification());
+ EXPECT_EQ(1, child->GetVisibleBounds().height());
+ child->set_received_notification(false);
+
+ widget->CloseNow();
+}
+
+#endif
diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc
index 547e3ab..1de505e 100644
--- a/views/widget/root_view.cc
+++ b/views/widget/root_view.cc
@@ -702,44 +702,6 @@ void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
////////////////////////////////////////////////////////////////////////////////
// RootView, protected:
-// Size and disposition --------------------------------------------------------
-
-void RootView::ViewBoundsChanged(View* view, bool size_changed,
- bool position_changed) {
- DCHECK(view && (size_changed || position_changed));
- if (!view->descendants_to_notify_.get())
- return;
-
- for (std::vector<View*>::iterator i = view->descendants_to_notify_->begin();
- i != view->descendants_to_notify_->end(); ++i) {
- (*i)->VisibleBoundsInRootChanged();
- }
-}
-
-void RootView::RegisterViewForVisibleBoundsNotification(View* view) {
- DCHECK(view);
- if (view->registered_for_visible_bounds_notification_)
- return;
- view->registered_for_visible_bounds_notification_ = true;
- View* ancestor = view->parent();
- while (ancestor) {
- ancestor->AddDescendantToNotify(view);
- ancestor = ancestor->parent();
- }
-}
-
-void RootView::UnregisterViewForVisibleBoundsNotification(View* view) {
- DCHECK(view);
- if (!view->registered_for_visible_bounds_notification_)
- return;
- view->registered_for_visible_bounds_notification_ = false;
- View* ancestor = view->parent();
- while (ancestor) {
- ancestor->RemoveDescendantToNotify(view);
- ancestor = ancestor->parent();
- }
-}
-
// Coordinate conversion -------------------------------------------------------
bool RootView::ConvertPointToMouseHandler(const gfx::Point& l,
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index ba294a8..495b013 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -205,17 +205,6 @@ class RootView : public View,
friend class GestureManager;
#endif
- // Size and disposition ------------------------------------------------------
-
- // Notification that size and/or position of a view has changed. This
- // notifies the appropriate views.
- void ViewBoundsChanged(View* view, bool size_changed, bool position_changed);
-
- // Registers a view for notification when the visible bounds relative to the
- // root of a view changes.
- void RegisterViewForVisibleBoundsNotification(View* view);
- void UnregisterViewForVisibleBoundsNotification(View* view);
-
// Coordinate conversion -----------------------------------------------------
// Convert a point to our current mouse handler. Returns false if the