aboutsummaryrefslogtreecommitdiffstats
path: root/mvc/widgets/osx/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'mvc/widgets/osx/base.py')
-rw-r--r--mvc/widgets/osx/base.py367
1 files changed, 0 insertions, 367 deletions
diff --git a/mvc/widgets/osx/base.py b/mvc/widgets/osx/base.py
deleted file mode 100644
index 913b372..0000000
--- a/mvc/widgets/osx/base.py
+++ /dev/null
@@ -1,367 +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.
-
-""".base.py -- Widget base classes."""
-
-from AppKit import *
-from Foundation import *
-from objc import YES, NO, nil
-
-from mvc import signals
-import wrappermap
-from .viewport import Viewport, BorrowedViewport
-
-class Widget(signals.SignalEmitter):
- """Base class for Cocoa widgets.
-
- attributes:
-
- CREATES_VIEW -- Does the widget create a view for itself? If this is True
- the widget must have an attribute named view, which is the view that the
- widget uses.
-
- placement -- What portion of view the widget occupies.
- """
-
- CREATES_VIEW = True
-
- def __init__(self):
- signals.SignalEmitter.__init__(self, 'size-request-changed',
- 'size-allocated', 'key-press', 'focus-out')
- self.create_signal('place-in-scroller')
- self.viewport = None
- self.parent_is_scroller = False
- self.manual_size_request = None
- self.cached_size_request = None
- self._disabled = False
-
- def set_can_focus(self, allow):
- assert isinstance(self.view, NSControl)
- self.view.setRefusesFirstResponder_(not allow)
-
- def set_size_request(self, width, height):
- self.manual_size_request = (width, height)
- self.invalidate_size_request()
-
- def clear_size_request_cache(self):
- from mvc.widgets.osx import size_request_manager
- if size_request_manager is not None:
- while size_request_manager.widgets_to_request:
- size_request_manager._run_requests()
-
- def get_size_request(self):
- if self.manual_size_request:
- width, height = self.manual_size_request
- if width == -1:
- width = self.get_natural_size_request()[0]
- if height == -1:
- height = self.get_natural_size_request()[1]
- return width, height
- return self.get_natural_size_request()
-
- def get_natural_size_request(self):
- if self.cached_size_request:
- return self.cached_size_request
- else:
- self.cached_size_request = self.calc_size_request()
- return self.cached_size_request
-
- def invalidate_size_request(self):
- from mvc.widgets.osx import size_request_manager
- if size_request_manager is not None:
- size_request_manager.add_widget(self)
-
- def do_invalidate_size_request(self):
- """Recalculate the size request for this widget."""
- old_size_request = self.cached_size_request
- self.cached_size_request = None
- self.emit('size-request-changed', old_size_request)
-
- def calc_size_request(self):
- """Return the minimum size needed to display this widget.
- Must be Implemented by subclasses.
- """
- raise NotImplementedError()
-
- def _debug_size_request(self, nesting_level=0):
- """Debug size request calculations.
-
- This method recursively prints out the size request for each widget.
- """
- request = self.calc_size_request()
- width = int(request[0])
- height = int(request[1])
- indent = ' ' * nesting_level
- me = str(self.__class__).split('.')[-1]
- print '%s%s: %sx%s' % (indent, me, width, height)
-
- def place(self, rect, containing_view):
- """Place this widget on a view. """
- if self.viewport is None:
- if self.CREATES_VIEW:
- self.viewport = Viewport(self.view, rect)
- containing_view.addSubview_(self.view)
- wrappermap.add(self.view, self)
- else:
- self.viewport = BorrowedViewport(containing_view, rect)
- self.viewport_created()
- else:
- if not self.viewport.at_position(rect):
- self.viewport.reposition(rect)
- self.viewport_repositioned()
- self.emit('size-allocated', rect.size.width, rect.size.height)
-
- def remove_viewport(self):
- if self.viewport is not None:
- self.viewport.remove()
- self.viewport = None
- if self.CREATES_VIEW:
- wrappermap.remove(self.view)
-
- def viewport_created(self):
- """Called after we first create a viewport. Subclasses can override
- this method if they want to handle this event.
- """
-
- def viewport_repositioned(self):
- """Called when we reposition our viewport. Subclasses can override
- this method if they want to handle this event.
- """
-
- def viewport_scrolled(self):
- """Called by the Scroller widget on it's child widget when it is
- scrolled.
- """
-
- def get_width(self):
- return int(self.viewport.get_width())
- width = property(get_width)
-
- def get_height(self):
- return int(self.viewport.get_height())
- height = property(get_height)
-
- def get_window(self):
- if not self.viewport.view:
- return None
- return wrappermap.wrapper(self.viewport.view.window())
-
- def queue_redraw(self):
- if self.viewport:
- self.viewport.queue_redraw()
-
- def redraw_now(self):
- if self.viewport:
- self.viewport.redraw_now()
-
- def relative_position(self, other_widget):
- """Get the position of another widget, relative to this widget."""
- basePoint = self.viewport.view.convertPoint_fromView_(
- other_widget.viewport.area().origin,
- other_widget.viewport.view)
- return (basePoint.x - self.viewport.area().origin.x,
- basePoint.y - self.viewport.area().origin.y)
-
- def make_color(self, (red, green, blue)):
- return NSColor.colorWithDeviceRed_green_blue_alpha_(red, green, blue,
- 1.0)
-
- def enable(self):
- self._disabled = False
-
- def disable(self):
- self._disabled = True
-
- def set_disabled(self, disabled):
- if disabled:
- self.disable()
- else:
- self.enable()
-
- def get_disabled(self):
- return self._disabled
-
-class Container(Widget):
- """Widget that holds other widgets. """
-
- def __init__(self):
- Widget.__init__(self)
- self.callback_handles = {}
-
- def on_child_size_request_changed(self, child, old_size):
- self.invalidate_size_request()
-
- def connect_child_signals(self, child):
- handle = child.connect_weak('size-request-changed',
- self.on_child_size_request_changed)
- self.callback_handles[child] = handle
-
- def disconnect_child_signals(self, child):
- child.disconnect(self.callback_handles.pop(child))
-
- def remove_viewport(self):
- for child in self.children:
- child.remove_viewport()
- Widget.remove_viewport(self)
-
- def child_added(self, child):
- """Must be called by subclasses when a child is added to the
- Container."""
- self.connect_child_signals(child)
- self.children_changed()
-
- def child_removed(self, child):
- """Must be called by subclasses when a child is removed from the
- Container."""
- self.disconnect_child_signals(child)
- child.remove_viewport()
- self.children_changed()
-
- def child_changed(self, old_child, new_child):
- """Must be called by subclasses when a child is replaced by a new
- child in the Container. To simplify things a bit for subclasses,
- old_child can be None in which case this is the same as
- child_added(new_child).
- """
- if old_child is not None:
- self.disconnect_child_signals(old_child)
- old_child.remove_viewport()
- self.connect_child_signals(new_child)
- self.children_changed()
-
- def children_changed(self):
- """Invoked when the set of children for this widget changes."""
- self.do_invalidate_size_request()
-
- def do_invalidate_size_request(self):
- Widget.do_invalidate_size_request(self)
- if self.viewport:
- self.place_children()
-
- def viewport_created(self):
- self.place_children()
-
- def viewport_repositioned(self):
- self.place_children()
-
- def viewport_scrolled(self):
- for child in self.children:
- child.viewport_scrolled()
-
- def place_children(self):
- """Layout our child widgets. Must be implemented by subclasses."""
- raise NotImplementedError()
-
- def _debug_size_request(self, nesting_level=0):
- for child in self.children:
- child._debug_size_request(nesting_level+1)
- Widget._debug_size_request(self, nesting_level)
-
-class Bin(Container):
- """Container that only has one child widget."""
-
- def __init__(self, child=None):
- Container.__init__(self)
- self.child = None
- if child is not None:
- self.add(child)
-
- def get_children(self):
- if self.child:
- return [self.child]
- else:
- return []
- children = property(get_children)
-
- def add(self, child):
- if self.child is not None:
- raise ValueError("Already have a child: %s" % self.child)
- self.child = child
- self.child_added(self.child)
-
- def remove(self):
- if self.child is not None:
- old_child = self.child
- self.child = None
- self.child_removed(old_child)
-
- def set_child(self, new_child):
- old_child = self.child
- self.child = new_child
- self.child_changed(old_child, new_child)
-
- def enable(self):
- Container.enable(self)
- self.child.enable()
-
- def disable(self):
- Container.disable(self)
- self.child.disable()
-
-class SimpleBin(Bin):
- """Bin that whose child takes up it's entire space."""
-
- def calc_size_request(self):
- if self.child is None:
- return (0, 0)
- else:
- return self.child.get_size_request()
-
- def place_children(self):
- if self.child:
- self.child.place(self.viewport.area(), self.viewport.view)
-
-class FlippedView(NSView):
- """Flipped NSView. We use these internally to lessen the differences
- between Cocoa and GTK.
- """
-
- def init(self):
- self = super(FlippedView, self).init()
- self.background = None
- return self
-
- def initWithFrame_(self, rect):
- self = super(FlippedView, self).initWithFrame_(rect)
- self.background = None
- return self
-
- def isFlipped(self):
- return YES
-
- def isOpaque(self):
- return self.background is not None
-
- def setBackgroundColor_(self, color):
- self.background = color
-
- def drawRect_(self, rect):
- if self.background:
- self.background.set()
- NSBezierPath.fillRect_(rect)