Commit abc411ba authored by Jack Jansen's avatar Jack Jansen

Started on support for callbacks for UserPane controls. Unfinished and untested.

parent fb4ece7f
...@@ -84,6 +84,8 @@ ControlFontStyle_Convert(v, itself) ...@@ -84,6 +84,8 @@ ControlFontStyle_Convert(v, itself)
/* TrackControl and HandleControlClick callback support */ /* TrackControl and HandleControlClick callback support */
static PyObject *tracker; static PyObject *tracker;
static ControlActionUPP mytracker_upp; static ControlActionUPP mytracker_upp;
static ControlUserPaneDrawUPP mydrawproc_upp;
static ControlUserPaneIdleUPP myidleproc_upp;
extern int settrackfunc(PyObject *); /* forward */ extern int settrackfunc(PyObject *); /* forward */
extern void clrtrackfunc(void); /* forward */ extern void clrtrackfunc(void); /* forward */
...@@ -99,6 +101,7 @@ PyTypeObject Control_Type; ...@@ -99,6 +101,7 @@ PyTypeObject Control_Type;
typedef struct ControlObject { typedef struct ControlObject {
PyObject_HEAD PyObject_HEAD
ControlHandle ob_itself; ControlHandle ob_itself;
PyObject *ob_callbackdict;
} ControlObject; } ControlObject;
PyObject *CtlObj_New(itself) PyObject *CtlObj_New(itself)
...@@ -110,6 +113,7 @@ PyObject *CtlObj_New(itself) ...@@ -110,6 +113,7 @@ PyObject *CtlObj_New(itself)
if (it == NULL) return NULL; if (it == NULL) return NULL;
it->ob_itself = itself; it->ob_itself = itself;
SetControlReference(itself, (long)it); SetControlReference(itself, (long)it);
it->ob_callbackdict = NULL;
return (PyObject *)it; return (PyObject *)it;
} }
CtlObj_Convert(v, p_itself) CtlObj_Convert(v, p_itself)
...@@ -128,6 +132,7 @@ CtlObj_Convert(v, p_itself) ...@@ -128,6 +132,7 @@ CtlObj_Convert(v, p_itself)
static void CtlObj_dealloc(self) static void CtlObj_dealloc(self)
ControlObject *self; ControlObject *self;
{ {
Py_XDECREF(self->ob_callbackdict);
if (self->ob_itself)SetControlReference(self->ob_itself, (long)0); /* Make it forget about us */ if (self->ob_itself)SetControlReference(self->ob_itself, (long)0); /* Make it forget about us */
PyMem_DEL(self); PyMem_DEL(self);
} }
...@@ -722,19 +727,18 @@ static PyObject *CtlObj_RemoveControlProperty(_self, _args) ...@@ -722,19 +727,18 @@ static PyObject *CtlObj_RemoveControlProperty(_self, _args)
PyObject *_args; PyObject *_args;
{ {
PyObject *_res = NULL; PyObject *_res = NULL;
OSStatus _err; OSStatus _rv;
OSType propertyCreator; OSType propertyCreator;
OSType propertyTag; OSType propertyTag;
if (!PyArg_ParseTuple(_args, "O&O&", if (!PyArg_ParseTuple(_args, "O&O&",
PyMac_GetOSType, &propertyCreator, PyMac_GetOSType, &propertyCreator,
PyMac_GetOSType, &propertyTag)) PyMac_GetOSType, &propertyTag))
return NULL; return NULL;
_err = RemoveControlProperty(_self->ob_itself, _rv = RemoveControlProperty(_self->ob_itself,
propertyCreator, propertyCreator,
propertyTag); propertyTag);
if (_err != noErr) return PyMac_Error(_err); _res = Py_BuildValue("l",
Py_INCREF(Py_None); _rv);
_res = Py_None;
return _res; return _res;
} }
...@@ -743,19 +747,18 @@ static PyObject *CtlObj_GetControlRegion(_self, _args) ...@@ -743,19 +747,18 @@ static PyObject *CtlObj_GetControlRegion(_self, _args)
PyObject *_args; PyObject *_args;
{ {
PyObject *_res = NULL; PyObject *_res = NULL;
OSStatus _err; OSStatus _rv;
ControlPartCode inPart; ControlPartCode inPart;
RgnHandle outRegion; RgnHandle outRegion;
if (!PyArg_ParseTuple(_args, "hO&", if (!PyArg_ParseTuple(_args, "hO&",
&inPart, &inPart,
ResObj_Convert, &outRegion)) ResObj_Convert, &outRegion))
return NULL; return NULL;
_err = GetControlRegion(_self->ob_itself, _rv = GetControlRegion(_self->ob_itself,
inPart, inPart,
outRegion); outRegion);
if (_err != noErr) return PyMac_Error(_err); _res = Py_BuildValue("l",
Py_INCREF(Py_None); _rv);
_res = Py_None;
return _res; return _res;
} }
...@@ -1255,6 +1258,39 @@ static PyObject *CtlObj_GetControlDataHandle(_self, _args) ...@@ -1255,6 +1258,39 @@ static PyObject *CtlObj_GetControlDataHandle(_self, _args)
} }
static PyObject *CtlObj_SetControlDataCallback(_self, _args)
ControlObject *_self;
PyObject *_args;
{
PyObject *_res = NULL;
OSErr _err;
ControlPartCode inPart;
ResType inTagName;
PyObject *callback;
UniversalProcPtr *c_callback;
if (!PyArg_ParseTuple(_args, "hO&O",
&inPart,
PyMac_GetOSType, &inTagName,
&callback))
return NULL;
if ( setcallback(_self, inTagName, callback, &c_callback) < 0 )
return NULL;
_err = SetControlData(_self->ob_itself,
inPart,
inTagName,
sizeof(c_callback),
(Ptr)&c_callback);
if (_err != noErr)
return PyMac_Error(_err);
_res = Py_None;
return _res;
}
static PyObject *CtlObj_GetPopupData(_self, _args) static PyObject *CtlObj_GetPopupData(_self, _args)
ControlObject *_self; ControlObject *_self;
PyObject *_args; PyObject *_args;
...@@ -1373,9 +1409,9 @@ static PyMethodDef CtlObj_methods[] = { ...@@ -1373,9 +1409,9 @@ static PyMethodDef CtlObj_methods[] = {
{"IsValidControlHandle", (PyCFunction)CtlObj_IsValidControlHandle, 1, {"IsValidControlHandle", (PyCFunction)CtlObj_IsValidControlHandle, 1,
"() -> (Boolean _rv)"}, "() -> (Boolean _rv)"},
{"RemoveControlProperty", (PyCFunction)CtlObj_RemoveControlProperty, 1, {"RemoveControlProperty", (PyCFunction)CtlObj_RemoveControlProperty, 1,
"(OSType propertyCreator, OSType propertyTag) -> None"}, "(OSType propertyCreator, OSType propertyTag) -> (OSStatus _rv)"},
{"GetControlRegion", (PyCFunction)CtlObj_GetControlRegion, 1, {"GetControlRegion", (PyCFunction)CtlObj_GetControlRegion, 1,
"(ControlPartCode inPart, RgnHandle outRegion) -> None"}, "(ControlPartCode inPart, RgnHandle outRegion) -> (OSStatus _rv)"},
{"GetControlVariant", (PyCFunction)CtlObj_GetControlVariant, 1, {"GetControlVariant", (PyCFunction)CtlObj_GetControlVariant, 1,
"() -> (ControlVariant _rv)"}, "() -> (ControlVariant _rv)"},
{"SetControlReference", (PyCFunction)CtlObj_SetControlReference, 1, {"SetControlReference", (PyCFunction)CtlObj_SetControlReference, 1,
...@@ -1420,6 +1456,8 @@ static PyMethodDef CtlObj_methods[] = { ...@@ -1420,6 +1456,8 @@ static PyMethodDef CtlObj_methods[] = {
"(ResObj) -> None"}, "(ResObj) -> None"},
{"GetControlDataHandle", (PyCFunction)CtlObj_GetControlDataHandle, 1, {"GetControlDataHandle", (PyCFunction)CtlObj_GetControlDataHandle, 1,
"(part, type) -> ResObj"}, "(part, type) -> ResObj"},
{"SetControlDataCallback", (PyCFunction)CtlObj_SetControlDataCallback, 1,
"(callbackfunc) -> None"},
{"GetPopupData", (PyCFunction)CtlObj_GetPopupData, 1, {"GetPopupData", (PyCFunction)CtlObj_GetPopupData, 1,
NULL}, NULL},
{"SetPopupData", (PyCFunction)CtlObj_SetPopupData, 1, {"SetPopupData", (PyCFunction)CtlObj_SetPopupData, 1,
...@@ -1912,6 +1950,83 @@ mytracker(ctl, part) ...@@ -1912,6 +1950,83 @@ mytracker(ctl, part)
PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\n"); PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\n");
} }
static int
setcallback(self, which, callback, uppp)
ControlObject *self;
OSType which;
PyObject *callback;
UniversalProcPtr *uppp;
{
char keybuf[9];
if ( which == kControlUserPaneDrawProcTag )
*uppp = mydrawproc_upp;
else if ( which == kControlUserPaneIdleProcTag )
*uppp = myidleproc_upp;
else
return -1;
/* Only now do we test for clearing of the callback: */
if ( callback == Py_None )
*uppp = NULL;
/* Create the dict if it doesn't exist yet (so we don't get such a dict for every control) */
if ( self->ob_callbackdict == NULL )
if ( (self->ob_callbackdict = PyDict_New()) == NULL )
return -1;
/* And store the Python callback */
sprintf(keybuf, "%x", which);
if (PyDict_SetItemString(self->ob_callbackdict, keybuf, callback) < 0)
return -1;
return 0;
}
static PyObject *
callcallback(self, which, arglist)
ControlObject *self;
OSType which;
PyObject *arglist;
{
char keybuf[9];
PyObject *func, *rv;
sprintf(keybuf, "%x", which);
if ( self->ob_callbackdict == NULL ||
(func = PyDict_GetItemString(self->ob_callbackdict, keybuf)) == NULL ) {
PySys_WriteStderr("Control callback without callback object\n");
return NULL;
}
rv = PyEval_CallObject(func, arglist);
if ( rv == NULL )
PySys_WriteStderr("Exception in control callback handler\n");
return rv;
}
static pascal void
mydrawproc(ControlHandle control, SInt16 part)
{
ControlObject *ctl_obj;
PyObject *arglist, *rv;
ctl_obj = (ControlObject *)CtlObj_WhichControl(control);
arglist = Py_BuildValue("Oh", ctl_obj, part);
rv = callcallback(ctl_obj, kControlUserPaneDrawProcTag, arglist);
Py_XDECREF(arglist);
Py_XDECREF(rv);
}
static pascal void
myidleproc(ControlHandle control)
{
ControlObject *ctl_obj;
PyObject *arglist, *rv;
ctl_obj = (ControlObject *)CtlObj_WhichControl(control);
arglist = Py_BuildValue("O", ctl_obj);
rv = callcallback(ctl_obj, kControlUserPaneIdleProcTag, arglist);
Py_XDECREF(arglist);
Py_XDECREF(rv);
}
void initCtl() void initCtl()
{ {
...@@ -1921,6 +2036,8 @@ void initCtl() ...@@ -1921,6 +2036,8 @@ void initCtl()
mytracker_upp = NewControlActionProc(mytracker); mytracker_upp = NewControlActionProc(mytracker);
mydrawproc_upp = NewControlUserPaneDrawProc(mydrawproc);
myidleproc_upp = NewControlUserPaneDrawProc(myidleproc);
m = Py_InitModule("Ctl", Ctl_methods); m = Py_InitModule("Ctl", Ctl_methods);
......
...@@ -84,6 +84,8 @@ ControlFontStyle_Convert(v, itself) ...@@ -84,6 +84,8 @@ ControlFontStyle_Convert(v, itself)
/* TrackControl and HandleControlClick callback support */ /* TrackControl and HandleControlClick callback support */
static PyObject *tracker; static PyObject *tracker;
static ControlActionUPP mytracker_upp; static ControlActionUPP mytracker_upp;
static ControlUserPaneDrawUPP mydrawproc_upp;
static ControlUserPaneIdleUPP myidleproc_upp;
extern int settrackfunc(PyObject *); /* forward */ extern int settrackfunc(PyObject *); /* forward */
extern void clrtrackfunc(void); /* forward */ extern void clrtrackfunc(void); /* forward */
...@@ -157,19 +159,103 @@ mytracker(ctl, part) ...@@ -157,19 +159,103 @@ mytracker(ctl, part)
else else
PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\\n"); PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\\n");
} }
static int
setcallback(self, which, callback, uppp)
ControlObject *self;
OSType which;
PyObject *callback;
UniversalProcPtr *uppp;
{
char keybuf[9];
if ( which == kControlUserPaneDrawProcTag )
*uppp = mydrawproc_upp;
else if ( which == kControlUserPaneIdleProcTag )
*uppp = myidleproc_upp;
else
return -1;
/* Only now do we test for clearing of the callback: */
if ( callback == Py_None )
*uppp = NULL;
/* Create the dict if it doesn't exist yet (so we don't get such a dict for every control) */
if ( self->ob_callbackdict == NULL )
if ( (self->ob_callbackdict = PyDict_New()) == NULL )
return -1;
/* And store the Python callback */
sprintf(keybuf, "%x", which);
if (PyDict_SetItemString(self->ob_callbackdict, keybuf, callback) < 0)
return -1;
return 0;
}
static PyObject *
callcallback(self, which, arglist)
ControlObject *self;
OSType which;
PyObject *arglist;
{
char keybuf[9];
PyObject *func, *rv;
sprintf(keybuf, "%x", which);
if ( self->ob_callbackdict == NULL ||
(func = PyDict_GetItemString(self->ob_callbackdict, keybuf)) == NULL ) {
PySys_WriteStderr("Control callback without callback object\\n");
return NULL;
}
rv = PyEval_CallObject(func, arglist);
if ( rv == NULL )
PySys_WriteStderr("Exception in control callback handler\\n");
return rv;
}
static pascal void
mydrawproc(ControlHandle control, SInt16 part)
{
ControlObject *ctl_obj;
PyObject *arglist, *rv;
ctl_obj = (ControlObject *)CtlObj_WhichControl(control);
arglist = Py_BuildValue("Oh", ctl_obj, part);
rv = callcallback(ctl_obj, kControlUserPaneDrawProcTag, arglist);
Py_XDECREF(arglist);
Py_XDECREF(rv);
}
static pascal void
myidleproc(ControlHandle control)
{
ControlObject *ctl_obj;
PyObject *arglist, *rv;
ctl_obj = (ControlObject *)CtlObj_WhichControl(control);
arglist = Py_BuildValue("O", ctl_obj);
rv = callcallback(ctl_obj, kControlUserPaneIdleProcTag, arglist);
Py_XDECREF(arglist);
Py_XDECREF(rv);
}
""" """
initstuff = initstuff + """ initstuff = initstuff + """
mytracker_upp = NewControlActionProc(mytracker); mytracker_upp = NewControlActionProc(mytracker);
mydrawproc_upp = NewControlUserPaneDrawProc(mydrawproc);
myidleproc_upp = NewControlUserPaneDrawProc(myidleproc);
""" """
class MyObjectDefinition(ObjectIdentityMixin, GlobalObjectDefinition): class MyObjectDefinition(ObjectIdentityMixin, GlobalObjectDefinition):
def outputStructMembers(self):
GlobalObjectDefinition.outputStructMembers(self)
Output("PyObject *ob_callbackdict;")
def outputCheckNewArg(self): def outputCheckNewArg(self):
Output("if (itself == NULL) return PyMac_Error(resNotFound);") Output("if (itself == NULL) return PyMac_Error(resNotFound);")
def outputInitStructMembers(self): def outputInitStructMembers(self):
GlobalObjectDefinition.outputInitStructMembers(self) GlobalObjectDefinition.outputInitStructMembers(self)
Output("SetControlReference(itself, (long)it);") Output("SetControlReference(itself, (long)it);")
Output("it->ob_callbackdict = NULL;")
def outputCleanupStructMembers(self): def outputCleanupStructMembers(self):
Output("Py_XDECREF(self->ob_callbackdict);")
Output("if (self->ob_itself)SetControlReference(self->ob_itself, (long)0); /* Make it forget about us */") Output("if (self->ob_itself)SetControlReference(self->ob_itself, (long)0); /* Make it forget about us */")
# Create the generator groups and link them # Create the generator groups and link them
...@@ -404,6 +490,38 @@ f = ManualGenerator("GetControlDataHandle", getcontroldatahandle_body); ...@@ -404,6 +490,38 @@ f = ManualGenerator("GetControlDataHandle", getcontroldatahandle_body);
f.docstring = lambda: "(part, type) -> ResObj" f.docstring = lambda: "(part, type) -> ResObj"
object.add(f) object.add(f)
# Manual Generator for SetControlDataCallback
setcontroldatacallback_body = """
OSErr _err;
ControlPartCode inPart;
ResType inTagName;
PyObject *callback;
UniversalProcPtr *c_callback;
if (!PyArg_ParseTuple(_args, "hO&O",
&inPart,
PyMac_GetOSType, &inTagName,
&callback))
return NULL;
if ( setcallback(_self, inTagName, callback, &c_callback) < 0 )
return NULL;
_err = SetControlData(_self->ob_itself,
inPart,
inTagName,
sizeof(c_callback),
(Ptr)&c_callback);
if (_err != noErr)
return PyMac_Error(_err);
_res = Py_None;
return _res;
"""
f = ManualGenerator("SetControlDataCallback", setcontroldatacallback_body);
f.docstring = lambda: "(callbackfunc) -> None"
object.add(f)
# And manual generators to get/set popup menu information # And manual generators to get/set popup menu information
getpopupdata_body = """ getpopupdata_body = """
PopupPrivateDataHandle hdl; PopupPrivateDataHandle hdl;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment