diff --git a/doc/sources/faq.rst b/doc/sources/faq.rst index e0be489c3..ad693de45 100644 --- a/doc/sources/faq.rst +++ b/doc/sources/faq.rst @@ -63,6 +63,15 @@ This message error can happen in many cases. Ensure that: In case of USB Mass Storage mode error, and if you don't want to keep unplugging the device, set the usb option to Power. +Crash on touch interaction on Android 2.3.x +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There have been reports of crashes on Adreno 200/205 based devices. +Apps otherwise run fine but crash when interacted with/through the screen. + +These reports also mentioned the issue being resolved when moving to a ICS or +higher rom. + Is it possible to have a kiosk app on android 3.0 ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/sources/installation/installation.rst b/doc/sources/installation/installation.rst index 16520c864..ea975ebc4 100644 --- a/doc/sources/installation/installation.rst +++ b/doc/sources/installation/installation.rst @@ -129,7 +129,7 @@ one .) Kivy tests are based on nosetest, that you can install from your package manager or using pip : - $ pip install nosetest + $ pip install nose to run the test suite, do : diff --git a/examples/demo/showcase/showcase.kv b/examples/demo/showcase/showcase.kv index ac6b43bd6..41f0efcc8 100644 --- a/examples/demo/showcase/showcase.kv +++ b/examples/demo/showcase/showcase.kv @@ -208,25 +208,27 @@ text: 'Sliders' Slider: - value: 33 + value: 25 size_hint_y: None height: 50 Slider: - value: 66 + value: 75 size_hint_y: None height: 50 + step: 25 BoxLayout: Slider: orientation: 'vertical' - value: 33 + value: 25 Slider: orientation: 'vertical' - value: 66 + value: 75 + step: 25 HSeparator: text: 'Progress Bar' diff --git a/kivy/__init__.py b/kivy/__init__.py index b638db6b2..2a6a013e8 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -28,7 +28,7 @@ __all__ = ( 'kivy_config_fn', 'kivy_usermodules_dir', ) -__version__ = '1.4.0-dev' +__version__ = '1.4.1-dev' import sys import shutil diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 25aa8834f..e2dfca6fe 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -153,7 +153,7 @@ class LabelBase(object): def resolve_font_name(self): options = self.options - fontname = self.options['font_name'] + fontname = options['font_name'] fonts = self._fonts fontscache = self._fonts_cache @@ -396,19 +396,18 @@ class LabelBase(object): sz[1] + self.options['padding_y'] * 2 def _get_text(self): - return self._text + try: + return self._text.decode('utf8') + except AttributeError: + # python 3 support + return str(self._text) + except UnicodeEncodeError: + return self._text def _set_text(self, text): - if text == self._text: - return - # try to automaticly decode unicode - try: - self._text = text.decode('utf8') - except: - try: - self._text = str(text) - except: - self._text = text + if text != self._text: + self._text = text + text = property(_get_text, _set_text, doc='Get/Set the text') label = property(_get_text, _set_text, doc='Get/Set the text') diff --git a/kivy/factory_registers.py b/kivy/factory_registers.py index 1de8ae812..e020e7ce5 100644 --- a/kivy/factory_registers.py +++ b/kivy/factory_registers.py @@ -80,6 +80,7 @@ r('Button', module='kivy.uix.button') r('Bubble', module='kivy.uix.bubble') r('BubbleButton', module='kivy.uix.bubble') r('Camera', module='kivy.uix.camera') +r('Carousel', module='kivy.uix.carousel') r('CheckBox', module='kivy.uix.checkbox') r('DropDown', module='kivy.uix.dropdown') r('FloatLayout', module='kivy.uix.floatlayout') diff --git a/kivy/uix/camera.py b/kivy/uix/camera.py index 81eb5dfb9..c707a9cf1 100644 --- a/kivy/uix/camera.py +++ b/kivy/uix/camera.py @@ -96,6 +96,8 @@ class Camera(Image): self._camera = None if self.index < 0: return + if self.resolution[0] < 0 or self.resolution[1] < 0: + return self._camera = CoreCamera(index=self.index, resolution=self.resolution, stopped=True) self._camera.bind(on_load=self._camera_loaded) diff --git a/kivy/uix/carousel.py b/kivy/uix/carousel.py index d5684ffa4..805949c56 100644 --- a/kivy/uix/carousel.py +++ b/kivy/uix/carousel.py @@ -9,6 +9,20 @@ where you can swipe between slides. You can add any content to the carousel and use it horizontally or verticaly. The carousel can display pages in loop or not. +Example:: + + class Example1(App): + + def build(self): + carousel = Carousel(direction='right') + for i in range(10): + src = "http://placehold.it/480x270.png&text=slide-%d&.png" % i + image = Factory.AsyncImage(source=src, allow_stretch=True) + carousel.add_widget(image) + return carousel + + Example1().run() + ''' __all__ = ('Carousel', ) @@ -22,12 +36,14 @@ from kivy.properties import BooleanProperty, OptionProperty, AliasProperty, \ class Carousel(StencilView): + '''Carousel class. See module documentation for more information. + ''' slides = ListProperty([]) - ''' List of slides inside the carousel. The slides are added when a - widget is added to Carousel using add_widget(). + '''List of slides inside the carousel. The slides are added when a widget is + added to Carousel using add_widget(). - :data: `slides` is a list of `~kivy.ui.relativelayout.RelativeLayout` + :data:`slides` is a list of :class:`~kivy.ui.relativelayout.RelativeLayout` widgets containing the content added through add_widget. ''' diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py index 98edbe3d9..6a8933f96 100644 --- a/kivy/uix/screenmanager.py +++ b/kivy/uix/screenmanager.py @@ -11,8 +11,8 @@ Screen Manager The screen manager is a widget dedicated to manage multiple screens on your application. The default :class:`ScreenManager` displays only one -:class:`Screen` at time, and use a :class:`TransitionBase` to switch from one to -another Screen. +:class:`Screen` at time, and use a :class:`TransitionBase` to switch from one +to another Screen. Multiple transitions are supported, based of moving the screen coordinate / scale, or even do fancy animation using custom shaders. @@ -102,9 +102,10 @@ You can easily switch to a new transition by changing the .. note:: Currently, all Shader based Transition doesn't have any anti-aliasing. This - is because we are using FBO, and don't have any logic to do supersampling on - them. This is a know issue, and working to have a transparent implementation - that will give the same result as it would be rendered on the screen. + is because we are using FBO, and don't have any logic to do supersampling + on them. This is a know issue, and working to have a transparent + implementation that will give the same result as it would be rendered on + the screen. To be more concrete, if you see sharped-text during the animation, it's normal. @@ -145,7 +146,7 @@ class Screen(RelativeLayout): :data:`name` is a :class:`~kivy.properties.StringProperty`, default to '' ''' - manager = ObjectProperty() + manager = ObjectProperty(None, allownone=True) '''Screen manager object, set when the screen is added within a manager. :data:`manager` is a :class:`~kivy.properties.ObjectProperty`, default to @@ -156,8 +157,8 @@ class Screen(RelativeLayout): '''Value that represent the completion of the current transition, if any is occuring. - If a transition is going on, whatever is the mode, the value will got from 0 - to 1. If you want to know if it's an entering or leaving animation, check + If a transition is going on, whatever is the mode, the value will got from + 0 to 1. If you want to know if it's an entering or leaving animation, check the :data:`transition_state` :data:`transition_progress` is a :class:`~kivy.properties.NumericProperty`, @@ -212,8 +213,8 @@ class TransitionBase(EventDispatcher): duration = NumericProperty(.7) '''Duration in seconds of the transition. - :class:`duration` is a :class:`~kivy.properties.NumericProperty`, default to - .7 (= 700ms) + :class:`duration` is a :class:`~kivy.properties.NumericProperty`, default + to .7 (= 700ms) ''' manager = ObjectProperty() @@ -223,11 +224,11 @@ class TransitionBase(EventDispatcher): None, read-only. ''' - is_active = BooleanProperty() + is_active = BooleanProperty(False) '''Indicate if the transition is currently active - :data:`is_active` is a :class:`~kivy.properties.BooleanProperty`, default to - False, read-only. + :data:`is_active` is a :class:`~kivy.properties.BooleanProperty`, default + to False, read-only. ''' # privates @@ -299,12 +300,11 @@ class TransitionBase(EventDispatcher): class ShaderTransition(TransitionBase): - '''Transition class that use a Shader for animating the transition between 2 - screens. By default, this class doesn't any assign fragment/vertex shader. - - If you want to create your own fragment shader for transition, you need to - declare the header yourself, and include the "t", "tex_in" and "tex_out" - uniform:: + '''Transition class that use a Shader for animating the transition between + 2 screens. By default, this class doesn't any assign fragment/vertex + shader. If you want to create your own fragment shader for transition, you + need to declare the header yourself, and include the "t", "tex_in" and + "tex_out" uniform:: # Create your own transition. This is shader implement a "fading" # transition. @@ -389,8 +389,8 @@ class SlideTransition(TransitionBase): direction = OptionProperty('left', options=('left', 'right', 'up', 'down')) '''Direction of the transition. - :data:`direction` is an :class:`~kivy.properties.OptionProperty`, default to - left. Can be one of 'left', 'right', 'up' or 'down'. + :data:`direction` is an :class:`~kivy.properties.OptionProperty`, default + to left. Can be one of 'left', 'right', 'up' or 'down'. ''' def on_progress(self, progression): @@ -524,8 +524,8 @@ class ScreenManager(FloatLayout): sm.add_widget(Screen(name='first')) sm.add_widget(Screen(name='second')) - # by default, the first added screen will be showed. If you want to show - # another one, just set the current string: + # by default, the first added screen will be showed. If you want to + show # another one, just set the current string: sm.current = 'second' ''' @@ -536,15 +536,15 @@ class ScreenManager(FloatLayout): For example, if you want to change to a :class:`WipeTransition`:: - from kivy.uix.screenmanager import ScreenManager, Screen, WipeTransition + from kivy.uix.screenmanager import ScreenManager, Screen, + WipeTransition sm = ScreenManager(transition=WipeTransition()) sm.add_widget(Screen(name='first')) sm.add_widget(Screen(name='second')) - # by default, the first added screen will be showed. If you want to show - # another one, just set the current string: - sm.current = 'second' + # by default, the first added screen will be showed. If you want to + show another one, just set the current string: sm.current = 'second' ''' screens = ListProperty() @@ -598,6 +598,23 @@ class ScreenManager(FloatLayout): if self.current is None: self.current = screen.name + def remove_widget(self, *l): + screen = l[0] + if not isinstance(screen, Screen): + raise ScreenManagerException( + 'ScreenManager uses remove_widget only to remove' + + 'screens added via add_widget! use real_remove_widget.') + + if not screen in self.screens: + return + if self.current_screen == screen: + other = self.next() + if other: + self.current = other + screen.manager = None + screen.unbind(name=self._screen_name_changed) + self.screens.remove(screen) + def real_add_widget(self, *l): # ensure screen is removed from it's previous parent before adding' if l[0].parent: @@ -671,10 +688,24 @@ class ScreenManager(FloatLayout): continue child.pos = value + def on_touch_down(self, touch): + if self.transition.is_active: + return False + return super(ScreenManager, self).on_touch_down(touch) + + def on_touch_move(self, touch): + if self.transition.is_active: + return False + return super(ScreenManager, self).on_touch_move(touch) + + def on_touch_up(self, touch): + if self.transition.is_active: + return False + return super(ScreenManager, self).on_touch_up(touch) + if __name__ == '__main__': from kivy.app import App from kivy.uix.button import Button - from kivy.lang import Builder Builder.load_string(''' : canvas: @@ -701,7 +732,10 @@ if __name__ == '__main__': #d = ('left', 'up', 'down', 'right') #di = d.index(self.sm.transition.direction) #self.sm.transition.direction = d[(di + 1) % len(d)] - self.sm.current = 'test2' if self.sm.current == 'test1' else 'test1' + self.sm.current = self.sm.next() + + def remove_screen(self, *l): + self.sm.remove_widget(self.sm.get_screen('test1')) def build(self): root = FloatLayout() @@ -712,9 +746,13 @@ if __name__ == '__main__': btn = Button(size_hint=(None, None)) btn.bind(on_release=self.change_view) + + btn2 = Button(size_hint=(None, None), x=100) + btn2.bind(on_release=self.remove_screen) + root.add_widget(sm) root.add_widget(btn) + root.add_widget(btn2) return root TestApp().run() - diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py index 1e93e2ef0..8293bde23 100644 --- a/kivy/uix/scrollview.py +++ b/kivy/uix/scrollview.py @@ -106,7 +106,7 @@ class ScrollView(StencilView): def __init__(self, **kwargs): self._touch = False self._tdx = self._tdy = self._ts = self._tsn = 0 - self._scroll_y_mouse = 0 + self._scroll_y_mouse = 1 super(ScrollView, self).__init__(**kwargs) self.bind(scroll_x=self.update_from_scroll, scroll_y=self.update_from_scroll, diff --git a/kivy/uix/slider.py b/kivy/uix/slider.py index 3b07a0a61..936ee0dbb 100644 --- a/kivy/uix/slider.py +++ b/kivy/uix/slider.py @@ -22,7 +22,7 @@ __all__ = ('Slider', ) from kivy.uix.widget import Widget from kivy.properties import NumericProperty, AliasProperty, OptionProperty, \ - ReferenceListProperty + ReferenceListProperty, BoundedNumericProperty class Slider(Widget): @@ -86,6 +86,18 @@ class Slider(Widget): (:data:`min`, :data:`max`) ''' + step = BoundedNumericProperty(0, min=0) + '''Step size of the slider. + + .. versionadded:: 1.4.0 + + Determines the size of each interval or step the slider takes between + min and max. If the value range can't be evenly divisible by step the + last step will be capped by slider.max + + :data:`step` is a :class:`~kivy.properties.NumericProperty`, default to 1. + ''' + def get_norm_value(self): vmin = self.min d = self.max - vmin @@ -95,9 +107,14 @@ class Slider(Widget): def set_norm_value(self, value): vmin = self.min - self.value = value * (self.max - vmin) + vmin + step = self.step + val = value * (self.max - vmin) + vmin + if step == 0: + self.value = val + else: + self.value = min(round((val - vmin) / step) * step, self.max) value_normalized = AliasProperty(get_norm_value, set_norm_value, - bind=('value', 'min', 'max')) + bind=('value', 'min', 'max', 'step')) '''Normalized value inside the :data:`range` (min/max) to 0-1 range:: >>> slider = Slider(value=50, min=0, max=100) diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 83d625b9d..d2f1a6ac0 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -206,7 +206,7 @@ class TextInput(Widget): self._selection_finished = True self._selection_touch = None self.selection_text = '' - self.__selection_from = None + self._selection_from = None self._selection_to = None self._bubble = None self._lines_flags = []