         self.font = UIFont.systemFont(ofSize: UIFont.systemFontSize)
         super.init(coder: aDecoder)
     }
-
-    func size(with font: UIFont) -> CGSize {
+    
+    // MARK:- Sizing
+    
+    /// The size of bubble
+    /// - Note: This size does NOT include the arrow
+    var bubbleSize: CGSize {
         
         let frame = UIApplication.shared.keyWindow!.frame
         var widthDelta = CGFloat(0)
         
         if (arrowPosition == .left || arrowPosition == .right) {
-            widthDelta = CGFloat(ARROW_SIZE)
-        }
-        
-        let boundingSize = CGSize(width: frame.size.width - widthDelta - CGFloat(PADDING * 3.0), height: CGFloat.greatestFiniteMagnitude)
-        let result = NSString(string: title!).boundingRect(with: boundingSize, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName : font], context: nil).size
-        
-        return CGSize(width: result.width + CGFloat(PADDING * 3.0), height: result.height + CGFloat(PADDING * 2.5))
-    }
-
-    func calculateFrame(with font: UIFont) -> CGRect {
+            widthDelta = CGFloat(arrowHeight)
+        }
+        
+        let boundingSize = CGSize(width: frame.size.width - widthDelta - textPadding * 3.0, height: CGFloat.greatestFiniteMagnitude)
+        let result = NSString(string: text!).boundingRect(with: boundingSize, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName : font], context: nil).size
+        
+        return CGSize(width: result.width + textPadding * 3.0, height: result.height + textPadding * 2.5)
+    }
+    
+    /// The frame of the entire BubbleView, including the arrow
+    var bubbleViewFrame: CGRect {
         // Calculate bubble position
         var x = attachedFrame.origin.x
         var y = attachedFrame.origin.y
       
-        let size = self.size(with: font)
-
-        var widthDelta = 0, heightDelta = 0
+        let size = bubbleSize
+
+        var widthDelta: CGFloat = 0, heightDelta: CGFloat = 0
 
         if (arrowPosition == .left || arrowPosition == .right) {
             y += attachedFrame.size.height / 2 - size.height / 2
-            x += arrowPosition == .left ? CGFloat(ARROW_SPACE) + attachedFrame.size.width : -(CGFloat(ARROW_SPACE) * 2 + size.width)
-            widthDelta = ARROW_SIZE
+            x += arrowPosition == .left ? arrowSpace + attachedFrame.size.width : -(arrowSpace * 2 + size.width)
+            widthDelta = arrowHeight
         } else {
             x += attachedFrame.size.width / 2 - size.width / 2
-            y += arrowPosition == .top ? CGFloat(ARROW_SPACE) + attachedFrame.size.height : -(CGFloat(ARROW_SPACE) * 2 + size.height)
-            heightDelta = ARROW_SIZE
-        }
-
-        return CGRect(x: x, y: y, width: size.width + CGFloat(widthDelta), height: size.height + CGFloat(heightDelta))
-    }
-
+            y += arrowPosition == .top ? arrowSpace + attachedFrame.size.height : -(arrowSpace * 2 + size.height)
+            heightDelta = arrowHeight
+        }
+
+        return CGRect(x: x, y: y, width: size.width + widthDelta, height: size.height + heightDelta)
+    }
+    
+    /// Offsets to account for the arrow position
     var offsets: CGSize {
-        return CGSize(width: arrowPosition == .left ? ARROW_SIZE : 0, height: arrowPosition == .top ? ARROW_SIZE : 0)
+        return CGSize(width: arrowPosition == .left ? arrowHeight : 0, height: arrowPosition == .top ? arrowHeight : 0)
     }
 
     // MARK:- Drawing & Animation

import Foundation
import UIKit

let ARROW_SIZE = 6
let ARROW_SPACE = 6
let PADDING = 8.0
let RADIUS = 6.0

class BubbleView: UIView {
    enum ArrowPosition {
        case top
        case bottom


        ctx.saveGState()

        let size = bubbleSize
        
        let clipPath = UIBezierPath(roundedRect: CGRect(x: offsets.width, y: offsets.height, width: size.width, height: size.height), cornerRadius: cornerRadius)
      
        ctx.addPath(clipPath.cgPath)
        ctx.setFillColor(color.cgColor)
