Commit e812f172 authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Animating layout manager can animate bounds in a constrained layout.

Previously, when animating layout manager was set to "animate bounds"
mode (see SetShouldAnimateBounds()), it assumed it would always be given
enough space for its preferred size at any point in the animation.

This CL makes it so that an animation can stop short if the containing
view stops granting the animating view more space. This allows a view
with an AnimatingLayoutManager to be more easily embedded in a view that
has, for example, a FlexLayout layout manager.

The primary use case will be capping the size of the account icon
container so the account name text is elided when the browser window is
too narrow to show the entire text without making the Omnibox too small
to effectively use.

The current behavior is that when space runs out, the kebab/wrench icon
slides off the right side of the window (see attached bug).

A follow-up will actually engage this new functionality to fix the
problem.

Bug: 1012681
Change-Id: Ia8e41bb15776a72a8d0869a3c387703e5e443c83
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1875107
Commit-Queue: Dana Fried <dfried@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709182}
parent 36571a8d
...@@ -19,6 +19,19 @@ ...@@ -19,6 +19,19 @@
namespace views { namespace views {
namespace {
int GetMainAxis(LayoutOrientation orientation, const gfx::Size& size) {
switch (orientation) {
case LayoutOrientation::kHorizontal:
return size.width();
case LayoutOrientation::kVertical:
return size.height();
}
}
} // anonymous namespace
// Holds data about a view that is fading in or out as part of an animation. // Holds data about a view that is fading in or out as part of an animation.
struct AnimatingLayoutManager::LayoutFadeInfo { struct AnimatingLayoutManager::LayoutFadeInfo {
// Whether the view is fading in or out. // Whether the view is fading in or out.
...@@ -215,9 +228,6 @@ AnimatingLayoutManager& AnimatingLayoutManager::SetDefaultFadeMode( ...@@ -215,9 +228,6 @@ AnimatingLayoutManager& AnimatingLayoutManager::SetDefaultFadeMode(
} }
void AnimatingLayoutManager::ResetLayout() { void AnimatingLayoutManager::ResetLayout() {
if (animation_delegate_)
animation_delegate_->Reset();
if (!target_layout_manager()) if (!target_layout_manager())
return; return;
...@@ -225,12 +235,31 @@ void AnimatingLayoutManager::ResetLayout() { ...@@ -225,12 +235,31 @@ void AnimatingLayoutManager::ResetLayout() {
should_animate_bounds_ should_animate_bounds_
? target_layout_manager()->GetPreferredSize(host_view()) ? target_layout_manager()->GetPreferredSize(host_view())
: host_view()->size(); : host_view()->size();
ResetLayoutToSize(target_size);
}
void AnimatingLayoutManager::ResetLayoutToSize(const gfx::Size& target_size) {
if (animation_delegate_)
animation_delegate_->Reset();
target_layout_ = target_layout_manager()->GetProposedLayout(target_size); target_layout_ = target_layout_manager()->GetProposedLayout(target_size);
current_layout_ = target_layout_; current_layout_ = target_layout_;
starting_layout_ = current_layout_; starting_layout_ = current_layout_;
fade_infos_.clear(); fade_infos_.clear();
current_offset_ = 1.0; current_offset_ = 1.0;
set_cached_layout_size(target_size); set_cached_layout_size(target_size);
if (is_animating_)
OnAnimationEnded();
}
void AnimatingLayoutManager::OnAnimationEnded() {
DCHECK(is_animating_);
is_animating_ = false;
RunDelayedActions();
DCHECK(!is_animating_) << "Queued actions should not change animation state.";
NotifyIsAnimatingChanged();
} }
void AnimatingLayoutManager::FadeOut(View* child_view) { void AnimatingLayoutManager::FadeOut(View* child_view) {
...@@ -289,7 +318,10 @@ gfx::Size AnimatingLayoutManager::GetMinimumSize(const View* host) const { ...@@ -289,7 +318,10 @@ gfx::Size AnimatingLayoutManager::GetMinimumSize(const View* host) const {
return gfx::Size(); return gfx::Size();
// TODO(dfried): consider cases where the minimum size might not be just the // TODO(dfried): consider cases where the minimum size might not be just the
// minimum size of the embedded layout. // minimum size of the embedded layout.
return target_layout_manager()->GetMinimumSize(host); gfx::Size minimum_size = target_layout_manager()->GetMinimumSize(host);
if (should_animate_bounds_ && is_animating_)
minimum_size.SetToMin(current_layout_.host_size);
return minimum_size;
} }
int AnimatingLayoutManager::GetPreferredHeightForWidth(const View* host, int AnimatingLayoutManager::GetPreferredHeightForWidth(const View* host,
...@@ -307,21 +339,22 @@ void AnimatingLayoutManager::Layout(View* host) { ...@@ -307,21 +339,22 @@ void AnimatingLayoutManager::Layout(View* host) {
// Changing the size of a view directly will lead to a layout call rather // Changing the size of a view directly will lead to a layout call rather
// than an invalidation. This should reset the layout (but see the note in // than an invalidation. This should reset the layout (but see the note in
// RecalculateTarget() below). // RecalculateTarget() below).
if (!should_animate_bounds_ && if (should_animate_bounds_) {
(!cached_layout_size() || host->size() != *cached_layout_size())) { const int host_main = GetMainAxis(orientation(), host->size());
const int desired_main =
GetMainAxis(orientation(), current_layout_.host_size);
if (desired_main > host_main)
ResetLayoutToSize(host->size());
} else if (!cached_layout_size() || host->size() != *cached_layout_size()) {
ResetLayout(); ResetLayout();
} }
ApplyLayout(current_layout_); ApplyLayout(current_layout_);
// Send animating stopped events on layout so the current layout during the // Send animating stopped events on layout so the current layout during the
// event represents the final state instead of an intermediate state. // event represents the final state instead of an intermediate state.
if (is_animating_ && current_offset_ == 1.0) { if (is_animating_ && current_offset_ == 1.0)
is_animating_ = false; OnAnimationEnded();
RunDelayedActions();
DCHECK(!is_animating_)
<< "Queued actions should not change animation state.";
NotifyIsAnimatingChanged();
}
} }
std::vector<View*> AnimatingLayoutManager::GetChildViewsInPaintOrder( std::vector<View*> AnimatingLayoutManager::GetChildViewsInPaintOrder(
......
...@@ -133,6 +133,14 @@ class VIEWS_EXPORT AnimatingLayoutManager : public LayoutManagerBase { ...@@ -133,6 +133,14 @@ class VIEWS_EXPORT AnimatingLayoutManager : public LayoutManagerBase {
// layout from the embedded layout manager. // layout from the embedded layout manager.
void ResetLayout(); void ResetLayout();
// Does the work of ResetLayout() or FreezeLayout(), with the resulting layout
// snapped to |target_size|.
void ResetLayoutToSize(const gfx::Size& target_size);
// Cleans up after an animation, runs delayed actions, and sends
// notifications.
void OnAnimationEnded();
// Causes the specified child view to fade out and become hidden. Alternative // Causes the specified child view to fade out and become hidden. Alternative
// to directly hiding the view (which will have the same effect, but could // to directly hiding the view (which will have the same effect, but could
// cause visual flicker if the view paints before it can re-layout. // cause visual flicker if the view paints before it can re-layout.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment