/// <summary> /// Calculate the character index and offset by characters for the given word and given offset.<br/> /// If the location is below the word line then set the selection to the end.<br/> /// If the location is to the right of the word then set the selection to the end.<br/> /// If the offset is to the left of the word set the selection to the beginning.<br/> /// Otherwise calculate the width of each substring to find the char the location is on. /// </summary> /// <param name="control">used to create graphics to measure string</param> /// <param name="word">the word to calculate its index and offset</param> /// <param name="loc">the location to calculate for</param> /// <param name="inclusive">is to include the first character in the calculation</param> /// <param name="selectionIndex">return the index of the char under the location</param> /// <param name="selectionOffset">return the offset of the char under the location</param> private static void CalculateWordCharIndexAndOffset(RControl control, CssRect word, RPoint loc, bool inclusive, out int selectionIndex, out double selectionOffset) { selectionIndex = 0; selectionOffset = 0f; var offset = loc.X - word.Left; if (word.Text == null) { // not a text word - set full selection selectionIndex = -1; selectionOffset = -1; } else if (offset > word.Width - word.OwnerBox.ActualWordSpacing || loc.Y > DomUtils.GetCssLineBoxByWord(word).LineBottom) { // mouse under the line, to the right of the word - set to the end of the word selectionIndex = word.Text.Length; selectionOffset = word.Width; } else if (offset > 0) { // calculate partial word selection int charFit; double charFitWidth; var maxWidth = offset + (inclusive ? 0 : 1.5f * word.LeftGlyphPadding); control.MeasureString(word.Text, word.OwnerBox.ActualFont, maxWidth, out charFit, out charFitWidth); selectionIndex = charFit; selectionOffset = charFitWidth; } }
/// <summary> /// Draw video image over the iframe if found. /// </summary> private void DrawImage(RGraphics g, RPoint offset, RRect rect) { if (_imageWord.Image != null) { if (rect.Width > 0 && rect.Height > 0) { if (_imageWord.ImageRectangle == RRect.Empty) { g.DrawImage(_imageWord.Image, rect); } else { g.DrawImage(_imageWord.Image, rect, _imageWord.ImageRectangle); } if (_imageWord.Selected) { g.DrawRectangle(GetSelectionBackBrush(g, true), _imageWord.Left + offset.X, _imageWord.Top + offset.Y, _imageWord.Width + 2, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } } else if (_isVideo && !_imageLoadingComplete) { RenderUtils.DrawImageLoadingIcon(g, HtmlContainer, rect); if (rect.Width > 19 && rect.Height > 19) { g.DrawRectangle(g.GetPen(RColor.LightGray), rect.X, rect.Y, rect.Width, rect.Height); } } }
/// <summary> /// Draw video image over the iframe if found. /// </summary> private void DrawImage(IGraphics g, PointF offset, Rectangle rect) { if (_imageWord.Image != null) { if (_imageWord.ImageRectangle == Rectangle.Empty) { g.DrawImage(_imageWord.Image, rect); } else { g.DrawImage(_imageWord.Image, rect, _imageWord.ImageRectangle); } if (_imageWord.Selected) { g.FillRectangle(GetSelectionBackBrush(true), _imageWord.Left + offset.X, _imageWord.Top + offset.Y, _imageWord.Width + 2, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } else if (_isVideo && !_imageLoadingComplete) { RenderUtils.DrawImageLoadingIcon(g, rect); if (rect.Width > 19 && rect.Height > 19) { g.DrawRectangle(Pens.LightGray, rect.X, rect.Y, rect.Width, rect.Height); } } }
/// <summary> /// Check if the selection direction is forward or backward.<br/> /// Is the selection start word is before the selection end word in DFS traversal. /// </summary> private void CheckSelectionDirection() { if (_selectionStart == _selectionEnd) { _backwardSelection = _selectionStartIndex > _selectionEndIndex; } else if (DomUtils.GetCssLineBoxByWord(_selectionStart) == DomUtils.GetCssLineBoxByWord(_selectionEnd)) { _backwardSelection = _selectionStart.Left > _selectionEnd.Left; } else { _backwardSelection = _selectionStart.Top >= _selectionEnd.Bottom; } }
/// <summary> /// Calculate the character index and offset by characters for the given word and given offset.<br/> /// If the location is below the word line then set the selection to the end.<br/> /// If the location is to the right of the word then set the selection to the end.<br/> /// If the offset is to the left of the word set the selection to the beginning.<br/> /// Otherwise calculate the width of each substring to find the char the location is on. /// </summary> /// <param name="control">used to create graphics to measure string</param> /// <param name="word">the word to calculate its index and offset</param> /// <param name="loc">the location to calculate for</param> /// <param name="selectionIndex">return the index of the char under the location</param> /// <param name="selectionOffset">return the offset of the char under the location</param> /// <param name="inclusive">is to include the first character in the calculation</param> private static void CalculateWordCharIndexAndOffset(Control control, CssRect word, Point loc, bool inclusive, out int selectionIndex, out float selectionOffset) { selectionIndex = 0; selectionOffset = 0f; float offset = loc.X - word.Left; if (word.Text == null) { // not a text word - set full selection selectionIndex = -1; selectionOffset = -1; } else if (offset > word.Width - word.OwnerBox.ActualWordSpacing || loc.Y > DomUtils.GetCssLineBoxByWord(word).LineBottom) { // mouse under the line, to the right of the word - set to the end of the word selectionIndex = word.Text.Length; selectionOffset = word.Width; } else if (offset > 0) { // calculate partial word selection Font font = word.OwnerBox.ActualFont; using (var g = new WinGraphics(control.CreateGraphics(), false)) { int charFit; int charFitWidth; float maxWidth = offset + (inclusive ? 0 : 1.5f * word.LeftGlyphPadding); g.MeasureString(word.Text, font, maxWidth, out charFit, out charFitWidth); selectionIndex = charFit; selectionOffset = charFitWidth; } } }
/// <summary> /// Paints the fragment /// </summary> /// <param name="g">the device to draw to</param> protected override void PaintImp(RGraphics g) { // load image if it is in visible rectangle if (_imageLoadHandler == null) { _imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete); _imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null); } var rect = CommonUtils.GetFirstValueOrDefault(Rectangles); RPoint offset = RPoint.Empty; if (!IsFixed) { offset = HtmlContainer.ScrollOffset; } rect.Offset(offset); var clipped = RenderUtils.ClipGraphicsByOverflow(g, this); PaintBackground(g, rect, true, true); BordersDrawHandler.DrawBoxBorders(g, this, rect, true, true); RRect r = _imageWord.Rectangle; r.Offset(offset); r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom; r.Y += ActualBorderTopWidth + ActualPaddingTop; r.X = Math.Floor(r.X); r.Y = Math.Floor(r.Y); if (_imageWord.Image != null) { if (r.Width > 0 && r.Height > 0) { if (_imageWord.ImageRectangle == RRect.Empty) { g.DrawImage(_imageWord.Image, r); } else { g.DrawImage(_imageWord.Image, r, _imageWord.ImageRectangle); } if (_imageWord.Selected) { g.DrawRectangle(GetSelectionBackBrush(g, true), _imageWord.Left + offset.X, _imageWord.Top + offset.Y, _imageWord.Width + 2, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } } else if (_imageLoadingComplete) { if (_imageLoadingComplete && r.Width > 19 && r.Height > 19) { RenderUtils.DrawImageErrorIcon(g, HtmlContainer, r); } } else { RenderUtils.DrawImageLoadingIcon(g, HtmlContainer, r); if (r.Width > 19 && r.Height > 19) { g.DrawRectangle(g.GetPen(RColor.LightGray), r.X, r.Y, r.Width, r.Height); } } if (clipped) { g.PopClip(); } }
/// <summary> /// Paints the fragment /// </summary> /// <param name="g">the device to draw to</param> protected override void PaintImp(IGraphics g) { // load image iff it is in visible rectangle if (_imageLoadHandler == null) { _imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete); _imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null); } RectangleF rect = CommonUtils.GetFirstValueOrDefault(Rectangles); PointF offset = HtmlContainer.ScrollOffset; rect.Offset(offset); RectangleF prevClip = RenderUtils.ClipGraphicsByOverflow(g, this); PaintBackground(g, rect, true, true); BordersDrawHandler.DrawBoxBorders(g, this, rect, true, true); RectangleF r = _imageWord.Rectangle; r.Offset(offset); r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom; r.Y += ActualBorderTopWidth + ActualPaddingTop; r.X = (float)Math.Floor(r.X); r.Y = (float)Math.Floor(r.Y); if (_imageWord.Image != null) { if (_imageWord.ImageRectangle == Rectangle.Empty) { g.DrawImage(_imageWord.Image, Rectangle.Round(r)); } else { g.DrawImage(_imageWord.Image, Rectangle.Round(r), _imageWord.ImageRectangle); } if (_imageWord.Selected) { g.FillRectangle(GetSelectionBackBrush(true), _imageWord.Left + offset.X, _imageWord.Top + offset.Y, _imageWord.Width + 2, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } else if (_imageLoadingComplete) { if (_imageLoadingComplete && r.Width > 19 && r.Height > 19) { RenderUtils.DrawImageErrorIcon(g, r); } } else { RenderUtils.DrawImageLoadingIcon(g, r); if (r.Width > 19 && r.Height > 19) { g.DrawRectangle(Pens.LightGray, r.X, r.Y, r.Width, r.Height); } } RenderUtils.ReturnClip(g, prevClip); }
/// <summary> /// Paints the fragment /// </summary> /// <param name="g">the device to draw to</param> protected override void PaintImp(Graphics g) { var rects = CommonUtils.GetFirstValueOrDefault(Rectangles); PointF offset = HtmlContainer != null ? HtmlContainer.ScrollOffset : PointF.Empty; rects.Offset(offset); var prevClip = RenderUtils.ClipGraphicsByOverflow(g, this); PaintBackground(g, rects, true, true); PaintBorder(g, rects, true, true); RectangleF r = _imageWord.Rectangle; r.Offset(offset); r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom; r.Y += ActualBorderTopWidth + ActualPaddingTop; if (_imageWord.Image != null) { if (_imageWord.ImageRectangle == Rectangle.Empty) { g.DrawImage(_imageWord.Image, Rectangle.Round(r)); } else { g.DrawImage(_imageWord.Image, Rectangle.Round(r), _imageWord.ImageRectangle, GraphicsUnit.Point); } if (_imageWord.Selected) { g.FillRectangle(CssUtils.SelectionBackcolor, _imageWord.Left - _imageWord.LastMeasureOffset.X + offset.X, _imageWord.Top + offset.Y, _imageWord.Width, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } else if (_imageLoadingComplete) { if (_imageLoadingComplete && r.Width > 19 && r.Height > 19) { DrawingUtils.DrawImageErrorIcon(g, r); } } else { DrawingUtils.DrawImageLoadingIcon(g, r); if (r.Width > 19 && r.Height > 19) { g.DrawRectangle(Pens.LightGray, Rectangle.Round(r)); } } RenderUtils.ReturnClip(g, prevClip); }
/// <summary> /// Paints the fragment /// </summary> /// <param name="g"></param> private void PaintImp(Graphics g) { if (Display != CssConstants.None && (Display != CssConstants.TableCell || EmptyCells != CssConstants.Hide || !IsSpaceOrEmpty)) { var areas = Rectangles.Count == 0 ? new List <RectangleF>(new[] { Bounds }) : new List <RectangleF>(Rectangles.Values); RectangleF[] rects = areas.ToArray(); PointF offset = HtmlContainer != null ? HtmlContainer.ScrollOffset : PointF.Empty; for (int i = 0; i < rects.Length; i++) { var actualRect = rects[i]; actualRect.Offset(offset); PaintBackground(g, actualRect, i == rects.Length - 1); PaintBorder(g, actualRect, i == 0, i == rects.Length - 1); } if (IsImage) { var word = Words[0]; RectangleF r = word.Bounds; r.Offset(offset); r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom; r.Y += ActualBorderTopWidth + ActualPaddingTop; //HACK: round rectangle only when necessary g.DrawImage(word.Image, Rectangle.Round(r)); if (word.Selected) { g.FillRectangle(CssUtils.SelectionBackcolor, word.Left - word.LastMeasureOffset.X + offset.X, word.Top + offset.Y, word.Width, DomUtils.GetCssLineBoxByWord(word).LineHeight); } } else if (Words.Count > 0) { Font font = ActualFont; var brush = CssUtils.GetSolidBrush(CssValueParser.GetActualColor(Color)); foreach (var word in Words) { if (word.Selected) { // handle paint selected word background and with partial word selection var left = word.SelectedStartOffset > -1 ? word.SelectedStartOffset : 0; var width = word.SelectedEndOffset > -1 ? word.SelectedEndOffset + word.LastMeasureOffset.X : word.Width; //REFACTOR THIS STUFF Brush b = CssUtils.SelectionBackcolor; CssLineBox box = DomUtils.GetCssLineBoxByWord(word); float h = box != null ? box.LineHeight : 0; float w = width - left; float x = word.Left - word.LastMeasureOffset.X + offset.X + left; float y = word.Top + offset.Y; g.FillRectangle(b, x, y, w, h); } g.DrawString(word.Text, font, brush, word.Left - word.LastMeasureOffset.X + offset.X, word.Top + offset.Y); } } for (int i = 0; i < rects.Length; i++) { var actualRect = rects[i]; actualRect.Offset(offset); PaintDecoration(g, actualRect, i == 0, i == rects.Length - 1); } foreach (CssBox b in Boxes) { b.Paint(g); } CreateListItemBox(g); if (ListItemBox != null) { ListItemBox.Paint(g); } } }
/// <summary> /// Draw video image over the iframe if found. /// </summary> private void DrawImage(Graphics g, PointF offset, Rectangle rect) { if (_imageWord.Image != null) { if (_imageWord.ImageRectangle == Rectangle.Empty) { g.DrawImage(_imageWord.Image, rect); } else { g.DrawImage(_imageWord.Image, rect, _imageWord.ImageRectangle, GraphicsUnit.Point); } if (_imageWord.Selected) { g.FillRectangle(CssUtils.SelectionBackcolor, _imageWord.Left - _imageWord.LastMeasureOffset.X + offset.X, _imageWord.Top + offset.Y, _imageWord.Width, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight); } } else if (_isVideo && !_imageLoadingComplete) { DrawingUtils.DrawImageLoadingIcon(g, rect); if (rect.Width > 19 && rect.Height > 19) { g.DrawRectangle(Pens.LightGray, rect); } } }