diff options
author | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2025-02-11 13:26:52 +0300 |
---|---|---|
committer | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2025-02-11 13:57:59 +0300 |
commit | f895bba65827952ed934b2b46f9a45e30a191fd2 (patch) | |
tree | 03260c906d9ec41cdc03e2a496b15d407459cec0 /contrib/python/matplotlib/py2/src/_macosx.m | |
parent | 5f7060466f7b9707818c2091e1a25c14f33c3474 (diff) | |
download | ydb-f895bba65827952ed934b2b46f9a45e30a191fd2.tar.gz |
Remove deps on pandas
<https://github.com/ydb-platform/ydb/pull/14418>
<https://github.com/ydb-platform/ydb/pull/14419>
\-- аналогичные правки в gh
Хочу залить в обход синка, чтобы посмотреть удалится ли pandas в нашей gh репе через piglet
commit_hash:abca127aa37d4dbb94b07e1e18cdb8eb5b711860
Diffstat (limited to 'contrib/python/matplotlib/py2/src/_macosx.m')
-rw-r--r-- | contrib/python/matplotlib/py2/src/_macosx.m | 3174 |
1 files changed, 0 insertions, 3174 deletions
diff --git a/contrib/python/matplotlib/py2/src/_macosx.m b/contrib/python/matplotlib/py2/src/_macosx.m deleted file mode 100644 index 8f44f1eb0c5..00000000000 --- a/contrib/python/matplotlib/py2/src/_macosx.m +++ /dev/null @@ -1,3174 +0,0 @@ -#include <Cocoa/Cocoa.h> -#include <ApplicationServices/ApplicationServices.h> -#include <sys/socket.h> -#include <Python.h> - -#define PYOSINPUTHOOK_REPETITIVE 1 /* Remove this once Python is fixed */ - -#if PY_MAJOR_VERSION >= 3 -#define PY3K 1 -#else -#define PY3K 0 -#endif - -/* Proper way to check for the OS X version we are compiling for, from - http://developer.apple.com/documentation/DeveloperTools/Conceptual/cross_development */ -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 -#define COMPILING_FOR_10_6 -#endif -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 -#define COMPILING_FOR_10_7 -#endif -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100 -#define COMPILING_FOR_10_10 -#endif - - -/* CGFloat was defined in Mac OS X 10.5 */ -#ifndef CGFLOAT_DEFINED -#define CGFloat float -#endif - - -/* Various NSApplicationDefined event subtypes */ -#define STOP_EVENT_LOOP 2 -#define WINDOW_CLOSING 3 - - -/* Keep track of number of windows present - Needed to know when to stop the NSApp */ -static long FigureWindowCount = 0; - -/* -------------------------- Helper function ---------------------------- */ - -static void -_stdin_callback(CFReadStreamRef stream, CFStreamEventType eventType, void* info) -{ - CFRunLoopRef runloop = info; - CFRunLoopStop(runloop); -} - -static int sigint_fd = -1; - -static void _sigint_handler(int sig) -{ - const char c = 'i'; - write(sigint_fd, &c, 1); -} - -static void _sigint_callback(CFSocketRef s, - CFSocketCallBackType type, - CFDataRef address, - const void * data, - void *info) -{ - char c; - int* interrupted = info; - CFSocketNativeHandle handle = CFSocketGetNative(s); - CFRunLoopRef runloop = CFRunLoopGetCurrent(); - read(handle, &c, 1); - *interrupted = 1; - CFRunLoopStop(runloop); -} - -static CGEventRef _eventtap_callback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - CFRunLoopRef runloop = refcon; - CFRunLoopStop(runloop); - return event; -} - -static int wait_for_stdin(void) -{ - int interrupted = 0; - const UInt8 buffer[] = "/dev/fd/0"; - const CFIndex n = (CFIndex)strlen((char*)buffer); - CFRunLoopRef runloop = CFRunLoopGetCurrent(); - CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - buffer, - n, - false); - CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, - url); - CFRelease(url); - - CFReadStreamOpen(stream); -#ifdef PYOSINPUTHOOK_REPETITIVE - if (!CFReadStreamHasBytesAvailable(stream)) - /* This is possible because of how PyOS_InputHook is called from Python */ - { -#endif - int error; - int channel[2]; - CFSocketRef sigint_socket = NULL; - PyOS_sighandler_t py_sigint_handler = NULL; - CFStreamClientContext clientContext = {0, NULL, NULL, NULL, NULL}; - clientContext.info = runloop; - CFReadStreamSetClient(stream, - kCFStreamEventHasBytesAvailable, - _stdin_callback, - &clientContext); - CFReadStreamScheduleWithRunLoop(stream, runloop, kCFRunLoopDefaultMode); - error = socketpair(AF_UNIX, SOCK_STREAM, 0, channel); - if (error==0) - { - CFSocketContext context; - context.version = 0; - context.info = &interrupted; - context.retain = NULL; - context.release = NULL; - context.copyDescription = NULL; - fcntl(channel[0], F_SETFL, O_WRONLY | O_NONBLOCK); - sigint_socket = CFSocketCreateWithNative( - kCFAllocatorDefault, - channel[1], - kCFSocketReadCallBack, - _sigint_callback, - &context); - if (sigint_socket) - { - CFRunLoopSourceRef source; - source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, - sigint_socket, - 0); - CFRelease(sigint_socket); - if (source) - { - CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode); - CFRelease(source); - sigint_fd = channel[0]; - py_sigint_handler = PyOS_setsig(SIGINT, _sigint_handler); - } - } - } - - NSEvent* event; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - while (true) { - while (true) { - event = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: [NSDate distantPast] - inMode: NSDefaultRunLoopMode - dequeue: YES]; - if (!event) break; - [NSApp sendEvent: event]; - } - CFRunLoopRun(); - if (interrupted || CFReadStreamHasBytesAvailable(stream)) break; - } - [pool release]; - - if (py_sigint_handler) PyOS_setsig(SIGINT, py_sigint_handler); - CFReadStreamUnscheduleFromRunLoop(stream, - runloop, - kCFRunLoopCommonModes); - if (sigint_socket) CFSocketInvalidate(sigint_socket); - if (error==0) { - close(channel[0]); - close(channel[1]); - } -#ifdef PYOSINPUTHOOK_REPETITIVE - } -#endif - CFReadStreamClose(stream); - CFRelease(stream); - if (interrupted) { - errno = EINTR; - raise(SIGINT); - return -1; - } - return 1; -} - -/* ---------------------------- Cocoa classes ---------------------------- */ - -@interface WindowServerConnectionManager : NSObject -{ -} -+ (WindowServerConnectionManager*)sharedManager; -- (void)launch:(NSNotification*)notification; -@end - -@interface Window : NSWindow -{ PyObject* manager; -} -- (Window*)initWithContentRect:(NSRect)rect styleMask:(unsigned int)mask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation withManager: (PyObject*)theManager; -- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen; -- (BOOL)closeButtonPressed; -- (void)dealloc; -@end - -@interface ToolWindow : NSWindow -{ -} -- (ToolWindow*)initWithContentRect:(NSRect)rect master:(NSWindow*)window; -- (void)masterCloses:(NSNotification*)notification; -- (void)close; -@end - -#ifdef COMPILING_FOR_10_6 -@interface View : NSView <NSWindowDelegate> -#else -@interface View : NSView -#endif -{ PyObject* canvas; - NSRect rubberband; - BOOL inside; - NSTrackingRectTag tracking; - @public double device_scale; -} -- (void)dealloc; -- (void)drawRect:(NSRect)rect; -- (void)windowDidResize:(NSNotification*)notification; -- (View*)initWithFrame:(NSRect)rect; -- (void)setCanvas: (PyObject*)newCanvas; -- (void)windowWillClose:(NSNotification*)notification; -- (BOOL)windowShouldClose:(NSNotification*)notification; -- (BOOL)isFlipped; -- (void)mouseEntered:(NSEvent*)event; -- (void)mouseExited:(NSEvent*)event; -- (void)mouseDown:(NSEvent*)event; -- (void)mouseUp:(NSEvent*)event; -- (void)mouseDragged:(NSEvent*)event; -- (void)mouseMoved:(NSEvent*)event; -- (void)rightMouseDown:(NSEvent*)event; -- (void)rightMouseUp:(NSEvent*)event; -- (void)rightMouseDragged:(NSEvent*)event; -- (void)otherMouseDown:(NSEvent*)event; -- (void)otherMouseUp:(NSEvent*)event; -- (void)otherMouseDragged:(NSEvent*)event; -- (void)setRubberband:(NSRect)rect; -- (void)removeRubberband; -- (const char*)convertKeyEvent:(NSEvent*)event; -- (void)keyDown:(NSEvent*)event; -- (void)keyUp:(NSEvent*)event; -- (void)scrollWheel:(NSEvent *)event; -- (BOOL)acceptsFirstResponder; -//- (void)flagsChanged:(NSEvent*)event; -@end - -@interface ScrollableButton : NSButton -{ - SEL scrollWheelUpAction; - SEL scrollWheelDownAction; -} -- (void)setScrollWheelUpAction:(SEL)action; -- (void)setScrollWheelDownAction:(SEL)action; -- (void)scrollWheel:(NSEvent *)event; -@end - -@interface MenuItem: NSMenuItem -{ int index; -} -+ (MenuItem*)menuItemWithTitle:(NSString*)title; -+ (MenuItem*)menuItemSelectAll; -+ (MenuItem*)menuItemInvertAll; -+ (MenuItem*)menuItemForAxis:(int)i; -- (void)toggle:(id)sender; -- (void)selectAll:(id)sender; -- (void)invertAll:(id)sender; -- (int)index; -@end - -/* ---------------------------- Python classes ---------------------------- */ - -static CGFloat _get_device_scale(CGContextRef cr) -{ - CGSize pixelSize = CGContextConvertSizeToDeviceSpace(cr, CGSizeMake(1, 1)); - return pixelSize.width; -} - -typedef struct { - PyObject_HEAD - View* view; -} FigureCanvas; - -static PyObject* -FigureCanvas_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - FigureCanvas *self = (FigureCanvas*)type->tp_alloc(type, 0); - if (!self) return NULL; - self->view = [View alloc]; - return (PyObject*)self; -} - -static int -FigureCanvas_init(FigureCanvas *self, PyObject *args, PyObject *kwds) -{ - int width; - int height; - if(!self->view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return -1; - } - - if(!PyArg_ParseTuple(args, "ii", &width, &height)) return -1; - - NSRect rect = NSMakeRect(0.0, 0.0, width, height); - self->view = [self->view initWithFrame: rect]; - [self->view setCanvas: (PyObject*)self]; - return 0; -} - -static void -FigureCanvas_dealloc(FigureCanvas* self) -{ - if (self->view) - { - [self->view setCanvas: NULL]; - [self->view release]; - } - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject* -FigureCanvas_repr(FigureCanvas* self) -{ -#if PY3K - return PyUnicode_FromFormat("FigureCanvas object %p wrapping NSView %p", - (void*)self, (void*)(self->view)); -#else - return PyString_FromFormat("FigureCanvas object %p wrapping NSView %p", - (void*)self, (void*)(self->view)); -#endif -} - -static PyObject* -FigureCanvas_draw(FigureCanvas* self) -{ - View* view = self->view; - - if(view) /* The figure may have been closed already */ - { - /* Whereas drawRect creates its own autorelease pool, apparently - * [view display] also needs one. Create and release it here. */ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [view display]; - [pool release]; - } - - Py_RETURN_NONE; -} - -static PyObject* -FigureCanvas_invalidate(FigureCanvas* self) -{ - View* view = self->view; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return NULL; - } - [view setNeedsDisplay: YES]; - Py_RETURN_NONE; -} - -static PyObject* -FigureCanvas_flush_events(FigureCanvas* self) -{ - View* view = self->view; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return NULL; - } - [view displayIfNeeded]; - Py_RETURN_NONE; -} - -static PyObject* -FigureCanvas_set_rubberband(FigureCanvas* self, PyObject *args) -{ - View* view = self->view; - int x0, y0, x1, y1; - NSRect rubberband; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return NULL; - } - if(!PyArg_ParseTuple(args, "iiii", &x0, &y0, &x1, &y1)) return NULL; - - x0 /= view->device_scale; - x1 /= view->device_scale; - y0 /= view->device_scale; - y1 /= view->device_scale; - - if (x1 > x0) - { - rubberband.origin.x = x0; - rubberband.size.width = x1 - x0; - } - else - { - rubberband.origin.x = x1; - rubberband.size.width = x0 - x1; - } - if (y1 > y0) - { - rubberband.origin.y = y0; - rubberband.size.height = y1 - y0; - } - else - { - rubberband.origin.y = y1; - rubberband.size.height = y0 - y1; - } - - [view setRubberband: rubberband]; - Py_RETURN_NONE; -} - -static PyObject* -FigureCanvas_remove_rubberband(FigureCanvas* self) -{ - View* view = self->view; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return NULL; - } - [view removeRubberband]; - Py_RETURN_NONE; -} - -static NSImage* _read_ppm_image(PyObject* obj) -{ - int width; - int height; - const char* data; - int n; - int i; - NSBitmapImageRep* bitmap; - unsigned char* bitmapdata; - - if (!obj) return NULL; - if (!PyTuple_Check(obj)) return NULL; - if (!PyArg_ParseTuple(obj, "iit#", &width, &height, &data, &n)) return NULL; - if (width*height*3 != n) return NULL; /* RGB image uses 3 colors / pixel */ - - bitmap = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes: NULL - pixelsWide: width - pixelsHigh: height - bitsPerSample: 8 - samplesPerPixel: 3 - hasAlpha: NO - isPlanar: NO - colorSpaceName: NSDeviceRGBColorSpace - bitmapFormat: 0 - bytesPerRow: width*3 - bitsPerPixel: 24]; - if (!bitmap) return NULL; - bitmapdata = [bitmap bitmapData]; - for (i = 0; i < n; i++) bitmapdata[i] = data[i]; - - NSSize size = NSMakeSize(width, height); - NSImage* image = [[NSImage alloc] initWithSize: size]; - if (image) [image addRepresentation: bitmap]; - - [bitmap release]; - - return image; -} - -static PyObject* -FigureCanvas_start_event_loop(FigureCanvas* self, PyObject* args, PyObject* keywords) -{ - float timeout = 0.0; - - static char* kwlist[] = {"timeout", NULL}; - if(!PyArg_ParseTupleAndKeywords(args, keywords, "f", kwlist, &timeout)) - return NULL; - - int error; - int interrupted = 0; - int channel[2]; - CFSocketRef sigint_socket = NULL; - PyOS_sighandler_t py_sigint_handler = NULL; - - CFRunLoopRef runloop = CFRunLoopGetCurrent(); - - error = pipe(channel); - if (error==0) - { - CFSocketContext context = {0, NULL, NULL, NULL, NULL}; - fcntl(channel[1], F_SETFL, O_WRONLY | O_NONBLOCK); - - context.info = &interrupted; - sigint_socket = CFSocketCreateWithNative(kCFAllocatorDefault, - channel[0], - kCFSocketReadCallBack, - _sigint_callback, - &context); - if (sigint_socket) - { - CFRunLoopSourceRef source; - source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, - sigint_socket, - 0); - CFRelease(sigint_socket); - if (source) - { - CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode); - CFRelease(source); - sigint_fd = channel[1]; - py_sigint_handler = PyOS_setsig(SIGINT, _sigint_handler); - } - } - else - close(channel[0]); - } - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSDate* date = - (timeout > 0.0) ? [NSDate dateWithTimeIntervalSinceNow: timeout] - : [NSDate distantFuture]; - while (true) - { NSEvent* event = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: date - inMode: NSDefaultRunLoopMode - dequeue: YES]; - if (!event || [event type]==NSApplicationDefined) break; - [NSApp sendEvent: event]; - } - [pool release]; - - if (py_sigint_handler) PyOS_setsig(SIGINT, py_sigint_handler); - - if (sigint_socket) CFSocketInvalidate(sigint_socket); - if (error==0) close(channel[1]); - if (interrupted) raise(SIGINT); - - Py_RETURN_NONE; -} - -static PyObject* -FigureCanvas_stop_event_loop(FigureCanvas* self) -{ - NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined - location: NSZeroPoint - modifierFlags: 0 - timestamp: 0.0 - windowNumber: 0 - context: nil - subtype: STOP_EVENT_LOOP - data1: 0 - data2: 0]; - [NSApp postEvent: event atStart: true]; - Py_RETURN_NONE; -} - -static PyMethodDef FigureCanvas_methods[] = { - {"draw", - (PyCFunction)FigureCanvas_draw, - METH_NOARGS, - "Draws the canvas." - }, - {"invalidate", - (PyCFunction)FigureCanvas_invalidate, - METH_NOARGS, - "Invalidates the canvas." - }, - {"flush_events", - (PyCFunction)FigureCanvas_flush_events, - METH_NOARGS, - "Flush the GUI events for the figure." - }, - {"set_rubberband", - (PyCFunction)FigureCanvas_set_rubberband, - METH_VARARGS, - "Specifies a new rubberband rectangle and invalidates it." - }, - {"remove_rubberband", - (PyCFunction)FigureCanvas_remove_rubberband, - METH_NOARGS, - "Removes the current rubberband rectangle." - }, - {"start_event_loop", - (PyCFunction)FigureCanvas_start_event_loop, - METH_KEYWORDS | METH_VARARGS, - "Runs the event loop until the timeout or until stop_event_loop is called.\n", - }, - {"stop_event_loop", - (PyCFunction)FigureCanvas_stop_event_loop, - METH_NOARGS, - "Stops the event loop that was started by start_event_loop.\n", - }, - {NULL} /* Sentinel */ -}; - -static char FigureCanvas_doc[] = -"A FigureCanvas object wraps a Cocoa NSView object.\n"; - -static PyTypeObject FigureCanvasType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_macosx.FigureCanvas", /*tp_name*/ - sizeof(FigureCanvas), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)FigureCanvas_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)FigureCanvas_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - FigureCanvas_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - FigureCanvas_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)FigureCanvas_init, /* tp_init */ - 0, /* tp_alloc */ - FigureCanvas_new, /* tp_new */ -}; - -typedef struct { - PyObject_HEAD - Window* window; -} FigureManager; - -static PyObject* -FigureManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Window* window = [Window alloc]; - if (!window) return NULL; - FigureManager *self = (FigureManager*)type->tp_alloc(type, 0); - if (!self) - { - [window release]; - return NULL; - } - self->window = window; - ++FigureWindowCount; - return (PyObject*)self; -} - -static int -FigureManager_init(FigureManager *self, PyObject *args, PyObject *kwds) -{ - NSRect rect; - Window* window; - View* view; - const char* title; - PyObject* size; - int width, height; - PyObject* obj; - FigureCanvas* canvas; - - if(!self->window) - { - PyErr_SetString(PyExc_RuntimeError, "NSWindow* is NULL"); - return -1; - } - - if(!PyArg_ParseTuple(args, "Os", &obj, &title)) return -1; - - canvas = (FigureCanvas*)obj; - view = canvas->view; - if (!view) /* Something really weird going on */ - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return -1; - } - - size = PyObject_CallMethod(obj, "get_width_height", ""); - if(!size) return -1; - if(!PyArg_ParseTuple(size, "ii", &width, &height)) - { Py_DECREF(size); - return -1; - } - Py_DECREF(size); - - rect.origin.x = 100; - rect.origin.y = 350; - rect.size.height = height; - rect.size.width = width; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - self->window = [self->window initWithContentRect: rect - styleMask: NSTitledWindowMask - | NSClosableWindowMask - | NSResizableWindowMask - | NSMiniaturizableWindowMask - backing: NSBackingStoreBuffered - defer: YES - withManager: (PyObject*)self]; - window = self->window; - [window setTitle: [NSString stringWithCString: title - encoding: NSASCIIStringEncoding]]; - - [window setAcceptsMouseMovedEvents: YES]; - [window setDelegate: view]; - [window makeFirstResponder: view]; - [[window contentView] addSubview: view]; - - [pool release]; - return 0; -} - -static PyObject* -FigureManager_repr(FigureManager* self) -{ -#if PY3K - return PyUnicode_FromFormat("FigureManager object %p wrapping NSWindow %p", - (void*) self, (void*)(self->window)); -#else - return PyString_FromFormat("FigureManager object %p wrapping NSWindow %p", - (void*) self, (void*)(self->window)); -#endif -} - -static void -FigureManager_dealloc(FigureManager* self) -{ - Window* window = self->window; - if(window) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [window close]; - [pool release]; - } - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject* -FigureManager_show(FigureManager* self) -{ - Window* window = self->window; - if(window) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [window makeKeyAndOrderFront: nil]; - [window orderFrontRegardless]; - [pool release]; - } - Py_RETURN_NONE; -} - -static PyObject* -FigureManager_destroy(FigureManager* self) -{ - Window* window = self->window; - if(window) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [window close]; - [pool release]; - self->window = NULL; - } - Py_RETURN_NONE; -} - -static PyObject* -FigureManager_set_window_title(FigureManager* self, - PyObject *args, PyObject *kwds) -{ - char* title; - if(!PyArg_ParseTuple(args, "es", "UTF-8", &title)) - return NULL; - - Window* window = self->window; - if(window) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSString* ns_title = [[[NSString alloc] - initWithCString: title - encoding: NSUTF8StringEncoding] autorelease]; - [window setTitle: ns_title]; - [pool release]; - } - PyMem_Free(title); - Py_RETURN_NONE; -} - -static PyObject* -FigureManager_get_window_title(FigureManager* self) -{ - Window* window = self->window; - PyObject* result = NULL; - if(window) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSString* title = [window title]; - if (title) { - const char* cTitle = [title UTF8String]; - result = PyUnicode_FromString(cTitle); - } - [pool release]; - } - if (result) { - return result; - } else { - Py_RETURN_NONE; - } -} - -static PyMethodDef FigureManager_methods[] = { - {"show", - (PyCFunction)FigureManager_show, - METH_NOARGS, - "Shows the window associated with the figure manager." - }, - {"destroy", - (PyCFunction)FigureManager_destroy, - METH_NOARGS, - "Closes the window associated with the figure manager." - }, - {"set_window_title", - (PyCFunction)FigureManager_set_window_title, - METH_VARARGS, - "Sets the title of the window associated with the figure manager." - }, - {"get_window_title", - (PyCFunction)FigureManager_get_window_title, - METH_NOARGS, - "Returns the title of the window associated with the figure manager." - }, - {NULL} /* Sentinel */ -}; - -static char FigureManager_doc[] = -"A FigureManager object wraps a Cocoa NSWindow object.\n"; - -static PyTypeObject FigureManagerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_macosx.FigureManager", /*tp_name*/ - sizeof(FigureManager), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)FigureManager_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)FigureManager_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - FigureManager_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - FigureManager_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)FigureManager_init, /* tp_init */ - 0, /* tp_alloc */ - FigureManager_new, /* tp_new */ -}; - -@interface NavigationToolbarHandler : NSObject -{ PyObject* toolbar; -} -- (NavigationToolbarHandler*)initWithToolbar:(PyObject*)toolbar; --(void)left:(id)sender; --(void)right:(id)sender; --(void)up:(id)sender; --(void)down:(id)sender; --(void)zoominx:(id)sender; --(void)zoominy:(id)sender; --(void)zoomoutx:(id)sender; --(void)zoomouty:(id)sender; -@end - -typedef struct { - PyObject_HEAD - NSPopUpButton* menu; - NavigationToolbarHandler* handler; -} NavigationToolbar; - -@implementation NavigationToolbarHandler -- (NavigationToolbarHandler*)initWithToolbar:(PyObject*)theToolbar -{ [self init]; - toolbar = theToolbar; - return self; -} - --(void)left:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "panx", "i", -1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)right:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "panx", "i", 1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)up:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "pany", "i", 1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)down:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "pany", "i", -1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)zoominx:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "zoomx", "i", 1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)zoomoutx:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "zoomx", "i", -1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)zoominy:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "zoomy", "i", 1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)zoomouty:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "zoomy", "i", -1); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)save_figure:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "save_figure", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} -@end - -static PyObject* -NavigationToolbar_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - NavigationToolbarHandler* handler = [NavigationToolbarHandler alloc]; - if (!handler) return NULL; - NavigationToolbar *self = (NavigationToolbar*)type->tp_alloc(type, 0); - if (!self) - { [handler release]; - return NULL; - } - self->handler = handler; - return (PyObject*)self; -} - -static int -NavigationToolbar_init(NavigationToolbar *self, PyObject *args, PyObject *kwds) -{ - int i; - NSRect rect; - - const float smallgap = 2; - const float biggap = 10; - const int height = 32; - - PyObject* images; - PyObject* obj; - - FigureCanvas* canvas; - View* view; - - obj = PyObject_GetAttrString((PyObject*)self, "canvas"); - if (obj==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Attempt to install toolbar for NULL canvas"); - return -1; - } - Py_DECREF(obj); /* Don't increase the reference count */ - if (!PyObject_IsInstance(obj, (PyObject*) &FigureCanvasType)) - { - PyErr_SetString(PyExc_TypeError, "Attempt to install toolbar for object that is not a FigureCanvas"); - return -1; - } - canvas = (FigureCanvas*)obj; - view = canvas->view; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return -1; - } - - if(!PyArg_ParseTuple(args, "O", &images)) return -1; - if(!PyDict_Check(images)) return -1; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect bounds = [view bounds]; - NSWindow* window = [view window]; - - bounds.origin.y += height; - [view setFrame: bounds]; - - bounds.size.height += height; - [window setContentSize: bounds.size]; - - char* imagenames[9] = {"stock_left", - "stock_right", - "stock_zoom-in", - "stock_zoom-out", - "stock_up", - "stock_down", - "stock_zoom-in", - "stock_zoom-out", - "stock_save_as"}; - - NSString* tooltips[9] = { - @"Pan left with click or wheel mouse (bidirectional)", - @"Pan right with click or wheel mouse (bidirectional)", - @"Zoom In X (shrink the x axis limits) with click or wheel mouse (bidirectional)", - @"Zoom Out X (expand the x axis limits) with click or wheel mouse (bidirectional)", - @"Pan up with click or wheel mouse (bidirectional)", - @"Pan down with click or wheel mouse (bidirectional)", - @"Zoom in Y (shrink the y axis limits) with click or wheel mouse (bidirectional)", - @"Zoom Out Y (expand the y axis limits) with click or wheel mouse (bidirectional)", - @"Save the figure"}; - - SEL actions[9] = {@selector(left:), - @selector(right:), - @selector(zoominx:), - @selector(zoomoutx:), - @selector(up:), - @selector(down:), - @selector(zoominy:), - @selector(zoomouty:), - @selector(save_figure:)}; - - SEL scroll_actions[9][2] = {{@selector(left:), @selector(right:)}, - {@selector(left:), @selector(right:)}, - {@selector(zoominx:), @selector(zoomoutx:)}, - {@selector(zoominx:), @selector(zoomoutx:)}, - {@selector(up:), @selector(down:)}, - {@selector(up:), @selector(down:)}, - {@selector(zoominy:), @selector(zoomouty:)}, - {@selector(zoominy:), @selector(zoomouty:)}, - {nil,nil}, - }; - - - rect.size.width = 120; - rect.size.height = 24; - rect.origin.x = biggap; - rect.origin.y = 0.5*(height - rect.size.height); - self->menu = [[NSPopUpButton alloc] initWithFrame: rect - pullsDown: YES]; - [self->menu setAutoenablesItems: NO]; - [[window contentView] addSubview: self->menu]; - [self->menu release]; - rect.origin.x += rect.size.width + biggap; - rect.size.width = 24; - - self->handler = [self->handler initWithToolbar: (PyObject*)self]; - for (i = 0; i < 9; i++) - { - NSButton* button; - SEL scrollWheelUpAction = scroll_actions[i][0]; - SEL scrollWheelDownAction = scroll_actions[i][1]; - if (scrollWheelUpAction && scrollWheelDownAction) - { - ScrollableButton* scrollable_button = [ScrollableButton alloc]; - [scrollable_button initWithFrame: rect]; - [scrollable_button setScrollWheelUpAction: scrollWheelUpAction]; - [scrollable_button setScrollWheelDownAction: scrollWheelDownAction]; - button = (NSButton*)scrollable_button; - } - else - { - button = [NSButton alloc]; - [button initWithFrame: rect]; - } - PyObject* imagedata = PyDict_GetItemString(images, imagenames[i]); - NSImage* image = _read_ppm_image(imagedata); - [button setBezelStyle: NSShadowlessSquareBezelStyle]; - [button setButtonType: NSMomentaryLightButton]; - if(image) - { - [button setImage: image]; - [image release]; - } - [button setToolTip: tooltips[i]]; - [button setTarget: self->handler]; - [button setAction: actions[i]]; - [[window contentView] addSubview: button]; - [button release]; - rect.origin.x += rect.size.width + smallgap; - } - [[window contentView] display]; - [pool release]; - - return 0; -} - -static void -NavigationToolbar_dealloc(NavigationToolbar *self) -{ - [self->handler release]; - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject* -NavigationToolbar_repr(NavigationToolbar* self) -{ -#if PY3K - return PyUnicode_FromFormat("NavigationToolbar object %p", (void*)self); -#else - return PyString_FromFormat("NavigationToolbar object %p", (void*)self); -#endif -} - -static char NavigationToolbar_doc[] = -"NavigationToolbar\n"; - -static PyObject* -NavigationToolbar_update (NavigationToolbar* self) -{ - int n; - NSPopUpButton* button = self->menu; - if (!button) - { - PyErr_SetString(PyExc_RuntimeError, "Menu button is NULL"); - return NULL; - } - - PyObject* canvas = PyObject_GetAttrString((PyObject*)self, "canvas"); - if (canvas==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Failed to find canvas"); - return NULL; - } - Py_DECREF(canvas); /* Don't keep a reference here */ - PyObject* figure = PyObject_GetAttrString(canvas, "figure"); - if (figure==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Failed to find figure"); - return NULL; - } - Py_DECREF(figure); /* Don't keep a reference here */ - PyObject* axes = PyObject_GetAttrString(figure, "axes"); - if (axes==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Failed to find figure axes"); - return NULL; - } - Py_DECREF(axes); /* Don't keep a reference here */ - if (!PyList_Check(axes)) - { - PyErr_SetString(PyExc_TypeError, "Figure axes is not a list"); - return NULL; - } - n = PyList_GET_SIZE(axes); - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [button removeAllItems]; - - NSMenu* menu = [button menu]; - [menu addItem: [MenuItem menuItemWithTitle: @"Axes"]]; - - if (n==0) - { - [button setEnabled: NO]; - } - else - { - int i; - [menu addItem: [MenuItem menuItemSelectAll]]; - [menu addItem: [MenuItem menuItemInvertAll]]; - [menu addItem: [NSMenuItem separatorItem]]; - for (i = 0; i < n; i++) - { - [menu addItem: [MenuItem menuItemForAxis: i]]; - } - [button setEnabled: YES]; - } - [pool release]; - Py_RETURN_NONE; -} - -static PyObject* -NavigationToolbar_get_active (NavigationToolbar* self) -{ - NSPopUpButton* button = self->menu; - if (!button) - { - PyErr_SetString(PyExc_RuntimeError, "Menu button is NULL"); - return NULL; - } - NSMenu* menu = [button menu]; - NSArray* items = [menu itemArray]; - size_t n = [items count]; - int* states = calloc(n, sizeof(int)); - if (!states) - { - PyErr_SetString(PyExc_RuntimeError, "calloc failed"); - return NULL; - } - int i; - unsigned int m = 0; - NSEnumerator* enumerator = [items objectEnumerator]; - MenuItem* item; - while ((item = [enumerator nextObject])) - { - if ([item isSeparatorItem]) continue; - i = [item index]; - if (i < 0) continue; - if ([item state]==NSOnState) - { - states[i] = 1; - m++; - } - } - Py_ssize_t list_index = 0; - PyObject* list = PyList_New(m); - - size_t state_index; - for (state_index = 0; state_index < n; state_index++) - { - if(states[state_index]==1) - { - PyList_SET_ITEM(list, list_index++, PyLong_FromSize_t(state_index)); - } - } - free(states); - return list; -} - -static PyMethodDef NavigationToolbar_methods[] = { - {"update", - (PyCFunction)NavigationToolbar_update, - METH_NOARGS, - "Updates the toolbar menu." - }, - {"get_active", - (PyCFunction)NavigationToolbar_get_active, - METH_NOARGS, - "Returns a list of integers identifying which items in the menu are selected." - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject NavigationToolbarType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_macosx.NavigationToolbar", /*tp_name*/ - sizeof(NavigationToolbar), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)NavigationToolbar_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)NavigationToolbar_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - NavigationToolbar_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NavigationToolbar_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)NavigationToolbar_init, /* tp_init */ - 0, /* tp_alloc */ - NavigationToolbar_new, /* tp_new */ -}; - -@interface NavigationToolbar2Handler : NSObject -{ PyObject* toolbar; - NSButton* panbutton; - NSButton* zoombutton; -} -- (NavigationToolbar2Handler*)initWithToolbar:(PyObject*)toolbar; -- (void)installCallbacks:(SEL[7])actions forButtons: (NSButton*[7])buttons; -- (void)home:(id)sender; -- (void)back:(id)sender; -- (void)forward:(id)sender; -- (void)pan:(id)sender; -- (void)zoom:(id)sender; -- (void)configure_subplots:(id)sender; -- (void)save_figure:(id)sender; -@end - -typedef struct { - PyObject_HEAD - NSPopUpButton* menu; - NSText* messagebox; - NavigationToolbar2Handler* handler; -} NavigationToolbar2; - -@implementation NavigationToolbar2Handler -- (NavigationToolbar2Handler*)initWithToolbar:(PyObject*)theToolbar -{ [self init]; - toolbar = theToolbar; - return self; -} - -- (void)installCallbacks:(SEL[7])actions forButtons: (NSButton*[7])buttons -{ - int i; - for (i = 0; i < 7; i++) - { - SEL action = actions[i]; - NSButton* button = buttons[i]; - [button setTarget: self]; - [button setAction: action]; - if (action==@selector(pan:)) panbutton = button; - if (action==@selector(zoom:)) zoombutton = button; - } -} - --(void)home:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "home", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)back:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "back", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)forward:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "forward", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)pan:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - if ([sender state]) - { - if (zoombutton) [zoombutton setState: NO]; - } - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "pan", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)zoom:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - if ([sender state]) - { - if (panbutton) [panbutton setState: NO]; - } - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "zoom", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - --(void)configure_subplots:(id)sender -{ PyObject* canvas; - View* view; - PyObject* size; - NSRect rect; - int width, height; - - rect.origin.x = 100; - rect.origin.y = 350; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* master = PyObject_GetAttrString(toolbar, "canvas"); - if (master==nil) - { - PyErr_Print(); - PyGILState_Release(gstate); - return; - } - canvas = PyObject_CallMethod(toolbar, "prepare_configure_subplots", ""); - if(!canvas) - { - PyErr_Print(); - Py_DECREF(master); - PyGILState_Release(gstate); - return; - } - - view = ((FigureCanvas*)canvas)->view; - if (!view) /* Something really weird going on */ - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - PyErr_Print(); - Py_DECREF(canvas); - Py_DECREF(master); - PyGILState_Release(gstate); - return; - } - - size = PyObject_CallMethod(canvas, "get_width_height", ""); - Py_DECREF(canvas); - if(!size) - { - PyErr_Print(); - Py_DECREF(master); - PyGILState_Release(gstate); - return; - } - - int ok = PyArg_ParseTuple(size, "ii", &width, &height); - Py_DECREF(size); - if (!ok) - { - PyErr_Print(); - Py_DECREF(master); - PyGILState_Release(gstate); - return; - } - - NSWindow* mw = [((FigureCanvas*)master)->view window]; - Py_DECREF(master); - PyGILState_Release(gstate); - - rect.size.width = width; - rect.size.height = height; - - ToolWindow* window = [ [ToolWindow alloc] initWithContentRect: rect - master: mw]; - [window setContentView: view]; - [view release]; - [window makeKeyAndOrderFront: nil]; -} - --(void)save_figure:(id)sender -{ PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(toolbar, "save_figure", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} -@end - -static PyObject* -NavigationToolbar2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - NavigationToolbar2Handler* handler = [NavigationToolbar2Handler alloc]; - if (!handler) return NULL; - NavigationToolbar2 *self = (NavigationToolbar2*)type->tp_alloc(type, 0); - if (!self) - { - [handler release]; - return NULL; - } - self->handler = handler; - return (PyObject*)self; -} - -static int -NavigationToolbar2_init(NavigationToolbar2 *self, PyObject *args, PyObject *kwds) -{ - PyObject* obj; - FigureCanvas* canvas; - View* view; - - int i; - NSRect rect; - NSSize size; - NSSize scale; - - const float gap = 2; - const int height = 36; - const int imagesize = 24; - - const char* basedir; - - obj = PyObject_GetAttrString((PyObject*)self, "canvas"); - if (obj==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Attempt to install toolbar for NULL canvas"); - return -1; - } - Py_DECREF(obj); /* Don't increase the reference count */ - if (!PyObject_IsInstance(obj, (PyObject*) &FigureCanvasType)) - { - PyErr_SetString(PyExc_TypeError, "Attempt to install toolbar for object that is not a FigureCanvas"); - return -1; - } - canvas = (FigureCanvas*)obj; - view = canvas->view; - if(!view) - { - PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); - return -1; - } - - if(!PyArg_ParseTuple(args, "s", &basedir)) return -1; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect bounds = [view bounds]; - NSWindow* window = [view window]; - - bounds.origin.y += height; - [view setFrame: bounds]; - - bounds.size.height += height; - [window setContentSize: bounds.size]; - - NSString* dir = [NSString stringWithCString: basedir - encoding: NSASCIIStringEncoding]; - - NSButton* buttons[7]; - - NSString* images[7] = {@"home.pdf", - @"back.pdf", - @"forward.pdf", - @"move.pdf", - @"zoom_to_rect.pdf", - @"subplots.pdf", - @"filesave.pdf"}; - - NSString* tooltips[7] = {@"Reset original view", - @"Back to previous view", - @"Forward to next view", - @"Pan axes with left mouse, zoom with right", - @"Zoom to rectangle", - @"Configure subplots", - @"Save the figure"}; - - SEL actions[7] = {@selector(home:), - @selector(back:), - @selector(forward:), - @selector(pan:), - @selector(zoom:), - @selector(configure_subplots:), - @selector(save_figure:)}; - - NSButtonType buttontypes[7] = {NSMomentaryLightButton, - NSMomentaryLightButton, - NSMomentaryLightButton, - NSPushOnPushOffButton, - NSPushOnPushOffButton, - NSMomentaryLightButton, - NSMomentaryLightButton}; - - rect.origin.x = 0; - rect.origin.y = 0; - rect.size.width = imagesize; - rect.size.height = imagesize; -#ifdef COMPILING_FOR_10_7 - rect = [window convertRectToBacking: rect]; -#endif - size = rect.size; - scale.width = imagesize / size.width; - scale.height = imagesize / size.height; - - rect.size.width = 32; - rect.size.height = 32; - rect.origin.x = gap; - rect.origin.y = 0.5*(height - rect.size.height); - - for (i = 0; i < 7; i++) - { - NSString* filename = [dir stringByAppendingPathComponent: images[i]]; - NSImage* image = [[NSImage alloc] initWithContentsOfFile: filename]; - buttons[i] = [[NSButton alloc] initWithFrame: rect]; - [image setSize: size]; - [buttons[i] setBezelStyle: NSShadowlessSquareBezelStyle]; - [buttons[i] setButtonType: buttontypes[i]]; - [buttons[i] setImage: image]; - [buttons[i] scaleUnitSquareToSize: scale]; - [buttons[i] setImagePosition: NSImageOnly]; - [buttons[i] setToolTip: tooltips[i]]; - [[window contentView] addSubview: buttons[i]]; - [buttons[i] release]; - [image release]; - rect.origin.x += rect.size.width + gap; - } - - self->handler = [self->handler initWithToolbar: (PyObject*)self]; - [self->handler installCallbacks: actions forButtons: buttons]; - - NSFont* font = [NSFont systemFontOfSize: 0.0]; - rect.size.width = 300; - rect.size.height = 0; - rect.origin.x += height; - NSText* messagebox = [[NSText alloc] initWithFrame: rect]; - [messagebox setFont: font]; - [messagebox setDrawsBackground: NO]; - [messagebox setSelectable: NO]; - /* if selectable, the messagebox can become first responder, - * which is not supposed to happen */ - rect = [messagebox frame]; - rect.origin.y = 0.5 * (height - rect.size.height); - [messagebox setFrameOrigin: rect.origin]; - [[window contentView] addSubview: messagebox]; - [messagebox release]; - [[window contentView] display]; - - [pool release]; - - self->messagebox = messagebox; - return 0; -} - -static void -NavigationToolbar2_dealloc(NavigationToolbar2 *self) -{ - [self->handler release]; - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject* -NavigationToolbar2_repr(NavigationToolbar2* self) -{ -#if PY3K - return PyUnicode_FromFormat("NavigationToolbar2 object %p", (void*)self); -#else - return PyString_FromFormat("NavigationToolbar2 object %p", (void*)self); -#endif -} - -static char NavigationToolbar2_doc[] = -"NavigationToolbar2\n"; - -static PyObject* -NavigationToolbar2_set_message(NavigationToolbar2 *self, PyObject* args) -{ - const char* message; - -#if PY3K - if(!PyArg_ParseTuple(args, "y", &message)) return NULL; -#else - if(!PyArg_ParseTuple(args, "s", &message)) return NULL; -#endif - - NSText* messagebox = self->messagebox; - - if (messagebox) - { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSString* text = [NSString stringWithUTF8String: message]; - [messagebox setString: text]; - [pool release]; - } - - Py_RETURN_NONE; -} - -static PyMethodDef NavigationToolbar2_methods[] = { - {"set_message", - (PyCFunction)NavigationToolbar2_set_message, - METH_VARARGS, - "Set the message to be displayed on the toolbar." - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject NavigationToolbar2Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_macosx.NavigationToolbar2", /*tp_name*/ - sizeof(NavigationToolbar2), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)NavigationToolbar2_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)NavigationToolbar2_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - NavigationToolbar2_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NavigationToolbar2_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)NavigationToolbar2_init, /* tp_init */ - 0, /* tp_alloc */ - NavigationToolbar2_new, /* tp_new */ -}; - -static PyObject* -choose_save_file(PyObject* unused, PyObject* args) -{ - int result; - const char* title; - char* default_filename; - if(!PyArg_ParseTuple(args, "ses", &title, "UTF-8", &default_filename)) - return NULL; - - NSSavePanel* panel = [NSSavePanel savePanel]; - [panel setTitle: [NSString stringWithCString: title - encoding: NSASCIIStringEncoding]]; - NSString* ns_default_filename = - [[NSString alloc] - initWithCString: default_filename - encoding: NSUTF8StringEncoding]; - PyMem_Free(default_filename); -#ifdef COMPILING_FOR_10_6 - [panel setNameFieldStringValue: ns_default_filename]; - result = [panel runModal]; -#else - result = [panel runModalForDirectory: nil file: ns_default_filename]; -#endif - [ns_default_filename release]; -#ifdef COMPILING_FOR_10_10 - if (result == NSModalResponseOK) -#else - if (result == NSOKButton) -#endif - { -#ifdef COMPILING_FOR_10_6 - NSURL* url = [panel URL]; - NSString* filename = [url path]; - if (!filename) { - PyErr_SetString(PyExc_RuntimeError, "Failed to obtain filename"); - return 0; - } -#else - NSString* filename = [panel filename]; -#endif - unsigned int n = [filename length]; - unichar* buffer = malloc(n*sizeof(unichar)); - [filename getCharacters: buffer]; -#if PY3K - PyObject* string = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, buffer, n); -#else - PyObject* string = PyUnicode_FromUnicode(buffer, n); -#endif - free(buffer); - return string; - } - Py_RETURN_NONE; -} - -static PyObject* -set_cursor(PyObject* unused, PyObject* args) -{ - int i; - if(!PyArg_ParseTuple(args, "i", &i)) return NULL; - switch (i) - { case 0: [[NSCursor pointingHandCursor] set]; break; - case 1: [[NSCursor arrowCursor] set]; break; - case 2: [[NSCursor crosshairCursor] set]; break; - case 3: [[NSCursor openHandCursor] set]; break; - /* OSX handles busy state itself so no need to set a cursor here */ - case 4: break; - default: return NULL; - } - Py_RETURN_NONE; -} - -@implementation WindowServerConnectionManager -static WindowServerConnectionManager *sharedWindowServerConnectionManager = nil; - -+ (WindowServerConnectionManager *)sharedManager -{ - if (sharedWindowServerConnectionManager == nil) - { - sharedWindowServerConnectionManager = [[super allocWithZone:NULL] init]; - } - return sharedWindowServerConnectionManager; -} - -+ (id)allocWithZone:(NSZone *)zone -{ - return [[self sharedManager] retain]; -} - -+ (id)copyWithZone:(NSZone *)zone -{ - return self; -} - -+ (id)retain -{ - return self; -} - -- (NSUInteger)retainCount -{ - return NSUIntegerMax; //denotes an object that cannot be released -} - -- (oneway void)release -{ - // Don't release a singleton object -} - -- (id)autorelease -{ - return self; -} - -- (void)launch:(NSNotification*)notification -{ - CFRunLoopRef runloop; - CFMachPortRef port; - CFRunLoopSourceRef source; - NSDictionary* dictionary = [notification userInfo]; - if (! [[dictionary valueForKey:@"NSApplicationName"] - isEqualToString:@"Python"]) - return; - NSNumber* psnLow = [dictionary valueForKey: @"NSApplicationProcessSerialNumberLow"]; - NSNumber* psnHigh = [dictionary valueForKey: @"NSApplicationProcessSerialNumberHigh"]; - ProcessSerialNumber psn; - psn.highLongOfPSN = [psnHigh intValue]; - psn.lowLongOfPSN = [psnLow intValue]; - runloop = CFRunLoopGetCurrent(); - port = CGEventTapCreateForPSN(&psn, - kCGHeadInsertEventTap, - kCGEventTapOptionListenOnly, - kCGEventMaskForAllEvents, - &_eventtap_callback, - runloop); - source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, - port, - 0); - CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode); - CFRelease(port); -} -@end - -@implementation Window -- (Window*)initWithContentRect:(NSRect)rect styleMask:(unsigned int)mask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation withManager: (PyObject*)theManager -{ - self = [super initWithContentRect: rect - styleMask: mask - backing: bufferingType - defer: deferCreation]; - manager = theManager; - Py_INCREF(manager); - return self; -} - -- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen -{ - /* Allow window sizes larger than the screen */ - NSRect suggested = [super constrainFrameRect: rect toScreen: screen]; - const CGFloat difference = rect.size.height - suggested.size.height; - suggested.origin.y -= difference; - suggested.size.height += difference; - return suggested; -} - -- (BOOL)closeButtonPressed -{ - PyObject* result; - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(manager, "close", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); - return YES; -} - -- (void)close -{ - [super close]; - --FigureWindowCount; - if (!FigureWindowCount) [NSApp stop: self]; - /* This is needed for show(), which should exit from [NSApp run] - * after all windows are closed. - */ -} - -- (void)dealloc -{ - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - Py_DECREF(manager); - PyGILState_Release(gstate); - /* The reference count of the view that was added as a subview to the - * content view of this window was increased during the call to addSubview, - * and is decreased during the call to [super dealloc]. - */ - [super dealloc]; -} -@end - -@implementation ToolWindow -- (ToolWindow*)initWithContentRect:(NSRect)rect master:(NSWindow*)window -{ - [self initWithContentRect: rect - styleMask: NSTitledWindowMask - | NSClosableWindowMask - | NSResizableWindowMask - | NSMiniaturizableWindowMask - backing: NSBackingStoreBuffered - defer: YES]; - [self setTitle: @"Subplot Configuration Tool"]; - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector(masterCloses:) - name: NSWindowWillCloseNotification - object: window]; - return self; -} - -- (void)masterCloses:(NSNotification*)notification -{ - [self close]; -} - -- (void)close -{ - [[NSNotificationCenter defaultCenter] removeObserver: self]; - [super close]; -} -@end - -@implementation View -- (BOOL)isFlipped -{ - return NO; -} - -- (View*)initWithFrame:(NSRect)rect -{ - self = [super initWithFrame: rect]; - rubberband = NSZeroRect; - inside = false; - tracking = 0; - device_scale = 1; - return self; -} - -- (void)dealloc -{ - FigureCanvas* fc = (FigureCanvas*)canvas; - if (fc) fc->view = NULL; - [self removeTrackingRect: tracking]; - [super dealloc]; -} - -- (void)setCanvas: (PyObject*)newCanvas -{ - canvas = newCanvas; -} - -static void _buffer_release(void* info, const void* data, size_t size) { - PyBuffer_Release((Py_buffer *)info); -} - -static int _copy_agg_buffer(CGContextRef cr, PyObject *renderer) -{ - Py_buffer buffer; - - if (PyObject_GetBuffer(renderer, &buffer, PyBUF_CONTIG_RO) == -1) { - PyErr_Print(); - return 1; - } - - if (buffer.ndim != 3 || buffer.shape[2] != 4) { - PyBuffer_Release(&buffer); - return 1; - } - - const Py_ssize_t nrows = buffer.shape[0]; - const Py_ssize_t ncols = buffer.shape[1]; - const size_t bytesPerComponent = 1; - const size_t bitsPerComponent = 8 * bytesPerComponent; - const size_t nComponents = 4; /* red, green, blue, alpha */ - const size_t bitsPerPixel = bitsPerComponent * nComponents; - const size_t bytesPerRow = nComponents * bytesPerComponent * ncols; - - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if (!colorspace) { - PyBuffer_Release(&buffer); - return 1; - } - - CGDataProviderRef provider = CGDataProviderCreateWithData(&buffer, - buffer.buf, - buffer.len, - _buffer_release); - if (!provider) { - PyBuffer_Release(&buffer); - CGColorSpaceRelease(colorspace); - return 1; - } - - CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast; - CGImageRef bitmap = CGImageCreate(ncols, - nrows, - bitsPerComponent, - bitsPerPixel, - bytesPerRow, - colorspace, - bitmapInfo, - provider, - NULL, - false, - kCGRenderingIntentDefault); - CGColorSpaceRelease(colorspace); - CGDataProviderRelease(provider); - - if (!bitmap) { - PyBuffer_Release(&buffer); - return 1; - } - - CGFloat deviceScale = _get_device_scale(cr); - CGContextSaveGState(cr); - CGContextDrawImage(cr, CGRectMake(0, 0, ncols/deviceScale, nrows/deviceScale), bitmap); - CGImageRelease(bitmap); - CGContextRestoreGState(cr); - - return 0; -} - --(void)drawRect:(NSRect)rect -{ - PyObject* renderer = NULL; - PyObject* renderer_buffer = NULL; - - PyGILState_STATE gstate = PyGILState_Ensure(); - - CGContextRef cr = [[NSGraphicsContext currentContext] graphicsPort]; - - double new_device_scale = _get_device_scale(cr); - - if (device_scale != new_device_scale) { - device_scale = new_device_scale; - if (!PyObject_CallMethod(canvas, "_set_device_scale", "d", device_scale, NULL)) { - PyErr_Print(); - goto exit; - } - } - - renderer = PyObject_CallMethod(canvas, "_draw", "", NULL); - if (!renderer) - { - PyErr_Print(); - goto exit; - } - - renderer_buffer = PyObject_GetAttrString(renderer, "_renderer"); - if (!renderer_buffer) { - PyErr_Print(); - goto exit; - } - - if (_copy_agg_buffer(cr, renderer_buffer)) { - printf("copy_agg_buffer failed\n"); - goto exit; - } - - - if (!NSIsEmptyRect(rubberband)) { - NSFrameRect(rubberband); - } - - exit: - Py_XDECREF(renderer_buffer); - Py_XDECREF(renderer); - - PyGILState_Release(gstate); -} - -- (void)windowDidResize: (NSNotification*)notification -{ - int width, height; - Window* window = [notification object]; - NSSize size = [[window contentView] frame].size; - NSRect rect = [self frame]; - - size.height -= rect.origin.y; - width = size.width; - height = size.height; - - [self setFrameSize: size]; - - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod( - canvas, "resize", "ii", width, height); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); - if (tracking) [self removeTrackingRect: tracking]; - tracking = [self addTrackingRect: [self bounds] - owner: self - userData: nil - assumeInside: NO]; - [self setNeedsDisplay: YES]; -} - -- (void)windowWillClose:(NSNotification*)notification -{ - PyGILState_STATE gstate; - PyObject* result; - - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "close_event", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); -} - -- (BOOL)windowShouldClose:(NSNotification*)notification -{ - NSWindow* window = [self window]; - NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined - location: NSZeroPoint - modifierFlags: 0 - timestamp: 0.0 - windowNumber: 0 - context: nil - subtype: WINDOW_CLOSING - data1: 0 - data2: 0]; - [NSApp postEvent: event atStart: true]; - if ([window respondsToSelector: @selector(closeButtonPressed)]) - { BOOL closed = [((Window*) window) closeButtonPressed]; - /* If closed, the window has already been closed via the manager. */ - if (closed) return NO; - } - return YES; -} - -- (void)mouseEntered:(NSEvent *)event -{ - PyGILState_STATE gstate; - PyObject* result; - NSWindow* window = [self window]; - if ([window isKeyWindow]==false) return; - - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "enter_notify_event", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); - - [window setAcceptsMouseMovedEvents: YES]; - inside = true; -} - -- (void)mouseExited:(NSEvent *)event -{ - PyGILState_STATE gstate; - PyObject* result; - NSWindow* window = [self window]; - if ([window isKeyWindow]==false) return; - - if (inside==false) return; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "leave_notify_event", ""); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - PyGILState_Release(gstate); - - [[self window] setAcceptsMouseMovedEvents: NO]; - inside = false; -} - -- (void)mouseDown:(NSEvent *)event -{ - int x, y; - int num; - int dblclick = 0; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - switch ([event type]) - { case NSLeftMouseDown: - { unsigned int modifier = [event modifierFlags]; - if (modifier & NSControlKeyMask) - /* emulate a right-button click */ - num = 3; - else if (modifier & NSAlternateKeyMask) - /* emulate a middle-button click */ - num = 2; - else - { - num = 1; - if ([NSCursor currentCursor]==[NSCursor openHandCursor]) - [[NSCursor closedHandCursor] set]; - } - break; - } - case NSOtherMouseDown: num = 2; break; - case NSRightMouseDown: num = 3; break; - default: return; /* Unknown mouse event */ - } - if ([event clickCount] == 2) { - dblclick = 1; - } - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)mouseUp:(NSEvent *)event -{ - int num; - int x, y; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - switch ([event type]) - { case NSLeftMouseUp: - num = 1; - if ([NSCursor currentCursor]==[NSCursor closedHandCursor]) - [[NSCursor openHandCursor] set]; - break; - case NSOtherMouseUp: num = 2; break; - case NSRightMouseUp: num = 3; break; - default: return; /* Unknown mouse event */ - } - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "button_release_event", "iii", x, y, num); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)mouseMoved:(NSEvent *)event -{ - int x, y; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod(canvas, "motion_notify_event", "ii", x, y); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)mouseDragged:(NSEvent *)event -{ - int x, y; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod(canvas, "motion_notify_event", "ii", x, y); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)rightMouseDown:(NSEvent *)event -{ - int x, y; - int num = 3; - int dblclick = 0; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - gstate = PyGILState_Ensure(); - if ([event clickCount] == 2) { - dblclick = 1; - } - result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)rightMouseUp:(NSEvent *)event -{ - int x, y; - int num = 3; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "button_release_event", "iii", x, y, num); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)rightMouseDragged:(NSEvent *)event -{ - int x, y; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod(canvas, "motion_notify_event", "ii", x, y); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)otherMouseDown:(NSEvent *)event -{ - int x, y; - int num = 2; - int dblclick = 0; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - gstate = PyGILState_Ensure(); - if ([event clickCount] == 2) { - dblclick = 1; - } - result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)otherMouseUp:(NSEvent *)event -{ - int x, y; - int num = 2; - PyObject* result; - PyGILState_STATE gstate; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "button_release_event", "iii", x, y, num); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)otherMouseDragged:(NSEvent *)event -{ - int x, y; - NSPoint location = [event locationInWindow]; - location = [self convertPoint: location fromView: nil]; - x = location.x * device_scale; - y = location.y * device_scale; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod(canvas, "motion_notify_event", "ii", x, y); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)setRubberband:(NSRect)rect -{ - if (!NSIsEmptyRect(rubberband)) [self setNeedsDisplayInRect: rubberband]; - rubberband = rect; - [self setNeedsDisplayInRect: rubberband]; -} - -- (void)removeRubberband -{ - if (NSIsEmptyRect(rubberband)) return; - [self setNeedsDisplayInRect: rubberband]; - rubberband = NSZeroRect; -} - - - -- (const char*)convertKeyEvent:(NSEvent*)event -{ - NSDictionary* specialkeymappings = [NSDictionary dictionaryWithObjectsAndKeys: - @"left", [NSNumber numberWithUnsignedLong:NSLeftArrowFunctionKey], - @"right", [NSNumber numberWithUnsignedLong:NSRightArrowFunctionKey], - @"up", [NSNumber numberWithUnsignedLong:NSUpArrowFunctionKey], - @"down", [NSNumber numberWithUnsignedLong:NSDownArrowFunctionKey], - @"f1", [NSNumber numberWithUnsignedLong:NSF1FunctionKey], - @"f2", [NSNumber numberWithUnsignedLong:NSF2FunctionKey], - @"f3", [NSNumber numberWithUnsignedLong:NSF3FunctionKey], - @"f4", [NSNumber numberWithUnsignedLong:NSF4FunctionKey], - @"f5", [NSNumber numberWithUnsignedLong:NSF5FunctionKey], - @"f6", [NSNumber numberWithUnsignedLong:NSF6FunctionKey], - @"f7", [NSNumber numberWithUnsignedLong:NSF7FunctionKey], - @"f8", [NSNumber numberWithUnsignedLong:NSF8FunctionKey], - @"f9", [NSNumber numberWithUnsignedLong:NSF9FunctionKey], - @"f10", [NSNumber numberWithUnsignedLong:NSF10FunctionKey], - @"f11", [NSNumber numberWithUnsignedLong:NSF11FunctionKey], - @"f12", [NSNumber numberWithUnsignedLong:NSF12FunctionKey], - @"f13", [NSNumber numberWithUnsignedLong:NSF13FunctionKey], - @"f14", [NSNumber numberWithUnsignedLong:NSF14FunctionKey], - @"f15", [NSNumber numberWithUnsignedLong:NSF15FunctionKey], - @"f16", [NSNumber numberWithUnsignedLong:NSF16FunctionKey], - @"f17", [NSNumber numberWithUnsignedLong:NSF17FunctionKey], - @"f18", [NSNumber numberWithUnsignedLong:NSF18FunctionKey], - @"f19", [NSNumber numberWithUnsignedLong:NSF19FunctionKey], - @"scroll_lock", [NSNumber numberWithUnsignedLong:NSScrollLockFunctionKey], - @"break", [NSNumber numberWithUnsignedLong:NSBreakFunctionKey], - @"insert", [NSNumber numberWithUnsignedLong:NSInsertFunctionKey], - @"delete", [NSNumber numberWithUnsignedLong:NSDeleteFunctionKey], - @"home", [NSNumber numberWithUnsignedLong:NSHomeFunctionKey], - @"end", [NSNumber numberWithUnsignedLong:NSEndFunctionKey], - @"pagedown", [NSNumber numberWithUnsignedLong:NSPageDownFunctionKey], - @"pageup", [NSNumber numberWithUnsignedLong:NSPageUpFunctionKey], - @"backspace", [NSNumber numberWithUnsignedLong:NSDeleteCharacter], - @"enter", [NSNumber numberWithUnsignedLong:NSEnterCharacter], - @"tab", [NSNumber numberWithUnsignedLong:NSTabCharacter], - @"enter", [NSNumber numberWithUnsignedLong:NSCarriageReturnCharacter], - @"backtab", [NSNumber numberWithUnsignedLong:NSBackTabCharacter], - @"escape", [NSNumber numberWithUnsignedLong:27], - nil - ]; - - NSMutableString* returnkey = [NSMutableString string]; - if ([event modifierFlags] & NSControlKeyMask) - [returnkey appendString:@"ctrl+" ]; - if ([event modifierFlags] & NSAlternateKeyMask) - [returnkey appendString:@"alt+" ]; - if ([event modifierFlags] & NSCommandKeyMask) - [returnkey appendString:@"cmd+" ]; - - unichar uc = [[event charactersIgnoringModifiers] characterAtIndex:0]; - NSString* specialchar = [specialkeymappings objectForKey:[NSNumber numberWithUnsignedLong:uc]]; - if (specialchar){ - if ([event modifierFlags] & NSShiftKeyMask) - [returnkey appendString:@"shift+" ]; - [returnkey appendString:specialchar]; - } - else - [returnkey appendString:[event charactersIgnoringModifiers]]; - - return [returnkey UTF8String]; -} - -- (void)keyDown:(NSEvent*)event -{ - PyObject* result; - const char* s = [self convertKeyEvent: event]; - PyGILState_STATE gstate = PyGILState_Ensure(); - if (s==NULL) - { - result = PyObject_CallMethod(canvas, "key_press_event", "O", Py_None); - } - else - { - result = PyObject_CallMethod(canvas, "key_press_event", "s", s); - } - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)keyUp:(NSEvent*)event -{ - PyObject* result; - const char* s = [self convertKeyEvent: event]; - PyGILState_STATE gstate = PyGILState_Ensure(); - if (s==NULL) - { - result = PyObject_CallMethod(canvas, "key_release_event", "O", Py_None); - } - else - { - result = PyObject_CallMethod(canvas, "key_release_event", "s", s); - } - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (void)scrollWheel:(NSEvent*)event -{ - int step; - float d = [event deltaY]; - if (d > 0) step = 1; - else if (d < 0) step = -1; - else return; - NSPoint location = [event locationInWindow]; - NSPoint point = [self convertPoint: location fromView: nil]; - int x = (int)round(point.x * device_scale); - int y = (int)round(point.y * device_scale - 1); - - PyObject* result; - PyGILState_STATE gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "scroll_event", "iii", x, y, step); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -/* This is all wrong. Address of pointer is being passed instead of pointer, keynames don't - match up with what the front-end and does the front-end even handle modifier keys by themselves? - -- (void)flagsChanged:(NSEvent*)event -{ - const char *s = NULL; - if (([event modifierFlags] & NSControlKeyMask) == NSControlKeyMask) - s = "control"; - else if (([event modifierFlags] & NSShiftKeyMask) == NSShiftKeyMask) - s = "shift"; - else if (([event modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) - s = "alt"; - else return; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallMethod(canvas, "key_press_event", "s", &s); - if(result) - Py_DECREF(result); - else - PyErr_Print(); - - PyGILState_Release(gstate); -} - */ -@end - -@implementation ScrollableButton -- (void)setScrollWheelUpAction:(SEL)action -{ - scrollWheelUpAction = action; -} - -- (void)setScrollWheelDownAction:(SEL)action -{ - scrollWheelDownAction = action; -} - -- (void)scrollWheel:(NSEvent*)event -{ - float d = [event deltaY]; - Window* target = [self target]; - if (d > 0) - [NSApp sendAction: scrollWheelUpAction to: target from: self]; - else if (d < 0) - [NSApp sendAction: scrollWheelDownAction to: target from: self]; -} -@end - -@implementation MenuItem -+ (MenuItem*)menuItemWithTitle: (NSString*)title -{ - MenuItem* item = [[MenuItem alloc] initWithTitle: title - action: nil - keyEquivalent: @""]; - item->index = -1; - return [item autorelease]; -} - -+ (MenuItem*)menuItemForAxis: (int)i -{ - NSString* title = [NSString stringWithFormat: @"Axis %d", i+1]; - MenuItem* item = [[MenuItem alloc] initWithTitle: title - action: @selector(toggle:) - keyEquivalent: @""]; - [item setTarget: item]; - [item setState: NSOnState]; - item->index = i; - return [item autorelease]; -} - -+ (MenuItem*)menuItemSelectAll -{ - MenuItem* item = [[MenuItem alloc] initWithTitle: @"Select All" - action: @selector(selectAll:) - keyEquivalent: @""]; - [item setTarget: item]; - item->index = -1; - return [item autorelease]; -} - -+ (MenuItem*)menuItemInvertAll -{ - MenuItem* item = [[MenuItem alloc] initWithTitle: @"Invert All" - action: @selector(invertAll:) - keyEquivalent: @""]; - [item setTarget: item]; - item->index = -1; - return [item autorelease]; -} - -- (void)toggle:(id)sender -{ - if ([self state]) [self setState: NSOffState]; - else [self setState: NSOnState]; -} - -- (void)selectAll:(id)sender -{ - NSMenu* menu = [sender menu]; - if(!menu) return; /* Weird */ - NSArray* items = [menu itemArray]; - NSEnumerator* enumerator = [items objectEnumerator]; - MenuItem* item; - while ((item = [enumerator nextObject])) - { - if (item->index >= 0) [item setState: NSOnState]; - } -} - -- (void)invertAll:(id)sender -{ - NSMenu* menu = [sender menu]; - if(!menu) return; /* Weird */ - NSArray* items = [menu itemArray]; - NSEnumerator* enumerator = [items objectEnumerator]; - MenuItem* item; - while ((item = [enumerator nextObject])) - { - if (item->index < 0) continue; - if ([item state]==NSOffState) [item setState: NSOnState]; - else [item setState: NSOffState]; - } -} - -- (int)index -{ - return self->index; -} -@end - -static PyObject* -show(PyObject* self) -{ - [NSApp activateIgnoringOtherApps: YES]; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSArray *windowsArray = [NSApp windows]; - NSEnumerator *enumerator = [windowsArray objectEnumerator]; - NSWindow *window; - while ((window = [enumerator nextObject])) { - [window orderFront:nil]; - } - [pool release]; - Py_BEGIN_ALLOW_THREADS - [NSApp run]; - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} - -typedef struct { - PyObject_HEAD - CFRunLoopTimerRef timer; -} Timer; - -static PyObject* -Timer_new(PyTypeObject* type, PyObject *args, PyObject *kwds) -{ - Timer* self = (Timer*)type->tp_alloc(type, 0); - if (!self) return NULL; - self->timer = NULL; - return (PyObject*) self; -} - -static PyObject* -Timer_repr(Timer* self) -{ -#if PY3K - return PyUnicode_FromFormat("Timer object %p wrapping CFRunLoopTimerRef %p", - (void*) self, (void*)(self->timer)); -#else - return PyString_FromFormat("Timer object %p wrapping CFRunLoopTimerRef %p", - (void*) self, (void*)(self->timer)); -#endif -} - -static char Timer_doc[] = -"A Timer object wraps a CFRunLoopTimerRef and can add it to the event loop.\n"; - -static void timer_callback(CFRunLoopTimerRef timer, void* info) -{ - PyObject* method = info; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* result = PyObject_CallFunction(method, NULL); - if (result) { - Py_DECREF(result); - } else { - PyErr_Print(); - } - PyGILState_Release(gstate); -} - -static void context_cleanup(const void* info) -{ - Py_DECREF((PyObject*)info); -} - -static PyObject* -Timer__timer_start(Timer* self, PyObject* args) -{ - CFRunLoopRef runloop; - CFRunLoopTimerRef timer; - CFRunLoopTimerContext context; - double milliseconds; - CFTimeInterval interval; - PyObject* attribute; - PyObject* failure; - runloop = CFRunLoopGetCurrent(); - if (!runloop) { - PyErr_SetString(PyExc_RuntimeError, "Failed to obtain run loop"); - return NULL; - } - attribute = PyObject_GetAttrString((PyObject*)self, "_interval"); - if (attribute==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_interval'"); - return NULL; - } - milliseconds = PyFloat_AsDouble(attribute); - failure = PyErr_Occurred(); - Py_DECREF(attribute); - if (failure) return NULL; - attribute = PyObject_GetAttrString((PyObject*)self, "_single"); - if (attribute==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_single'"); - return NULL; - } - switch (PyObject_IsTrue(attribute)) { - case 1: - interval = 0; - break; - case 0: - interval = milliseconds / 1000.0; - break; - case -1: - default: - PyErr_SetString(PyExc_ValueError, "Cannot interpret _single attribute as True of False"); - return NULL; - } - Py_DECREF(attribute); - attribute = PyObject_GetAttrString((PyObject*)self, "_on_timer"); - if (attribute==NULL) - { - PyErr_SetString(PyExc_AttributeError, "Timer has no attribute '_on_timer'"); - return NULL; - } - if (!PyMethod_Check(attribute)) { - PyErr_SetString(PyExc_RuntimeError, "_on_timer should be a Python method"); - return NULL; - } - context.version = 0; - context.retain = NULL; - context.release = context_cleanup; - context.copyDescription = NULL; - context.info = attribute; - timer = CFRunLoopTimerCreate(kCFAllocatorDefault, - 0, - interval, - 0, - 0, - timer_callback, - &context); - if (!timer) { - Py_DECREF(attribute); - PyErr_SetString(PyExc_RuntimeError, "Failed to create timer"); - return NULL; - } - if (self->timer) { - CFRunLoopTimerInvalidate(self->timer); - CFRelease(self->timer); - } - CFRunLoopAddTimer(runloop, timer, kCFRunLoopCommonModes); - /* Don't release the timer here, since the run loop may be destroyed and - * the timer lost before we have a chance to decrease the reference count - * of the attribute */ - self->timer = timer; - Py_RETURN_NONE; -} - -static PyObject* -Timer__timer_stop(Timer* self) -{ - if (self->timer) { - CFRunLoopTimerInvalidate(self->timer); - CFRelease(self->timer); - self->timer = NULL; - } - Py_RETURN_NONE; -} - -static void -Timer_dealloc(Timer* self) -{ - Timer__timer_stop(self); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyMethodDef Timer_methods[] = { - {"_timer_start", - (PyCFunction)Timer__timer_start, - METH_VARARGS, - "Initialize and start the timer." - }, - {"_timer_stop", - (PyCFunction)Timer__timer_stop, - METH_NOARGS, - "Stop the timer." - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject TimerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_macosx.Timer", /*tp_name*/ - sizeof(Timer), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)Timer_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)Timer_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - Timer_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Timer_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - Timer_new, /* tp_new */ -}; - -static bool verify_framework(void) -{ -#ifdef COMPILING_FOR_10_6 - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRunningApplication* app = [NSRunningApplication currentApplication]; - NSApplicationActivationPolicy activationPolicy = [app activationPolicy]; - [pool release]; - switch (activationPolicy) { - case NSApplicationActivationPolicyRegular: - case NSApplicationActivationPolicyAccessory: - return true; - case NSApplicationActivationPolicyProhibited: - break; - } -#else - ProcessSerialNumber psn; - if (CGMainDisplayID()!=0 - && GetCurrentProcess(&psn)==noErr - && SetFrontProcess(&psn)==noErr) return true; -#endif - PyErr_SetString(PyExc_RuntimeError, - "Python is not installed as a framework. The Mac OS X backend will " - "not be able to function correctly if Python is not installed as a " - "framework. See the Python documentation for more information on " - "installing Python as a framework on Mac OS X. Please either reinstall " - "Python as a framework, or try one of the other backends. If you are " - "using (Ana)Conda please install python.app and replace the use of 'python' " - "with 'pythonw'. See 'Working with Matplotlib on OSX' " - "in the Matplotlib FAQ for more information."); - return false; -} - -static struct PyMethodDef methods[] = { - {"show", - (PyCFunction)show, - METH_NOARGS, - "Show all the figures and enter the main loop.\nThis function does not return until all Matplotlib windows are closed,\nand is normally not needed in interactive sessions." - }, - {"choose_save_file", - (PyCFunction)choose_save_file, - METH_VARARGS, - "Closes the window." - }, - {"set_cursor", - (PyCFunction)set_cursor, - METH_VARARGS, - "Sets the active cursor." - }, - {NULL, NULL, 0, NULL}/* sentinel */ -}; - -#if PY3K - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_macosx", - "Mac OS X native backend", - -1, - methods, - NULL, - NULL, - NULL, - NULL -}; - -PyObject* PyInit__macosx(void) - -#else - -void init_macosx(void) -#endif -{ - PyObject *module; - - if (PyType_Ready(&FigureCanvasType) < 0 - || PyType_Ready(&FigureManagerType) < 0 - || PyType_Ready(&NavigationToolbarType) < 0 - || PyType_Ready(&NavigationToolbar2Type) < 0 - || PyType_Ready(&TimerType) < 0) -#if PY3K - return NULL; -#else - return; -#endif - - NSApp = [NSApplication sharedApplication]; - - if (!verify_framework()) -#if PY3K - return NULL; -#else - return; -#endif - -#if PY3K - module = PyModule_Create(&moduledef); - if (module==NULL) return NULL; -#else - module = Py_InitModule4("_macosx", - methods, - "Mac OS X native backend", - NULL, - PYTHON_API_VERSION); -#endif - - Py_INCREF(&FigureCanvasType); - Py_INCREF(&FigureManagerType); - Py_INCREF(&NavigationToolbarType); - Py_INCREF(&NavigationToolbar2Type); - Py_INCREF(&TimerType); - PyModule_AddObject(module, "FigureCanvas", (PyObject*) &FigureCanvasType); - PyModule_AddObject(module, "FigureManager", (PyObject*) &FigureManagerType); - PyModule_AddObject(module, "NavigationToolbar", (PyObject*) &NavigationToolbarType); - PyModule_AddObject(module, "NavigationToolbar2", (PyObject*) &NavigationToolbar2Type); - PyModule_AddObject(module, "Timer", (PyObject*) &TimerType); - - PyOS_InputHook = wait_for_stdin; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - WindowServerConnectionManager* connectionManager = [WindowServerConnectionManager sharedManager]; - NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; - NSNotificationCenter* notificationCenter = [workspace notificationCenter]; - [notificationCenter addObserver: connectionManager - selector: @selector(launch:) - name: NSWorkspaceDidLaunchApplicationNotification - object: nil]; - [pool release]; -#if PY3K - return module; -#endif -} |