aboutsummaryrefslogtreecommitdiffstats
path: root/mvc/widgets/osx/window.py
diff options
context:
space:
mode:
Diffstat (limited to 'mvc/widgets/osx/window.py')
-rw-r--r--mvc/widgets/osx/window.py896
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