Commits

Virgil Dupras committed 397685b

Added support for NSPoint, NSSize and NSRect.

  • Participants
  • Parent commits 7b84988

Comments (0)

Files changed (7)

 * ``bool/BOOL``
 * ``list/NSArray*``
 * ``dict/NSDictionary*``
+* ``nspoint/NSPoint``
+* ``nssize/NSSize``
+* ``nsrect/NSRect``
 
 ObjP also supports ``object`` which dynamically converts the argument depending on its type and
 returns an ``NSObject`` subclass (which means that ``int``, ``float`` and ``bool` convert to
 Another special argument type is ``pyref`` (which you must import from ``objp.util`` in your code)
 which simply passes the ``PyObject*`` instance around without converting it.
 
+The structure arguments allow you to transform tuples to native objc structures and vice-versa.
+Python has no "native" structure for points, sizes and rects, so that's why we convert to/from
+tuples (``(x, y)``, ``(w, h)`` and ``(x, y, w, h)``). Like ``pyref``, the ``ns*`` signature
+arguments have to be imported from ``objp.util``.
+
 Utilities
 ---------
 
-``objp.util`` contains the ``pyref`` argument type, but it also contains two useful method
-decorators: ``dontwrap`` and ``objcname``. A method decorated with ``dontwrap`` will be ignored by
-the code generator, and a method decorated with ``@objcname('some:selector:')`` will use this name
-for generating objc code instead of the automatically generated name.
+``objp.util`` contains the ``pyref`` and ``ns*`` argument types, but it also contains two useful
+method decorators: ``dontwrap`` and ``objcname``. A method decorated with ``dontwrap`` will be
+ignored by the code generator, and a method decorated with ``@objcname('some:selector:')`` will use
+this name for generating objc code instead of the automatically generated name.

demos/datatypes/main.m

         [NSNumber numberWithFloat:42.42], [NSNumber numberWithBool:YES], [NSArray array],
         [NSDictionary dictionary], nil]]);
     NSLog(@"%@", [foo dict:[NSDictionary dictionaryWithObject:@"foo" forKey:@"bar"]]);
+    NSPoint p = NSMakePoint(1, 2);
+    NSPoint rp = [foo point:p];
+    NSLog(@"%f %f", rp.x, rp.y);
+    NSSize s = NSMakeSize(3, 4);
+    NSSize rs = [foo size:s];
+    NSLog(@"%f %f", rs.width, rs.height);
+    NSRect r;
+    r.origin = p;
+    r.size = s;
+    NSLog(@"%@", NSStringFromRect([foo rect:r]));
     Py_Finalize();
     [pool release];
     return 0;   

demos/datatypes/main.py

+from objp.util import nspoint, nssize, nsrect
+
 class Main:
     def string_(self, arg: str) -> str:
         print('string', repr(arg))
         print('dict', repr(arg))
         return arg
     
+    def point_(self, arg: nspoint) -> nspoint:
+        print('point', repr(arg))
+        return arg
+        
+    def size_(self, arg: nssize) -> nssize:
+        print('size', repr(arg))
+        return arg
+    
+    def rect_(self, arg: nsrect) -> nsrect:
+        print('rect', repr(arg))
+        return arg
+    
 import shutil
 from collections import namedtuple
 
-from .util import pyref
+from .util import pyref, nspoint, nssize, nsrect
 
 TypeSpec = namedtuple('TypeSpec', 'pytype objctype o2p_code p2o_code')
 ArgSpec = namedtuple('ArgSpec', 'argname typespec')
     TypeSpec(object, 'id', 'ObjP_obj_o2p(%s)', 'ObjP_obj_p2o(%s)'),
     TypeSpec(list, 'NSArray *', 'ObjP_list_o2p(%s)', 'ObjP_list_p2o(%s)'),
     TypeSpec(dict, 'NSDictionary *', 'ObjP_dict_o2p(%s)', 'ObjP_dict_p2o(%s)'),
+    TypeSpec(nspoint, 'NSPoint ', 'ObjP_nspoint_o2p(%s)', 'ObjP_nspoint_p2o(%s)'),
+    TypeSpec(nssize, 'NSSize ', 'ObjP_nssize_o2p(%s)', 'ObjP_nssize_p2o(%s)'),
+    TypeSpec(nsrect, 'NSRect ', 'ObjP_nsrect_o2p(%s)', 'ObjP_nsrect_p2o(%s)'),
     TypeSpec(pyref, 'PyObject *', 'ObjP_pyref_o2p(%s)', '%s'),
 ]
 
 PyObject* ObjP_list_o2p(NSArray *list);
 NSDictionary* ObjP_dict_p2o(PyObject *pDict);
 PyObject* ObjP_dict_o2p(NSDictionary *dict);
+NSPoint ObjP_nspoint_p2o(PyObject *pPoint);
+PyObject* ObjP_nspoint_o2p(NSPoint p);
+NSSize ObjP_nssize_p2o(PyObject *pSize);
+PyObject* ObjP_nssize_o2p(NSSize s);
+NSRect ObjP_nsrect_p2o(PyObject *pRect);
+PyObject* ObjP_nsrect_o2p(NSRect r);
 PyObject* ObjP_pyref_o2p(PyObject *pyref);
+
     return pResult;
 }
 
+NSPoint ObjP_nspoint_p2o(PyObject *pPoint)
+{
+    OBJP_LOCKGIL;
+    NSPoint result;
+    PyObject *iterator = PyObject_GetIter(pPoint);
+    OBJP_ERRCHECK(iterator);
+    PyObject *item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.x = ObjP_float_p2o(item);
+    item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.y = ObjP_float_p2o(item);
+    OBJP_UNLOCKGIL;
+    return result;
+}
+
+PyObject* ObjP_nspoint_o2p(NSPoint p)
+{
+    OBJP_LOCKGIL;
+    PyObject *pResult = PyTuple_New(2);
+    OBJP_ERRCHECK(pResult);
+    PyTuple_SET_ITEM(pResult, 0, ObjP_float_o2p(p.x));
+    PyTuple_SET_ITEM(pResult, 1, ObjP_float_o2p(p.y));
+    OBJP_UNLOCKGIL;
+    return pResult;
+}
+
+// NSSize and NSPoint have the same structure, we can same some code duplication here.
+NSSize ObjP_nssize_p2o(PyObject *pSize)
+{
+    NSPoint p = ObjP_nspoint_p2o(pSize);
+    return NSMakeSize(p.x, p.y);
+}
+
+PyObject* ObjP_nssize_o2p(NSSize s)
+{
+    NSPoint p = NSMakePoint(s.width, s.height);
+    return ObjP_nspoint_o2p(p);
+}
+
+NSRect ObjP_nsrect_p2o(PyObject *pRect)
+{
+    OBJP_LOCKGIL;
+    NSRect result;
+    PyObject *iterator = PyObject_GetIter(pRect);
+    OBJP_ERRCHECK(iterator);
+    PyObject *item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.origin.x = ObjP_float_p2o(item);
+    item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.origin.y = ObjP_float_p2o(item);
+    item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.size.width = ObjP_float_p2o(item);
+    item = PyIter_Next(iterator);
+    OBJP_ERRCHECK(item);
+    result.size.height = ObjP_float_p2o(item);
+    OBJP_UNLOCKGIL;
+    return result;
+}
+
+PyObject* ObjP_nsrect_o2p(NSRect r)
+{
+    OBJP_LOCKGIL;
+    PyObject *pResult = PyTuple_New(4);
+    OBJP_ERRCHECK(pResult);
+    PyTuple_SET_ITEM(pResult, 0, ObjP_float_o2p(r.origin.x));
+    PyTuple_SET_ITEM(pResult, 1, ObjP_float_o2p(r.origin.y));
+    PyTuple_SET_ITEM(pResult, 2, ObjP_float_o2p(r.size.width));
+    PyTuple_SET_ITEM(pResult, 3, ObjP_float_o2p(r.size.height));
+    OBJP_UNLOCKGIL;
+    return pResult;
+}
+
 /* We can use pyref as is, but in all other o2p code, we expect to have to decref the result,
    so in pyrefs case, we have to incref our pyref before returning it.
 */
 pyref = object()
+nspoint = object()
+nssize = object()
+nsrect = object()
 
 def objcname(name):
     def decorator(func):