488 lines
14 KiB
C#
488 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using Value = System.Object;
|
|
|
|
namespace Ooui
|
|
{
|
|
public class Style : INotifyPropertyChanged
|
|
{
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
readonly Dictionary<string, Value> properties =
|
|
new Dictionary<string, Value> ();
|
|
static readonly private char[] numberChars = new char[] {
|
|
'0','1','2','3','4','5','6','7','8','9',
|
|
'.','-','+',
|
|
};
|
|
|
|
public Value AlignSelf {
|
|
get => this["align-self"];
|
|
set => this["align-self"] = value;
|
|
}
|
|
public Value BackfaceVisibility {
|
|
get => this["backface-visibility"];
|
|
set => this["backface-visibility"] = value;
|
|
}
|
|
|
|
public Value BackgroundColor {
|
|
get => this["background-color"];
|
|
set => this["background-color"] = value;
|
|
}
|
|
|
|
public Value BackgroundImage {
|
|
get => this["background-image"];
|
|
set => this["background-image"] = AddUrl(value);
|
|
}
|
|
|
|
public Value BackgroundPosition {
|
|
get => this["background-position"];
|
|
set => this["background-position"] = value;
|
|
}
|
|
|
|
public Value BorderTopColor {
|
|
get => this["border-top-color"];
|
|
set => this["border-top-color"] = value;
|
|
}
|
|
|
|
public Value BorderRightColor {
|
|
get => this["border-right-color"];
|
|
set => this["border-right-color"] = value;
|
|
}
|
|
|
|
public Value BorderBottomColor {
|
|
get => this["border-bottom-color"];
|
|
set => this["border-bottom-color"] = value;
|
|
}
|
|
|
|
public Value BorderLeftColor {
|
|
get => this["border-left-color"];
|
|
set => this["border-left-color"] = value;
|
|
}
|
|
|
|
public Value BorderColor {
|
|
get => this["border-top-color"];
|
|
set {
|
|
this["border-top-color"] = value;
|
|
this["border-right-color"] = value;
|
|
this["border-bottom-color"] = value;
|
|
this["border-left-color"] = value;
|
|
}
|
|
}
|
|
|
|
public Value BorderTopStyle {
|
|
get => this["border-top-style"];
|
|
set => this["border-top-style"] = value;
|
|
}
|
|
|
|
public Value BorderRightStyle {
|
|
get => this["border-right-style"];
|
|
set => this["border-right-style"] = value;
|
|
}
|
|
|
|
public Value BorderBottomStyle {
|
|
get => this["border-bottom-style"];
|
|
set => this["border-bottom-style"] = value;
|
|
}
|
|
|
|
public Value BorderLeftStyle {
|
|
get => this["border-left-style"];
|
|
set => this["border-left-style"] = value;
|
|
}
|
|
|
|
public Value BorderStyle {
|
|
get => this["border-top-style"];
|
|
set {
|
|
this["border-top-style"] = value;
|
|
this["border-right-style"] = value;
|
|
this["border-bottom-style"] = value;
|
|
this["border-left-style"] = value;
|
|
}
|
|
}
|
|
|
|
public Value BorderTopWidth {
|
|
get => this["border-top-width"];
|
|
set => this["border-top-width"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value BorderRightWidth {
|
|
get => this["border-right-width"];
|
|
set => this["border-right-width"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value BorderBottomWidth {
|
|
get => this["border-bottom-width"];
|
|
set => this["border-bottom-width"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value BorderLeftWidth {
|
|
get => this["border-left-width"];
|
|
set => this["border-left-width"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value BorderRadius {
|
|
get => this["border-radius"];
|
|
set {
|
|
this["border-radius"] = AddNumberUnits (value, "px");
|
|
}
|
|
}
|
|
|
|
public Value BorderWidth {
|
|
get => this["border-top-width"];
|
|
set {
|
|
this["border-top-width"] = AddNumberUnits (value, "px");
|
|
this["border-right-width"] = AddNumberUnits (value, "px");
|
|
this["border-bottom-width"] = AddNumberUnits (value, "px");
|
|
this["border-left-width"] = AddNumberUnits (value, "px");
|
|
}
|
|
}
|
|
|
|
public Value Bottom {
|
|
get => this["bottom"];
|
|
set => this["bottom"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value Clear {
|
|
get => this["clear"];
|
|
set => this["clear"] = value;
|
|
}
|
|
|
|
public Value Color {
|
|
get => this["color"];
|
|
set => this["color"] = value;
|
|
}
|
|
|
|
public Value Cursor {
|
|
get => this["cursor"];
|
|
set => this["cursor"] = value;
|
|
}
|
|
|
|
public Value Display {
|
|
get => this["display"];
|
|
set => this["display"] = value;
|
|
}
|
|
|
|
public Value FlexFlow {
|
|
get => this["flex-flow"];
|
|
set => this["flex-flow"] = value;
|
|
}
|
|
|
|
public Value FlexGrow {
|
|
get => this["flex-grow"];
|
|
set => this["flex-grow"] = value;
|
|
}
|
|
|
|
public Value FlexShrink {
|
|
get => this["flex-shrink"];
|
|
set => this["flex-shrink"] = value;
|
|
}
|
|
|
|
public Value Float {
|
|
get => this["float"];
|
|
set => this["float"] = value;
|
|
}
|
|
|
|
public Value FontFamily {
|
|
get => this["font-family"];
|
|
set => this["font-family"] = value;
|
|
}
|
|
|
|
public Value FontSize {
|
|
get => this["font-size"];
|
|
set => this["font-size"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value FontStyle {
|
|
get => this["font-style"];
|
|
set => this["font-style"] = value;
|
|
}
|
|
|
|
public Value FontVariant {
|
|
get => this["font-variant"];
|
|
set => this["font-variant"] = value;
|
|
}
|
|
|
|
public Value FontWeight {
|
|
get => this["font-weight"];
|
|
set => this["font-weight"] = value;
|
|
}
|
|
|
|
public Value Height {
|
|
get => this["height"];
|
|
set => this["height"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value Left {
|
|
get => this["left"];
|
|
set => this["left"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value LineHeight {
|
|
get => this["line-height"];
|
|
set => this["line-height"] = value;
|
|
}
|
|
|
|
public Value MarginTop {
|
|
get => this["margin-top"];
|
|
set => this["margin-top"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value MarginRight {
|
|
get => this["margin-right"];
|
|
set => this["margin-right"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value MarginBottom {
|
|
get => this["margin-bottom"];
|
|
set => this["margin-bottom"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value MarginLeft {
|
|
get => this["margin-left"];
|
|
set => this["margin-left"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value Margin {
|
|
get => this["margin-top"];
|
|
set {
|
|
this["margin-top"] = AddNumberUnits (value, "px");
|
|
this["margin-right"] = AddNumberUnits (value, "px");
|
|
this["margin-bottom"] = AddNumberUnits (value, "px");
|
|
this["margin-left"] = AddNumberUnits (value, "px");
|
|
}
|
|
}
|
|
|
|
public Value Opacity {
|
|
get => this["opacity"];
|
|
set => this["opacity"] = value;
|
|
}
|
|
|
|
public Value Order {
|
|
get => this["order"];
|
|
set => this["order"] = value;
|
|
}
|
|
|
|
public Value Overflow {
|
|
get => this["overflow"];
|
|
set => this["overflow"] = value;
|
|
}
|
|
|
|
public Value PaddingTop {
|
|
get => this["padding-top"];
|
|
set => this["padding-top"] = value;
|
|
}
|
|
|
|
public Value PaddingRight {
|
|
get => this["padding-right"];
|
|
set => this["padding-right"] = value;
|
|
}
|
|
|
|
public Value PaddingBottom {
|
|
get => this["padding-bottom"];
|
|
set => this["padding-bottom"] = value;
|
|
}
|
|
|
|
public Value PaddingLeft {
|
|
get => this["padding-left"];
|
|
set => this["padding-left"] = value;
|
|
}
|
|
|
|
public Value Padding {
|
|
get => this["padding-top"];
|
|
set {
|
|
this["padding-top"] = value;
|
|
this["padding-right"] = value;
|
|
this["padding-bottom"] = value;
|
|
this["padding-left"] = value;
|
|
}
|
|
}
|
|
|
|
public Value Perspective {
|
|
get => this["perspective"];
|
|
set => this["perspective"] = value;
|
|
}
|
|
|
|
public Value Position {
|
|
get => this["position"];
|
|
set => this["position"] = value;
|
|
}
|
|
|
|
public Value Right {
|
|
get => this["right"];
|
|
set => this["right"] = value;
|
|
}
|
|
|
|
public Value TextAlign {
|
|
get => this["text-align"];
|
|
set => this["text-align"] = value;
|
|
}
|
|
|
|
public Value TextDecoration {
|
|
get => this["text-decoration"];
|
|
set => this["text-decoration"] = value;
|
|
}
|
|
|
|
public Value Top {
|
|
get => this["top"];
|
|
set => this["top"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value Transform {
|
|
get => this["transform"];
|
|
set => this["transform"] = value;
|
|
}
|
|
|
|
public Value TransformOrigin {
|
|
get => this["transform-origin"];
|
|
set => this["transform-origin"] = value;
|
|
}
|
|
|
|
public Value TransformStyle {
|
|
get => this["transform-style"];
|
|
set => this["transform-style"] = value;
|
|
}
|
|
|
|
public Value Transition
|
|
{
|
|
get => this["transition"];
|
|
set => this["transition"] = value;
|
|
}
|
|
|
|
public Value VerticalAlign {
|
|
get => this["vertical-align"];
|
|
set => this["vertical-align"] = value;
|
|
}
|
|
|
|
public Value Visibility {
|
|
get => this["visibility"];
|
|
set => this["visibility"] = value;
|
|
}
|
|
|
|
public Value Width {
|
|
get => this["width"];
|
|
set => this["width"] = AddNumberUnits (value, "px");
|
|
}
|
|
|
|
public Value ZIndex {
|
|
get => this["z-index"];
|
|
set => this["z-index"] = value;
|
|
}
|
|
|
|
public Value this[string propertyName] {
|
|
get {
|
|
lock (properties) {
|
|
Value p;
|
|
if (!properties.TryGetValue (propertyName, out p)) {
|
|
p = "inherit";
|
|
}
|
|
return p;
|
|
}
|
|
}
|
|
set {
|
|
var safeValue = value ?? "inherit";
|
|
lock (properties) {
|
|
if (value == null) {
|
|
if (!properties.Remove (propertyName))
|
|
return;
|
|
}
|
|
else {
|
|
Value old;
|
|
if (properties.TryGetValue (propertyName, out old)) {
|
|
if (EqualityComparer<Value>.Default.Equals (old, safeValue))
|
|
return;
|
|
}
|
|
properties[propertyName] = safeValue;
|
|
}
|
|
}
|
|
PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
|
|
}
|
|
}
|
|
|
|
public static string GetJsName (string propertyName)
|
|
{
|
|
var o = new System.Text.StringBuilder ();
|
|
var needsCap = false;
|
|
for (var i = 0; i < propertyName.Length; i++) {
|
|
var c = propertyName[i];
|
|
if (c == '-') {
|
|
needsCap = true;
|
|
}
|
|
else {
|
|
o.Append (needsCap ? Char.ToUpperInvariant (c) : c);
|
|
needsCap = false;
|
|
}
|
|
}
|
|
return o.ToString ();
|
|
}
|
|
|
|
public override string ToString ()
|
|
{
|
|
var o = new System.Text.StringBuilder ();
|
|
var head = "";
|
|
lock (properties) {
|
|
foreach (var p in properties) {
|
|
o.Append (head);
|
|
o.Append (p.Key);
|
|
o.Append (":");
|
|
o.Append (Convert.ToString (p.Value, System.Globalization.CultureInfo.InvariantCulture));
|
|
head = ";";
|
|
}
|
|
}
|
|
return o.ToString ();
|
|
}
|
|
static string AddUrl(object val)
|
|
{
|
|
if (val == null)
|
|
return null;
|
|
return String.Format("url('{0}')", val);
|
|
}
|
|
|
|
static string AddNumberUnits (object val, string units)
|
|
{
|
|
if (val == null)
|
|
return null;
|
|
if (val is string s)
|
|
return s;
|
|
|
|
if (val is int i)
|
|
return i + units;
|
|
if (val is double d)
|
|
return d.ToString (System.Globalization.CultureInfo.InvariantCulture) + units;
|
|
if (val is float f)
|
|
return f.ToString (System.Globalization.CultureInfo.InvariantCulture) + units;
|
|
|
|
if (val is IConvertible c)
|
|
return c.ToString (System.Globalization.CultureInfo.InvariantCulture) + units;
|
|
|
|
return val.ToString ();
|
|
}
|
|
|
|
public double GetNumberWithUnits (string key, string units, double baseValue)
|
|
{
|
|
var v = this[key];
|
|
if (v == null)
|
|
return 0;
|
|
|
|
if (v is string s) {
|
|
var lastIndex = s.LastIndexOfAny (numberChars);
|
|
if (lastIndex < 0)
|
|
return 0;
|
|
var num = double.Parse (s.Substring (0, lastIndex + 1), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
|
|
return num;
|
|
}
|
|
|
|
if (v is int i)
|
|
return i;
|
|
if (v is double d)
|
|
return d;
|
|
if (v is float f)
|
|
return f;
|
|
|
|
if (v is IConvertible c)
|
|
return c.ToDouble (System.Globalization.CultureInfo.InvariantCulture);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|