I'm using PDFKit on iOS to highlight texts (PDF file). I do it by create a PDFAnnotation and add it to the selected text area. I want to highlight precisely the selected area but it always covers the whole line like the pics below. How can I create the annotation for the selected area only??
My code:
let highlight = PDFAnnotation(bounds: selectionText.bounds(for: page), forType: PDFAnnotationSubtype.highlight, withProperties: nil)
highlight.color = highlightColor
page.addAnnotation(highlight)
As suggested in PDFKit Highlight Annotation: quadrilateralPoints you can use quadrilateralPoints to add different lines highlights to the same annotation.
func highlight() {
guard let selection = pdfView.currentSelection, let currentPage = pdfView.currentPage else {return}
let selectionBounds = selection.bounds(for: currentPage)
let lineSelections = selection.selectionsByLine()
let highlightAnnotation = PDFAnnotation(bounds: selectionBounds, forType: PDFAnnotationSubtype.highlight, withProperties: nil)
highlightAnnotation.quadrilateralPoints = [NSValue]()
for (index, lineSelection) in lineSelections.enumerated() {
let n = index * 4
let bounds = lineSelection.bounds(for: pdfView.currentPage!)
let convertedBounds = bounds.convert(to: selectionBounds.origin)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.topLeft), at: 0 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.topRight), at: 1 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.bottomLeft), at: 2 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.bottomRight), at: 3 + n)
}
pdfView.currentPage?.addAnnotation(highlightAnnotation)
}
extension CGRect {
var topLeft: CGPoint {
get {
return CGPoint(x: self.origin.x, y: self.origin.y + self.height)
}
}
var topRight: CGPoint {
get {
return CGPoint(x: self.origin.x + self.width, y: self.origin.y + self.height)
}
}
var bottomLeft: CGPoint {
get {
return CGPoint(x: self.origin.x, y: self.origin.y)
}
}
func convert(to origin: CGPoint) -> CGRect {
return CGRect(x: self.origin.x - origin.x, y: self.origin.y - origin.y, width: self.width, height: self.height)
}
}
PDFSelection bounds(forPage:) method returns one rectangle to satisfy whole selection area. Is not the best solution in your case.
Try with selectionsByLine(), and add individual annotation for every rect, representing every single selected line in PDF. Example:
let selections = pdfView.currentSelection?.selectionsByLine()
// Simple scenario, assuming your pdf is single-page.
guard let page = selections?.first?.pages.first else { return }
selections?.forEach({ selection in
let highlight = PDFAnnotation(bounds: selection.bounds(for: page), forType: .highlight, withProperties: nil)
highlight.endLineStyle = .square
highlight.color = UIColor.orange.withAlphaComponent(0.5)
page.addAnnotation(highlight)
})
Related
I was able to get the position of the x Label from xAxisRenderer. But I failed to import this into my project. I'm trying to get this position and create a custom x-axis. How can I store a value in an external module and use it in an internal module?
#objc open func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint)
{
guard let transformer = self.transformer else { return }
let paraStyle = ParagraphStyle.default.mutableCopy() as! MutableParagraphStyle
paraStyle.alignment = .center
let labelAttrs: [NSAttributedString.Key : Any] = [.font: axis.labelFont,
.foregroundColor: axis.labelTextColor,
.paragraphStyle: paraStyle]
let labelRotationAngleRadians = axis.labelRotationAngle.DEG2RAD
let isCenteringEnabled = axis.isCenterAxisLabelsEnabled
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint.zero
var labelMaxSize = CGSize.zero
if axis.isWordWrapEnabled
{
labelMaxSize.width = axis.wordWrapWidthPercent * valueToPixelMatrix.a
}
let entries = axis.entries
for i in entries.indices
{
let px = isCenteringEnabled ? CGFloat(axis.centeredEntries[i]) : CGFloat(entries[i])
position = CGPoint(x: px, y: 0)
.applying(valueToPixelMatrix)
guard viewPortHandler.isInBoundsX(position.x) else { continue }
let label = axis.valueFormatter?.stringForValue(axis.entries[i], axis: axis) ?? ""
let labelns = label as NSString
if axis.isAvoidFirstLastClippingEnabled
{
// avoid clipping of the last
if i == axis.entryCount - 1 && axis.entryCount > 1
{
let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
if width > viewPortHandler.offsetRight * 2.0,
position.x + width > viewPortHandler.chartWidth
{
position.x -= width / 2.0
}
}
else if i == 0
{ // avoid clipping of the first
let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
position.x += width / 2.0
}
}
print(position.x)
drawLabel(context: context,
formattedLabel: label,
x: position.x,
y: pos,
attributes: labelAttrs,
constrainedTo: labelMaxSize,
anchor: anchor,
angleRadians: labelRotationAngleRadians)
}
}
I tried to get the position value by creating an open class called XAxisPosition, but the value is initialized to 0 in the process of importing it into my project module. I have access to it, but how do I get the values fully into my project?
public protocol XAxisRendererDelegate
{
#objc optional func renderer(_ renderer: XAxisRenderer,
labelPostion: CGPoint)
}
#objc open weak var delegate: XAxisRendererDelegate?
I added this XAxisRenderer.
and add this in drawLabels.
let px = isCenteringEnabled ? CGFloat(axis.centeredEntries[i]) :
CGFloat(entries[i])
position = CGPoint(x: px, y: 0)
.applying(valueToPixelMatrix)
delegate?.renderer?(self, labelPostion: position)
and use this
chartView.xAxisRenderer.delegate = self
Its array data for only one cell view, I need to set product_name and total_quantity on table view cell.sometime total_quantity can be 2 sometime it can be 10. Just give me some basic idea so I can move forward.
[[{"total_quantity":"50","product_id":"13","product_name":"Prawns"},{"total_quantity":"13","product_id":"14","product_name":"Fish"},{"total_quantity":"57","product_id":"15","product_name":"Chicken
Breast"},{"total_quantity":"10","product_id":"16","product_name":"Beef"}],[{"total_quantity":"50","product_id":"13","product_name":"Prawns"},{"total_quantity":"13","product_id":"14","product_name":"Fish"},{"total_quantity":"57","product_id":"15","product_name":"Chicken
Breast"},{"total_quantity":"10","product_id":"16","product_name":"Beef"}]]
Screen shot
extension String {
func sizeWithGivenSize(_ size: CGSize,font: UIFont,paragraph: NSMutableParagraphStyle? = nil) -> CGSize {
var attributes = [String:AnyObject]()
attributes[NSFontAttributeName] = font
if let p = paragraph {
attributes[NSParagraphStyleAttributeName] = p
}
attributes[NSFontAttributeName] = font
return (self as NSString).boundingRect(with: size,
options: [.usesLineFragmentOrigin,.usesFontLeading],
attributes: attributes,
context: nil).size
}
Use this Method to get UILabel's Frame with different length string.
then to calculate Height form top to bottom.
for high performance, you'd better to do this at model.
For example:
func calculateFrame() -> Void {
let width = UIComponentsConst.screenWidth
var tmpFrame = ProjectDetailTeamCellLayout()
var maxX: CGFloat = 0
var maxY: CGFloat = tmpFrame.topSpace
if let titleText = title {
let titleSize = titleText.sizeWithGivenSize(MaxSize, font: ProjectDetailTeamCellLayout.titleFont, paragraph: nil)
tmpFrame.titleLabelFrame = CGRect.init(x: 15, y: maxY, width: titleSize.width, height: titleSize.height)
maxY = tmpFrame.titleLabelFrame!.maxY
maxX = tmpFrame.titleLabelFrame!.maxX
}
if let nameText = nameTitle, !nameText.isEmpty {
tmpFrame.grayLineFrame = CGRect(x: maxX + tmpFrame.itemSpace, y: tmpFrame.topSpace, width: 1, height: tmpFrame.titleLabelFrame?.height ?? 0)
let nameSize = nameText.sizeWithGivenSize(MaxSize, font: ProjectDetailTeamCellLayout.nameLabelFont, paragraph: nil)
let nameTmpFrame = CGRect(x: tmpFrame.grayLineFrame!.maxX + tmpFrame.itemSpace, y: tmpFrame.topSpace + (tmpFrame.titleLabelFrame?.height ?? nameSize.height ) / 2 - nameSize.height / 2, width: nameSize.width, height: nameSize.height)
tmpFrame.nameLabelFrame = nameTmpFrame
maxY = maxY > tmpFrame.nameLabelFrame!.maxY ? maxY : tmpFrame.nameLabelFrame!.maxY
}
if let subTitleText = subTitle, !subTitleText.isEmpty {
let subTitleSize = subTitleText.sizeWithGivenSize(CGSize(width: width - 45, height: CGFloat.greatestFiniteMagnitude), font: ProjectDetailTeamCellLayout.subTitleFont, paragraph: nil)
tmpFrame.subTitleLabelFrame = CGRect(x: 15, y: maxY + tmpFrame.lineSpace, width: subTitleSize.width, height: subTitleSize.height)
maxY = tmpFrame.subTitleLabelFrame!.maxY + 10
}
tmpFrame.height = maxY + 5
self.frameInfo = tmpFrame
}
try ?
Use something like this, if you want to change the height:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let object = myArrayDataset[indexPath.row]
//for example
if object.numberOfItems > 10 {
return 80.0
}
else {
return 40.0
}
}
I have a pain map where I use location coordinates to plot where there has been pain. I can add the "dots" in a for in loop and they show up fine. However I cannot remove them before I instantiate them outside the for in loop. So every time I update the view it will plot new ones not ones on top of the old ones. What can I do?
This version adds the dots well but I cannot remove them outside as I cannot call dot.removeFromSuperview()
DispatchQueue.global(qos: .background).async {
if let locationNotNilX = self.painDiagramAnalysisModel.painLocationXFor(days: self.daysChosen){
x = locationNotNilX
count = locationNotNilX.count
}
if let locationNotNilY = self.painDiagramAnalysisModel.painLocationYFor(days: self.daysChosen){
y = locationNotNilY
}
let locationsArray = zip(x, y)
print("zipped array \(locationsArray)")
DispatchQueue.main.async {
let dot = UIImageView()
dot.removeFromSuperview()
dot.image = nil
for item in locationsArray {
self.locationPainY = (diagramHeight * CGFloat(item.1)) + originY
self.locationPainX = (diagramWidth * CGFloat(item.0)) + originX
print(" locationX \(self.locationPainX) locationY \(self.locationPainY)")
dot.image = UIImage(named: "dot")
dot.frame = CGRect(x: self.locationPainX - (dotDiameter / 4), y: self.locationPainY - (dotDiameter / 4), width: dotDiameter , height: dotDiameter)
if count > 2 {
dot.alpha = 0.6
} else {
dot.alpha = 1.0
}
dot.readingsPressedAnimation()
self.view.addSubview(dot)
}
}
}
This version removes the dot but there is only one dot (self hangs on to the dot and just instantiates it once in the for in loop.
let dot = UIImageView()
dot.removeFromSuperview()
dot.image = nil
DispatchQueue.global(qos: .background).async {
if let locationNotNilX = self.painDiagramAnalysisModel.painLocationXFor(days: self.daysChosen){
x = locationNotNilX
count = locationNotNilX.count
}
if let locationNotNilY = self.painDiagramAnalysisModel.painLocationYFor(days: self.daysChosen){
y = locationNotNilY
}
let locationsArray = zip(x, y)
print("zipped array \(locationsArray)")
DispatchQueue.main.async {
for item in locationsArray {
self.locationPainY = (diagramHeight * CGFloat(item.1)) + originY
self.locationPainX = (diagramWidth * CGFloat(item.0)) + originX
print(" locationX \(self.locationPainX) locationY \(self.locationPainY)")
dot.image = UIImage(named: "dot")
dot.frame = CGRect(x: self.locationPainX - (dotDiameter / 4), y: self.locationPainY - (dotDiameter / 4), width: dotDiameter , height: dotDiameter)
if count > 2 {
dot.alpha = 0.6
} else {
dot.alpha = 1.0
}
dot.readingsPressedAnimation()
self.view.addSubview(dot)
}
}
}
How can I add many instances of the dot and remove them outside the loop?
Iterate over your maps subviews and remove all UIImageViews:
func removeDots() {
for case let dot as UIImageView in yourPainMapView.subViews {
dot.removeFromSuperView()
}
}
In case you are using other UIImageView subViews you do not want to remove, subclass UIImageView (class MyDot:UIImage {...}):
for case let dot as MyDot in yourPainMapView.subViews
I have a UIView class in my app which plots a line graph. In there, I assign my graphPoints variables like so :
var graphPoints:[Int] = [1,2,3,5,7,9]
var graphPoints2:[Int] = [1,2,3,5,7,9]
What I want to do is pass an array of Int from another class and assign those variables, but I am not sure how to do it. Initially i put all my code into one func with array [Int] as parameters and called it from another class but it stopped plotting the graph altogether. How do i do this?
Here is my UIVIew GraphPlotter class code :
import UIKit
#IBDesignable class GraphPlotter: UIView {
var graphPoints:[Int] = [1,2,3,5,7,9]
var graphPoints2:[Int] = [1,2,3,5,7,9]
//1 - the properties for the gradient
var startColor: UIColor = UIColor.redColor()
var endColor: UIColor = UIColor.greenColor()
override func drawRect(rect: CGRect) {
let width = rect.width
let height = rect.height
//set up background clipping area
let path = UIBezierPath(roundedRect: rect,
byRoundingCorners: UIRectCorner.AllCorners,
cornerRadii: CGSize(width: 8.0, height: 8.0))
path.addClip()
//2 - get the current context
let context = UIGraphicsGetCurrentContext()
let colors = [startColor.CGColor, endColor.CGColor]
//3 - set up the color space
let colorSpace = CGColorSpaceCreateDeviceRGB()
//4 - set up the color stops
let colorLocations:[CGFloat] = [0.0, 1.0]
//5 - create the gradient
let gradient = CGGradientCreateWithColors(colorSpace,
colors,
colorLocations)
//6 - draw the gradient
var startPoint = CGPoint.zero
var endPoint = CGPoint(x:0, y:self.bounds.height)
CGContextDrawLinearGradient(context,
gradient,
startPoint,
endPoint,
[])
//calculate the x point
let margin:CGFloat = 40.0
let columnXPoint = { (column:Int) -> CGFloat in
//Calculate gap between points
let spacer = (width - margin*2 - 4) /
CGFloat((self.graphPoints.count - 1))
var x:CGFloat = CGFloat(column) * spacer
x += margin + 2
return x
}
// calculate the y point
let topBorder:CGFloat = 60
let bottomBorder:CGFloat = 50
let graphHeight = height - topBorder - bottomBorder
let maxValue = graphPoints2.maxElement()!
let columnYPoint = { (graphPoint2:Int) -> CGFloat in
var y:CGFloat = CGFloat(graphPoint2) /
CGFloat(maxValue) * graphHeight
y = graphHeight + topBorder - y // Flip the graph
return y
}
// draw the line graph
UIColor.flatTealColor().setFill()
UIColor.flatTealColor().setStroke()
//set up the points line
let graphPath = UIBezierPath()
//go to start of line
graphPath.moveToPoint(CGPoint(x:columnXPoint(0),
y:columnYPoint(graphPoints2[0])))
//add points for each item in the graphPoints array
//at the correct (x, y) for the point
for i in 1..<graphPoints.count {
let nextPoint = CGPoint(x:columnXPoint(i),
y:columnYPoint(graphPoints2[i]))
graphPath.addLineToPoint(nextPoint)
}
//Create the clipping path for the graph gradient
//1 - save the state of the context (commented out for now)
CGContextSaveGState(context)
//2 - make a copy of the path
let clippingPath = graphPath.copy() as! UIBezierPath
//3 - add lines to the copied path to complete the clip area
clippingPath.addLineToPoint(CGPoint(
x: columnXPoint(graphPoints.count - 1),
y:height))
clippingPath.addLineToPoint(CGPoint(
x:columnXPoint(0),
y:height))
clippingPath.closePath()
//4 - add the clipping path to the context
clippingPath.addClip()
let highestYPoint = columnYPoint(maxValue)
startPoint = CGPoint(x:margin, y: highestYPoint)
endPoint = CGPoint(x:margin, y:self.bounds.height)
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, [])
CGContextRestoreGState(context)
//draw the line on top of the clipped gradient
graphPath.lineWidth = 2.0
graphPath.stroke()
//Draw the circles on top of graph stroke
for i in 0..<graphPoints.count {
var point = CGPoint(x:columnXPoint(i), y:columnYPoint(graphPoints2[i]))
point.x -= 5.0/2
point.y -= 5.0/2
let circle = UIBezierPath(ovalInRect:
CGRect(origin: point,
size: CGSize(width: 5.0, height: 5.0)))
circle.fill()
let label = UILabel(frame: CGRectMake(0, 0, 200, 21))
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
// label.text = "I'am a test label"
self.addSubview(label)
}
//Draw horizontal graph lines on the top of everything
let linePath = UIBezierPath()
//top line
linePath.moveToPoint(CGPoint(x:margin, y: topBorder))
linePath.addLineToPoint(CGPoint(x: width - margin,
y:topBorder))
//center line
linePath.moveToPoint(CGPoint(x:margin,
y: graphHeight/2 + topBorder))
linePath.addLineToPoint(CGPoint(x:width - margin,
y:graphHeight/2 + topBorder))
//bottom line
linePath.moveToPoint(CGPoint(x:margin,
y:height - bottomBorder))
linePath.addLineToPoint(CGPoint(x:width - margin,
y:height - bottomBorder))
let color = UIColor.flatTealColor()
color.setStroke()
linePath.lineWidth = 1.0
linePath.stroke()
}
}
DBController, func dosmth where I pass the array :
func dosmth(metadata: DBMetadata!) {
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let localFilePath = (documentsDirectoryPath as NSString).stringByAppendingPathComponent(metadata.filename)
var newarray = [Int]()
do{
let data = try String(contentsOfFile: localFilePath as String,
encoding: NSASCIIStringEncoding)
print(data)
newarray = data.characters.split(){$0 == ","}.map{
Int(String.init($0).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()))!}
print(newarray)
}
catch let error { print(error) }
//Probably wrong
GraphPlotter().graphPoints = newarray
GraphPlotter().graphPoints2 = newarray
}
So your drawRect method is based on the two variables graphPoints and graphPoints2. Create a method whose job is to update the arrays of these two variables, and then invoke setNeedsDisplay - which will go on to redraw the view.
func plotGraphPoints(gpArray1 : [Int], andMorePoints gpArray2: [Int] ) {
print("Old Values", self.graphPoints)
self.graphPoints = gpArray1
self.graphPoints2 = gpArray2
print("New values", self.graphPoints)
self.setNeedsDisplay()
}
First, I'd set these up so that any update will redraw the view:
var graphPoints:[Int]? { didSet { setNeedsDisplay() } }
var graphPoints2:[Int]? { didSet { setNeedsDisplay() } }
Note, I made those optionals, because you generally want it to handle the absence of data with nil values rather than dummy values. This does assume, though, that you'll tweak your implementation to detect and handle these nil values, e.g., before you start drawing the lines, do a
guard graphPoints != nil && graphPoints2 != nil else { return }
But, I notice that this whole class is IBDesignable, in which case, you probably want a prepareForInterfaceBuilder that provides sample data:
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
graphPoints = [1,2,3,5,7,9]
graphPoints2 = [1,2,3,5,7,9]
}
Second, your other class needs to have a reference to this custom view.
If this "other" class is the view controller and you added the custom view via IB, you would just add a #IBOutlet for the custom view to this view controller. If you added this custom view programmatically, you'd just keep a reference to it in some property after adding it to the view hierarchy. But, however you added a reference to that view, say graphView, you'd just set these properties:
graphView.graphPoints = ...
graphView.graphPoints2 = ...
If this "other" class is something other than a view controller (and in discussion, it sounds like the class in question is a controller for processing of asynchronous DropBox API), you also need to give that class some mechanism to reference the view controller (and thus the custom view). You can accomplish this by either implementing a "completion handler pattern" or a "delegate-protocol" pattern.
I am using BarChartView from danielgindi/ios-charts charting library. So far I am able to get following BarChartView. My question, is there any way to Customize X Axis that way, it will only show min (left most value 37.03), max (right most value 37.31 which is hiding), value for green bar (37.17) and value for orange bar (37.18 which is hiding again). In a nutshell I want to hide some value from XAxis which is not important in my case.
This is an example: add a property called showOnlyLeftRightEnabled in YourChartXAxis class, then in your custom x axis renderer, overide internal override func drawLabels(context context: CGContext, pos: CGFloat, anchor: CGPoint).
To display the middle one's you need to figure out which bar it is, and convert the x Index to pixel values just like what I did for the left most and right most value via CGPointApplyAffineTransform(position, valueToPixelMatrix)
internal override func drawLabels(context context: CGContext, pos: CGFloat, anchor: CGPoint)
{
let paraStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
paraStyle.alignment = .Center
let labelAttrs = [NSFontAttributeName: _xAxis.labelFont,
NSForegroundColorAttributeName: _xAxis.labelTextColor,
NSParagraphStyleAttributeName: paraStyle]
let labelRotationAngleRadians = _xAxis.labelRotationAngle * ChartUtils.Math.FDEG2RAD
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
var labelMaxSize = CGSize()
if (_xAxis.isWordWrapEnabled)
{
labelMaxSize.width = _xAxis.wordWrapWidthPercent * valueToPixelMatrix.a
}
if let showOnlyLeftRight = (_xAxis as? YourChartXAxis)?.showOnlyLeftRightEnabled
{
if (showOnlyLeftRight)
{
for (var i = lowestVisibleXIndex, maxX = min(highestVisibleXIndex + 1, _xAxis.values.count); i < maxX; i += maxX - lowestVisibleXIndex - 1)
{
let label = _xAxis.values[i]
if (label == nil)
{
continue
}
position.x = CGFloat(i)
position.y = 0.0
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
let labelns = label! as NSString
//label location by string width
// fix rightLabel
if (highestVisibleXIndex == lowestVisibleXIndex)
{
return super.drawLabels(context: context, pos: pos, anchor: anchor)
}
else if (i == highestVisibleXIndex)
{
let width = labelns.boundingRectWithSize(labelMaxSize, options: .UsesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
rightLabelX -= width / 2.0
}
else if (i == lowestVisibleXIndex)
{ // fix leftLabel
let width = labelns.boundingRectWithSize(labelMaxSize, options: .UsesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
leftLabelX += width / 2.0
}
// fill leftLabel and rightLabel in current visible screen
if (lowestVisibleXIndex == highestVisibleXIndex) {
ChartUtils.drawMultilineText(context: context, text: label!, point: CGPoint(x: leftLabelX, y: pos), attributes: labelAttrs, constrainedToSize: labelMaxSize, anchor: anchor, angleRadians: labelRotationAngleRadians)
ChartUtils.drawMultilineText(context: context, text: label!, point: CGPoint(x: rightLabelX, y: pos), attributes: labelAttrs, constrainedToSize: labelMaxSize, anchor: anchor, angleRadians: labelRotationAngleRadians)
break
} else if (i == lowestVisibleXIndex) {
ChartUtils.drawMultilineText(context: context, text: label!, point: CGPoint(x: leftLabelX, y: pos), attributes: labelAttrs, constrainedToSize: labelMaxSize, anchor: anchor, angleRadians: labelRotationAngleRadians)
} else if (i == highestVisibleXIndex) {
ChartUtils.drawMultilineText(context: context, text: label!, point: CGPoint(x: rightLabelX, y: pos), attributes: labelAttrs, constrainedToSize: labelMaxSize, anchor: anchor, angleRadians: labelRotationAngleRadians)
}
}
} else {
super.drawLabels(context: context, pos: pos, anchor: anchor)
}
}
}