add way for adding/removing classes
This commit is contained in:
@@ -5,11 +5,13 @@
|
||||
#include <llmr/style/class_properties.hpp>
|
||||
#include <llmr/style/style_properties.hpp>
|
||||
#include <llmr/style/rasterize_properties.hpp>
|
||||
#include <llmr/style/applied_class_properties.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
@@ -33,6 +35,15 @@ public:
|
||||
|
||||
bool isBackground() const;
|
||||
|
||||
// Sets the list of classes and creates transitions to the currently applied values.
|
||||
void setClasses(const std::vector<std::string> &class_names, timestamp now,
|
||||
const ClassPropertyTransition &defaultTransition);
|
||||
|
||||
private:
|
||||
// Applies all properties from a class, if they haven't been applied already.
|
||||
void applyClassProperties(ClassID class_id, std::set<PropertyKey> &already_applied,
|
||||
timestamp now, const ClassPropertyTransition &defaultTransition);
|
||||
|
||||
public:
|
||||
// The name of this layer.
|
||||
const std::string id;
|
||||
@@ -44,6 +55,12 @@ public:
|
||||
// Contains all style classes that can be applied to this layer.
|
||||
const std::map<ClassID, ClassProperties> styles;
|
||||
|
||||
private:
|
||||
// For every property, stores a list of applied property values, with
|
||||
// optional transition times.
|
||||
std::map<PropertyKey, AppliedClassProperties> appliedStyle;
|
||||
|
||||
public:
|
||||
// Stores the evaluated, and cascaded styling information, specific to this
|
||||
// layer's type.
|
||||
StyleProperties style;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <llmr/style/style_layer.hpp>
|
||||
#include <llmr/style/property_fallback.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
@@ -10,4 +11,81 @@ bool StyleLayer::isBackground() const {
|
||||
return id == "background";
|
||||
}
|
||||
|
||||
void StyleLayer::setClasses(const std::vector<std::string> &class_names, const timestamp now,
|
||||
const ClassPropertyTransition &defaultTransition) {
|
||||
// Stores all keys that we have already added transitions for.
|
||||
std::set<PropertyKey> already_applied;
|
||||
|
||||
// Reverse iterate through all class names and apply them last to first.
|
||||
for (auto it = class_names.rbegin(); it != class_names.rend(); it++) {
|
||||
const std::string &class_name = *it;
|
||||
// From here on, we're only dealing with IDs to avoid comparing strings all the time.
|
||||
const ClassID class_id = ClassDictionary::Lookup(class_name);
|
||||
applyClassProperties(class_id, already_applied, now, defaultTransition);
|
||||
}
|
||||
|
||||
// As the last class, apply the default class.
|
||||
applyClassProperties(ClassID::Default, already_applied, now, defaultTransition);
|
||||
|
||||
// Make sure that we also transition to the fallback value for keys that aren't changed by
|
||||
// any applied classes.
|
||||
for (std::pair<const PropertyKey, AppliedClassProperties> &property_pair : appliedStyle) {
|
||||
const PropertyKey key = property_pair.first;
|
||||
if (already_applied.find(key) != already_applied.end()) {
|
||||
// This property has already been set by a previous class, so we don't need to
|
||||
// transition to the fallback.
|
||||
continue;
|
||||
}
|
||||
|
||||
AppliedClassProperties &appliedProperties = property_pair.second;
|
||||
// Make sure that we don't do double transitions to the fallback value.
|
||||
if (appliedProperties.mostRecent() != ClassID::Fallback) {
|
||||
// This property key hasn't been set by a previous class, so we need to add a transition
|
||||
// to the fallback value for that key.
|
||||
const timestamp begin = now + defaultTransition.delay;
|
||||
const timestamp end = begin + defaultTransition.duration;
|
||||
const PropertyValue &value = PropertyFallbackValue::Get(key);
|
||||
appliedProperties.add(ClassID::Fallback, begin, end, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for applying all properties of a a single class that haven't been applied yet.
|
||||
void StyleLayer::applyClassProperties(const ClassID class_id,
|
||||
std::set<PropertyKey> &already_applied, timestamp now,
|
||||
const ClassPropertyTransition &defaultTransition) {
|
||||
auto style_it = styles.find(class_id);
|
||||
if (style_it == styles.end()) {
|
||||
// There is no class in this layer with this class_name.
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through all the properties in this style, and add transitions to them, if they're
|
||||
// not already the most recent transition.
|
||||
const ClassProperties &properties = style_it->second;
|
||||
for (const std::pair<PropertyKey, PropertyValue> &property_pair : properties) {
|
||||
PropertyKey key = property_pair.first;
|
||||
if (already_applied.find(key) != already_applied.end()) {
|
||||
// This property has already been set by a previous class.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark this property as written by a previous class, so that subsequent
|
||||
// classes won't override this.
|
||||
already_applied.insert(key);
|
||||
|
||||
// If the most recent transition is not the one with the highest priority, create
|
||||
// a transition.
|
||||
AppliedClassProperties &appliedProperties = appliedStyle[key];
|
||||
if (appliedProperties.mostRecent() != class_id) {
|
||||
const ClassPropertyTransition &transition =
|
||||
properties.getTransition(key, defaultTransition);
|
||||
const timestamp begin = now + transition.delay;
|
||||
const timestamp end = begin + transition.duration;
|
||||
const PropertyValue &value = property_pair.second;
|
||||
appliedProperties.add(class_id, begin, end, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user