/usr/share/pyshared/kivy/uix/modalview.py is in python-kivy 1.7.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | '''
ModalView
=========
.. versionadded:: 1.4.0
The :class:`ModalView` widget is used to create modal views. By default, the
view will cover the whole "parent" window.
Remember that the default size of a Widget is size_hint=(1, 1). If you don't
want your view to be fullscreen, either use lower than 1 size hints (for
instance size_hint=(.8, .8)) or deactivate the size_hint and use fixed size
attributes.
Examples
--------
Example of a simple 400x400 Hello world view::
view = ModalView(size_hint=(None, None), size=(400, 400))
view.add_widget(Label(text='Hello world'))
By default, any click outside the view will dismiss it. If you don't
want that, you can set :data:`ModalView.auto_dismiss` to False::
view = ModalView(auto_dismiss=False)
view.add_widget(Label(text='Hello world'))
view.open()
To manually dismiss/close the view, use :meth:`ModalView.dismiss`::
ModalView.dismiss()
The :meth:`ModalView.open` and :meth:`ModalView.dismiss` are bindable. That
means you can directly bind the function to an action, e.g., to a button's
on_press ::
# create content and assign to the view
content = Button(text='Close me!')
view = ModalView(auto_dismiss=False)
view.add_widget(content)
# bind the on_press event of the button to the dismiss function
content.bind(on_press=view.dismiss)
# open the view
view.open()
ModalView Events
----------------
There are two events available: `on_open` when the view is opening, and
`on_dismiss` when it is closed. For `on_dismiss`, you can prevent the
view from closing by explictly returning True from your callback ::
def my_callback(instance):
print 'ModalView', instance, 'is being dismissed, but is prevented!'
return True
view = ModalView()
view.add_widget(Label(text='Hello world'))
view.bind(on_dismiss=my_callback)
view.open()
.. versionchanged:: 1.5.0
The ModalView can be closed by hitting escape key on the keyboard, if the
:data:`ModalView.auto_dismiss` is allowed.
'''
__all__ = ('ModalView', )
from kivy.logger import Logger
from kivy.animation import Animation
from kivy.uix.anchorlayout import AnchorLayout
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty, \
NumericProperty, ListProperty
class ModalView(AnchorLayout):
'''ModalView class. See module documentation for more information.
:Events:
`on_open`:
Fired when the ModalView is opened
`on_dismiss`:
Fired when the ModalView is closed. If the callback returns True,
the dismiss will be canceled.
'''
auto_dismiss = BooleanProperty(True)
'''Default to True, this property determines if the view is automatically
dismissed when the user clicks outside it.
:data:`auto_dismiss` is a :class:`~kivy.properties.BooleanProperty`,
default to True.
'''
attach_to = ObjectProperty(None)
'''If a widget is set on attach_to, the view will attach to the nearest
parent window of the widget. If none is found, it will attach to the
main/global Window.
:data:`attach_to` is a :class:`~kivy.properties.ObjectProperty`, default to
None.
'''
background_color = ListProperty([0, 0, 0, .7])
'''Background color, in the format (r, g, b, a).
:data:`background_color` is a :class:`~kivy.properties.ListProperty`,
default to [0, 0, 0, .7].
'''
background = StringProperty(
'atlas://data/images/defaulttheme/modalview-background')
'''Background image of the view used for the view background.
:data:`background` is an :class:`~kivy.properties.StringProperty`,
default to 'atlas://data/images/defaulttheme/modalview-background'
'''
border = ListProperty([16, 16, 16, 16])
'''Border used for :class:`~kivy.graphics.vertex_instructions.BorderImage`
graphics instruction. Used for :data:`background_normal` and
:data:`background_down`. Can be used when using custom background.
It must be a list of four values: (top, right, bottom, left). Read the
BorderImage instructions for more information about how to use it.
:data:`border` is a :class:`~kivy.properties.ListProperty`, default to (16,
16, 16, 16)
'''
# Internals properties used for graphical representation.
_anim_alpha = NumericProperty(0)
_anim_duration = NumericProperty(.1)
_window = ObjectProperty(None, allownone=True)
__events__ = ('on_open', 'on_dismiss')
def __init__(self, **kwargs):
self._parent = None
super(ModalView, self).__init__(**kwargs)
def _search_window(self):
# get window to attach to
window = None
if self.attach_to is not None:
window = self.attach_to.get_parent_window()
if not window:
window = self.attach_to.get_root_window()
if not window:
from kivy.core.window import Window
window = Window
return window
def open(self, *largs):
'''Show the view window from the :data:`attach_to` widget. If set, it
will attach to the nearest window. If the widget is not attached to any
window, the view will attach to the global
:class:`~kivy.core.window.Window`.
'''
if self._window is not None:
Logger.warning('ModalView: you can only open once.')
return self
# search window
self._window = self._search_window()
if not self._window:
Logger.warning('ModalView: cannot open view, no window found.')
return self
self._window.add_widget(self)
self._window.bind(
on_resize=self._align_center,
on_keyboard=self._handle_keyboard)
self.center = self._window.center
self.bind(size=self._update_center)
a = Animation(_anim_alpha=1., d=self._anim_duration)
a.bind(on_complete=lambda *x: self.dispatch('on_open'))
a.start(self)
return self
def _update_center(self, *args):
if not self._window:
return
# XXX HACK DONT REMOVE OR FOUND AND FIX THE ISSUE
# It seems that if we don't access to the center before assigning a new
# value, no dispatch will be done >_>
a = self.center
self.center = self._window.center
def dismiss(self, *largs, **kwargs):
'''Close the view if it is open. If you really want to close the
view, whatever the on_dismiss event returns, you can do this:
::
view = ModalView(...)
view.dismiss(force=True)
When the view is dismissed, it will be faded out, before
removal from the parent. If you don't want animation, use:
view.dismiss(animation=False)
'''
if self._window is None:
return self
if self.dispatch('on_dismiss') is True:
if kwargs.get('force', False) is not True:
return self
if kwargs.get('animation', True):
Animation(_anim_alpha=0., d=self._anim_duration).start(self)
else:
self._anim_alpha = 0
self._real_remove_widget()
return self
def on_size(self, instance, value):
self._align_center()
def _align_center(self, *l):
if self._window:
self.center = self._window.center
# hack to resize dark background on window resize
_window = self._window
self._window = None
self._window = _window
def on_touch_down(self, touch):
if not self.collide_point(*touch.pos):
if self.auto_dismiss:
self.dismiss()
return True
super(ModalView, self).on_touch_down(touch)
return True
def on_touch_move(self, touch):
super(ModalView, self).on_touch_move(touch)
return True
def on_touch_up(self, touch):
super(ModalView, self).on_touch_up(touch)
return True
def on__anim_alpha(self, instance, value):
if value == 0 and self._window is not None:
self._real_remove_widget()
def _real_remove_widget(self):
if self._window is None:
return
self._window.remove_widget(self)
self._window.unbind(
on_resize=self._align_center,
on_keyboard=self._handle_keyboard)
self._window = None
def on_open(self):
pass
def on_dismiss(self):
pass
def _handle_keyboard(self, window, key, *largs):
if key == 27 and self.auto_dismiss:
self.dismiss()
return True
if __name__ == '__main__':
from kivy.base import runTouchApp
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
# add view
content = GridLayout(cols=1)
content.add_widget(Label(text='This is a hello world'))
view = ModalView(size_hint=(None, None), size=(256, 256), auto_dismiss=True)
view.add_widget(content)
def open_view(btn):
view.open()
layout = GridLayout(cols=3)
for x in xrange(9):
btn = Button(text='click me %s' % x)
btn.bind(on_release=view.open)
layout.add_widget(btn)
Window.add_widget(layout)
view.open()
runTouchApp()
|