uchcode
9/16/2016 - 7:13 AM

Currency Converter

Currency Converter

ObjC.import('Cocoa')

////////////////////////////////////////////////////////////////////////////////
// View
////////////////////////////////////////////////////////////////////////////////

class Window {
  constructor(x, y, width, height) {
    let f = $.NSMakeRect(x, y, width, height)
    let s = $.NSTitledWindowMask | $.NSClosableWindowMask | $.NSMiniaturizableWindowMask
    let b = $.NSBackingStoreBuffered
    let d = false
    let w = $.NSWindow.alloc.initWithContentRectStyleMaskBackingDefer(f, s, b, d)
    w.releasedWhenClosed = false
    w.show = function() {
      w.makeKeyAndOrderFront(null)
    }
    w.hide = function() {
      w.orderOut(null)
    }
    return w
  }
}

class Button {
  constructor(x, y, width, height) {
    let f = $.NSMakeRect(x, y, width, height)
    let b = $.NSButton.alloc.initWithFrame(f)
    b.bezelStyle = $.NSRoundedBezelStyle
    return b
  }
}

class Label {
  constructor(x, y, width, height) {
    let f = $.NSMakeRect(x, y, width, height)
    let t = $.NSTextField.alloc.initWithFrame(f)
    t.drawsBackground = false
    t.bordered = false
    t.editable = false
    t.selectable = true
    return t
  }
}

class TextField {
  constructor(x, y, width, height) {
    let f = $.NSMakeRect(x, y, width, height)
    let t = $.NSTextField.alloc.initWithFrame(f)
    return t
  }
}

class Line {
  constructor(x, y, width, height) {
    let f = $.NSMakeRect(x, y, width, height)
    let b = $.NSBox.alloc.initWithFrame(f)
    b.boxType = $.NSBoxSeparator
    return b
  }
}

class View {
  constructor() {
    this.RateLabel = new Label(10, 110, 160, 26); {
      this.RateLabel.alignment = $.NSRightTextAlignment
      this.RateLabel.stringValue = 'Exchange Rate per $1:'
    }
    this.DollersLabel = new Label(10, 80, 160, 26); {
      this.DollersLabel.alignment = $.NSRightTextAlignment
      this.DollersLabel.stringValue = 'Dollers to Convert:'
    }
    this.TotalLabel = new Label(10, 50, 160, 26); {
      this.TotalLabel.alignment = $.NSRightTextAlignment
      this.TotalLabel.stringValue = 'Amount in Other Currency:'
    }
    this.RateField = new TextField(180, 116, 200, 22); {
    }
    this.DollersField = new TextField(180, 86, 200, 22); {
    }
    this.TotalField = new TextField(180, 56, 200, 22); {
      this.TotalField.editable = false
      this.TotalField.selectable = true
    }
    this.HorizontalLine = new Line(10, 50, 380, 1); {
    }
    this.ConvertButton = new Button(280, 10, 110, 26); {
      this.ConvertButton.title  = 'Convert'
    }
    this.MainWindow = new Window(0, 0, 400, 160); {
      this.MainWindow.center
      this.MainWindow.title = 'Currency Converter'
      //this.MainWindow.frameAutosaveName = 'main'
      this.MainWindow.contentView.addSubview(this.RateLabel)
      this.MainWindow.contentView.addSubview(this.DollersLabel)
      this.MainWindow.contentView.addSubview(this.TotalLabel)
      this.MainWindow.contentView.addSubview(this.RateField)
      this.MainWindow.contentView.addSubview(this.DollersField)
      this.MainWindow.contentView.addSubview(this.TotalField)
      this.MainWindow.contentView.addSubview(this.HorizontalLine)
      this.MainWindow.contentView.addSubview(this.ConvertButton)
      this.MainWindow.defaultButtonCell = this.ConvertButton.cell
    }
  }
  get rate() {
    return this.RateField.floatValue
  }
  set rate(value) {
    this.RateField.floatValue = value
  }
  get dollers() {
    return this.DollersField.floatValue
  }
  set dollers(value) {
    this.DollersField.floatValue = value
  }
  get total() {
    return this.TotalField.floatValue
  }
  set total(value) {
    this.TotalField.floatValue = value
  }
}

////////////////////////////////////////////////////////////////////////////////
// Model
////////////////////////////////////////////////////////////////////////////////

class Model {
  convertRateDollers(rate, dollers) {
    return rate * dollers
  }
}

////////////////////////////////////////////////////////////////////////////////
// Controller
////////////////////////////////////////////////////////////////////////////////

class SimpleSubclass {
  constructor(_name, methods) {
    if (!_name) throw new Error('SimpleSubclass: missing argument: _name')
    if ($[_name]) return $[_name].new
    let _methods = {}
    for (let m in methods) {
      _methods[m+':'] = {
        types: ['void', ['id']],
        implementation: methods[m],
      }
    }
    ObjC.registerSubclass({
      name: _name,
      methods: _methods,
    })
    return $[_name].new
  }
}

class Controller {
  constructor(view, model) {
    if (!view) throw new Error('Controller: missing argument: view')
    if (!model) throw new Error('Controller: missing argument: model')
    return new SimpleSubclass('Controller', {
      convert(sender) {
        view.total = model.convertRateDollers(view.rate, view.dollers)
      },
    })
  }
}

////////////////////////////////////////////////////////////////////////////////
// Application
////////////////////////////////////////////////////////////////////////////////

function connect(control, target, action) {
  control.target = target
  control.action = action
}

class Applet {
  constructor() {
    let view = new View()
    let model = new Model()
    let controller =  new Controller(view, model)
    //
    connect(view.RateField, controller, 'convert:')
    connect(view.DollersField, controller, 'convert:')
    connect(view.ConvertButton, controller, 'convert:')
    //
    this.view = view
    this.controller = controller
  }
}

////////////////////////////////////////////////////////////////////////////////
// Main
////////////////////////////////////////////////////////////////////////////////

function run() {
  applet = new Applet()
  applet.view.rate = 103
  applet.view.dollers = 1
  applet.controller.convert(this)
  applet.view.MainWindow.show()
}

function reopen() {
  applet.view.MainWindow.show()
}