blob: fd64deae16b2ee7afeeacb24c3ffe0d6891e041c [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h"
#include <algorithm>
#include "base/logging.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h"
#include "ios/chrome/browser/ui/ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Object that increments |counter| by 1 for its lifetime.
class ScopedIncrementer {
public:
explicit ScopedIncrementer(size_t* counter) : counter_(counter) {
++(*counter_);
}
~ScopedIncrementer() { --(*counter_); }
private:
size_t* counter_;
};
}
FullscreenModel::FullscreenModel() = default;
FullscreenModel::~FullscreenModel() = default;
void FullscreenModel::IncrementDisabledCounter() {
if (++disabled_counter_ == 1U) {
ScopedIncrementer disabled_incrementer(&observer_callback_count_);
for (auto& observer : observers_) {
observer.FullscreenModelEnabledStateChanged(this);
}
}
}
void FullscreenModel::DecrementDisabledCounter() {
DCHECK_GT(disabled_counter_, 0U);
if (!--disabled_counter_) {
ScopedIncrementer enabled_incrementer(&observer_callback_count_);
for (auto& observer : observers_) {
observer.FullscreenModelEnabledStateChanged(this);
}
}
}
void FullscreenModel::ResetForNavigation() {
SetProgress(1.0);
scrolling_ = false;
base_offset_ = NAN;
}
void FullscreenModel::AnimationEndedWithProgress(CGFloat progress) {
DCHECK_GE(progress, 0.0);
DCHECK_LE(progress, 1.0);
// Since this is being set by the animator instead of by scroll events, do not
// broadcast the new progress value.
progress_ = progress;
}
void FullscreenModel::SetToolbarHeight(CGFloat toolbar_height) {
if (AreCGFloatsEqual(toolbar_height_, toolbar_height))
return;
DCHECK_GE(toolbar_height, 0.0);
toolbar_height_ = toolbar_height;
ResetForNavigation();
}
CGFloat FullscreenModel::GetToolbarHeight() const {
return toolbar_height_;
}
void FullscreenModel::SetYContentOffset(CGFloat y_content_offset) {
if (!enabled())
return;
y_content_offset_ = y_content_offset;
if (!has_base_offset())
UpdateBaseOffset();
if (scrolling_ && !observer_callback_count_) {
CGFloat delta = base_offset_ - y_content_offset_;
SetProgress(1.0 + delta / toolbar_height_);
} else {
UpdateBaseOffset();
}
}
CGFloat FullscreenModel::GetYContentOffset() const {
return y_content_offset_;
}
void FullscreenModel::SetScrollViewIsScrolling(bool scrolling) {
if (scrolling_ == scrolling)
return;
scrolling_ = scrolling;
if (!scrolling_) {
ScopedIncrementer scroll_ended_incrementer(&observer_callback_count_);
for (auto& observer : observers_) {
observer.FullscreenModelScrollEventEnded(this);
}
}
}
bool FullscreenModel::ISScrollViewScrolling() const {
return scrolling_;
}
void FullscreenModel::SetScrollViewIsDragging(bool dragging) {
if (dragging_ == dragging)
return;
dragging_ = dragging;
if (dragging_) {
ScopedIncrementer scroll_started_incrementer(&observer_callback_count_);
for (auto& observer : observers_) {
observer.FullscreenModelScrollEventStarted(this);
}
UpdateBaseOffset();
}
}
bool FullscreenModel::IsScrollViewDragging() const {
return dragging_;
}
void FullscreenModel::SetProgress(CGFloat progress) {
progress = std::min(static_cast<CGFloat>(1.0), progress);
progress = std::max(static_cast<CGFloat>(0.0), progress);
if (AreCGFloatsEqual(progress_, progress))
return;
progress_ = progress;
ScopedIncrementer progress_incrementer(&observer_callback_count_);
for (auto& observer : observers_) {
observer.FullscreenModelProgressUpdated(this);
}
}
void FullscreenModel::UpdateBaseOffset() {
base_offset_ = y_content_offset_ - (1.0 - progress_) * toolbar_height_;
}
void FullscreenModel::OnContentScrollOffsetBroadcasted(CGFloat offset) {
SetYContentOffset(offset);
}
void FullscreenModel::OnScrollViewIsScrollingBroadcasted(bool scrolling) {
SetScrollViewIsScrolling(scrolling);
}
void FullscreenModel::OnScrollViewIsDraggingBroadcasted(bool dragging) {
SetScrollViewIsDragging(dragging);
}
void FullscreenModel::OnToolbarHeightBroadcasted(CGFloat toolbar_height) {
SetToolbarHeight(toolbar_height);
}