Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JeanSebTr/4333025 to your computer and use it in GitHub Desktop.
Save JeanSebTr/4333025 to your computer and use it in GitHub Desktop.
var fs = require('fs');
var $ = require('NodObjC');
$.import('Cocoa');
var App = $.NSApplication;
var methods = App.getInstanceMethods().sort();
var head = fs.createWriteStream('./ProxyApplication.h', {
encoding: 'utf8'
});
var body = fs.createWriteStream('./ProxyApplication.m', {
encoding: 'utf8'
});
head.write('\n');
head.write('#import <Cocoa/Cocoa.h>\n');
head.write('@interface ProxyApplication : NSApplication\n');
head.write('{\nint callLevel;\n}\n');
body.write('\n');
body.write('#import "ProxyApplication.h"\n');
body.write('@implementation ProxyApplication\n');
writeMethods:
for(var i=0; i<methods.length; i++) {
var t = App._getTypesClass(methods[i], false);
if(!t) {
console.log("Can't get types informations for", methods[i]);
continue;
}
var def = '- (';
var ret = '';
var call = '';
var logText = '';
var logVars = '';
switch(t[0]) {
case '@':
ret='id';
break;
case ':':
ret='SEL';
break;
case '#':
ret='Class';
break;
case 'v':
ret='void';
break;
case 'c':
ret='char';
break;
case 'q':
ret='long long';
break;
case 's':
ret='short';
break;
case 'i':
ret='int32_t';
break;
case 'f':
ret='float';
break;
case 'Q':
ret='unsigned long long';
break;
case 'I':
ret='uint32_t';
break;
case '^v':
ret='void *';
break;
case '^q':
ret='long long *';
break;
default:
console.log('What is return type "%s" for %s', t[0], methods[i]);
continue writeMethods;
}
def+=ret+')';
var selectors = methods[i].split(':');
if(selectors.length == 1) {
def+= ' '+selectors[0];
logText=' '+selectors[0];
call= ' '+selectors[0];
}
else {
var args = t[1];
for(var j=0; j<selectors.length-1; j++) {
def+=' '+selectors[j]+':(';
logText+=' '+selectors[j];
call+=' '+selectors[j]+':arg'+(j.toString(10));
var loggedVar = false;
switch(args[j+2]) {
case '@':
def+='id';
logText+=':%@';
break;
case ':':
def+='SEL';
logText+=':%@';
logVars+=', NSStringFromSelector(arg'+(j.toString(10))+')';
loggedVar=true;
break;
case '#':
def+='Class';
logText+=':%@';
break;
case 'c':
def+='char';
logText+=':%hhd';
break;
case 'q':
def+='long long';
logText+=':%qd';
break;
case 's':
def+='short';
logText+=':%hd';
break;
case 'i':
def+='int32_t';
logText+=':%d';
break;
case 'f':
def+='float';
logText+=':%f';
logVars+=', (double)arg'+(j.toString(10));
loggedVar=true;
break;
case 'Q':
def+='unsigned long long';
logText+=':%lld';
break;
case 'I':
def+='uint32_t';
logText+=':%u';
break;
case '^v':
def+='void *';
logText+=':%p';
break;
case '^q':
def+='long long *';
logText+=':*%lld';
logVars+=', *arg'+(j.toString(10));
loggedVar=true;
break;
default:
console.log('What is argument type "%s" for %s@%d', args[j+2], methods[i], j);
continue writeMethods;
}
def+=')arg'+(j.toString(10));
if(!loggedVar) {
logVars+=', arg'+(j.toString(10));
}
}
}
head.write(def+';\n');
body.write(def+' {\n');
if(methods[i] == 'init') {
body.write('\tcallLevel = 1;\n');
}
else {
body.write('\tcallLevel++;\n');
}
if(selectors.length == 1) {
body.write('\tprintf("[%d] '+methods[i]+'\\n", callLevel);\n');
}
else {
body.write('\tprintf([[NSString stringWithFormat:@"[%d]'+logText+'\\n", callLevel'+logVars+'] UTF8String]);\n');
}
if(t[0] != 'v') {
body.write('\t'+ret+' ret = [super'+call+'];\n');
body.write('\tcallLevel--;\n');
body.write('\treturn ret;\n');
}
else {
body.write('\t[super'+call+'];\n');
body.write('\tcallLevel--;\n');
}
body.write('}\n');
}
head.write('@end\n');
head.end('\n');
body.write('@end\n');
body.end('\n');
// This example adapted from Matt Gallagher's "Minimalist Cocoa Programming"
// blog article:
var $ = require('NodObjC');
//var helpers = require('./test-helpers.js');
$.import('Cocoa');
var pool = $.NSAutoreleasePool('alloc')('init');
//var ProxyApplication = helpers.proxy($.NSApplication, 'ProxyApplication');
var app = $.NSApplication('sharedApplication');
app('setActivationPolicy', $.NSApplicationActivationPolicyRegular);
var menuBar = $.NSMenu('alloc')('init');
var appMenuItem = $.NSMenuItem('alloc')('init');
menuBar('addItem', appMenuItem);
app('setMainMenu', menuBar);
var appMenu = $.NSMenu('alloc')('init');
var appName = $('Hello NodeJS!');
var quitTitle = $('Quit "' + appName + '"');
var quitMenuItem = $.NSMenuItem('alloc')('initWithTitle', quitTitle,
'action', 'terminate:',
'keyEquivalent', $('q'));
//*
var testMenuItem = $.NSMenuItem('alloc')('initWithTitle', $('testing 1-2'),
'action', 'dotest:', 'keyEquivalent', $('t'));//*/
appMenu('addItem', testMenuItem);
appMenu('addItem', quitMenuItem);
appMenuItem('setSubmenu', appMenu);
var styleMask = $.NSTitledWindowMask
| $.NSResizableWindowMask
| $.NSClosableWindowMask;
var window = $.NSWindow('alloc')('initWithContentRect', $.NSMakeRect(0,0,200,200),
'styleMask', styleMask,
'backing', $.NSBackingStoreBuffered,
'defer', false);
window('cascadeTopLeftFromPoint', $.NSMakePoint(20,20));
window('setTitle', appName);
window('makeKeyAndOrderFront', window);
window('center');
var keepRunning = true;
var fnDelegate = module.exports = function fnDelegate(self, _cmd, notif) {
console.log('got', _cmd, fnDelegate);
console.log(self, _cmd, notif);
if(_cmd == 'applicationShouldTerminate:') {
keepRunning = false;
return 0;
}
/*else if(_cmd == 'dotest:'){
}*/
};
// set up the app delegate
var AppDelegate = $.NSObject.extend('AppDelegate');
AppDelegate.addMethod('dotest:', 'v@:@', fnDelegate);
AppDelegate.addMethod('applicationWillFinishLaunching:', 'v@:@', fnDelegate);
AppDelegate.addMethod('applicationDidFinishLaunching:', 'v@:@', fnDelegate);
//AppDelegate.addMethod('applicationShouldTerminate:', 'B@:@', fnDelegate);
AppDelegate.addMethod('applicationWillTerminate:', 'v@:@', fnDelegate);
AppDelegate.register();
var delegate = AppDelegate('alloc')('init');
app('setDelegate', delegate);
app('activateIgnoringOtherApps', 1);
//app('run');
//*
var notifCenter = $.NSNotificationCenter('defaultCenter');
console.log('_isCurrentlyLightLaunched ?', app('_isCurrentlyLightLaunched'));
app('finishLaunching');
var termSupp = app('_checkForAutomaticTerminationSupportPossiblyEnablingIt');
app('setWindowsNeedUpdate', 1);
var dic = $.NSDictionary('dictionaryWithObject', $(1), 'forKey', $('NSApplicationLaunchIsDefaultLaunchKey'));
notifCenter('postNotificationName', $.NSApplicationDidFinishLaunchingNotification,
'object', app, 'userInfo', dic);
function tick () {
var ev;
do {
app('_enableSuddenTermination');
ev = app('nextEventMatchingMask', 4294967295,
//$.NSAnyEventMask is loosing precision somewhere
'untilDate', $.NSDate('dateWithTimeIntervalSinceNow', $(0.01)), // don't wait if there is no event
'inMode', $.NSDefaultRunLoopMode,
'dequeue', 1);
app('_disableSuddenTermination');
if(ev) {
console.log(ev);
app('sendEvent', ev);
}
} while(ev);
//app('updateWindows');
if(keepRunning) {
process.nextTick(tick);
}
}
tick();
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200);
res.end('YEAH!');
}).listen(3000);
//*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment