예제 #1
0
        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);
예제 #2
0
        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);
        }
예제 #3
0
        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)
                    );
            }
        }
예제 #4
0
        void AppendData(NSData d)
        {
            NSString      s  = NSString.FromData(d, NSStringEncoding.UTF8);
            NSTextStorage ts = outputView.TextStorage;

            ts.Replace(new NSRange(ts.Length, 0), s);
        }
예제 #5
0
        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);
        }
예제 #7
0
 public LayoutInfo(ApplicationContext actx)
 {
     ApplicationContext = actx;
     Attributes         = new List <TextAttribute> ();
     TextStorage        = new NSTextStorage();
     TextContainer      = new NSTextContainer {
         LineFragmentPadding = 0.0f
     };
 }
예제 #8
0
        // 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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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");
                }
            }
        }
예제 #11
0
        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);
                }
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
 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);
 }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #17
0
        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));
        }
예제 #18
0
파일: TextBlock.iOS.cs 프로젝트: zzyzy/uno
        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);
            }
        }
예제 #19
0
        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);
        }
예제 #21
0
        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;
            }
        }
예제 #23
0
        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.";
            });
        }
예제 #24
0
        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);
        }
예제 #25
0
        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;
            }
        }
예제 #26
0
        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);
        }
예제 #28
0
        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);
 }
예제 #30
0
		public virtual void ReplaceTextStorage (NSTextStorage newTextStorage)
			=> throw new NotSupportedException ();
예제 #31
0
 public void InitWithString()
 {
     using var obj = new NSTextStorage("Hello World");
 }
예제 #32
0
        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));
        }