[Pythonmac-SIG] Python RAD tools
Donovan Preston
dp@ulaluma.com
Mon, 14 Jan 2002 11:36:42 -0800
--Apple-Mail-2-517548007
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
On Sunday, January 13, 2002, at 05:27 AM, Adam Eijdenberg wrote:
> Hello all,
>
> I'm toying around with the idea of developing a Python rapid
> application development tool, initially just for the Mac. This tool is
> written in C for Carbon, so it is native in all regards and uses the
> Unix mach-o version of Python.
>
Sounds cool. Myself, I'm just using Interface Builder -- It already has
a RAD tool for designing interfaces, and likewise saves them in an XML
format. Apple has provided as a part of Carbon, IBCarbonRuntime, which
allows dearchiving of Carbon Interface Builder nibs on both OS X and OS
9.
I just wrapped the IBCarbonRuntime.h header provided by Apple and it has
been very easy for me to load nibs and attach event handlers to them
using Carbon Events.
Here's an example of how little code it takes to use the module:
--------------------
from Carbon import IBCarbon
from Carbon import CarbonEvt # The CarbonEvents functions
from Carbon import CarbonEvents # The CarbonEvents constants
windowlist = []
def commandCallback(handler, event):
# Get the event record describing what command was executed
result =
event.GetEventParameter(CarbonEvents.kEventParamDirectObject,
CarbonEvents.typeHICommand)
event = result[4:8]
if event == 'new ':
# If the user selected new window, load a nib and unarchive a window
global windowlist
# Create a reference to the nib named 'main' in my Application Bundle
nib = IBCarbon.CreateNibReference('main')
# Unarchive a window from the nib
window = nib.CreateWindowFromNib('MyWindowNameInTheMainNib')
# Keep the window from disappearing after the function falls
out of scope
windowlist.append(window)
window.ShowWindow()
# Get the application event target
AppTarget = CarbonEvt.GetApplicationEventTarget()
# Install a handler for "command" events on the application
# Command events can be set using the inspector panel in Interface
Builder
# Many basic commands, such as new, quit, copy, paste, are already set
(and many are handled automatically)
cmdsHandler = target.InstallEventHandler(('cmds', 1), commandCallback)
----------------------
It's great because the window objects that CreateWindowFromNib are
standard wrapped WindowRef objects in Python, and you have full access
to the PythonMac toolbox wrappers. Of course, you're programming more at
a C level but with a little effort, a nicer Python framework API could
be constructed that used these commands (similar to W. I'm writing my
own very simple one, dspFramework, for my own purposes.) The nice thing
about using the PythonMac toolbox wrappers is that there is lots of
documentation -- any of the C Carbon or C Toolbox documentation can be
used as a reference, with minor changes for use with python.
I'm attaching the IBCarbonRuntime.c file as well as the bgen files I
used to generate it, in case anyone wants to play with it. Jack, maybe
you'd consider putting it in the distribution this time?
Donovan
--Apple-Mail-2-517548007
Content-Disposition: attachment;
filename=_IBCarbon.c
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
x-mac-creator=43574945;
x-unix-mode=0644;
x-mac-type=54455854;
name="_IBCarbon.c"
/* ======================== Module _IBCarbon ======================== */
#include "Python.h"
#ifdef WITHOUT_FRAMEWORKS
#include <IBCarbonRuntime.h>
#else
#include <Carbon/Carbon.h>
#endif /* WITHOUT_FRAMEWORKS */
#include "macglue.h"
#ifdef USE_TOOLBOX_OBJECT_GLUE
extern int _CFStringRefObj_Convert(PyObject *, CFStringRef *);
//#define CFStringRefObj_Convert _CFStringRefObj_Convert
#endif
//extern int CFBundleRefObj_Convert(PyObject *, CFBundleRef *); // need to wrap CFBundle
static PyObject *IBCarbon_Error;
/* ---------------------- Object type IBNibRef ---------------------- */
PyTypeObject IBNibRef_Type;
#define IBNibRefObj_Check(x) ((x)->ob_type == &IBNibRef_Type)
typedef struct IBNibRefObject {
PyObject_HEAD
IBNibRef ob_itself;
} IBNibRefObject;
PyObject *IBNibRefObj_New(IBNibRef itself)
{
IBNibRefObject *it;
it = PyObject_NEW(IBNibRefObject, &IBNibRef_Type);
if (it == NULL) return NULL;
it->ob_itself = itself;
return (PyObject *)it;
}
int IBNibRefObj_Convert(PyObject *v, IBNibRef *p_itself)
{
if (!IBNibRefObj_Check(v))
{
PyErr_SetString(PyExc_TypeError, "IBNibRef required");
return 0;
}
*p_itself = ((IBNibRefObject *)v)->ob_itself;
return 1;
}
static void IBNibRefObj_dealloc(IBNibRefObject *self)
{
DisposeNibReference(self->ob_itself);
PyMem_DEL(self);
}
static PyObject *IBNibRefObj_CreateWindowFromNib(IBNibRefObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
CFStringRef inName;
WindowPtr outWindow;
if (!PyArg_ParseTuple(_args, "O&",
CFStringRefObj_Convert, &inName))
return NULL;
Py_BEGIN_ALLOW_THREADS
_err = CreateWindowFromNib(_self->ob_itself,
inName,
&outWindow);
Py_END_ALLOW_THREADS
if (_err != noErr) return PyMac_Error(_err);
_res = Py_BuildValue("O&",
WinObj_New, outWindow);
return _res;
}
static PyObject *IBNibRefObj_CreateMenuFromNib(IBNibRefObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
CFStringRef inName;
MenuHandle outMenuRef;
if (!PyArg_ParseTuple(_args, "O&",
CFStringRefObj_Convert, &inName))
return NULL;
Py_BEGIN_ALLOW_THREADS
_err = CreateMenuFromNib(_self->ob_itself,
inName,
&outMenuRef);
Py_END_ALLOW_THREADS
if (_err != noErr) return PyMac_Error(_err);
_res = Py_BuildValue("O&",
MenuObj_New, outMenuRef);
return _res;
}
static PyObject *IBNibRefObj_CreateMenuBarFromNib(IBNibRefObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
CFStringRef inName;
Handle outMenuBar;
if (!PyArg_ParseTuple(_args, "O&",
CFStringRefObj_Convert, &inName))
return NULL;
Py_BEGIN_ALLOW_THREADS
_err = CreateMenuBarFromNib(_self->ob_itself,
inName,
&outMenuBar);
Py_END_ALLOW_THREADS
if (_err != noErr) return PyMac_Error(_err);
_res = Py_BuildValue("O&",
ResObj_New, outMenuBar);
return _res;
}
static PyObject *IBNibRefObj_SetMenuBarFromNib(IBNibRefObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
CFStringRef inName;
if (!PyArg_ParseTuple(_args, "O&",
CFStringRefObj_Convert, &inName))
return NULL;
Py_BEGIN_ALLOW_THREADS
_err = SetMenuBarFromNib(_self->ob_itself,
inName);
Py_END_ALLOW_THREADS
if (_err != noErr) return PyMac_Error(_err);
Py_INCREF(Py_None);
_res = Py_None;
return _res;
}
static PyMethodDef IBNibRefObj_methods[] = {
{"CreateWindowFromNib", (PyCFunction)IBNibRefObj_CreateWindowFromNib, 1,
"(CFStringRef inName) -> (WindowPtr outWindow)"},
{"CreateMenuFromNib", (PyCFunction)IBNibRefObj_CreateMenuFromNib, 1,
"(CFStringRef inName) -> (MenuHandle outMenuRef)"},
{"CreateMenuBarFromNib", (PyCFunction)IBNibRefObj_CreateMenuBarFromNib, 1,
"(CFStringRef inName) -> (Handle outMenuBar)"},
{"SetMenuBarFromNib", (PyCFunction)IBNibRefObj_SetMenuBarFromNib, 1,
"(CFStringRef inName) -> None"},
{NULL, NULL, 0}
};
PyMethodChain IBNibRefObj_chain = { IBNibRefObj_methods, NULL };
static PyObject *IBNibRefObj_getattr(IBNibRefObject *self, char *name)
{
return Py_FindMethodInChain(&IBNibRefObj_chain, (PyObject *)self, name);
}
#define IBNibRefObj_setattr NULL
#define IBNibRefObj_compare NULL
#define IBNibRefObj_repr NULL
#define IBNibRefObj_hash NULL
PyTypeObject IBNibRef_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"_IBCarbon.IBNibRef", /*tp_name*/
sizeof(IBNibRefObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor) IBNibRefObj_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc) IBNibRefObj_getattr, /*tp_getattr*/
(setattrfunc) IBNibRefObj_setattr, /*tp_setattr*/
(cmpfunc) IBNibRefObj_compare, /*tp_compare*/
(reprfunc) IBNibRefObj_repr, /*tp_repr*/
(PyNumberMethods *)0, /* tp_as_number */
(PySequenceMethods *)0, /* tp_as_sequence */
(PyMappingMethods *)0, /* tp_as_mapping */
(hashfunc) IBNibRefObj_hash, /*tp_hash*/
};
/* -------------------- End object type IBNibRef -------------------- */
static PyObject *IBCarbon_CreateNibReference(PyObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
CFStringRef inNibName;
IBNibRef outNibRef;
if (!PyArg_ParseTuple(_args, "O&",
CFStringRefObj_Convert, &inNibName))
return NULL;
Py_BEGIN_ALLOW_THREADS
_err = CreateNibReference(inNibName,
&outNibRef);
Py_END_ALLOW_THREADS
if (_err != noErr) return PyMac_Error(_err);
_res = Py_BuildValue("O&",
IBNibRefObj_New, outNibRef);
return _res;
}
static PyMethodDef IBCarbon_methods[] = {
{"CreateNibReference", (PyCFunction)IBCarbon_CreateNibReference, 1,
"(CFStringRef inNibName) -> (IBNibRef outNibRef)"},
{NULL, NULL, 0}
};
void init_IBCarbon(void)
{
PyObject *m;
PyObject *d;
m = Py_InitModule("_IBCarbon", IBCarbon_methods);
d = PyModule_GetDict(m);
IBCarbon_Error = PyMac_GetOSErrException();
if (IBCarbon_Error == NULL ||
PyDict_SetItemString(d, "Error", IBCarbon_Error) != 0)
return;
IBNibRef_Type.ob_type = &PyType_Type;
Py_INCREF(&IBNibRef_Type);
if (PyDict_SetItemString(d, "IBNibRefType", (PyObject *)&IBNibRef_Type) != 0)
Py_FatalError("can't initialize IBNibRefType");
}
/* ====================== End module _IBCarbon ====================== */
--Apple-Mail-2-517548007
Content-Disposition: attachment
Content-Type: multipart/appledouble;
boundary=Apple-Mail-3-517548009
--Apple-Mail-3-517548009
Content-Disposition: attachment;
filename=IBCarbonscan.py
Content-Transfer-Encoding: base64
Content-Type: application/applefile;
name="IBCarbonscan.py"
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAAAoAAAADAAAASAAAAA8AAAACAAAA
VwAAAX5URVhUUipjaAEASUJDYXJib25zY2FuLnB5AAABAAAAAUwAAABMAAAAMgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAEgACU1vbmFjbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABABPAAMCvwJ9AE8AAwK/
An24aG9uAAABggAAAYIAAAAAAQAAAAEAAAABTAAAAEwAAAAyACbAkAH7AAAAHAAyAABNUFNSAAAA
CgPt//8AAAAAAh9UwA==
--Apple-Mail-3-517548009
Content-Disposition: attachment;
filename=IBCarbonscan.py
Content-Transfer-Encoding: 7bit
Content-Type: application/text;
x-mac-creator=522A6368;
x-unix-mode=0644;
x-mac-type=54455854;
name="IBCarbonscan.py"
# IBCarbonscan.py
import sys
import os
import string
import MacOS
BGENDIR= '/Users/dp/python/dist/src/Tools/bgen/bgen'
sys.path.append(BGENDIR)
print sys.path, sys.prefix
from bgenlocations import TOOLBOXDIR
from scantools import Scanner_OSX
def main():
print "---Scanning IBCarbonRuntime.h---"
input = ["IBCarbonRuntime.h"]
output = "IBCarbongen.py"
defsoutput = TOOLBOXDIR + "IBCarbonRuntime.py"
scanner = IBCarbon_Scanner(input, output, defsoutput)
scanner.scan()
scanner.close()
print "--done scanning, importing--"
import IBCarbonsupport
print "done"
class IBCarbon_Scanner(Scanner_OSX):
def destination(self, type, name, arglist):
classname = "IBCarbonFunction"
listname = "functions"
if arglist:
t, n, m = arglist[0]
if t == "IBNibRef" and m == "InMode":
classname = "IBCarbonMethod"
listname = "methods"
return classname, listname
def makeblacklistnames(self):
return [
"DisposeNibReference", # taken care of by destructor
"CreateNibReferenceWithCFBundle", ## need to wrap CFBundle.h properly first
]
if __name__ == "__main__":
main()
--Apple-Mail-3-517548009--
--Apple-Mail-2-517548007
Content-Disposition: attachment
Content-Type: multipart/appledouble;
boundary=Apple-Mail-4-517548011
--Apple-Mail-4-517548011
Content-Disposition: attachment;
filename=IBCarbonsupport.py
Content-Transfer-Encoding: base64
Content-Type: application/applefile;
name="IBCarbonsupport.py"
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAAAoAAAADAAAASAAAABIAAAACAAAA
WgAAAX5URVhUUipjaAEASUJDYXJib25zdXBwb3J0LnB5AAABAAAAAUwAAABMAAAAMgAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEgACU1vbmFjbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABABTAJgCvQMSAFMA
mAK9AxK4aHCPAAABdAAAAXQAAAAAAQAAAAEAAAABTAAAAEwAAAAyACbAkALQAAAAHAAyAABNUFNS
AAAACgPt//8AAAAAAh9GpA==
--Apple-Mail-4-517548011
Content-Disposition: attachment;
filename=IBCarbonsupport.py
Content-Transfer-Encoding: 7bit
Content-Type: application/text;
x-mac-creator=522A6368;
x-unix-mode=0644;
x-mac-type=54455854;
name="IBCarbonsupport.py"
# IBCarbonsupport.py
from macsupport import *
CFStringRef = OpaqueByValueType('CFStringRef', 'CFStringRefObj')
IBNibRef = OpaqueByValueType('IBNibRef', 'IBNibRefObj')
#CFBundleRef = OpaqueByValueType('CFBundleRef')
IBCarbonFunction = OSErrFunctionGenerator
IBCarbonMethod = OSErrMethodGenerator
includestuff = """
#ifdef WITHOUT_FRAMEWORKS
#include <IBCarbonRuntime.h>
#else
#include <Carbon/Carbon.h>
#endif /* WITHOUT_FRAMEWORKS */
#include "macglue.h"
#ifdef USE_TOOLBOX_OBJECT_GLUE
extern int _CFStringRefObj_Convert(PyObject *, CFStringRef *);
//#define CFStringRefObj_Convert _CFStringRefObj_Convert
#endif
//extern int CFBundleRefObj_Convert(PyObject *, CFBundleRef *); // need to wrap CFBundle
"""
initstuff = """
"""
module = MacModule('_IBCarbon', 'IBCarbon', includestuff, finalstuff, initstuff)
class CFReleaserObject(GlobalObjectDefinition):
def outputFreeIt(self, name):
Output("CFRelease(%s);" % name)
class CFNibDesc(GlobalObjectDefinition):
def outputFreeIt(self, name):
Output("DisposeNibReference(%s);" % name)
#cfstringobject = CFReleaserObject("CFStringRef")
#module.addobject(cfstringobject)
#cfbundleobject = CFReleaserObject("CFBundleRef")
#module.addobject(cfbundleobject)
ibnibobject = CFNibDesc("IBNibRef", "IBNibRefObj")
module.addobject(ibnibobject)
functions = []
methods = []
execfile('IBCarbongen.py')
for f in functions: module.add(f)
for m in methods: ibnibobject.add(m)
SetOutputFileName('_IBCarbon.c')
module.generate()
--Apple-Mail-4-517548011--
--Apple-Mail-2-517548007--