/// <summary> /// This method inserts newArgument before the current index-th argument of this /// element. If index is 0, or if index is one more than the current number /// of arguments, newArgument is appended as the last argument. This frequently /// differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement InsertArgument(MathMLElement newArgument, int index) { if (index == 0) { element.AppendChild(newArgument); } else { element.InsertBefore(newArgument, arguments.Item(index)); } return(newArgument); }
private IEnumerable <Tuple <string, int, string> > GetAttributes(Type type, MathMLElement element) { var attributes = new List <Tuple <string, int, string> >(); var properties = type.GetProperties(); foreach (var property in properties) { var isAttribute = false; var attributeName = ""; var attributeOrderIndex = 100; object defaultPropertyValue = null; var propertyAttributes = property.GetCustomAttributes(true); foreach (var propertyAttribute in propertyAttributes) { if (propertyAttribute is MathMLAttributeName) { isAttribute = true; attributeName = ((MathMLAttributeName)propertyAttribute).AttributeName; } else if (propertyAttribute is MathMLAttributeOrderIndex) { attributeOrderIndex = ((MathMLAttributeOrderIndex)propertyAttribute).OrderIndex; } else if (propertyAttribute is DefaultValue) { defaultPropertyValue = ((DefaultValue)propertyAttribute).Value; } } if (isAttribute) { var propertyValue = property.GetValue(element, null); var attributeValue = SerializeAttributeValue(propertyValue); var defaultAttributeValue = SerializeAttributeValue(defaultPropertyValue); if (attributeValue != defaultAttributeValue) { attributes.Add(new Tuple <string, int, string>(attributeName, attributeOrderIndex, attributeValue)); } } } return(attributes.OrderBy(a => a.Item2)); }
private string SerializeMathMLElement(MathMLElement element) { var type = GetMathMLElementType(element); var elementName = GetElementName(type); var attributes = GetAttributes(type, element); var attributeString = string.Join("", attributes.Select(a => string.Format(" {0}=\"{1}\"", a.Item1, a.Item3))); var childElementsString = ""; foreach (var node in element.Children) { childElementsString += SerializeMathMLNode(node); } return(string.Format("<{0}{1}>{2}</{3}>", elementName, attributeString, childElementsString, elementName)); }
/// <summary> /// This method sets newArgument as the index-th argument of this element. /// If there is currently an index-th argument, it is replaced by newArgument. /// This frequently differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement SetArgument(MathMLElement newArgument, int index) { XmlNode node = arguments.Item(index); if (node != null) { node = element.ReplaceChild(newArgument, node); } else if (index == arguments.Count + 1) { node = element.AppendChild(newArgument); } else { // this is bad, should throw some sort of exceptionb } return((MathMLElement)node); }
/// <summary> /// This method inserts newArgument before the current index-th argument of this /// element. If index is 0, or if index is one more than the current number /// of arguments, newArgument is appended as the last argument. This frequently /// differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement InsertArgument(MathMLElement newArgument, int index) { if(index == 0) { element.AppendChild(newArgument); } else { element.InsertBefore(newArgument, arguments.Item(index)); } return newArgument; }
internal MathMLPresentationTokenNodeList(MathMLElement p) { list = p.ChildNodes; }
internal MathMLArgumentsList(MathMLElement p) { parent = p; }
internal MathMLDeclarationsList(MathMLElement p) { parent = p; }
/// <summary> /// This method sets newArgument as the index-th argument of this element. /// If there is currently an index-th argument, it is replaced by newArgument. /// This frequently differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement SetArgument(MathMLElement newArgument, int index) { return(container.SetArgument(newArgument, index)); }
private Area FormatFencedContainer(MathMLElement e, IFormattingContext context, ArrayList arguments, char[] separators, String open, String close) { BoundingBox extent = BoundingBox.New(); int argCount = arguments.Count; int openCount = open.Length > 0 ? 1 : 0; int closeCount = close.Length > 0 ? 1 : 0; // list to hold fences, childs and separators Area[] areas = new Area[openCount + closeCount + argCount + (argCount > 1 ? argCount - 1 : 0)]; // process all nodes that are not stretchy operators, get thier total // extents for(int i = 0, j = 0; i < argCount; i++) { MathMLElement element = (MathMLElement)arguments[i]; MathMLOperatorElement op = element as MathMLOperatorElement; if(op == null || op.Stretchy == false) { areas[i + j + openCount] = (Area)element.Accept(this, context); extent.Append(areas[i + j + openCount].BoundingBox); } // insert a separator if(i + 1 < argCount) { // at the next child node, but i has not been bumped yet areas[i + j + openCount + 1] = GlyphFactory.GetGlyph(context, context.Size, separators[j < separators.Length ? j : separators.Length - 1]); j++; } } if(!context.Stretch.Defined) { // avail width is epsilon because stretchy glyphs were not counted in the // width calculation context.Stretch = BoundingBox.New(Single.Epsilon, extent.Height, extent.Depth); } else { // calculate availible width context.StretchWidth = context.StretchWidth - extent.Width; if(context.Stretch.Width < 0) context.StretchWidth = 0; } // process all areas that need to be stretched for(int i = 0, j = 0; i < argCount; i++) { MathMLOperatorElement op = arguments[i] as MathMLOperatorElement; if(op != null && op.Stretchy) { areas[i + openCount + j] = (Area)op.Accept(this, context); context.StretchWidth -= areas[i + openCount + j].BoundingBox.Width; if(context.Stretch.Width < 0) context.StretchWidth = 0; // adjust sep index if (i + 1 < argCount) j++; } } // add fenced elements, these only stretchy vertically context.StretchWidth = 0; if(openCount > 0) { areas[0] = open.Length > 1 ? AreaFactory.String(context, open) : GlyphFactory.GetStretchyGlyph(context, context.Size, open[0], context.Stretch); } if(closeCount > 0) { areas[areas.Length - 1] = close.Length > 1 ? AreaFactory.String(context, close) : GlyphFactory.GetStretchyGlyph(context, context.Size, close[0], context.Stretch); } return AreaFactory.Horizontal(areas); }
/** * There was an error processing a node, create an error node. * wrap the completed area with a MathMLWrapper area and set the * elements area field to point to the newly completed area */ private Area Error(IFormattingContext ctx, MathMLElement e, String errorMsg) { Debug.WriteLine("Error Formatting " + e.GetType().Name + " element, " + errorMsg); Area area = AreaFactory.String(ctx, "?"); area = AreaFactory.Color(Color.Red, area); area = new MathMLWrapperArea(area, e); Area.SetArea(e, area); return area; }
/** * wrap the completed area with a MathMLWrapper area and set the * elements area field to point to the newly completed area */ private Area CompleteArea(IFormattingContext ctx, MathMLElement e, Area area) { if(ctx.cacheArea) { area = new MathMLWrapperArea(area, e); Area.SetArea(e, area); } return area; }
/// <summary> /// Format a row of elements. This can be either a presentation container or a mrow /// </summary> private Area FormatContainer(MathMLElement e, IFormattingContext ctx, ArrayList arguments) { IFormattingContext context = ctx.Clone(); BoundingBox extent = BoundingBox.New(); Area[] areas = new Area[arguments.Count]; int stretchCount = 0; // save the stretch size because stretch scope can not extend into another // level of nesting BoundingBox stretch = context.Stretch; context.Stretch = BoundingBox.New(); // process all nodes that are not stretchy operators, get thier total // extents for(int i = 0; i < arguments.Count; i++) { MathMLElement element = (MathMLElement)arguments[i]; MathMLOperatorElement op = element as MathMLOperatorElement; if(op == null || op.Stretchy == false) { areas[i] = (Area)element.Accept(this, context); extent.Append(areas[i].BoundingBox); } if(op != null && op.Stretchy) { stretchCount++; } } // if we have any elements that can be stretched, stretch them if(stretchCount > 0) { if(!stretch.Defined) { // avail width is epsilon because stretchy glyphs were not counted in the // width calculation context.Stretch = BoundingBox.New(Single.Epsilon, extent.Height, extent.Depth); } else { // set the stretch size back to stretch the child elements context.Stretch = stretch; // calculate availible width context.StretchWidth = context.Stretch.Width - extent.Width; if(context.Stretch.Width < 0) context.StretchWidth = 0; // size to stretch each width equally context.StretchWidth = context.Stretch.Width / (float)stretchCount; } // process all areas that need to be stretched for(int i = 0; i < arguments.Count; i++) { MathMLOperatorElement op = arguments[i] as MathMLOperatorElement; if(op != null && op.Stretchy) { areas[i] = (Area)op.Accept(this, context); } } } Area area = AreaFactory.Horizontal(areas); // hide the areas if it is a phantom if(e.Name == "mphantom") { area = AreaFactory.Hide(area); } else if(e.Name == "merror") { area = AreaFactory.Color(Color.Red, area); } // table cell areas elemetns area a special case, they get 'Completed' // in the MathMLTableCellElement method return area; }
/// <summary> /// create the enumerator. the enumerator is initially created with the /// current element set before the collection /// </summary> /// <param name="p">the parent node</param> internal MathMLArgumentsEnumerator(MathMLElement p) { parent = p; }
public MathMLContainerImpl(MathMLElement e) { element = e; arguments = new MathMLArgumentsList(e); declarations = new MathMLDeclarationsList(e); }
/// <summary> /// This method sets newArgument as the index-th argument of this element. /// If there is currently an index-th argument, it is replaced by newArgument. /// This frequently differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement SetArgument(MathMLElement newArgument, int index) { XmlNode node = arguments.Item(index); if(node != null) { node = element.ReplaceChild(newArgument, node); } else if(index == arguments.Count + 1) { node = element.AppendChild(newArgument); } else { // this is bad, should throw some sort of exceptionb } return (MathMLElement)node; }
/// <summary> /// This method inserts newArgument before the current index-th argument of this /// element. If index is 0, or if index is one more than the current number /// of arguments, newArgument is appended as the last argument. This frequently /// differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement InsertArgument(MathMLElement newArgument, int index) { return(container_impl.InsertArgument(newArgument, index)); }
/// <summary> /// This method sets newArgument as the index-th argument of this element. /// If there is currently an index-th argument, it is replaced by newArgument. /// This frequently differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement SetArgument(MathMLElement newArgument, int index) { return container.SetArgument(newArgument, index); }
private Type GetMathMLElementType(MathMLElement element) { if (element is MathMLEnclose) { return(typeof(MathMLEnclose)); } if (element is MathMLFenced) { return(typeof(MathMLFenced)); } if (element is MathMLFraction) { return(typeof(MathMLFraction)); } if (element is MathMLGlyph) { return(typeof(MathMLGlyph)); } if (element is MathMLIdentifier) { return(typeof(MathMLIdentifier)); } if (element is MathMLLabeledTableRow) { return(typeof(MathMLLabeledTableRow)); } if (element is MathMLLongDivision) { return(typeof(MathMLLongDivision)); } if (element is MathMLMath) { return(typeof(MathMLMath)); } if (element is MathMLMultiscripts) { return(typeof(MathMLMultiscripts)); } if (element is MathMLNumber) { return(typeof(MathMLNumber)); } if (element is MathMLOperator) { return(typeof(MathMLOperator)); } if (element is MathMLOver) { return(typeof(MathMLOver)); } if (element is MathMLPadded) { return(typeof(MathMLPadded)); } if (element is MathMLPhantom) { return(typeof(MathMLPhantom)); } if (element is MathMLRoot) { return(typeof(MathMLRoot)); } if (element is MathMLRow) { return(typeof(MathMLRow)); } if (element is MathMLSpace) { return(typeof(MathMLSpace)); } if (element is MathMLSquareRoot) { return(typeof(MathMLSquareRoot)); } if (element is MathMLStyle) { return(typeof(MathMLStyle)); } if (element is MathMLSubscript) { return(typeof(MathMLSubscript)); } if (element is MathMLSubscriptSuperscript) { return(typeof(MathMLSubscriptSuperscript)); } if (element is MathMLSuperscript) { return(typeof(MathMLSuperscript)); } if (element is MathMLTable) { return(typeof(MathMLTable)); } if (element is MathMLTableCell) { return(typeof(MathMLTableCell)); } if (element is MathMLTableRow) { return(typeof(MathMLTableRow)); } if (element is MathMLText) { return(typeof(MathMLText)); } if (element is MathMLUnder) { return(typeof(MathMLUnder)); } if (element is MathMLUnderOver) { return(typeof(MathMLUnderOver)); } throw new UnknownMathMLElementException(); }
/// <summary> /// This method inserts newArgument before the current index-th argument of this /// element. If index is 0, or if index is one more than the current number /// of arguments, newArgument is appended as the last argument. This frequently /// differs from setting the node at Node::childNodes().item(index), /// as qualifier elements and declare elements are not counted. /// </summary> public MathMLElement InsertArgument(MathMLElement newArgument, int index) { return container_impl.InsertArgument(newArgument, index); }