ui/core/material/cfmaterial_motion.h¶
Material Design 3 Motion Scheme with EmbeddedTokenRegistry. More...
Namespaces¶
| Name |
|---|
| cf |
| cf::ui |
| cf::ui::core |
| cf::ui::core::tokens |
Classes¶
| Name | |
|---|---|
| struct | cf::ui::core::MotionSpec Motion specification structure. |
| struct | cf::ui::core::MotionPresets Static motion preset functions. |
| class | cf::ui::core::MaterialMotionScheme Material Design 3 Motion Scheme with EmbeddedTokenRegistry. |
| struct | cf::ui::core::MaterialMotionScheme::MotionPresetsGroup Motion presets group structure. |
Detailed Description¶
Material Design 3 Motion Scheme with EmbeddedTokenRegistry.
Author: Charliechen114514 (chengh1922@mails.jlu.edu.cn)
Version: 0.1
Date: 2026-02-26
Copyright: Copyright © 2026
Implements the complete Material Design 3 motion system with duration, easing, and delay specifications. Motion specs are stored in an embedded registry for independent scheme instances.
Source code¶
#pragma once
#include <QEasingCurve>
#include <string>
#include <unordered_map>
#include "../motion_spec.h"
#include "../token.hpp"
#include "../token/motion/cfmaterial_motion_token_literals.h"
#include "base/easing.h"
#include "base/hash/constexpr_fnv1a.hpp"
#include "export.h"
namespace cf::ui::core {
// =============================================================================
// Motion Token Type Aliases - Material Motion System
// =============================================================================
namespace tokens {
using namespace cf::ui::core::token::literals;
// Duration tokens
using ShortEnterDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_SHORT_ENTER_DURATION)>;
using ShortExitDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_SHORT_EXIT_DURATION)>;
using MediumEnterDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_MEDIUM_ENTER_DURATION)>;
using MediumExitDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_MEDIUM_EXIT_DURATION)>;
using LongEnterDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_LONG_ENTER_DURATION)>;
using LongExitDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_LONG_EXIT_DURATION)>;
using StateChangeDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_STATE_CHANGE_DURATION)>;
using RippleExpandDurationToken =
StaticToken<int, cf::hash::fnv1a64(MOTION_RIPPLE_EXPAND_DURATION)>;
using RippleFadeDurationToken = StaticToken<int, cf::hash::fnv1a64(MOTION_RIPPLE_FADE_DURATION)>;
// Easing tokens (stored as int enum values)
using ShortEnterEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_SHORT_ENTER_EASING)>;
using ShortExitEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_SHORT_EXIT_EASING)>;
using MediumEnterEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_MEDIUM_ENTER_EASING)>;
using MediumExitEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_MEDIUM_EXIT_EASING)>;
using LongEnterEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_LONG_ENTER_EASING)>;
using LongExitEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_LONG_EXIT_EASING)>;
using StateChangeEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_STATE_CHANGE_EASING)>;
using RippleExpandEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_RIPPLE_EXPAND_EASING)>;
using RippleFadeEasingToken = StaticToken<int, cf::hash::fnv1a64(MOTION_RIPPLE_FADE_EASING)>;
} // namespace tokens
// =============================================================================
// Motion Data Structure
// =============================================================================
struct MotionSpec {
int durationMs;
cf::ui::base::Easing::Type easing;
int delayMs = 0;
QEasingCurve toEasingCurve() const { return cf::ui::base::Easing::fromEasingType(easing); }
bool operator==(const MotionSpec& other) const {
return durationMs == other.durationMs && easing == other.easing && delayMs == other.delayMs;
}
bool operator!=(const MotionSpec& other) const { return !(*this == other); }
};
// =============================================================================
// Motion Presets
// =============================================================================
struct MotionPresets {
static MotionSpec shortEnter() {
return {200, cf::ui::base::Easing::Type::EmphasizedDecelerate, 0};
}
static MotionSpec shortExit() {
return {150, cf::ui::base::Easing::Type::EmphasizedAccelerate, 0};
}
static MotionSpec mediumEnter() {
return {300, cf::ui::base::Easing::Type::EmphasizedDecelerate, 0};
}
static MotionSpec mediumExit() {
return {250, cf::ui::base::Easing::Type::EmphasizedAccelerate, 0};
}
static MotionSpec longEnter() { return {450, cf::ui::base::Easing::Type::Emphasized, 0}; }
static MotionSpec longExit() { return {400, cf::ui::base::Easing::Type::Emphasized, 0}; }
static MotionSpec stateChange() { return {200, cf::ui::base::Easing::Type::Standard, 0}; }
static MotionSpec rippleExpand() { return {400, cf::ui::base::Easing::Type::Standard, 0}; }
static MotionSpec rippleFade() { return {150, cf::ui::base::Easing::Type::Linear, 0}; }
};
// =============================================================================
// Material Motion Scheme
// =============================================================================
class CF_UI_EXPORT MaterialMotionScheme : public IMotionSpec {
public:
MaterialMotionScheme();
~MaterialMotionScheme() override = default;
// Non-copyable, movable
MaterialMotionScheme(const MaterialMotionScheme&) = delete;
MaterialMotionScheme& operator=(const MaterialMotionScheme&) = delete;
MaterialMotionScheme(MaterialMotionScheme&&) noexcept = default;
MaterialMotionScheme& operator=(MaterialMotionScheme&&) noexcept = default;
int queryDuration(const char* name) override;
int queryEasing(const char* name) override;
int queryDelay(const char* name) override;
MotionSpec getMotionSpec(const char* name);
EmbeddedTokenRegistry& registry() { return registry_; }
const EmbeddedTokenRegistry& registry() const { return registry_; }
struct MotionPresetsGroup {
MotionSpec shortEnter;
MotionSpec shortExit;
MotionSpec mediumEnter;
MotionSpec mediumExit;
MotionSpec longEnter;
MotionSpec longExit;
MotionSpec stateChange;
MotionSpec rippleExpand;
MotionSpec rippleFade;
};
[[nodiscard]] MotionPresetsGroup presets() const {
return MotionPresetsGroup{MotionPresets::shortEnter(), MotionPresets::shortExit(),
MotionPresets::mediumEnter(), MotionPresets::mediumExit(),
MotionPresets::longEnter(), MotionPresets::longExit(),
MotionPresets::stateChange(), MotionPresets::rippleExpand(),
MotionPresets::rippleFade()};
}
private:
EmbeddedTokenRegistry registry_;
mutable std::unordered_map<std::string, MotionSpec> spec_cache_;
};
} // namespace cf::ui::core
Updated on 2026-03-09 at 10:14:01 +0000