diff options
Diffstat (limited to 'mvc/widgets/osx/window.py')
-rw-r--r-- | mvc/widgets/osx/window.py | 896 |
1 files changed, 0 insertions, 896 deletions
diff --git a/mvc/widgets/osx/window.py b/mvc/widgets/osx/window.py deleted file mode 100644 index b959333..0000000 --- a/mvc/widgets/osx/window.py +++ /dev/null @@ -1,896 +0,0 @@ -# @Base: Miro - an RSS based video player application -# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 -# Participatory Culture Foundation -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. - -""".window -- Top-level Window class. """ - -import logging - -from AppKit import * -from Foundation import * -from objc import YES, NO, nil -from PyObjCTools import AppHelper - -from mvc import signals -from mvc.widgets import widgetconst -import wrappermap -import osxmenus -from .helpers import NotificationForwarder -from .base import Widget, FlippedView -from .layout import VBox, HBox, Alignment -from .control import Button -from .simple import Label -from .rect import Rect, NSRectWrapper -from .utils import filename_to_unicode - -# Tracks all windows that haven't been destroyed. This makes sure there -# object stay alive as long as the window is alive. -alive_windows = set() - -class MiroResponderInterceptor(NSResponder): - """Intercepts cocoa events and gives our wrappers and chance to handle - them first. - """ - - def initWithResponder_(self, responder): - """Initialize a MiroResponderInterceptor - - We will give the wrapper for responder a chance to handle the event, - then pass it along to responder. - """ - self = super(MiroResponderInterceptor, self).init() - self.responder = responder - return self - - def keyDown_(self, event): - if self.sendKeyDownToWrapper_(event): - return # signal handler returned True, stop processing - - # If our responder is the last in the chain, we can stop intercepting - if self.responder.nextResponder() is None: - self.responder.keyDown_(event) - return - - # Here's the tricky part, we want to call keyDown_ on our responder, - # but if it doesn't handle the event, then it will pass it along to - # it's next responder. We need to set things up so that we will - # intercept that call. - - # Make a new MiroResponderInterceptor whose responder is the next - # responder down the chain. - next_intercepter = MiroResponderInterceptor.alloc().initWithResponder_( - self.responder.nextResponder()) - # Install the interceptor - self.responder.setNextResponder_(next_intercepter) - # Send event along - self.responder.keyDown_(event) - # Restore old nextResponder value - self.responder.setNextResponder_(next_intercepter.responder) - - def sendKeyDownToWrapper_(self, event): - """Give a keyDown event to the wrapper for our responder - - Return True if the wrapper handled the event - """ - key = event.charactersIgnoringModifiers() - if len(key) != 1 or not key.isalnum(): - key = osxmenus.REVERSE_KEYS_MAP.get(key) - mods = osxmenus.translate_event_modifiers(event) - wrapper = wrappermap.wrapper(self.responder) - if isinstance(wrapper, Widget) or isinstance(wrapper, Window): - if wrapper.emit('key-press', key, mods): - return True - return False - -class MiroWindow(NSWindow): - def initWithContentRect_styleMask_backing_defer_(self, rect, mask, - backing, defer): - self = NSWindow.initWithContentRect_styleMask_backing_defer_(self, - rect, mask, backing, defer) - self._last_focus_chain = None - return self - - def handleKeyDown_(self, event): - if self.handle_tab_navigation(event): - return - interceptor = MiroResponderInterceptor.alloc().initWithResponder_( - self.firstResponder()) - interceptor.keyDown_(event) - - def handle_tab_navigation(self, event): - """Handle tab navigation through the window. - - :returns: True if we handled the event - """ - keystr = event.charactersIgnoringModifiers() - if keystr[0] == NSTabCharacter: - # handle cycling through views with Tab. - self.focusNextKeyView_(True) - return True - elif keystr[0] == NSBackTabCharacter: - self.focusNextKeyView_(False) - return True - return False - - def acceptsMouseMovedEvents(self): - # HACK: for some reason calling setAcceptsMouseMovedEvents_() doesn't - # work, we have to forcefully override this method. - return NO - - def sendEvent_(self, event): - if event.type() == NSKeyDown: - self.handleKeyDown_(event) - else: - NSWindow.sendEvent_(self, event) - - def _calc_current_focus_wrapper(self): - responder = self.firstResponder() - while responder: - wrapper = wrappermap.wrapper(responder) - # check if we have a wrapper for the view, if not try the parent - # view - if wrapper is not None: - return wrapper - responder = responder.superview() - return None - - def focusNextKeyView_(self, is_forward): - current_focus = self._calc_current_focus_wrapper() - my_wrapper = wrappermap.wrapper(self) - next_focus = my_wrapper.get_next_tab_focus(current_focus, is_forward) - if next_focus is not None: - next_focus.focus() - - def draggingEntered_(self, info): - wrapper = wrappermap.wrapper(self) - return wrapper.draggingEntered_(info) or NSDragOperationNone - - def draggingUpdated_(self, info): - wrapper = wrappermap.wrapper(self) - return wrapper.draggingUpdated_(info) or NSDragOperationNone - - def draggingExited_(self, info): - wrapper = wrappermap.wrapper(self) - wrapper.draggingExited_(info) - - def prepareForDragOperation_(self, info): - wrapper = wrappermap.wrapper(self) - return wrapper.prepareForDragOperation_(info) or NO - - def performDragOperation_(self, info): - wrapper = wrappermap.wrapper(self) - return wrapper.performDragOperation_(info) or NO - -class MainMiroWindow(MiroWindow): - def isMovableByWindowBackground(self): - return YES - -class Window(signals.SignalEmitter): - """See https://develop.participatoryculture.org/index.php/WidgetAPI for a description of the API for this class.""" - def __init__(self, title, rect=None): - signals.SignalEmitter.__init__(self) - self.create_signal('active-change') - self.create_signal('will-close') - self.create_signal('did-move') - self.create_signal('key-press') - self.create_signal('show') - self.create_signal('hide') - self.create_signal('on-shown') - self.create_signal('file-drag-motion') - self.create_signal('file-drag-received') - self.create_signal('file-drag-leave') - self.is_closing = False - if rect is None: - rect = Rect(0, 0, 470, 600) - self.nswindow = MainMiroWindow.alloc().initWithContentRect_styleMask_backing_defer_( - rect.nsrect, - self.get_style_mask(), - NSBackingStoreBuffered, - NO) - self.nswindow.setTitle_(title) - self.nswindow.setMinSize_(NSSize(470, 600)) - self.nswindow.setReleasedWhenClosed_(NO) - self.content_view = FlippedView.alloc().initWithFrame_(rect.nsrect) - self.content_view.setAutoresizesSubviews_(NO) - self.nswindow.setContentView_(self.content_view) - self.content_widget = None - self.view_notifications = NotificationForwarder.create(self.content_view) - self.view_notifications.connect(self.on_frame_change, 'NSViewFrameDidChangeNotification') - self.window_notifications = NotificationForwarder.create(self.nswindow) - self.window_notifications.connect(self.on_activate, 'NSWindowDidBecomeMainNotification') - self.window_notifications.connect(self.on_deactivate, 'NSWindowDidResignMainNotification') - self.window_notifications.connect(self.on_did_move, 'NSWindowDidMoveNotification') - self.window_notifications.connect(self.on_will_close, 'NSWindowWillCloseNotification') - wrappermap.add(self.nswindow, self) - alive_windows.add(self) - - def get_next_tab_focus(self, current, is_forward): - """Return the next widget to cycle through for keyboard focus - - Subclasses can override this to for find-grained control of keyboard - focus. - - :param current: currently-focused widget - :param is_forward: are we tabbing forward? - """ - return None - - # XXX Use MainWindow not Window for MVCStyle/MiroStyle - def get_style_mask(self): - return (NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask) - - def set_title(self, title): - self.nswindow.setTitle_(title) - - def get_title(self): - return self.nswindow.title() - - def on_frame_change(self, notification): - self.place_child() - - def on_activate(self, notification): - self.emit('active-change') - - def on_deactivate(self, notification): - self.emit('active-change') - - def on_did_move(self, notification): - self.emit('did-move') - - def on_will_close(self, notification): - # unset the first responder. This allows text entry widgets to get - # the NSControlTextDidEndEditingNotification - if self.is_closing: - logging.info('on_will_close: already closing') - return - self.is_closing = True - self.nswindow.makeFirstResponder_(nil) - self.emit('will-close') - self.emit('hide') - self.is_closing = False - - def is_active(self): - return self.nswindow.isMainWindow() - - def is_visible(self): - return self.nswindow.isVisible() - - def show(self): - if self not in alive_windows: - raise ValueError("Window destroyed") - self.nswindow.makeKeyAndOrderFront_(nil) - self.nswindow.makeMainWindow() - self.emit('show') - # Cocoa doesn't apply default selections as forcefully as GTK, so - # currently there's no need for on-shown to actually wait until the - # window has been shown here - self.emit('on-shown') - - def close(self): - self.nswindow.close() - - def destroy(self): - self.close() - self.window_notifications.disconnect() - self.view_notifications.disconnect() - self.nswindow.setContentView_(nil) - wrappermap.remove(self.nswindow) - alive_windows.discard(self) - self.nswindow = None - - def place_child(self): - rect = self.nswindow.contentRectForFrameRect_(self.nswindow.frame()) - self.content_widget.place(NSRect(NSPoint(0, 0), rect.size), - self.content_view) - - def hookup_content_widget_signals(self): - self.size_req_handler = self.content_widget.connect('size-request-changed', - self.on_content_widget_size_request_change) - - def unhook_content_widget_signals(self): - self.content_widget.disconnect(self.size_req_handler) - self.size_req_handler = None - - def on_content_widget_size_request_change(self, widget, old_size): - self.update_size_constraints() - - def set_content_widget(self, widget): - if self.content_widget: - self.content_widget.remove_viewport() - self.unhook_content_widget_signals() - self.content_widget = widget - self.hookup_content_widget_signals() - self.place_child() - self.update_size_constraints() - - def update_size_constraints(self): - width, height = self.content_widget.get_size_request() - # It is possible the window is torn down between the size invalidate - # request and the actual size invalidation invocation. So check - # to see if nswindow is there if not then do not do anything. - if self.nswindow: - # FIXME: I'm not sure that this code does what we want it to do. - # It enforces the min-size when the user drags the window, but I - # think it should also call setContentSize_ if the window is - # currently too small to fit the content - BDK - self.nswindow.setContentMinSize_(NSSize(width, height)) - rect = self.nswindow.contentRectForFrameRect_(self.nswindow.frame()) - if rect.size.width < width or rect.size.height < height: - logging.warn("Content widget too large for this window " - "size available: %dx%d widget size: %dx%d", - rect.size.width, rect.size.height, width, height) - - def get_content_widget(self): - return self.content_widget - - def get_frame(self): - frame = self.nswindow.frame() - frame.size.height -= 22 - return NSRectWrapper(frame) - - def connect_menu_keyboard_shortcuts(self): - # All OS X windows are connected to the menu shortcuts - pass - - def accept_file_drag(self, val): - if not val: - self.drag_dest = None - else: - self.drag_dest = NSDragOperationCopy - self.nswindow.registerForDraggedTypes_([NSFilenamesPboardType]) - - def prepareForDragOperation_(self, info): - return NO if self.drag_dest is None else YES - - def performDragOperation_(self, info): - pb = info.draggingPasteboard() - available_types = set(pb.types()) & set([NSFilenamesPboardType]) - drag_ok = False - if available_types: - type_ = available_types.pop() - # DANCE! Everybody dance for portable Python code! - values = [unicode( - NSURL.fileURLWithPath_(v).filePathURL()).encode('utf-8') - for v in list(pb.propertyListForType_(type_))] - self.emit('file-drag-received', values) - drag_ok = True - self.draggingExited_(info) - return drag_ok - - def draggingEntered_(self, info): - return self.draggingUpdated_(info) - - def draggingUpdated_(self, info): - self.emit('file-drag-motion') - return self.drag_dest - - def draggingExited_(self, info): - self.emit('file-drag-leave') - - def center(self): - self.nswindow.center() - -class MainWindow(Window): - def __init__(self, title, rect): - Window.__init__(self, title, rect) - self.nswindow.setReleasedWhenClosed_(NO) - - def close(self): - self.nswindow.orderOut_(nil) - -class DialogBase(object): - def __init__(self): - self.sheet_parent = None - def set_transient_for(self, window): - self.sheet_parent = window - -class MiroPanel(NSPanel): - def cancelOperation_(self, event): - wrappermap.wrapper(self).end_with_code(-1) - -class Dialog(DialogBase): - def __init__(self, title, description=None): - DialogBase.__init__(self) - self.title = title - self.description = description - self.buttons = [] - self.extra_widget = None - self.window = None - self.running = False - - def add_button(self, text): - button = Button(text) - button.set_size(widgetconst.SIZE_NORMAL) - button.connect('clicked', self.on_button_clicked, len(self.buttons)) - self.buttons.append(button) - - def on_button_clicked(self, button, code): - self.end_with_code(code) - - def end_with_code(self, code): - if self.sheet_parent is not None: - NSApp().endSheet_returnCode_(self.window, code) - else: - NSApp().stopModalWithCode_(code) - - def build_text(self): - vbox = VBox(spacing=6) - if self.description is not None: - description_label = Label(self.description, wrap=True) - description_label.set_bold(True) - description_label.set_size_request(360, -1) - vbox.pack_start(description_label) - return vbox - - def build_buttons(self): - hbox = HBox(spacing=12) - for button in reversed(self.buttons): - hbox.pack_start(button) - alignment = Alignment(xalign=1.0, yscale=1.0) - alignment.add(hbox) - return alignment - - def build_content(self): - vbox = VBox(spacing=12) - vbox.pack_start(self.build_text()) - if self.extra_widget: - vbox.pack_start(self.extra_widget) - vbox.pack_start(self.build_buttons()) - alignment = Alignment(xscale=1.0, yscale=1.0) - alignment.set_padding(12, 12, 17, 17) - alignment.add(vbox) - return alignment - - def build_window(self): - self.content_widget = self.build_content() - width, height = self.content_widget.get_size_request() - width = max(width, 400) - window = MiroPanel.alloc() - window.initWithContentRect_styleMask_backing_defer_( - NSMakeRect(400, 400, width, height), - NSTitledWindowMask, NSBackingStoreBuffered, NO) - view = FlippedView.alloc().initWithFrame_(NSMakeRect(0, 0, width, - height)) - window.setContentView_(view) - window.setTitle_(self.title) - self.content_widget.place(view.frame(), view) - if self.buttons: - self.buttons[0].make_default() - return window - - def hookup_content_widget_signals(self): - self.size_req_handler = self.content_widget.connect( - 'size-request-changed', - self.on_content_widget_size_request_change) - - def unhook_content_widget_signals(self): - self.content_widget.disconnect(self.size_req_handler) - self.size_req_handler = None - - def on_content_widget_size_request_change(self, widget, old_size): - width, height = self.content_widget.get_size_request() - # It is possible the window is torn down between the size invalidate - # request and the actual size invalidation invocation. So check - # to see if nswindow is there if not then do not do anything. - if self.window and (width, height) != old_size: - self.change_content_size(width, height) - - def change_content_size(self, width, height): - content_rect = self.window.contentRectForFrameRect_( - self.window.frame()) - # Cocoa's coordinate system is funky, adjust y so that the top stays - # in place - content_rect.origin.y += (content_rect.size.height - height) - # change our frame to fit the new content. It would be nice to - # animate the change, but timers don't work when we are displaying a - # modal dialog - content_rect.size = NSSize(width, height) - new_frame = self.window.frameRectForContentRect_(content_rect) - self.window.setFrame_display_(new_frame, NO) - # Need to call place() again, since our window has changed size - contentView = self.window.contentView() - self.content_widget.place(contentView.frame(), contentView) - - def run(self): - self.window = self.build_window() - wrappermap.add(self.window, self) - self.hookup_content_widget_signals() - self.running = True - if self.sheet_parent is None: - response = NSApp().runModalForWindow_(self.window) - if self.window: - self.window.close() - else: - delegate = SheetDelegate.alloc().init() - NSApp().beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_( - self.window, self.sheet_parent.nswindow, - delegate, 'sheetDidEnd:returnCode:contextInfo:', 0) - response = NSApp().runModalForWindow_(self.window) - if self.window: - # self.window won't be around if we call destroy() to cancel - # the dialog - self.window.orderOut_(nil) - self.running = False - self.unhook_content_widget_signals() - - if response < 0: - return -1 - return response - - def destroy(self): - if self.running: - NSApp().stopModalWithCode_(-1) - - if self.window is not None: - self.window.setContentView_(None) - self.window.close() - self.window = None - self.buttons = None - self.extra_widget = None - - def set_extra_widget(self, widget): - self.extra_widget = widget - - def get_extra_widget(self): - return self.extra_widget - -class SheetDelegate(NSObject): - @AppHelper.endSheetMethod - def sheetDidEnd_returnCode_contextInfo_(self, sheet, return_code, info): - NSApp().stopModalWithCode_(return_code) - -class FileDialogBase(DialogBase): - def __init__(self): - DialogBase.__init__(self) - self._types = None - self._filename = None - self._directory = None - self._filter_on_run = True - - def run(self): - self._panel.setAllowedFileTypes_(self._types) - if self.sheet_parent is None: - if self._filter_on_run: - response = self._panel.runModalForDirectory_file_types_(self._directory, self._filename, self._types) - else: - response = self._panel.runModalForDirectory_file_(self._directory, self._filename) - else: - delegate = SheetDelegate.alloc().init() - if self._filter_on_run: - self._panel.beginSheetForDirectory_file_types_modalForWindow_modalDelegate_didEndSelector_contextInfo_( - self._directory, self._filename, self._types, - self.sheet_parent.nswindow, delegate, 'sheetDidEnd:returnCode:contextInfo:', 0) - else: - self._panel.beginSheetForDirectory_file_modalForWindow_modalDelegate_didEndSelector_contextInfo_( - self._directory, self._filename, - self.sheet_parent.nswindow, delegate, 'sheetDidEnd:returnCode:contextInfo:', 0) - response = NSApp().runModalForWindow_(self._panel) - self._panel.orderOut_(nil) - return response - -class FileSaveDialog(FileDialogBase): - def __init__(self, title): - FileDialogBase.__init__(self) - self._title = title - self._panel = NSSavePanel.savePanel() - self._panel.setCanChooseFiles_(YES) - self._panel.setCanChooseDirectories_(NO) - self._filename = None - self._filter_on_run = False - - def set_filename(self, s): - self._filename = filename_to_unicode(s) - - def get_filename(self): - # Use encode('utf-8') instead of unicode_to_filename, because - # unicode_to_filename has code to make sure nextFilename works, but it's - # more important here to not change the filename. - return self._filename.encode('utf-8') - - def run(self): - response = FileDialogBase.run(self) - if response == NSFileHandlingPanelOKButton: - self._filename = self._panel.filename() - return 0 - self._filename = "" - - def destroy(self): - self._panel = None - - set_path = set_filename - get_path = get_filename - -class FileOpenDialog(FileDialogBase): - def __init__(self, title): - FileDialogBase.__init__(self) - self._title = title - self._panel = NSOpenPanel.openPanel() - self._panel.setCanChooseFiles_(YES) - self._panel.setCanChooseDirectories_(NO) - self._filenames = None - - def set_select_multiple(self, value): - if value: - self._panel.setAllowsMultipleSelection_(YES) - else: - self._panel.setAllowsMultipleSelection_(NO) - - def set_directory(self, d): - self._directory = filename_to_unicode(d) - - def set_filename(self, s): - self._filename = filename_to_unicode(s) - - def add_filters(self, filters): - self._types = [] - for _, t in filters: - self._types += t - - def get_filename(self): - if self._filenames is None: - # canceled - return None - return self.get_filenames()[0] - - def get_filenames(self): - if self._filenames is None: - # canceled - return [] - # Use encode('utf-8') instead of unicode_to_filename, because - # unicode_to_filename has code to make sure nextFilename works, but it's - # more important here to not change the filename. - return [f.encode('utf-8') for f in self._filenames] - - def run(self): - response = FileDialogBase.run(self) - if response == NSFileHandlingPanelOKButton: - self._filenames = self._panel.filenames() - return 0 - self._filename = '' - self._filenames = None - - def destroy(self): - self._panel = None - - set_path = set_filename - get_path = get_filename - -class DirectorySelectDialog(FileDialogBase): - def __init__(self, title): - FileDialogBase.__init__(self) - self._title = title - self._panel = NSOpenPanel.openPanel() - self._panel.setCanChooseFiles_(NO) - self._panel.setCanChooseDirectories_(YES) - self._directory = None - - def set_directory(self, d): - self._directory = filename_to_unicode(d) - - def get_directory(self): - # Use encode('utf-8') instead of unicode_to_filename, because - # unicode_to_filename has code to make sure nextFilename - # works, but it's more important here to not change the - # filename. - return self._directory.encode('utf-8') - - def run(self): - response = FileDialogBase.run(self) - if response == NSFileHandlingPanelOKButton: - self._directory = self._panel.filenames()[0] - return 0 - self._directory = "" - - def destroy(self): - self._panel = None - - set_path = set_directory - get_path = get_directory - -class AboutDialog(DialogBase): - def run(self): - optionsDictionary = dict() - #revision = app.config.get(prefs.APP_REVISION_NUM) - #if revision: - # optionsDictionary['Version'] = revision - if not optionsDictionary: - optionsDictionary = nil - NSApplication.sharedApplication().orderFrontStandardAboutPanelWithOptions_(optionsDictionary) - def destroy(self): - pass - -class AlertDialog(DialogBase): - def __init__(self, title, message, alert_type): - DialogBase.__init__(self) - self._nsalert = NSAlert.alloc().init(); - self._nsalert.setMessageText_(title) - self._nsalert.setInformativeText_(message) - self._nsalert.setAlertStyle_(alert_type) - def add_button(self, text): - self._nsalert.addButtonWithTitle_(text) - def run(self): - self._nsalert.runModal() - def destroy(self): - self._nsalert = nil - -class PreferenceItem(NSToolbarItem): - - def setPanel_(self, panel): - self.panel = panel - -class PreferenceToolbarDelegate(NSObject): - - def initWithPanels_identifiers_window_(self, panels, identifiers, window): - self = super(PreferenceToolbarDelegate, self).init() - self.panels = panels - self.identifiers = identifiers - self.window = window - return self - - def toolbarAllowedItemIdentifiers_(self, toolbar): - return self.identifiers - - def toolbarDefaultItemIdentifiers_(self, toolbar): - return self.identifiers - - def toolbarSelectableItemIdentifiers_(self, toolbar): - return self.identifiers - - def toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_(self, toolbar, - itemIdentifier, - flag): - panel = self.panels[itemIdentifier] - item = PreferenceItem.alloc().initWithItemIdentifier_(itemIdentifier) - item.setLabel_(unicode(panel[1])) - item.setImage_(NSImage.imageNamed_(u"pref_tab_%s" % itemIdentifier)) - item.setAction_("switchPreferenceView:") - item.setTarget_(self) - item.setPanel_(panel[0]) - return item - - def validateToolbarItem_(self, item): - return YES - - def switchPreferenceView_(self, sender): - self.window.do_select_panel(sender.panel, YES) - -class DialogWindow(Window): - def __init__(self, title, rect, allow_miniaturize=False): - self.allow_miniaturize = allow_miniaturize - Window.__init__(self, title, rect) - self.nswindow.setShowsToolbarButton_(NO) - - def get_style_mask(self): - mask = (NSTitledWindowMask | NSClosableWindowMask) - if self.allow_miniaturize: - mask |= NSMiniaturizableWindowMask - return mask - -class DonateWindow(Window): - def __init__(self, title): - Window.__init__(self, title, Rect(0, 0, 640, 440)) - self.panels = dict() - self.identifiers = list() - self.first_show = True - self.nswindow.setShowsToolbarButton_(NO) - self.nswindow.setReleasedWhenClosed_(NO) - self.app_notifications = NotificationForwarder.create(NSApp()) - self.app_notifications.connect(self.on_app_quit, - 'NSApplicationWillTerminateNotification') - - def destroy(self): - super(PreferencesWindow, self).destroy() - self.app_notifications.disconnect() - - def get_style_mask(self): - return (NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask) - - def show(self): - if self.first_show: - self.nswindow.center() - self.first_show = False - Window.show(self) - - def on_app_quit(self, notification): - self.close() - -class PreferencesWindow(Window): - def __init__(self, title): - Window.__init__(self, title, Rect(0, 0, 640, 440)) - self.panels = dict() - self.identifiers = list() - self.first_show = True - self.nswindow.setShowsToolbarButton_(NO) - self.nswindow.setReleasedWhenClosed_(NO) - self.app_notifications = NotificationForwarder.create(NSApp()) - self.app_notifications.connect(self.on_app_quit, - 'NSApplicationWillTerminateNotification') - - def destroy(self): - super(PreferencesWindow, self).destroy() - self.app_notifications.disconnect() - - def get_style_mask(self): - return (NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask) - - def append_panel(self, name, panel, title, image_name): - self.panels[name] = (panel, title) - self.identifiers.append(name) - - def finish_panels(self): - self.tbdelegate = PreferenceToolbarDelegate.alloc().initWithPanels_identifiers_window_(self.panels, self.identifiers, self) - toolbar = NSToolbar.alloc().initWithIdentifier_(u"Preferences") - toolbar.setAllowsUserCustomization_(NO) - toolbar.setDelegate_(self.tbdelegate) - - self.nswindow.setToolbar_(toolbar) - - def select_panel(self, index): - panel = self.identifiers[index] - self.nswindow.toolbar().setSelectedItemIdentifier_(panel) - self.do_select_panel(self.panels[panel][0], NO) - - def do_select_panel(self, panel, animate): - wframe = self.nswindow.frame() - vsize = list(panel.get_size_request()) - if vsize[0] < 650: - vsize[0] = 650 - if vsize[1] < 200: - vsize[1] = 200 - - toolbarHeight = wframe.size.height - self.nswindow.contentView().frame().size.height - wframe.origin.y += wframe.size.height - vsize[1] - toolbarHeight - wframe.size = (vsize[0], vsize[1] + toolbarHeight) - - self.set_content_widget(panel) - self.nswindow.setFrame_display_animate_(wframe, YES, animate) - - def show(self): - if self.first_show: - self.nswindow.center() - self.first_show = False - Window.show(self) - - def on_app_quit(self, notification): - self.close() - -def get_first_time_dialog_coordinates(width, height): - """Returns the coordinates for the first time dialog. - """ - # windowFrame is None on first run. in that case, we want - # to put librevideoconverter in the middle. - mainscreen = NSScreen.mainScreen() - rect = mainscreen.frame() - - x = (rect.size.width - width) / 2 - y = (rect.size.height - height) / 2 - - return x, y |