2016-03-22 23:02:25 +03:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
namespace Xamarin.Forms
|
|
|
|
{
|
|
|
|
public partial class VisualElement
|
|
|
|
{
|
|
|
|
sealed class MergedStyle : IStyle
|
|
|
|
{
|
|
|
|
////If the base type is one of these, stop registering dynamic resources further
|
|
|
|
////The last one (typeof(Element)) is a safety guard as we might be creating VisualElement directly in internal code
|
|
|
|
static readonly IList<Type> s_stopAtTypes = new List<Type> { typeof(View), typeof(Layout<>), typeof(VisualElement), typeof(Element) };
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
IList<BindableProperty> _classStyleProperties;
|
2016-03-22 23:02:25 +03:00
|
|
|
|
|
|
|
readonly List<BindableProperty> _implicitStyles = new List<BindableProperty>();
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
IList<Style> _classStyles;
|
2016-03-22 23:02:25 +03:00
|
|
|
|
|
|
|
IStyle _implicitStyle;
|
|
|
|
|
|
|
|
IStyle _style;
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
IList<string> _styleClass;
|
2016-03-22 23:02:25 +03:00
|
|
|
|
|
|
|
public MergedStyle(Type targetType, BindableObject target)
|
|
|
|
{
|
|
|
|
Target = target;
|
|
|
|
TargetType = targetType;
|
|
|
|
RegisterImplicitStyles();
|
|
|
|
Apply(Target);
|
|
|
|
}
|
|
|
|
|
|
|
|
public IStyle Style
|
|
|
|
{
|
|
|
|
get { return _style; }
|
2016-04-26 01:03:33 +03:00
|
|
|
set { SetStyle(ImplicitStyle, ClassStyles, value); }
|
2016-03-22 23:02:25 +03:00
|
|
|
}
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
public IList<string> StyleClass
|
2016-03-22 23:02:25 +03:00
|
|
|
{
|
|
|
|
get { return _styleClass; }
|
|
|
|
set
|
|
|
|
{
|
2016-04-26 01:03:33 +03:00
|
|
|
if (_styleClass == value)
|
2016-03-22 23:02:25 +03:00
|
|
|
return;
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
if (_styleClass != null && _classStyles != null)
|
|
|
|
foreach (var classStyleProperty in _classStyleProperties)
|
|
|
|
Target.RemoveDynamicResource(classStyleProperty);
|
2016-03-22 23:02:25 +03:00
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
_styleClass = value;
|
2016-03-22 23:02:25 +03:00
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
if (_styleClass != null) {
|
|
|
|
_classStyleProperties = new List<BindableProperty> ();
|
|
|
|
foreach (var styleClass in _styleClass) {
|
|
|
|
var classStyleProperty = BindableProperty.Create ("ClassStyle", typeof(IList<Style>), typeof(VisualElement), default(IList<Style>),
|
|
|
|
propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.OnClassStyleChanged());
|
|
|
|
_classStyleProperties.Add (classStyleProperty);
|
|
|
|
Target.OnSetDynamicResource (classStyleProperty, Forms.Style.StyleClassPrefix + styleClass);
|
|
|
|
}
|
|
|
|
}
|
2016-03-22 23:02:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public BindableObject Target { get; }
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
IList<Style> ClassStyles
|
2016-03-22 23:02:25 +03:00
|
|
|
{
|
2016-04-26 01:03:33 +03:00
|
|
|
get { return _classStyles; }
|
2016-03-22 23:02:25 +03:00
|
|
|
set { SetStyle(ImplicitStyle, value, Style); }
|
|
|
|
}
|
|
|
|
|
|
|
|
IStyle ImplicitStyle
|
|
|
|
{
|
|
|
|
get { return _implicitStyle; }
|
2016-04-26 01:03:33 +03:00
|
|
|
set { SetStyle(value, ClassStyles, Style); }
|
2016-03-22 23:02:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Apply(BindableObject bindable)
|
|
|
|
{
|
|
|
|
ImplicitStyle?.Apply(bindable);
|
2016-04-26 01:03:33 +03:00
|
|
|
if (ClassStyles != null)
|
|
|
|
foreach (var classStyle in ClassStyles)
|
|
|
|
((IStyle)classStyle)?.Apply(bindable);
|
2016-03-22 23:02:25 +03:00
|
|
|
Style?.Apply(bindable);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Type TargetType { get; }
|
|
|
|
|
|
|
|
public void UnApply(BindableObject bindable)
|
|
|
|
{
|
|
|
|
Style?.UnApply(bindable);
|
2016-04-26 01:03:33 +03:00
|
|
|
if (ClassStyles != null)
|
|
|
|
foreach (var classStyle in ClassStyles)
|
|
|
|
((IStyle)classStyle)?.UnApply(bindable);
|
2016-03-22 23:02:25 +03:00
|
|
|
ImplicitStyle?.UnApply(bindable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnClassStyleChanged()
|
|
|
|
{
|
2016-04-26 01:03:33 +03:00
|
|
|
ClassStyles = _classStyleProperties.Select (p => (Target.GetValue (p) as IList<Style>)?.FirstOrDefault (s => s.CanBeAppliedTo (TargetType))).ToList ();
|
2016-03-22 23:02:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnImplicitStyleChanged()
|
|
|
|
{
|
|
|
|
var first = true;
|
|
|
|
foreach (BindableProperty implicitStyleProperty in _implicitStyles)
|
|
|
|
{
|
|
|
|
var implicitStyle = (Style)Target.GetValue(implicitStyleProperty);
|
|
|
|
if (implicitStyle != null)
|
|
|
|
{
|
|
|
|
if (first || implicitStyle.ApplyToDerivedTypes)
|
|
|
|
{
|
|
|
|
ImplicitStyle = implicitStyle;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RegisterImplicitStyles()
|
|
|
|
{
|
|
|
|
Type type = TargetType;
|
2017-03-03 01:28:37 +03:00
|
|
|
while (true) {
|
2016-03-22 23:02:25 +03:00
|
|
|
BindableProperty implicitStyleProperty = BindableProperty.Create("ImplicitStyle", typeof(Style), typeof(VisualElement), default(Style),
|
2017-03-03 01:28:37 +03:00
|
|
|
propertyChanged: (bindable, oldvalue, newvalue) => OnImplicitStyleChanged());
|
2016-03-22 23:02:25 +03:00
|
|
|
_implicitStyles.Add(implicitStyleProperty);
|
2017-03-03 01:28:37 +03:00
|
|
|
Target.SetDynamicResource(implicitStyleProperty, type.FullName);
|
2016-03-22 23:02:25 +03:00
|
|
|
type = type.GetTypeInfo().BaseType;
|
|
|
|
if (s_stopAtTypes.Contains(type))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-26 01:03:33 +03:00
|
|
|
void SetStyle(IStyle implicitStyle, IList<Style> classStyles, IStyle style)
|
2016-03-22 23:02:25 +03:00
|
|
|
{
|
2016-04-26 01:03:33 +03:00
|
|
|
bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles || Style != style;
|
|
|
|
bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles;
|
2016-03-22 23:02:25 +03:00
|
|
|
bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
|
|
|
|
|
|
|
|
if (shouldReApplyStyle)
|
|
|
|
Style?.UnApply(Target);
|
2016-04-26 01:03:33 +03:00
|
|
|
if (shouldReApplyClassStyle && ClassStyles != null)
|
|
|
|
foreach (var classStyle in ClassStyles)
|
|
|
|
((IStyle)classStyle)?.UnApply(Target);
|
2016-03-22 23:02:25 +03:00
|
|
|
if (shouldReApplyImplicitStyle)
|
|
|
|
ImplicitStyle?.UnApply(Target);
|
|
|
|
|
|
|
|
_implicitStyle = implicitStyle;
|
2016-04-26 01:03:33 +03:00
|
|
|
_classStyles = classStyles;
|
2016-03-22 23:02:25 +03:00
|
|
|
_style = style;
|
|
|
|
|
|
|
|
if (shouldReApplyImplicitStyle)
|
|
|
|
ImplicitStyle?.Apply(Target);
|
2016-04-26 01:03:33 +03:00
|
|
|
if (shouldReApplyClassStyle && ClassStyles != null)
|
|
|
|
foreach (var classStyle in ClassStyles)
|
|
|
|
((IStyle)classStyle)?.Apply(Target);
|
2016-03-22 23:02:25 +03:00
|
|
|
if (shouldReApplyStyle)
|
|
|
|
Style?.Apply(Target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|