@@ -183,7 +183,7 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
183
183
184
184
185
185
func dimLineUnderLocation( location: CGPoint ) {
186
- let currentLine = Int ( location. y / ( font . lineHeight + lineSpacing ) )
186
+ let currentLine = lineNumberUnderPoint ( location)
187
187
slightlyDimLineWhileDraggingOver ( lineNumber: currentLine)
188
188
}
189
189
@@ -407,6 +407,13 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
407
407
}
408
408
}
409
409
410
+ func paragraphRangeUnderLocation( loc: CGPoint ) -> NSRange {
411
+ /*let storage = textStorage as EditorTextStorage
412
+ let nearestCharacterIndex = layoutManager.characterIndexForPoint(loc, inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
413
+ return storage.string()!.paragraphRangeForRange(<#range: NSRange#>)*/
414
+ return NSRange ( location: 0 , length: 0 )
415
+ }
416
+
410
417
func lineNumberUnderPoint( var point: CGPoint ) -> Int {
411
418
//point.y += lineSpacing
412
419
let storage = textStorage as EditorTextStorage
@@ -444,6 +451,51 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
444
451
return lineNumberToReturn
445
452
}
446
453
454
+ func boundingRectForLineNumber( lineNumber: Int ) -> CGRect {
455
+ //point.y += lineSpacing
456
+ let storage = textStorage as EditorTextStorage
457
+ let Context = UIGraphicsGetCurrentContext ( )
458
+ let Bounds = bounds
459
+
460
+ let textRange = layoutManager. glyphRangeForTextContainer ( textContainer)
461
+ let glyphsToShow = layoutManager. glyphRangeForCharacterRange ( textRange,
462
+ actualCharacterRange: nil )
463
+
464
+ var currentLineNumber = 0
465
+ var boundingRect : CGRect ?
466
+ var numberOfExtraLines = 0
467
+ func lineFragmentClosure( aRect: CGRect , aUsedRect: CGRect ,
468
+ textContainer: NSTextContainer ! , glyphRange: NSRange ,
469
+ stop: UnsafeMutablePointer < ObjCBool > ) -> Void {
470
+ let charRange = layoutManager. characterRangeForGlyphRange ( glyphRange, actualGlyphRange: nil )
471
+ let paraRange = storage. string ( ) !. paragraphRangeForRange ( charRange)
472
+ if charRange. location == paraRange. location {
473
+ currentLineNumber++
474
+ if currentLineNumber == lineNumber {
475
+ boundingRect = layoutManager. boundingRectForGlyphRange ( layoutManager. glyphRangeForCharacterRange ( paraRange, actualCharacterRange: nil ) , inTextContainer: textContainer)
476
+ boundingRect!. origin. x = 0
477
+ boundingRect!. size. width = frame. width
478
+ stop. initialize ( true )
479
+ }
480
+ } else {
481
+ numberOfExtraLines++
482
+ }
483
+ }
484
+ layoutManager. enumerateLineFragmentsForGlyphRange ( glyphsToShow,
485
+ usingBlock: lineFragmentClosure)
486
+ if boundingRect == nil {
487
+ let LineHeight = font. lineHeight + lineSpacing
488
+ let LineNumberRect = CGRect (
489
+ x: 0 ,
490
+ y: LineHeight * CGFloat( lineNumber - numberOfExtraLines + 1 ) ,
491
+ width: frame. width,
492
+ height: LineHeight)
493
+ boundingRect = LineNumberRect
494
+ }
495
+
496
+ return boundingRect!
497
+ }
498
+
447
499
private func drawLineNumbers( rect: CGRect ) {
448
500
let storage = textStorage as EditorTextStorage
449
501
let Context = UIGraphicsGetCurrentContext ( )
@@ -535,7 +587,8 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
535
587
func fragmentEnumerator( aRect: CGRect , aUsedRect: CGRect , textContainer: NSTextContainer ! , glyphRange: NSRange , stop: UnsafeMutablePointer < ObjCBool > ) -> Void {
536
588
let fragmentCharacterRange = layoutManager. characterRangeForGlyphRange ( glyphRange, actualGlyphRange: nil )
537
589
let fragmentParagraphRange = editorTextStorage. string ( ) !. paragraphRangeForRange ( fragmentCharacterRange)
538
- if NSEqualRanges ( draggedCharacterRange, fragmentCharacterRange) {
590
+ let draggedParagraphRange = editorTextStorage. string ( ) !. paragraphRangeForRange ( draggedCharacterRange)
591
+ if NSEqualRanges ( draggedParagraphRange, fragmentParagraphRange) {
539
592
//This means we've found the dragged line
540
593
currentLineNumber++
541
594
return
@@ -567,10 +620,22 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
567
620
if fragmentCharacterRange. length == fragmentParagraphRange. length {
568
621
label. attributedText = parentTextViewController. getAttributedStringForCharacterRange ( fragmentParagraphRange)
569
622
} else {
570
- let attributedStringBeforeLineBreak = NSMutableAttributedString ( attributedString: parentTextViewController. getAttributedStringForCharacterRange ( fragmentCharacterRange) )
571
- attributedStringBeforeLineBreak. appendAttributedString ( NSAttributedString ( string: " \n " ) )
572
- let attributedStringAfterLineBreak = parentTextViewController. getAttributedStringForCharacterRange ( NSRange ( location: NSMaxRange ( fragmentCharacterRange) , length: ( fragmentParagraphRange. length - fragmentCharacterRange. length) ) )
573
- attributedStringBeforeLineBreak. appendAttributedString ( attributedStringAfterLineBreak)
623
+ var attributedStringBeforeLineBreak : NSMutableAttributedString !
624
+ var attributedStringAfterLineBreak : NSMutableAttributedString !
625
+ if fragmentCharacterRange. location == fragmentParagraphRange. location {
626
+ //Dragging first line
627
+ attributedStringBeforeLineBreak = NSMutableAttributedString ( attributedString: parentTextViewController. getAttributedStringForCharacterRange ( fragmentCharacterRange) )
628
+ attributedStringBeforeLineBreak. appendAttributedString ( NSAttributedString ( string: " \n " ) )
629
+ attributedStringAfterLineBreak = NSMutableAttributedString ( attributedString: parentTextViewController. getAttributedStringForCharacterRange ( NSRange ( location: NSMaxRange ( fragmentCharacterRange) , length: ( fragmentParagraphRange. length - fragmentCharacterRange. length) ) ) )
630
+ attributedStringBeforeLineBreak. appendAttributedString ( attributedStringAfterLineBreak)
631
+ } else {
632
+ //Dragging second line, character range is smaller than paragraph range
633
+ attributedStringBeforeLineBreak = NSMutableAttributedString ( attributedString: parentTextViewController. getAttributedStringForCharacterRange ( NSRange ( location: fragmentParagraphRange. location, length: fragmentParagraphRange. length - fragmentCharacterRange. length) ) )
634
+ attributedStringBeforeLineBreak. appendAttributedString ( NSAttributedString ( string: " \n " ) )
635
+ attributedStringAfterLineBreak = NSMutableAttributedString ( attributedString: parentTextViewController. getAttributedStringForCharacterRange ( fragmentCharacterRange) )
636
+ attributedStringBeforeLineBreak. appendAttributedString ( attributedStringAfterLineBreak)
637
+ }
638
+
574
639
label. lineBreakMode = NSLineBreakMode . ByWordWrapping
575
640
label. numberOfLines = 0
576
641
var paragraphStyle = NSMutableParagraphStyle ( )
@@ -619,49 +684,54 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
619
684
if max ( 1 , lineNumber) < draggedLineNumber {
620
685
//Move the ones between the current drag location and dragged line
621
686
for lineToMove in max ( lineNumber, 1 ) ... ( draggedLineNumber - 1 ) {
622
- let labelToMove = dragOverlayLabels [ lineToMove] !
623
- //check if offset is supposed to move
624
- if labelToMove. frame. origin. y == originalDragOverlayLabelOffsets [ lineToMove] ! {
625
- //shift down
626
- var oldFrame = labelToMove. frame
627
- oldFrame. origin. y += lineSpacing + font. lineHeight
628
- labelToMove. frame = oldFrame
629
- labelToMove. setNeedsLayout ( )
687
+ if let labelToMove = dragOverlayLabels [ lineToMove] {
688
+ //check if offset is supposed to move
689
+ if labelToMove. frame. origin. y == originalDragOverlayLabelOffsets [ lineToMove] ! {
690
+ //shift down
691
+ var oldFrame = labelToMove. frame
692
+ oldFrame. origin. y += lineSpacing + font. lineHeight
693
+ labelToMove. frame = oldFrame
694
+ labelToMove. setNeedsLayout ( )
695
+ }
630
696
}
697
+
631
698
}
632
699
//Reset the ones above that
633
700
if lineNumber != 1 && draggedLineNumber != 1 {
634
701
for lineToReset in 1 ... max ( 1 , lineNumber - 1 ) {
635
- let labelToReset = dragOverlayLabels [ lineToReset] !
636
- if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
637
- var oldFrame = labelToReset. frame
638
- oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
639
- labelToReset. frame = oldFrame
640
- labelToReset. setNeedsLayout ( )
702
+ if let labelToReset = dragOverlayLabels [ lineToReset] {
703
+ if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
704
+ var oldFrame = labelToReset. frame
705
+ oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
706
+ labelToReset. frame = oldFrame
707
+ labelToReset. setNeedsLayout ( )
708
+ }
641
709
}
642
710
}
643
711
}
644
712
645
713
} else if min ( lineNumber, maxLine) > draggedLineNumber {
646
714
//Move the lines between the dragged line and the current drag
647
715
for lineToMove in ( draggedLineNumber + 1 ) ... min ( lineNumber, maxLine) {
648
- let labelToMove = dragOverlayLabels [ lineToMove] !
649
- if labelToMove. frame. origin. y == originalDragOverlayLabelOffsets [ lineToMove] ! {
650
- var oldFrame = labelToMove. frame
651
- oldFrame. origin. y -= lineSpacing + font. lineHeight
652
- labelToMove. frame = oldFrame
653
- labelToMove. setNeedsLayout ( )
716
+ if let labelToMove = dragOverlayLabels [ lineToMove] {
717
+ if labelToMove. frame. origin. y == originalDragOverlayLabelOffsets [ lineToMove] ! {
718
+ var oldFrame = labelToMove. frame
719
+ oldFrame. origin. y -= lineSpacing + font. lineHeight
720
+ labelToMove. frame = oldFrame
721
+ labelToMove. setNeedsLayout ( )
722
+ }
654
723
}
655
724
}
656
725
//Reset the ones below that
657
726
if lineNumber != maxLine {
658
727
for lineToReset in min ( maxLine, lineNumber + 1 ) ... maxLine {
659
- let labelToReset = dragOverlayLabels [ lineToReset] !
660
- if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
661
- var oldFrame = labelToReset. frame
662
- oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
663
- labelToReset. frame = oldFrame
664
- labelToReset. setNeedsLayout ( )
728
+ if let labelToReset = dragOverlayLabels [ lineToReset] {
729
+ if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
730
+ var oldFrame = labelToReset. frame
731
+ oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
732
+ labelToReset. frame = oldFrame
733
+ labelToReset. setNeedsLayout ( )
734
+ }
665
735
}
666
736
}
667
737
}
@@ -679,13 +749,15 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
679
749
linesToReset. append ( draggedLineNumber + 1 )
680
750
}
681
751
for lineToReset in linesToReset {
682
- let labelToReset = dragOverlayLabels [ lineToReset] !
683
- if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
684
- var oldFrame = labelToReset. frame
685
- oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
686
- labelToReset. frame = oldFrame
687
- labelToReset. setNeedsLayout ( )
752
+ if let labelToReset = dragOverlayLabels [ lineToReset] {
753
+ if labelToReset. frame. origin. y != originalDragOverlayLabelOffsets [ lineToReset] ! {
754
+ var oldFrame = labelToReset. frame
755
+ oldFrame. origin. y = originalDragOverlayLabelOffsets [ lineToReset] !
756
+ labelToReset. frame = oldFrame
757
+ labelToReset. setNeedsLayout ( )
758
+ }
688
759
}
760
+
689
761
}
690
762
}
691
763
}
@@ -699,17 +771,11 @@ class EditorTextView: UITextView, NSLayoutManagerDelegate {
699
771
700
772
//Note, this won't take doubled lines into account
701
773
private func lineNumberOfLocationInTextView( loc: CGPoint ) -> Int {
702
- return Int ( ( loc. y - lineSpacing ) / ( lineSpacing + font . lineHeight ) + 1 )
774
+ return lineNumberUnderPoint ( loc)
703
775
}
704
776
705
777
func getLineNumberRect( lineNumber: Int ) -> CGRect {
706
- let LineHeight = font. lineHeight + lineSpacing
707
- let LineNumberRect = CGRect (
708
- x: 0 ,
709
- y: LineHeight * CGFloat( lineNumber) + lineSpacing,
710
- width: frame. width,
711
- height: LineHeight)
712
- return LineNumberRect
778
+ return boundingRectForLineNumber ( lineNumber)
713
779
}
714
780
715
781
0 commit comments