private static string DetectTappedUrl(UIGestureRecognizer tap, UILabel control) { CGRect bounds = control.Bounds; NSAttributedString attributedText = control.AttributedText; // Setup containers using var textContainer = new NSTextContainer(bounds.Size) { LineFragmentPadding = 0, LineBreakMode = control.LineBreakMode, MaximumNumberOfLines = (nuint)control.Lines }; using var layoutManager = new NSLayoutManager(); layoutManager.AddTextContainer(textContainer); using var textStorage = new NSTextStorage(); textStorage.SetString(attributedText); using var fontAttributeName = new NSString("NSFont"); var textRange = new NSRange(0, control.AttributedText.Length); textStorage.AddAttribute(fontAttributeName, control.Font, textRange); textStorage.AddLayoutManager(layoutManager); CGRect textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer);
int IndexAtPoint(Point point) { if (Control is UILabel control) { var cgPoint = new CGPoint(point.X, point.Y - control.Frame.Y); // init text storage var textStorage = new NSTextStorage(); var attrText = new NSAttributedString(control.AttributedText); textStorage.SetString(attrText); // init layout manager var layoutManager = new NSLayoutManager(); textStorage.AddLayoutManager(layoutManager); // init text container var textContainer = new NSTextContainer(new CGSize(control.Frame.Width, control.Frame.Height * 2)) { LineFragmentPadding = 0, MaximumNumberOfLines = (nuint)_currentDrawState.Lines, LineBreakMode = UILineBreakMode.WordWrap, Size = new CGSize(control.Frame.Width, control.Frame.Height * 2) }; layoutManager.AddTextContainer(textContainer); layoutManager.AllowsNonContiguousLayout = true; var characterIndex = layoutManager.GetCharacterIndex(cgPoint, textContainer); return((int)characterIndex); } return(-1); }
private void UpdateHyperlinkLayout() { // Configure textContainer var textContainer = new NSTextContainer(); textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)Lines; textContainer.Size = _drawRect.Size; // Configure layoutManager _layoutManager = new NSLayoutManager(); _layoutManager.AddTextContainer(textContainer); // Configure textStorage var textStorage = new NSTextStorage(); textStorage.SetString(GetAttributedText(NSAttributedStringTarget.NSTextStorage)); textStorage.AddLayoutManager(_layoutManager); if (FeatureConfiguration.TextBlock.ShowHyperlinkLayouts) { textStorage.AddAttributes( new UIStringAttributes() { ForegroundColor = UIColor.Red }, new NSRange(0, textStorage.Length) ); } }
void AppendData(NSData d) { NSString s = NSString.FromData(d, NSStringEncoding.UTF8); NSTextStorage ts = outputView.TextStorage; ts.Replace(new NSRange(ts.Length, 0), s); }
static double FindDefaultLineHeight(this NativeLabel control, int start, int length) { if (length == 0) { return(0.0); } var textStorage = new NSTextStorage(); #if __MOBILE__ textStorage.SetString(control.AttributedText.Substring(start, length)); #else textStorage.SetString(control.AttributedStringValue.Substring(start, length)); #endif var layoutManager = new NSLayoutManager(); textStorage.AddLayoutManager(layoutManager); var textContainer = new NSTextContainer(size: new SizeF(float.MaxValue, float.MaxValue)) { LineFragmentPadding = 0 }; layoutManager.AddTextContainer(textContainer); var rect = GetCharacterBounds(new NSRange(0, 1), layoutManager, textContainer); return(rect.Bottom - rect.Top); }
private string DetectTappedUrl(UIGestureRecognizer tap, UILabel label, IEnumerable <LinkData> linkList) { // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage var layoutManager = new NSLayoutManager(); var textContainer = new NSTextContainer(); var textStorage = new NSTextStorage(); textStorage.SetString(label.AttributedText); // Configure layoutManager and textStorage layoutManager.AddTextContainer(textContainer); textStorage.AddLayoutManager(layoutManager); // Configure textContainer textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = label.LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)label.Lines; var labelSize = label.Bounds.Size; textContainer.Size = labelSize; // Find the tapped character location and compare it to the specified range var locationOfTouchInLabel = tap.LocationInView(label); var textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); var textContainerOffset = new CGPoint((labelSize.Width - textBoundingBox.Size.Width) * 0.0 - textBoundingBox.Location.X, (labelSize.Height - textBoundingBox.Size.Height) * 0.0 - textBoundingBox.Location.Y); nfloat labelX; switch (Element.HorizontalTextAlignment) { case TextAlignment.End: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width); break; case TextAlignment.Center: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width) / 2; break; default: labelX = locationOfTouchInLabel.X; break; } var locationOfTouchInTextContainer = new CGPoint(labelX - textContainerOffset.X, locationOfTouchInLabel.Y - textContainerOffset.Y); nfloat partialFraction = 0; var indexOfCharacter = (nint)layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref partialFraction); foreach (var link in linkList) { // Xamarin version of NSLocationInRange? if ((indexOfCharacter >= link.Range.Location) && (indexOfCharacter < link.Range.Location + link.Range.Length)) { return(link.Url); } } return(null); }
public LayoutInfo(ApplicationContext actx) { ApplicationContext = actx; Attributes = new List <TextAttribute> (); TextStorage = new NSTextStorage(); TextContainer = new NSTextContainer { LineFragmentPadding = 0.0f }; }
// NOTE: this method only works with single line UILabels, or multi-line labels with left aligned text // Potential fix found on timbroder's comment on https://stackoverflow.com/questions/1256887/create-tap-able-links-in-the-nsattributedstring-of-a-uilabel // Based on https://stackoverflow.com/questions/1256887/create-tap-able-links-in-the-nsattributedstring-of-a-uilabel // Based on https://samwize.com/2016/03/04/how-to-create-multiple-tappable-links-in-a-uilabel/ /// <summary> /// Determines whether the tap is within the NSRange targetRange. Returns true if so, otherwise returns false. /// </summary> /// <returns><c>true</c>, if tap was within the targetRange of the label, <c>false</c> otherwise.</returns> /// <param name="label">The label containing the text.</param> /// <param name="targetRange">The target range of the tappable text within the label.</param> /// <param name="gestureRecognizer">Gesture recognizer.</param> /// <param name="textAlignment">Text alignment of the label.</param> public static bool DidTapAttributedTextInLabel(UILabel label, NSRange targetRange, UIGestureRecognizer gestureRecognizer, UITextAlignment textAlignment) { NSLayoutManager layoutManager = new NSLayoutManager(); NSTextContainer textContainer = new NSTextContainer(CGSize.Empty); NSTextStorage textStorage = new NSTextStorage(); textStorage.SetString(label.AttributedText); // Configure layoutManager and textStorage layoutManager.AddTextContainer(textContainer); textStorage.AddLayoutManager(layoutManager); // Configure textContainer textContainer.LineFragmentPadding = 0.0f; textContainer.LineBreakMode = label.LineBreakMode; textContainer.MaximumNumberOfLines = (System.nuint)label.Lines; CGSize labelSize = label.Bounds.Size; textContainer.Size = labelSize; // Find the tapped character location and compare it to the specified range CGPoint locationOfTouchInLabel = gestureRecognizer.LocationInView(label); CGRect textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); // Change based on the UITextAlignment enum float multiplier; if (textAlignment == UITextAlignment.Center) { multiplier = 0.5f; } else if (textAlignment == UITextAlignment.Right) { multiplier = 1.0f; } else { // textAlignment is Left, Natural, or Justified multiplier = 0.0f; } CGPoint textContainerOffset = new CGPoint( ((labelSize.Width - textBoundingBox.Size.Width) * multiplier - textBoundingBox.Location.X), ((labelSize.Height - textBoundingBox.Size.Height) * multiplier - textBoundingBox.Location.Y) ); CGPoint locationOfTouchInTextContainer = new CGPoint(locationOfTouchInLabel.X - textContainerOffset.X, locationOfTouchInLabel.Y - textContainerOffset.Y); nfloat partialFraction = 0; int indexOfCharacter = (int)layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref partialFraction); // Xamarin version of the function NSLocationInRange (Swift equivalent is to call ```NSLocationInRange(indexOfCharacter, targetRange);``` ) // Credit to https://forums.xamarin.com/discussion/56484/need-to-put-html-into-a-label bool isInRange = (indexOfCharacter >= targetRange.Location) && (indexOfCharacter <= targetRange.Location + targetRange.Length); return(isInRange); }
int IndexAtPoint(Point point) { var cgPoint = new CGPoint(point.X, point.Y - Control.Frame.Y); // init text storage var textStorage = new NSTextStorage(); //if (Control.AttributedText != null) var attrText = new NSAttributedString(Control.AttributedText); textStorage.SetString(attrText); /* * else * { * var attrString = new NSMutableAttributedString(Control.Text); * attrString.AddAttribute(UIStringAttributeKey.Font, Control.Font, new NSRange(0, Control.Text.Length)); * textStorage.SetString(attrString); * } */ // init layout manager var layoutManager = new NSLayoutManager(); textStorage.AddLayoutManager(layoutManager); // init text container var textContainer = new NSTextContainer(new CGSize(Control.Frame.Width, Control.Frame.Height * 2)); textContainer.LineFragmentPadding = 0; textContainer.MaximumNumberOfLines = (nuint)ControlLines; textContainer.LineBreakMode = UILineBreakMode.WordWrap;//Control.LineBreakMode; //if (Control.LineBreakMode == UILineBreakMode.TailTruncation || Control.LineBreakMode == UILineBreakMode.HeadTruncation || Control.LineBreakMode == UILineBreakMode.MiddleTruncation) // textContainer.LineBreakMode = UILineBreakMode.WordWrap; textContainer.Size = new CGSize(Control.Frame.Width, Control.Frame.Height * 2); layoutManager.AddTextContainer(textContainer); layoutManager.AllowsNonContiguousLayout = true; //layoutManager.SetTextContainer(textContainer,new NSRange(0,Control.AttributedText.Length)); //layoutManager.UsesFontLeading = true; //layoutManager.EnsureLayoutForCharacterRange(new NSRange(0,Control.AttributedText.Length)); //layoutManager.EnsureLayoutForTextContainer(textContainer); nfloat partialFraction = 0; var characterIndex = layoutManager.CharacterIndexForPoint(cgPoint, textContainer, ref partialFraction); //[self.layoutManager drawGlyphsForGlyphRange:NSMakeRange(0, self.textStorage.length) atPoint:CGPointMake(0, 0)]; //layoutManager.DrawGlyphs(new NSRange(0,Control.AttributedText.Length),Control.Frame.Location); return((int)characterIndex); }
public void GetGlyphsTest() { TestRuntime.AssertSystemVersion(ApplePlatform.iOS, 7, 0, throwIfOtherPlatform: false); using (var txt = new NSTextStorage()) { var str = "hello world\n\t"; txt.SetString(new NSAttributedString(str)); using (var lm = new NSLayoutManager()) { lm.TextStorage = txt; var glyphs = new short[str.Length]; var props = new NSGlyphProperty [glyphs.Length]; var charIndexBuffer = new nuint [glyphs.Length]; var bidiLevelBuffer = new byte [glyphs.Length]; lm.GetGlyphs(new NSRange(0, str.Length), glyphs, props, charIndexBuffer, bidiLevelBuffer); Assert.That(glyphs, Is.EqualTo(new short [] { 75, 72, 79, 79, 82, 3, 90, 82, 85, 79, 71, -1, -1 }), "glyphs"); Assert.That(props, Is.EqualTo(new NSGlyphProperty [] { 0, 0, 0, 0, 0, NSGlyphProperty.Elastic, 0, 0, 0, 0, 0, NSGlyphProperty.ControlCharacter, NSGlyphProperty.ControlCharacter }), "props"); Assert.That(charIndexBuffer, Is.EqualTo(new nuint [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }), "charIndexBuffer"); Assert.That(bidiLevelBuffer, Is.EqualTo(new byte [str.Length]), "bidiLevelBuffer"); } } using (var txt = new NSTextStorage()) { var str = "hello world\n\t"; txt.SetString(new NSAttributedString(str)); using (var lm = new NSLayoutManager()) { lm.TextStorage = txt; var glyphs = new short[str.Length]; var charIndexBuffer = new nuint [glyphs.Length]; var bidiLevelBuffer = new byte [glyphs.Length]; lm.GetGlyphs(new NSRange(0, str.Length), glyphs, null, charIndexBuffer, bidiLevelBuffer); Assert.That(glyphs, Is.EqualTo(new short [] { 75, 72, 79, 79, 82, 3, 90, 82, 85, 79, 71, -1, -1 }), "glyphs"); Assert.That(charIndexBuffer, Is.EqualTo(new nuint [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }), "charIndexBuffer"); Assert.That(bidiLevelBuffer, Is.EqualTo(new byte [str.Length]), "bidiLevelBuffer"); } } }
protected override void OnElementChanged(ElementChangedEventArgs <MyLabel> e) { base.OnElementChanged(e); if (e.NewElement != null) { if (Control == null) { var uiLabel = new UILabel { UserInteractionEnabled = true, LineBreakMode = UILineBreakMode.WordWrap, Lines = 0, Text = "عندما يريد العالم أن يتكلّم ، فهو يتحدّث بلغة يونيكود. تسجّل الآن لحضور المؤتمر الدولي العاشر ليونيكود (Unicode Conference)، الذي سيعقد في 10-12 آذار 1997 بمدينة مَايِنْتْس، ألمانيا. و سيجمع المؤتمر بين خبراء من كافة قطاعات الصناعة على الشبكة العالمية انترنيت ويونيكود، حيث ستتم، على الصعيدين الدولي والمحلي على حد سواء مناقشة سبل استخدام يونكود في النظم القائمة وفيما يخص التطبيقات الحاسوبية، الخطوط، تصميم النصوص والحوسبة متعددة اللغات...TapMe" }; var uiTapGestureRecognizer = new UITapGestureRecognizer(); uiTapGestureRecognizer.AddTarget(() => { var label = uiLabel; var recognizer = uiTapGestureRecognizer; var range = new NSRange(uiLabel.Text.Length - "TapMe".Length, "TapMe".Length); using (var ts = new NSTextStorage()) { var lm = new NSLayoutManager(); var tc = new NSTextContainer(new CGSize(label.Frame.Width, double.MaxValue)); lm.AddTextContainer(tc); ts.Append(label.AttributedText); ts.AddLayoutManager(lm); tc.LineFragmentPadding = (float)0.0; tc.LineBreakMode = label.LineBreakMode; tc.MaximumNumberOfLines = (uint)label.Lines; tc.Size = label.Bounds.Size; var index = lm.GetCharacterIndex(recognizer.LocationOfTouch(0, label), tc); var isWithinRange = (nint)index >= range.Location && (nint)index < range.Location + range.Length; App.Current.MainPage.DisplayAlert("Alert", "Character count: " + label.Text.Length + "\nRange location: " + range.Location + "\nRange length:" + range.Length + "\nCharacter index: " + index + "\nIs within range: " + isWithinRange, "Dismiss"); } }); uiLabel.AddGestureRecognizer(uiTapGestureRecognizer); SetNativeControl(uiLabel); } } }
nfloat HeightWrappedToWidth(float width) { nfloat height = 0; NSTextStorage storage = new NSTextStorage(); NSLayoutManager layoutManager = new NSLayoutManager(); CGSize size = new CGSize(width, 100); NSTextContainer container = new NSTextContainer(size); layoutManager.AddTextContainer(container); storage.AddLayoutManager(layoutManager); layoutManager.GetGlyphRange(container); //force layout height = layoutManager.GetUsedRectForTextContainer(container).Height; return(height); }
public void CreateManager() { // This sets up the global context so our drawing doesn't produce error messages NSBitmapImageRep bitmap = new NSBitmapImageRep(IntPtr.Zero, 1000, 1000, 16, 4, true, false, NSColorSpace.DeviceRGB, 0, 0); NSGraphicsContext.CurrentContext = NSGraphicsContext.FromBitmap(bitmap); NSTextStorage storage = new NSTextStorage("Hello World"); NSTextContainer container = new NSTextContainer(); manager = new NSLayoutManager(); manager.AddTextContainer(container); storage.AddLayoutManager(manager); }
static FontExtensions() { storage = new NSTextStorage(); layout = new NSLayoutManager { UsesFontLeading = true }; #if OSX layout.BackgroundLayoutEnabled = false; #endif container = new NSTextContainer { LineFragmentPadding = 0f }; layout.UsesFontLeading = true; layout.AddTextContainer(container); storage.AddLayoutManager(layout); }
private CGSize textSize(string str, NSDictionary attributes) { // The three components var storage = new NSTextStorage(); var layout = new NSLayoutManager(); var container = new NSTextContainer(); // Bind them layout.AddTextContainer(container); storage.AddLayoutManager(layout); storage.SetString(new NSAttributedString(str, attributes)); // Compute layout.GetGlyphRange(container); // Get size CGSize size = layout.GetUsedRectForTextContainer(container).Size; return(size); }
private int GetCharacterIndexAtPoint(Point point) { if (!_drawRect.Contains(point)) { return(-1); } // Configure textContainer var textContainer = new NSTextContainer(); textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)Lines; textContainer.Size = _drawRect.Size; // Configure layoutManager var layoutManager = new NSLayoutManager(); layoutManager.AddTextContainer(textContainer); // Configure textStorage var textStorage = new NSTextStorage(); textStorage.SetString(AttributedText); textStorage.AddLayoutManager(layoutManager); textStorage.SetAttributes( new UIStringAttributes() { Font = Font }, new NSRange(0, textStorage.Length) ); // Find the tapped character's index var partialFraction = (nfloat)0; var pointInTextContainer = new CGPoint(point.X - _drawRect.X, point.Y - _drawRect.Y); var characterIndex = (int)layoutManager.CharacterIndexForPoint(pointInTextContainer, textContainer, ref partialFraction); return(characterIndex); }
public CGRect boundingRectForCharacter(NSRange range) { NSTextStorage textStorage = new NSTextStorage(); textStorage.SetString(this.AttributedText); NSLayoutManager layoutManager = new NSLayoutManager(); textStorage.AddLayoutManager(layoutManager); NSTextContainer textContainer = new NSTextContainer(this.Bounds.Size); textContainer.LineFragmentPadding = 0f; layoutManager.AddTextContainer(textContainer); NSRange glyphRange; glyphRange = layoutManager.CharacterRangeForGlyphRange(range); return(layoutManager.BoundingRectForGlyphRange(glyphRange, textContainer)); }
private void UpdateTypography() { _attributedString = GetAttributedText(); if (UseLayoutManager) { // Configure textContainer _textContainer = new NSTextContainer(); _textContainer.LineFragmentPadding = 0; _textContainer.LineBreakMode = GetLineBreakMode(); _textContainer.MaximumNumberOfLines = (nuint)GetLines(); // Configure layoutManager _layoutManager = new NSLayoutManager(); _layoutManager.AddTextContainer(_textContainer); // Configure textStorage _textStorage = new NSTextStorage(); _textStorage.AddLayoutManager(_layoutManager); _textStorage.SetString(_attributedString); } }
public void GetGlyphsTest() { if (!TestRuntime.CheckSystemAndSDKVersion(7, 0)) { Assert.Ignore("requires iOS7+"); } using (var txt = new NSTextStorage()) { var str = "hello world\n\t"; txt.SetString(new NSAttributedString(str)); using (var lm = new NSLayoutManager()) { lm.TextStorage = txt; var glyphs = new short[str.Length]; var props = new NSGlyphProperty [glyphs.Length]; var charIndexBuffer = new nuint [glyphs.Length]; var bidiLevelBuffer = new byte [glyphs.Length]; lm.GetGlyphs(new NSRange(0, str.Length), glyphs, props, charIndexBuffer, bidiLevelBuffer); Assert.That(glyphs, Is.EqualTo(new short [] { 75, 72, 79, 79, 82, 3, 90, 82, 85, 79, 71, -1, -1 }), "glyphs"); Assert.That(props, Is.EqualTo(new NSGlyphProperty [] { 0, 0, 0, 0, 0, NSGlyphProperty.Elastic, 0, 0, 0, 0, 0, NSGlyphProperty.ControlCharacter, NSGlyphProperty.ControlCharacter }), "props"); Assert.That(charIndexBuffer, Is.EqualTo(new nuint [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }), "charIndexBuffer"); Assert.That(bidiLevelBuffer, Is.EqualTo(new byte [str.Length]), "bidiLevelBuffer"); } } }
private NSRange?AttributedTextRangeForPoint(CGPoint point) { var layoutManager = new NSLayoutManager(); var textContainer = new NSTextContainer(CGSize.Empty) { LineFragmentPadding = 0.0f, LineBreakMode = LineBreakMode, MaximumNumberOfLines = (nuint)Lines, Size = Bounds.Size }; layoutManager.AddTextContainer(textContainer); var textStorage = new NSTextStorage(); textStorage.SetString(AttributedText); textStorage.AddLayoutManager(layoutManager); var textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); var textContainerOffset = new CGPoint( (Bounds.Width - textBoundingBox.Width) * 0.5f - textBoundingBox.GetMinX(), (Bounds.Height - textBoundingBox.Height) * 0.5f - textBoundingBox.GetMinY()); var locationOfTouchInTextContainer = new CGPoint(point.X - textContainerOffset.X, point.Y - textContainerOffset.Y); var frac = new nfloat(0.0f); var indexOfCharacter = layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref frac); foreach (var pair in _handlerDictionary) { var range = pair.Key; if (range.LocationInRange((int)indexOfCharacter)) { return(range); } } return(null); }
bool didTapAttributedTextInLabel(UITapGestureRecognizer tap, UILabel label, NSRange targetRange) { var layoutManager = new NSLayoutManager(); var textContainer = new NSTextContainer(CGSize.Empty); var textStorage = new NSTextStorage(); textStorage.SetString(label.AttributedText); layoutManager.AddTextContainer(textContainer); textStorage.AddLayoutManager(layoutManager); textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = label.LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)label.Lines; var labelSize = label.Bounds.Size; textContainer.Size = labelSize; var locationOfTouchInLabel = tap.LocationInView(label); var textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); var textContainerOffset = new CGPoint((labelSize.Width - textBoundingBox.Size.Width) * 0.5 - textBoundingBox.Location.X, (labelSize.Height - textBoundingBox.Size.Height) * 0.5 - textBoundingBox.Location.Y); var locationOfTouchInTextContainer = new CGPoint(locationOfTouchInLabel.X - textContainerOffset.X, locationOfTouchInLabel.Y - textContainerOffset.Y); nfloat partialFraction = 1; var indexOfCharacter = layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref partialFraction); if (((nint)indexOfCharacter >= targetRange.Location) && ((nint)indexOfCharacter < targetRange.Location + targetRange.Length)) { return(true); } return(false); }
private void SetStyle() { if (ExtendedLabel.Children != null && ExtendedLabel.Children.Count > 0) { NSTextStorage attributedString = new NSTextStorage(); _styledTextPartList = new List <KeyValuePair <int, StyledTextPart> >(); ExtendedLabel.Children.ToList().ForEach(styledTextPart => { _styledTextPartList.Add(new KeyValuePair <int, StyledTextPart>(Convert.ToInt32(attributedString.Length), styledTextPart)); attributedString.Append(styledTextPart.CustomFont.BuildAttributedString(styledTextPart.Text, this.Control.TextAlignment)); }); Control.AttributedText = attributedString; Control.UserInteractionEnabled = true; var tapGestureRecognizer = new UITapGestureRecognizer(); tapGestureRecognizer.AddTarget(() => LabelTapped(tapGestureRecognizer)); Control.AddGestureRecognizer(tapGestureRecognizer); //if (!ExtendedLabel.TextShouldWrap) //{ // Control.Lines = 1; //} _layoutManager = new NSLayoutManager(); _layoutManager.AddTextContainer(_textContainer); attributedString.AddLayoutManager(_layoutManager); return; } if (ExtendedLabel.Text != null) { var attributedString = ExtendedLabel.CustomFont.BuildAttributedString(ExtendedLabel.Text, this.Control.TextAlignment); Control.AttributedText = attributedString; } }
async Task loadAndParse(IExtractor extractor) { // progress tracker var updater = new Progress <ExtractorProgress>(); updater.ProgressChanged += (sender, evt) => { InvokeOnMainThread(() => { label.StringValue = evt.Message; }); }; // task Dictionary <String, Session> sessions = extractor.GetSessions(updater); var data = extractor.SerialiseToJson(updater, sessions); InvokeOnMainThread(() => { Results.RichText = false; var ts = new NSTextStorage(data); Results.LayoutManager.ReplaceTextStorage(ts); reflectState(State.LOADED); label.StringValue = "Done."; }); }
public ApplyStyles(TextController controller, NSTextView text) { Contract.Requires(text.textStorage().layoutManagers().count() == 1, "expected one layout not " + text.textStorage().layoutManagers().count()); m_controller = controller; m_storage = text.textStorage(); m_layout = m_storage.layoutManagers().objectAtIndex(0).To<NSLayoutManager>(); m_current = new CurrentStyles(controller, m_storage); Broadcaster.Register("tab stops changed", this); Broadcaster.Register("selected line color changed", this); Broadcaster.Register("computed style runs", this); Broadcaster.Register("text changed", this); if (ms_selectedLineColor == null) DoSetTempAttrs(); DoResetTabStops(); DoApplyParagraphStyles(true); ActiveObjects.Add(this); }
public static void RecalculateSpanPositions(this NativeLabel control, Label element) { if (element == null) { return; } if (element.TextType == TextType.Html) { return; } if (element?.FormattedText?.Spans == null || element.FormattedText.Spans.Count == 0) { return; } var finalSize = control.Frame; if (finalSize.Width <= 0 || finalSize.Height <= 0) { return; } #if __MOBILE__ var inline = control.AttributedText; #else var inline = control.AttributedStringValue; #endif var range = new NSRange(0, inline.Length); NSTextStorage textStorage = new NSTextStorage(); textStorage.SetString(inline); var layoutManager = new NSLayoutManager(); textStorage.AddLayoutManager(layoutManager); var textContainer = new NSTextContainer(size: finalSize.Size) { LineFragmentPadding = 0 }; layoutManager.AddTextContainer(textContainer); var labelWidth = finalSize.Width; var currentLocation = 0; for (int i = 0; i < element.FormattedText.Spans.Count; i++) { var span = element.FormattedText.Spans[i]; var location = currentLocation; var length = span.Text?.Length ?? 0; if (length == 0) { continue; } var startRect = GetCharacterBounds(new NSRange(location, 1), layoutManager, textContainer); var endRect = GetCharacterBounds(new NSRange(location + length, 1), layoutManager, textContainer); var startLineHeight = startRect.Bottom - startRect.Top; var endLineHeight = endRect.Bottom - endRect.Top; var defaultLineHeight = control.FindDefaultLineHeight(location, length); var yaxis = startRect.Top; var lineHeights = new List <double>(); while ((endRect.Bottom - yaxis) > 0.001) { double lineHeight; if (yaxis == startRect.Top) // First Line { lineHeight = startRect.Bottom - startRect.Top; } else if (yaxis != endRect.Top) // Middle Line(s) { lineHeight = defaultLineHeight; } else // Bottom Line { lineHeight = endRect.Bottom - endRect.Top; } lineHeights.Add(lineHeight); yaxis += (float)lineHeight; } ((ISpatialElement)span).Region = Region.FromLines(lineHeights.ToArray(), finalSize.Width, startRect.X, endRect.X, startRect.Top).Inflate(10); // update current location currentLocation += length; } }
public CurrentStyles(TextController controller, NSTextStorage storage) { m_controller = controller; m_storage = storage; m_stylesWriteTime = DateTime.Now; Broadcaster.Register("text spaces color changed", this); Broadcaster.Register("text tabs color changed", this); string path = Path.GetDirectoryName(ms_stylesPath); m_watcher = new DirectoryWatcher(path, TimeSpan.FromMilliseconds(250)); m_watcher.Changed += this.DoFilesChanged; ActiveObjects.Add(this); }
private string DetectTappedUrl(UIGestureRecognizer tap, UILabel label, IEnumerable <LinkData> linkList) { var layoutManager = new NSLayoutManager(); var textContainer = new NSTextContainer(); var textStorage = new NSTextStorage(); textStorage.SetString(label.AttributedText); layoutManager.AddTextContainer(textContainer); textStorage.AddLayoutManager(layoutManager); textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = label.LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)label.Lines; var labelSize = label.Bounds.Size; textContainer.Size = labelSize; var locationOfTouchInLabel = tap.LocationInView(label); var textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); var textContainerOffset = new CGPoint( (labelSize.Width - textBoundingBox.Size.Width) * 0.0 - textBoundingBox.Location.X, (labelSize.Height - textBoundingBox.Size.Height) * 0.0 - textBoundingBox.Location.Y); nfloat labelX; switch (Element.HorizontalTextAlignment) { case TextAlignment.End: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width); break; case TextAlignment.Center: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width) / 2; break; default: labelX = locationOfTouchInLabel.X; break; } var locationOfTouchInTextContainer = new CGPoint(labelX - textContainerOffset.X, locationOfTouchInLabel.Y - textContainerOffset.Y); nfloat partialFraction = 0; var indexOfCharacter = (nint)layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref partialFraction); nint scaledIndexOfCharacter = 0; if (label.Font.Name == "NeoSans-Light") { scaledIndexOfCharacter = (nint)(indexOfCharacter * 1.13); } if (label.Font.Name.StartsWith("HelveticaNeue", StringComparison.InvariantCulture)) { scaledIndexOfCharacter = (nint)(indexOfCharacter * 1.02); } foreach (var link in linkList) { var rangeLength = link.Range.Length; var tolerance = 0; if (label.Font.Name == "NeoSans-Light") { rangeLength = (nint)(rangeLength * 1.13); tolerance = 25; indexOfCharacter = scaledIndexOfCharacter; } if (label.Font.Name.StartsWith("HelveticaNeue", StringComparison.InvariantCulture)) { if (link.Range.Location > 2000) { indexOfCharacter = scaledIndexOfCharacter; } } // Xamarin version of NSLocationInRange? if ((indexOfCharacter >= (link.Range.Location - tolerance)) && (indexOfCharacter < (link.Range.Location + rangeLength + tolerance))) { return(link.Url); } } return(null); }
private string DetectTappedUrl(UIGestureRecognizer tap, UILabel label, IEnumerable <LinkData> linkList) { // Creates instances of NSLayoutManager, NSTextContainer and NSTextStorage var layoutManager = new NSLayoutManager(); var textContainer = new NSTextContainer(); var textStorage = new NSTextStorage(); textStorage.SetString(label.AttributedText); // Configures layoutManager and textStorage layoutManager.AddTextContainer(textContainer); textStorage.AddLayoutManager(layoutManager); // Configures textContainer textContainer.LineFragmentPadding = 0; textContainer.LineBreakMode = label.LineBreakMode; textContainer.MaximumNumberOfLines = (nuint)label.Lines; var labelSize = label.Bounds.Size; textContainer.Size = labelSize; // Finds the tapped character location and compare it to the specified range var locationOfTouchInLabel = tap.LocationInView(label); var textBoundingBox = layoutManager.GetUsedRectForTextContainer(textContainer); var textContainerOffset = new CGPoint((labelSize.Width - textBoundingBox.Size.Width) * 0.0 - textBoundingBox.Location.X, (labelSize.Height - textBoundingBox.Size.Height) * 0.0 - textBoundingBox.Location.Y); nfloat labelX; switch (Element.HorizontalTextAlignment) { case TextAlignment.End: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width); break; case TextAlignment.Center: labelX = locationOfTouchInLabel.X - (labelSize.Width - textBoundingBox.Size.Width) / 2; break; default: labelX = locationOfTouchInLabel.X; break; } var locationOfTouchInTextContainer = new CGPoint(labelX - textContainerOffset.X, locationOfTouchInLabel.Y - textContainerOffset.Y); nfloat partialFraction = 0; var indexOfCharacter = (nint)layoutManager.CharacterIndexForPoint(locationOfTouchInTextContainer, textContainer, ref partialFraction); nint scaledIndexOfCharacter = 0; // Problem is that method CharacterIndexForPoint always returns index based on UILabel font // ".SFUIText" which is the default Helvetica iOS font // HACK is to scale indexOfCharacter for 13% because NeoSans-Light is narrower font than ".SFUIText" if (label.Font.Name == "NeoSans-Light") { scaledIndexOfCharacter = (nint)(indexOfCharacter * 1.13); } // HelveticaNeue font family works perfect until character position in the string is more than 2000 chars // some uncosnsistent behaviour // if string has <b> tag than label.Font.Name from HelveticaNeue-Thin goes to HelveticaNeue-Bold if (label.Font.Name.StartsWith("HelveticaNeue", StringComparison.InvariantCulture)) { scaledIndexOfCharacter = (nint)(indexOfCharacter * 1.02); } foreach (var link in linkList) { var rangeLength = link.Range.Length; var tolerance = 0; if (label.Font.Name == "NeoSans-Light") { rangeLength = (nint)(rangeLength * 1.13); tolerance = 25; indexOfCharacter = scaledIndexOfCharacter; } if (label.Font.Name.StartsWith("HelveticaNeue", StringComparison.InvariantCulture)) { if (link.Range.Location > 2000) { indexOfCharacter = scaledIndexOfCharacter; } } // Xamarin version of NSLocationInRange? if ((indexOfCharacter >= (link.Range.Location - tolerance)) && (indexOfCharacter < (link.Range.Location + rangeLength + tolerance))) { return(link.Url); } } return(null); }
public void Include(NSTextStorage textStorage) { textStorage.DidProcessEditing += (sender, e) => { }; textStorage.WeakSubscribe <NSTextStorage, NSTextStorageEventArgs>(nameof(textStorage.DidProcessEditing), null); }
public virtual void ReplaceTextStorage (NSTextStorage newTextStorage) => throw new NotSupportedException ();
public void InitWithString() { using var obj = new NSTextStorage("Hello World"); }
public override void DrawRect(RectangleF dirtyRect) { var height = base.Bounds.Height; var calcValue = base.Bounds.Width * (Value * 0.01f); var context = NSGraphicsContext.CurrentContext.GraphicsPort; context.SetStrokeColor("#999999".ToCGColor()); context.SetLineWidth (1.0F); context.StrokeRect(new RectangleF(0, 0, base.Bounds.Width, height)); context.SetFillColor("#999999".ToCGColor()); context.FillRect(new RectangleF(0, 0, base.Bounds.Width, height)); context.SetFillColor(BackgroundColor.ToCGColor()); context.FillRect(new RectangleF(0, 0, calcValue, height)); var attrStr = "{0}".ToFormat(Label).CreateString("#ffffff".ToNSColor(), Font); var storage = new NSTextStorage(); storage.SetString(attrStr); var layout = new NSLayoutManager(); var container = new NSTextContainer(); layout.AddTextContainer(container); storage.AddLayoutManager(layout); // Get size // var size = layout.GetUsedRectForTextContainer (container).Size; // var width = size.Width / 2.0f; var width = (base.Bounds.Width / 2.0f) - (TextOffset.X); storage.DrawString(new PointF(width, TextOffset.Y)); }