#ifndef CC_INPUT_SNAP_SELECTION_STRATEGY_H_
#define CC_INPUT_SNAP_SELECTION_STRATEGY_H_
#include <memory>
#include "cc/input/scroll_snap_data.h"
namespace cc {
enum class SnapStopAlwaysFilter { kIgnore, kRequire };
enum class SnapTargetsPrioritization { kIgnore, kRequire };
class CC_EXPORT SnapSelectionStrategy {
public:
SnapSelectionStrategy() = default;
virtual ~SnapSelectionStrategy() = default;
static std::unique_ptr<SnapSelectionStrategy> CreateForEndPosition(
const gfx::PointF& current_position,
bool scrolled_x,
bool scrolled_y,
SnapTargetsPrioritization prioritization =
SnapTargetsPrioritization::kIgnore);
static std::unique_ptr<SnapSelectionStrategy> CreateForDirection(
gfx::PointF current_position,
gfx::Vector2dF step,
bool use_fractional_offsets,
SnapStopAlwaysFilter filter = SnapStopAlwaysFilter::kIgnore);
static std::unique_ptr<SnapSelectionStrategy> CreateForEndAndDirection(
gfx::PointF current_position,
gfx::Vector2dF displacement,
bool use_fractional_offsets);
static std::unique_ptr<SnapSelectionStrategy> CreateForTargetElement(
gfx::PointF current_position);
virtual bool ShouldSnapOnX() const = 0;
virtual bool ShouldSnapOnY() const = 0;
virtual bool ShouldPrioritizeSnapTargets() const;
virtual gfx::PointF intended_position() const = 0;
virtual gfx::PointF base_position() const = 0;
const gfx::PointF& current_position() const { return current_position_; }
virtual bool IsValidSnapPosition(SearchAxis axis, float position) const = 0;
virtual bool IsValidSnapArea(SearchAxis axis, const SnapAreaData& data) const;
virtual bool HasIntendedDirection() const;
virtual bool ShouldRespectSnapStop() const;
virtual const absl::optional<SnapSearchResult>& PickBestResult(
const absl::optional<SnapSearchResult>& closest,
const absl::optional<SnapSearchResult>& covering) const = 0;
virtual bool UsingFractionalOffsets() const;
protected:
explicit SnapSelectionStrategy(const gfx::PointF& current_position)
: current_position_(current_position) {}
const gfx::PointF current_position_;
};
class EndPositionStrategy : public SnapSelectionStrategy {
public:
EndPositionStrategy(const gfx::PointF& current_position,
bool scrolled_x,
bool scrolled_y,
SnapTargetsPrioritization snap_targets_prioritization)
: SnapSelectionStrategy(current_position),
scrolled_x_(scrolled_x),
scrolled_y_(scrolled_y),
snap_targets_prioritization_(snap_targets_prioritization) {}
~EndPositionStrategy() override = default;
bool ShouldSnapOnX() const override;
bool ShouldSnapOnY() const override;
gfx::PointF intended_position() const override;
gfx::PointF base_position() const override;
bool IsValidSnapPosition(SearchAxis axis, float position) const override;
bool HasIntendedDirection() const override;
bool ShouldPrioritizeSnapTargets() const override;
const absl::optional<SnapSearchResult>& PickBestResult(
const absl::optional<SnapSearchResult>& closest,
const absl::optional<SnapSearchResult>& covering) const override;
private:
const bool scrolled_x_;
const bool scrolled_y_;
SnapTargetsPrioritization snap_targets_prioritization_;
};
class DirectionStrategy : public SnapSelectionStrategy {
public:
DirectionStrategy(const gfx::PointF& current_position,
const gfx::Vector2dF& step,
SnapStopAlwaysFilter filter,
bool use_fractional_offsets)
: SnapSelectionStrategy(current_position),
step_(step),
snap_stop_always_filter_(filter),
use_fractional_offsets_(use_fractional_offsets) {}
~DirectionStrategy() override = default;
bool ShouldSnapOnX() const override;
bool ShouldSnapOnY() const override;
gfx::PointF intended_position() const override;
gfx::PointF base_position() const override;
bool IsValidSnapPosition(SearchAxis axis, float position) const override;
bool IsValidSnapArea(SearchAxis axis,
const SnapAreaData& area) const override;
const absl::optional<SnapSearchResult>& PickBestResult(
const absl::optional<SnapSearchResult>& closest,
const absl::optional<SnapSearchResult>& covering) const override;
bool UsingFractionalOffsets() const override;
private:
const gfx::Vector2dF step_;
SnapStopAlwaysFilter snap_stop_always_filter_;
bool use_fractional_offsets_;
};
class EndAndDirectionStrategy : public SnapSelectionStrategy {
public:
EndAndDirectionStrategy(const gfx::PointF& current_position,
const gfx::Vector2dF& displacement,
bool use_fractional_offsets)
: SnapSelectionStrategy(current_position),
displacement_(displacement),
use_fractional_offsets_(use_fractional_offsets) {}
~EndAndDirectionStrategy() override = default;
bool ShouldSnapOnX() const override;
bool ShouldSnapOnY() const override;
gfx::PointF intended_position() const override;
gfx::PointF base_position() const override;
bool IsValidSnapPosition(SearchAxis axis, float position) const override;
bool ShouldRespectSnapStop() const override;
const absl::optional<SnapSearchResult>& PickBestResult(
const absl::optional<SnapSearchResult>& closest,
const absl::optional<SnapSearchResult>& covering) const override;
bool UsingFractionalOffsets() const override;
private:
const gfx::Vector2dF displacement_;
bool use_fractional_offsets_;
};
}
#endif