Files
NativeScript/ui/styling/visual-state.ts
Tsvetan Raikov 073cc94926 implemented CSS animations
fixing animation tests
2016-03-25 15:26:48 +02:00

118 lines
3.4 KiB
TypeScript

import viewModule = require("ui/core/view");
import observable = require("ui/core/dependency-observable");
import styleProperty = require("ui/styling/style-property");
import cssSelector = require("ui/styling/css-selector");
import * as visualStateConstants from "ui/styling/visual-state-constants";
export class VisualState {
private _setters: {}; // use css selector instead
private _animatedSelectors: cssSelector.CssVisualStateSelector[];
constructor() {
this._setters = {};
this._animatedSelectors = [];
}
get setters(): {} {
return this._setters;
}
get animatedSelectors(): cssSelector.CssVisualStateSelector[] {
return this._animatedSelectors;
}
}
/**
*
*/
export function goToState(view: viewModule.View, state: string): string {
let root = <any>view.page;
if (!root) {
return undefined;
}
//TODO: this of optimization
let allStates = root._getStyleScope().getVisualStates(view);
if (!allStates) {
return undefined;
}
// logic here is:
// 1. Verify the new state, whether we have setters for it and rollback to Normal(default) if not.
// 2. If the new visual state is the same as the current one, do nothing
// 3. Else, remove the visual state value for all the properties from the current state that are not present in the new one
// 4. Apply all the properties from the new state.
// Step 1
if (!(state in allStates)) {
// TODO: Directly go to normal?
state = visualStateConstants.Normal;
}
// Step 2
if (state !== view.visualState) {
let newState: VisualState = allStates[state];
let oldState: VisualState = allStates[view.visualState];
// Step 3
resetProperties(view, oldState, newState);
// Step 4
applyProperties(view, newState);
}
return state;
}
function resetProperties(view: viewModule.View, oldState: VisualState, newState: VisualState) {
if (!oldState) {
return;
}
let property: styleProperty.Property;
for (let name in oldState.setters) {
if (newState && (name in newState.setters)) {
// Property will be altered by the new state, no need to reset it.
continue;
}
property = styleProperty.getPropertyByName(name);
if (property) {
view.style._resetValue(property, observable.ValueSource.VisualState);
}
}
for (let selector of oldState.animatedSelectors) {
for (let animationInfo of selector.animations) {
for (let keyframe of animationInfo.keyframes) {
for (let declaration of keyframe.declarations) {
property = styleProperty.getPropertyByName(declaration.property);
if (property) {
view.style._resetValue(property, observable.ValueSource.VisualState);
}
}
}
}
}
}
function applyProperties(view: viewModule.View, state: VisualState) {
if (!state) {
return;
}
let property: styleProperty.Property;
for (let name in state.setters) {
property = styleProperty.getPropertyByName(name);
if (property) {
view.style._setValue(property, state.setters[name], observable.ValueSource.VisualState);
}
}
for (let selector of state.animatedSelectors) {
selector.apply(view, observable.ValueSource.VisualState);
}
}