using System;
using System.Text.RegularExpressions;
#if TEST
using NUnit.Framework;
#endif
namespace SharpVectors.Dom.Css{
public class CssPrimitiveAngleValue : CssPrimitiveValue
{
#region Constructors
public CssPrimitiveAngleValue(string number, string unit, bool readOnly) : base(number+unit, readOnly)
{
_setType(unit);
_setFloatValue(number);
}
public CssPrimitiveAngleValue(string cssText, bool readOnly) : base(cssText, readOnly)
{
_setCssText(cssText);
}
public CssPrimitiveAngleValue(double number, string unit, bool readOnly) : base(number+unit, readOnly)
{
_setType(unit);
_setFloatValue(number);
}
#endregion
protected internal override void _setCssText(string cssText)
{
Regex re = new Regex(CssValue.AnglePattern);
Match match = re.Match(cssText);
if(match.Success)
{
_setType(match.Groups["angleUnit"].Value);
_setFloatValue(match.Groups["angleNumber"].Value);
}
else
{
throw new DomException(DomExceptionType.SyntaxErr, "Unrecognized angle format: " + cssText);
}
}
private void _setType(string unit)
{
switch(unit)
{
case "":
_setType(CssPrimitiveType.Number);
break;
case "deg":
_setType(CssPrimitiveType.Deg);
break;
case "rad":
_setType(CssPrimitiveType.Rad);
break;
case "grad":
_setType(CssPrimitiveType.Grad);
break;
default:
throw new DomException(DomExceptionType.SyntaxErr, "Unknown angle unit");
}
}
// only for absolute values
private double _getDegAngle()
{
double ret;
switch(PrimitiveType)
{
case CssPrimitiveType.Rad:
ret = floatValue * 180 / Math.PI;
break;
case CssPrimitiveType.Grad:
ret = floatValue *90 / 100;
break;
default:
ret = floatValue;
break;
}
ret %= 360;
while(ret<0) ret += 360;
return ret;
}
public override double GetFloatValue(CssPrimitiveType unitType)
{
double ret = Double.NaN;
switch(unitType)
{
case CssPrimitiveType.Number:
case CssPrimitiveType.Deg:
ret = _getDegAngle();
break;
case CssPrimitiveType.Rad:
ret = _getDegAngle() * Math.PI / 180;
break;
case CssPrimitiveType.Grad:
ret = _getDegAngle() * 100 / 90;
break;
}
if(Double.IsNaN(ret))
{
throw new DomException(DomExceptionType.InvalidAccessErr);
}
else
{
return ret;
}
}
public override string CssText
{
get
{
return GetFloatValue(PrimitiveType).ToString(CssNumber.Format) + PrimitiveTypeAsString;
}
}
#region Unit tests
#if TEST
[TestFixture]
public class CssPrimitiveAngleValueTests : CssValueTests
{
CssPrimitiveAngleValue angle;
protected override string aCssText
{
get{return "12deg";}
}
protected override string anotherCssText
{
get{return "2rad";}
}
protected override CssValueType cssValueType
{
get{return CssValueType.PrimitiveValue;}
}
protected override CssValue _getCssValue(string cssText, bool readOnly)
{
return new CssPrimitiveAngleValue(aCssText, readOnly);
}
protected override Type Type
{
get{return typeof(CssPrimitiveAngleValue);}
}
[Test]
public void TestDegValue()
{
angle = new CssPrimitiveAngleValue("90deg", false);
Assert.AreEqual(90, angle.GetFloatValue(CssPrimitiveType.Deg));
Assert.AreEqual(100, angle.GetFloatValue(CssPrimitiveType.Grad));
Assert.AreEqual(Math.PI/2, angle.GetFloatValue(CssPrimitiveType.Rad));
angle = new CssPrimitiveAngleValue("47", false);
Assert.AreEqual(47, angle.GetFloatValue(CssPrimitiveType.Deg));
angle = new CssPrimitiveAngleValue("385deg", false);
Assert.AreEqual(25, angle.GetFloatValue(CssPrimitiveType.Deg));
angle = new CssPrimitiveAngleValue("-90deg", false);
Assert.AreEqual(270, angle.GetFloatValue(CssPrimitiveType.Deg));
}
[Test]
public void TestRadValue()
{
angle = new CssPrimitiveAngleValue("1rad", false);
Assert.AreEqual(1, angle.GetFloatValue(CssPrimitiveType.Rad));
Assert.AreEqual(1 * 180 / Math.PI, angle.GetFloatValue(CssPrimitiveType.Deg));
Assert.AreEqual(1 * 200 / Math.PI, angle.GetFloatValue(CssPrimitiveType.Grad));
angle = new CssPrimitiveAngleValue("-2rad", false);
Assert.AreEqual(2*Math.PI - 2, angle.GetFloatValue(CssPrimitiveType.Rad));
angle = new CssPrimitiveAngleValue("8rad", false);
Assert.AreEqual(8%(2*Math.PI), angle.GetFloatValue(CssPrimitiveType.Rad));
}
[Test]
public void TestGradValue()
{
angle = new CssPrimitiveAngleValue("100grad", false);
Assert.AreEqual(100, angle.GetFloatValue(CssPrimitiveType.Grad));
Assert.AreEqual(90, angle.GetFloatValue(CssPrimitiveType.Deg));
Assert.AreEqual(Math.PI / 2, angle.GetFloatValue(CssPrimitiveType.Rad));
angle = new CssPrimitiveAngleValue("600grad", false);
Assert.AreEqual(200, angle.GetFloatValue(CssPrimitiveType.Grad));
}
}
#endif
#endregion
}
}
|