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()
}