protected override void OnAfterApplyHorizontalAlignmentAndWidth() { // It is important that the "ContentEditable" div has the same CSS size properties as the outer div, so that the overflow and scrolling work properly: if (_contentEditableDiv != null) //this can be true in the case where a template has been defined, in which case we wait for the template to be created before adding the text area. { var outerDomStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this); var contentEditableStyle = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(_contentEditableDiv); if (Host.HorizontalContentAlignment == HorizontalAlignment.Stretch) { contentEditableStyle.width = "100%"; contentEditableStyle.maxWidth = outerDomStyle.maxWidth; } else //it is top, bottom or center so we don't want to stretch, but we want it to be limited as much as the outerDomElement { if (double.IsNaN(Width)) { if (!double.IsNaN(MaxWidth)) { contentEditableStyle.maxWidth = outerDomStyle.maxWidth; }//else, neither Width or maxWidth are set so we let it be. } else { double contentEditableMaxWidth = Math.Max(0, Width - Host.BorderThickness.Left - Host.BorderThickness.Right); contentEditableStyle.maxWidth = contentEditableMaxWidth.ToInvariantString() + "px"; //note: this might be incorrect as it does not take into consideration any padding, margin, or other elements that happens between outerDomElement and contentEditableDiv. } } } }
private void RefreshEffect() //todo: if we add support for multiple effects on a same element, return the string instead of directly setting the property. { if (_parentUIElement != null && INTERNAL_VisualTreeManager.IsElementInVisualTree(_parentUIElement)) { var domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(_parentUIElement); double x, y; GetXYPositionFromDirectionAndDepth(out x, out y); double opacity = Math.Max(Math.Min(1.0, this.Opacity), 0.0); string shadowString = x.ToInvariantString() + "px " + y.ToInvariantString() + "px " + BlurRadius.ToInvariantString() + "px " + Color.FromArgb(Convert.ToByte(opacity * 255d), Color.R, Color.G, Color.B).INTERNAL_ToHtmlString(1d); if (_parentUIElement is TextBlock) { domStyle.textShadow = shadowString; } else { domStyle.boxShadow = shadowString; domStyle.borderCollapse = "separate"; // This is required for IE only. If this property is not set or equal to "collapse", the shadow does not render at all on IE. See: http://stackoverflow.com/questions/9949396/css-box-shadow-not-working-in-ie domStyle.borderSpacing = "0px"; // This is required to fix a bug that comes with the line above: a 2 px margin appears around the children of the element, which can lead to some elements overflowing relative to those children when they shouldn't. } } }
protected override void OnAfterApplyVerticalAlignmentAndWidth() { // It is important that the "ContentEditable" div has the same CSS size properties as the outer div, so that the overflow and scrolling work properly: if (_contentEditableDiv != null) //this can be true in the case where a template has been defined, in which case we wait for the template to be created before adding the text area. { var outerDomStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this); var contentEditableStyle = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(_contentEditableDiv); if (Host.VerticalContentAlignment == VerticalAlignment.Stretch) { contentEditableStyle.height = "100%"; contentEditableStyle.maxHeight = outerDomStyle.maxHeight; } else { if (double.IsNaN(Height)) { if (!double.IsNaN(MaxHeight)) { contentEditableStyle.maxHeight = outerDomStyle.maxHeight; }//else, neither Height or maxHeight are set so we let it be. } else { contentEditableStyle.maxHeight = outerDomStyle.height; //note: this might be incorrect as it does not take into consideration any padding or margin that happens between outerDomElement and contentEditableDiv. } } } }
static void Orientation_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { var wrapPanel = (WrapPanel)d; Orientation newValue = (Orientation)e.NewValue; if (INTERNAL_VisualTreeManager.IsElementInVisualTree(wrapPanel)) { //todo: change all the wrappers of the children to set their style.display to inline-block var el = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(wrapPanel); switch (wrapPanel.HorizontalAlignment) { case HorizontalAlignment.Left: el.textAlign = "left"; break; case HorizontalAlignment.Right: el.textAlign = "right"; break; case HorizontalAlignment.Center: el.textAlign = "center"; break; default: el.textAlign = "left"; break; } } }
static void TextAlignment_MethodToUpdateDom(DependencyObject d, object newValue) { var textBlock = (TextBlock)d; switch ((TextAlignment)newValue) { case TextAlignment.Center: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(textBlock).textAlign = "center"; break; case TextAlignment.Left: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(textBlock).textAlign = "left"; break; case TextAlignment.Right: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(textBlock).textAlign = "right"; break; case TextAlignment.Justify: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(textBlock).textAlign = "justify"; break; default: break; } }
internal override void INTERNAL_UnapplyTransform() { if (this.INTERNAL_parent != null && INTERNAL_VisualTreeManager.IsElementInVisualTree(this.INTERNAL_parent)) { dynamic domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this.INTERNAL_parent); string value = ""; try { domStyle.transform = value; } catch { } try { domStyle.msTransform = value; } catch { } try // Prevents crash in the simulator that uses IE. { domStyle.WebkitTransform = value; } catch { } } }
private static void CornerRadius_MethodToUpdateDom(DependencyObject d, object newValue) { var border = (Border)d; var cr = (CornerRadius)newValue; var domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(border); domStyle.borderRadius = $"{cr.TopLeft.ToString(CultureInfo.InvariantCulture)}px {cr.TopRight.ToString(CultureInfo.InvariantCulture)}px {cr.BottomRight.ToString(CultureInfo.InvariantCulture)}px {cr.BottomLeft.ToString(CultureInfo.InvariantCulture)}px"; }
private void UpdateCSSLineHeight(string value) { if (INTERNAL_VisualTreeManager.IsElementInVisualTree(this)) { var domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this); domStyle.lineHeight = value ?? ""; } }
private static void BorderThickness_MethodToUpdateDom(DependencyObject d, object newValue) { var border = (Border)d; var domElement = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(border); var thickness = (Thickness)newValue; domElement.boxSizing = "border-box"; domElement.borderStyle = "solid"; //todo: see if we should put this somewhere else domElement.borderWidth = $"{thickness.Top.ToString(CultureInfo.InvariantCulture)}px {thickness.Right.ToString(CultureInfo.InvariantCulture)}px {thickness.Bottom.ToString(CultureInfo.InvariantCulture)}px {thickness.Left.ToString(CultureInfo.InvariantCulture)}px"; }
static void CornerRadius_MethodToUpdateDom(DependencyObject d, object newValue) { var border = (Border)d; var cornerRadius = (CornerRadius)newValue; var domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(border); domStyle.borderTopLeftRadius = cornerRadius.TopLeft + "px"; domStyle.borderTopRightRadius = cornerRadius.TopRight + "px"; domStyle.borderBottomRightRadius = cornerRadius.BottomRight + "px"; domStyle.borderBottomLeftRadius = cornerRadius.BottomLeft + "px"; }
static void Orientation_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { var wrapPanel = (WrapPanel)d; Orientation newValue = (Orientation)e.NewValue; if (INTERNAL_VisualTreeManager.IsElementInVisualTree(wrapPanel)) { //todo: change all the wrappers of the children to set their style.display to inline-block INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(wrapPanel).textAlign = "left"; } }
private static void BorderThickness_MethodToUpdateDom(DependencyObject d, object newValue) { var control = (Control)d; if (!control.HasTemplate) { var newThickness = (Thickness)newValue; var domElement = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(control); domElement.borderStyle = "solid"; //todo: see if we should put this somewhere else domElement.borderWidth = $"{newThickness.Top.ToString(CultureInfo.InvariantCulture)}px {newThickness.Right.ToString(CultureInfo.InvariantCulture)}px {newThickness.Bottom.ToString(CultureInfo.InvariantCulture)}px {newThickness.Left.ToString(CultureInfo.InvariantCulture)}px"; } }
static void BorderThickness_MethodToUpdateDom(DependencyObject d, object newValue) { var control = (Control)d; if (!control.HasTemplate && newValue != null) //todo: check why sometimes this is null. { var newThickness = (Thickness)newValue; dynamic domElement = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(control); domElement.borderStyle = "solid"; //todo: see if we should put this somewhere else domElement.borderWidth = newThickness.Top + "px " + newThickness.Right + "px " + newThickness.Bottom + "px " + newThickness.Left + "px "; } }
/// <summary> /// This method fixes css property line-height for Rectangle. /// Line height is not needed in shapes because it was causing layout issues. /// </summary> /// <param name="shape"></param> internal void FixLineHeight(Shape shape) { if (shape == null) { return; } if (INTERNAL_VisualTreeManager.IsElementInVisualTree(shape)) { dynamic shapeDom = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(shape); shapeDom.lineHeight = "0"; } }
private static void OnTextTrimmedChangedUpdateDOM(DependencyObject d, object newValue) { var style = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification((TextBlock)d); switch ((TextTrimming)newValue) { case TextTrimming.CharacterEllipsis: case TextTrimming.WordEllipsis: style.textOverflow = "ellipsis"; break; default: style.textOverflow = "clip"; break; } }
static void BorderThickness_MethodToUpdateDom(DependencyObject d, object newValue) { if (newValue != null) { var border = (Border)d; dynamic domElement = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(border); var thickness = (Thickness)newValue; domElement.borderStyle = "solid"; //todo: see if we should put this somewhere else domElement.borderWidth = thickness.Top + "px " + thickness.Right + "px " + thickness.Bottom + "px " + thickness.Left + "px "; domElement.boxSizing = "border-box"; //domElement.borderWidth = // (newValue.Top > 0 ? newValue.Top + 1 : 0).ToString() + "px " // + (newValue.Right > 0 ? newValue.Right + 1 : 0).ToString() + "px " // + (newValue.Bottom > 0 ? newValue.Bottom + 1 : 0).ToString() + "px " // + (newValue.Left > 0 ? newValue.Left + 1 : 0).ToString() + "px "; } }
static void Orientation_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { var wrapPanel = (WrapPanel)d; Orientation newValue = (Orientation)e.NewValue; if (INTERNAL_VisualTreeManager.IsElementInVisualTree(wrapPanel)) { if (newValue == Orientation.Vertical) { throw new NotSupportedException("Vertical orientation is not yet supported for the WrapPanel"); } else { //todo: change all the wrappers of the children to set their style.display to inline-block INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(wrapPanel).textAlign = "left"; } } }
internal override void INTERNAL_ApplyTransform() { if (this.INTERNAL_parent != null && INTERNAL_VisualTreeManager.IsElementInVisualTree(this.INTERNAL_parent)) { dynamic domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this.INTERNAL_parent); var matrix = this.Matrix; string value = "matrix(" + matrix.M11.ToString(CultureInfo.InvariantCulture) + "," + matrix.M12.ToString(CultureInfo.InvariantCulture) + "," + matrix.M21.ToString(CultureInfo.InvariantCulture) + "," + matrix.M22.ToString(CultureInfo.InvariantCulture) + "," + matrix.OffsetX.ToString(CultureInfo.InvariantCulture) + "," + matrix.OffsetY.ToString(CultureInfo.InvariantCulture) + ")"; try { domStyle.transform = value; } catch { } try { domStyle.msTransform = value; } catch { } try // Prevents crash in the simulator that uses IE. { domStyle.WebkitTransform = value; } catch { } } }
internal override void INTERNAL_ApplyTransform() { if (this.INTERNAL_parent != null && INTERNAL_VisualTreeManager.IsElementInVisualTree(this.INTERNAL_parent)) { dynamic domStyle = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this.INTERNAL_parent); var matrix = this.Matrix; string value = "matrix(" + matrix.M11.ToString() + "," + matrix.M12.ToString() + "," + matrix.M21.ToString() + "," + matrix.M22.ToString() + "," + matrix.OffsetX.ToString() + "," + matrix.OffsetY.ToString() + ")"; //todo: make sure that the conversion from double to string is culture-invariant so that it uses dots instead of commas for the decimal separator. try { domStyle.transform = value; } catch { } try { domStyle.msTransform = value; } catch { } try // Prevents crash in the simulator that uses IE. { domStyle.WebkitTransform = value; } catch { } } }
internal void OnTextAlignmentChanged(TextAlignment alignment) { switch (alignment) { case TextAlignment.Center: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this).textAlign = "center"; break; case TextAlignment.Left: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this).textAlign = "left"; break; case TextAlignment.Right: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this).textAlign = "right"; break; case TextAlignment.Justify: INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this).textAlign = "justify"; break; default: break; } }
//INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", sizeToApply.Height); /// <summary> /// Prepares the Shape so that its canvas has the size it should have, depending on its container, content and Stretch mode. /// </summary> /// <param name="frameworkElement">The Shape containing the canvas.</param> /// <param name="canvasDomElement">The canvas in the Shape.</param> /// <param name="minX">The minimum X-coordinate of the points in the Shape.</param> /// <param name="maxX">The maximum X-coordinate of the points in the Shape.</param> /// <param name="minY">The minimum Y-coordinate of the points in the Shape.</param> /// <param name="maxY">The maximum Y-coordinate of the points in the Shape.</param> /// <param name="stretch">The Stretch mode to apply on the Shape</param> /// <param name="shapeActualSize"></param> internal static void PrepareStretch(FrameworkElement frameworkElement, object canvasDomElement, double minX, double maxX, double minY, double maxY, Stretch stretch, out Size shapeActualSize) { var canvasStyle = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(canvasDomElement); //Two steps: // 1) We get the size the Shape would take if Stretch = None so that we know its prefered size // 2) We make the element take the allowed size closest to that prefered size. //We get the size the Shape would take if its Stretch mode was Stretch.None: //in Stretch.None mode, the size is from 0 to the rightmost poit and bottommost point: double sizeX = maxX; double sizeY = maxY; //in other Stretched modes, the size is from the leftmost point to the rightmost point and from the topmost to the bottommost point: if (stretch != Stretch.None) { sizeX = maxX - minX; sizeY = maxY - minY; } else //we want to add the size of the shape that goes into negative values: { if (minX < 0) { sizeX = maxX - minX; } if (minY < 0) { sizeY = maxY - minY; } } //todo: (?) for the line below, replace the "+ 1" with the StrokeThickness/LineWidth Size sizeToApply = new Size(Math.Max(sizeX + 1, 0), Math.Max(sizeY + 1, 0)); //example: a vertical line still needs 1 pixel width //we apply the possible defined size of the outerDomElement of the shape: var style = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(frameworkElement); bool frameworkElementWidthWasSpecified = false; double frameworkElementWidth = frameworkElement.Width; double frameworkElementHeight = frameworkElement.Height; if (!double.IsNaN(frameworkElementWidth)) { frameworkElementWidthWasSpecified = true; sizeToApply.Width = frameworkElementWidth + 1; style.width = sizeToApply.Width.ToInvariantString() + "px"; } bool frameworkElementHeightWasSpecified = false; if (!double.IsNaN(frameworkElementHeight)) { frameworkElementHeightWasSpecified = true; sizeToApply.Height = frameworkElementHeight + 1; style.height = sizeToApply.Height.ToInvariantString() + "px"; } if (frameworkElementWidthWasSpecified && frameworkElementHeightWasSpecified) { shapeActualSize = new Size(frameworkElementWidth, frameworkElementHeight); //We apply the size defined earlier (size either by the Width and/or Height of the Shape (when they are set) or by the width and/or height of its content): INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "width", sizeToApply.Width); INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", sizeToApply.Height); canvasStyle.width = sizeToApply.Width.ToInvariantString() + "px"; // The "sizeToApply" is the size that the shape would take if it was not constrained by the parent framework element. canvasStyle.height = sizeToApply.Height.ToInvariantString() + "px"; } else { if (frameworkElement.IsUnderCustomLayout == false) { //We apply the size defined earlier (size either by the Width and/or Height of the Shape (when they are set) or by the width and/or height of its content): INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "width", sizeToApply.Width); INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", sizeToApply.Height); canvasStyle.width = sizeToApply.Width.ToInvariantString() + "px"; // The "sizeToApply" is the size that the shape would take if it was not constrained by the parent framework element. canvasStyle.height = sizeToApply.Height.ToInvariantString() + "px"; shapeActualSize = frameworkElement.INTERNAL_GetActualWidthAndHeight(); //Note: in case that the framework element is constrained, it won't take the size of its canvas2d content, so we then resize the canvas2d content so that the shape stretches. if (!frameworkElementWidthWasSpecified) { canvasStyle.width = shapeActualSize.Width.ToInvariantString() + "px"; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "width", shapeActualSize.Width + 1); //todo: add StrokeThickness instead of +1? } if (!frameworkElementHeightWasSpecified) { canvasStyle.height = shapeActualSize.Height.ToInvariantString() + "px"; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", shapeActualSize.Height + 1); //todo: add StrokeThickness instead of +1? } } else { shapeActualSize = frameworkElement.VisualBounds.Size; if (!frameworkElementWidthWasSpecified) { canvasStyle.width = shapeActualSize.Width.ToInvariantString() + "px"; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "width", shapeActualSize.Width + 1); //todo: add StrokeThickness instead of +1? } else { shapeActualSize.Width = frameworkElementWidth; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "width", sizeToApply.Width); canvasStyle.width = sizeToApply.Width.ToInvariantString() + "px"; } if (!frameworkElementHeightWasSpecified) { canvasStyle.height = shapeActualSize.Height.ToInvariantString() + "px"; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", shapeActualSize.Height + 1); //todo: add StrokeThickness instead of +1? } else { shapeActualSize.Height = frameworkElementHeight; INTERNAL_HtmlDomManager.SetDomElementAttribute(canvasDomElement, "height", sizeToApply.Height); canvasStyle.height = sizeToApply.Height.ToInvariantString() + "px"; } } } var context = INTERNAL_HtmlDomManager.Get2dCanvasContext(canvasDomElement); context.translate(0.5, 0.5); //makes is less blurry for some reason. }
internal protected static void Stretch_Changed(DependencyObject i, DependencyPropertyChangedEventArgs e) { //note: Stretch is actually more implemented in the Redraw method of the classes that inherit from shape (Line, Ellipse, Path, Rectangle) //todo: remove this method? var shape = (Shape)i; Stretch newValue = (Stretch)e.NewValue; if (INTERNAL_VisualTreeManager.IsElementInVisualTree(shape)) { dynamic shapeDom = INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(shape); if (double.IsNaN(shape.Width)) { switch (newValue) { case Stretch.None: shapeDom.width = "auto"; break; case Stretch.Fill: shapeDom.width = "100%"; break; case Stretch.Uniform: //todo: make it work when the image needs to be made bigger to fill the container shapeDom.maxWidth = "100%"; break; case Stretch.UniformToFill: //todo: add a negative margin top and left so that the image is centered shapeDom.minWidth = "100%"; break; default: break; } } if (double.IsNaN(shape.Height)) { switch (newValue) { case Stretch.None: shapeDom.height = "auto"; break; case Stretch.Fill: shapeDom.height = "100%"; break; case Stretch.Uniform: //todo: make it work when the image needs to be made bigger to fill the container shapeDom.maxHeight = "100%"; break; case Stretch.UniformToFill: //todo: add a negative margin top and left so that the image is centered shapeDom.minHeight = "100%"; break; default: break; } } shape.ScheduleRedraw(); } }
internal void OnTextAlignmentChanged(TextAlignment alignment) { UpdateTextAlignment(INTERNAL_HtmlDomManager.GetFrameworkElementOuterStyleForModification(this), alignment); }