Skip to content

Instantly share code, notes, and snippets.

@irshadpc
Forked from natecook1000/CalculatorView.swift
Created February 28, 2017 11:45
Show Gist options
  • Select an option

  • Save irshadpc/00b1d6391b23fc5012883d2d5c7f11a5 to your computer and use it in GitHub Desktop.

Select an option

Save irshadpc/00b1d6391b23fc5012883d2d5c7f11a5 to your computer and use it in GitHub Desktop.

Revisions

  1. @natecook1000 natecook1000 revised this gist Dec 17, 2015. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions CalculatorView.swift
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    -// CalculatorView.swift
    -// as seen in http://nshipster.com/ibinspectable-ibdesignable/
    -//
    -// (c) 2015 Nate Cook, licensed under the MIT license
    // CalculatorView.swift
    // as seen in http://nshipster.com/ibinspectable-ibdesignable/
    //
    // (c) 2015 Nate Cook, licensed under the MIT license

    /// The alignment for drawing an String inside a bounding rectangle.
    enum NCStringAlignment {
  2. @natecook1000 natecook1000 revised this gist Dec 17, 2015. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions CalculatorView.swift
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,8 @@
    -// CalculatorView.swift
    -// as seen in http://nshipster.com/ibinspectable-ibdesignable/
    -//
    -// (c) 2015 Nate Cook, licensed under the MIT license

    /// The alignment for drawing an String inside a bounding rectangle.
    enum NCStringAlignment {
    case LeftTop
  3. @natecook1000 natecook1000 revised this gist Dec 17, 2015. 1 changed file with 15 additions and 22 deletions.
    37 changes: 15 additions & 22 deletions CalculatorView.swift
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,3 @@
    // CalculatorView.swift
    // as seen in http://nshipster.com/ibinspectable-ibdesignable/
    //
    // (c) 2015 Nate Cook, licensed under the MIT license

    /// The alignment for drawing an String inside a bounding rectangle.
    enum NCStringAlignment {
    case LeftTop
    @@ -18,9 +13,9 @@ enum NCStringAlignment {

    extension String {
    /// Draw the `String` inside the bounding rectangle with a given alignment.
    func drawAtPointInRect(rect: CGRect, withAttributes attributes: [NSObject: AnyObject]?, andAlignment alignment: NCStringAlignment) {
    func drawAtPointInRect(rect: CGRect, withAttributes attributes: [String: AnyObject]?, andAlignment alignment: NCStringAlignment) {
    let size = self.sizeWithAttributes(attributes)
    var x, y: CGFloat
    let x, y: CGFloat

    switch alignment {
    case .LeftTop, .LeftCenter, .LeftBottom:
    @@ -44,14 +39,12 @@ extension String {
    }
    }

    /// Convert a rect to a pixel-aligned version, rounding position and size
    func pixelAlignedRect(var rect: CGRect) -> CGRect {
    rect.origin.x = round(rect.origin.x)
    rect.origin.y = round(rect.origin.y)
    rect.size.width = round(rect.size.width)
    rect.size.height = round(rect.size.height)

    return rect
    extension CGRect {
    /// Convert a rect to a pixel-aligned version, rounding position and size
    func pixelAligned() -> CGRect {
    return CGRect(x: round(origin.x), y: round(origin.y),
    width: round(size.width), height: round(size.height))
    }
    }

    @IBDesignable
    @@ -119,13 +112,13 @@ class CalculatorView: UIView {
    let width = size.width * unitWidth + (size.width - 1) * spacingX
    let height = size.height * unitHeight + (size.height - 1) * spacingY

    return pixelAlignedRect(CGRect(x: x, y: y, width: width, height: height))
    return CGRect(x: x, y: y, width: width, height: height).pixelAligned()
    }

    // draw a button in the specified rect
    func drawButtonInRect(rect: CGRect, withText text: String) {
    shadowColor.setFill()
    UIRectFill(rect.rectByOffsetting(dx: shadowOffset, dy: shadowOffset))
    UIRectFill(rect.offsetBy(dx: shadowOffset, dy: shadowOffset))

    buttonColor.setFill()
    edgeColor.setStroke()
    @@ -152,7 +145,7 @@ class CalculatorView: UIView {
    UIRectFill(rect)
    UIRectFrame(rect)

    text.drawAtPointInRect(rect.rectByOffsetting(dx: unitWidth / -3, dy: 0), withAttributes: textAttributes, andAlignment: .RightCenter)
    text.drawAtPointInRect(rect.offsetBy(dx: unitWidth / -3, dy: 0), withAttributes: textAttributes, andAlignment: .RightCenter)
    }


    @@ -163,12 +156,12 @@ class CalculatorView: UIView {

    // center the title in the title bar
    let title = "Calculator"
    let (titleRect, _) = bounds.rectsByDividing(titleHeight, fromEdge: CGRectEdge.MinYEdge)
    let (titleRect, _) = bounds.divide(titleHeight, fromEdge: CGRectEdge.MinYEdge)
    let titleAttributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(textSize + 2), NSForegroundColorAttributeName: titleColor]
    title.drawAtPointInRect(titleRect, withAttributes: titleAttributes, andAlignment: .Center)

    // calculator "face" - covers most of the window
    let face = UIBezierPath(roundedRect: bounds.rectByInsetting(dx: 0, dy: titleHeight / 2).rectByOffsetting(dx: 0, dy: titleHeight / 2), cornerRadius: cornerRadius)
    let face = UIBezierPath(roundedRect: bounds.insetBy(dx: 0, dy: titleHeight / 2).offsetBy(dx: 0, dy: titleHeight / 2), cornerRadius: cornerRadius)
    faceColor.setFill()
    face.fill()

    @@ -177,8 +170,8 @@ class CalculatorView: UIView {
    drawDisplayInRect(displayRect, withText: "3")

    // draw basic buttons
    for (rowNumber, row) in enumerate(buttonRows) {
    for (columnNumber, text) in enumerate(row) {
    for (rowNumber, row) in buttonRows.enumerate() {
    for (columnNumber, text) in row.enumerate() {
    drawButtonInRect(rectForPosition(CGPoint(x: columnNumber, y: rowNumber + 1), andSize: CGSize(width: 1, height: 1)), withText: text)
    }
    }
  4. @natecook1000 natecook1000 created this gist Feb 3, 2015.
    191 changes: 191 additions & 0 deletions CalculatorView.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,191 @@
    // CalculatorView.swift
    // as seen in http://nshipster.com/ibinspectable-ibdesignable/
    //
    // (c) 2015 Nate Cook, licensed under the MIT license

    /// The alignment for drawing an String inside a bounding rectangle.
    enum NCStringAlignment {
    case LeftTop
    case CenterTop
    case RightTop
    case LeftCenter
    case Center
    case RightCenter
    case LeftBottom
    case CenterBottom
    case RightBottom
    }

    extension String {
    /// Draw the `String` inside the bounding rectangle with a given alignment.
    func drawAtPointInRect(rect: CGRect, withAttributes attributes: [NSObject: AnyObject]?, andAlignment alignment: NCStringAlignment) {
    let size = self.sizeWithAttributes(attributes)
    var x, y: CGFloat

    switch alignment {
    case .LeftTop, .LeftCenter, .LeftBottom:
    x = CGRectGetMinX(rect)
    case .CenterTop, .Center, .CenterBottom:
    x = CGRectGetMidX(rect) - size.width / 2
    case .RightTop, .RightCenter, .RightBottom:
    x = CGRectGetMaxX(rect) - size.width
    }

    switch alignment {
    case .LeftTop, .CenterTop, .RightTop:
    y = CGRectGetMinY(rect)
    case .LeftCenter, .Center, .RightCenter:
    y = CGRectGetMidY(rect) - size.height / 2
    case .LeftBottom, .CenterBottom, .RightBottom:
    y = CGRectGetMaxY(rect) - size.height
    }

    self.drawAtPoint(CGPoint(x: x, y: y), withAttributes: attributes)
    }
    }

    /// Convert a rect to a pixel-aligned version, rounding position and size
    func pixelAlignedRect(var rect: CGRect) -> CGRect {
    rect.origin.x = round(rect.origin.x)
    rect.origin.y = round(rect.origin.y)
    rect.size.width = round(rect.size.width)
    rect.size.height = round(rect.size.height)

    return rect
    }

    @IBDesignable
    class CalculatorView: UIView {

    let (columns, rows) = (4, 6) as (CGFloat, CGFloat)

    // basic buttons: all 1x1 unit
    let buttonRows = [ ["C", "=", "/", "*"], ["7", "8", "9", "-"], ["4", "5", "6", "+"], ["1", "2", "3"] ]

    // special cases: non-square or out of position
    let specialButtons = [("=", CGPoint(x: 3, y: 4), CGSize(width: 1, height: 2)),
    ("0", CGPoint(x: 0, y: 5), CGSize(width: 2, height: 1)),
    (".", CGPoint(x: 2, y: 5), CGSize(width: 1, height: 1))]

    // MARK: - IBInspectable

    @IBInspectable var faceColor: UIColor = UIColor(red: 211/255, green: 211/255, blue: 211/255, alpha: 1)

    @IBInspectable var textColor: UIColor = UIColor.blackColor()
    @IBInspectable var textSize: CGFloat = 12

    @IBInspectable var buttonColor: UIColor = UIColor.whiteColor()
    @IBInspectable var edgeColor: UIColor = UIColor.blackColor()
    @IBInspectable var edgeWidth: CGFloat = 1

    @IBInspectable var shadowColor: UIColor = UIColor.blackColor()
    @IBInspectable var shadowOffset: CGFloat = 2

    @IBInspectable var cornerRadius: CGFloat = 7

    @IBInspectable var paddingX: CGFloat = 7
    @IBInspectable var paddingY: CGFloat = 8
    @IBInspectable var spacingX: CGFloat = 3
    @IBInspectable var spacingY: CGFloat = 5

    @IBInspectable var titleHeight: CGFloat = 20
    @IBInspectable var titleColor: UIColor = UIColor.whiteColor()
    @IBInspectable var titleBarColor: UIColor = UIColor.blackColor()

    // MARK: - Drawing

    override func drawRect(rect: CGRect) {

    // initial drawing setup

    // determine unit height/width from view size, padding and button spacing
    let unitHeight = (bounds.height - 2 * paddingY - (rows - 1) * spacingY - titleHeight) / rows
    let unitWidth = (bounds.width - 2 * paddingX - (columns - 1) * spacingX) / columns

    // set up text attributes
    let textFont = UIFont.systemFontOfSize(textSize)
    let textAttributes = [NSFontAttributeName: textFont, NSForegroundColorAttributeName: textColor]

    // get the graphics context
    let context = UIGraphicsGetCurrentContext()


    // helper functions

    // maps a point and size (in units) to an actual rect in the view's coordinates for drawing
    func rectForPosition(position: CGPoint, andSize size: CGSize) -> CGRect {
    let x = paddingX + unitWidth * position.x + spacingX * position.x
    let y = titleHeight + paddingY + unitHeight * position.y + spacingY * position.y
    let width = size.width * unitWidth + (size.width - 1) * spacingX
    let height = size.height * unitHeight + (size.height - 1) * spacingY

    return pixelAlignedRect(CGRect(x: x, y: y, width: width, height: height))
    }

    // draw a button in the specified rect
    func drawButtonInRect(rect: CGRect, withText text: String) {
    shadowColor.setFill()
    UIRectFill(rect.rectByOffsetting(dx: shadowOffset, dy: shadowOffset))

    buttonColor.setFill()
    edgeColor.setStroke()
    CGContextSetLineWidth(context, edgeWidth)
    UIRectFill(rect)
    UIRectFrame(rect)

    var textRect = rect
    if textRect.width != unitWidth {
    textRect.size.width = unitWidth
    }
    if textRect.height != unitHeight {
    textRect.origin.y = textRect.maxY - unitHeight
    textRect.size.height = unitHeight
    }
    text.drawAtPointInRect(textRect, withAttributes: textAttributes, andAlignment: .Center)
    }

    // draw the display
    func drawDisplayInRect(rect: CGRect, withText text: String) {
    buttonColor.setFill()
    edgeColor.setStroke()
    CGContextSetLineWidth(context, edgeWidth)
    UIRectFill(rect)
    UIRectFrame(rect)

    text.drawAtPointInRect(rect.rectByOffsetting(dx: unitWidth / -3, dy: 0), withAttributes: textAttributes, andAlignment: .RightCenter)
    }


    // calculator "window" - paint the color of the title bar
    let window = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
    titleBarColor.setFill()
    window.fill()

    // center the title in the title bar
    let title = "Calculator"
    let (titleRect, _) = bounds.rectsByDividing(titleHeight, fromEdge: CGRectEdge.MinYEdge)
    let titleAttributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(textSize + 2), NSForegroundColorAttributeName: titleColor]
    title.drawAtPointInRect(titleRect, withAttributes: titleAttributes, andAlignment: .Center)

    // calculator "face" - covers most of the window
    let face = UIBezierPath(roundedRect: bounds.rectByInsetting(dx: 0, dy: titleHeight / 2).rectByOffsetting(dx: 0, dy: titleHeight / 2), cornerRadius: cornerRadius)
    faceColor.setFill()
    face.fill()

    // draw the display
    let displayRect = rectForPosition(CGPoint(x: 0, y: 0), andSize: CGSize(width: 4, height: 1))
    drawDisplayInRect(displayRect, withText: "3")

    // draw basic buttons
    for (rowNumber, row) in enumerate(buttonRows) {
    for (columnNumber, text) in enumerate(row) {
    drawButtonInRect(rectForPosition(CGPoint(x: columnNumber, y: rowNumber + 1), andSize: CGSize(width: 1, height: 1)), withText: text)
    }
    }

    // draw special buttons
    for buttonInfo in specialButtons {
    drawButtonInRect(rectForPosition(buttonInfo.1, andSize: buttonInfo.2), withText: buttonInfo.0)
    }
    }
    }